@mcp-use/client 2.0.0-beta.0 → 2.0.0-beta.10
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/.tsbuildinfo +1 -1
- package/dist/auth/browser.d.ts +8 -4
- package/dist/auth/browser.d.ts.map +1 -1
- package/dist/auth/session-store.d.ts +5 -0
- package/dist/auth/session-store.d.ts.map +1 -1
- package/dist/index-browser.d.ts +1 -1
- package/dist/index-browser.d.ts.map +1 -1
- package/dist/index-browser.js +49 -151
- package/dist/index-browser.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -161
- package/dist/index.js.map +1 -1
- package/dist/react/McpClientProvider.d.ts.map +1 -1
- package/dist/react/index.js +309 -215
- package/dist/react/index.js.map +1 -1
- package/dist/react/types.d.ts +9 -3
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/useMcp-helpers.d.ts.map +1 -1
- package/dist/react/useMcp-operations.d.ts.map +1 -1
- package/dist/react/useMcp.d.ts.map +1 -1
- package/dist/react/view/ViewRenderer.d.ts +2 -1
- package/dist/react/view/ViewRenderer.d.ts.map +1 -1
- package/dist/react/view/inject-openai-file-apis.d.ts +6 -0
- package/dist/react/view/inject-openai-file-apis.d.ts.map +1 -0
- package/dist/react/view/types.d.ts +16 -0
- package/dist/react/view/types.d.ts.map +1 -1
- package/dist/react/view/use-display-mode.d.ts +1 -0
- package/dist/react/view/use-display-mode.d.ts.map +1 -1
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/tel-fetch.d.ts +0 -6
- package/dist/telemetry/tel-fetch.d.ts.map +1 -1
- package/dist/telemetry/telemetry-node.d.ts.map +1 -1
- package/dist/telemetry/telemetry.d.ts +0 -8
- package/dist/telemetry/telemetry.d.ts.map +1 -1
- package/dist/transport/http.d.ts +6 -6
- package/package.json +2 -2
package/dist/react/index.js
CHANGED
|
@@ -1473,7 +1473,7 @@ var HttpConnector = class extends BaseConnector {
|
|
|
1473
1473
|
};
|
|
1474
1474
|
|
|
1475
1475
|
// src/utils/version.ts
|
|
1476
|
-
var VERSION = "2.0.0-beta.
|
|
1476
|
+
var VERSION = "2.0.0-beta.9";
|
|
1477
1477
|
function getPackageVersion() {
|
|
1478
1478
|
return VERSION;
|
|
1479
1479
|
}
|
|
@@ -1849,6 +1849,14 @@ var OAuthSessionStore = class _OAuthSessionStore {
|
|
|
1849
1849
|
async getTokenEndpoint() {
|
|
1850
1850
|
return (await this.discoveryState())?.authorizationServerMetadata?.token_endpoint ?? null;
|
|
1851
1851
|
}
|
|
1852
|
+
/**
|
|
1853
|
+
* Return the protected-resource URL selected during OAuth discovery.
|
|
1854
|
+
* Consumers can persist it and reuse it for server-side refresh exchanges.
|
|
1855
|
+
*/
|
|
1856
|
+
async getResource() {
|
|
1857
|
+
const resource = (await this.discoveryState())?.resourceMetadata?.resource;
|
|
1858
|
+
return typeof resource === "string" ? resource : null;
|
|
1859
|
+
}
|
|
1852
1860
|
};
|
|
1853
1861
|
|
|
1854
1862
|
// src/auth/browser.ts
|
|
@@ -1966,20 +1974,19 @@ var BrowserOAuthClientProvider = class {
|
|
|
1966
1974
|
* therefore never alters fetch behavior for other servers, other
|
|
1967
1975
|
* connections, or the rest of the page.
|
|
1968
1976
|
*
|
|
1969
|
-
*
|
|
1970
|
-
*
|
|
1971
|
-
*
|
|
1972
|
-
*
|
|
1977
|
+
* OAuth metadata is always fetched with `cache: "no-store"`, including in
|
|
1978
|
+
* direct mode. Authorization servers commonly vary CORS headers by Origin;
|
|
1979
|
+
* bypassing the browser HTTP cache prevents a revalidated response cached
|
|
1980
|
+
* for another localhost origin from poisoning discovery. When OAuth proxying
|
|
1981
|
+
* is disabled or no `oauthProxyUrl` is configured, all requests still go
|
|
1982
|
+
* directly to their original URLs.
|
|
1973
1983
|
*
|
|
1974
1984
|
* @param baseFetch - The fetch used for non-OAuth requests and for the
|
|
1975
1985
|
* underlying proxy calls. Defaults to the global `fetch`.
|
|
1976
1986
|
*/
|
|
1977
1987
|
getProxyFetch(baseFetch) {
|
|
1978
|
-
if (!this.proxyOAuthRequests || !this.oauthProxyUrl) {
|
|
1979
|
-
return baseFetch;
|
|
1980
|
-
}
|
|
1981
1988
|
const base = baseFetch ?? globalThis.fetch.bind(globalThis);
|
|
1982
|
-
const oauthProxyUrl = this.oauthProxyUrl;
|
|
1989
|
+
const oauthProxyUrl = this.proxyOAuthRequests && this.oauthProxyUrl ? this.oauthProxyUrl : void 0;
|
|
1983
1990
|
const discoveredEndpoints = /* @__PURE__ */ new Set();
|
|
1984
1991
|
let restoredDiscovery = false;
|
|
1985
1992
|
return async (input, init) => {
|
|
@@ -1992,6 +1999,12 @@ var BrowserOAuthClientProvider = class {
|
|
|
1992
1999
|
return await base(input, init);
|
|
1993
2000
|
}
|
|
1994
2001
|
const isMetadata = pathname.includes("/.well-known/");
|
|
2002
|
+
if (!oauthProxyUrl) {
|
|
2003
|
+
return await base(
|
|
2004
|
+
isMetadata ? url : input,
|
|
2005
|
+
isMetadata ? { ...init, cache: "no-store" } : init
|
|
2006
|
+
);
|
|
2007
|
+
}
|
|
1995
2008
|
if (!restoredDiscovery) {
|
|
1996
2009
|
restoredDiscovery = true;
|
|
1997
2010
|
const metadata = (await this.discoveryState())?.authorizationServerMetadata;
|
|
@@ -2026,7 +2039,8 @@ var BrowserOAuthClientProvider = class {
|
|
|
2026
2039
|
if (isMetadata) {
|
|
2027
2040
|
const response2 = await base(proxyEndpoint, {
|
|
2028
2041
|
...init,
|
|
2029
|
-
method: "GET"
|
|
2042
|
+
method: "GET",
|
|
2043
|
+
cache: "no-store"
|
|
2030
2044
|
});
|
|
2031
2045
|
try {
|
|
2032
2046
|
const metadata = await response2.clone().json();
|
|
@@ -2083,7 +2097,16 @@ var BrowserOAuthClientProvider = class {
|
|
|
2083
2097
|
}
|
|
2084
2098
|
async saveClientInformation(clientInformation, ctx) {
|
|
2085
2099
|
if (this.staticClientInfo) return;
|
|
2086
|
-
|
|
2100
|
+
const { client_secret: discardedClientSecret, ...publicClientInformation } = clientInformation;
|
|
2101
|
+
if (discardedClientSecret) {
|
|
2102
|
+
console.info(
|
|
2103
|
+
`[${this.storageKeyPrefix}] Discarded client_secret returned for a public browser OAuth client.`
|
|
2104
|
+
);
|
|
2105
|
+
}
|
|
2106
|
+
return this.session.saveClientInformation(
|
|
2107
|
+
publicClientInformation,
|
|
2108
|
+
ctx
|
|
2109
|
+
);
|
|
2087
2110
|
}
|
|
2088
2111
|
codeVerifier() {
|
|
2089
2112
|
return this.session.codeVerifier();
|
|
@@ -2113,6 +2136,10 @@ var BrowserOAuthClientProvider = class {
|
|
|
2113
2136
|
getTokenEndpoint() {
|
|
2114
2137
|
return this.session.getTokenEndpoint();
|
|
2115
2138
|
}
|
|
2139
|
+
/** Return the protected-resource URL selected during OAuth discovery. */
|
|
2140
|
+
getResource() {
|
|
2141
|
+
return this.session.getResource();
|
|
2142
|
+
}
|
|
2116
2143
|
/**
|
|
2117
2144
|
* Return the stored public OAuth client ID. Browser providers do not retain
|
|
2118
2145
|
* client secrets.
|
|
@@ -2370,62 +2397,6 @@ async function telFetch(url, init) {
|
|
|
2370
2397
|
}
|
|
2371
2398
|
var POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
2372
2399
|
var POSTHOG_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI";
|
|
2373
|
-
var SCARF_GATEWAY_URL = "https://mcpuse.gateway.scarf.sh/events-ts";
|
|
2374
|
-
var SCARF_GATEWAY_BEACON_URL = "https://mcpuse.gateway.scarf.sh/simple/";
|
|
2375
|
-
var SCARF_BEACON_MAX_URL = 1800;
|
|
2376
|
-
var SCARF_BEACON_TRUNCATED_KEYS = /* @__PURE__ */ new Set(["query", "response", "messages"]);
|
|
2377
|
-
function stringifyScarfValue(value) {
|
|
2378
|
-
if (value === null || value === void 0) return "";
|
|
2379
|
-
if (typeof value === "string") return value;
|
|
2380
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
2381
|
-
return String(value);
|
|
2382
|
-
}
|
|
2383
|
-
try {
|
|
2384
|
-
return JSON.stringify(value);
|
|
2385
|
-
} catch {
|
|
2386
|
-
return String(value);
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
function buildScarfBeaconUrl(properties, baseUrl = SCARF_GATEWAY_BEACON_URL) {
|
|
2390
|
-
const params = new URLSearchParams();
|
|
2391
|
-
for (const [key, value] of Object.entries(properties)) {
|
|
2392
|
-
let serialized = stringifyScarfValue(value);
|
|
2393
|
-
if (SCARF_BEACON_TRUNCATED_KEYS.has(key) && serialized.length > 120) {
|
|
2394
|
-
serialized = `${serialized.slice(0, 117)}...`;
|
|
2395
|
-
}
|
|
2396
|
-
if (serialized !== "") params.set(key, serialized);
|
|
2397
|
-
}
|
|
2398
|
-
let url = `${baseUrl}${baseUrl.includes("?") ? "&" : "?"}${params.toString()}`;
|
|
2399
|
-
if (url.length <= SCARF_BEACON_MAX_URL) return url;
|
|
2400
|
-
const keys = [...params.keys()].sort(
|
|
2401
|
-
(a, b) => (params.get(b)?.length ?? 0) - (params.get(a)?.length ?? 0)
|
|
2402
|
-
);
|
|
2403
|
-
for (const key of keys) {
|
|
2404
|
-
if (url.length <= SCARF_BEACON_MAX_URL) break;
|
|
2405
|
-
if (key === "event" || key === "user_id") continue;
|
|
2406
|
-
params.delete(key);
|
|
2407
|
-
url = `${baseUrl}${baseUrl.includes("?") ? "&" : "?"}${params.toString()}`;
|
|
2408
|
-
}
|
|
2409
|
-
return url.slice(0, SCARF_BEACON_MAX_URL);
|
|
2410
|
-
}
|
|
2411
|
-
function captureScarfPost(properties, endpoint) {
|
|
2412
|
-
return telFetch(endpoint, {
|
|
2413
|
-
method: "POST",
|
|
2414
|
-
headers: { "Content-Type": "application/json" },
|
|
2415
|
-
keepalive: true,
|
|
2416
|
-
body: JSON.stringify(properties)
|
|
2417
|
-
});
|
|
2418
|
-
}
|
|
2419
|
-
function captureScarfBeacon(properties, endpoint) {
|
|
2420
|
-
try {
|
|
2421
|
-
const url = buildScarfBeaconUrl(properties, endpoint);
|
|
2422
|
-
const img = new Image();
|
|
2423
|
-
img.referrerPolicy = "no-referrer-when-downgrade";
|
|
2424
|
-
img.src = url;
|
|
2425
|
-
} catch {
|
|
2426
|
-
}
|
|
2427
|
-
return Promise.resolve();
|
|
2428
|
-
}
|
|
2429
2400
|
function capturePostHog(params) {
|
|
2430
2401
|
const host = params.host ?? POSTHOG_HOST;
|
|
2431
2402
|
const apiKey = params.apiKey ?? POSTHOG_API_KEY;
|
|
@@ -2442,13 +2413,6 @@ function capturePostHog(params) {
|
|
|
2442
2413
|
})
|
|
2443
2414
|
});
|
|
2444
2415
|
}
|
|
2445
|
-
function captureScarf(properties, endpoint = SCARF_GATEWAY_URL) {
|
|
2446
|
-
if (typeof window !== "undefined") {
|
|
2447
|
-
const beaconEndpoint = endpoint === SCARF_GATEWAY_URL ? SCARF_GATEWAY_BEACON_URL : endpoint;
|
|
2448
|
-
return captureScarfBeacon(properties, beaconEndpoint);
|
|
2449
|
-
}
|
|
2450
|
-
return captureScarfPost(properties, endpoint);
|
|
2451
|
-
}
|
|
2452
2416
|
|
|
2453
2417
|
// src/telemetry/telemetry.ts
|
|
2454
2418
|
function generateUUID() {
|
|
@@ -2459,18 +2423,6 @@ function secureRandomString() {
|
|
|
2459
2423
|
globalThis.crypto.getRandomValues(array);
|
|
2460
2424
|
return Array.from(array, (v) => v.toString(16).padStart(2, "0")).join("");
|
|
2461
2425
|
}
|
|
2462
|
-
function isVersionGreater(a, b) {
|
|
2463
|
-
const parse = (v) => v.split("-")[0].split(".").map((n) => parseInt(n, 10) || 0);
|
|
2464
|
-
const pa = parse(a);
|
|
2465
|
-
const pb = parse(b);
|
|
2466
|
-
const len = Math.max(pa.length, pb.length);
|
|
2467
|
-
for (let i = 0; i < len; i++) {
|
|
2468
|
-
const da = pa[i] ?? 0;
|
|
2469
|
-
const db = pb[i] ?? 0;
|
|
2470
|
-
if (da !== db) return da > db;
|
|
2471
|
-
}
|
|
2472
|
-
return false;
|
|
2473
|
-
}
|
|
2474
2426
|
var USER_ID_STORAGE_KEY = "mcp_use_user_id";
|
|
2475
2427
|
var PROJECT_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI";
|
|
2476
2428
|
var HOST = "https://eu.i.posthog.com";
|
|
@@ -2499,10 +2451,7 @@ function createLocalStorageBackend() {
|
|
|
2499
2451
|
localStorage.setItem(USER_ID_STORAGE_KEY, id);
|
|
2500
2452
|
} catch {
|
|
2501
2453
|
}
|
|
2502
|
-
}
|
|
2503
|
-
// Package-download dedup is node/Scarf-oriented; localStorage unused.
|
|
2504
|
-
getDownloadedVersion: () => null,
|
|
2505
|
-
setDownloadedVersion: () => void 0
|
|
2454
|
+
}
|
|
2506
2455
|
};
|
|
2507
2456
|
}
|
|
2508
2457
|
function detectRuntimeEnvironment() {
|
|
@@ -2570,17 +2519,13 @@ var Telemetry = class _Telemetry {
|
|
|
2570
2519
|
_currUserId = null;
|
|
2571
2520
|
_telemetryEnabled = false;
|
|
2572
2521
|
_pending = /* @__PURE__ */ new Set();
|
|
2573
|
-
_scarfEnabled = false;
|
|
2574
2522
|
_runtimeEnvironment;
|
|
2575
2523
|
_storageCapability;
|
|
2576
2524
|
_storage;
|
|
2577
|
-
/** True when node entry installed fs storage (package-download dedup). */
|
|
2578
|
-
_fsBacked;
|
|
2579
2525
|
_source;
|
|
2580
2526
|
_productVersion;
|
|
2581
2527
|
constructor() {
|
|
2582
2528
|
this._runtimeEnvironment = detectRuntimeEnvironment();
|
|
2583
|
-
this._fsBacked = configuredStorage !== null;
|
|
2584
2529
|
this._storage = configuredStorage ?? createLocalStorageBackend() ?? null;
|
|
2585
2530
|
this._storageCapability = this._storage ? "persistent" : "session-only";
|
|
2586
2531
|
this._source = readSourceHint() || this._runtimeEnvironment;
|
|
@@ -2599,14 +2544,6 @@ var Telemetry = class _Telemetry {
|
|
|
2599
2544
|
"Anonymized telemetry enabled. Set MCP_USE_ANONYMIZED_TELEMETRY=false to disable."
|
|
2600
2545
|
);
|
|
2601
2546
|
this._telemetryEnabled = true;
|
|
2602
|
-
this._scarfEnabled = true;
|
|
2603
|
-
if (this._fsBacked) {
|
|
2604
|
-
setTimeout(() => {
|
|
2605
|
-
this.trackPackageDownload({ triggered_by: "initialization" }).catch(
|
|
2606
|
-
(e) => logger.debug(`Failed to track package download: ${e}`)
|
|
2607
|
-
);
|
|
2608
|
-
}, 0);
|
|
2609
|
-
}
|
|
2610
2547
|
}
|
|
2611
2548
|
}
|
|
2612
2549
|
get runtimeEnvironment() {
|
|
@@ -2638,7 +2575,7 @@ var Telemetry = class _Telemetry {
|
|
|
2638
2575
|
this._productVersion = version;
|
|
2639
2576
|
}
|
|
2640
2577
|
get isEnabled() {
|
|
2641
|
-
return this._telemetryEnabled
|
|
2578
|
+
return this._telemetryEnabled;
|
|
2642
2579
|
}
|
|
2643
2580
|
get userId() {
|
|
2644
2581
|
if (this._currUserId) return this._currUserId;
|
|
@@ -2661,7 +2598,7 @@ var Telemetry = class _Telemetry {
|
|
|
2661
2598
|
return this._currUserId;
|
|
2662
2599
|
}
|
|
2663
2600
|
async capture(event) {
|
|
2664
|
-
if (!this._telemetryEnabled
|
|
2601
|
+
if (!this._telemetryEnabled) return;
|
|
2665
2602
|
const currentUserId = this.userId;
|
|
2666
2603
|
const properties = {
|
|
2667
2604
|
...event.properties,
|
|
@@ -2670,52 +2607,15 @@ var Telemetry = class _Telemetry {
|
|
|
2670
2607
|
source: this._source,
|
|
2671
2608
|
runtime: this._runtimeEnvironment
|
|
2672
2609
|
};
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
properties
|
|
2680
|
-
});
|
|
2681
|
-
this._pending.add(p);
|
|
2682
|
-
void p.finally(() => this._pending.delete(p));
|
|
2683
|
-
}
|
|
2684
|
-
if (this._scarfEnabled) {
|
|
2685
|
-
const p = captureScarf({
|
|
2686
|
-
...properties,
|
|
2687
|
-
user_id: currentUserId,
|
|
2688
|
-
event: event.name
|
|
2689
|
-
});
|
|
2690
|
-
this._pending.add(p);
|
|
2691
|
-
void p.finally(() => this._pending.delete(p));
|
|
2692
|
-
}
|
|
2693
|
-
}
|
|
2694
|
-
async trackPackageDownload(properties) {
|
|
2695
|
-
if (!this._scarfEnabled || !this._fsBacked || !this._storage) return;
|
|
2696
|
-
const currentVersion = getPackageVersion();
|
|
2697
|
-
const saved = this._storage.getDownloadedVersion();
|
|
2698
|
-
let firstDownload = false;
|
|
2699
|
-
let shouldTrack = false;
|
|
2700
|
-
if (!saved) {
|
|
2701
|
-
shouldTrack = true;
|
|
2702
|
-
firstDownload = true;
|
|
2703
|
-
this._storage.setDownloadedVersion(currentVersion);
|
|
2704
|
-
} else if (isVersionGreater(currentVersion, saved)) {
|
|
2705
|
-
shouldTrack = true;
|
|
2706
|
-
this._storage.setDownloadedVersion(currentVersion);
|
|
2707
|
-
}
|
|
2708
|
-
if (!shouldTrack) return;
|
|
2709
|
-
await captureScarf({
|
|
2710
|
-
...properties || {},
|
|
2711
|
-
mcp_use_version: currentVersion,
|
|
2712
|
-
user_id: this.userId,
|
|
2713
|
-
event: "package_download",
|
|
2714
|
-
first_download: firstDownload,
|
|
2715
|
-
language: "typescript",
|
|
2716
|
-
source: this._source,
|
|
2717
|
-
runtime: this._runtimeEnvironment
|
|
2610
|
+
const p = capturePostHog({
|
|
2611
|
+
host: HOST,
|
|
2612
|
+
apiKey: PROJECT_API_KEY,
|
|
2613
|
+
event: event.name,
|
|
2614
|
+
distinctId: currentUserId,
|
|
2615
|
+
properties
|
|
2718
2616
|
});
|
|
2617
|
+
this._pending.add(p);
|
|
2618
|
+
void p.finally(() => this._pending.delete(p));
|
|
2719
2619
|
}
|
|
2720
2620
|
async trackAgentExecution(data) {
|
|
2721
2621
|
if (!this.isEnabled) return;
|
|
@@ -4142,9 +4042,13 @@ function createBrowserOAuthProvider(params) {
|
|
|
4142
4042
|
function startConnectionHealthMonitoring(params) {
|
|
4143
4043
|
let healthCheckInterval = null;
|
|
4144
4044
|
let lastSuccessfulCheck = Date.now();
|
|
4045
|
+
let headProbeUnsupported = false;
|
|
4145
4046
|
const healthCheckIntervalMs = params.healthCheckIntervalMs ?? 1e4;
|
|
4146
4047
|
const healthCheckTimeoutMs = params.healthCheckTimeoutMs ?? 3e4;
|
|
4147
4048
|
const checkConnectionHealth = async () => {
|
|
4049
|
+
if (headProbeUnsupported) {
|
|
4050
|
+
return;
|
|
4051
|
+
}
|
|
4148
4052
|
if (!params.isMountedRef.current || params.stateRef.current !== "ready") {
|
|
4149
4053
|
if (healthCheckInterval) {
|
|
4150
4054
|
clearInterval(healthCheckInterval);
|
|
@@ -4163,6 +4067,15 @@ function startConnectionHealthMonitoring(params) {
|
|
|
4163
4067
|
headers: { ...params.allHeaders, ...authHeaders },
|
|
4164
4068
|
signal: AbortSignal.timeout(5e3)
|
|
4165
4069
|
});
|
|
4070
|
+
if (response.status === 405 || response.status === 404) {
|
|
4071
|
+
headProbeUnsupported = true;
|
|
4072
|
+
lastSuccessfulCheck = Date.now();
|
|
4073
|
+
if (healthCheckInterval) {
|
|
4074
|
+
clearInterval(healthCheckInterval);
|
|
4075
|
+
healthCheckInterval = null;
|
|
4076
|
+
}
|
|
4077
|
+
return;
|
|
4078
|
+
}
|
|
4166
4079
|
if (response.ok || response.status < 500) {
|
|
4167
4080
|
lastSuccessfulCheck = Date.now();
|
|
4168
4081
|
} else {
|
|
@@ -4371,6 +4284,7 @@ function useMcp(options) {
|
|
|
4371
4284
|
headers: headersOption,
|
|
4372
4285
|
proxyConfig,
|
|
4373
4286
|
oauthProxyUrl: oauthProxyUrlOption,
|
|
4287
|
+
connectionMode,
|
|
4374
4288
|
autoProxyFallback = false,
|
|
4375
4289
|
logLevel: logLevelOption = "silent",
|
|
4376
4290
|
autoRetry = false,
|
|
@@ -4394,6 +4308,7 @@ function useMcp(options) {
|
|
|
4394
4308
|
oauth: oauthOptions
|
|
4395
4309
|
} = options;
|
|
4396
4310
|
const transportType = "http";
|
|
4311
|
+
const requestedProxyAddress = proxyConfig?.proxyAddress;
|
|
4397
4312
|
const oauthClientId = oauthOptions?.clientId?.trim() || void 0;
|
|
4398
4313
|
const oauthClientMetadataUrl = oauthOptions?.clientMetadataUrl?.trim() || void 0;
|
|
4399
4314
|
const oauthScope = oauthOptions?.scope?.trim() || void 0;
|
|
@@ -4441,6 +4356,9 @@ function useMcp(options) {
|
|
|
4441
4356
|
);
|
|
4442
4357
|
const oauthClientConfig = derivedOAuthClientConfig;
|
|
4443
4358
|
const autoProxyFallbackConfig = useMemo(() => {
|
|
4359
|
+
if (connectionMode === "direct" || connectionMode === "proxy") {
|
|
4360
|
+
return { enabled: false, proxyAddress: void 0 };
|
|
4361
|
+
}
|
|
4444
4362
|
if (!autoProxyFallback) {
|
|
4445
4363
|
return { enabled: false, proxyAddress: void 0 };
|
|
4446
4364
|
}
|
|
@@ -4456,7 +4374,7 @@ function useMcp(options) {
|
|
|
4456
4374
|
enabled: autoProxyFallback.enabled !== false && Boolean(proxyAddress),
|
|
4457
4375
|
proxyAddress
|
|
4458
4376
|
};
|
|
4459
|
-
}, [autoProxyFallback, proxyConfig]);
|
|
4377
|
+
}, [autoProxyFallback, connectionMode, proxyConfig]);
|
|
4460
4378
|
const autoReconnectConfig = useMemo(() => {
|
|
4461
4379
|
if (autoReconnect === false) {
|
|
4462
4380
|
return {
|
|
@@ -4492,20 +4410,33 @@ function useMcp(options) {
|
|
|
4492
4410
|
const [effectiveProxyConfig, setEffectiveProxyConfig] = useState(void 0);
|
|
4493
4411
|
useEffect(() => {
|
|
4494
4412
|
setEffectiveProxyConfig(void 0);
|
|
4495
|
-
}, [
|
|
4413
|
+
}, [
|
|
4414
|
+
url,
|
|
4415
|
+
requestedProxyAddress,
|
|
4416
|
+
connectionMode,
|
|
4417
|
+
autoProxyFallbackConfig.proxyAddress
|
|
4418
|
+
]);
|
|
4496
4419
|
const activeProxyConfig = useMemo(() => {
|
|
4497
|
-
|
|
4498
|
-
|
|
4420
|
+
const hasCurrentAutoFallback = autoProxyFallbackConfig.enabled && effectiveProxyConfig?.proxyAddress === autoProxyFallbackConfig.proxyAddress;
|
|
4421
|
+
if (hasCurrentAutoFallback && effectiveProxyConfig) {
|
|
4422
|
+
const latestHeaders = proxyConfig?.headers ?? {};
|
|
4423
|
+
return {
|
|
4424
|
+
...effectiveProxyConfig,
|
|
4425
|
+
headers: {
|
|
4426
|
+
...latestHeaders,
|
|
4427
|
+
...effectiveProxyConfig.headers ?? {}
|
|
4428
|
+
}
|
|
4429
|
+
};
|
|
4499
4430
|
}
|
|
4500
|
-
const
|
|
4501
|
-
return
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4431
|
+
const startsDirect = connectionMode === "auto" || connectionMode === "direct" || connectionMode === void 0 && autoProxyFallbackConfig.enabled;
|
|
4432
|
+
return startsDirect ? void 0 : proxyConfig;
|
|
4433
|
+
}, [
|
|
4434
|
+
effectiveProxyConfig,
|
|
4435
|
+
proxyConfig,
|
|
4436
|
+
connectionMode,
|
|
4437
|
+
autoProxyFallbackConfig.enabled,
|
|
4438
|
+
autoProxyFallbackConfig.proxyAddress
|
|
4439
|
+
]);
|
|
4509
4440
|
const gatewayUrl = activeProxyConfig?.proxyAddress;
|
|
4510
4441
|
const proxyHeaders = activeProxyConfig?.headers ?? {};
|
|
4511
4442
|
const effectiveOAuthUrl = useMemo(() => {
|
|
@@ -4837,8 +4768,9 @@ function useMcp(options) {
|
|
|
4837
4768
|
clientInfo: mergedClientInfo,
|
|
4838
4769
|
// Pass a fetch that scopes OAuth-proxy routing to this server's
|
|
4839
4770
|
// transport/auth calls. getProxyFetch wraps `customFetch` (e.g. the
|
|
4840
|
-
// OAuth retry fetch for scope step-up)
|
|
4841
|
-
//
|
|
4771
|
+
// OAuth retry fetch for scope step-up), bypasses the browser cache
|
|
4772
|
+
// for OAuth metadata, and optionally routes OAuth through the BFF.
|
|
4773
|
+
// It never mutates the global fetch.
|
|
4842
4774
|
...(() => {
|
|
4843
4775
|
const scopedFetch = authProviderRef.current?.getProxyFetch?.(customFetch) ?? customFetch;
|
|
4844
4776
|
return scopedFetch ? { fetch: scopedFetch } : {};
|
|
@@ -5039,12 +4971,18 @@ function useMcp(options) {
|
|
|
5039
4971
|
if (tokens?.access_token) {
|
|
5040
4972
|
const expiresAt = tokens.expires_in ? Date.now() + tokens.expires_in * 1e3 : void 0;
|
|
5041
4973
|
let tokenEndpoint = null;
|
|
4974
|
+
let resource = null;
|
|
5042
4975
|
let clientCreds = null;
|
|
5043
4976
|
try {
|
|
5044
4977
|
tokenEndpoint = await authProviderRef.current.getTokenEndpoint?.() ?? null;
|
|
5045
4978
|
} catch {
|
|
5046
4979
|
tokenEndpoint = null;
|
|
5047
4980
|
}
|
|
4981
|
+
try {
|
|
4982
|
+
resource = await authProviderRef.current.getResource?.() ?? null;
|
|
4983
|
+
} catch {
|
|
4984
|
+
resource = null;
|
|
4985
|
+
}
|
|
5048
4986
|
try {
|
|
5049
4987
|
clientCreds = await authProviderRef.current.getClientCredentials?.() ?? null;
|
|
5050
4988
|
} catch {
|
|
@@ -5061,6 +4999,7 @@ function useMcp(options) {
|
|
|
5061
4999
|
refresh_token: tokens.refresh_token,
|
|
5062
5000
|
scope: tokens.scope,
|
|
5063
5001
|
...tokenEndpoint ? { token_endpoint: tokenEndpoint } : {},
|
|
5002
|
+
...resource ? { resource } : {},
|
|
5064
5003
|
...clientCreds?.client_id ? { client_id: clientCreds.client_id } : {},
|
|
5065
5004
|
...clientCreds?.client_secret ? { client_secret: clientCreds.client_secret } : {}
|
|
5066
5005
|
});
|
|
@@ -5305,19 +5244,20 @@ function useMcp(options) {
|
|
|
5305
5244
|
addLog("info", "Triggering fresh OAuth authorization...");
|
|
5306
5245
|
const parsedUrl = new URL(url);
|
|
5307
5246
|
const baseUrl = parsedUrl.origin + parsedUrl.pathname.replace(/\/+$/, "");
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5247
|
+
const authResult = await auth2(freshAuthProvider, {
|
|
5248
|
+
serverUrl: baseUrl,
|
|
5249
|
+
fetchFn: freshAuthProvider.getProxyFetch?.()
|
|
5250
|
+
});
|
|
5251
|
+
if (authResult === "AUTHORIZED") {
|
|
5313
5252
|
addLog("info", "OAuth flow completed (tokens obtained)");
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
"OAuth flow initiated (popup/redirect):",
|
|
5318
|
-
err instanceof Error ? err.message : "Redirecting..."
|
|
5319
|
-
);
|
|
5253
|
+
connectingRef.current = false;
|
|
5254
|
+
connectRef.current?.();
|
|
5255
|
+
return;
|
|
5320
5256
|
}
|
|
5257
|
+
if (authResult !== "REDIRECT") {
|
|
5258
|
+
throw new Error(`Unexpected OAuth auth() result: ${authResult}`);
|
|
5259
|
+
}
|
|
5260
|
+
addLog("info", "OAuth authorization redirect initiated");
|
|
5321
5261
|
const newAuthUrl = freshAuthProvider.getLastAttemptedAuthUrl?.();
|
|
5322
5262
|
if (newAuthUrl) {
|
|
5323
5263
|
setAuthUrl(newAuthUrl);
|
|
@@ -5383,11 +5323,8 @@ function useMcp(options) {
|
|
|
5383
5323
|
}
|
|
5384
5324
|
} catch (authError) {
|
|
5385
5325
|
if (!isMountedRef.current) return;
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
"error",
|
|
5389
|
-
`Manual authentication failed: ${authError instanceof Error ? authError.message : String(authError)}`
|
|
5390
|
-
);
|
|
5326
|
+
const error2 = authError instanceof Error ? authError : new Error(String(authError));
|
|
5327
|
+
failConnection(`Manual authentication failed: ${error2.message}`, error2);
|
|
5391
5328
|
}
|
|
5392
5329
|
} else if (currentState === "authenticating") {
|
|
5393
5330
|
addLog(
|
|
@@ -5595,6 +5532,7 @@ function useMcp(options) {
|
|
|
5595
5532
|
// Triggers reconnection when proxy fallback changes OAuth URL
|
|
5596
5533
|
proxyConfig,
|
|
5597
5534
|
// Triggers reconnection when proxy config (including headers) changes
|
|
5535
|
+
autoProxyFallbackConfig.proxyAddress,
|
|
5598
5536
|
providedAuthProvider
|
|
5599
5537
|
]);
|
|
5600
5538
|
const retryRef = useRef(retry);
|
|
@@ -6711,7 +6649,8 @@ function McpClientProvider({
|
|
|
6711
6649
|
}),
|
|
6712
6650
|
[serverConfigs, defaultCapabilities, defaultServerConfig]
|
|
6713
6651
|
);
|
|
6714
|
-
|
|
6652
|
+
const skipServerConnections = typeof window !== "undefined" && /\/oauth\/callback\/?$/.test(window.location.pathname);
|
|
6653
|
+
return /* @__PURE__ */ React.createElement(McpClientContext.Provider, { value: contextValue }, children, !skipServerConnections && mergedServerConfigs.map((config) => /* @__PURE__ */ React.createElement(
|
|
6715
6654
|
McpServerWrapper,
|
|
6716
6655
|
{
|
|
6717
6656
|
key: `${config.id}-v${serverRevisions[config.id] ?? 0}`,
|
|
@@ -6867,6 +6806,7 @@ import React2, {
|
|
|
6867
6806
|
memo,
|
|
6868
6807
|
useCallback as useCallback6,
|
|
6869
6808
|
useEffect as useEffect5,
|
|
6809
|
+
useMemo as useMemo3,
|
|
6870
6810
|
useRef as useRef4,
|
|
6871
6811
|
useState as useState4
|
|
6872
6812
|
} from "react";
|
|
@@ -6889,6 +6829,53 @@ function parseCustomProps(customProps) {
|
|
|
6889
6829
|
return parsed;
|
|
6890
6830
|
}
|
|
6891
6831
|
|
|
6832
|
+
// src/react/view/inject-openai-file-apis.ts
|
|
6833
|
+
var OPENAI_FILE_APIS_SCRIPT = `<script>
|
|
6834
|
+
(function () {
|
|
6835
|
+
var files = new Map();
|
|
6836
|
+
window.openai = window.openai || {};
|
|
6837
|
+
window.openai.uploadFile = async function (file) {
|
|
6838
|
+
var fileId = crypto.randomUUID();
|
|
6839
|
+
files.set(fileId, file);
|
|
6840
|
+
return { fileId: fileId };
|
|
6841
|
+
};
|
|
6842
|
+
window.openai.getFileDownloadUrl = async function (ref) {
|
|
6843
|
+
var file = files.get(ref.fileId);
|
|
6844
|
+
if (!file) {
|
|
6845
|
+
throw new Error("File not found: " + ref.fileId);
|
|
6846
|
+
}
|
|
6847
|
+
return { downloadUrl: URL.createObjectURL(file) };
|
|
6848
|
+
};
|
|
6849
|
+
})();
|
|
6850
|
+
</script>`;
|
|
6851
|
+
function injectOpenAiFileApis(html) {
|
|
6852
|
+
if (html.includes("<head>")) {
|
|
6853
|
+
return html.replace("<head>", "<head>" + OPENAI_FILE_APIS_SCRIPT);
|
|
6854
|
+
}
|
|
6855
|
+
if (html.includes("<HEAD>")) {
|
|
6856
|
+
return html.replace("<HEAD>", "<HEAD>" + OPENAI_FILE_APIS_SCRIPT);
|
|
6857
|
+
}
|
|
6858
|
+
if (html.includes("<html>")) {
|
|
6859
|
+
return html.replace(
|
|
6860
|
+
"<html>",
|
|
6861
|
+
"<html><head>" + OPENAI_FILE_APIS_SCRIPT + "</head>"
|
|
6862
|
+
);
|
|
6863
|
+
}
|
|
6864
|
+
if (html.includes("<HTML>")) {
|
|
6865
|
+
return html.replace(
|
|
6866
|
+
"<HTML>",
|
|
6867
|
+
"<HTML><head>" + OPENAI_FILE_APIS_SCRIPT + "</head>"
|
|
6868
|
+
);
|
|
6869
|
+
}
|
|
6870
|
+
if (html.includes("<!DOCTYPE") || html.includes("<!doctype")) {
|
|
6871
|
+
return html.replace(
|
|
6872
|
+
/(<!DOCTYPE[^>]*>|<!doctype[^>]*>)/i,
|
|
6873
|
+
"$1<head>" + OPENAI_FILE_APIS_SCRIPT + "</head>"
|
|
6874
|
+
);
|
|
6875
|
+
}
|
|
6876
|
+
return OPENAI_FILE_APIS_SCRIPT + html;
|
|
6877
|
+
}
|
|
6878
|
+
|
|
6892
6879
|
// src/react/view/resolve-view-resource.ts
|
|
6893
6880
|
function resolveViewResource(options) {
|
|
6894
6881
|
const { resourceResult, listingResource, cspMode, resourceUri } = options;
|
|
@@ -7238,9 +7225,9 @@ function buildSandboxProxyBlobHtml(search) {
|
|
|
7238
7225
|
// src/react/view/use-display-mode.ts
|
|
7239
7226
|
import { useCallback as useCallback5, useEffect as useEffect4 } from "react";
|
|
7240
7227
|
var SHELL_BASE = "w-full h-full min-h-0 bg-background flex flex-col [&:fullscreen]:h-full [&:fullscreen]:w-full [&:fullscreen]:bg-background";
|
|
7241
|
-
var WIDGET_FULLSCREEN_OVERLAY_CLASSES = `fixed inset-0 z-[
|
|
7228
|
+
var WIDGET_FULLSCREEN_OVERLAY_CLASSES = `fixed inset-0 z-[200] ${SHELL_BASE}`;
|
|
7242
7229
|
var WIDGET_PIP_SHELL_CLASSES = [
|
|
7243
|
-
"fixed top-4 left-1/2 -translate-x-1/2 z-[
|
|
7230
|
+
"fixed top-4 left-1/2 -translate-x-1/2 z-[200]",
|
|
7244
7231
|
"rounded-3xl w-full min-w-[300px] h-[400px]",
|
|
7245
7232
|
"shadow-2xl border overflow-hidden",
|
|
7246
7233
|
"bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80",
|
|
@@ -7298,7 +7285,8 @@ function useViewDisplayModeControls({
|
|
|
7298
7285
|
}
|
|
7299
7286
|
var VIEW_DIMENSIONS = {
|
|
7300
7287
|
PIP_MAX_WIDTH: 700,
|
|
7301
|
-
DEFAULT_HEIGHT: 400
|
|
7288
|
+
DEFAULT_HEIGHT: 400,
|
|
7289
|
+
FULLSCREEN_HEADER_HEIGHT: 50
|
|
7302
7290
|
};
|
|
7303
7291
|
|
|
7304
7292
|
// src/react/view/view-detection.ts
|
|
@@ -7325,8 +7313,28 @@ var DEFAULT_HOST_CAPABILITIES = {
|
|
|
7325
7313
|
serverTools: {},
|
|
7326
7314
|
serverResources: {},
|
|
7327
7315
|
logging: {},
|
|
7328
|
-
updateModelContext: { text: {} }
|
|
7316
|
+
updateModelContext: { text: {} },
|
|
7317
|
+
// ponytail: always advertised; bridge.onmessage no-ops when onMessage unset
|
|
7318
|
+
message: { text: {} }
|
|
7329
7319
|
};
|
|
7320
|
+
function CloseIcon() {
|
|
7321
|
+
return /* @__PURE__ */ React2.createElement(
|
|
7322
|
+
"svg",
|
|
7323
|
+
{
|
|
7324
|
+
width: "14",
|
|
7325
|
+
height: "14",
|
|
7326
|
+
viewBox: "0 0 24 24",
|
|
7327
|
+
fill: "none",
|
|
7328
|
+
stroke: "currentColor",
|
|
7329
|
+
strokeWidth: "2",
|
|
7330
|
+
strokeLinecap: "round",
|
|
7331
|
+
strokeLinejoin: "round",
|
|
7332
|
+
"aria-hidden": true
|
|
7333
|
+
},
|
|
7334
|
+
/* @__PURE__ */ React2.createElement("path", { d: "M18 6 6 18" }),
|
|
7335
|
+
/* @__PURE__ */ React2.createElement("path", { d: "m6 6 12 12" })
|
|
7336
|
+
);
|
|
7337
|
+
}
|
|
7330
7338
|
function waitForSandboxProxyReady(iframe) {
|
|
7331
7339
|
return new Promise((resolve) => {
|
|
7332
7340
|
const listener = (event) => {
|
|
@@ -7387,6 +7395,10 @@ function ViewRendererBase({
|
|
|
7387
7395
|
onResourceResolved,
|
|
7388
7396
|
wrapTransport,
|
|
7389
7397
|
toolCallTimeout = DEFAULT_TOOL_CALL_TIMEOUT,
|
|
7398
|
+
mockOpenAiFileApis = false,
|
|
7399
|
+
onInlineHeightChange,
|
|
7400
|
+
fullscreenHeader,
|
|
7401
|
+
renderFullscreenClose,
|
|
7390
7402
|
className,
|
|
7391
7403
|
testId = "mcp-app-frame",
|
|
7392
7404
|
invoking,
|
|
@@ -7395,6 +7407,9 @@ function ViewRendererBase({
|
|
|
7395
7407
|
const iframeRef = useRef4(null);
|
|
7396
7408
|
const bridgeRef = useRef4(null);
|
|
7397
7409
|
const containerRef = useRef4(null);
|
|
7410
|
+
const pendingBlobRevocationsRef = useRef4(
|
|
7411
|
+
/* @__PURE__ */ new Map()
|
|
7412
|
+
);
|
|
7398
7413
|
const connectionRef = useRef4(
|
|
7399
7414
|
source.kind === "live" ? source.connection : null
|
|
7400
7415
|
);
|
|
@@ -7408,12 +7423,19 @@ function ViewRendererBase({
|
|
|
7408
7423
|
);
|
|
7409
7424
|
const [internalDisplayMode, setInternalDisplayMode] = useState4("inline");
|
|
7410
7425
|
const displayMode = displayModeProp ?? internalDisplayMode;
|
|
7411
|
-
const
|
|
7412
|
-
|
|
7426
|
+
const effectiveHostContext = useMemo3(() => {
|
|
7427
|
+
if (!hostContext) return hostContext;
|
|
7428
|
+
if (hostContext.displayMode === displayMode) return hostContext;
|
|
7429
|
+
return { ...hostContext, displayMode };
|
|
7430
|
+
}, [hostContext, displayMode]);
|
|
7431
|
+
const hostContextRef = useRef4(effectiveHostContext);
|
|
7432
|
+
hostContextRef.current = effectiveHostContext;
|
|
7413
7433
|
const onMessageRef = useRef4(onMessage);
|
|
7414
7434
|
onMessageRef.current = onMessage;
|
|
7415
7435
|
const toolInputRef = useRef4(toolInput);
|
|
7416
7436
|
toolInputRef.current = toolInput;
|
|
7437
|
+
const partialToolInputRef = useRef4(partialToolInput);
|
|
7438
|
+
partialToolInputRef.current = partialToolInput;
|
|
7417
7439
|
const toolOutputRef = useRef4(toolOutput);
|
|
7418
7440
|
toolOutputRef.current = toolOutput;
|
|
7419
7441
|
const customPropsRef = useRef4(customProps);
|
|
@@ -7432,10 +7454,14 @@ function ViewRendererBase({
|
|
|
7432
7454
|
onReadyRef.current = onReady;
|
|
7433
7455
|
const onLifecycleChangeRef = useRef4(onLifecycleChange);
|
|
7434
7456
|
onLifecycleChangeRef.current = onLifecycleChange;
|
|
7457
|
+
const onInlineHeightChangeRef = useRef4(onInlineHeightChange);
|
|
7458
|
+
onInlineHeightChangeRef.current = onInlineHeightChange;
|
|
7435
7459
|
const sandboxUrlRef = useRef4(sandboxUrl);
|
|
7436
7460
|
sandboxUrlRef.current = sandboxUrl;
|
|
7437
7461
|
const cspModeRef = useRef4(cspMode);
|
|
7438
7462
|
cspModeRef.current = cspMode;
|
|
7463
|
+
const mockOpenAiFileApisRef = useRef4(mockOpenAiFileApis);
|
|
7464
|
+
mockOpenAiFileApisRef.current = mockOpenAiFileApis;
|
|
7439
7465
|
const resolveSandboxUrl = useCallback6((next) => {
|
|
7440
7466
|
const custom = sandboxUrlRef.current;
|
|
7441
7467
|
if (custom) {
|
|
@@ -7539,10 +7565,18 @@ function ViewRendererBase({
|
|
|
7539
7565
|
}, [source.kind, liveResourceUri, preloadedHtml, cspMode, resolveSandboxUrl]);
|
|
7540
7566
|
useEffect5(() => {
|
|
7541
7567
|
const url = activeSandboxUrl;
|
|
7568
|
+
if (!url || url.protocol !== "blob:") return;
|
|
7569
|
+
const pending = pendingBlobRevocationsRef.current.get(url.href);
|
|
7570
|
+
if (pending) {
|
|
7571
|
+
clearTimeout(pending);
|
|
7572
|
+
pendingBlobRevocationsRef.current.delete(url.href);
|
|
7573
|
+
}
|
|
7542
7574
|
return () => {
|
|
7543
|
-
|
|
7575
|
+
const timer = setTimeout(() => {
|
|
7544
7576
|
URL.revokeObjectURL(url.href);
|
|
7545
|
-
|
|
7577
|
+
pendingBlobRevocationsRef.current.delete(url.href);
|
|
7578
|
+
}, 1e3);
|
|
7579
|
+
pendingBlobRevocationsRef.current.set(url.href, timer);
|
|
7546
7580
|
};
|
|
7547
7581
|
}, [activeSandboxUrl]);
|
|
7548
7582
|
const isBlobSandbox = activeSandboxUrl?.protocol === "blob:";
|
|
@@ -7603,7 +7637,14 @@ function ViewRendererBase({
|
|
|
7603
7637
|
iframe.setAttribute("allow", allowAttribute);
|
|
7604
7638
|
}
|
|
7605
7639
|
const readyPromise = waitForSandboxProxyReady(iframe);
|
|
7606
|
-
|
|
7640
|
+
if (activeSandboxUrl.protocol === "blob:") {
|
|
7641
|
+
const response = await fetch(activeSandboxUrl.href);
|
|
7642
|
+
const sandboxHtml = await response.text();
|
|
7643
|
+
if (disposed) return;
|
|
7644
|
+
iframe.srcdoc = sandboxHtml;
|
|
7645
|
+
} else {
|
|
7646
|
+
iframe.src = activeSandboxUrl.href;
|
|
7647
|
+
}
|
|
7607
7648
|
await readyPromise;
|
|
7608
7649
|
if (disposed) return;
|
|
7609
7650
|
const capabilities = {
|
|
@@ -7689,7 +7730,10 @@ function ViewRendererBase({
|
|
|
7689
7730
|
height
|
|
7690
7731
|
}) => {
|
|
7691
7732
|
if (displayModeRef.current !== "inline") return;
|
|
7692
|
-
if (height !== void 0)
|
|
7733
|
+
if (height !== void 0) {
|
|
7734
|
+
setInlineHeight(height);
|
|
7735
|
+
onInlineHeightChangeRef.current?.(height);
|
|
7736
|
+
}
|
|
7693
7737
|
};
|
|
7694
7738
|
const initPromise = hookInitialized(bridge);
|
|
7695
7739
|
let transport = new PostMessageTransport(
|
|
@@ -7702,7 +7746,7 @@ function ViewRendererBase({
|
|
|
7702
7746
|
await bridge.connect(transport);
|
|
7703
7747
|
if (disposed) return;
|
|
7704
7748
|
await bridge.sendSandboxResourceReady({
|
|
7705
|
-
html: resolved.html,
|
|
7749
|
+
html: mockOpenAiFileApisRef.current ? injectOpenAiFileApis(resolved.html) : resolved.html,
|
|
7706
7750
|
csp: resolved.csp,
|
|
7707
7751
|
permissions: resolved.permissions
|
|
7708
7752
|
});
|
|
@@ -7711,11 +7755,18 @@ function ViewRendererBase({
|
|
|
7711
7755
|
bridgeRef.current = bridge;
|
|
7712
7756
|
setInitCount((c) => c + 1);
|
|
7713
7757
|
onLifecycleChangeRef.current?.({ status: "initialized" });
|
|
7714
|
-
const
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7758
|
+
const currentPartialToolInput = partialToolInputRef.current;
|
|
7759
|
+
if (currentPartialToolInput) {
|
|
7760
|
+
bridge.sendToolInputPartial({
|
|
7761
|
+
arguments: currentPartialToolInput
|
|
7762
|
+
});
|
|
7763
|
+
} else {
|
|
7764
|
+
const mergedArgs = {
|
|
7765
|
+
...toolInputRef.current,
|
|
7766
|
+
...parseCustomProps(customPropsRef.current)
|
|
7767
|
+
};
|
|
7768
|
+
bridge.sendToolInput({ arguments: mergedArgs });
|
|
7769
|
+
}
|
|
7719
7770
|
const toolResultPayload = buildToolResultPayload(
|
|
7720
7771
|
toolOutputRef.current,
|
|
7721
7772
|
customPropsRef.current
|
|
@@ -7764,13 +7815,14 @@ function ViewRendererBase({
|
|
|
7764
7815
|
cspMode,
|
|
7765
7816
|
viewId,
|
|
7766
7817
|
wrapTransport,
|
|
7767
|
-
toolCallTimeout
|
|
7818
|
+
toolCallTimeout,
|
|
7819
|
+
mockOpenAiFileApis
|
|
7768
7820
|
]);
|
|
7769
7821
|
useEffect5(() => {
|
|
7770
7822
|
const bridge = bridgeRef.current;
|
|
7771
|
-
if (!bridge || initCount === 0 || !
|
|
7772
|
-
bridge.setHostContext(
|
|
7773
|
-
}, [
|
|
7823
|
+
if (!bridge || initCount === 0 || !effectiveHostContext) return;
|
|
7824
|
+
bridge.setHostContext(effectiveHostContext);
|
|
7825
|
+
}, [effectiveHostContext, initCount]);
|
|
7774
7826
|
useEffect5(() => {
|
|
7775
7827
|
const bridge = bridgeRef.current;
|
|
7776
7828
|
if (!bridge || initCount === 0 || !partialToolInput) return;
|
|
@@ -7778,13 +7830,13 @@ function ViewRendererBase({
|
|
|
7778
7830
|
}, [initCount, partialToolInput]);
|
|
7779
7831
|
useEffect5(() => {
|
|
7780
7832
|
const bridge = bridgeRef.current;
|
|
7781
|
-
if (!bridge || initCount === 0) return;
|
|
7833
|
+
if (!bridge || initCount === 0 || partialToolInput) return;
|
|
7782
7834
|
const mergedArgs = {
|
|
7783
7835
|
...toolInput,
|
|
7784
7836
|
...parseCustomProps(customProps)
|
|
7785
7837
|
};
|
|
7786
7838
|
bridge.sendToolInput({ arguments: mergedArgs });
|
|
7787
|
-
}, [initCount, toolInput, customProps]);
|
|
7839
|
+
}, [initCount, toolInput, partialToolInput, customProps]);
|
|
7788
7840
|
useEffect5(() => {
|
|
7789
7841
|
const bridge = bridgeRef.current;
|
|
7790
7842
|
if (!bridge || initCount === 0) return;
|
|
@@ -7808,6 +7860,7 @@ function ViewRendererBase({
|
|
|
7808
7860
|
const timer = setTimeout(() => setShowSpinner(false), 300);
|
|
7809
7861
|
return () => clearTimeout(timer);
|
|
7810
7862
|
}, [initCount, showSpinner]);
|
|
7863
|
+
const showHostBorder = resolved !== null && resolved.prefersBorder && displayMode !== "fullscreen";
|
|
7811
7864
|
if (loadError) {
|
|
7812
7865
|
return /* @__PURE__ */ React2.createElement("div", { className }, /* @__PURE__ */ React2.createElement("div", { className: "border border-red-200/50 dark:border-red-800/50 bg-red-50/30 dark:bg-red-950/20 rounded-lg p-4" }, /* @__PURE__ */ React2.createElement("p", { className: "text-sm text-red-600 dark:text-red-400" }, "Failed to load view: ", loadError)));
|
|
7813
7866
|
}
|
|
@@ -7825,29 +7878,69 @@ function ViewRendererBase({
|
|
|
7825
7878
|
"div",
|
|
7826
7879
|
{
|
|
7827
7880
|
ref: containerRef,
|
|
7828
|
-
className: containerClassName,
|
|
7881
|
+
className: isFullscreen ? `${containerClassName} flex flex-col` : containerClassName,
|
|
7829
7882
|
style: isPip ? {
|
|
7830
7883
|
height: VIEW_DIMENSIONS.DEFAULT_HEIGHT,
|
|
7831
7884
|
maxWidth: VIEW_DIMENSIONS.PIP_MAX_WIDTH,
|
|
7832
7885
|
zIndex: 100
|
|
7833
7886
|
} : isFullscreen ? { zIndex: 100 } : void 0
|
|
7834
7887
|
},
|
|
7835
|
-
|
|
7888
|
+
isFullscreen && // ponytail: inspector Tailwind may not emit client arbitrary classes
|
|
7889
|
+
// (h-[50px], grid-cols-[auto_1fr_auto]) — use inline layout instead.
|
|
7890
|
+
/* @__PURE__ */ React2.createElement(
|
|
7891
|
+
"header",
|
|
7892
|
+
{
|
|
7893
|
+
className: "grid shrink-0 items-center border-b border-zinc-200 bg-background px-3 dark:border-zinc-700",
|
|
7894
|
+
style: {
|
|
7895
|
+
height: VIEW_DIMENSIONS.FULLSCREEN_HEADER_HEIGHT,
|
|
7896
|
+
gridTemplateColumns: "auto 1fr auto"
|
|
7897
|
+
}
|
|
7898
|
+
},
|
|
7899
|
+
renderFullscreenClose ? renderFullscreenClose({
|
|
7900
|
+
onClick: () => void handleDisplayModeChange("inline"),
|
|
7901
|
+
"data-testid": "debugger-exit-fullscreen-button",
|
|
7902
|
+
"aria-label": "Exit fullscreen"
|
|
7903
|
+
}) : /* @__PURE__ */ React2.createElement(
|
|
7904
|
+
"button",
|
|
7905
|
+
{
|
|
7906
|
+
type: "button",
|
|
7907
|
+
"data-testid": "debugger-exit-fullscreen-button",
|
|
7908
|
+
"aria-label": "Exit fullscreen",
|
|
7909
|
+
className: "flex size-8 cursor-pointer items-center justify-center rounded-full border border-zinc-200 bg-background text-foreground shadow-sm hover:bg-muted dark:border-zinc-700",
|
|
7910
|
+
onClick: () => void handleDisplayModeChange("inline")
|
|
7911
|
+
},
|
|
7912
|
+
/* @__PURE__ */ React2.createElement(CloseIcon, null)
|
|
7913
|
+
),
|
|
7914
|
+
/* @__PURE__ */ React2.createElement("div", { className: "flex min-w-0 items-center justify-center gap-2 px-2" }, fullscreenHeader?.iconUrl ? /* @__PURE__ */ React2.createElement(
|
|
7915
|
+
"img",
|
|
7916
|
+
{
|
|
7917
|
+
src: fullscreenHeader.iconUrl,
|
|
7918
|
+
alt: "",
|
|
7919
|
+
className: "size-6 shrink-0 rounded-md object-contain"
|
|
7920
|
+
}
|
|
7921
|
+
) : null, /* @__PURE__ */ React2.createElement("span", { className: "truncate text-sm font-medium text-foreground" }, fullscreenHeader?.title ?? toolName)),
|
|
7922
|
+
/* @__PURE__ */ React2.createElement("div", { className: "size-8 shrink-0", "aria-hidden": true })
|
|
7923
|
+
),
|
|
7924
|
+
isPip && (renderFullscreenClose ? /* @__PURE__ */ React2.createElement("div", { className: "absolute right-3 top-3", style: { zIndex: 110 } }, renderFullscreenClose({
|
|
7925
|
+
onClick: () => void handleDisplayModeChange("inline"),
|
|
7926
|
+
"data-testid": "debugger-exit-pip-button",
|
|
7927
|
+
"aria-label": "Exit picture-in-picture"
|
|
7928
|
+
})) : /* @__PURE__ */ React2.createElement(
|
|
7836
7929
|
"button",
|
|
7837
7930
|
{
|
|
7838
7931
|
type: "button",
|
|
7839
|
-
"data-testid":
|
|
7840
|
-
"aria-label":
|
|
7841
|
-
className: "absolute right-3 top-3 z-[110] flex size-8 items-center justify-center rounded-full border border-border bg-background/90 text-
|
|
7932
|
+
"data-testid": "debugger-exit-pip-button",
|
|
7933
|
+
"aria-label": "Exit picture-in-picture",
|
|
7934
|
+
className: "absolute right-3 top-3 z-[110] flex size-8 cursor-pointer items-center justify-center rounded-full border border-border bg-background/90 text-foreground shadow-sm backdrop-blur-sm hover:bg-background",
|
|
7842
7935
|
style: { zIndex: 110 },
|
|
7843
7936
|
onClick: () => void handleDisplayModeChange("inline")
|
|
7844
7937
|
},
|
|
7845
|
-
|
|
7846
|
-
),
|
|
7938
|
+
/* @__PURE__ */ React2.createElement(CloseIcon, null)
|
|
7939
|
+
)),
|
|
7847
7940
|
/* @__PURE__ */ React2.createElement(
|
|
7848
7941
|
"div",
|
|
7849
7942
|
{
|
|
7850
|
-
className: isFullscreen
|
|
7943
|
+
className: isFullscreen ? "relative flex min-h-0 w-full flex-1 flex-col" : isPip ? "relative w-full h-full min-h-0 flex flex-1 flex-col" : "relative w-full flex flex-1 justify-center items-center"
|
|
7851
7944
|
},
|
|
7852
7945
|
showSpinner && /* @__PURE__ */ React2.createElement("div", { className: "flex absolute inset-0 items-center justify-center z-10" }, /* @__PURE__ */ React2.createElement("span", { className: "text-sm text-muted-foreground" }, "Loading\u2026")),
|
|
7853
7946
|
!isPip && !isFullscreen && (invoking || invoked) && /* @__PURE__ */ React2.createElement("div", { className: "absolute -top-8 left-2 z-10 whitespace-nowrap pointer-events-none text-xs text-muted-foreground" }, invoking && !toolOutput ? invoking : invoked),
|
|
@@ -7864,10 +7957,7 @@ function ViewRendererBase({
|
|
|
7864
7957
|
{
|
|
7865
7958
|
ref: iframeRef,
|
|
7866
7959
|
title: `MCP App: ${toolName}`,
|
|
7867
|
-
className: "w-full h-full border-
|
|
7868
|
-
style: {
|
|
7869
|
-
border: resolved.prefersBorder && displayMode !== "fullscreen" ? void 0 : "none"
|
|
7870
|
-
}
|
|
7960
|
+
className: showHostBorder ? "w-full h-full bg-transparent border border-border rounded-xl" : "w-full h-full bg-transparent border-0"
|
|
7871
7961
|
}
|
|
7872
7962
|
)
|
|
7873
7963
|
)
|
|
@@ -7888,6 +7978,10 @@ function viewRendererAreEqual(prev, next) {
|
|
|
7888
7978
|
if (prev.hostContext !== next.hostContext) return false;
|
|
7889
7979
|
if (prev.hostCapabilities !== next.hostCapabilities) return false;
|
|
7890
7980
|
if (prev.cspMode !== next.cspMode) return false;
|
|
7981
|
+
if (prev.mockOpenAiFileApis !== next.mockOpenAiFileApis) return false;
|
|
7982
|
+
if (prev.onInlineHeightChange !== next.onInlineHeightChange) return false;
|
|
7983
|
+
if (prev.fullscreenHeader !== next.fullscreenHeader) return false;
|
|
7984
|
+
if (prev.renderFullscreenClose !== next.renderFullscreenClose) return false;
|
|
7891
7985
|
if (prev.className !== next.className) return false;
|
|
7892
7986
|
if (prev.onReady !== next.onReady) return false;
|
|
7893
7987
|
if (prev.onLifecycleChange !== next.onLifecycleChange) return false;
|