@trops/dash-core 0.1.508 → 0.1.510
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/electron/index.js +555 -100
- package/dist/electron/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -3,6 +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$$0$3 = require('crypto');
|
|
6
7
|
var require$$9$1 = require('objects-to-csv');
|
|
7
8
|
var require$$1$2 = require('readline');
|
|
8
9
|
var require$$2 = require('xtreamer');
|
|
@@ -10,30 +11,29 @@ var require$$3$1 = require('xml2js');
|
|
|
10
11
|
var require$$4 = require('JSONStream');
|
|
11
12
|
var require$$5 = require('stream');
|
|
12
13
|
var require$$6 = require('csv-parser');
|
|
13
|
-
var require$$0$
|
|
14
|
+
var require$$0$4 = require('quickjs-emscripten');
|
|
14
15
|
var require$$11 = require('https');
|
|
15
|
-
var require$$0$
|
|
16
|
+
var require$$0$6 = require('@modelcontextprotocol/sdk/client/index.js');
|
|
16
17
|
var require$$1$3 = require('@modelcontextprotocol/sdk/client/stdio.js');
|
|
17
|
-
var require$$0$
|
|
18
|
+
var require$$0$5 = require('pkce-challenge');
|
|
18
19
|
var require$$2$1 = require('os');
|
|
19
20
|
var require$$12 = require('child_process');
|
|
20
|
-
var require$$0$
|
|
21
|
+
var require$$0$7 = require('electron-store');
|
|
21
22
|
var require$$3$2 = require('adm-zip');
|
|
22
23
|
var require$$4$1 = require('url');
|
|
23
24
|
var require$$2$2 = require('vm');
|
|
24
25
|
var require$$1$4 = require('croner');
|
|
25
26
|
var require$$2$3 = require('algoliasearch');
|
|
26
27
|
var require$$3$3 = require('node:path');
|
|
27
|
-
var require$$0$
|
|
28
|
-
var require$$0$
|
|
29
|
-
var require$$3$4 = require('crypto');
|
|
28
|
+
var require$$0$8 = require('openai');
|
|
29
|
+
var require$$0$b = require('@anthropic-ai/sdk');
|
|
30
30
|
var require$$8$1 = require('zod');
|
|
31
|
-
var require$$0$
|
|
31
|
+
var require$$0$9 = require('http');
|
|
32
32
|
var require$$1$5 = require('http2');
|
|
33
33
|
var require$$2$4 = require('node-forge');
|
|
34
|
-
var require$$0$
|
|
34
|
+
var require$$0$a = require('css');
|
|
35
35
|
var require$$1$6 = require('node-vibrant/node');
|
|
36
|
-
var require$$3$
|
|
36
|
+
var require$$3$4 = require('ws');
|
|
37
37
|
|
|
38
38
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
39
39
|
|
|
@@ -993,14 +993,14 @@ var events$8 = {
|
|
|
993
993
|
* Open a dialog window for choosing files
|
|
994
994
|
*/
|
|
995
995
|
|
|
996
|
-
const { dialog: dialog$
|
|
996
|
+
const { dialog: dialog$3 } = require$$0$1;
|
|
997
997
|
const events$7 = events$8;
|
|
998
998
|
|
|
999
999
|
const showDialog$1 = async (win, message, allowFile, extensions = ["*"]) => {
|
|
1000
1000
|
const properties =
|
|
1001
1001
|
allowFile === true ? ["openFile"] : ["openDirectory", "createDirectory"];
|
|
1002
1002
|
const filters = allowFile === true ? [{ name: "Data", extensions }] : [];
|
|
1003
|
-
const result = await dialog$
|
|
1003
|
+
const result = await dialog$3.showOpenDialog({ properties, filters });
|
|
1004
1004
|
if (result.canceled || !result.filePaths[0]) return null;
|
|
1005
1005
|
return result.filePaths[0];
|
|
1006
1006
|
};
|
|
@@ -2083,7 +2083,7 @@ var grantedPermissions = {
|
|
|
2083
2083
|
* _resetForTest() → void (test-only)
|
|
2084
2084
|
*/
|
|
2085
2085
|
|
|
2086
|
-
const { BrowserWindow: BrowserWindow$
|
|
2086
|
+
const { BrowserWindow: BrowserWindow$3, ipcMain: ipcMain$3 } = require$$0$1;
|
|
2087
2087
|
|
|
2088
2088
|
const REQUEST_CHANNEL = "widget:permission-required";
|
|
2089
2089
|
const RESPONSE_CHANNEL = "widget:permission-response";
|
|
@@ -2129,7 +2129,7 @@ function coalesceKeyOf(req) {
|
|
|
2129
2129
|
function emitEvent(payload) {
|
|
2130
2130
|
let wins = [];
|
|
2131
2131
|
try {
|
|
2132
|
-
wins = BrowserWindow$
|
|
2132
|
+
wins = BrowserWindow$3.getAllWindows() || [];
|
|
2133
2133
|
} catch {
|
|
2134
2134
|
wins = [];
|
|
2135
2135
|
}
|
|
@@ -2248,8 +2248,8 @@ let _handlersRegistered = false;
|
|
|
2248
2248
|
*/
|
|
2249
2249
|
function setupJitConsentHandlers() {
|
|
2250
2250
|
if (_handlersRegistered) return;
|
|
2251
|
-
if (!ipcMain$
|
|
2252
|
-
ipcMain$
|
|
2251
|
+
if (!ipcMain$3 || typeof ipcMain$3.on !== "function") return;
|
|
2252
|
+
ipcMain$3.on(RESPONSE_CHANNEL, (_event, payload) => {
|
|
2253
2253
|
_handleResponse(payload);
|
|
2254
2254
|
});
|
|
2255
2255
|
_handlersRegistered = true;
|
|
@@ -2265,6 +2265,93 @@ var jitConsent$1 = {
|
|
|
2265
2265
|
DEFAULT_TIMEOUT_MS,
|
|
2266
2266
|
};
|
|
2267
2267
|
|
|
2268
|
+
/**
|
|
2269
|
+
* mountTokenRegistry.js
|
|
2270
|
+
*
|
|
2271
|
+
* Trusted root of widget identity at the IPC boundary. Each time
|
|
2272
|
+
* `WidgetFactory` mounts a widget it calls
|
|
2273
|
+
* `framework:register-widget-mount`, which calls `register(widgetId)`
|
|
2274
|
+
* here. The returned token is baked into the widget's bound API
|
|
2275
|
+
* (`makeBoundApi`) and sent on every gated IPC call. Gates resolve the
|
|
2276
|
+
* widgetId via `lookup(token)` instead of trusting whatever the
|
|
2277
|
+
* renderer claims.
|
|
2278
|
+
*
|
|
2279
|
+
* Why server-generated tokens: the renderer-supplied widgetId path was
|
|
2280
|
+
* the original consent-bypass surface. Tokens are produced by
|
|
2281
|
+
* `crypto.randomBytes(24)` here (192 bits) and are NEVER accepted from
|
|
2282
|
+
* the renderer — the renderer can only present tokens it received from
|
|
2283
|
+
* a prior `register` call. A widget cannot fabricate a token for
|
|
2284
|
+
* another widgetId.
|
|
2285
|
+
*
|
|
2286
|
+
* Limit: in single-renderer (one BrowserWindow shared across all
|
|
2287
|
+
* widgets), a malicious widget can still walk the React fiber tree to
|
|
2288
|
+
* find another widget's bound API and call its functions — the bound
|
|
2289
|
+
* function fires IPC with the *victim's* token. Fully closing that
|
|
2290
|
+
* residual requires per-widget BrowserView (multi-week refactor). The
|
|
2291
|
+
* token model raises the bar from "type a widgetId string" to "walk
|
|
2292
|
+
* the fiber tree and call another widget's bound function," which is
|
|
2293
|
+
* a deliberate malicious step that's visible at install-time review.
|
|
2294
|
+
*/
|
|
2295
|
+
|
|
2296
|
+
const crypto$1 = require$$0$3;
|
|
2297
|
+
|
|
2298
|
+
const _byToken = new Map(); // token → widgetId
|
|
2299
|
+
|
|
2300
|
+
function _generateToken() {
|
|
2301
|
+
// 24 random bytes = 48 hex chars = 192 bits of entropy. More than
|
|
2302
|
+
// enough; collision probability is negligible.
|
|
2303
|
+
return crypto$1.randomBytes(24).toString("hex");
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
/**
|
|
2307
|
+
* Register a widgetId mount and return a fresh token bound to it.
|
|
2308
|
+
* @param {string} widgetId
|
|
2309
|
+
* @returns {string} token
|
|
2310
|
+
*/
|
|
2311
|
+
function register$1(widgetId) {
|
|
2312
|
+
if (typeof widgetId !== "string" || widgetId.length === 0) {
|
|
2313
|
+
throw new Error(
|
|
2314
|
+
"mountTokenRegistry.register: widgetId must be a non-empty string",
|
|
2315
|
+
);
|
|
2316
|
+
}
|
|
2317
|
+
let token = _generateToken();
|
|
2318
|
+
// Defensive — collision is astronomically unlikely but if it did
|
|
2319
|
+
// happen we'd silently overwrite a valid mapping. Regenerate.
|
|
2320
|
+
while (_byToken.has(token)) {
|
|
2321
|
+
token = _generateToken();
|
|
2322
|
+
}
|
|
2323
|
+
_byToken.set(token, widgetId);
|
|
2324
|
+
return token;
|
|
2325
|
+
}
|
|
2326
|
+
|
|
2327
|
+
/**
|
|
2328
|
+
* Resolve a token to the widgetId it was bound to.
|
|
2329
|
+
* @param {string} token
|
|
2330
|
+
* @returns {string|null}
|
|
2331
|
+
*/
|
|
2332
|
+
function lookup(token) {
|
|
2333
|
+
if (typeof token !== "string") return null;
|
|
2334
|
+
return _byToken.has(token) ? _byToken.get(token) : null;
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
/**
|
|
2338
|
+
* Drop a token. Silent no-op for unknown tokens or non-strings —
|
|
2339
|
+
* unregister is called from unmount cleanup paths and should never
|
|
2340
|
+
* throw.
|
|
2341
|
+
* @param {string} token
|
|
2342
|
+
*/
|
|
2343
|
+
function unregister$1(token) {
|
|
2344
|
+
if (typeof token !== "string") return;
|
|
2345
|
+
_byToken.delete(token);
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
/** Test-only — clears the registry between cases. */
|
|
2349
|
+
function _resetForTests() {
|
|
2350
|
+
_byToken.clear();
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2353
|
+
var mountTokenRegistry = { register: register$1, lookup, unregister: unregister$1, _resetForTests };
|
|
2354
|
+
|
|
2268
2355
|
/**
|
|
2269
2356
|
* fsGate.js
|
|
2270
2357
|
*
|
|
@@ -2302,6 +2389,25 @@ var jitConsent$1 = {
|
|
|
2302
2389
|
|
|
2303
2390
|
const { getGrant: getGrant$3, setGrant: setGrant$3 } = grantedPermissions;
|
|
2304
2391
|
const { requestApproval: requestApproval$2 } = jitConsent$1;
|
|
2392
|
+
const { lookup: lookupMountToken$2 } = mountTokenRegistry;
|
|
2393
|
+
|
|
2394
|
+
// If a token is supplied, the gate resolves widgetId via the mount
|
|
2395
|
+
// registry and ignores any renderer-supplied widgetId. Tokens are
|
|
2396
|
+
// server-generated and bound to a widgetId at WidgetFactory mount —
|
|
2397
|
+
// the renderer cannot fabricate a token for another widget. See
|
|
2398
|
+
// `mountTokenRegistry.js`.
|
|
2399
|
+
//
|
|
2400
|
+
// Legacy callers without a token fall through to the existing
|
|
2401
|
+
// widgetId-based path (Slice 1 keeps this for back-compat; Slice 2
|
|
2402
|
+
// flips to deny).
|
|
2403
|
+
function _resolveIdentity$2({ token, widgetId }) {
|
|
2404
|
+
if (typeof token === "string" && token.length > 0) {
|
|
2405
|
+
const resolved = lookupMountToken$2(token);
|
|
2406
|
+
if (resolved) return { widgetId: resolved, source: "token" };
|
|
2407
|
+
return { widgetId: null, source: "token-unknown" };
|
|
2408
|
+
}
|
|
2409
|
+
return { widgetId: widgetId || null, source: "legacy" };
|
|
2410
|
+
}
|
|
2305
2411
|
|
|
2306
2412
|
// Action names treated as writes. Anything not in this set is a read.
|
|
2307
2413
|
// Conservative — when in doubt, classify as a read so write-protected
|
|
@@ -2336,7 +2442,15 @@ function _filenameMatches(filename, allowedList) {
|
|
|
2336
2442
|
* Synchronous gate evaluation.
|
|
2337
2443
|
* @returns {{ allow: true } | { allow: false, reason: string }}
|
|
2338
2444
|
*/
|
|
2339
|
-
function gateFsCall$1({ widgetId, action, args }) {
|
|
2445
|
+
function gateFsCall$1({ widgetId, token, action, args }) {
|
|
2446
|
+
const resolved = _resolveIdentity$2({ token, widgetId });
|
|
2447
|
+
if (resolved.source === "token-unknown") {
|
|
2448
|
+
return {
|
|
2449
|
+
allow: false,
|
|
2450
|
+
reason: "fs gate: unknown mount token; widget identity not verifiable",
|
|
2451
|
+
};
|
|
2452
|
+
}
|
|
2453
|
+
widgetId = resolved.widgetId;
|
|
2340
2454
|
if (!widgetId) {
|
|
2341
2455
|
return {
|
|
2342
2456
|
allow: false,
|
|
@@ -2460,11 +2574,21 @@ async function gateFsCallWithJit$1(req, opts = {}) {
|
|
|
2460
2574
|
if (!opts.enableJit) return initial;
|
|
2461
2575
|
if (!_isNoGrantDenial$2(initial.reason)) return initial;
|
|
2462
2576
|
|
|
2577
|
+
// Resolve verified identity once (token wins over claimed widgetId).
|
|
2578
|
+
// Re-using the same resolution as gateFsCall keeps the JIT prompt
|
|
2579
|
+
// and grant write tied to the same identity the gate just denied.
|
|
2580
|
+
const resolved = _resolveIdentity$2({
|
|
2581
|
+
token: req.token,
|
|
2582
|
+
widgetId: req.widgetId,
|
|
2583
|
+
});
|
|
2584
|
+
const verifiedWidgetId = resolved.widgetId;
|
|
2585
|
+
if (!verifiedWidgetId) return initial;
|
|
2586
|
+
|
|
2463
2587
|
let decision;
|
|
2464
2588
|
try {
|
|
2465
2589
|
decision = await requestApproval$2(
|
|
2466
2590
|
{
|
|
2467
|
-
widgetId:
|
|
2591
|
+
widgetId: verifiedWidgetId,
|
|
2468
2592
|
domain: "fs",
|
|
2469
2593
|
action: req.action,
|
|
2470
2594
|
args: req.args || {},
|
|
@@ -2487,7 +2611,7 @@ async function gateFsCallWithJit$1(req, opts = {}) {
|
|
|
2487
2611
|
allow: false,
|
|
2488
2612
|
reason:
|
|
2489
2613
|
"user declined JIT consent for widget '" +
|
|
2490
|
-
|
|
2614
|
+
verifiedWidgetId +
|
|
2491
2615
|
"' calling fs '" +
|
|
2492
2616
|
req.action +
|
|
2493
2617
|
"'",
|
|
@@ -2511,9 +2635,9 @@ async function gateFsCallWithJit$1(req, opts = {}) {
|
|
|
2511
2635
|
addition.grantOrigin = "live";
|
|
2512
2636
|
|
|
2513
2637
|
try {
|
|
2514
|
-
const current = getGrant$3(
|
|
2638
|
+
const current = getGrant$3(verifiedWidgetId);
|
|
2515
2639
|
const merged = _mergeFsGrant(current, addition);
|
|
2516
|
-
setGrant$3(
|
|
2640
|
+
setGrant$3(verifiedWidgetId, merged);
|
|
2517
2641
|
} catch (e) {
|
|
2518
2642
|
return {
|
|
2519
2643
|
allow: false,
|
|
@@ -2575,6 +2699,20 @@ var fsGate = {
|
|
|
2575
2699
|
|
|
2576
2700
|
const { getGrant: getGrant$2, setGrant: setGrant$2 } = grantedPermissions;
|
|
2577
2701
|
const { requestApproval: requestApproval$1 } = jitConsent$1;
|
|
2702
|
+
const { lookup: lookupMountToken$1 } = mountTokenRegistry;
|
|
2703
|
+
|
|
2704
|
+
// See `mountTokenRegistry.js` and the matching block in fsGate.js —
|
|
2705
|
+
// when a token is supplied, it's the trusted identity source; the
|
|
2706
|
+
// renderer-claimed widgetId is ignored. Legacy widgetId-only callers
|
|
2707
|
+
// still work in slice 1 (additive); slice 2 will flip to deny.
|
|
2708
|
+
function _resolveIdentity$1({ token, widgetId }) {
|
|
2709
|
+
if (typeof token === "string" && token.length > 0) {
|
|
2710
|
+
const resolved = lookupMountToken$1(token);
|
|
2711
|
+
if (resolved) return { widgetId: resolved, source: "token" };
|
|
2712
|
+
return { widgetId: null, source: "token-unknown" };
|
|
2713
|
+
}
|
|
2714
|
+
return { widgetId: widgetId || null, source: "legacy" };
|
|
2715
|
+
}
|
|
2578
2716
|
|
|
2579
2717
|
function _isNoGrantDenial$1(reason) {
|
|
2580
2718
|
return (
|
|
@@ -2617,7 +2755,16 @@ function _parseHost(url) {
|
|
|
2617
2755
|
* Synchronous gate evaluation.
|
|
2618
2756
|
* @returns {{ allow: true } | { allow: false, reason: string }}
|
|
2619
2757
|
*/
|
|
2620
|
-
function gateNetworkCall$2({ widgetId, action, args }) {
|
|
2758
|
+
function gateNetworkCall$2({ widgetId, token, action, args }) {
|
|
2759
|
+
const resolved = _resolveIdentity$1({ token, widgetId });
|
|
2760
|
+
if (resolved.source === "token-unknown") {
|
|
2761
|
+
return {
|
|
2762
|
+
allow: false,
|
|
2763
|
+
reason:
|
|
2764
|
+
"network gate: unknown mount token; widget identity not verifiable",
|
|
2765
|
+
};
|
|
2766
|
+
}
|
|
2767
|
+
widgetId = resolved.widgetId;
|
|
2621
2768
|
if (!widgetId) {
|
|
2622
2769
|
return {
|
|
2623
2770
|
allow: false,
|
|
@@ -2708,11 +2855,21 @@ async function gateNetworkCallWithJit$2(req, opts = {}) {
|
|
|
2708
2855
|
if (!opts.enableJit) return initial;
|
|
2709
2856
|
if (!_isNoGrantDenial$1(initial.reason)) return initial;
|
|
2710
2857
|
|
|
2858
|
+
// Same identity-resolution as the sync gate — the JIT prompt and
|
|
2859
|
+
// grant write must use the verified widgetId, not whatever the
|
|
2860
|
+
// renderer claimed.
|
|
2861
|
+
const resolved = _resolveIdentity$1({
|
|
2862
|
+
token: req.token,
|
|
2863
|
+
widgetId: req.widgetId,
|
|
2864
|
+
});
|
|
2865
|
+
const verifiedWidgetId = resolved.widgetId;
|
|
2866
|
+
if (!verifiedWidgetId) return initial;
|
|
2867
|
+
|
|
2711
2868
|
let decision;
|
|
2712
2869
|
try {
|
|
2713
2870
|
decision = await requestApproval$1(
|
|
2714
2871
|
{
|
|
2715
|
-
widgetId:
|
|
2872
|
+
widgetId: verifiedWidgetId,
|
|
2716
2873
|
domain: "network",
|
|
2717
2874
|
action: req.action,
|
|
2718
2875
|
args: req.args || {},
|
|
@@ -2735,7 +2892,7 @@ async function gateNetworkCallWithJit$2(req, opts = {}) {
|
|
|
2735
2892
|
allow: false,
|
|
2736
2893
|
reason:
|
|
2737
2894
|
"user declined JIT consent for widget '" +
|
|
2738
|
-
|
|
2895
|
+
verifiedWidgetId +
|
|
2739
2896
|
"' calling network '" +
|
|
2740
2897
|
req.action +
|
|
2741
2898
|
"'",
|
|
@@ -2753,9 +2910,9 @@ async function gateNetworkCallWithJit$2(req, opts = {}) {
|
|
|
2753
2910
|
addition.grantOrigin = "live";
|
|
2754
2911
|
|
|
2755
2912
|
try {
|
|
2756
|
-
const current = getGrant$2(
|
|
2913
|
+
const current = getGrant$2(verifiedWidgetId);
|
|
2757
2914
|
const merged = _mergeNetworkGrant(current, addition);
|
|
2758
|
-
setGrant$2(
|
|
2915
|
+
setGrant$2(verifiedWidgetId, merged);
|
|
2759
2916
|
} catch (e) {
|
|
2760
2917
|
return {
|
|
2761
2918
|
allow: false,
|
|
@@ -2867,7 +3024,7 @@ function requireSafeJsExecutor () {
|
|
|
2867
3024
|
let _modulePromise = null;
|
|
2868
3025
|
function getModule() {
|
|
2869
3026
|
if (!_modulePromise) {
|
|
2870
|
-
const { getQuickJS } = require$$0$
|
|
3027
|
+
const { getQuickJS } = require$$0$4;
|
|
2871
3028
|
_modulePromise = getQuickJS();
|
|
2872
3029
|
}
|
|
2873
3030
|
return _modulePromise;
|
|
@@ -3541,13 +3698,19 @@ function _loadFlags$1() {
|
|
|
3541
3698
|
*
|
|
3542
3699
|
* @returns {Promise<boolean>}
|
|
3543
3700
|
*/
|
|
3544
|
-
async function _runFsGate(win, action, widgetId, args, errorEvent) {
|
|
3701
|
+
async function _runFsGate(win, action, widgetId, args, errorEvent, token) {
|
|
3545
3702
|
const settings = _loadFlags$1();
|
|
3546
3703
|
if (!readEnforceFlag$2(settings)) return true; // gate disabled
|
|
3547
|
-
|
|
3704
|
+
// Slice 1 (additive): token is the trusted identity when present.
|
|
3705
|
+
// If neither token nor widgetId is supplied, legacy bypass still
|
|
3706
|
+
// applies; slice 2 will flip this to deny.
|
|
3707
|
+
if (!widgetId && !token) return true;
|
|
3548
3708
|
const gate = readJitFlag$2(settings)
|
|
3549
|
-
? await gateFsCallWithJit(
|
|
3550
|
-
|
|
3709
|
+
? await gateFsCallWithJit(
|
|
3710
|
+
{ widgetId, token, action, args },
|
|
3711
|
+
{ enableJit: true },
|
|
3712
|
+
)
|
|
3713
|
+
: gateFsCall({ widgetId, token, action, args });
|
|
3551
3714
|
if (gate.allow) return true;
|
|
3552
3715
|
if (win && errorEvent) {
|
|
3553
3716
|
win.webContents.send(errorEvent, {
|
|
@@ -3562,16 +3725,16 @@ async function _runFsGate(win, action, widgetId, args, errorEvent) {
|
|
|
3562
3725
|
* Phase 3 network gate. Same shape as _runFsGate but for outbound
|
|
3563
3726
|
* URLs. Mirrors fs's "disabled / no widgetId / sync vs async" branching.
|
|
3564
3727
|
*/
|
|
3565
|
-
async function _runNetworkGate$1(win, action, widgetId, args, errorEvent) {
|
|
3728
|
+
async function _runNetworkGate$1(win, action, widgetId, args, errorEvent, token) {
|
|
3566
3729
|
const settings = _loadFlags$1();
|
|
3567
3730
|
if (!readEnforceFlag$2(settings)) return true;
|
|
3568
|
-
if (!widgetId) return true;
|
|
3731
|
+
if (!widgetId && !token) return true;
|
|
3569
3732
|
const gate = readJitFlag$2(settings)
|
|
3570
3733
|
? await gateNetworkCallWithJit$1(
|
|
3571
|
-
{ widgetId, action, args },
|
|
3734
|
+
{ widgetId, token, action, args },
|
|
3572
3735
|
{ enableJit: true },
|
|
3573
3736
|
)
|
|
3574
|
-
: gateNetworkCall$1({ widgetId, action, args });
|
|
3737
|
+
: gateNetworkCall$1({ widgetId, token, action, args });
|
|
3575
3738
|
if (gate.allow) return true;
|
|
3576
3739
|
if (win && errorEvent) {
|
|
3577
3740
|
win.webContents.send(errorEvent, {
|
|
@@ -3741,7 +3904,13 @@ const dataController$1 = {
|
|
|
3741
3904
|
}
|
|
3742
3905
|
},
|
|
3743
3906
|
|
|
3744
|
-
readDataFromURL: async (
|
|
3907
|
+
readDataFromURL: async (
|
|
3908
|
+
win,
|
|
3909
|
+
url,
|
|
3910
|
+
toFilepath,
|
|
3911
|
+
widgetId = null,
|
|
3912
|
+
token = null,
|
|
3913
|
+
) => {
|
|
3745
3914
|
// Phase 3 network gate. Runs before HTTPS-protocol + safePath
|
|
3746
3915
|
// checks so JIT can prompt the user without leaking URL parser
|
|
3747
3916
|
// edge cases through error timing.
|
|
@@ -3751,6 +3920,7 @@ const dataController$1 = {
|
|
|
3751
3920
|
widgetId,
|
|
3752
3921
|
{ url },
|
|
3753
3922
|
events$5.READ_DATA_URL_ERROR,
|
|
3923
|
+
token,
|
|
3754
3924
|
);
|
|
3755
3925
|
if (!gateOk) return;
|
|
3756
3926
|
try {
|
|
@@ -3938,6 +4108,7 @@ const dataController$1 = {
|
|
|
3938
4108
|
append,
|
|
3939
4109
|
returnEmpty = {},
|
|
3940
4110
|
widgetId = null,
|
|
4111
|
+
token = null,
|
|
3941
4112
|
) => {
|
|
3942
4113
|
// Phase 2 fs gate. Runs before safePath containment so JIT can
|
|
3943
4114
|
// prompt the user without leaking path-shape information through
|
|
@@ -3948,6 +4119,7 @@ const dataController$1 = {
|
|
|
3948
4119
|
widgetId,
|
|
3949
4120
|
{ filename },
|
|
3950
4121
|
events$5.DATA_SAVE_TO_FILE_ERROR,
|
|
4122
|
+
token,
|
|
3951
4123
|
);
|
|
3952
4124
|
if (!gateOk) return;
|
|
3953
4125
|
try {
|
|
@@ -4043,7 +4215,13 @@ const dataController$1 = {
|
|
|
4043
4215
|
}
|
|
4044
4216
|
},
|
|
4045
4217
|
|
|
4046
|
-
readFromFile: async (
|
|
4218
|
+
readFromFile: async (
|
|
4219
|
+
win,
|
|
4220
|
+
filename,
|
|
4221
|
+
returnIfEmpty = {},
|
|
4222
|
+
widgetId = null,
|
|
4223
|
+
token = null,
|
|
4224
|
+
) => {
|
|
4047
4225
|
// Phase 2 fs gate — same as saveToFile.
|
|
4048
4226
|
const gateOk = await _runFsGate(
|
|
4049
4227
|
win,
|
|
@@ -4051,6 +4229,7 @@ const dataController$1 = {
|
|
|
4051
4229
|
widgetId,
|
|
4052
4230
|
{ filename },
|
|
4053
4231
|
events$5.DATA_READ_FROM_FILE_ERROR,
|
|
4232
|
+
token,
|
|
4054
4233
|
);
|
|
4055
4234
|
if (!gateOk) return;
|
|
4056
4235
|
try {
|
|
@@ -20707,7 +20886,7 @@ auth$2.exchangeAuthorization = exchangeAuthorization;
|
|
|
20707
20886
|
auth$2.refreshAuthorization = refreshAuthorization;
|
|
20708
20887
|
auth$2.fetchToken = fetchToken;
|
|
20709
20888
|
auth$2.registerClient = registerClient;
|
|
20710
|
-
const pkce_challenge_1 = __importDefault$2(require$$0$
|
|
20889
|
+
const pkce_challenge_1 = __importDefault$2(require$$0$5);
|
|
20711
20890
|
const types_js_1$5 = types$2;
|
|
20712
20891
|
const auth_js_1$1 = auth$1;
|
|
20713
20892
|
const auth_js_2 = auth$1;
|
|
@@ -22265,6 +22444,21 @@ streamableHttp$1.StreamableHTTPClientTransport = StreamableHTTPClientTransport$1
|
|
|
22265
22444
|
const { getGrant: getGrant$1, setGrant: setGrant$1 } = grantedPermissions;
|
|
22266
22445
|
const { safePath: safePath$1 } = safePath_1;
|
|
22267
22446
|
const { requestApproval } = jitConsent$1;
|
|
22447
|
+
const { lookup: lookupMountToken } = mountTokenRegistry;
|
|
22448
|
+
|
|
22449
|
+
// See `electron/security/mountTokenRegistry.js`. When a token is
|
|
22450
|
+
// supplied it's the trusted identity source — gates resolve widgetId
|
|
22451
|
+
// via lookupMountToken and ignore renderer-claimed widgetId. Slice 1
|
|
22452
|
+
// keeps the legacy widgetId-only path working (additive); slice 2 will
|
|
22453
|
+
// flip to deny-without-token.
|
|
22454
|
+
function _resolveIdentity({ token, widgetId }) {
|
|
22455
|
+
if (typeof token === "string" && token.length > 0) {
|
|
22456
|
+
const resolved = lookupMountToken(token);
|
|
22457
|
+
if (resolved) return { widgetId: resolved, source: "token" };
|
|
22458
|
+
return { widgetId: null, source: "token-unknown" };
|
|
22459
|
+
}
|
|
22460
|
+
return { widgetId: widgetId || null, source: "legacy" };
|
|
22461
|
+
}
|
|
22268
22462
|
|
|
22269
22463
|
// Argument keys that look like paths. Different MCP servers use
|
|
22270
22464
|
// different conventions; this list covers the common filesystem-style
|
|
@@ -22286,7 +22480,15 @@ function isWriteTool(toolName) {
|
|
|
22286
22480
|
/**
|
|
22287
22481
|
* @returns {{ allow: true } | { allow: false, reason: string }}
|
|
22288
22482
|
*/
|
|
22289
|
-
function gateToolCall$1({ widgetId, serverName, toolName, args }) {
|
|
22483
|
+
function gateToolCall$1({ widgetId, token, serverName, toolName, args }) {
|
|
22484
|
+
const resolved = _resolveIdentity({ token, widgetId });
|
|
22485
|
+
if (resolved.source === "token-unknown") {
|
|
22486
|
+
return {
|
|
22487
|
+
allow: false,
|
|
22488
|
+
reason: "MCP gate: unknown mount token; widget identity not verifiable",
|
|
22489
|
+
};
|
|
22490
|
+
}
|
|
22491
|
+
widgetId = resolved.widgetId;
|
|
22290
22492
|
if (!widgetId) {
|
|
22291
22493
|
return {
|
|
22292
22494
|
allow: false,
|
|
@@ -22440,11 +22642,20 @@ async function gateToolCallWithJit$1(req, opts = {}) {
|
|
|
22440
22642
|
if (!opts.enableJit) return initial;
|
|
22441
22643
|
if (!_isNoGrantDenial(initial.reason)) return initial;
|
|
22442
22644
|
|
|
22645
|
+
// Same identity-resolution as the sync gate — JIT prompt and grant
|
|
22646
|
+
// write must use the verified widgetId.
|
|
22647
|
+
const resolved = _resolveIdentity({
|
|
22648
|
+
token: req.token,
|
|
22649
|
+
widgetId: req.widgetId,
|
|
22650
|
+
});
|
|
22651
|
+
const verifiedWidgetId = resolved.widgetId;
|
|
22652
|
+
if (!verifiedWidgetId) return initial;
|
|
22653
|
+
|
|
22443
22654
|
let decision;
|
|
22444
22655
|
try {
|
|
22445
22656
|
decision = await requestApproval(
|
|
22446
22657
|
{
|
|
22447
|
-
widgetId:
|
|
22658
|
+
widgetId: verifiedWidgetId,
|
|
22448
22659
|
domain: "mcp",
|
|
22449
22660
|
action: "callTool",
|
|
22450
22661
|
args: {
|
|
@@ -22471,7 +22682,7 @@ async function gateToolCallWithJit$1(req, opts = {}) {
|
|
|
22471
22682
|
allow: false,
|
|
22472
22683
|
reason:
|
|
22473
22684
|
"user declined JIT consent for widget '" +
|
|
22474
|
-
|
|
22685
|
+
verifiedWidgetId +
|
|
22475
22686
|
"' calling '" +
|
|
22476
22687
|
req.toolName +
|
|
22477
22688
|
"' on '" +
|
|
@@ -22501,9 +22712,9 @@ async function gateToolCallWithJit$1(req, opts = {}) {
|
|
|
22501
22712
|
addition.grantOrigin = "live";
|
|
22502
22713
|
|
|
22503
22714
|
try {
|
|
22504
|
-
const current = getGrant$1(
|
|
22715
|
+
const current = getGrant$1(verifiedWidgetId);
|
|
22505
22716
|
const merged = _mergeGrant(current, addition);
|
|
22506
|
-
setGrant$1(
|
|
22717
|
+
setGrant$1(verifiedWidgetId, merged);
|
|
22507
22718
|
} catch (e) {
|
|
22508
22719
|
return {
|
|
22509
22720
|
allow: false,
|
|
@@ -22716,7 +22927,7 @@ var mcpScopeResolver = {
|
|
|
22716
22927
|
* Uses @modelcontextprotocol/sdk for protocol handling.
|
|
22717
22928
|
*/
|
|
22718
22929
|
|
|
22719
|
-
const { Client } = require$$0$
|
|
22930
|
+
const { Client } = require$$0$6;
|
|
22720
22931
|
const {
|
|
22721
22932
|
StdioClientTransport,
|
|
22722
22933
|
} = require$$1$3;
|
|
@@ -23521,6 +23732,7 @@ const mcpController$3 = {
|
|
|
23521
23732
|
allowedTools = null,
|
|
23522
23733
|
widgetId = null,
|
|
23523
23734
|
workspaceId = null,
|
|
23735
|
+
token = null,
|
|
23524
23736
|
) => {
|
|
23525
23737
|
const key = serverKey(workspaceId, serverName);
|
|
23526
23738
|
try {
|
|
@@ -23544,8 +23756,12 @@ const mcpController$3 = {
|
|
|
23544
23756
|
// startServer happens after the gate decides — and (b) avoids
|
|
23545
23757
|
// leaking server-running state through error timing to a
|
|
23546
23758
|
// probing widget that doesn't have permission anyway.
|
|
23547
|
-
|
|
23548
|
-
|
|
23759
|
+
// Slice 1 (additive): if a mount token is supplied it's the
|
|
23760
|
+
// trusted identity source; widgetId is verified-or-overwritten
|
|
23761
|
+
// inside the gate via mountTokenRegistry. Gate gets to run
|
|
23762
|
+
// whenever EITHER token or widgetId is present.
|
|
23763
|
+
if (isWidgetPermissionEnforcementEnabled() && (widgetId || token)) {
|
|
23764
|
+
const gateReq = { widgetId, token, serverName, toolName, args };
|
|
23549
23765
|
const gate = isJitConsentEnabled()
|
|
23550
23766
|
? await gateToolCallWithJit(gateReq, { enableJit: true })
|
|
23551
23767
|
: gateToolCall(gateReq);
|
|
@@ -24099,7 +24315,7 @@ const REGISTRY_BASE_URL$1 =
|
|
|
24099
24315
|
let store$3 = null;
|
|
24100
24316
|
function getStore$1() {
|
|
24101
24317
|
if (!store$3) {
|
|
24102
|
-
const Store = require$$0$
|
|
24318
|
+
const Store = require$$0$7;
|
|
24103
24319
|
store$3 = new Store({
|
|
24104
24320
|
name: "dash-registry-auth",
|
|
24105
24321
|
encryptionKey: "dash-registry-v1",
|
|
@@ -25384,7 +25600,7 @@ var manifestScanner = {
|
|
|
25384
25600
|
* and dispatching task-fired events to renderer windows.
|
|
25385
25601
|
*/
|
|
25386
25602
|
|
|
25387
|
-
const Store$1 = require$$0$
|
|
25603
|
+
const Store$1 = require$$0$7;
|
|
25388
25604
|
const { Cron } = require$$1$4;
|
|
25389
25605
|
|
|
25390
25606
|
const store$2 = new Store$1({ name: "dash-scheduler" });
|
|
@@ -28600,7 +28816,7 @@ const algoliaController$1 = {
|
|
|
28600
28816
|
|
|
28601
28817
|
var algoliaController_1 = algoliaController$1;
|
|
28602
28818
|
|
|
28603
|
-
const OpenAI = require$$0$
|
|
28819
|
+
const OpenAI = require$$0$8;
|
|
28604
28820
|
const events$2 = events$8;
|
|
28605
28821
|
|
|
28606
28822
|
const openaiController$1 = {
|
|
@@ -34803,13 +35019,20 @@ boolean.parseBooleanDef = parseBooleanDef;
|
|
|
34803
35019
|
|
|
34804
35020
|
var branded = {};
|
|
34805
35021
|
|
|
34806
|
-
|
|
34807
|
-
|
|
34808
|
-
|
|
34809
|
-
|
|
34810
|
-
|
|
35022
|
+
var hasRequiredBranded;
|
|
35023
|
+
|
|
35024
|
+
function requireBranded () {
|
|
35025
|
+
if (hasRequiredBranded) return branded;
|
|
35026
|
+
hasRequiredBranded = 1;
|
|
35027
|
+
Object.defineProperty(branded, "__esModule", { value: true });
|
|
35028
|
+
branded.parseBrandedDef = void 0;
|
|
35029
|
+
const parseDef_js_1 = requireParseDef();
|
|
35030
|
+
function parseBrandedDef(_def, refs) {
|
|
35031
|
+
return (0, parseDef_js_1.parseDef)(_def.type._def, refs);
|
|
35032
|
+
}
|
|
35033
|
+
branded.parseBrandedDef = parseBrandedDef;
|
|
35034
|
+
return branded;
|
|
34811
35035
|
}
|
|
34812
|
-
branded.parseBrandedDef = parseBrandedDef;
|
|
34813
35036
|
|
|
34814
35037
|
var _catch = {};
|
|
34815
35038
|
|
|
@@ -35392,7 +35615,7 @@ function requireRecord () {
|
|
|
35392
35615
|
const v3_1 = v3;
|
|
35393
35616
|
const parseDef_js_1 = requireParseDef();
|
|
35394
35617
|
const string_js_1 = string;
|
|
35395
|
-
const branded_js_1 =
|
|
35618
|
+
const branded_js_1 = requireBranded();
|
|
35396
35619
|
const any_js_1 = any;
|
|
35397
35620
|
function parseRecordDef(def, refs) {
|
|
35398
35621
|
if (refs.target === "openAi") {
|
|
@@ -36043,7 +36266,7 @@ function requireSelectParser () {
|
|
|
36043
36266
|
const array_js_1 = requireArray();
|
|
36044
36267
|
const bigint_js_1 = bigint;
|
|
36045
36268
|
const boolean_js_1 = boolean;
|
|
36046
|
-
const branded_js_1 =
|
|
36269
|
+
const branded_js_1 = requireBranded();
|
|
36047
36270
|
const catch_js_1 = require_catch();
|
|
36048
36271
|
const date_js_1 = date;
|
|
36049
36272
|
const default_js_1 = require_default();
|
|
@@ -36342,7 +36565,7 @@ zodToJsonSchema$1.zodToJsonSchema = zodToJsonSchema;
|
|
|
36342
36565
|
__exportStar(requireArray(), exports);
|
|
36343
36566
|
__exportStar(bigint, exports);
|
|
36344
36567
|
__exportStar(boolean, exports);
|
|
36345
|
-
__exportStar(
|
|
36568
|
+
__exportStar(requireBranded(), exports);
|
|
36346
36569
|
__exportStar(require_catch(), exports);
|
|
36347
36570
|
__exportStar(date, exports);
|
|
36348
36571
|
__exportStar(require_default(), exports);
|
|
@@ -46953,7 +47176,7 @@ __export(src_exports, {
|
|
|
46953
47176
|
var dist = __toCommonJS(src_exports);
|
|
46954
47177
|
|
|
46955
47178
|
// src/server.ts
|
|
46956
|
-
var import_node_http = require$$0$
|
|
47179
|
+
var import_node_http = require$$0$9;
|
|
46957
47180
|
|
|
46958
47181
|
// src/listener.ts
|
|
46959
47182
|
var import_node_http22 = require$$1$5;
|
|
@@ -47304,7 +47527,7 @@ var buildOutgoingHttpHeaders = (headers) => {
|
|
|
47304
47527
|
var X_ALREADY_SENT = "x-hono-already-sent";
|
|
47305
47528
|
|
|
47306
47529
|
// src/globals.ts
|
|
47307
|
-
var import_node_crypto = __toESM(require$$3
|
|
47530
|
+
var import_node_crypto = __toESM(require$$0$3);
|
|
47308
47531
|
if (typeof commonjsGlobal.crypto === "undefined") {
|
|
47309
47532
|
commonjsGlobal.crypto = import_node_crypto.default;
|
|
47310
47533
|
}
|
|
@@ -48732,8 +48955,8 @@ var jsonSchemaToZod_1 = { jsonSchemaToZod: jsonSchemaToZod$1, jsonSchemaProperty
|
|
|
48732
48955
|
*/
|
|
48733
48956
|
|
|
48734
48957
|
const https$1 = require$$11;
|
|
48735
|
-
const { randomUUID } = require$$3
|
|
48736
|
-
const { BrowserWindow: BrowserWindow$
|
|
48958
|
+
const { randomUUID } = require$$0$3;
|
|
48959
|
+
const { BrowserWindow: BrowserWindow$2 } = require$$0$1;
|
|
48737
48960
|
const { McpServer } = mcp;
|
|
48738
48961
|
const {
|
|
48739
48962
|
StreamableHTTPServerTransport,
|
|
@@ -48777,7 +49000,7 @@ function broadcastStateChanged(toolName, result) {
|
|
|
48777
49000
|
/* leave null */
|
|
48778
49001
|
}
|
|
48779
49002
|
const payload = { toolName, result: parsed };
|
|
48780
|
-
for (const win of BrowserWindow$
|
|
49003
|
+
for (const win of BrowserWindow$2.getAllWindows()) {
|
|
48781
49004
|
if (!win.isDestroyed()) {
|
|
48782
49005
|
try {
|
|
48783
49006
|
win.webContents.send("dash-mcp:state-changed", payload);
|
|
@@ -50538,10 +50761,10 @@ var themeFromUrlErrors$1 = {
|
|
|
50538
50761
|
* computed styles, and favicon/logo images (via node-vibrant).
|
|
50539
50762
|
*/
|
|
50540
50763
|
|
|
50541
|
-
const css = require$$0$
|
|
50764
|
+
const css = require$$0$a;
|
|
50542
50765
|
const { Vibrant } = require$$1$6;
|
|
50543
50766
|
const https = require$$11;
|
|
50544
|
-
const http = require$$0$
|
|
50767
|
+
const http = require$$0$9;
|
|
50545
50768
|
const { URL: URL$1 } = require$$4$1;
|
|
50546
50769
|
const {
|
|
50547
50770
|
UrlUnreachableError,
|
|
@@ -55101,7 +55324,7 @@ var toolHandlers$1 = {
|
|
|
55101
55324
|
* per-request, receiving the full messages array each time.
|
|
55102
55325
|
*/
|
|
55103
55326
|
|
|
55104
|
-
const Anthropic = require$$0$
|
|
55327
|
+
const Anthropic = require$$0$b;
|
|
55105
55328
|
const mcpController$2 = mcpControllerExports;
|
|
55106
55329
|
const cliController$1 = cliController_1;
|
|
55107
55330
|
const toolDefinitions = toolDefinitions$1;
|
|
@@ -57558,7 +57781,7 @@ function requireWidgetPublishManifest () {
|
|
|
57558
57781
|
* and registry interaction.
|
|
57559
57782
|
*/
|
|
57560
57783
|
const path$4 = require$$1$1;
|
|
57561
|
-
const { app: app$4, dialog: dialog$
|
|
57784
|
+
const { app: app$4, dialog: dialog$2 } = require$$0$1;
|
|
57562
57785
|
const AdmZip$2 = require$$3$2;
|
|
57563
57786
|
|
|
57564
57787
|
const themeController$3 = themeController_1;
|
|
@@ -57757,7 +57980,7 @@ async function prepareThemeForPublish$1(win, appId, themeKey, options = {}) {
|
|
|
57757
57980
|
const sanitizedName = sanitizeName(themeKey);
|
|
57758
57981
|
const defaultFilename = `theme-${sanitizedName}-v${manifest.version}.zip`;
|
|
57759
57982
|
|
|
57760
|
-
const saveResult = await dialog$
|
|
57983
|
+
const saveResult = await dialog$2.showSaveDialog(win, {
|
|
57761
57984
|
title: "Save Theme Package",
|
|
57762
57985
|
defaultPath: defaultFilename,
|
|
57763
57986
|
filters: [{ name: "ZIP Files", extensions: ["zip"] }],
|
|
@@ -58296,7 +58519,7 @@ var themeRegistryController$1 = {
|
|
|
58296
58519
|
* applies event wiring. (Import is implemented in DASH-13.)
|
|
58297
58520
|
*/
|
|
58298
58521
|
|
|
58299
|
-
const { app: app$3, dialog } = require$$0$1;
|
|
58522
|
+
const { app: app$3, dialog: dialog$1 } = require$$0$1;
|
|
58300
58523
|
const path$3 = require$$1$1;
|
|
58301
58524
|
const AdmZip$1 = require$$3$2;
|
|
58302
58525
|
const { getFileContents: getFileContents$1 } = file;
|
|
@@ -58458,7 +58681,7 @@ async function exportDashboardConfig$1(
|
|
|
58458
58681
|
.replace(/\s+/g, "-")
|
|
58459
58682
|
.toLowerCase();
|
|
58460
58683
|
|
|
58461
|
-
const { canceled, filePath } = await dialog.showSaveDialog(win, {
|
|
58684
|
+
const { canceled, filePath } = await dialog$1.showSaveDialog(win, {
|
|
58462
58685
|
title: "Export Dashboard as ZIP",
|
|
58463
58686
|
defaultPath: path$3.join(
|
|
58464
58687
|
app$3.getPath("desktop"),
|
|
@@ -58512,7 +58735,7 @@ async function exportDashboardConfig$1(
|
|
|
58512
58735
|
*/
|
|
58513
58736
|
async function selectDashboardFile$1(win) {
|
|
58514
58737
|
try {
|
|
58515
|
-
const { canceled, filePaths } = await dialog.showOpenDialog(win, {
|
|
58738
|
+
const { canceled, filePaths } = await dialog$1.showOpenDialog(win, {
|
|
58516
58739
|
title: "Import Dashboard Configuration",
|
|
58517
58740
|
filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
|
|
58518
58741
|
properties: ["openFile"],
|
|
@@ -58619,7 +58842,7 @@ async function importDashboardConfig$1(
|
|
|
58619
58842
|
zipPath = options.filePath;
|
|
58620
58843
|
} else {
|
|
58621
58844
|
// Show file picker
|
|
58622
|
-
const { canceled, filePaths } = await dialog.showOpenDialog(win, {
|
|
58845
|
+
const { canceled, filePaths } = await dialog$1.showOpenDialog(win, {
|
|
58623
58846
|
title: "Import Dashboard Configuration",
|
|
58624
58847
|
filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
|
|
58625
58848
|
properties: ["openFile"],
|
|
@@ -59967,7 +60190,7 @@ async function prepareDashboardForPublish$1(
|
|
|
59967
60190
|
|
|
59968
60191
|
// 9. Show save dialog for the publish package
|
|
59969
60192
|
const sanitizedName = manifest.name;
|
|
59970
|
-
const { canceled, filePath } = await dialog.showSaveDialog(win, {
|
|
60193
|
+
const { canceled, filePath } = await dialog$1.showSaveDialog(win, {
|
|
59971
60194
|
title: "Save Dashboard Package for Registry",
|
|
59972
60195
|
defaultPath: path$3.join(
|
|
59973
60196
|
app$3.getPath("desktop"),
|
|
@@ -60266,7 +60489,7 @@ var dashboardConfigController$1 = {
|
|
|
60266
60489
|
*/
|
|
60267
60490
|
|
|
60268
60491
|
const { Notification } = require$$0$1;
|
|
60269
|
-
const Store = require$$0$
|
|
60492
|
+
const Store = require$$0$7;
|
|
60270
60493
|
|
|
60271
60494
|
const store$1 = new Store({ name: "dash-notifications" });
|
|
60272
60495
|
|
|
@@ -60529,7 +60752,7 @@ var notificationController_1 = notificationController$2;
|
|
|
60529
60752
|
const { app: app$2 } = require$$0$1;
|
|
60530
60753
|
const fs$1 = require$$0$2;
|
|
60531
60754
|
const path$2 = require$$1$1;
|
|
60532
|
-
const WebSocket = require$$3$
|
|
60755
|
+
const WebSocket = require$$3$4;
|
|
60533
60756
|
const {
|
|
60534
60757
|
gateNetworkCall,
|
|
60535
60758
|
gateNetworkCallWithJit,
|
|
@@ -60550,16 +60773,16 @@ function _loadFlags() {
|
|
|
60550
60773
|
}
|
|
60551
60774
|
}
|
|
60552
60775
|
|
|
60553
|
-
async function _runNetworkGate(action, widgetId, args) {
|
|
60776
|
+
async function _runNetworkGate(action, widgetId, args, token) {
|
|
60554
60777
|
const settings = _loadFlags();
|
|
60555
60778
|
if (!readEnforceFlag(settings)) return { allow: true };
|
|
60556
|
-
if (!widgetId) return { allow: true }; // legacy callers
|
|
60779
|
+
if (!widgetId && !token) return { allow: true }; // legacy callers
|
|
60557
60780
|
return readJitFlag(settings)
|
|
60558
60781
|
? await gateNetworkCallWithJit(
|
|
60559
|
-
{ widgetId, action, args },
|
|
60782
|
+
{ widgetId, token, action, args },
|
|
60560
60783
|
{ enableJit: true },
|
|
60561
60784
|
)
|
|
60562
|
-
: gateNetworkCall({ widgetId, action, args });
|
|
60785
|
+
: gateNetworkCall({ widgetId, token, action, args });
|
|
60563
60786
|
}
|
|
60564
60787
|
|
|
60565
60788
|
/**
|
|
@@ -60991,17 +61214,20 @@ const webSocketController$1 = {
|
|
|
60991
61214
|
* @param {object} config - { url, headers, subprotocols, credentials }
|
|
60992
61215
|
* @returns {{ success, providerName, status } | { error, message }}
|
|
60993
61216
|
*/
|
|
60994
|
-
connect: async (win, providerName, config, widgetId = null) => {
|
|
60995
|
-
// Phase 3 network gate — fires
|
|
60996
|
-
// supplied. The interpolated URL (with credentials substituted)
|
|
60997
|
-
// what we actually open the socket to, so the gate uses it for
|
|
61217
|
+
connect: async (win, providerName, config, widgetId = null, token = null) => {
|
|
61218
|
+
// Phase 3 network gate — fires when an explicit widgetId or token
|
|
61219
|
+
// is supplied. The interpolated URL (with credentials substituted)
|
|
61220
|
+
// is what we actually open the socket to, so the gate uses it for
|
|
60998
61221
|
// hostname extraction.
|
|
60999
61222
|
const interpolatedForGate = config?.credentials
|
|
61000
61223
|
? interpolate(config.url, config.credentials)
|
|
61001
61224
|
: config?.url;
|
|
61002
|
-
const gateResult = await _runNetworkGate(
|
|
61003
|
-
|
|
61004
|
-
|
|
61225
|
+
const gateResult = await _runNetworkGate(
|
|
61226
|
+
"wsConnect",
|
|
61227
|
+
widgetId,
|
|
61228
|
+
{ url: interpolatedForGate },
|
|
61229
|
+
token,
|
|
61230
|
+
);
|
|
61005
61231
|
if (!gateResult.allow) {
|
|
61006
61232
|
return {
|
|
61007
61233
|
error: true,
|
|
@@ -61465,6 +61691,133 @@ function buildGrantsListing$1(
|
|
|
61465
61691
|
|
|
61466
61692
|
var widgetMcpGrantsListing = { buildGrantsListing: buildGrantsListing$1 };
|
|
61467
61693
|
|
|
61694
|
+
/**
|
|
61695
|
+
* grantDiff.js
|
|
61696
|
+
*
|
|
61697
|
+
* Pure-function diff between two grant blobs. Used by the
|
|
61698
|
+
* `widget-mcp:set-grant` IPC handler to decide whether the change
|
|
61699
|
+
* needs OS-native confirmation (broadening permissions) or can pass
|
|
61700
|
+
* through silently (revocations / equal / narrowing).
|
|
61701
|
+
*
|
|
61702
|
+
* Returns { broadening: boolean, summary: string[] }. `summary` is a
|
|
61703
|
+
* list of human-readable additions used to populate the native
|
|
61704
|
+
* confirm dialog.
|
|
61705
|
+
*
|
|
61706
|
+
* Broadening dimensions checked:
|
|
61707
|
+
* - servers: new server name present in newGrant.servers but not in
|
|
61708
|
+
* currentGrant.servers
|
|
61709
|
+
* - server tools: new tool name in an existing server's `tools[]`
|
|
61710
|
+
* - server paths: new entry in `readPaths[]` or `writePaths[]`
|
|
61711
|
+
* (including `*` wildcard added)
|
|
61712
|
+
* - domains.fs: new block, or new `readPaths[]` / `writePaths[]`
|
|
61713
|
+
* entry within an existing block (including `*`)
|
|
61714
|
+
* - domains.network: new block, or new `hosts[]` entry (including
|
|
61715
|
+
* `*` and `*.<base>` wildcards)
|
|
61716
|
+
*
|
|
61717
|
+
* Reductions, equality, and "no permission" → "no permission"
|
|
61718
|
+
* transitions are NOT broadening.
|
|
61719
|
+
*/
|
|
61720
|
+
|
|
61721
|
+
function _arr(x) {
|
|
61722
|
+
return Array.isArray(x) ? x : [];
|
|
61723
|
+
}
|
|
61724
|
+
|
|
61725
|
+
function _added(currentList, newList) {
|
|
61726
|
+
const cur = new Set(_arr(currentList));
|
|
61727
|
+
const out = [];
|
|
61728
|
+
for (const item of _arr(newList)) {
|
|
61729
|
+
if (!cur.has(item)) out.push(item);
|
|
61730
|
+
}
|
|
61731
|
+
return out;
|
|
61732
|
+
}
|
|
61733
|
+
|
|
61734
|
+
function _diffServer(serverName, currentSrv, newSrv) {
|
|
61735
|
+
const summary = [];
|
|
61736
|
+
const cur = currentSrv || {};
|
|
61737
|
+
const nxt = newSrv || {};
|
|
61738
|
+
|
|
61739
|
+
for (const tool of _added(cur.tools, nxt.tools)) {
|
|
61740
|
+
summary.push(`server "${serverName}" tool "${tool}"`);
|
|
61741
|
+
}
|
|
61742
|
+
for (const p of _added(cur.readPaths, nxt.readPaths)) {
|
|
61743
|
+
summary.push(`server "${serverName}" readPath "${p}"`);
|
|
61744
|
+
}
|
|
61745
|
+
for (const p of _added(cur.writePaths, nxt.writePaths)) {
|
|
61746
|
+
summary.push(`server "${serverName}" writePath "${p}"`);
|
|
61747
|
+
}
|
|
61748
|
+
return summary;
|
|
61749
|
+
}
|
|
61750
|
+
|
|
61751
|
+
function _diffServers(curServers, nxtServers) {
|
|
61752
|
+
const summary = [];
|
|
61753
|
+
const cur = curServers || {};
|
|
61754
|
+
const nxt = nxtServers || {};
|
|
61755
|
+
for (const name of Object.keys(nxt)) {
|
|
61756
|
+
if (!cur[name]) {
|
|
61757
|
+
// Whole new server entry → list each component as broadening.
|
|
61758
|
+
const srv = nxt[name];
|
|
61759
|
+
const tools = _arr(srv?.tools);
|
|
61760
|
+
const reads = _arr(srv?.readPaths);
|
|
61761
|
+
const writes = _arr(srv?.writePaths);
|
|
61762
|
+
if (tools.length === 0 && reads.length === 0 && writes.length === 0) {
|
|
61763
|
+
// Empty-shell server entry — no actual permissions added.
|
|
61764
|
+
// Skip; not a meaningful broadening.
|
|
61765
|
+
continue;
|
|
61766
|
+
}
|
|
61767
|
+
summary.push(`new server "${name}"`);
|
|
61768
|
+
for (const t of tools) summary.push(` tool "${t}"`);
|
|
61769
|
+
for (const p of reads) summary.push(` readPath "${p}"`);
|
|
61770
|
+
for (const p of writes) summary.push(` writePath "${p}"`);
|
|
61771
|
+
} else {
|
|
61772
|
+
summary.push(..._diffServer(name, cur[name], nxt[name]));
|
|
61773
|
+
}
|
|
61774
|
+
}
|
|
61775
|
+
return summary;
|
|
61776
|
+
}
|
|
61777
|
+
|
|
61778
|
+
function _diffDomainsFs(curFs, nxtFs) {
|
|
61779
|
+
const summary = [];
|
|
61780
|
+
const cur = curFs || {};
|
|
61781
|
+
const nxt = nxtFs || {};
|
|
61782
|
+
for (const p of _added(cur.readPaths, nxt.readPaths)) {
|
|
61783
|
+
summary.push(`fs readPath "${p}"`);
|
|
61784
|
+
}
|
|
61785
|
+
for (const p of _added(cur.writePaths, nxt.writePaths)) {
|
|
61786
|
+
summary.push(`fs writePath "${p}"`);
|
|
61787
|
+
}
|
|
61788
|
+
return summary;
|
|
61789
|
+
}
|
|
61790
|
+
|
|
61791
|
+
function _diffDomainsNetwork(curNet, nxtNet) {
|
|
61792
|
+
const summary = [];
|
|
61793
|
+
const cur = curNet || {};
|
|
61794
|
+
const nxt = nxtNet || {};
|
|
61795
|
+
for (const h of _added(cur.hosts, nxt.hosts)) {
|
|
61796
|
+
summary.push(`network host "${h}"`);
|
|
61797
|
+
}
|
|
61798
|
+
return summary;
|
|
61799
|
+
}
|
|
61800
|
+
|
|
61801
|
+
/**
|
|
61802
|
+
* @param {object|null|undefined} currentGrant
|
|
61803
|
+
* @param {object|null|undefined} newGrant
|
|
61804
|
+
* @returns {{ broadening: boolean, summary: string[] }}
|
|
61805
|
+
*/
|
|
61806
|
+
function isBroadening$1(currentGrant, newGrant) {
|
|
61807
|
+
const cur = currentGrant || {};
|
|
61808
|
+
const nxt = newGrant || {};
|
|
61809
|
+
|
|
61810
|
+
const summary = [
|
|
61811
|
+
..._diffServers(cur.servers, nxt.servers),
|
|
61812
|
+
..._diffDomainsFs(cur?.domains?.fs, nxt?.domains?.fs),
|
|
61813
|
+
..._diffDomainsNetwork(cur?.domains?.network, nxt?.domains?.network),
|
|
61814
|
+
];
|
|
61815
|
+
|
|
61816
|
+
return { broadening: summary.length > 0, summary };
|
|
61817
|
+
}
|
|
61818
|
+
|
|
61819
|
+
var grantDiff = { isBroadening: isBroadening$1 };
|
|
61820
|
+
|
|
61468
61821
|
/**
|
|
61469
61822
|
* widgetMcpGrantsController.js
|
|
61470
61823
|
*
|
|
@@ -61480,7 +61833,7 @@ var widgetMcpGrantsListing = { buildGrantsListing: buildGrantsListing$1 };
|
|
|
61480
61833
|
* grant are also surfaced — those are the install-consent retroactive prompts.
|
|
61481
61834
|
*/
|
|
61482
61835
|
|
|
61483
|
-
const { ipcMain: ipcMain$1 } = require$$0$1;
|
|
61836
|
+
const { ipcMain: ipcMain$2, dialog, BrowserWindow: BrowserWindow$1 } = require$$0$1;
|
|
61484
61837
|
const {
|
|
61485
61838
|
getGrant,
|
|
61486
61839
|
setGrant,
|
|
@@ -61491,21 +61844,70 @@ const {
|
|
|
61491
61844
|
const { getWidgetMcpPermissions } = widgetPermissions;
|
|
61492
61845
|
const { getWidgetRegistry } = widgetRegistryExports;
|
|
61493
61846
|
const { buildGrantsListing } = widgetMcpGrantsListing;
|
|
61847
|
+
const { isBroadening } = grantDiff;
|
|
61848
|
+
|
|
61849
|
+
// Native confirm dialog for any set-grant call that broadens the
|
|
61850
|
+
// widget's current permissions. The dialog runs at OS level — a
|
|
61851
|
+
// renderer (including a malicious widget) cannot dismiss it
|
|
61852
|
+
// programmatically. This is the defense-in-depth fix for the
|
|
61853
|
+
// `widget-mcp:set-grant` consent-bypass gap documented in the IPC
|
|
61854
|
+
// audit doc: a widget calling `mainApi.widgetMcp.setGrant("@self",
|
|
61855
|
+
// {wide-open perms})` now triggers a system-level prompt the user
|
|
61856
|
+
// must explicitly approve. Reductions / equality pass unprompted.
|
|
61857
|
+
async function _confirmBroadening(event, widgetId, summary) {
|
|
61858
|
+
const senderWindow =
|
|
61859
|
+
BrowserWindow$1.fromWebContents(event.sender) ||
|
|
61860
|
+
BrowserWindow$1.getFocusedWindow();
|
|
61861
|
+
// Cap the listed lines so the dialog body stays readable.
|
|
61862
|
+
const MAX_LINES = 20;
|
|
61863
|
+
const trimmed = summary.slice(0, MAX_LINES);
|
|
61864
|
+
const overflow =
|
|
61865
|
+
summary.length > MAX_LINES
|
|
61866
|
+
? `\n …and ${summary.length - MAX_LINES} more`
|
|
61867
|
+
: "";
|
|
61868
|
+
const detail =
|
|
61869
|
+
"Widget '" +
|
|
61870
|
+
widgetId +
|
|
61871
|
+
"' will be granted the following NEW permissions:\n\n " +
|
|
61872
|
+
trimmed.join("\n ") +
|
|
61873
|
+
overflow +
|
|
61874
|
+
"\n\nIf you didn't initiate this from Settings → Privacy & Security, " +
|
|
61875
|
+
"click Cancel — a malicious widget may be trying to escalate its own " +
|
|
61876
|
+
"permissions.";
|
|
61877
|
+
|
|
61878
|
+
const result = await dialog.showMessageBox(senderWindow, {
|
|
61879
|
+
type: "warning",
|
|
61880
|
+
title: "Confirm permissions change",
|
|
61881
|
+
message: "Allow new permissions for " + widgetId + "?",
|
|
61882
|
+
detail,
|
|
61883
|
+
buttons: ["Cancel", "Allow"],
|
|
61884
|
+
defaultId: 0,
|
|
61885
|
+
cancelId: 0,
|
|
61886
|
+
noLink: true,
|
|
61887
|
+
});
|
|
61888
|
+
return result.response === 1;
|
|
61889
|
+
}
|
|
61494
61890
|
|
|
61495
61891
|
function setupWidgetMcpGrantsHandlers() {
|
|
61496
|
-
ipcMain$
|
|
61892
|
+
ipcMain$2.handle("widget-mcp:get-grant", (event, widgetId) => {
|
|
61497
61893
|
return getGrant(widgetId);
|
|
61498
61894
|
});
|
|
61499
61895
|
|
|
61500
|
-
ipcMain$
|
|
61896
|
+
ipcMain$2.handle("widget-mcp:set-grant", async (event, widgetId, perms) => {
|
|
61897
|
+
const current = getGrant(widgetId);
|
|
61898
|
+
const diff = isBroadening(current, perms);
|
|
61899
|
+
if (diff.broadening) {
|
|
61900
|
+
const approved = await _confirmBroadening(event, widgetId, diff.summary);
|
|
61901
|
+
if (!approved) return false;
|
|
61902
|
+
}
|
|
61501
61903
|
return setGrant(widgetId, perms);
|
|
61502
61904
|
});
|
|
61503
61905
|
|
|
61504
|
-
ipcMain$
|
|
61906
|
+
ipcMain$2.handle("widget-mcp:revoke", (event, widgetId) => {
|
|
61505
61907
|
return revokeGrant(widgetId);
|
|
61506
61908
|
});
|
|
61507
61909
|
|
|
61508
|
-
ipcMain$
|
|
61910
|
+
ipcMain$2.handle("widget-mcp:revoke-server", (event, widgetId, serverName) => {
|
|
61509
61911
|
return revokeServer(widgetId, serverName);
|
|
61510
61912
|
});
|
|
61511
61913
|
|
|
@@ -61515,7 +61917,7 @@ function setupWidgetMcpGrantsHandlers() {
|
|
|
61515
61917
|
// "Grant manually" for unmanifested widgets. Plus orphan-grant rows for
|
|
61516
61918
|
// granted-but-uninstalled cases. Logic delegated to
|
|
61517
61919
|
// widgetMcpGrantsListing.buildGrantsListing for unit-testability.
|
|
61518
|
-
ipcMain$
|
|
61920
|
+
ipcMain$2.handle("widget-mcp:list-all", () => {
|
|
61519
61921
|
const grantsByWidget = new Map();
|
|
61520
61922
|
for (const { widgetId, granted } of listAllGrants()) {
|
|
61521
61923
|
grantsByWidget.set(widgetId, granted);
|
|
@@ -61546,6 +61948,46 @@ function setupWidgetMcpGrantsHandlers() {
|
|
|
61546
61948
|
|
|
61547
61949
|
var widgetMcpGrantsController$1 = { setupWidgetMcpGrantsHandlers };
|
|
61548
61950
|
|
|
61951
|
+
/**
|
|
61952
|
+
* widgetMountTokenController.js
|
|
61953
|
+
*
|
|
61954
|
+
* IPC handlers for the widget mount-token registry. Called by
|
|
61955
|
+
* `WidgetFactory` at React mount/unmount time. Returns a fresh
|
|
61956
|
+
* server-generated token that the widget framework bakes into the
|
|
61957
|
+
* widget's bound API; the renderer never picks the token itself.
|
|
61958
|
+
*
|
|
61959
|
+
* See `electron/security/mountTokenRegistry.js` for the registry and
|
|
61960
|
+
* the longer threat-model note.
|
|
61961
|
+
*
|
|
61962
|
+
* Channels:
|
|
61963
|
+
* - "framework:register-widget-mount" (widgetId) → token string
|
|
61964
|
+
* - "framework:unregister-widget-mount" (token) → boolean (true = unregistered)
|
|
61965
|
+
*/
|
|
61966
|
+
|
|
61967
|
+
const { ipcMain: ipcMain$1 } = require$$0$1;
|
|
61968
|
+
const { register, unregister } = mountTokenRegistry;
|
|
61969
|
+
|
|
61970
|
+
function setupWidgetMountTokenHandlers() {
|
|
61971
|
+
ipcMain$1.handle("framework:register-widget-mount", (_event, widgetId) => {
|
|
61972
|
+
if (typeof widgetId !== "string" || widgetId.length === 0) {
|
|
61973
|
+
return null;
|
|
61974
|
+
}
|
|
61975
|
+
try {
|
|
61976
|
+
return register(widgetId);
|
|
61977
|
+
} catch {
|
|
61978
|
+
return null;
|
|
61979
|
+
}
|
|
61980
|
+
});
|
|
61981
|
+
|
|
61982
|
+
ipcMain$1.handle("framework:unregister-widget-mount", (_event, token) => {
|
|
61983
|
+
if (typeof token !== "string" || token.length === 0) return false;
|
|
61984
|
+
unregister(token);
|
|
61985
|
+
return true;
|
|
61986
|
+
});
|
|
61987
|
+
}
|
|
61988
|
+
|
|
61989
|
+
var widgetMountTokenController$1 = { setupWidgetMountTokenHandlers };
|
|
61990
|
+
|
|
61549
61991
|
/**
|
|
61550
61992
|
* clientFactories.js
|
|
61551
61993
|
*
|
|
@@ -61569,7 +62011,7 @@ clientCache$1.registerFactory("algolia", (credentials) => {
|
|
|
61569
62011
|
|
|
61570
62012
|
// --- OpenAI ---
|
|
61571
62013
|
clientCache$1.registerFactory("openai", (credentials) => {
|
|
61572
|
-
const OpenAI = require$$0$
|
|
62014
|
+
const OpenAI = require$$0$8;
|
|
61573
62015
|
return new OpenAI({ apiKey: credentials.apiKey });
|
|
61574
62016
|
});
|
|
61575
62017
|
|
|
@@ -61588,7 +62030,7 @@ const MAX_RECENTS = 20;
|
|
|
61588
62030
|
let store = null;
|
|
61589
62031
|
function getStore() {
|
|
61590
62032
|
if (!store) {
|
|
61591
|
-
const Store = require$$0$
|
|
62033
|
+
const Store = require$$0$7;
|
|
61592
62034
|
store = new Store({ name: "dash-session" });
|
|
61593
62035
|
}
|
|
61594
62036
|
return store;
|
|
@@ -63044,8 +63486,8 @@ const dataApi$2 = {
|
|
|
63044
63486
|
ipcRenderer$l.invoke(READ_JSON, { filepath, objectCount });
|
|
63045
63487
|
},
|
|
63046
63488
|
|
|
63047
|
-
readDataFromURL: (url, toFilepath, widgetId = null) => {
|
|
63048
|
-
ipcRenderer$l.invoke(READ_DATA_URL, { url, toFilepath, widgetId });
|
|
63489
|
+
readDataFromURL: (url, toFilepath, widgetId = null, token = null) => {
|
|
63490
|
+
ipcRenderer$l.invoke(READ_DATA_URL, { url, toFilepath, widgetId, token });
|
|
63049
63491
|
},
|
|
63050
63492
|
|
|
63051
63493
|
/*
|
|
@@ -63053,13 +63495,21 @@ const dataApi$2 = {
|
|
|
63053
63495
|
* @param {object} options { filename, extension }
|
|
63054
63496
|
* @param {object} returnEmpty the return empty object
|
|
63055
63497
|
*/
|
|
63056
|
-
saveData: (
|
|
63498
|
+
saveData: (
|
|
63499
|
+
data,
|
|
63500
|
+
filename,
|
|
63501
|
+
append,
|
|
63502
|
+
returnEmpty,
|
|
63503
|
+
widgetId = null,
|
|
63504
|
+
token = null,
|
|
63505
|
+
) =>
|
|
63057
63506
|
ipcRenderer$l.invoke(DATA_SAVE_TO_FILE, {
|
|
63058
63507
|
data,
|
|
63059
63508
|
filename,
|
|
63060
63509
|
append,
|
|
63061
63510
|
returnEmpty,
|
|
63062
63511
|
widgetId,
|
|
63512
|
+
token,
|
|
63063
63513
|
}),
|
|
63064
63514
|
|
|
63065
63515
|
/*
|
|
@@ -63071,11 +63521,12 @@ const dataApi$2 = {
|
|
|
63071
63521
|
* for legacy callers (`enforceWidgetMcpPermissions` flag still
|
|
63072
63522
|
* gates the gate itself).
|
|
63073
63523
|
*/
|
|
63074
|
-
readData: (filename, returnEmpty = [], widgetId = null) =>
|
|
63524
|
+
readData: (filename, returnEmpty = [], widgetId = null, token = null) =>
|
|
63075
63525
|
ipcRenderer$l.invoke(DATA_READ_FROM_FILE, {
|
|
63076
63526
|
filename,
|
|
63077
63527
|
returnEmpty,
|
|
63078
63528
|
widgetId,
|
|
63529
|
+
token,
|
|
63079
63530
|
}),
|
|
63080
63531
|
|
|
63081
63532
|
/**
|
|
@@ -63848,6 +64299,7 @@ const mcpApi$2 = {
|
|
|
63848
64299
|
allowedTools = null,
|
|
63849
64300
|
widgetId = null,
|
|
63850
64301
|
workspaceId = null,
|
|
64302
|
+
token = null,
|
|
63851
64303
|
) =>
|
|
63852
64304
|
ipcRenderer$g.invoke(MCP_CALL_TOOL, {
|
|
63853
64305
|
serverName,
|
|
@@ -63856,6 +64308,7 @@ const mcpApi$2 = {
|
|
|
63856
64308
|
allowedTools,
|
|
63857
64309
|
widgetId,
|
|
63858
64310
|
workspaceId,
|
|
64311
|
+
token,
|
|
63859
64312
|
}),
|
|
63860
64313
|
|
|
63861
64314
|
/**
|
|
@@ -65031,8 +65484,8 @@ const webSocketApi$2 = {
|
|
|
65031
65484
|
* @param {object} config { url, headers, subprotocols, credentials }
|
|
65032
65485
|
* @returns {Promise<{ success, providerName, status } | { error, message }>}
|
|
65033
65486
|
*/
|
|
65034
|
-
connect: (providerName, config, widgetId = null) =>
|
|
65035
|
-
ipcRenderer$4.invoke(WS_CONNECT, { providerName, config, widgetId }),
|
|
65487
|
+
connect: (providerName, config, widgetId = null, token = null) =>
|
|
65488
|
+
ipcRenderer$4.invoke(WS_CONNECT, { providerName, config, widgetId, token }),
|
|
65036
65489
|
|
|
65037
65490
|
/**
|
|
65038
65491
|
* disconnect
|
|
@@ -66552,6 +67005,7 @@ const webSocketController = webSocketController_1;
|
|
|
66552
67005
|
const extractionCacheController = extractionCacheController_1;
|
|
66553
67006
|
const mcpDashServerController = mcpDashServerController_1;
|
|
66554
67007
|
const widgetMcpGrantsController = widgetMcpGrantsController$1;
|
|
67008
|
+
const widgetMountTokenController = widgetMountTokenController$1;
|
|
66555
67009
|
const jitConsent = jitConsent$1;
|
|
66556
67010
|
|
|
66557
67011
|
// --- Errors ---
|
|
@@ -66655,6 +67109,7 @@ var electron = {
|
|
|
66655
67109
|
extractionCacheController,
|
|
66656
67110
|
mcpDashServerController,
|
|
66657
67111
|
widgetMcpGrantsController,
|
|
67112
|
+
widgetMountTokenController,
|
|
66658
67113
|
jitConsent,
|
|
66659
67114
|
|
|
66660
67115
|
// Controller functions (flat) — spread for convenient destructuring
|