sunpeak 0.20.28 → 0.20.30

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.
@@ -19,6 +19,8 @@ const { existsSync, readdirSync, readFileSync } = fs;
19
19
  const { join, resolve, dirname, sep } = path;
20
20
  import { fileURLToPath, pathToFileURL } from 'url';
21
21
  import { createServer as createHttpServer } from 'http';
22
+ import { LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/sdk/types.js';
23
+ import { OAuthProtectedResourceMetadataSchema } from '@modelcontextprotocol/sdk/shared/auth.js';
22
24
  import { getPort } from '../lib/get-port.mjs';
23
25
  import { startSandboxServer } from '../lib/sandbox-server.mjs';
24
26
  import { getDevOverlayScript } from '../lib/dev-overlay.mjs';
@@ -176,6 +178,82 @@ function createInMemoryOAuthProvider(redirectUrl, opts = {}) {
176
178
  };
177
179
  }
178
180
 
181
+ /**
182
+ * @param {URL} serverUrl
183
+ * @returns {{ pathMetadataUrl: URL, rootMetadataUrl: URL } | undefined}
184
+ */
185
+ function getMcpResourceMetadataUrls(serverUrl) {
186
+ if (serverUrl.protocol !== 'http:' && serverUrl.protocol !== 'https:') return undefined;
187
+ if (serverUrl.pathname === '/' || serverUrl.pathname === '') return undefined;
188
+
189
+ const pathname = serverUrl.pathname.endsWith('/')
190
+ ? serverUrl.pathname.slice(0, -1)
191
+ : serverUrl.pathname;
192
+
193
+ const pathMetadataUrl = new URL(`/.well-known/oauth-protected-resource${pathname}`, serverUrl);
194
+ pathMetadataUrl.search = serverUrl.search;
195
+
196
+ const rootMetadataUrl = new URL('/.well-known/oauth-protected-resource', serverUrl.origin);
197
+ return { pathMetadataUrl, rootMetadataUrl };
198
+ }
199
+
200
+ /**
201
+ * MCP auth discovery supports both endpoint-path and root protected-resource
202
+ * metadata. When no WWW-Authenticate resource_metadata URL is available, the
203
+ * current MCP authorization draft says clients must try the endpoint path
204
+ * first, then the root well-known URI.
205
+ *
206
+ * The SDK already falls back from endpoint-path to root on 4xx responses. This
207
+ * helper detects the remaining common invalid-endpoint case before OAuth starts:
208
+ * the endpoint-path URL returns 200 but serves a text/html or text/plain landing
209
+ * page instead of protected-resource metadata JSON. In that case, start OAuth
210
+ * directly with the root metadata URL so no partial provider state is carried
211
+ * across a failed SDK auth attempt.
212
+ *
213
+ * @param {string | URL} serverUrl
214
+ * @param {typeof fetch} [fetchFn]
215
+ * @returns {Promise<string | undefined>}
216
+ */
217
+ export async function resolveMcpResourceMetadataUrl(serverUrl, fetchFn = fetch) {
218
+ let parsed;
219
+ try {
220
+ parsed = serverUrl instanceof URL ? serverUrl : new URL(serverUrl);
221
+ } catch {
222
+ return undefined;
223
+ }
224
+
225
+ const urls = getMcpResourceMetadataUrls(parsed);
226
+ if (!urls) return undefined;
227
+
228
+ let response;
229
+ try {
230
+ response = await fetchFn(urls.pathMetadataUrl, {
231
+ headers: { 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION },
232
+ });
233
+ } catch {
234
+ return undefined;
235
+ }
236
+
237
+ if (!response.ok) {
238
+ await response.body?.cancel();
239
+ return undefined;
240
+ }
241
+
242
+ const contentType = response.headers.get('content-type') ?? '';
243
+ if (!contentType.toLowerCase().includes('application/json')) {
244
+ await response.body?.cancel();
245
+ return urls.rootMetadataUrl.toString();
246
+ }
247
+
248
+ try {
249
+ OAuthProtectedResourceMetadataSchema.parse(await response.json());
250
+ } catch {
251
+ return urls.rootMetadataUrl.toString();
252
+ }
253
+
254
+ return undefined;
255
+ }
256
+
179
257
  /**
180
258
  * Negotiate OAuth with an MCP server and return an authenticated provider.
181
259
  *
@@ -197,10 +275,14 @@ async function negotiateOAuth(serverUrl) {
197
275
 
198
276
  const oauthState = createInMemoryOAuthProvider(callbackUrl);
199
277
  const { provider } = oauthState;
278
+ const resourceMetadataUrl = await resolveMcpResourceMetadataUrl(serverUrl);
200
279
 
201
280
  // First call to auth() — discovers metadata, registers client, and either
202
281
  // returns AUTHORIZED (client_credentials) or REDIRECT (authorization_code).
203
- const result = await auth(provider, { serverUrl: new URL(serverUrl) });
282
+ const result = await auth(provider, {
283
+ serverUrl: new URL(serverUrl),
284
+ ...(resourceMetadataUrl ? { resourceMetadataUrl: new URL(resourceMetadataUrl) } : {}),
285
+ });
204
286
 
205
287
  if (result === 'AUTHORIZED') {
206
288
  return provider;
@@ -1054,6 +1136,7 @@ function sunpeakInspectEndpointsPlugin(getClient, setClient, pluginOpts = {}) {
1054
1136
  // Always create a fresh provider for an explicit Authorize click.
1055
1137
  // This ensures the user's current credentials (or lack thereof) are
1056
1138
  // used, not stale ones from a previous attempt.
1139
+ const resourceMetadataUrl = await resolveMcpResourceMetadataUrl(serverUrl);
1057
1140
  const oauthState = createInMemoryOAuthProvider(callbackUrl, { clientId, clientSecret });
1058
1141
  oauthProviders.set(serverUrl, oauthState);
1059
1142
 
@@ -1062,6 +1145,7 @@ function sunpeakInspectEndpointsPlugin(getClient, setClient, pluginOpts = {}) {
1062
1145
  const result = await auth(oauthState.provider, {
1063
1146
  serverUrl,
1064
1147
  scope,
1148
+ ...(resourceMetadataUrl ? { resourceMetadataUrl: new URL(resourceMetadataUrl) } : {}),
1065
1149
  });
1066
1150
 
1067
1151
  if (result === 'REDIRECT') {
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../chunk-CoPdw6nB.cjs");
3
- const require_inspector = require("../inspector-DSX76Z-W.cjs");
3
+ const require_inspector = require("../inspector-CJPO4f12.cjs");
4
4
  const require_inspector_url = require("../inspector-url-CCgv8H74.cjs");
5
5
  const require_discovery = require("../discovery-C9fQVb1u.cjs");
6
6
  //#region src/chatgpt/index.ts
@@ -1,5 +1,5 @@
1
1
  import { I as __exportAll } from "../v4-Bvhoa4sV.js";
2
- import { _ as extractResourceCSP, f as ThemeProvider, g as IframeResource, p as useThemeContext, r as resolveServerToolResult, t as Inspector, v as McpAppHost, y as SCREEN_WIDTHS } from "../inspector-tIphAHtK.js";
2
+ import { _ as extractResourceCSP, f as ThemeProvider, g as IframeResource, p as useThemeContext, r as resolveServerToolResult, t as Inspector, v as McpAppHost, y as SCREEN_WIDTHS } from "../inspector-B1355aXh.js";
3
3
  import { t as createInspectorUrl } from "../inspector-url-CyQcuBI9.js";
4
4
  import { c as toPascalCase, i as findResourceKey, n as extractSimulationKey, r as findResourceDirs, s as getComponentName, t as extractResourceKey } from "../discovery-Cgoegt62.js";
5
5
  //#region src/chatgpt/index.ts
@@ -1,4 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../chunk-CoPdw6nB.cjs");
3
- const require_inspector = require("../inspector-DSX76Z-W.cjs");
3
+ const require_inspector = require("../inspector-CJPO4f12.cjs");
4
4
  exports.Inspector = require_inspector.Inspector;
@@ -1,2 +1,2 @@
1
- import { t as Inspector } from "../inspector-tIphAHtK.js";
1
+ import { t as Inspector } from "../inspector-B1355aXh.js";
2
2
  export { Inspector };
package/dist/index.cjs CHANGED
@@ -3,7 +3,7 @@ const require_chunk = require("./chunk-CoPdw6nB.cjs");
3
3
  const require_protocol = require("./protocol-DUYcEQSv.cjs");
4
4
  const require_v4 = require("./v4-Bgte15Jv.cjs");
5
5
  const require_use_app = require("./use-app-DIWh7-3f.cjs");
6
- const require_inspector = require("./inspector-DSX76Z-W.cjs");
6
+ const require_inspector = require("./inspector-CJPO4f12.cjs");
7
7
  const require_host_index = require("./host/index.cjs");
8
8
  const require_inspector_index = require("./inspector/index.cjs");
9
9
  const require_chatgpt_index = require("./chatgpt/index.cjs");
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { L as __require, _ as record, a as array, b as unknown, f as never, i as _undefined, m as object, o as boolean, p as number, u as literal, v as string, y as union } from "./v4-Bvhoa4sV.js";
2
2
  import { B as ResourceLinkSchema, G as ToolSchema, a as CallToolResultSchema, m as EmbeddedResourceSchema, s as ContentBlockSchema, v as ImplementationSchema, z as RequestIdSchema } from "./protocol-kqfS1G0V.js";
3
3
  import { $ as s, A as TQ, B as e, C as PQ, D as RQ, E as R, F as ZQ, G as i, H as f, I as _, J as l, K as j, L as _Q, M as W, N as XQ, O as SQ, P as YQ, Q as r, R as bQ, S as P, T as QY, U as g, V as eX, W as h, X as q, Y as n, Z as qQ, _ as JQ, a as AQ, at as z, b as O, c as CQ, d as F, et as t, f as FQ, g as IQ, h as I, i as A, it as wQ, j as U, k as T, l as DQ, m as HQ, n as AppProvider, nt as v, o as B, ot as zQ, p as H, q as kQ, r as $Q, rt as w, s as C, t as useApp, tt as u, u as E, v as L, w as QQ, x as OQ, y as M, z as d } from "./use-app-C2pGHlnF.js";
4
- import { C as cn, w as DEFAULT_STYLE_VARIABLES } from "./inspector-tIphAHtK.js";
4
+ import { C as cn, w as DEFAULT_STYLE_VARIABLES } from "./inspector-B1355aXh.js";
5
5
  import { detectHost, isChatGPT, isClaude } from "./host/index.js";
6
6
  import { t as inspector_exports } from "./inspector/index.js";
7
7
  import { t as chatgpt_exports } from "./chatgpt/index.js";
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../chunk-CoPdw6nB.cjs");
3
- const require_inspector = require("../inspector-DSX76Z-W.cjs");
3
+ const require_inspector = require("../inspector-CJPO4f12.cjs");
4
4
  const require_inspector_url = require("../inspector-url-CCgv8H74.cjs");
5
5
  const require_discovery = require("../discovery-C9fQVb1u.cjs");
6
6
  //#region src/inspector/index.ts
@@ -1,5 +1,5 @@
1
1
  import { I as __exportAll } from "../v4-Bvhoa4sV.js";
2
- import { S as registerHostShell, _ as extractResourceCSP, a as SidebarCollapsibleControl, b as getHostShell, c as SidebarSelect, d as SimpleSidebar, f as ThemeProvider, g as IframeResource, h as useInspectorState, i as SidebarCheckbox, l as SidebarTextarea, m as useMcpConnection, n as flattenAppToSimulations, o as SidebarControl, p as useThemeContext, r as resolveServerToolResult, s as SidebarInput, t as Inspector, u as SidebarToggle, v as McpAppHost, x as getRegisteredHosts, y as SCREEN_WIDTHS } from "../inspector-tIphAHtK.js";
2
+ import { S as registerHostShell, _ as extractResourceCSP, a as SidebarCollapsibleControl, b as getHostShell, c as SidebarSelect, d as SimpleSidebar, f as ThemeProvider, g as IframeResource, h as useInspectorState, i as SidebarCheckbox, l as SidebarTextarea, m as useMcpConnection, n as flattenAppToSimulations, o as SidebarControl, p as useThemeContext, r as resolveServerToolResult, s as SidebarInput, t as Inspector, u as SidebarToggle, v as McpAppHost, x as getRegisteredHosts, y as SCREEN_WIDTHS } from "../inspector-B1355aXh.js";
3
3
  import { t as createInspectorUrl } from "../inspector-url-CyQcuBI9.js";
4
4
  import { c as toPascalCase, i as findResourceKey, n as extractSimulationKey, r as findResourceDirs, s as getComponentName, t as extractResourceKey } from "../discovery-Cgoegt62.js";
5
5
  //#region src/inspector/index.ts
@@ -0,0 +1,3 @@
1
+ export declare function inspectorApiEndpoint(path: string, apiBaseUrl?: string): string;
2
+ export declare function readInspectorJson<T>(res: Response, endpoint: string): Promise<T>;
3
+ export declare function resolveInspectorResourceUrls<T>(simulations: T, apiBaseUrl?: string): T;
@@ -56,5 +56,12 @@ export interface InspectorProps {
56
56
  * to a different server.
57
57
  */
58
58
  mcpServerUrl?: string;
59
+ /**
60
+ * Base URL for the sunpeak inspector backend endpoints (`/__sunpeak/*`).
61
+ * Defaults to same-origin. Embedders that serve the React Inspector from
62
+ * their own app can point this at a same-origin proxy or hosted inspector
63
+ * backend, for example `/api/sunpeak`.
64
+ */
65
+ inspectorApiBaseUrl?: string;
59
66
  }
60
- export declare function Inspector({ children, app, simulations: initialSimulationsProp, appName: appNameProp, appIcon: appIconProp, defaultHost, onCallTool, onCallToolDirect, defaultProdResources, hideInspectorModes, demoMode, sandboxUrl, mcpServerUrl, }: InspectorProps): import("react/jsx-runtime").JSX.Element;
67
+ export declare function Inspector({ children, app, simulations: initialSimulationsProp, appName: appNameProp, appIcon: appIconProp, defaultHost, onCallTool, onCallToolDirect, defaultProdResources, hideInspectorModes, demoMode, sandboxUrl, mcpServerUrl, inspectorApiBaseUrl, }: InspectorProps): import("react/jsx-runtime").JSX.Element;
@@ -29,4 +29,4 @@ export interface McpConnectionState {
29
29
  * once (or safely twice with cancellation), while explicit `reconnect()` calls
30
30
  * are triggered by the Inspector's URL-change effect.
31
31
  */
32
- export declare function useMcpConnection(initialServerUrl: string | undefined): McpConnectionState;
32
+ export declare function useMcpConnection(initialServerUrl: string | undefined, inspectorApiBaseUrl?: string): McpConnectionState;
@@ -6573,6 +6573,40 @@ function useInspectorState({ simulations, defaultHost = "chatgpt" }) {
6573
6573
  };
6574
6574
  }
6575
6575
  //#endregion
6576
+ //#region src/inspector/inspector-api.ts
6577
+ function inspectorApiEndpoint(path, apiBaseUrl) {
6578
+ if (!apiBaseUrl) return path;
6579
+ return `${apiBaseUrl.replace(/\/+$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
6580
+ }
6581
+ async function readInspectorJson(res, endpoint) {
6582
+ const text = await res.text();
6583
+ if (!text) return {};
6584
+ try {
6585
+ return JSON.parse(text);
6586
+ } catch {
6587
+ const contentType = res.headers.get("content-type");
6588
+ const preview = text.trim().replace(/\s+/g, " ").slice(0, 120);
6589
+ const typeHint = contentType ? ` (${contentType})` : "";
6590
+ throw new Error(`Expected JSON from ${endpoint} but received a non-JSON response${typeHint}: ${preview}`);
6591
+ }
6592
+ }
6593
+ function resolveInspectorResourceUrls(simulations, apiBaseUrl) {
6594
+ if (!apiBaseUrl || !simulations || typeof simulations !== "object") return simulations;
6595
+ const resolved = {};
6596
+ for (const [key, value] of Object.entries(simulations)) {
6597
+ if (!value || typeof value !== "object") {
6598
+ resolved[key] = value;
6599
+ continue;
6600
+ }
6601
+ const sim = value;
6602
+ resolved[key] = {
6603
+ ...sim,
6604
+ resourceUrl: typeof sim.resourceUrl === "string" && sim.resourceUrl.startsWith("/") ? inspectorApiEndpoint(sim.resourceUrl, apiBaseUrl) : sim.resourceUrl
6605
+ };
6606
+ }
6607
+ return resolved;
6608
+ }
6609
+ //#endregion
6576
6610
  //#region src/inspector/use-mcp-connection.ts
6577
6611
  /**
6578
6612
  * Hook for managing MCP server connection status via the dev server proxy.
@@ -6585,7 +6619,7 @@ function useInspectorState({ simulations, defaultHost = "chatgpt" }) {
6585
6619
  * once (or safely twice with cancellation), while explicit `reconnect()` calls
6586
6620
  * are triggered by the Inspector's URL-change effect.
6587
6621
  */
6588
- function useMcpConnection(initialServerUrl) {
6622
+ function useMcpConnection(initialServerUrl, inspectorApiBaseUrl) {
6589
6623
  const [status, setStatus] = useState(initialServerUrl ? "connecting" : "disconnected");
6590
6624
  const [error, setError] = useState();
6591
6625
  const [simulations, setSimulations] = useState();
@@ -6597,7 +6631,8 @@ function useMcpConnection(initialServerUrl) {
6597
6631
  try {
6598
6632
  const body = { url };
6599
6633
  if (auth && auth.type !== "none") body.auth = auth;
6600
- const res = await fetch("/__sunpeak/connect", {
6634
+ const endpoint = inspectorApiEndpoint("/__sunpeak/connect", inspectorApiBaseUrl);
6635
+ const res = await fetch(endpoint, {
6601
6636
  method: "POST",
6602
6637
  headers: { "Content-Type": "application/json" },
6603
6638
  body: JSON.stringify(body)
@@ -6605,7 +6640,7 @@ function useMcpConnection(initialServerUrl) {
6605
6640
  if (!res.ok) {
6606
6641
  let message;
6607
6642
  try {
6608
- const json = await res.json();
6643
+ const json = await readInspectorJson(res, endpoint);
6609
6644
  if (json.error) message = json.error;
6610
6645
  } catch {}
6611
6646
  if (!message) if (res.status === 404) message = "Server not found at this URL. Check the URL and make sure the server is running.";
@@ -6613,9 +6648,9 @@ function useMcpConnection(initialServerUrl) {
6613
6648
  else message = `Connection failed (${res.status})`;
6614
6649
  throw new Error(message);
6615
6650
  }
6616
- const data = await res.json();
6651
+ const data = await readInspectorJson(res, endpoint);
6617
6652
  setStatus("connected");
6618
- setSimulations(data.simulations ?? void 0);
6653
+ setSimulations(resolveInspectorResourceUrls(data.simulations, inspectorApiBaseUrl));
6619
6654
  } catch (err) {
6620
6655
  let message = err instanceof Error ? err.message : String(err);
6621
6656
  if (err instanceof TypeError && message === "Failed to fetch") message = "Cannot reach MCP server. Is it running?";
@@ -6623,20 +6658,21 @@ function useMcpConnection(initialServerUrl) {
6623
6658
  setStatus("error");
6624
6659
  setSimulations(void 0);
6625
6660
  }
6626
- }, []);
6661
+ }, [inspectorApiBaseUrl]);
6627
6662
  const setConnected = useCallback((sims) => {
6628
6663
  setHasReconnected(true);
6629
6664
  setStatus("connected");
6630
6665
  setError(void 0);
6631
- setSimulations(sims);
6632
- }, []);
6666
+ setSimulations(resolveInspectorResourceUrls(sims, inspectorApiBaseUrl));
6667
+ }, [inspectorApiBaseUrl]);
6633
6668
  useEffect(() => {
6634
6669
  if (!initialServerUrl) return;
6635
6670
  let cancelled = false;
6636
6671
  setStatus("connecting");
6637
6672
  (async () => {
6638
6673
  try {
6639
- const res = await fetch("/__sunpeak/list-tools");
6674
+ const endpoint = inspectorApiEndpoint("/__sunpeak/list-tools", inspectorApiBaseUrl);
6675
+ const res = await fetch(endpoint);
6640
6676
  if (cancelled) return;
6641
6677
  if (!res.ok) {
6642
6678
  const msg = res.status === 404 ? "MCP server not reachable. Is it running?" : `Health check failed (${res.status}). Check the MCP server logs.`;
@@ -7136,7 +7172,7 @@ function hasFixtureData(sim) {
7136
7172
  return sim.toolResult != null || sim.toolInput != null || sim.serverTools != null;
7137
7173
  }
7138
7174
  var EMPTY_SIMULATIONS = Object.freeze({});
7139
- function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_SIMULATIONS, appName: appNameProp, appIcon: appIconProp, defaultHost = "chatgpt", onCallTool, onCallToolDirect, defaultProdResources = false, hideInspectorModes = false, demoMode = false, sandboxUrl, mcpServerUrl }) {
7175
+ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_SIMULATIONS, appName: appNameProp, appIcon: appIconProp, defaultHost = "chatgpt", onCallTool, onCallToolDirect, defaultProdResources = false, hideInspectorModes = false, demoMode = false, sandboxUrl, mcpServerUrl, inspectorApiBaseUrl }) {
7140
7176
  const initialSimulations = React.useMemo(() => app ? flattenAppToSimulations(app) : initialSimulationsProp, [app, initialSimulationsProp]);
7141
7177
  const appName = app?.name ?? appNameProp ?? "Sunpeak";
7142
7178
  const appIcon = app?.icon ?? appIconProp;
@@ -7232,13 +7268,14 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
7232
7268
  const [oauthClientSecret, setOauthClientSecret] = React.useState("");
7233
7269
  const [oauthStatus, setOauthStatus] = React.useState("none");
7234
7270
  const [oauthError, setOauthError] = React.useState();
7235
- const connection = useMcpConnection(isEmbedded ? void 0 : mcpServerUrl || void 0);
7271
+ const connection = useMcpConnection(isEmbedded ? void 0 : mcpServerUrl || void 0, inspectorApiBaseUrl);
7236
7272
  const [prodResources, setProdResources] = React.useState(state.urlProdResources ?? defaultProdResources);
7237
7273
  const showSidebar = state.urlSidebar !== false;
7238
7274
  const showDevOverlay = state.urlDevOverlay !== false;
7239
7275
  const [isRunning, setIsRunning] = React.useState(false);
7240
7276
  const [hasRun, setHasRun] = React.useState(false);
7241
7277
  const [showCheck, setShowCheck] = React.useState(false);
7278
+ const [serverPreviewGeneration, setServerPreviewGeneration] = React.useState(0);
7242
7279
  const checkTimerRef = React.useRef(void 0);
7243
7280
  const oauthCleanupRef = React.useRef(void 0);
7244
7281
  React.useEffect(() => {
@@ -7274,7 +7311,8 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
7274
7311
  setOauthError(void 0);
7275
7312
  const popup = window.open("about:blank", `sunpeak-oauth-${Date.now()}`, "width=600,height=700,popup=yes");
7276
7313
  try {
7277
- const res = await fetch("/__sunpeak/oauth/start", {
7314
+ const endpoint = inspectorApiEndpoint("/__sunpeak/oauth/start", inspectorApiBaseUrl);
7315
+ const res = await fetch(endpoint, {
7278
7316
  method: "POST",
7279
7317
  headers: { "Content-Type": "application/json" },
7280
7318
  body: JSON.stringify({
@@ -7284,15 +7322,12 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
7284
7322
  clientSecret: oauthClientSecret || void 0
7285
7323
  })
7286
7324
  });
7325
+ const data = await readInspectorJson(res, endpoint);
7287
7326
  if (!res.ok) {
7288
7327
  let message = `OAuth start failed (${res.status})`;
7289
- try {
7290
- const json = await res.json();
7291
- if (json.error) message = json.error;
7292
- } catch {}
7328
+ if (data.error) message = data.error;
7293
7329
  throw new Error(message);
7294
7330
  }
7295
- const data = await res.json();
7296
7331
  if (data.error) {
7297
7332
  popup?.close();
7298
7333
  setOauthError(data.error);
@@ -7373,11 +7408,14 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
7373
7408
  oauthClientId,
7374
7409
  oauthClientSecret,
7375
7410
  demoMode,
7376
- connection
7411
+ connection,
7412
+ inspectorApiBaseUrl
7377
7413
  ]);
7378
7414
  React.useEffect(() => {
7379
- if (connection.simulations) setSimulations(connection.simulations);
7380
- else if (connection.status === "error" && connection.hasReconnected) setSimulations({});
7415
+ if (connection.simulations) {
7416
+ setSimulations(connection.simulations);
7417
+ setServerPreviewGeneration((generation) => generation + 1);
7418
+ } else if (connection.status === "error" && connection.hasReconnected) setSimulations({});
7381
7419
  }, [
7382
7420
  connection.simulations,
7383
7421
  connection.status,
@@ -7699,7 +7737,7 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
7699
7737
  injectOpenAIRuntime: state.activeHost === "chatgpt",
7700
7738
  sandboxUrl,
7701
7739
  className: "h-full w-full"
7702
- }, `${state.activeHost}-${state.selectedSimulationName}-${effectiveResourceUrl}-${prodResources}-${prodResourcesGeneration}`)
7740
+ }, `${state.activeHost}-${state.selectedSimulationName}-${effectiveResourceUrl}-${prodResources}-${prodResourcesGeneration}-${serverPreviewGeneration}`)
7703
7741
  });
7704
7742
  else if (!prodResources && state.resourceScript) content = /* @__PURE__ */ jsx("div", {
7705
7743
  className: "h-full w-full",
@@ -8324,4 +8362,4 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
8324
8362
  //#endregion
8325
8363
  export { cn as C, registerHostShell as S, extractResourceCSP as _, SidebarCollapsibleControl as a, getHostShell as b, SidebarSelect as c, SimpleSidebar as d, ThemeProvider as f, IframeResource as g, useInspectorState as h, SidebarCheckbox as i, SidebarTextarea as l, useMcpConnection as m, flattenAppToSimulations as n, SidebarControl as o, useThemeContext as p, resolveServerToolResult as r, SidebarInput as s, Inspector as t, SidebarToggle as u, McpAppHost as v, DEFAULT_STYLE_VARIABLES as w, getRegisteredHosts as x, SCREEN_WIDTHS as y };
8326
8364
 
8327
- //# sourceMappingURL=inspector-tIphAHtK.js.map
8365
+ //# sourceMappingURL=inspector-B1355aXh.js.map