sunpeak 0.13.6 → 0.13.8

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.
Files changed (98) hide show
  1. package/dist/chatgpt/conversation.d.ts +1 -7
  2. package/dist/chatgpt/iframe-resource.d.ts +7 -8
  3. package/dist/chatgpt/index.cjs +2 -1
  4. package/dist/chatgpt/index.cjs.map +1 -1
  5. package/dist/chatgpt/index.d.ts +1 -1
  6. package/dist/chatgpt/index.js +4 -3
  7. package/dist/chatgpt/mcp-app-host.d.ts +5 -0
  8. package/dist/{index-B_In_BWg.cjs → index-B9MMk69u.cjs} +57 -56
  9. package/dist/index-B9MMk69u.cjs.map +1 -0
  10. package/dist/{index-CkEAx7FS.js → index-DqOCq5r8.js} +56 -55
  11. package/dist/index-DqOCq5r8.js.map +1 -0
  12. package/dist/index.cjs +1 -1
  13. package/dist/index.js +2 -2
  14. package/package.json +1 -1
  15. package/template/.sunpeak/resource-loader.html +0 -13
  16. package/template/dist/albums/albums.json +1 -1
  17. package/template/dist/carousel/carousel.json +1 -1
  18. package/template/dist/map/map.json +1 -1
  19. package/template/dist/review/review.json +1 -1
  20. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_SegmentedControl.js +3 -3
  21. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Select.js +9 -9
  22. package/template/node_modules/.vite/deps/_metadata.json +34 -34
  23. package/template/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  24. package/dist/index-B_In_BWg.cjs.map +0 -1
  25. package/dist/index-CkEAx7FS.js.map +0 -1
  26. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@modelcontextprotocol_ext-apps.js +0 -0
  27. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@modelcontextprotocol_ext-apps.js.map +0 -0
  28. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@modelcontextprotocol_ext-apps_app-bridge.js +0 -0
  29. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@modelcontextprotocol_ext-apps_app-bridge.js.map +0 -0
  30. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@modelcontextprotocol_ext-apps_react.js +0 -0
  31. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@modelcontextprotocol_ext-apps_react.js.map +0 -0
  32. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Avatar.js +0 -0
  33. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Avatar.js.map +0 -0
  34. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Button.js +0 -0
  35. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Button.js.map +0 -0
  36. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Checkbox.js +0 -0
  37. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Checkbox.js.map +0 -0
  38. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Icon.js +0 -0
  39. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Icon.js.map +0 -0
  40. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Input.js +0 -0
  41. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Input.js.map +0 -0
  42. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_SegmentedControl.js +0 -0
  43. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_SegmentedControl.js.map +0 -0
  44. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Select.js +0 -0
  45. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Select.js.map +0 -0
  46. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Textarea.js +0 -0
  47. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_components_Textarea.js.map +0 -0
  48. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_theme.js +0 -0
  49. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/@openai_apps-sdk-ui_theme.js.map +0 -0
  50. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-3FUH6LFP.js +0 -0
  51. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-3FUH6LFP.js.map +0 -0
  52. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-4EQ7FTMQ.js +0 -0
  53. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-4EQ7FTMQ.js.map +0 -0
  54. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-4WVD247F.js +0 -0
  55. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-4WVD247F.js.map +0 -0
  56. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-ABGJ7IDC.js +0 -0
  57. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-ABGJ7IDC.js.map +0 -0
  58. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-DP4XHQAG.js +0 -0
  59. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-DP4XHQAG.js.map +0 -0
  60. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-EGRHWZRV.js +0 -0
  61. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-EGRHWZRV.js.map +0 -0
  62. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-EHI2XMPP.js +0 -0
  63. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-EHI2XMPP.js.map +0 -0
  64. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-JWMBYPFX.js +0 -0
  65. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-JWMBYPFX.js.map +0 -0
  66. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-PZDCUP6P.js +0 -0
  67. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-PZDCUP6P.js.map +0 -0
  68. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-Q2RBUOJ3.js +0 -0
  69. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-Q2RBUOJ3.js.map +0 -0
  70. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-SPDZ46BB.js +0 -0
  71. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-SPDZ46BB.js.map +0 -0
  72. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-WEIC4XKX.js +0 -0
  73. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-WEIC4XKX.js.map +0 -0
  74. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-WSHFT23M.js +0 -0
  75. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-WSHFT23M.js.map +0 -0
  76. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-XQARMNNG.js +0 -0
  77. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/chunk-XQARMNNG.js.map +0 -0
  78. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/clsx.js +0 -0
  79. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/clsx.js.map +0 -0
  80. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/embla-carousel-react.js +0 -0
  81. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/embla-carousel-react.js.map +0 -0
  82. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/embla-carousel-wheel-gestures.js +0 -0
  83. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/embla-carousel-wheel-gestures.js.map +0 -0
  84. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/mapbox-gl.js +0 -0
  85. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/mapbox-gl.js.map +0 -0
  86. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/package.json +0 -0
  87. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/react-dom.js +0 -0
  88. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/react-dom.js.map +0 -0
  89. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/react-dom_client.js +0 -0
  90. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/react-dom_client.js.map +0 -0
  91. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/react.js +0 -0
  92. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/react.js.map +0 -0
  93. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/react_jsx-dev-runtime.js +0 -0
  94. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/react_jsx-dev-runtime.js.map +0 -0
  95. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/react_jsx-runtime.js +0 -0
  96. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/react_jsx-runtime.js.map +0 -0
  97. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/tailwind-merge.js +0 -0
  98. /package/template/node_modules/.vite-mcp/{deps_temp_170f8fb8 → deps_temp_64e1a2fa}/tailwind-merge.js.map +0 -0
@@ -11,12 +11,6 @@ interface ConversationProps {
11
11
  appName?: string;
12
12
  appIcon?: string;
13
13
  userMessage?: string;
14
- /**
15
- * Whether the content is transitioning between display modes.
16
- * When true, the content area is hidden (opacity 0) to prevent flashing
17
- * stale content in the new layout.
18
- */
19
- isTransitioning?: boolean;
20
14
  }
21
15
  /**
22
16
  * Conversation layout that renders children (iframe) at a stable tree position.
@@ -31,5 +25,5 @@ interface ConversationProps {
31
25
  * - **fullscreen**: content wrapper becomes `position: fixed` covering the viewport;
32
26
  * fullscreen chrome (header/footer) rendered as a separate fixed overlay
33
27
  */
34
- export declare function Conversation({ children, screenWidth, displayMode, platform, onRequestDisplayMode, appName, appIcon, userMessage, isTransitioning, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function Conversation({ children, screenWidth, displayMode, platform, onRequestDisplayMode, appName, appIcon, userMessage, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
35
29
  export {};
@@ -20,6 +20,12 @@ export interface ResourceCSP {
20
20
  /** Domains allowed for scripts, images, styles, fonts */
21
21
  resourceDomains?: string[];
22
22
  }
23
+ /**
24
+ * Extract CSP configuration from a resource's _meta.ui.csp field.
25
+ */
26
+ export declare function extractResourceCSP(resource: {
27
+ _meta?: unknown;
28
+ }): ResourceCSP | undefined;
23
29
  /**
24
30
  * Validates a CSP source entry is a safe origin URL (scheme + host + optional port).
25
31
  * Rejects wildcards, CSP keywords, and whitespace that could inject extra directives.
@@ -61,13 +67,6 @@ interface IframeResourceProps {
61
67
  className?: string;
62
68
  /** Optional style for the iframe */
63
69
  style?: React.CSSProperties;
64
- /**
65
- * Called after the iframe has rendered following a display mode change.
66
- * The callback receives the display mode that was confirmed.
67
- * Used by the simulator to hide content during transitions and only
68
- * reveal it once the app has committed its DOM for the new mode.
69
- */
70
- onDisplayModeReady?: (mode: string) => void;
71
70
  /**
72
71
  * Debug: State to inject directly into the app's useAppState hook.
73
72
  * This bypasses the normal MCP Apps protocol and is for simulator testing.
@@ -86,7 +85,7 @@ interface IframeResourceProps {
86
85
  * connects via PostMessageTransport to window.parent. The parent side uses
87
86
  * McpAppHost (wrapping AppBridge) to communicate.
88
87
  */
89
- export declare function IframeResource({ src, scriptSrc, hostContext, toolInput, toolResult, hostOptions, csp, className, style, onDisplayModeReady, debugInjectState, }: IframeResourceProps): import("react/jsx-runtime").JSX.Element;
88
+ export declare function IframeResource({ src, scriptSrc, hostContext, toolInput, toolResult, hostOptions, csp, className, style, debugInjectState, }: IframeResourceProps): import("react/jsx-runtime").JSX.Element;
90
89
  export declare const _testExports: {
91
90
  escapeHtml: typeof escapeHtml;
92
91
  isAllowedUrl: typeof isAllowedUrl;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const chatgpt_index = require("../index-B_In_BWg.cjs");
3
+ const chatgpt_index = require("../index-B9MMk69u.cjs");
4
4
  const discovery = require("../discovery-CRR3SlyI.cjs");
5
5
  exports.ChatGPTSimulator = chatgpt_index.ChatGPTSimulator;
6
6
  exports.IframeResource = chatgpt_index.IframeResource;
@@ -8,6 +8,7 @@ exports.McpAppHost = chatgpt_index.McpAppHost;
8
8
  exports.SCREEN_WIDTHS = chatgpt_index.SCREEN_WIDTHS;
9
9
  exports.ThemeProvider = chatgpt_index.ThemeProvider;
10
10
  exports.createSimulatorUrl = chatgpt_index.createSimulatorUrl;
11
+ exports.extractResourceCSP = chatgpt_index.extractResourceCSP;
11
12
  exports.useThemeContext = chatgpt_index.useThemeContext;
12
13
  exports.buildDevSimulations = discovery.buildDevSimulations;
13
14
  exports.buildResourceMap = discovery.buildResourceMap;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -27,7 +27,7 @@ export type { ScreenWidth, SimulatorConfig } from './chatgpt-simulator-types';
27
27
  export { SCREEN_WIDTHS } from './chatgpt-simulator-types';
28
28
  export { McpAppHost } from './mcp-app-host';
29
29
  export type { McpAppHostOptions } from './mcp-app-host';
30
- export { IframeResource } from './iframe-resource';
30
+ export { IframeResource, extractResourceCSP } from './iframe-resource';
31
31
  export type { ResourceCSP } from './iframe-resource';
32
32
  export * from './theme-provider';
33
33
  export { createSimulatorUrl } from './simulator-url';
@@ -1,5 +1,5 @@
1
- import { C, I, M, S, T, a, u } from "../index-CkEAx7FS.js";
2
- import { a as a2, b, d, c, e, f, g, h, i, j, k, l, t } from "../discovery-COZUnY6a.js";
1
+ import { C, I, M, S, T, a, e, u } from "../index-DqOCq5r8.js";
2
+ import { a as a2, b, d, c, e as e2, f, g, h, i, j, k, l, t } from "../discovery-COZUnY6a.js";
3
3
  export {
4
4
  C as ChatGPTSimulator,
5
5
  I as IframeResource,
@@ -11,7 +11,8 @@ export {
11
11
  d as buildSimulations,
12
12
  c as createResourceExports,
13
13
  a as createSimulatorUrl,
14
- e as extractResourceKey,
14
+ e as extractResourceCSP,
15
+ e2 as extractResourceKey,
15
16
  f as extractSimulationKey,
16
17
  g as extractSimulationName,
17
18
  h as findResourceDirs,
@@ -12,6 +12,8 @@ export interface McpAppHostOptions {
12
12
  }) => void;
13
13
  onLog?: (params: LoggingMessageNotification['params']) => void;
14
14
  onCallTool?: (params: CallToolRequest['params']) => CallToolResult | Promise<CallToolResult>;
15
+ /** Called after the iframe confirms rendering in a new display mode (paint fence resolved). */
16
+ onDisplayModeReady?: (mode: string) => void;
15
17
  }
16
18
  /**
17
19
  * MCP Apps host for the Sunpeak simulator.
@@ -25,6 +27,7 @@ export declare class McpAppHost {
25
27
  private _contentWindow;
26
28
  private _fenceId;
27
29
  private _fenceCleanup;
30
+ private _prevDisplayMode;
28
31
  private _pendingToolInput;
29
32
  private _pendingToolResult;
30
33
  constructor(options?: McpAppHostOptions);
@@ -46,6 +49,8 @@ export declare class McpAppHost {
46
49
  waitForPaint(): Promise<void>;
47
50
  /**
48
51
  * Update the host context and notify the connected app.
52
+ * Automatically detects display mode changes and waits for the iframe
53
+ * to commit its DOM before firing onDisplayModeReady.
49
54
  */
50
55
  setHostContext(context: McpUiHostContext): void;
51
56
  /**
@@ -5442,7 +5442,7 @@ const useEscCloseStack = (listening, cb) => {
5442
5442
  }, [id, listening, latestCallback]);
5443
5443
  };
5444
5444
  const __vite_import_meta_env__ = { "DEV": false, "MODE": "production" };
5445
- const META_ENV = typeof { url: typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index-B_In_BWg.cjs", document.baseURI).href } !== "undefined" ? __vite_import_meta_env__ : void 0;
5445
+ const META_ENV = typeof { url: typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index-B9MMk69u.cjs", document.baseURI).href } !== "undefined" ? __vite_import_meta_env__ : void 0;
5446
5446
  const NODE_ENV = typeof process !== "undefined" && process.env?.NODE_ENV ? process.env?.NODE_ENV : "production";
5447
5447
  const isDev = NODE_ENV === "development" || !!META_ENV?.DEV;
5448
5448
  const isJSDomLike = typeof navigator !== "undefined" && /(jsdom|happy-dom)/i.test(navigator.userAgent) || typeof globalThis.happyDOM === "object";
@@ -7545,8 +7545,7 @@ function Conversation({
7545
7545
  onRequestDisplayMode,
7546
7546
  appName = "Sunpeak",
7547
7547
  appIcon,
7548
- userMessage = "What have you got for me today?",
7549
- isTransitioning = false
7548
+ userMessage = "What have you got for me today?"
7550
7549
  }) {
7551
7550
  const isDesktop = platform2 === "desktop";
7552
7551
  const containerWidth = screenWidth === "full" ? "100%" : `${SCREEN_WIDTHS[screenWidth]}px`;
@@ -7668,12 +7667,6 @@ function Conversation({
7668
7667
  "div",
7669
7668
  {
7670
7669
  className: isPip ? "h-full w-full max-w-full overflow-auto bg-white dark:bg-[#212121]" : isFullscreen ? "h-full w-full max-w-full overflow-auto bg-surface" : "h-full w-full max-w-full bg-transparent",
7671
- style: {
7672
- opacity: isTransitioning ? 0 : 1,
7673
- // Only animate the reveal — the hide must be instant
7674
- // to prevent old content from being visible in the new layout.
7675
- transition: isTransitioning ? "none" : "opacity 100ms"
7676
- },
7677
7670
  children
7678
7671
  }
7679
7672
  )
@@ -14071,10 +14064,12 @@ class McpAppHost {
14071
14064
  _contentWindow = null;
14072
14065
  _fenceId = 0;
14073
14066
  _fenceCleanup = null;
14067
+ _prevDisplayMode;
14074
14068
  _pendingToolInput = null;
14075
14069
  _pendingToolResult = null;
14076
14070
  constructor(options = {}) {
14077
14071
  this.options = options;
14072
+ this._prevDisplayMode = options.hostContext?.displayMode;
14078
14073
  this.bridge = new j_(null, HOST_INFO, HOST_CAPABILITIES, {
14079
14074
  hostContext: options.hostContext
14080
14075
  });
@@ -14209,9 +14204,19 @@ class McpAppHost {
14209
14204
  }
14210
14205
  /**
14211
14206
  * Update the host context and notify the connected app.
14207
+ * Automatically detects display mode changes and waits for the iframe
14208
+ * to commit its DOM before firing onDisplayModeReady.
14212
14209
  */
14213
14210
  setHostContext(context) {
14214
14211
  this.bridge.setHostContext(context);
14212
+ const currentMode = context.displayMode;
14213
+ if (currentMode && currentMode !== this._prevDisplayMode) {
14214
+ this._prevDisplayMode = currentMode;
14215
+ const mode = currentMode;
14216
+ this.waitForPaint().then(() => {
14217
+ this.options.onDisplayModeReady?.(mode);
14218
+ });
14219
+ }
14215
14220
  }
14216
14221
  /**
14217
14222
  * Send tool input to the app.
@@ -14270,7 +14275,6 @@ class McpAppHost {
14270
14275
  }
14271
14276
  await this.bridge.close();
14272
14277
  this._initialized = false;
14273
- this._contentWindow = null;
14274
14278
  }
14275
14279
  /**
14276
14280
  * Debug: Inject state directly into the app's useAppState hook.
@@ -14327,6 +14331,11 @@ function isAllowedUrl(src) {
14327
14331
  return false;
14328
14332
  }
14329
14333
  }
14334
+ function extractResourceCSP(resource) {
14335
+ const meta = resource._meta;
14336
+ const ui2 = meta?.ui;
14337
+ return ui2?.csp;
14338
+ }
14330
14339
  const SDK_RESOURCE_DOMAINS = ["https://cdn.openai.com"];
14331
14340
  function isValidCspSource(source) {
14332
14341
  if (!source || /[\s;,']/.test(source) || source === "*") return false;
@@ -14381,6 +14390,23 @@ function generateCSP(csp, scriptSrc) {
14381
14390
  directives.push(`media-src ${resourceList}`);
14382
14391
  return directives.join("; ");
14383
14392
  }
14393
+ const PAINT_FENCE_SCRIPT = `window.addEventListener("message",function(e){
14394
+ if(e.data&&e.data.method==="sunpeak/fence"){
14395
+ var fid=e.data.params&&e.data.params.fenceId;
14396
+ requestAnimationFrame(function(){
14397
+ e.source.postMessage({jsonrpc:"2.0",method:"sunpeak/fence-ack",params:{fenceId:fid}},"*");
14398
+ });}});`;
14399
+ function injectPaintFence(iframe) {
14400
+ try {
14401
+ const doc = iframe.contentDocument;
14402
+ if (!doc || doc.querySelector("script[data-sunpeak-fence]")) return;
14403
+ const script = doc.createElement("script");
14404
+ script.setAttribute("data-sunpeak-fence", "");
14405
+ script.textContent = PAINT_FENCE_SCRIPT;
14406
+ doc.head.appendChild(script);
14407
+ } catch {
14408
+ }
14409
+ }
14384
14410
  function generateScriptHtml(scriptSrc, theme, cspPolicy) {
14385
14411
  const safeScriptSrc = escapeHtml(scriptSrc);
14386
14412
  const safeCsp = escapeHtml(cspPolicy);
@@ -14405,19 +14431,7 @@ function generateScriptHtml(scriptSrc, theme, cspPolicy) {
14405
14431
  color-scheme: dark light;
14406
14432
  }
14407
14433
  </style>
14408
- <script>
14409
- // Paint fence responder — allows the host to wait for this iframe to
14410
- // process pending messages and commit DOM updates before revealing content.
14411
- // Formatted as JSON-RPC 2.0 notifications to avoid PostMessageTransport parse errors.
14412
- window.addEventListener("message",function(e){
14413
- if(e.data&&e.data.method==="sunpeak/fence"){
14414
- var fid=e.data.params&&e.data.params.fenceId;
14415
- requestAnimationFrame(function(){
14416
- e.source.postMessage({jsonrpc:"2.0",method:"sunpeak/fence-ack",params:{fenceId:fid}},"*");
14417
- });
14418
- }
14419
- });
14420
- <\/script>
14434
+ <script>${PAINT_FENCE_SCRIPT}<\/script>
14421
14435
  </head>
14422
14436
  <body>
14423
14437
  <div id="root"></div>
@@ -14435,14 +14449,13 @@ function IframeResource({
14435
14449
  csp,
14436
14450
  className,
14437
14451
  style,
14438
- onDisplayModeReady,
14439
14452
  debugInjectState
14440
14453
  }) {
14441
14454
  const iframeRef = React.useRef(null);
14442
14455
  const hostRef = React.useRef(null);
14443
- const prevDisplayModeRef = React.useRef(hostContext?.displayMode);
14444
- const onDisplayModeReadyRef = React.useRef(onDisplayModeReady);
14445
- onDisplayModeReadyRef.current = onDisplayModeReady;
14456
+ const [readyDisplayMode, setReadyDisplayMode] = React.useState(
14457
+ hostContext?.displayMode
14458
+ );
14446
14459
  const resourceUrl = src ?? scriptSrc;
14447
14460
  const hasReceivedSizeRef = React.useRef(false);
14448
14461
  const host = React.useMemo(
@@ -14455,7 +14468,8 @@ function IframeResource({
14455
14468
  hasReceivedSizeRef.current = true;
14456
14469
  iframeRef.current.style.height = `${params.height}px`;
14457
14470
  }
14458
- }
14471
+ },
14472
+ onDisplayModeReady: (mode) => setReadyDisplayMode(mode)
14459
14473
  }),
14460
14474
  // eslint-disable-next-line react-hooks/exhaustive-deps
14461
14475
  []
@@ -14472,22 +14486,13 @@ function IframeResource({
14472
14486
  [host]
14473
14487
  );
14474
14488
  const handleLoad = React.useCallback(() => {
14475
- if (toolInput) host.sendToolInput(toolInput);
14476
- if (toolResult) host.sendToolResult(toolResult);
14477
- }, [host, toolInput, toolResult]);
14489
+ if (src && iframeRef.current) {
14490
+ injectPaintFence(iframeRef.current);
14491
+ }
14492
+ }, [src]);
14478
14493
  React.useEffect(() => {
14479
14494
  if (hostContext) {
14480
14495
  host.setHostContext(hostContext);
14481
- const currentMode = hostContext.displayMode;
14482
- if (currentMode !== prevDisplayModeRef.current) {
14483
- prevDisplayModeRef.current = currentMode;
14484
- if (currentMode) {
14485
- const mode = currentMode;
14486
- host.waitForPaint().then(() => {
14487
- onDisplayModeReadyRef.current?.(mode);
14488
- });
14489
- }
14490
- }
14491
14496
  }
14492
14497
  }, [host, hostContext]);
14493
14498
  React.useEffect(() => {
@@ -14523,6 +14528,7 @@ function IframeResource({
14523
14528
  const theme = hostContext?.theme ?? "dark";
14524
14529
  return generateScriptHtml(absoluteScriptSrc, theme, cspPolicy);
14525
14530
  }, [scriptSrc, isValidUrl, csp, hostContext?.theme]);
14531
+ const isTransitioning = hostContext?.displayMode !== readyDisplayMode;
14526
14532
  if (src) {
14527
14533
  if (!isValidUrl) {
14528
14534
  console.error("[IframeResource] URL not allowed:", src);
@@ -14546,6 +14552,10 @@ function IframeResource({
14546
14552
  // Start with minHeight to prevent collapse, but allow auto-resize to set actual height.
14547
14553
  // Don't use height: 100% as it requires explicit height in parent chain.
14548
14554
  minHeight: "200px",
14555
+ // Hide during display mode transitions; reveal with a short fade once
14556
+ // the iframe has committed its DOM for the new mode.
14557
+ opacity: isTransitioning ? 0 : 1,
14558
+ transition: isTransitioning ? "none" : "opacity 100ms",
14549
14559
  ...style
14550
14560
  },
14551
14561
  title: "Resource Preview",
@@ -14569,6 +14579,8 @@ function IframeResource({
14569
14579
  // Start with minHeight to prevent collapse, but allow auto-resize to set actual height.
14570
14580
  // Don't use height: 100% as it requires explicit height in parent chain.
14571
14581
  minHeight: "200px",
14582
+ opacity: isTransitioning ? 0 : 1,
14583
+ transition: isTransitioning ? "none" : "opacity 100ms",
14572
14584
  ...style
14573
14585
  },
14574
14586
  title: "Resource Preview",
@@ -14694,12 +14706,6 @@ function ChatGPTSimulator({
14694
14706
  _setDisplayMode(mode);
14695
14707
  }
14696
14708
  };
14697
- const [readyDisplayMode, setReadyDisplayMode] = React.useState(
14698
- urlParams.displayMode ?? DEFAULT_DISPLAY_MODE
14699
- );
14700
- const handleDisplayModeReady = React.useCallback((mode) => {
14701
- setReadyDisplayMode(mode);
14702
- }, []);
14703
14709
  const hostContext = React.useMemo(
14704
14710
  () => ({
14705
14711
  theme,
@@ -14790,11 +14796,7 @@ function ChatGPTSimulator({
14790
14796
  }, [toolResult, modelContext]);
14791
14797
  const resourceUrl = selectedSim?.resourceUrl;
14792
14798
  const resourceScript = selectedSim?.resourceScript;
14793
- const resourceMeta = selectedSim?.resource._meta;
14794
- const resourceUi = resourceMeta?.ui;
14795
- const csp = resourceUi?.csp;
14796
- const hasIframeContent = !!(resourceUrl || resourceScript);
14797
- const isTransitioning = hasIframeContent && displayMode !== readyDisplayMode;
14799
+ const csp = selectedSim ? extractResourceCSP(selectedSim.resource) : void 0;
14798
14800
  let content;
14799
14801
  if (resourceUrl) {
14800
14802
  content = /* @__PURE__ */ jsxRuntime.jsx(
@@ -14808,7 +14810,6 @@ function ChatGPTSimulator({
14808
14810
  onDisplayModeChange: handleDisplayModeChange,
14809
14811
  onUpdateModelContext: handleUpdateModelContext
14810
14812
  },
14811
- onDisplayModeReady: handleDisplayModeReady,
14812
14813
  debugInjectState: modelContext,
14813
14814
  className: "h-full w-full"
14814
14815
  }
@@ -14826,7 +14827,6 @@ function ChatGPTSimulator({
14826
14827
  onDisplayModeChange: handleDisplayModeChange,
14827
14828
  onUpdateModelContext: handleUpdateModelContext
14828
14829
  },
14829
- onDisplayModeReady: handleDisplayModeReady,
14830
14830
  debugInjectState: modelContext,
14831
14831
  className: "h-full w-full"
14832
14832
  }
@@ -15052,7 +15052,6 @@ function ChatGPTSimulator({
15052
15052
  appName,
15053
15053
  appIcon,
15054
15054
  userMessage: selectedSim?.userMessage,
15055
- isTransitioning,
15056
15055
  children: content
15057
15056
  },
15058
15057
  selectedSimulationName
@@ -15113,6 +15112,7 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
15113
15112
  buildSimulations: discovery.buildSimulations,
15114
15113
  createResourceExports: discovery.createResourceExports,
15115
15114
  createSimulatorUrl,
15115
+ extractResourceCSP,
15116
15116
  extractResourceKey: discovery.extractResourceKey,
15117
15117
  extractSimulationKey: discovery.extractSimulationKey,
15118
15118
  extractSimulationName: discovery.extractSimulationName,
@@ -15131,6 +15131,7 @@ exports.SCREEN_WIDTHS = SCREEN_WIDTHS;
15131
15131
  exports.ThemeProvider = ThemeProvider;
15132
15132
  exports.clsx = clsx;
15133
15133
  exports.createSimulatorUrl = createSimulatorUrl;
15134
+ exports.extractResourceCSP = extractResourceCSP;
15134
15135
  exports.index = index;
15135
15136
  exports.useThemeContext = useThemeContext;
15136
- //# sourceMappingURL=index-B_In_BWg.cjs.map
15137
+ //# sourceMappingURL=index-B9MMk69u.cjs.map