sunpeak 0.20.23 → 0.20.29
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/README.md +29 -4
- package/bin/commands/inspect.mjs +18 -0
- package/dist/chatgpt/index.cjs +1 -1
- package/dist/chatgpt/index.js +1 -1
- package/dist/claude/index.cjs +1 -1
- package/dist/claude/index.js +1 -1
- package/dist/embed.css +2 -0
- package/dist/host/chatgpt/index.cjs +1 -1
- package/dist/host/chatgpt/index.js +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/inspector/app-flatten.d.ts +7 -0
- package/dist/inspector/app-types.d.ts +83 -0
- package/dist/inspector/iframe-resource.d.ts +19 -1
- package/dist/inspector/index.cjs +3 -1
- package/dist/inspector/index.cjs.map +1 -1
- package/dist/inspector/index.d.ts +2 -0
- package/dist/inspector/index.js +3 -2
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/inline-helper-script.d.ts +22 -0
- package/dist/inspector/inspector-api.d.ts +3 -0
- package/dist/inspector/inspector.d.ts +21 -1
- package/dist/inspector/simple-sidebar.d.ts +13 -1
- package/dist/inspector/use-inspector-state.d.ts +1 -0
- package/dist/inspector/use-mcp-connection.d.ts +1 -1
- package/dist/{inspector-CJNvLoHo.js → inspector-B1355aXh.js} +393 -49
- package/dist/inspector-B1355aXh.js.map +1 -0
- package/dist/{inspector-DtEighD9.cjs → inspector-CJPO4f12.cjs} +397 -47
- package/dist/inspector-CJPO4f12.cjs.map +1 -0
- package/dist/mcp/index.cjs +1 -1
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/sandbox-proxy.html +173 -0
- package/dist/style.css +9 -1
- package/dist/types/simulation.d.ts +3 -8
- package/dist/{use-app-cSBm5Pjl.js → use-app-C2pGHlnF.js} +2 -2
- package/dist/{use-app-cSBm5Pjl.js.map → use-app-C2pGHlnF.js.map} +1 -1
- package/dist/{use-app-CxtSfkSF.cjs → use-app-DIWh7-3f.cjs} +2 -2
- package/dist/{use-app-CxtSfkSF.cjs.map → use-app-DIWh7-3f.cjs.map} +1 -1
- package/package.json +6 -3
- package/template/dist/albums/albums.html +1 -1
- package/template/dist/albums/albums.json +1 -1
- package/template/dist/carousel/carousel.html +1 -1
- package/template/dist/carousel/carousel.json +1 -1
- package/template/dist/map/map.html +1 -1
- package/template/dist/map/map.json +1 -1
- package/template/dist/review/review.html +1 -1
- package/template/dist/review/review.json +1 -1
- package/template/node_modules/.vite/deps/_metadata.json +3 -3
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/_metadata.json +22 -22
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-claude-linux.png +0 -0
- package/dist/inspector-CJNvLoHo.js.map +0 -1
- package/dist/inspector-DtEighD9.cjs.map +0 -1
|
@@ -2,7 +2,7 @@ import { L as __require, _ as record, a as array, b as unknown, f as never, i as
|
|
|
2
2
|
import { B as ResourceLinkSchema, C as ListPromptsRequestSchema, D as ListResourcesRequestSchema, E as ListResourceTemplatesResultSchema, F as PingRequestSchema, G as ToolSchema, I as PromptListChangedNotificationSchema, L as ReadResourceRequestSchema, N as LoggingMessageNotificationSchema, O as ListResourcesResultSchema, R as ReadResourceResultSchema, T as ListResourceTemplatesRequestSchema, V as ResourceListChangedNotificationSchema, W as ToolListChangedNotificationSchema, a as CallToolResultSchema, c as CreateMessageRequestSchema, i as CallToolRequestSchema, j as ListToolsResultSchema, m as EmbeddedResourceSchema, s as ContentBlockSchema, t as Protocol, v as ImplementationSchema, w as ListPromptsResultSchema, x as JSONRPCMessageSchema, z as RequestIdSchema } from "./protocol-kqfS1G0V.js";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
//#region src/lib/default-style-variables.ts
|
|
7
7
|
var DEFAULT_STYLE_VARIABLES = {
|
|
8
8
|
"--color-background-primary": "light-dark(#ffffff, #1a1a1a)",
|
|
@@ -4223,7 +4223,7 @@ registerHostShell({
|
|
|
4223
4223
|
}`
|
|
4224
4224
|
});
|
|
4225
4225
|
//#endregion
|
|
4226
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.7.
|
|
4226
|
+
//#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.7.2_@modelcontextprotocol+sdk@1.29.0_zod@4.4.3__react-_f5b843da9146ebea748e10ad8dfce46a/node_modules/@modelcontextprotocol/ext-apps/dist/src/app-bridge.js
|
|
4227
4227
|
((X) => typeof __require < "u" ? __require : typeof Proxy < "u" ? new Proxy(X, { get: (Y, Z) => (typeof __require < "u" ? __require : Y)[Z] }) : X)(function(X) {
|
|
4228
4228
|
if (typeof __require < "u") return __require.apply(this, arguments);
|
|
4229
4229
|
throw Error("Dynamic require of \"" + X + "\" is not supported");
|
|
@@ -5545,6 +5545,145 @@ iframe { border: none; width: 100%; height: 100%; display: block; }
|
|
|
5545
5545
|
</body>
|
|
5546
5546
|
</html>`;
|
|
5547
5547
|
}
|
|
5548
|
+
var SUNPEAK_INLINE_HELPER_SCRIPT = `
|
|
5549
|
+
(function() {
|
|
5550
|
+
if (window.sunpeak) return; // already installed (e.g. parent hot-reload)
|
|
5551
|
+
// Opt-out: resource HTML using the real MCP Apps SDK can suppress the
|
|
5552
|
+
// helper to avoid sending two ui/initialize requests. Manual lowercase
|
|
5553
|
+
// comparison so content="off" / "OFF" / "Off" all match (the Selectors
|
|
5554
|
+
// L4 case-insensitive flag isn't supported in all test environments).
|
|
5555
|
+
try {
|
|
5556
|
+
var metas = document.querySelectorAll('meta[name="sunpeak-helper"]');
|
|
5557
|
+
for (var mi = 0; mi < metas.length; mi++) {
|
|
5558
|
+
var contentAttr = metas[mi].getAttribute('content');
|
|
5559
|
+
if (contentAttr && contentAttr.toLowerCase() === 'off') return;
|
|
5560
|
+
}
|
|
5561
|
+
} catch (e) { /* document not ready or querySelector missing */ }
|
|
5562
|
+
|
|
5563
|
+
var listeners = {
|
|
5564
|
+
toolInput: [],
|
|
5565
|
+
toolInputPartial: [],
|
|
5566
|
+
toolResult: [],
|
|
5567
|
+
toolCancelled: [],
|
|
5568
|
+
hostContext: []
|
|
5569
|
+
};
|
|
5570
|
+
var last = {
|
|
5571
|
+
toolInput: undefined,
|
|
5572
|
+
toolInputPartial: undefined,
|
|
5573
|
+
toolResult: undefined,
|
|
5574
|
+
toolCancelled: undefined,
|
|
5575
|
+
hostContext: undefined
|
|
5576
|
+
};
|
|
5577
|
+
function dispatch(channel, value) {
|
|
5578
|
+
last[channel] = value;
|
|
5579
|
+
// Iterate over a SNAPSHOT — callbacks that unsubscribe themselves
|
|
5580
|
+
// mutate the live list, which would skip subsequent callbacks under a
|
|
5581
|
+
// for-by-index loop on the original array.
|
|
5582
|
+
var list = listeners[channel].slice();
|
|
5583
|
+
for (var i = 0; i < list.length; i++) {
|
|
5584
|
+
try { list[i](value); } catch (e) { console.error('[sunpeak] callback error:', e); }
|
|
5585
|
+
}
|
|
5586
|
+
}
|
|
5587
|
+
// Map channel names to the public method name for error messages.
|
|
5588
|
+
var channelMethodName = {
|
|
5589
|
+
toolInput: 'onToolInput',
|
|
5590
|
+
toolInputPartial: 'onToolInputPartial',
|
|
5591
|
+
toolResult: 'onToolResult',
|
|
5592
|
+
toolCancelled: 'onToolCancelled',
|
|
5593
|
+
hostContext: 'onHostContextChange'
|
|
5594
|
+
};
|
|
5595
|
+
function subscribe(channel) {
|
|
5596
|
+
return function(cb) {
|
|
5597
|
+
if (typeof cb !== 'function') {
|
|
5598
|
+
throw new TypeError('window.sunpeak.' + channelMethodName[channel] + ' expects a function');
|
|
5599
|
+
}
|
|
5600
|
+
listeners[channel].push(cb);
|
|
5601
|
+
if (last[channel] !== undefined) {
|
|
5602
|
+
try { cb(last[channel]); } catch (e) { console.error('[sunpeak] callback error:', e); }
|
|
5603
|
+
}
|
|
5604
|
+
return function unsubscribe() {
|
|
5605
|
+
var idx = listeners[channel].indexOf(cb);
|
|
5606
|
+
if (idx >= 0) listeners[channel].splice(idx, 1);
|
|
5607
|
+
};
|
|
5608
|
+
};
|
|
5609
|
+
}
|
|
5610
|
+
|
|
5611
|
+
window.sunpeak = {
|
|
5612
|
+
onToolInput: subscribe('toolInput'),
|
|
5613
|
+
onToolInputPartial: subscribe('toolInputPartial'),
|
|
5614
|
+
onToolResult: subscribe('toolResult'),
|
|
5615
|
+
onToolCancelled: subscribe('toolCancelled'),
|
|
5616
|
+
onHostContextChange: subscribe('hostContext')
|
|
5617
|
+
};
|
|
5618
|
+
|
|
5619
|
+
var nextId = 1;
|
|
5620
|
+
var pending = {};
|
|
5621
|
+
|
|
5622
|
+
function sendRequest(method, params) {
|
|
5623
|
+
var id = nextId++;
|
|
5624
|
+
return new Promise(function(resolve, reject) {
|
|
5625
|
+
pending[id] = { resolve: resolve, reject: reject };
|
|
5626
|
+
try {
|
|
5627
|
+
window.parent.postMessage({ jsonrpc: '2.0', id: id, method: method, params: params }, '*');
|
|
5628
|
+
} catch (e) {
|
|
5629
|
+
delete pending[id];
|
|
5630
|
+
reject(e);
|
|
5631
|
+
}
|
|
5632
|
+
});
|
|
5633
|
+
}
|
|
5634
|
+
function sendNotification(method, params) {
|
|
5635
|
+
try {
|
|
5636
|
+
window.parent.postMessage({ jsonrpc: '2.0', method: method, params: params || {} }, '*');
|
|
5637
|
+
} catch (e) { /* parent detached */ }
|
|
5638
|
+
}
|
|
5639
|
+
|
|
5640
|
+
window.addEventListener('message', function(ev) {
|
|
5641
|
+
// Only trust messages from the actual parent (the sandbox proxy).
|
|
5642
|
+
// Without this guard, a sibling iframe in the same browsing context or
|
|
5643
|
+
// a browser extension content script could forge JSON-RPC notifications
|
|
5644
|
+
// and drive the embedder's onToolResult/onToolInput callbacks with
|
|
5645
|
+
// attacker-controlled data.
|
|
5646
|
+
if (ev.source !== window.parent) return;
|
|
5647
|
+
var msg = ev.data;
|
|
5648
|
+
if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') return;
|
|
5649
|
+
if (typeof msg.id !== 'undefined' && pending[msg.id]) {
|
|
5650
|
+
var p = pending[msg.id];
|
|
5651
|
+
delete pending[msg.id];
|
|
5652
|
+
if (msg.error) p.reject(new Error((msg.error && msg.error.message) || 'request error'));
|
|
5653
|
+
else p.resolve(msg.result);
|
|
5654
|
+
return;
|
|
5655
|
+
}
|
|
5656
|
+
if (msg.method === 'ui/notifications/tool-input') {
|
|
5657
|
+
dispatch('toolInput', (msg.params && msg.params.arguments) || {});
|
|
5658
|
+
} else if (msg.method === 'ui/notifications/tool-input-partial') {
|
|
5659
|
+
dispatch('toolInputPartial', (msg.params && msg.params.arguments) || {});
|
|
5660
|
+
} else if (msg.method === 'ui/notifications/tool-result') {
|
|
5661
|
+
// tool-result params are the CallToolResult directly per the spec.
|
|
5662
|
+
dispatch('toolResult', msg.params || {});
|
|
5663
|
+
} else if (msg.method === 'ui/notifications/tool-cancelled') {
|
|
5664
|
+
// Clear cached input / partial / result so a late onToolResult
|
|
5665
|
+
// subscriber doesn't get the cancelled-then-stale value replayed.
|
|
5666
|
+
// hostContext stays — the environment hasn't changed.
|
|
5667
|
+
last.toolInput = undefined;
|
|
5668
|
+
last.toolInputPartial = undefined;
|
|
5669
|
+
last.toolResult = undefined;
|
|
5670
|
+
dispatch('toolCancelled', msg.params || {});
|
|
5671
|
+
} else if (msg.method === 'ui/notifications/host-context-changed') {
|
|
5672
|
+
dispatch('hostContext', msg.params || {});
|
|
5673
|
+
}
|
|
5674
|
+
});
|
|
5675
|
+
|
|
5676
|
+
sendRequest('ui/initialize', {
|
|
5677
|
+
appInfo: { name: 'sunpeak-inline-helper', version: '1.0.0' },
|
|
5678
|
+
appCapabilities: {},
|
|
5679
|
+
protocolVersion: '2026-01-26'
|
|
5680
|
+
}).then(function() {
|
|
5681
|
+
sendNotification('ui/notifications/initialized');
|
|
5682
|
+
}).catch(function(err) {
|
|
5683
|
+
console.warn('[sunpeak] ui/initialize failed:', err && err.message);
|
|
5684
|
+
});
|
|
5685
|
+
})();
|
|
5686
|
+
`.trim();
|
|
5548
5687
|
//#endregion
|
|
5549
5688
|
//#region src/inspector/iframe-resource.tsx
|
|
5550
5689
|
/**
|
|
@@ -5683,6 +5822,23 @@ requestAnimationFrame(function(){
|
|
|
5683
5822
|
e.source.postMessage({jsonrpc:"2.0",method:"sunpeak/fence-ack",params:{fenceId:fid}},"*");
|
|
5684
5823
|
});}});`;
|
|
5685
5824
|
/**
|
|
5825
|
+
* Inject the paint-fence responder and (optionally) a platform runtime script
|
|
5826
|
+
* into a user-provided HTML document. Used for the `html` prop mode where the
|
|
5827
|
+
* embedder hands us a complete document from `mcpClient.readResource(...)` and
|
|
5828
|
+
* we need to splice in the same infrastructure that the `scriptSrc` wrapper
|
|
5829
|
+
* provides. The injection is placed before `</head>` when present, falling
|
|
5830
|
+
* back to the start of `<body>` or the document start.
|
|
5831
|
+
*/
|
|
5832
|
+
function injectInfraScripts(html, platformScript) {
|
|
5833
|
+
const fenceTag = `<script data-sunpeak-fence>${PAINT_FENCE_SCRIPT}<\/script>`;
|
|
5834
|
+
const injection = `${platformScript ? `<script>${platformScript}<\/script>` : ""}${fenceTag}${`<script data-sunpeak-helper>${SUNPEAK_INLINE_HELPER_SCRIPT}<\/script>`}`;
|
|
5835
|
+
const headMatch = html.match(/<\/head\s*>/i);
|
|
5836
|
+
if (headMatch) return html.replace(headMatch[0], `${injection}${headMatch[0]}`);
|
|
5837
|
+
const bodyMatch = html.match(/<body([^>]*)>/i);
|
|
5838
|
+
if (bodyMatch) return html.replace(bodyMatch[0], `${bodyMatch[0]}${injection}`);
|
|
5839
|
+
return injection + html;
|
|
5840
|
+
}
|
|
5841
|
+
/**
|
|
5686
5842
|
* Generates HTML wrapper for a script URL.
|
|
5687
5843
|
* The MCP Apps SDK in the loaded script handles communication via PostMessageTransport.
|
|
5688
5844
|
*/
|
|
@@ -5746,7 +5902,7 @@ function buildIframeAllow(permissions) {
|
|
|
5746
5902
|
* connects via PostMessageTransport to window.parent. The parent side uses
|
|
5747
5903
|
* McpAppHost (wrapping AppBridge) to communicate.
|
|
5748
5904
|
*/
|
|
5749
|
-
function IframeResource({ src, scriptSrc, hostContext, toolInput, toolInputPartial, toolResult, hostOptions, csp, permissions, prefersBorder, className, style, onDisplayModeReady, debugInjectState, injectOpenAIRuntime, sandboxUrl }) {
|
|
5905
|
+
function IframeResource({ src, scriptSrc, html, hostContext, toolInput, toolInputPartial, toolResult, hostOptions, csp, permissions, prefersBorder, className, style, onDisplayModeReady, debugInjectState, injectOpenAIRuntime, sandboxUrl }) {
|
|
5750
5906
|
const iframeRef = useRef(null);
|
|
5751
5907
|
const hostRef = useRef(null);
|
|
5752
5908
|
const resourceUrl = src ?? scriptSrc;
|
|
@@ -5754,6 +5910,8 @@ function IframeResource({ src, scriptSrc, hostContext, toolInput, toolInputParti
|
|
|
5754
5910
|
srcRef.current = src;
|
|
5755
5911
|
const scriptSrcRef = useRef(scriptSrc);
|
|
5756
5912
|
scriptSrcRef.current = scriptSrc;
|
|
5913
|
+
const htmlRef = useRef(html);
|
|
5914
|
+
htmlRef.current = html;
|
|
5757
5915
|
const cspRef = useRef(csp);
|
|
5758
5916
|
cspRef.current = csp;
|
|
5759
5917
|
const hostContextRef = useRef(hostContext);
|
|
@@ -5803,9 +5961,20 @@ function IframeResource({ src, scriptSrc, hostContext, toolInput, toolInputParti
|
|
|
5803
5961
|
onSandboxReady: () => {
|
|
5804
5962
|
const currentSrc = srcRef.current;
|
|
5805
5963
|
const currentScriptSrc = scriptSrcRef.current;
|
|
5964
|
+
const currentHtml = htmlRef.current;
|
|
5806
5965
|
const currentHost = hostRef.current;
|
|
5807
5966
|
if (!currentHost) return;
|
|
5808
|
-
if (
|
|
5967
|
+
if (currentHtml) {
|
|
5968
|
+
const finalHtml = injectInfraScripts(currentHtml, injectOpenAIRuntimeRef.current ? MOCK_OPENAI_RUNTIME_SCRIPT : void 0);
|
|
5969
|
+
currentHost.sendSandboxResourceReady({
|
|
5970
|
+
html: finalHtml,
|
|
5971
|
+
sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
|
|
5972
|
+
});
|
|
5973
|
+
if (iframeRef.current) {
|
|
5974
|
+
iframeRef.current.style.opacity = "1";
|
|
5975
|
+
iframeRef.current.style.transition = "opacity 100ms";
|
|
5976
|
+
}
|
|
5977
|
+
} else if (currentScriptSrc) {
|
|
5809
5978
|
const absoluteScriptSrc = currentScriptSrc.startsWith("/") ? `${window.location.origin}${currentScriptSrc}` : currentScriptSrc;
|
|
5810
5979
|
const cspPolicy = generateCSP(cspRef.current, absoluteScriptSrc);
|
|
5811
5980
|
const appHtml = generateScriptHtml(absoluteScriptSrc, hostContextRef.current?.theme ?? "dark", cspPolicy, injectOpenAIRuntimeRef.current ? MOCK_OPENAI_RUNTIME_SCRIPT : void 0);
|
|
@@ -5876,7 +6045,17 @@ function IframeResource({ src, scriptSrc, hostContext, toolInput, toolInputParti
|
|
|
5876
6045
|
const borderStyle = prefersBorder ? { border: "1px solid var(--color-border-primary, #e5e7eb)" } : { border: "none" };
|
|
5877
6046
|
const sandboxSrc = useMemo(() => {
|
|
5878
6047
|
if (!sandboxUrl) return void 0;
|
|
5879
|
-
|
|
6048
|
+
let url;
|
|
6049
|
+
try {
|
|
6050
|
+
const parsed = new URL(sandboxUrl);
|
|
6051
|
+
url = parsed.pathname && parsed.pathname !== "/" ? parsed : new URL("/proxy", sandboxUrl);
|
|
6052
|
+
} catch {
|
|
6053
|
+
return;
|
|
6054
|
+
}
|
|
6055
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
6056
|
+
console.warn("[IframeResource] Ignoring non-http(s) sandboxUrl:", sandboxUrl);
|
|
6057
|
+
return;
|
|
6058
|
+
}
|
|
5880
6059
|
if (injectOpenAIRuntime) url.searchParams.set("platform", "chatgpt");
|
|
5881
6060
|
return url.toString();
|
|
5882
6061
|
}, [sandboxUrl, injectOpenAIRuntime]);
|
|
@@ -6316,6 +6495,7 @@ function useInspectorState({ simulations, defaultHost = "chatgpt" }) {
|
|
|
6316
6495
|
}, [toolResult, modelContext]);
|
|
6317
6496
|
const resourceUrl = selectedSim?.resourceUrl;
|
|
6318
6497
|
const resourceScript = selectedSim?.resourceScript;
|
|
6498
|
+
const resourceHtml = selectedSim?.resourceHtml;
|
|
6319
6499
|
const csp = selectedSim?.resource ? extractResourceCSP(selectedSim.resource) : void 0;
|
|
6320
6500
|
const resourceMeta = (selectedSim?.resource?._meta)?.ui;
|
|
6321
6501
|
return {
|
|
@@ -6382,6 +6562,7 @@ function useInspectorState({ simulations, defaultHost = "chatgpt" }) {
|
|
|
6382
6562
|
handleUpdateModelContext,
|
|
6383
6563
|
resourceUrl,
|
|
6384
6564
|
resourceScript,
|
|
6565
|
+
resourceHtml,
|
|
6385
6566
|
csp,
|
|
6386
6567
|
permissions: resourceMeta?.permissions,
|
|
6387
6568
|
prefersBorder: resourceMeta?.prefersBorder ?? false,
|
|
@@ -6392,6 +6573,40 @@ function useInspectorState({ simulations, defaultHost = "chatgpt" }) {
|
|
|
6392
6573
|
};
|
|
6393
6574
|
}
|
|
6394
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
|
|
6395
6610
|
//#region src/inspector/use-mcp-connection.ts
|
|
6396
6611
|
/**
|
|
6397
6612
|
* Hook for managing MCP server connection status via the dev server proxy.
|
|
@@ -6404,7 +6619,7 @@ function useInspectorState({ simulations, defaultHost = "chatgpt" }) {
|
|
|
6404
6619
|
* once (or safely twice with cancellation), while explicit `reconnect()` calls
|
|
6405
6620
|
* are triggered by the Inspector's URL-change effect.
|
|
6406
6621
|
*/
|
|
6407
|
-
function useMcpConnection(initialServerUrl) {
|
|
6622
|
+
function useMcpConnection(initialServerUrl, inspectorApiBaseUrl) {
|
|
6408
6623
|
const [status, setStatus] = useState(initialServerUrl ? "connecting" : "disconnected");
|
|
6409
6624
|
const [error, setError] = useState();
|
|
6410
6625
|
const [simulations, setSimulations] = useState();
|
|
@@ -6416,7 +6631,8 @@ function useMcpConnection(initialServerUrl) {
|
|
|
6416
6631
|
try {
|
|
6417
6632
|
const body = { url };
|
|
6418
6633
|
if (auth && auth.type !== "none") body.auth = auth;
|
|
6419
|
-
const
|
|
6634
|
+
const endpoint = inspectorApiEndpoint("/__sunpeak/connect", inspectorApiBaseUrl);
|
|
6635
|
+
const res = await fetch(endpoint, {
|
|
6420
6636
|
method: "POST",
|
|
6421
6637
|
headers: { "Content-Type": "application/json" },
|
|
6422
6638
|
body: JSON.stringify(body)
|
|
@@ -6424,7 +6640,7 @@ function useMcpConnection(initialServerUrl) {
|
|
|
6424
6640
|
if (!res.ok) {
|
|
6425
6641
|
let message;
|
|
6426
6642
|
try {
|
|
6427
|
-
const json = await res
|
|
6643
|
+
const json = await readInspectorJson(res, endpoint);
|
|
6428
6644
|
if (json.error) message = json.error;
|
|
6429
6645
|
} catch {}
|
|
6430
6646
|
if (!message) if (res.status === 404) message = "Server not found at this URL. Check the URL and make sure the server is running.";
|
|
@@ -6432,9 +6648,9 @@ function useMcpConnection(initialServerUrl) {
|
|
|
6432
6648
|
else message = `Connection failed (${res.status})`;
|
|
6433
6649
|
throw new Error(message);
|
|
6434
6650
|
}
|
|
6435
|
-
const data = await res
|
|
6651
|
+
const data = await readInspectorJson(res, endpoint);
|
|
6436
6652
|
setStatus("connected");
|
|
6437
|
-
setSimulations(data.simulations
|
|
6653
|
+
setSimulations(resolveInspectorResourceUrls(data.simulations, inspectorApiBaseUrl));
|
|
6438
6654
|
} catch (err) {
|
|
6439
6655
|
let message = err instanceof Error ? err.message : String(err);
|
|
6440
6656
|
if (err instanceof TypeError && message === "Failed to fetch") message = "Cannot reach MCP server. Is it running?";
|
|
@@ -6442,20 +6658,21 @@ function useMcpConnection(initialServerUrl) {
|
|
|
6442
6658
|
setStatus("error");
|
|
6443
6659
|
setSimulations(void 0);
|
|
6444
6660
|
}
|
|
6445
|
-
}, []);
|
|
6661
|
+
}, [inspectorApiBaseUrl]);
|
|
6446
6662
|
const setConnected = useCallback((sims) => {
|
|
6447
6663
|
setHasReconnected(true);
|
|
6448
6664
|
setStatus("connected");
|
|
6449
6665
|
setError(void 0);
|
|
6450
|
-
setSimulations(sims);
|
|
6451
|
-
}, []);
|
|
6666
|
+
setSimulations(resolveInspectorResourceUrls(sims, inspectorApiBaseUrl));
|
|
6667
|
+
}, [inspectorApiBaseUrl]);
|
|
6452
6668
|
useEffect(() => {
|
|
6453
6669
|
if (!initialServerUrl) return;
|
|
6454
6670
|
let cancelled = false;
|
|
6455
6671
|
setStatus("connecting");
|
|
6456
6672
|
(async () => {
|
|
6457
6673
|
try {
|
|
6458
|
-
const
|
|
6674
|
+
const endpoint = inspectorApiEndpoint("/__sunpeak/list-tools", inspectorApiBaseUrl);
|
|
6675
|
+
const res = await fetch(endpoint);
|
|
6459
6676
|
if (cancelled) return;
|
|
6460
6677
|
if (!res.ok) {
|
|
6461
6678
|
const msg = res.status === 404 ? "MCP server not reachable. Is it running?" : `Health check failed (${res.status}). Check the MCP server logs.`;
|
|
@@ -6484,7 +6701,14 @@ function useMcpConnection(initialServerUrl) {
|
|
|
6484
6701
|
//#endregion
|
|
6485
6702
|
//#region src/inspector/theme-provider.tsx
|
|
6486
6703
|
var ThemeProviderContext = React.createContext(void 0);
|
|
6487
|
-
/**
|
|
6704
|
+
/**
|
|
6705
|
+
* Default theme applier: sets `data-theme` on `document.documentElement`.
|
|
6706
|
+
* Kept for callers using `ThemeProvider` outside the bundled `<Inspector />`
|
|
6707
|
+
* (e.g. custom-inspector builds composed from this package's primitives).
|
|
6708
|
+
* The bundled Inspector overrides this with a no-op applier and applies
|
|
6709
|
+
* theme to its own root element, so embedding it inside a host React app
|
|
6710
|
+
* leaves the host's document attributes untouched.
|
|
6711
|
+
*/
|
|
6488
6712
|
function defaultApplyTheme(theme) {
|
|
6489
6713
|
if (typeof document !== "undefined") document.documentElement.setAttribute("data-theme", theme);
|
|
6490
6714
|
}
|
|
@@ -6527,7 +6751,7 @@ function ChevronRightIcon() {
|
|
|
6527
6751
|
})
|
|
6528
6752
|
});
|
|
6529
6753
|
}
|
|
6530
|
-
function SimpleSidebar({ children, controls, headerRight }) {
|
|
6754
|
+
function SimpleSidebar({ children, controls, headerRight, rootRef, fillParent = false }) {
|
|
6531
6755
|
const [isDrawerOpen, setIsDrawerOpen] = React.useState(false);
|
|
6532
6756
|
const [sidebarWidth, setSidebarWidth] = React.useState(DEFAULT_SIDEBAR_WIDTH);
|
|
6533
6757
|
const [isResizing, setIsResizing] = React.useState(false);
|
|
@@ -6552,7 +6776,8 @@ function SimpleSidebar({ children, controls, headerRight }) {
|
|
|
6552
6776
|
};
|
|
6553
6777
|
}, [isResizing]);
|
|
6554
6778
|
return /* @__PURE__ */ jsxs("div", {
|
|
6555
|
-
|
|
6779
|
+
ref: rootRef,
|
|
6780
|
+
className: `sunpeak-inspector-root flex ${fillParent ? "h-full w-full" : "h-screen w-full"} overflow-hidden relative`,
|
|
6556
6781
|
children: [
|
|
6557
6782
|
isResizing && /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-50 cursor-col-resize" }),
|
|
6558
6783
|
isDrawerOpen && /* @__PURE__ */ jsx("div", {
|
|
@@ -6882,13 +7107,85 @@ function resolveServerToolResult(mock, args) {
|
|
|
6882
7107
|
for (const entry of mock) if (Object.entries(entry.when).every(([key, value]) => args != null && args[key] === value)) return entry.result;
|
|
6883
7108
|
}
|
|
6884
7109
|
//#endregion
|
|
7110
|
+
//#region src/inspector/app-flatten.ts
|
|
7111
|
+
/** Pull the output-template URI off a tool's _meta, if present. */
|
|
7112
|
+
function getOutputTemplate(toolMeta) {
|
|
7113
|
+
if (!toolMeta || typeof toolMeta !== "object") return void 0;
|
|
7114
|
+
const openai = toolMeta.openai;
|
|
7115
|
+
if (!openai || typeof openai !== "object") return void 0;
|
|
7116
|
+
const template = openai.outputTemplate;
|
|
7117
|
+
return typeof template === "string" ? template : void 0;
|
|
7118
|
+
}
|
|
7119
|
+
/** Build an MCP-shaped `Resource` from the embedder's input. Used purely for
|
|
7120
|
+
* sidebar metadata (CSP, permissions, prefersBorder); the actual HTML render
|
|
7121
|
+
* goes through `resourceHtml` on the resulting Simulation. */
|
|
7122
|
+
function toMcpResource(r) {
|
|
7123
|
+
return {
|
|
7124
|
+
uri: r.uri,
|
|
7125
|
+
mimeType: r.mimeType ?? "text/html",
|
|
7126
|
+
name: r.uri,
|
|
7127
|
+
...r._meta ? { _meta: r._meta } : {}
|
|
7128
|
+
};
|
|
7129
|
+
}
|
|
7130
|
+
/**
|
|
7131
|
+
* Flatten an `InspectorApp` to the `Record<string, Simulation>` shape the
|
|
7132
|
+
* Inspector consumes internally. Returns an empty map if `app` is missing.
|
|
7133
|
+
*/
|
|
7134
|
+
function flattenAppToSimulations(app) {
|
|
7135
|
+
if (!app) return {};
|
|
7136
|
+
const result = {};
|
|
7137
|
+
const resourcesByUri = /* @__PURE__ */ new Map();
|
|
7138
|
+
for (const r of app.resources) {
|
|
7139
|
+
if (resourcesByUri.has(r.uri)) console.warn(`[Inspector] Duplicate resource URI '${r.uri}' in app.resources — the second entry replaces the first.`);
|
|
7140
|
+
resourcesByUri.set(r.uri, r);
|
|
7141
|
+
}
|
|
7142
|
+
for (const appTool of app.tools) {
|
|
7143
|
+
const uri = getOutputTemplate(appTool.tool._meta);
|
|
7144
|
+
if (!uri) continue;
|
|
7145
|
+
const resource = resourcesByUri.get(uri);
|
|
7146
|
+
if (!resource) continue;
|
|
7147
|
+
const mcpResource = toMcpResource(resource);
|
|
7148
|
+
const sims = appTool.simulations && appTool.simulations.length > 0 ? appTool.simulations : [{ name: appTool.tool.name }];
|
|
7149
|
+
for (const sim of sims) {
|
|
7150
|
+
const key = `${appTool.tool.name}__${sim.name}`;
|
|
7151
|
+
if (key in result) console.warn(`[Inspector] Duplicate simulation name '${sim.name}' under tool '${appTool.tool.name}' — the second entry replaces the first.`);
|
|
7152
|
+
result[key] = {
|
|
7153
|
+
name: key,
|
|
7154
|
+
displayName: sim.name,
|
|
7155
|
+
resourceHtml: resource.html,
|
|
7156
|
+
userMessage: sim.userMessage,
|
|
7157
|
+
tool: appTool.tool,
|
|
7158
|
+
resource: mcpResource,
|
|
7159
|
+
toolInput: sim.toolInput,
|
|
7160
|
+
toolResult: sim.toolResult,
|
|
7161
|
+
serverTools: sim.serverTools
|
|
7162
|
+
};
|
|
7163
|
+
}
|
|
7164
|
+
}
|
|
7165
|
+
return result;
|
|
7166
|
+
}
|
|
7167
|
+
//#endregion
|
|
6885
7168
|
//#region src/inspector/inspector.tsx
|
|
6886
7169
|
var DOCS_BASE_URL = "https://sunpeak.ai/docs";
|
|
6887
7170
|
/** Check whether a simulation has user-authored fixture data. */
|
|
6888
7171
|
function hasFixtureData(sim) {
|
|
6889
7172
|
return sim.toolResult != null || sim.toolInput != null || sim.serverTools != null;
|
|
6890
7173
|
}
|
|
6891
|
-
|
|
7174
|
+
var EMPTY_SIMULATIONS = Object.freeze({});
|
|
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 }) {
|
|
7176
|
+
const initialSimulations = React.useMemo(() => app ? flattenAppToSimulations(app) : initialSimulationsProp, [app, initialSimulationsProp]);
|
|
7177
|
+
const appName = app?.name ?? appNameProp ?? "Sunpeak";
|
|
7178
|
+
const appIcon = app?.icon ?? appIconProp;
|
|
7179
|
+
const isEmbedded = !!app;
|
|
7180
|
+
const conflictWarnedRef = React.useRef(false);
|
|
7181
|
+
React.useEffect(() => {
|
|
7182
|
+
if (conflictWarnedRef.current) return;
|
|
7183
|
+
if (app && initialSimulationsProp && Object.keys(initialSimulationsProp).length > 0) {
|
|
7184
|
+
conflictWarnedRef.current = true;
|
|
7185
|
+
console.warn("[Inspector] Both `app` and `simulations` were provided. `app` takes precedence; `simulations` is ignored.");
|
|
7186
|
+
}
|
|
7187
|
+
}, [app, initialSimulationsProp]);
|
|
7188
|
+
const rootRef = React.useRef(null);
|
|
6892
7189
|
const [simulations, setSimulations] = React.useState(initialSimulations);
|
|
6893
7190
|
React.useEffect(() => {
|
|
6894
7191
|
setSimulations(initialSimulations);
|
|
@@ -6971,13 +7268,14 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
6971
7268
|
const [oauthClientSecret, setOauthClientSecret] = React.useState("");
|
|
6972
7269
|
const [oauthStatus, setOauthStatus] = React.useState("none");
|
|
6973
7270
|
const [oauthError, setOauthError] = React.useState();
|
|
6974
|
-
const connection = useMcpConnection(mcpServerUrl || void 0);
|
|
7271
|
+
const connection = useMcpConnection(isEmbedded ? void 0 : mcpServerUrl || void 0, inspectorApiBaseUrl);
|
|
6975
7272
|
const [prodResources, setProdResources] = React.useState(state.urlProdResources ?? defaultProdResources);
|
|
6976
7273
|
const showSidebar = state.urlSidebar !== false;
|
|
6977
7274
|
const showDevOverlay = state.urlDevOverlay !== false;
|
|
6978
7275
|
const [isRunning, setIsRunning] = React.useState(false);
|
|
6979
7276
|
const [hasRun, setHasRun] = React.useState(false);
|
|
6980
7277
|
const [showCheck, setShowCheck] = React.useState(false);
|
|
7278
|
+
const [serverPreviewGeneration, setServerPreviewGeneration] = React.useState(0);
|
|
6981
7279
|
const checkTimerRef = React.useRef(void 0);
|
|
6982
7280
|
const oauthCleanupRef = React.useRef(void 0);
|
|
6983
7281
|
React.useEffect(() => {
|
|
@@ -7013,7 +7311,8 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7013
7311
|
setOauthError(void 0);
|
|
7014
7312
|
const popup = window.open("about:blank", `sunpeak-oauth-${Date.now()}`, "width=600,height=700,popup=yes");
|
|
7015
7313
|
try {
|
|
7016
|
-
const
|
|
7314
|
+
const endpoint = inspectorApiEndpoint("/__sunpeak/oauth/start", inspectorApiBaseUrl);
|
|
7315
|
+
const res = await fetch(endpoint, {
|
|
7017
7316
|
method: "POST",
|
|
7018
7317
|
headers: { "Content-Type": "application/json" },
|
|
7019
7318
|
body: JSON.stringify({
|
|
@@ -7023,15 +7322,12 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7023
7322
|
clientSecret: oauthClientSecret || void 0
|
|
7024
7323
|
})
|
|
7025
7324
|
});
|
|
7325
|
+
const data = await readInspectorJson(res, endpoint);
|
|
7026
7326
|
if (!res.ok) {
|
|
7027
7327
|
let message = `OAuth start failed (${res.status})`;
|
|
7028
|
-
|
|
7029
|
-
const json = await res.json();
|
|
7030
|
-
if (json.error) message = json.error;
|
|
7031
|
-
} catch {}
|
|
7328
|
+
if (data.error) message = data.error;
|
|
7032
7329
|
throw new Error(message);
|
|
7033
7330
|
}
|
|
7034
|
-
const data = await res.json();
|
|
7035
7331
|
if (data.error) {
|
|
7036
7332
|
popup?.close();
|
|
7037
7333
|
setOauthError(data.error);
|
|
@@ -7045,12 +7341,22 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7045
7341
|
return;
|
|
7046
7342
|
}
|
|
7047
7343
|
if (data.status === "redirect" && data.authUrl) {
|
|
7344
|
+
let parsedAuthUrl = null;
|
|
7345
|
+
try {
|
|
7346
|
+
parsedAuthUrl = new URL(data.authUrl);
|
|
7347
|
+
} catch {}
|
|
7348
|
+
if (!parsedAuthUrl || parsedAuthUrl.protocol !== "http:" && parsedAuthUrl.protocol !== "https:") {
|
|
7349
|
+
popup?.close();
|
|
7350
|
+
setOauthError("OAuth authorization URL is not a valid http(s) URL.");
|
|
7351
|
+
setOauthStatus("error");
|
|
7352
|
+
return;
|
|
7353
|
+
}
|
|
7048
7354
|
if (!popup || popup.closed) {
|
|
7049
7355
|
setOauthError("Popup was blocked. Allow popups for this site and try again.");
|
|
7050
7356
|
setOauthStatus("error");
|
|
7051
7357
|
return;
|
|
7052
7358
|
}
|
|
7053
|
-
popup.location.href =
|
|
7359
|
+
popup.location.href = parsedAuthUrl.toString();
|
|
7054
7360
|
let checkClosed;
|
|
7055
7361
|
let bc;
|
|
7056
7362
|
const cleanup = () => {
|
|
@@ -7102,11 +7408,14 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7102
7408
|
oauthClientId,
|
|
7103
7409
|
oauthClientSecret,
|
|
7104
7410
|
demoMode,
|
|
7105
|
-
connection
|
|
7411
|
+
connection,
|
|
7412
|
+
inspectorApiBaseUrl
|
|
7106
7413
|
]);
|
|
7107
7414
|
React.useEffect(() => {
|
|
7108
|
-
if (connection.simulations)
|
|
7109
|
-
|
|
7415
|
+
if (connection.simulations) {
|
|
7416
|
+
setSimulations(connection.simulations);
|
|
7417
|
+
setServerPreviewGeneration((generation) => generation + 1);
|
|
7418
|
+
} else if (connection.status === "error" && connection.hasReconnected) setSimulations({});
|
|
7110
7419
|
}, [
|
|
7111
7420
|
connection.simulations,
|
|
7112
7421
|
connection.status,
|
|
@@ -7239,15 +7548,23 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7239
7548
|
displayMode,
|
|
7240
7549
|
setDisplayMode
|
|
7241
7550
|
]);
|
|
7242
|
-
React.
|
|
7243
|
-
const vars = activeShell?.styleVariables;
|
|
7244
|
-
if (!vars) return;
|
|
7245
|
-
const root = document.documentElement;
|
|
7246
|
-
for (const [key, value] of Object.entries(vars)) if (value) root.style.setProperty(key, value);
|
|
7247
|
-
}, [activeShell]);
|
|
7551
|
+
const prevStyleVarKeysRef = React.useRef([]);
|
|
7248
7552
|
const prevPageStyleKeysRef = React.useRef([]);
|
|
7249
7553
|
React.useLayoutEffect(() => {
|
|
7250
|
-
const root =
|
|
7554
|
+
const root = rootRef.current;
|
|
7555
|
+
if (!root) return;
|
|
7556
|
+
root.setAttribute("data-theme", state.theme);
|
|
7557
|
+
root.style.colorScheme = state.theme;
|
|
7558
|
+
for (const key of prevStyleVarKeysRef.current) root.style.removeProperty(key);
|
|
7559
|
+
const vars = activeShell?.styleVariables;
|
|
7560
|
+
if (vars) {
|
|
7561
|
+
const keys = [];
|
|
7562
|
+
for (const [key, value] of Object.entries(vars)) if (value) {
|
|
7563
|
+
root.style.setProperty(key, value);
|
|
7564
|
+
keys.push(key);
|
|
7565
|
+
}
|
|
7566
|
+
prevStyleVarKeysRef.current = keys;
|
|
7567
|
+
} else prevStyleVarKeysRef.current = [];
|
|
7251
7568
|
for (const key of prevPageStyleKeysRef.current) root.style.removeProperty(key);
|
|
7252
7569
|
const pageStyles = activeShell?.pageStyles;
|
|
7253
7570
|
if (pageStyles) {
|
|
@@ -7258,7 +7575,7 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7258
7575
|
}
|
|
7259
7576
|
prevPageStyleKeysRef.current = keys;
|
|
7260
7577
|
} else prevPageStyleKeysRef.current = [];
|
|
7261
|
-
}, [activeShell]);
|
|
7578
|
+
}, [activeShell, state.theme]);
|
|
7262
7579
|
React.useLayoutEffect(() => {
|
|
7263
7580
|
const fontCss = activeShell?.fontCss;
|
|
7264
7581
|
const id = "sunpeak-host-fonts";
|
|
@@ -7349,7 +7666,7 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7349
7666
|
children: /* @__PURE__ */ jsx("span", {
|
|
7350
7667
|
className: "text-sm text-center max-w-xs",
|
|
7351
7668
|
style: { color: "var(--color-text-secondary)" },
|
|
7352
|
-
children: isError ? "Could not connect to MCP server" : isConnected ? "No tools with UI resources found on this server" : serverUrl ? "Connecting…" : "Enter an MCP server URL to get started"
|
|
7669
|
+
children: isEmbedded ? "No tools with UI resources in this app" : isError ? "Could not connect to MCP server" : isConnected ? "No tools with UI resources found on this server" : serverUrl ? "Connecting…" : "Enter an MCP server URL to get started"
|
|
7353
7670
|
})
|
|
7354
7671
|
});
|
|
7355
7672
|
} else if (showEmptyState) content = /* @__PURE__ */ jsx("div", {
|
|
@@ -7374,6 +7691,30 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7374
7691
|
children: "Building…"
|
|
7375
7692
|
})
|
|
7376
7693
|
});
|
|
7694
|
+
else if (state.resourceHtml) content = /* @__PURE__ */ jsx("div", {
|
|
7695
|
+
className: "h-full w-full",
|
|
7696
|
+
style: { background: iframeBg },
|
|
7697
|
+
children: /* @__PURE__ */ jsx(IframeResource, {
|
|
7698
|
+
html: state.resourceHtml,
|
|
7699
|
+
hostContext,
|
|
7700
|
+
toolInput: state.toolInput,
|
|
7701
|
+
toolResult: state.effectiveToolResult,
|
|
7702
|
+
hostOptions: {
|
|
7703
|
+
hostInfo: activeShell?.hostInfo,
|
|
7704
|
+
hostCapabilities: activeShell?.hostCapabilities,
|
|
7705
|
+
onDisplayModeChange: state.handleDisplayModeChange,
|
|
7706
|
+
onUpdateModelContext: state.handleUpdateModelContext,
|
|
7707
|
+
onCallTool: handleCallTool
|
|
7708
|
+
},
|
|
7709
|
+
permissions: state.permissions,
|
|
7710
|
+
prefersBorder: state.prefersBorder,
|
|
7711
|
+
onDisplayModeReady: state.handleDisplayModeReady,
|
|
7712
|
+
debugInjectState: state.modelContext,
|
|
7713
|
+
injectOpenAIRuntime: state.activeHost === "chatgpt",
|
|
7714
|
+
sandboxUrl,
|
|
7715
|
+
className: "h-full w-full"
|
|
7716
|
+
}, `${state.activeHost}-${state.selectedSimulationName}-html`)
|
|
7717
|
+
});
|
|
7377
7718
|
else if (effectiveResourceUrl) content = /* @__PURE__ */ jsx("div", {
|
|
7378
7719
|
className: "h-full w-full",
|
|
7379
7720
|
style: { background: iframeBg },
|
|
@@ -7396,7 +7737,7 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7396
7737
|
injectOpenAIRuntime: state.activeHost === "chatgpt",
|
|
7397
7738
|
sandboxUrl,
|
|
7398
7739
|
className: "h-full w-full"
|
|
7399
|
-
}, `${state.activeHost}-${state.selectedSimulationName}-${effectiveResourceUrl}-${prodResources}-${prodResourcesGeneration}`)
|
|
7740
|
+
}, `${state.activeHost}-${state.selectedSimulationName}-${effectiveResourceUrl}-${prodResources}-${prodResourcesGeneration}-${serverPreviewGeneration}`)
|
|
7400
7741
|
});
|
|
7401
7742
|
else if (!prodResources && state.resourceScript) content = /* @__PURE__ */ jsx("div", {
|
|
7402
7743
|
className: "h-full w-full",
|
|
@@ -7424,7 +7765,7 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7424
7765
|
}, `${state.activeHost}-${state.selectedSimulationName}-${state.resourceScript}`)
|
|
7425
7766
|
});
|
|
7426
7767
|
else content = children;
|
|
7427
|
-
const applyTheme =
|
|
7768
|
+
const applyTheme = React.useCallback((_theme) => {}, []);
|
|
7428
7769
|
const runButton = !demoMode && onCallTool && currentSim && activeSimulationName === null ? /* @__PURE__ */ jsxs("button", {
|
|
7429
7770
|
type: "button",
|
|
7430
7771
|
onClick: handleRun,
|
|
@@ -7464,11 +7805,13 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7464
7805
|
headerAction: runButton,
|
|
7465
7806
|
children: content
|
|
7466
7807
|
}) : content;
|
|
7808
|
+
const rootSizing = isEmbedded ? "h-full w-full" : "h-screen w-screen";
|
|
7467
7809
|
if (!showSidebar) return /* @__PURE__ */ jsx(ThemeProvider, {
|
|
7468
7810
|
theme: state.theme,
|
|
7469
7811
|
applyTheme,
|
|
7470
7812
|
children: /* @__PURE__ */ jsx("div", {
|
|
7471
|
-
|
|
7813
|
+
ref: rootRef,
|
|
7814
|
+
className: `sunpeak-inspector-root flex ${rootSizing}`,
|
|
7472
7815
|
children: conversationContent
|
|
7473
7816
|
})
|
|
7474
7817
|
});
|
|
@@ -7476,10 +7819,12 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7476
7819
|
theme: state.theme,
|
|
7477
7820
|
applyTheme,
|
|
7478
7821
|
children: [/* @__PURE__ */ jsx(SimpleSidebar, {
|
|
7822
|
+
rootRef,
|
|
7823
|
+
fillParent: isEmbedded,
|
|
7479
7824
|
controls: /* @__PURE__ */ jsxs("div", {
|
|
7480
7825
|
className: "space-y-1",
|
|
7481
7826
|
children: [
|
|
7482
|
-
/* @__PURE__ */ jsx(SidebarControl, {
|
|
7827
|
+
!isEmbedded && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SidebarControl, {
|
|
7483
7828
|
label: /* @__PURE__ */ jsxs("span", {
|
|
7484
7829
|
className: "flex items-center gap-1.5",
|
|
7485
7830
|
children: ["MCP Server", serverUrl && !demoMode && /* @__PURE__ */ jsx("span", {
|
|
@@ -7498,8 +7843,7 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7498
7843
|
placeholder: "http://localhost:8000/mcp",
|
|
7499
7844
|
disabled: demoMode
|
|
7500
7845
|
})
|
|
7501
|
-
}),
|
|
7502
|
-
!demoMode && /* @__PURE__ */ jsx(SidebarCollapsibleControl, {
|
|
7846
|
+
}), !demoMode && /* @__PURE__ */ jsx(SidebarCollapsibleControl, {
|
|
7503
7847
|
label: "Authentication",
|
|
7504
7848
|
defaultCollapsed: authType === "none",
|
|
7505
7849
|
children: /* @__PURE__ */ jsxs("div", {
|
|
@@ -7584,8 +7928,8 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7584
7928
|
})
|
|
7585
7929
|
]
|
|
7586
7930
|
})
|
|
7587
|
-
}, `auth-${authType === "none" ? "none" : "active"}`),
|
|
7588
|
-
!hideInspectorModes && !demoMode && /* @__PURE__ */ jsx(SidebarCheckbox, {
|
|
7931
|
+
}, `auth-${authType === "none" ? "none" : "active"}`)] }),
|
|
7932
|
+
!hideInspectorModes && !demoMode && !isEmbedded && /* @__PURE__ */ jsx(SidebarCheckbox, {
|
|
7589
7933
|
checked: prodResources,
|
|
7590
7934
|
onChange: setProdResources,
|
|
7591
7935
|
label: "Prod Resources",
|
|
@@ -7636,7 +7980,7 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
7636
7980
|
label: selectedToolInfo && selectedToolInfo.fixtureSimNames.length > 0 ? "None (call server)" : "None"
|
|
7637
7981
|
}], ...(selectedToolInfo?.fixtureSimNames ?? []).map((simName) => ({
|
|
7638
7982
|
value: simName,
|
|
7639
|
-
label: simName
|
|
7983
|
+
label: simulations[simName]?.displayName ?? simName
|
|
7640
7984
|
}))]
|
|
7641
7985
|
})
|
|
7642
7986
|
})]
|
|
@@ -8016,6 +8360,6 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
8016
8360
|
});
|
|
8017
8361
|
}
|
|
8018
8362
|
//#endregion
|
|
8019
|
-
export {
|
|
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 };
|
|
8020
8364
|
|
|
8021
|
-
//# sourceMappingURL=inspector-
|
|
8365
|
+
//# sourceMappingURL=inspector-B1355aXh.js.map
|