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