sunpeak 0.14.3 → 0.15.1

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 (128) hide show
  1. package/README.md +32 -28
  2. package/bin/commands/build.mjs +2 -1
  3. package/bin/commands/dev.mjs +72 -2
  4. package/dist/chatgpt/{conversation.d.ts → chatgpt-conversation.d.ts} +1 -1
  5. package/dist/chatgpt/chatgpt-host.d.ts +1 -0
  6. package/dist/chatgpt/globals.css +618 -6156
  7. package/dist/chatgpt/index.cjs +11 -8
  8. package/dist/chatgpt/index.cjs.map +1 -1
  9. package/dist/chatgpt/index.d.ts +10 -32
  10. package/dist/chatgpt/index.js +15 -12
  11. package/dist/chatgpt/index.js.map +1 -1
  12. package/dist/claude/claude-conversation.d.ts +23 -0
  13. package/dist/claude/claude-host.d.ts +1 -0
  14. package/dist/claude/index.cjs +6 -0
  15. package/dist/claude/index.cjs.map +1 -0
  16. package/dist/claude/index.d.ts +1 -0
  17. package/dist/claude/index.js +6 -0
  18. package/dist/claude/index.js.map +1 -0
  19. package/dist/claude-host-C7KPfOM8.cjs +284 -0
  20. package/dist/claude-host-C7KPfOM8.cjs.map +1 -0
  21. package/dist/claude-host-CaD7ptbt.js +283 -0
  22. package/dist/claude-host-CaD7ptbt.js.map +1 -0
  23. package/dist/{discovery-COZUnY6a.js → discovery-DzV3HLXs.js} +5 -5
  24. package/dist/{discovery-COZUnY6a.js.map → discovery-DzV3HLXs.js.map} +1 -1
  25. package/dist/hooks/index.d.ts +4 -0
  26. package/dist/hooks/use-app-tools.d.ts +44 -0
  27. package/dist/hooks/use-update-model-context.d.ts +29 -0
  28. package/dist/index-BKrboRah.js +44 -0
  29. package/dist/index-BKrboRah.js.map +1 -0
  30. package/dist/index-BSKuY-oH.cjs +527 -0
  31. package/dist/index-BSKuY-oH.cjs.map +1 -0
  32. package/dist/index-CiqvXo8n.js +512 -0
  33. package/dist/index-CiqvXo8n.js.map +1 -0
  34. package/dist/index-Dr-L0Nb3.cjs +43 -0
  35. package/dist/index-Dr-L0Nb3.cjs.map +1 -0
  36. package/dist/index.cjs +1705 -1647
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.js +2732 -2675
  40. package/dist/index.js.map +1 -1
  41. package/dist/lib/default-style-variables.d.ts +2 -0
  42. package/dist/lib/discovery-cli.js +1 -1
  43. package/dist/mcp/index.cjs +86 -27
  44. package/dist/mcp/index.cjs.map +1 -1
  45. package/dist/mcp/index.d.ts +3 -1
  46. package/dist/mcp/index.js +85 -26
  47. package/dist/mcp/index.js.map +1 -1
  48. package/dist/mcp/server.d.ts +4 -3
  49. package/dist/mcp/types.d.ts +11 -0
  50. package/dist/platform/chatgpt/index.cjs +1 -1
  51. package/dist/platform/chatgpt/index.js +1 -1
  52. package/dist/platform/index.cjs +3 -0
  53. package/dist/platform/index.cjs.map +1 -1
  54. package/dist/platform/index.d.ts +3 -1
  55. package/dist/platform/index.js +3 -0
  56. package/dist/platform/index.js.map +1 -1
  57. package/dist/{protocol-BQCnIrc9.js → protocol-DFbsCx7E.js} +29 -29
  58. package/dist/{protocol-BQCnIrc9.js.map → protocol-DFbsCx7E.js.map} +1 -1
  59. package/dist/simulator/host-styles.d.ts +5 -0
  60. package/dist/simulator/hosts.d.ts +73 -0
  61. package/dist/{chatgpt → simulator}/iframe-resource.d.ts +27 -3
  62. package/dist/simulator/index.cjs +40 -0
  63. package/dist/simulator/index.cjs.map +1 -0
  64. package/dist/simulator/index.d.ts +18 -0
  65. package/dist/simulator/index.js +40 -0
  66. package/dist/simulator/index.js.map +1 -0
  67. package/dist/{chatgpt → simulator}/mcp-app-host.d.ts +8 -1
  68. package/dist/simulator/mock-openai-runtime.d.ts +20 -0
  69. package/dist/{chatgpt → simulator}/simulator-url.d.ts +8 -1
  70. package/dist/simulator/simulator.d.ts +12 -0
  71. package/dist/{chatgpt → simulator}/theme-provider.d.ts +3 -1
  72. package/dist/simulator/use-simulator-state.d.ts +91 -0
  73. package/dist/simulator-BqZmzFVR.cjs +8214 -0
  74. package/dist/simulator-BqZmzFVR.cjs.map +1 -0
  75. package/dist/simulator-CMgCGNuD.js +8199 -0
  76. package/dist/simulator-CMgCGNuD.js.map +1 -0
  77. package/dist/simulator-url-BQ-7SMht.js +335 -0
  78. package/dist/simulator-url-BQ-7SMht.js.map +1 -0
  79. package/dist/simulator-url-uNqOCaPJ.cjs +334 -0
  80. package/dist/simulator-url-uNqOCaPJ.cjs.map +1 -0
  81. package/dist/style.css +558 -6143
  82. package/dist/types/runtime.d.ts +1 -1
  83. package/dist/{use-app-D7kRAPSG.cjs → use-app-BnoSPiUT.cjs} +2 -1
  84. package/dist/{use-app-D7kRAPSG.cjs.map → use-app-BnoSPiUT.cjs.map} +1 -1
  85. package/dist/{use-app-Dvr4LKs2.js → use-app-D_TeaMFG.js} +4 -3
  86. package/dist/{use-app-Dvr4LKs2.js.map → use-app-D_TeaMFG.js.map} +1 -1
  87. package/package.json +18 -3
  88. package/template/.sunpeak/dev.tsx +4 -4
  89. package/template/.sunpeak/resource-loader.html +1 -1
  90. package/template/node_modules/.bin/nodemon +2 -2
  91. package/template/node_modules/.bin/playwright +2 -2
  92. package/template/node_modules/.bin/sunpeak +2 -2
  93. package/template/node_modules/.bin/tsc +2 -2
  94. package/template/node_modules/.bin/tsserver +2 -2
  95. package/template/node_modules/.bin/tsx +2 -2
  96. package/template/node_modules/.bin/vite +2 -2
  97. package/template/src/components/avatar.tsx +4 -1
  98. package/template/src/components/button.tsx +17 -20
  99. package/template/src/resources/albums/albums-resource.tsx +2 -3
  100. package/template/src/resources/albums/components/album-card.tsx +4 -2
  101. package/template/src/resources/albums/components/film-strip.test.tsx +2 -2
  102. package/template/src/resources/albums/components/film-strip.tsx +2 -2
  103. package/template/src/resources/albums/components/fullscreen-viewer.tsx +7 -5
  104. package/template/src/resources/carousel/carousel-resource.tsx +2 -3
  105. package/template/src/resources/carousel/components/card.test.tsx +3 -2
  106. package/template/src/resources/carousel/components/card.tsx +8 -4
  107. package/template/src/resources/map/components/map-view.tsx +1 -1
  108. package/template/src/resources/map/components/map.tsx +1 -1
  109. package/template/src/resources/map/components/place-card.tsx +8 -4
  110. package/template/src/resources/map/components/place-carousel.tsx +1 -1
  111. package/template/src/resources/map/components/place-inspector.tsx +15 -7
  112. package/template/src/resources/map/components/place-list.tsx +7 -4
  113. package/template/src/resources/map/map-resource.tsx +0 -2
  114. package/template/src/resources/review/review-resource.tsx +61 -27
  115. package/template/tests/e2e/albums.spec.ts +118 -102
  116. package/template/tests/e2e/carousel.spec.ts +103 -100
  117. package/template/tests/e2e/map.spec.ts +220 -181
  118. package/template/tests/e2e/review.spec.ts +224 -198
  119. package/dist/_commonjsHelpers-Bc2YnDe1.cjs +0 -8
  120. package/dist/_commonjsHelpers-Bc2YnDe1.cjs.map +0 -1
  121. package/dist/_commonjsHelpers-DWwsNxpa.js +0 -9
  122. package/dist/_commonjsHelpers-DWwsNxpa.js.map +0 -1
  123. package/dist/index-CJ3jfcjj.js +0 -15131
  124. package/dist/index-CJ3jfcjj.js.map +0 -1
  125. package/dist/index-Cdeg96So.cjs +0 -15147
  126. package/dist/index-Cdeg96So.cjs.map +0 -1
  127. /package/dist/{chatgpt → simulator}/simple-sidebar.d.ts +0 -0
  128. /package/dist/{chatgpt/chatgpt-simulator-types.d.ts → simulator/simulator-types.d.ts} +0 -0
@@ -0,0 +1,335 @@
1
+ import { a as SCREEN_WIDTHS, r as registerHostShell, D as DEFAULT_STYLE_VARIABLES } from "./simulator-CMgCGNuD.js";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ function CloseIcon({ className }) {
4
+ return /* @__PURE__ */ jsx("svg", { width: "1em", height: "1em", viewBox: "0 0 24 24", fill: "currentColor", className, children: /* @__PURE__ */ jsx(
5
+ "path",
6
+ {
7
+ fillRule: "evenodd",
8
+ clipRule: "evenodd",
9
+ d: "M5.83071 5.83077C6.33839 5.32309 7.16151 5.32309 7.66919 5.83077L12 10.1615L16.3307 5.83077C16.8384 5.32309 17.6615 5.32309 18.1692 5.83077C18.6769 6.33845 18.6769 7.16157 18.1692 7.66925L13.8384 12L18.1692 16.3308C18.6769 16.8385 18.6769 17.6616 18.1692 18.1693C17.6615 18.6769 16.8384 18.6769 16.3307 18.1693L12 13.8385L7.66919 18.1693C7.16151 18.6769 6.33839 18.6769 5.83071 18.1693C5.32303 17.6616 5.32303 16.8385 5.83071 16.3308L10.1615 12L5.83071 7.66925C5.32303 7.16157 5.32303 6.33845 5.83071 5.83077Z"
10
+ }
11
+ ) });
12
+ }
13
+ function Conversation({
14
+ children,
15
+ screenWidth,
16
+ displayMode,
17
+ platform,
18
+ onRequestDisplayMode,
19
+ appName = "Sunpeak",
20
+ appIcon,
21
+ userMessage = "What have you got for me today?",
22
+ isTransitioning = false
23
+ }) {
24
+ const isDesktop = platform === "desktop";
25
+ const containerWidth = screenWidth === "full" ? "100%" : `${SCREEN_WIDTHS[screenWidth]}px`;
26
+ const isFullscreen = displayMode === "fullscreen";
27
+ const isPip = displayMode === "pip";
28
+ const handleClose = () => onRequestDisplayMode?.("inline");
29
+ return /* @__PURE__ */ jsxs(
30
+ "div",
31
+ {
32
+ className: "flex flex-col w-full h-full flex-1 items-center relative",
33
+ style: {
34
+ transform: "translate(0)",
35
+ backgroundColor: "var(--sim-bg-conversation, var(--color-background-primary))",
36
+ color: "var(--color-text-primary)"
37
+ },
38
+ children: [
39
+ isFullscreen && /* @__PURE__ */ jsxs(
40
+ "div",
41
+ {
42
+ className: "fixed start-0 end-0 top-0 bottom-0 z-[51] mx-auto flex flex-col pointer-events-none",
43
+ style: { maxWidth: containerWidth },
44
+ children: [
45
+ /* @__PURE__ */ jsxs(
46
+ "div",
47
+ {
48
+ className: "z-10 grid h-[3.25rem] grid-cols-[1fr_auto_1fr] border-b px-2 pointer-events-auto",
49
+ style: {
50
+ borderColor: "var(--color-border-primary)",
51
+ backgroundColor: "var(--sim-bg-conversation, var(--color-background-primary))"
52
+ },
53
+ children: [
54
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-start gap-3", children: /* @__PURE__ */ jsx(
55
+ "button",
56
+ {
57
+ onClick: handleClose,
58
+ "aria-label": "Close",
59
+ className: "h-7 w-7 flex items-center justify-center rounded-md transition-colors hover:opacity-70",
60
+ type: "button",
61
+ children: /* @__PURE__ */ jsx(CloseIcon, {})
62
+ }
63
+ ) }),
64
+ isDesktop && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center text-base", children: appName }),
65
+ isDesktop && /* @__PURE__ */ jsx("div", {})
66
+ ]
67
+ }
68
+ ),
69
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
70
+ /* @__PURE__ */ jsx(
71
+ "footer",
72
+ {
73
+ className: "pointer-events-auto",
74
+ style: {
75
+ backgroundColor: "var(--sim-bg-conversation, var(--color-background-primary))"
76
+ },
77
+ children: /* @__PURE__ */ jsx("div", { className: "max-w-[48rem] mx-auto px-4 py-4", children: /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
78
+ "input",
79
+ {
80
+ type: "text",
81
+ name: "userInput",
82
+ disabled: true,
83
+ placeholder: "Message sunpeak.ai",
84
+ className: "w-full rounded-3xl px-5 py-3 pr-12 shadow-md",
85
+ style: {
86
+ backgroundColor: "var(--sim-bg-reply-input, var(--color-background-secondary))",
87
+ color: "var(--color-text-primary)",
88
+ border: "1px solid var(--color-border-tertiary)"
89
+ }
90
+ }
91
+ ) }) })
92
+ }
93
+ )
94
+ ]
95
+ }
96
+ ),
97
+ !isFullscreen && /* @__PURE__ */ jsx(
98
+ "header",
99
+ {
100
+ className: "h-12 flex items-center px-4 text-lg sticky top-0 z-40 w-full",
101
+ style: {
102
+ maxWidth: containerWidth,
103
+ backgroundColor: "var(--sim-bg-conversation, var(--color-background-primary))"
104
+ },
105
+ children: /* @__PURE__ */ jsx("span", { children: "sunpeak.ai" })
106
+ }
107
+ ),
108
+ /* @__PURE__ */ jsxs(
109
+ "div",
110
+ {
111
+ className: "flex flex-col flex-1 w-full transition-all duration-200 overflow-hidden",
112
+ style: { maxWidth: containerWidth },
113
+ children: [
114
+ /* @__PURE__ */ jsxs("main", { className: "flex-1 overflow-y-auto overflow-x-hidden", children: [
115
+ !isFullscreen && /* @__PURE__ */ jsxs("article", { className: "w-full focus:outline-none", dir: "auto", "data-turn": "user", children: [
116
+ /* @__PURE__ */ jsx("h5", { className: "sr-only", children: "You said:" }),
117
+ /* @__PURE__ */ jsx("div", { className: "text-base my-auto mx-auto md:pt-8 px-4", children: /* @__PURE__ */ jsx("div", { className: "max-w-[48rem] mx-auto flex-1 relative flex w-full min-w-0 flex-col", children: /* @__PURE__ */ jsx("div", { className: "flex max-w-full flex-col grow", children: /* @__PURE__ */ jsx(
118
+ "div",
119
+ {
120
+ "data-message-author-role": "user",
121
+ className: "min-h-8 relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal",
122
+ children: /* @__PURE__ */ jsx("div", { className: "flex w-full flex-col gap-1 empty:hidden items-end", children: /* @__PURE__ */ jsx(
123
+ "div",
124
+ {
125
+ className: "relative rounded-[18px] px-4 py-3 max-w-[70%]",
126
+ style: {
127
+ backgroundColor: "var(--sim-bg-user-bubble, var(--color-background-tertiary))"
128
+ },
129
+ children: /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap", children: userMessage })
130
+ }
131
+ ) })
132
+ }
133
+ ) }) }) })
134
+ ] }),
135
+ /* @__PURE__ */ jsxs("article", { className: "w-full focus:outline-none", dir: "auto", "data-turn": "assistant", children: [
136
+ /* @__PURE__ */ jsxs("h6", { className: "sr-only", children: [
137
+ appName,
138
+ " said:"
139
+ ] }),
140
+ /* @__PURE__ */ jsx("div", { className: "text-base my-auto mx-auto pb-10 px-4", children: /* @__PURE__ */ jsx("div", { className: "max-w-[48rem] mx-auto flex-1 relative flex w-full min-w-0 flex-col", children: /* @__PURE__ */ jsxs("div", { className: "flex max-w-full flex-col grow", children: [
141
+ !isFullscreen && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 my-3", children: [
142
+ appIcon ? /* @__PURE__ */ jsx("div", { className: "size-6 flex items-center justify-center text-base", children: appIcon }) : /* @__PURE__ */ jsx(
143
+ "div",
144
+ {
145
+ className: "size-6 rounded-full flex items-center justify-center font-medium text-xs text-white",
146
+ style: { backgroundColor: "#10a37f" },
147
+ children: "AI"
148
+ }
149
+ ),
150
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-sm", children: appName })
151
+ ] }),
152
+ /* @__PURE__ */ jsx(
153
+ "div",
154
+ {
155
+ "data-message-author-role": "assistant",
156
+ className: "min-h-8 relative flex w-full flex-col items-start gap-2 text-start break-words whitespace-normal",
157
+ children: /* @__PURE__ */ jsx("div", { className: "flex w-full flex-col gap-1 empty:hidden", children: /* @__PURE__ */ jsxs(
158
+ "div",
159
+ {
160
+ className: isPip ? "no-scrollbar @w-xl/main:top-4 fixed start-4 end-4 top-12 z-50 mx-auto max-w-[40rem] lg:max-w-[48rem] sm:start-0 sm:end-0 sm:top-[3.25rem] sm:w-full overflow-visible" : isFullscreen ? "no-scrollbar fixed inset-x-0 top-[3.25rem] bottom-0 z-50 mx-auto" : "no-scrollbar relative mb-2 @w-sm/main:w-full mx-0 max-sm:-mx-[1rem] max-sm:w-[100cqw] max-sm:overflow-hidden overflow-visible",
161
+ style: {
162
+ ...isPip ? { maxHeight: "480px" } : {},
163
+ ...isFullscreen ? { maxWidth: containerWidth } : {}
164
+ },
165
+ children: [
166
+ isPip && /* @__PURE__ */ jsx(
167
+ "button",
168
+ {
169
+ onClick: handleClose,
170
+ className: "absolute -start-2 -top-1.5 z-10 rounded-full bg-[#3a3a3a] p-1.5 text-white shadow-[0px_0px_0px_1px_#fff3,0px_4px_12px_rgba(0,0,0,0.12)] hover:bg-[#6a6a6a]",
171
+ "aria-label": "Close picture-in-picture",
172
+ type: "button",
173
+ children: /* @__PURE__ */ jsx(CloseIcon, { className: "h-4 w-4" })
174
+ },
175
+ "pip-close"
176
+ ),
177
+ /* @__PURE__ */ jsx(
178
+ "div",
179
+ {
180
+ className: isPip ? "relative overflow-hidden h-full rounded-2xl sm:rounded-3xl shadow-[0px_0px_0px_1px_#fff3,0px_6px_20px_rgba(0,0,0,0.1)] md:-mx-4" : "relative overflow-hidden h-full",
181
+ children: /* @__PURE__ */ jsx(
182
+ "div",
183
+ {
184
+ className: "h-full w-full max-w-full",
185
+ style: {
186
+ ...isPip ? {
187
+ overflow: "auto",
188
+ backgroundColor: "var(--color-background-primary)"
189
+ } : isFullscreen ? {
190
+ overflow: "auto",
191
+ backgroundColor: "var(--color-background-primary)"
192
+ } : { backgroundColor: "transparent" },
193
+ opacity: isTransitioning ? 0 : 1,
194
+ transition: isTransitioning ? "none" : "opacity 100ms"
195
+ },
196
+ children
197
+ }
198
+ )
199
+ },
200
+ "content"
201
+ )
202
+ ]
203
+ }
204
+ ) })
205
+ }
206
+ )
207
+ ] }) }) })
208
+ ] })
209
+ ] }),
210
+ !isFullscreen && /* @__PURE__ */ jsx(
211
+ "footer",
212
+ {
213
+ style: {
214
+ backgroundColor: "var(--sim-bg-conversation, var(--color-background-primary))"
215
+ },
216
+ children: /* @__PURE__ */ jsx("div", { className: "max-w-[48rem] mx-auto px-4 py-4", children: /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
217
+ "input",
218
+ {
219
+ type: "text",
220
+ name: "userInput",
221
+ disabled: true,
222
+ placeholder: "Message sunpeak.ai",
223
+ className: "w-full rounded-3xl px-5 py-3 pr-12 shadow-md",
224
+ style: {
225
+ backgroundColor: "var(--sim-bg-reply-input, var(--color-background-secondary))",
226
+ color: "var(--color-text-primary)",
227
+ border: "1px solid var(--color-border-tertiary)"
228
+ }
229
+ }
230
+ ) }) })
231
+ }
232
+ )
233
+ ]
234
+ }
235
+ )
236
+ ]
237
+ }
238
+ );
239
+ }
240
+ const CHATGPT_HOST_INFO = {
241
+ name: "ChatGPT",
242
+ version: "1.0.0"
243
+ };
244
+ const CHATGPT_HOST_CAPABILITIES = {
245
+ openLinks: {},
246
+ serverTools: {},
247
+ logging: {},
248
+ updateModelContext: { text: {} },
249
+ message: { text: {} }
250
+ };
251
+ function applyChatGPTTheme(theme) {
252
+ document.documentElement.setAttribute("data-theme", theme);
253
+ document.documentElement.style.colorScheme = theme;
254
+ }
255
+ const CHATGPT_STYLE_VARIABLES = {
256
+ ...DEFAULT_STYLE_VARIABLES,
257
+ // Background colors — ChatGPT's standard palette
258
+ "--color-background-primary": "light-dark(#ffffff, #212121)",
259
+ "--color-background-secondary": "light-dark(#f7f7f8, #2f2f2f)",
260
+ "--color-background-tertiary": "light-dark(#ececf1, #444654)",
261
+ "--color-background-inverse": "light-dark(#212121, #ffffff)",
262
+ // Text colors
263
+ "--color-text-primary": "light-dark(#0d0d0d, #ececec)",
264
+ "--color-text-secondary": "light-dark(#6e6e80, #acacbe)",
265
+ "--color-text-tertiary": "light-dark(#acacbe, #6e6e80)",
266
+ "--color-text-inverse": "light-dark(#ececec, #0d0d0d)",
267
+ // Border colors
268
+ "--color-border-primary": "light-dark(#e5e5e5, #4e4e4e)",
269
+ "--color-border-secondary": "light-dark(#d9d9e3, #565869)",
270
+ "--color-border-tertiary": "light-dark(#f0f0f0, #3a3a3a)"
271
+ };
272
+ registerHostShell({
273
+ id: "chatgpt",
274
+ label: "ChatGPT",
275
+ Conversation,
276
+ applyTheme: applyChatGPTTheme,
277
+ hostInfo: CHATGPT_HOST_INFO,
278
+ hostCapabilities: CHATGPT_HOST_CAPABILITIES,
279
+ styleVariables: CHATGPT_STYLE_VARIABLES,
280
+ pageStyles: {
281
+ "--sim-bg-sidebar": "light-dark(#f9f9f9, #181818)",
282
+ "--sim-bg-conversation": "light-dark(#ffffff, #212121)",
283
+ "--sim-bg-user-bubble": "light-dark(#f4f4f4, #303030)",
284
+ "--sim-bg-reply-input": "light-dark(#ffffff, #303030)"
285
+ }
286
+ });
287
+ function createSimulatorUrl(params, basePath = "/") {
288
+ const searchParams = new URLSearchParams();
289
+ if (params.simulation !== void 0) {
290
+ searchParams.set("simulation", params.simulation);
291
+ }
292
+ if (params.host !== void 0) {
293
+ searchParams.set("host", params.host);
294
+ }
295
+ if (params.theme !== void 0) {
296
+ searchParams.set("theme", params.theme);
297
+ }
298
+ if (params.displayMode !== void 0) {
299
+ searchParams.set("displayMode", params.displayMode);
300
+ }
301
+ if (params.locale !== void 0) {
302
+ searchParams.set("locale", params.locale);
303
+ }
304
+ if (params.maxHeight !== void 0) {
305
+ searchParams.set("maxHeight", String(params.maxHeight));
306
+ }
307
+ if (params.deviceType !== void 0) {
308
+ searchParams.set("deviceType", params.deviceType);
309
+ }
310
+ if (params.hover !== void 0) {
311
+ searchParams.set("hover", String(params.hover));
312
+ }
313
+ if (params.touch !== void 0) {
314
+ searchParams.set("touch", String(params.touch));
315
+ }
316
+ if (params.safeAreaTop !== void 0) {
317
+ searchParams.set("safeAreaTop", String(params.safeAreaTop));
318
+ }
319
+ if (params.safeAreaBottom !== void 0) {
320
+ searchParams.set("safeAreaBottom", String(params.safeAreaBottom));
321
+ }
322
+ if (params.safeAreaLeft !== void 0) {
323
+ searchParams.set("safeAreaLeft", String(params.safeAreaLeft));
324
+ }
325
+ if (params.safeAreaRight !== void 0) {
326
+ searchParams.set("safeAreaRight", String(params.safeAreaRight));
327
+ }
328
+ const queryString = searchParams.toString();
329
+ return queryString ? `${basePath}?${queryString}` : basePath;
330
+ }
331
+ export {
332
+ Conversation as C,
333
+ createSimulatorUrl as c
334
+ };
335
+ //# sourceMappingURL=simulator-url-BQ-7SMht.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simulator-url-BQ-7SMht.js","sources":["../src/chatgpt/chatgpt-conversation.tsx","../src/chatgpt/chatgpt-host.ts","../src/simulator/simulator-url.ts"],"sourcesContent":["import * as React from 'react';\nimport { SCREEN_WIDTHS, type ScreenWidth } from '../simulator/simulator-types';\nimport type { McpUiDisplayMode, McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\ntype Platform = NonNullable<McpUiHostContext['platform']>;\n\nfunction CloseIcon({ className }: { className?: string }) {\n return (\n <svg width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className}>\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M5.83071 5.83077C6.33839 5.32309 7.16151 5.32309 7.66919 5.83077L12 10.1615L16.3307 5.83077C16.8384 5.32309 17.6615 5.32309 18.1692 5.83077C18.6769 6.33845 18.6769 7.16157 18.1692 7.66925L13.8384 12L18.1692 16.3308C18.6769 16.8385 18.6769 17.6616 18.1692 18.1693C17.6615 18.6769 16.8384 18.6769 16.3307 18.1693L12 13.8385L7.66919 18.1693C7.16151 18.6769 6.33839 18.6769 5.83071 18.1693C5.32303 17.6616 5.32303 16.8385 5.83071 16.3308L10.1615 12L5.83071 7.66925C5.32303 7.16157 5.32303 6.33845 5.83071 5.83077Z\"\n />\n </svg>\n );\n}\n\ninterface ConversationProps {\n children?: React.ReactNode;\n screenWidth: ScreenWidth;\n displayMode: McpUiDisplayMode;\n platform: Platform;\n onRequestDisplayMode?: (mode: McpUiDisplayMode) => void;\n appName?: string;\n appIcon?: string;\n userMessage?: string;\n /**\n * Whether the content is transitioning between display modes.\n * When true, the content area is hidden (opacity 0) to prevent the pip\n * border from flashing at a stale height before the iframe resizes.\n */\n isTransitioning?: boolean;\n}\n\n/**\n * Conversation layout that renders children (iframe) at a stable tree position.\n *\n * All three display modes (inline, pip, fullscreen) share the same React tree\n * shape so that the iframe never unmounts when switching modes, avoiding a\n * white-flash reload.\n *\n * Visual differences are achieved purely with CSS:\n * - **inline**: content in normal document flow\n * - **pip**: content wrapper becomes `position: fixed` floating overlay\n * - **fullscreen**: content wrapper becomes `position: fixed` covering the viewport;\n * fullscreen chrome (header/footer) rendered as a separate fixed overlay\n */\nexport function Conversation({\n children,\n screenWidth,\n displayMode,\n platform,\n onRequestDisplayMode,\n appName = 'Sunpeak',\n appIcon,\n userMessage = 'What have you got for me today?',\n isTransitioning = false,\n}: ConversationProps) {\n const isDesktop = platform === 'desktop';\n const containerWidth = screenWidth === 'full' ? '100%' : `${SCREEN_WIDTHS[screenWidth]}px`;\n const isFullscreen = displayMode === 'fullscreen';\n const isPip = displayMode === 'pip';\n\n const handleClose = () => onRequestDisplayMode?.('inline');\n\n return (\n <div\n className=\"flex flex-col w-full h-full flex-1 items-center relative\"\n style={{\n transform: 'translate(0)',\n backgroundColor: 'var(--sim-bg-conversation, var(--color-background-primary))',\n color: 'var(--color-text-primary)',\n }}\n >\n {/* ─── Fullscreen chrome overlay ─── */}\n {isFullscreen && (\n <div\n className=\"fixed start-0 end-0 top-0 bottom-0 z-[51] mx-auto flex flex-col pointer-events-none\"\n style={{ maxWidth: containerWidth }}\n >\n <div\n className=\"z-10 grid h-[3.25rem] grid-cols-[1fr_auto_1fr] border-b px-2 pointer-events-auto\"\n style={{\n borderColor: 'var(--color-border-primary)',\n backgroundColor: 'var(--sim-bg-conversation, var(--color-background-primary))',\n }}\n >\n <div className=\"flex items-center justify-start gap-3\">\n <button\n onClick={handleClose}\n aria-label=\"Close\"\n className=\"h-7 w-7 flex items-center justify-center rounded-md transition-colors hover:opacity-70\"\n type=\"button\"\n >\n <CloseIcon />\n </button>\n </div>\n {isDesktop && (\n <div className=\"flex items-center justify-center text-base\">{appName}</div>\n )}\n {isDesktop && <div />}\n </div>\n {/* Spacer - pointer events pass through to content below */}\n <div className=\"flex-1\" />\n <footer\n className=\"pointer-events-auto\"\n style={{\n backgroundColor: 'var(--sim-bg-conversation, var(--color-background-primary))',\n }}\n >\n <div className=\"max-w-[48rem] mx-auto px-4 py-4\">\n <div className=\"relative\">\n <input\n type=\"text\"\n name=\"userInput\"\n disabled\n placeholder=\"Message sunpeak.ai\"\n className=\"w-full rounded-3xl px-5 py-3 pr-12 shadow-md\"\n style={{\n backgroundColor: 'var(--sim-bg-reply-input, var(--color-background-secondary))',\n color: 'var(--color-text-primary)',\n border: '1px solid var(--color-border-tertiary)',\n }}\n />\n </div>\n </div>\n </footer>\n </div>\n )}\n\n {/* ─── Conversation header ─── */}\n {!isFullscreen && (\n <header\n className=\"h-12 flex items-center px-4 text-lg sticky top-0 z-40 w-full\"\n style={{\n maxWidth: containerWidth,\n backgroundColor: 'var(--sim-bg-conversation, var(--color-background-primary))',\n }}\n >\n <span>sunpeak.ai</span>\n </header>\n )}\n\n {/* ─── Conversation container ─── */}\n <div\n className=\"flex flex-col flex-1 w-full transition-all duration-200 overflow-hidden\"\n style={{ maxWidth: containerWidth }}\n >\n <main className=\"flex-1 overflow-y-auto overflow-x-hidden\">\n {/* User turn - hidden in fullscreen */}\n {!isFullscreen && (\n <article className=\"w-full focus:outline-none\" dir=\"auto\" data-turn=\"user\">\n <h5 className=\"sr-only\">You said:</h5>\n <div className=\"text-base my-auto mx-auto md:pt-8 px-4\">\n <div className=\"max-w-[48rem] mx-auto flex-1 relative flex w-full min-w-0 flex-col\">\n <div className=\"flex max-w-full flex-col grow\">\n <div\n data-message-author-role=\"user\"\n className=\"min-h-8 relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal\"\n >\n <div className=\"flex w-full flex-col gap-1 empty:hidden items-end\">\n <div\n className=\"relative rounded-[18px] px-4 py-3 max-w-[70%]\"\n style={{\n backgroundColor:\n 'var(--sim-bg-user-bubble, var(--color-background-tertiary))',\n }}\n >\n <div className=\"whitespace-pre-wrap\">{userMessage}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </article>\n )}\n\n {/* Assistant turn */}\n <article className=\"w-full focus:outline-none\" dir=\"auto\" data-turn=\"assistant\">\n <h6 className=\"sr-only\">{appName} said:</h6>\n <div className=\"text-base my-auto mx-auto pb-10 px-4\">\n <div className=\"max-w-[48rem] mx-auto flex-1 relative flex w-full min-w-0 flex-col\">\n <div className=\"flex max-w-full flex-col grow\">\n {/* Assistant avatar and name - hidden in fullscreen */}\n {!isFullscreen && (\n <div className=\"flex items-center gap-2 my-3\">\n {appIcon ? (\n <div className=\"size-6 flex items-center justify-center text-base\">\n {appIcon}\n </div>\n ) : (\n <div\n className=\"size-6 rounded-full flex items-center justify-center font-medium text-xs text-white\"\n style={{ backgroundColor: '#10a37f' }}\n >\n AI\n </div>\n )}\n <span className=\"font-semibold text-sm\">{appName}</span>\n </div>\n )}\n\n {/* Assistant message content */}\n <div\n data-message-author-role=\"assistant\"\n className=\"min-h-8 relative flex w-full flex-col items-start gap-2 text-start break-words whitespace-normal\"\n >\n <div className=\"flex w-full flex-col gap-1 empty:hidden\">\n {/*\n * ─── CONTENT AREA ───\n * Children (iframe) are always at this tree position.\n * CSS handles visual positioning for each display mode:\n * inline: normal flow (position: relative)\n * pip: floating overlay (position: fixed)\n * fullscreen: viewport takeover (position: fixed)\n */}\n <div\n className={\n isPip\n ? 'no-scrollbar @w-xl/main:top-4 fixed start-4 end-4 top-12 z-50 mx-auto max-w-[40rem] lg:max-w-[48rem] sm:start-0 sm:end-0 sm:top-[3.25rem] sm:w-full overflow-visible'\n : isFullscreen\n ? 'no-scrollbar fixed inset-x-0 top-[3.25rem] bottom-0 z-50 mx-auto'\n : 'no-scrollbar relative mb-2 @w-sm/main:w-full mx-0 max-sm:-mx-[1rem] max-sm:w-[100cqw] max-sm:overflow-hidden overflow-visible'\n }\n style={{\n ...(isPip ? { maxHeight: '480px' } : {}),\n ...(isFullscreen ? { maxWidth: containerWidth } : {}),\n }}\n >\n {/* PiP close button - keyed so it doesn't shift content's position */}\n {isPip && (\n <button\n key=\"pip-close\"\n onClick={handleClose}\n className=\"absolute -start-2 -top-1.5 z-10 rounded-full bg-[#3a3a3a] p-1.5 text-white shadow-[0px_0px_0px_1px_#fff3,0px_4px_12px_rgba(0,0,0,0.12)] hover:bg-[#6a6a6a]\"\n aria-label=\"Close picture-in-picture\"\n type=\"button\"\n >\n <CloseIcon className=\"h-4 w-4\" />\n </button>\n )}\n <div\n key=\"content\"\n className={\n isPip\n ? 'relative overflow-hidden h-full rounded-2xl sm:rounded-3xl shadow-[0px_0px_0px_1px_#fff3,0px_6px_20px_rgba(0,0,0,0.1)] md:-mx-4'\n : 'relative overflow-hidden h-full'\n }\n >\n <div\n className=\"h-full w-full max-w-full\"\n style={{\n ...(isPip\n ? {\n overflow: 'auto',\n backgroundColor: 'var(--color-background-primary)',\n }\n : isFullscreen\n ? {\n overflow: 'auto',\n backgroundColor: 'var(--color-background-primary)',\n }\n : { backgroundColor: 'transparent' }),\n opacity: isTransitioning ? 0 : 1,\n transition: isTransitioning ? 'none' : 'opacity 100ms',\n }}\n >\n {children}\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </article>\n </main>\n\n {/* Input area - hidden in fullscreen since fullscreen chrome has its own footer */}\n {!isFullscreen && (\n <footer\n style={{\n backgroundColor: 'var(--sim-bg-conversation, var(--color-background-primary))',\n }}\n >\n <div className=\"max-w-[48rem] mx-auto px-4 py-4\">\n <div className=\"relative\">\n <input\n type=\"text\"\n name=\"userInput\"\n disabled\n placeholder=\"Message sunpeak.ai\"\n className=\"w-full rounded-3xl px-5 py-3 pr-12 shadow-md\"\n style={{\n backgroundColor: 'var(--sim-bg-reply-input, var(--color-background-secondary))',\n color: 'var(--color-text-primary)',\n border: '1px solid var(--color-border-tertiary)',\n }}\n />\n </div>\n </div>\n </footer>\n )}\n </div>\n </div>\n );\n}\n","import type { McpUiHostCapabilities } from '@modelcontextprotocol/ext-apps';\nimport { registerHostShell } from '../simulator/hosts';\nimport { DEFAULT_STYLE_VARIABLES } from '../simulator/host-styles';\nimport { Conversation } from './chatgpt-conversation';\n\nconst CHATGPT_HOST_INFO = {\n name: 'ChatGPT',\n version: '1.0.0',\n};\n\nconst CHATGPT_HOST_CAPABILITIES: McpUiHostCapabilities = {\n openLinks: {},\n serverTools: {},\n logging: {},\n updateModelContext: { text: {} },\n message: { text: {} },\n};\n\n/**\n * Apply ChatGPT-style theming to the document.\n * Sets data-theme attribute and color-scheme for light-dark() CSS support.\n */\nfunction applyChatGPTTheme(theme: 'light' | 'dark'): void {\n document.documentElement.setAttribute('data-theme', theme);\n document.documentElement.style.colorScheme = theme;\n}\n\n/**\n * ChatGPT-specific style variable overrides.\n * Inherits defaults, overriding colors to match ChatGPT's palette.\n */\nconst CHATGPT_STYLE_VARIABLES = {\n ...DEFAULT_STYLE_VARIABLES,\n // Background colors — ChatGPT's standard palette\n '--color-background-primary': 'light-dark(#ffffff, #212121)',\n '--color-background-secondary': 'light-dark(#f7f7f8, #2f2f2f)',\n '--color-background-tertiary': 'light-dark(#ececf1, #444654)',\n '--color-background-inverse': 'light-dark(#212121, #ffffff)',\n // Text colors\n '--color-text-primary': 'light-dark(#0d0d0d, #ececec)',\n '--color-text-secondary': 'light-dark(#6e6e80, #acacbe)',\n '--color-text-tertiary': 'light-dark(#acacbe, #6e6e80)',\n '--color-text-inverse': 'light-dark(#ececec, #0d0d0d)',\n // Border colors\n '--color-border-primary': 'light-dark(#e5e5e5, #4e4e4e)',\n '--color-border-secondary': 'light-dark(#d9d9e3, #565869)',\n '--color-border-tertiary': 'light-dark(#f0f0f0, #3a3a3a)',\n};\n\nregisterHostShell({\n id: 'chatgpt',\n label: 'ChatGPT',\n Conversation,\n applyTheme: applyChatGPTTheme,\n hostInfo: CHATGPT_HOST_INFO,\n hostCapabilities: CHATGPT_HOST_CAPABILITIES,\n styleVariables: CHATGPT_STYLE_VARIABLES,\n pageStyles: {\n '--sim-bg-sidebar': 'light-dark(#f9f9f9, #181818)',\n '--sim-bg-conversation': 'light-dark(#ffffff, #212121)',\n '--sim-bg-user-bubble': 'light-dark(#f4f4f4, #303030)',\n '--sim-bg-reply-input': 'light-dark(#ffffff, #303030)',\n },\n});\n","import type { Theme, DisplayMode, DeviceType } from '../types/runtime';\n\n/**\n * Strongly-typed URL parameters for the Simulator.\n *\n * Use with `createSimulatorUrl()` to generate type-safe URL paths for e2e tests.\n *\n * @example\n * ```ts\n * import { createSimulatorUrl } from 'sunpeak/chatgpt';\n *\n * // In e2e tests:\n * await page.goto(createSimulatorUrl({\n * simulation: 'albums-show',\n * theme: 'dark',\n * displayMode: 'fullscreen',\n * host: 'claude',\n * }));\n * ```\n */\nexport interface SimulatorUrlParams {\n /**\n * The simulation name to load (e.g., 'albums-show', 'review-diff').\n * Corresponds to the simulation JSON filename without the '-simulation.json' suffix.\n */\n simulation?: string;\n\n /**\n * The host shell to use (e.g., 'chatgpt', 'claude').\n * Switches conversation chrome, theming, and reported host info/capabilities.\n * @default 'chatgpt'\n */\n host?: string;\n\n /**\n * The color theme for the simulator.\n * @default 'dark'\n */\n theme?: Theme;\n\n /**\n * The display mode for the widget.\n * - 'inline': Embedded in the conversation\n * - 'pip': Picture-in-picture mode with max height\n * - 'fullscreen': Full screen overlay\n * @default 'inline'\n */\n displayMode?: DisplayMode;\n\n /**\n * The locale for the simulator (e.g., 'en-US', 'ja-JP').\n * @default 'en-US'\n */\n locale?: string;\n\n /**\n * Maximum height in pixels for PiP mode.\n * Only applicable when displayMode is 'pip'.\n */\n maxHeight?: number;\n\n /**\n * The device type to simulate.\n * Affects default hover/touch capabilities.\n */\n deviceType?: DeviceType;\n\n /**\n * Whether the device supports hover interactions.\n * @default true for desktop, false for mobile/tablet\n */\n hover?: boolean;\n\n /**\n * Whether the device supports touch interactions.\n * @default false for desktop, true for mobile/tablet\n */\n touch?: boolean;\n\n /**\n * Safe area inset from the top of the screen (in pixels).\n * Used for devices with notches or status bars.\n */\n safeAreaTop?: number;\n\n /**\n * Safe area inset from the bottom of the screen (in pixels).\n * Used for devices with home indicators.\n */\n safeAreaBottom?: number;\n\n /**\n * Safe area inset from the left of the screen (in pixels).\n */\n safeAreaLeft?: number;\n\n /**\n * Safe area inset from the right of the screen (in pixels).\n */\n safeAreaRight?: number;\n}\n\n/**\n * Creates a URL path with query parameters for the ChatGPT Simulator.\n *\n * @param params - The simulator parameters to encode\n * @param basePath - The base path for the URL (default: '/')\n * @returns A URL path string with encoded query parameters\n *\n * @example\n * ```ts\n * // Basic usage\n * createSimulatorUrl({ simulation: 'albums-show', theme: 'light' })\n * // Returns: '/?simulation=albums-show&theme=light'\n *\n * // With display mode\n * createSimulatorUrl({\n * simulation: 'review-diff',\n * theme: 'dark',\n * displayMode: 'fullscreen',\n * })\n * // Returns: '/?simulation=review-diff&theme=dark&displayMode=fullscreen'\n *\n * // With device simulation\n * createSimulatorUrl({\n * simulation: 'map-show',\n * deviceType: 'mobile',\n * touch: true,\n * hover: false,\n * })\n * // Returns: '/?simulation=map-show&deviceType=mobile&touch=true&hover=false'\n *\n * // With safe area insets (for notch simulation)\n * createSimulatorUrl({\n * simulation: 'carousel-show',\n * safeAreaTop: 44,\n * safeAreaBottom: 34,\n * })\n * // Returns: '/?simulation=carousel-show&safeAreaTop=44&safeAreaBottom=34'\n * ```\n */\nexport function createSimulatorUrl(params: SimulatorUrlParams, basePath = '/'): string {\n const searchParams = new URLSearchParams();\n\n // Add each defined parameter\n if (params.simulation !== undefined) {\n searchParams.set('simulation', params.simulation);\n }\n if (params.host !== undefined) {\n searchParams.set('host', params.host);\n }\n if (params.theme !== undefined) {\n searchParams.set('theme', params.theme);\n }\n if (params.displayMode !== undefined) {\n searchParams.set('displayMode', params.displayMode);\n }\n if (params.locale !== undefined) {\n searchParams.set('locale', params.locale);\n }\n if (params.maxHeight !== undefined) {\n searchParams.set('maxHeight', String(params.maxHeight));\n }\n if (params.deviceType !== undefined) {\n searchParams.set('deviceType', params.deviceType);\n }\n if (params.hover !== undefined) {\n searchParams.set('hover', String(params.hover));\n }\n if (params.touch !== undefined) {\n searchParams.set('touch', String(params.touch));\n }\n if (params.safeAreaTop !== undefined) {\n searchParams.set('safeAreaTop', String(params.safeAreaTop));\n }\n if (params.safeAreaBottom !== undefined) {\n searchParams.set('safeAreaBottom', String(params.safeAreaBottom));\n }\n if (params.safeAreaLeft !== undefined) {\n searchParams.set('safeAreaLeft', String(params.safeAreaLeft));\n }\n if (params.safeAreaRight !== undefined) {\n searchParams.set('safeAreaRight', String(params.safeAreaRight));\n }\n const queryString = searchParams.toString();\n return queryString ? `${basePath}?${queryString}` : basePath;\n}\n"],"names":[],"mappings":"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"}