sunpeak 0.16.5 → 0.16.9
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 +0 -2
- package/bin/commands/build.mjs +19 -16
- package/bin/commands/dev.mjs +7 -6
- package/bin/commands/new.mjs +69 -40
- package/dist/chatgpt/index.cjs +2 -2
- package/dist/chatgpt/index.js +2 -2
- package/dist/claude/index.cjs +1 -1
- package/dist/claude/index.js +1 -1
- package/dist/{index-Bll1bszc.cjs → index-ByfnqReC.cjs} +2 -2
- package/dist/{index-Bll1bszc.cjs.map → index-ByfnqReC.cjs.map} +1 -1
- package/dist/{index-CLcr8IyR.js → index-CuZQ3nqW.js} +2 -2
- package/dist/index-CuZQ3nqW.js.map +1 -0
- package/dist/{index-CaQmwZJc.cjs → index-CvZ0BZ0R.cjs} +2 -2
- package/dist/index-CvZ0BZ0R.cjs.map +1 -0
- package/dist/{index-CACtnwu2.js → index-D3h7o2YP.js} +2 -2
- package/dist/{index-CACtnwu2.js.map → index-D3h7o2YP.js.map} +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.js +3 -3
- package/dist/simulator/index.cjs +1 -1
- package/dist/simulator/index.js +1 -1
- package/dist/{simulator-B7rw83zP.js → simulator-BGHFdLfD.js} +11 -2
- package/dist/{simulator-B7rw83zP.js.map → simulator-BGHFdLfD.js.map} +1 -1
- package/dist/{simulator-DjZNa1MI.cjs → simulator-DYM74GCT.cjs} +10 -1
- package/dist/{simulator-DjZNa1MI.cjs.map → simulator-DYM74GCT.cjs.map} +1 -1
- package/package.json +3 -2
- package/template/src/resources/review/review.tsx +133 -21
- package/dist/index-CLcr8IyR.js.map +0 -1
- package/dist/index-CaQmwZJc.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -43,8 +43,6 @@ pnpm add -g sunpeak
|
|
|
43
43
|
sunpeak new
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
To add `sunpeak` to an existing project, refer to the [documentation](https://sunpeak.ai/docs/add-to-existing-project).
|
|
47
|
-
|
|
48
46
|
## Overview
|
|
49
47
|
|
|
50
48
|
`sunpeak` is an npm package that helps you build MCP Apps (interactive UI resources) while keeping your MCP server client-agnostic. Built on the [MCP Apps SDK](https://github.com/modelcontextprotocol/ext-apps) (`@modelcontextprotocol/ext-apps`). `sunpeak` consists of:
|
package/bin/commands/build.mjs
CHANGED
|
@@ -49,7 +49,8 @@ function resolveEsmEntry(require, packageName) {
|
|
|
49
49
|
* Build all resources for a Sunpeak project
|
|
50
50
|
* Runs in the context of a user's project directory
|
|
51
51
|
*/
|
|
52
|
-
export async function build(projectRoot = process.cwd()) {
|
|
52
|
+
export async function build(projectRoot = process.cwd(), { quiet = false } = {}) {
|
|
53
|
+
const log = quiet ? () => {} : console.log.bind(console);
|
|
53
54
|
|
|
54
55
|
// Check for package.json first
|
|
55
56
|
const pkgJsonPath = path.join(projectRoot, 'package.json');
|
|
@@ -191,7 +192,7 @@ export async function build(projectRoot = process.cwd()) {
|
|
|
191
192
|
process.exit(1);
|
|
192
193
|
}
|
|
193
194
|
|
|
194
|
-
|
|
195
|
+
log('Building all resources...\n');
|
|
195
196
|
|
|
196
197
|
// Read and validate the template
|
|
197
198
|
const template = readFileSync(templateFile, 'utf-8');
|
|
@@ -214,7 +215,7 @@ export async function build(projectRoot = process.cwd()) {
|
|
|
214
215
|
// Build all resources (but don't copy yet)
|
|
215
216
|
for (let i = 0; i < resourceFiles.length; i++) {
|
|
216
217
|
const { componentName, componentFile, kebabName, entry, jsOutput, buildOutDir } = resourceFiles[i];
|
|
217
|
-
|
|
218
|
+
log(`[${i + 1}/${resourceFiles.length}] Building ${kebabName}...`);
|
|
218
219
|
|
|
219
220
|
try {
|
|
220
221
|
// Create build directory if it doesn't exist
|
|
@@ -234,6 +235,7 @@ export async function build(projectRoot = process.cwd()) {
|
|
|
234
235
|
await viteBuild({
|
|
235
236
|
mode: 'production',
|
|
236
237
|
root: projectRoot,
|
|
238
|
+
...(quiet && { logLevel: 'silent' }),
|
|
237
239
|
plugins: [react(), tailwindcss(), inlineCssPlugin(buildOutDir)],
|
|
238
240
|
define: {
|
|
239
241
|
'process.env.NODE_ENV': JSON.stringify('production'),
|
|
@@ -277,7 +279,7 @@ export async function build(projectRoot = process.cwd()) {
|
|
|
277
279
|
}
|
|
278
280
|
|
|
279
281
|
// Now copy all files from build-output to dist/{resource}/
|
|
280
|
-
|
|
282
|
+
log('\nCopying built files to dist/...');
|
|
281
283
|
const timestamp = Date.now().toString(36);
|
|
282
284
|
|
|
283
285
|
for (const { jsOutput, htmlOutput, buildOutDir, distOutDir, kebabName, componentFile, resourceDir } of resourceFiles) {
|
|
@@ -296,7 +298,7 @@ export async function build(projectRoot = process.cwd()) {
|
|
|
296
298
|
// Generate URI using resource name and build timestamp
|
|
297
299
|
meta.uri = `ui://${meta.name}-${timestamp}`;
|
|
298
300
|
writeFileSync(destJson, JSON.stringify(meta, null, 2));
|
|
299
|
-
|
|
301
|
+
log(`✓ Generated ${kebabName}/${kebabName}.json (uri: ${meta.uri})`);
|
|
300
302
|
|
|
301
303
|
// Read built JS file and wrap in HTML shell
|
|
302
304
|
const builtJsFile = path.join(buildOutDir, jsOutput);
|
|
@@ -318,13 +320,13 @@ ${jsContents}
|
|
|
318
320
|
</body>
|
|
319
321
|
</html>`;
|
|
320
322
|
writeFileSync(destHtmlFile, html);
|
|
321
|
-
|
|
323
|
+
log(`✓ Built ${kebabName}/${htmlOutput}`);
|
|
322
324
|
} else {
|
|
323
325
|
console.error(`Built file not found: ${builtJsFile}`);
|
|
324
326
|
if (existsSync(buildOutDir)) {
|
|
325
|
-
|
|
327
|
+
log(` Files in ${buildOutDir}:`, readdirSync(buildOutDir));
|
|
326
328
|
} else {
|
|
327
|
-
|
|
329
|
+
log(` Build directory doesn't exist: ${buildOutDir}`);
|
|
328
330
|
}
|
|
329
331
|
process.exit(1);
|
|
330
332
|
}
|
|
@@ -339,10 +341,10 @@ ${jsContents}
|
|
|
339
341
|
rmSync(buildDir, { recursive: true });
|
|
340
342
|
}
|
|
341
343
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
+
log('\n✓ All resources built successfully!');
|
|
345
|
+
log('\nBuilt resources:');
|
|
344
346
|
for (const { kebabName } of resourceFiles) {
|
|
345
|
-
|
|
347
|
+
log(` ${kebabName}`);
|
|
346
348
|
}
|
|
347
349
|
|
|
348
350
|
// ========================================================================
|
|
@@ -360,7 +362,7 @@ ${jsContents}
|
|
|
360
362
|
const hasServerEntry = existsSync(serverEntryPath);
|
|
361
363
|
|
|
362
364
|
if (toolFiles.length > 0 || hasServerEntry) {
|
|
363
|
-
|
|
365
|
+
log('\nCompiling server-side code...');
|
|
364
366
|
|
|
365
367
|
let esbuild;
|
|
366
368
|
try {
|
|
@@ -407,7 +409,7 @@ ${jsContents}
|
|
|
407
409
|
loader: { '.tsx': 'tsx', '.ts': 'ts' },
|
|
408
410
|
logLevel: 'warning',
|
|
409
411
|
});
|
|
410
|
-
|
|
412
|
+
log(`✓ Compiled tools/${toolName}.js`);
|
|
411
413
|
} catch (err) {
|
|
412
414
|
console.error(`Failed to compile tool ${toolName}:`, err.message);
|
|
413
415
|
process.exit(1);
|
|
@@ -439,7 +441,7 @@ ${jsContents}
|
|
|
439
441
|
loader: { '.tsx': 'tsx', '.ts': 'ts' },
|
|
440
442
|
logLevel: 'warning',
|
|
441
443
|
});
|
|
442
|
-
|
|
444
|
+
log(`✓ Compiled server.js`);
|
|
443
445
|
} catch (err) {
|
|
444
446
|
console.error(`Failed to compile server entry:`, err.message);
|
|
445
447
|
process.exit(1);
|
|
@@ -448,12 +450,13 @@ ${jsContents}
|
|
|
448
450
|
}
|
|
449
451
|
}
|
|
450
452
|
|
|
451
|
-
|
|
453
|
+
log('\n✓ Build complete!');
|
|
452
454
|
}
|
|
453
455
|
|
|
454
456
|
// Allow running directly
|
|
455
457
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
456
|
-
|
|
458
|
+
const quiet = process.argv.includes('--quiet');
|
|
459
|
+
build(process.cwd(), { quiet }).catch(error => {
|
|
457
460
|
console.error(error);
|
|
458
461
|
process.exit(1);
|
|
459
462
|
});
|
package/bin/commands/dev.mjs
CHANGED
|
@@ -66,17 +66,17 @@ function startBuildWatcher(projectRoot, resourcesDir, mcpHandle) {
|
|
|
66
66
|
let activeChild = null;
|
|
67
67
|
const sunpeakBin = join(dirname(new URL(import.meta.url).pathname), '..', 'sunpeak.js');
|
|
68
68
|
|
|
69
|
-
const runBuild = (
|
|
69
|
+
const runBuild = () => {
|
|
70
70
|
// Kill any in-progress build and start fresh
|
|
71
71
|
if (activeChild) {
|
|
72
72
|
activeChild.kill('SIGTERM');
|
|
73
73
|
activeChild = null;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
console.log(`[build]
|
|
77
|
-
const child = spawn(process.execPath, [sunpeakBin, 'build'], {
|
|
76
|
+
console.log(`[build] Building resources for the MCP server for non-ChatGPT hosts...`);
|
|
77
|
+
const child = spawn(process.execPath, [sunpeakBin, 'build', '--quiet'], {
|
|
78
78
|
cwd: projectRoot,
|
|
79
|
-
stdio: ['ignore', '
|
|
79
|
+
stdio: ['ignore', 'pipe', 'inherit'],
|
|
80
80
|
env: { ...process.env, NODE_ENV: 'production' },
|
|
81
81
|
});
|
|
82
82
|
activeChild = child;
|
|
@@ -85,6 +85,7 @@ function startBuildWatcher(projectRoot, resourcesDir, mcpHandle) {
|
|
|
85
85
|
if (child !== activeChild) return; // Superseded by a newer build
|
|
86
86
|
activeChild = null;
|
|
87
87
|
if (code === 0) {
|
|
88
|
+
console.log(`[build] Built resources for the MCP server for non-ChatGPT hosts.`);
|
|
88
89
|
// Notify non-local sessions (Claude, etc.) that resources changed
|
|
89
90
|
mcpHandle?.invalidateResources();
|
|
90
91
|
} else if (code !== null) {
|
|
@@ -94,7 +95,7 @@ function startBuildWatcher(projectRoot, resourcesDir, mcpHandle) {
|
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
// Initial build
|
|
97
|
-
runBuild(
|
|
98
|
+
runBuild();
|
|
98
99
|
|
|
99
100
|
// Watch src/resources/ for changes using fs.watch (recursive supported on macOS/Windows)
|
|
100
101
|
let debounceTimer = null;
|
|
@@ -108,7 +109,7 @@ function startBuildWatcher(projectRoot, resourcesDir, mcpHandle) {
|
|
|
108
109
|
|
|
109
110
|
clearTimeout(debounceTimer);
|
|
110
111
|
debounceTimer = setTimeout(() => {
|
|
111
|
-
runBuild(
|
|
112
|
+
runBuild();
|
|
112
113
|
}, 500);
|
|
113
114
|
});
|
|
114
115
|
console.log('[build] Watching src/resources/ for changes...');
|
package/bin/commands/new.mjs
CHANGED
|
@@ -2,26 +2,59 @@
|
|
|
2
2
|
import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync, renameSync } from 'fs';
|
|
3
3
|
import { join, dirname, basename } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { execSync, exec } from 'child_process';
|
|
6
|
+
import { promisify } from 'util';
|
|
7
|
+
|
|
8
|
+
const execAsync = promisify(exec);
|
|
9
|
+
import * as clack from '@clack/prompts';
|
|
7
10
|
import { discoverResources } from '../lib/patterns.mjs';
|
|
8
11
|
import { detectPackageManager } from '../utils.mjs';
|
|
9
12
|
|
|
10
13
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
|
-
* Default prompt
|
|
14
|
-
* @param {string} question
|
|
16
|
+
* Default prompt for project name using clack text input.
|
|
15
17
|
* @returns {Promise<string>}
|
|
16
18
|
*/
|
|
17
|
-
function
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
async function defaultPromptName() {
|
|
20
|
+
const value = await clack.text({
|
|
21
|
+
message: 'Project name',
|
|
22
|
+
placeholder: 'my-app',
|
|
23
|
+
defaultValue: 'my-app',
|
|
24
|
+
validate: (v) => {
|
|
25
|
+
if (v === 'template') return '"template" is a reserved name';
|
|
26
|
+
},
|
|
24
27
|
});
|
|
28
|
+
if (clack.isCancel(value)) {
|
|
29
|
+
clack.cancel('Cancelled.');
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Default resource selection using clack multiselect.
|
|
37
|
+
* @param {string[]} availableResources
|
|
38
|
+
* @returns {Promise<string[]>}
|
|
39
|
+
*/
|
|
40
|
+
async function defaultSelectResources(availableResources) {
|
|
41
|
+
const selected = await clack.multiselect({
|
|
42
|
+
message: 'Resources (UIs) to include (space to toggle)',
|
|
43
|
+
options: (() => {
|
|
44
|
+
const maxLen = Math.max(...availableResources.map((r) => r.length));
|
|
45
|
+
return availableResources.map((r) => ({
|
|
46
|
+
value: r,
|
|
47
|
+
label: `${r.padEnd(maxLen)} (https://sunpeak.ai/docs/api-reference/resources/${r})`,
|
|
48
|
+
}));
|
|
49
|
+
})(),
|
|
50
|
+
initialValues: availableResources,
|
|
51
|
+
required: true,
|
|
52
|
+
});
|
|
53
|
+
if (clack.isCancel(selected)) {
|
|
54
|
+
clack.cancel('Cancelled.');
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
return selected;
|
|
25
58
|
}
|
|
26
59
|
|
|
27
60
|
/**
|
|
@@ -37,7 +70,12 @@ export const defaultDeps = {
|
|
|
37
70
|
writeFileSync,
|
|
38
71
|
renameSync,
|
|
39
72
|
execSync,
|
|
40
|
-
|
|
73
|
+
execAsync,
|
|
74
|
+
promptName: defaultPromptName,
|
|
75
|
+
selectResources: defaultSelectResources,
|
|
76
|
+
intro: clack.intro,
|
|
77
|
+
outro: clack.outro,
|
|
78
|
+
spinner: clack.spinner,
|
|
41
79
|
console,
|
|
42
80
|
process,
|
|
43
81
|
cwd: () => process.cwd(),
|
|
@@ -88,6 +126,8 @@ export function parseResourcesInput(input, validResources, deps = defaultDeps) {
|
|
|
88
126
|
export async function init(projectName, resourcesArg, deps = defaultDeps) {
|
|
89
127
|
const d = { ...defaultDeps, ...deps };
|
|
90
128
|
|
|
129
|
+
d.intro('☀️ sunpeak');
|
|
130
|
+
|
|
91
131
|
// Discover available resources from template
|
|
92
132
|
const availableResources = d.discoverResources();
|
|
93
133
|
if (availableResources.length === 0) {
|
|
@@ -96,10 +136,7 @@ export async function init(projectName, resourcesArg, deps = defaultDeps) {
|
|
|
96
136
|
}
|
|
97
137
|
|
|
98
138
|
if (!projectName) {
|
|
99
|
-
projectName = await d.
|
|
100
|
-
if (!projectName) {
|
|
101
|
-
projectName = 'my-app';
|
|
102
|
-
}
|
|
139
|
+
projectName = await d.promptName();
|
|
103
140
|
}
|
|
104
141
|
|
|
105
142
|
if (projectName === 'template') {
|
|
@@ -107,17 +144,13 @@ export async function init(projectName, resourcesArg, deps = defaultDeps) {
|
|
|
107
144
|
d.process.exit(1);
|
|
108
145
|
}
|
|
109
146
|
|
|
110
|
-
// Use resources from args or
|
|
111
|
-
let
|
|
112
|
-
if (resourcesArg) {
|
|
113
|
-
|
|
114
|
-
d.console.log(`☀️ 🏔️ Resources: ${resourcesArg}`);
|
|
147
|
+
// Use resources from args or interactively select them
|
|
148
|
+
let selectedResources;
|
|
149
|
+
if (resourcesArg !== undefined) {
|
|
150
|
+
selectedResources = parseResourcesInput(resourcesArg, availableResources, d);
|
|
115
151
|
} else {
|
|
116
|
-
|
|
117
|
-
`☀️ 🏔️ Resources (UIs) to include [${availableResources.join(', ')}]: `
|
|
118
|
-
);
|
|
152
|
+
selectedResources = await d.selectResources(availableResources);
|
|
119
153
|
}
|
|
120
|
-
const selectedResources = parseResourcesInput(resourcesInput, availableResources, d);
|
|
121
154
|
|
|
122
155
|
const targetDir = join(d.cwd(), projectName);
|
|
123
156
|
|
|
@@ -126,13 +159,11 @@ export async function init(projectName, resourcesArg, deps = defaultDeps) {
|
|
|
126
159
|
d.process.exit(1);
|
|
127
160
|
}
|
|
128
161
|
|
|
129
|
-
d.console.log(`☀️ 🏔️ Creating ${projectName}...`);
|
|
130
|
-
|
|
131
|
-
d.mkdirSync(targetDir, { recursive: true });
|
|
132
|
-
|
|
133
162
|
// Filter resource directories based on selection
|
|
134
163
|
const excludedResources = availableResources.filter((r) => !selectedResources.includes(r));
|
|
135
164
|
|
|
165
|
+
d.mkdirSync(targetDir, { recursive: true });
|
|
166
|
+
|
|
136
167
|
d.cpSync(d.templateDir, targetDir, {
|
|
137
168
|
recursive: true,
|
|
138
169
|
filter: (src) => {
|
|
@@ -223,32 +254,30 @@ export async function init(projectName, resourcesArg, deps = defaultDeps) {
|
|
|
223
254
|
|
|
224
255
|
d.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
225
256
|
|
|
226
|
-
//
|
|
257
|
+
// Install dependencies with spinner
|
|
227
258
|
const pm = d.detectPackageManager();
|
|
228
|
-
d.
|
|
259
|
+
const s = d.spinner();
|
|
260
|
+
s.start(`Installing dependencies with ${pm}...`);
|
|
229
261
|
|
|
230
262
|
try {
|
|
231
|
-
d.
|
|
263
|
+
await d.execAsync(`${pm} install`, { cwd: targetDir });
|
|
264
|
+
s.stop(`Installed dependencies with ${pm}`);
|
|
232
265
|
} catch {
|
|
233
|
-
|
|
266
|
+
s.stop(`Install failed. You can try running "${pm} install" manually.`);
|
|
234
267
|
}
|
|
235
268
|
|
|
236
269
|
const runCmd = pm === 'npm' ? 'npm run' : pm;
|
|
237
270
|
|
|
238
|
-
d.
|
|
239
|
-
Done! To get started:
|
|
271
|
+
d.outro(`Done! To get started:
|
|
240
272
|
|
|
241
273
|
cd ${projectName}
|
|
242
274
|
sunpeak dev
|
|
243
275
|
|
|
244
|
-
|
|
276
|
+
Your project commands:
|
|
245
277
|
|
|
246
278
|
sunpeak dev # Start dev server + MCP endpoint
|
|
247
279
|
sunpeak build # Build for production
|
|
248
|
-
${runCmd} test # Run tests
|
|
249
|
-
|
|
250
|
-
See README.md for more details.
|
|
251
|
-
`);
|
|
280
|
+
${runCmd} test # Run tests`);
|
|
252
281
|
}
|
|
253
282
|
|
|
254
283
|
// Allow running directly
|
package/dist/chatgpt/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const simulator = require("../simulator-
|
|
4
|
-
const chatgpt_index = require("../index-
|
|
3
|
+
const simulator = require("../simulator-DYM74GCT.cjs");
|
|
4
|
+
const chatgpt_index = require("../index-ByfnqReC.cjs");
|
|
5
5
|
const simulatorUrl = require("../simulator-url-rgg_KYOg.cjs");
|
|
6
6
|
const discovery = require("../discovery-DmB8_4QL.cjs");
|
|
7
7
|
exports.IframeResource = simulator.IframeResource;
|
package/dist/chatgpt/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { I, M, a, S, T, j, m } from "../simulator-
|
|
2
|
-
import { C } from "../index-
|
|
1
|
+
import { I, M, a, S, T, j, m } from "../simulator-BGHFdLfD.js";
|
|
2
|
+
import { C } from "../index-D3h7o2YP.js";
|
|
3
3
|
import { c } from "../simulator-url-CuLqtnSS.js";
|
|
4
4
|
import { b, a as a2, c as c2, d, e, f, g, h, i, t } from "../discovery-CH80W5l9.js";
|
|
5
5
|
export {
|
package/dist/claude/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const simulator = require("../simulator-
|
|
3
|
+
const simulator = require("../simulator-DYM74GCT.cjs");
|
|
4
4
|
exports.ClaudeSimulator = simulator.Simulator;
|
|
5
5
|
//# sourceMappingURL=index.cjs.map
|
package/dist/claude/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const simulator = require("./simulator-
|
|
2
|
+
const simulator = require("./simulator-DYM74GCT.cjs");
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const React = require("react");
|
|
5
5
|
const simulatorUrl = require("./simulator-url-rgg_KYOg.cjs");
|
|
@@ -521,4 +521,4 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
521
521
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
522
522
|
exports.ChatGPTSimulator = ChatGPTSimulator;
|
|
523
523
|
exports.index = index;
|
|
524
|
-
//# sourceMappingURL=index-
|
|
524
|
+
//# sourceMappingURL=index-ByfnqReC.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-Bll1bszc.cjs","sources":["../src/chatgpt/chatgpt-simulator.tsx"],"sourcesContent":["import * as React from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n SimpleSidebar,\n SidebarControl,\n SidebarCollapsibleControl,\n SidebarSelect,\n SidebarInput,\n SidebarCheckbox,\n SidebarTextarea,\n SidebarToggle,\n} from '../simulator/simple-sidebar';\nimport { Conversation } from './chatgpt-conversation';\nimport { IframeResource, extractResourceCSP } from '../simulator/iframe-resource';\nimport { ThemeProvider } from '../simulator/theme-provider';\nimport type {\n McpUiHostContext,\n McpUiDisplayMode,\n McpUiTheme,\n} from '@modelcontextprotocol/ext-apps';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ScreenWidth } from '../simulator/simulator-types';\nimport type { Simulation } from '../types/simulation';\n\ntype Platform = NonNullable<McpUiHostContext['platform']>;\n\nconst DEFAULT_THEME: McpUiTheme = 'dark';\nconst DEFAULT_DISPLAY_MODE: McpUiDisplayMode = 'inline';\nconst DEFAULT_PLATFORM: Platform = 'desktop';\n\ninterface ChatGPTSimulatorProps {\n children?: React.ReactNode;\n simulations?: Record<string, Simulation>;\n appName?: string;\n appIcon?: string;\n}\n\n/**\n * Parse URL params for initial simulator values.\n * Supported params:\n * - simulation: simulation name (e.g., 'show-albums')\n * - theme: 'light' | 'dark'\n * - displayMode: 'inline' | 'pip' | 'fullscreen'\n * - locale: e.g., 'en-US'\n * - maxHeight: number (for pip mode)\n * - deviceType: 'mobile' | 'tablet' | 'desktop' → maps to platform\n * - hover: 'true' | 'false'\n * - touch: 'true' | 'false'\n * - safeAreaTop, safeAreaBottom, safeAreaLeft, safeAreaRight: number\n * - host: 'chatgpt' | 'claude'\n */\nfunction parseUrlParams(): {\n simulation?: string;\n theme?: McpUiTheme;\n displayMode?: McpUiDisplayMode;\n locale?: string;\n containerMaxHeight?: number;\n platform?: Platform;\n deviceCapabilities?: { hover?: boolean; touch?: boolean };\n safeAreaInsets?: { top: number; bottom: number; left: number; right: number };\n} {\n if (typeof window === 'undefined') return {};\n\n const params = new URLSearchParams(window.location.search);\n\n const simulation = params.get('simulation') ?? undefined;\n const theme = params.get('theme') as McpUiTheme | null;\n const displayMode = params.get('displayMode') as McpUiDisplayMode | null;\n const locale = params.get('locale');\n const maxHeightParam = params.get('maxHeight');\n const containerMaxHeight = maxHeightParam ? Number(maxHeightParam) : undefined;\n\n // Map deviceType param to MCP Apps platform\n const deviceType = params.get('deviceType');\n let platform: Platform | undefined;\n if (deviceType === 'mobile' || deviceType === 'tablet') {\n platform = 'mobile';\n } else if (deviceType === 'desktop') {\n platform = 'desktop';\n }\n\n // Device capabilities\n const hoverParam = params.get('hover');\n const touchParam = params.get('touch');\n const hasCapParams = hoverParam || touchParam;\n const deviceCapabilities = hasCapParams\n ? {\n hover: hoverParam === 'false' ? false : true,\n touch: touchParam === 'true' ? true : false,\n }\n : undefined;\n\n // Safe area insets\n const safeAreaTop = params.get('safeAreaTop');\n const safeAreaBottom = params.get('safeAreaBottom');\n const safeAreaLeft = params.get('safeAreaLeft');\n const safeAreaRight = params.get('safeAreaRight');\n const hasSafeAreaParams = safeAreaTop || safeAreaBottom || safeAreaLeft || safeAreaRight;\n const safeAreaInsets = hasSafeAreaParams\n ? {\n top: safeAreaTop ? Number(safeAreaTop) : 0,\n bottom: safeAreaBottom ? Number(safeAreaBottom) : 0,\n left: safeAreaLeft ? Number(safeAreaLeft) : 0,\n right: safeAreaRight ? Number(safeAreaRight) : 0,\n }\n : undefined;\n\n return {\n simulation,\n theme: theme ?? undefined,\n displayMode: displayMode ?? undefined,\n locale: locale ?? undefined,\n containerMaxHeight,\n platform,\n deviceCapabilities,\n safeAreaInsets,\n };\n}\n\nexport function ChatGPTSimulator({\n children,\n simulations = {},\n appName = 'Sunpeak',\n appIcon,\n}: ChatGPTSimulatorProps) {\n const simulationNames = Object.keys(simulations);\n const urlParams = useMemo(() => parseUrlParams(), []);\n const [screenWidth, setScreenWidth] = React.useState<ScreenWidth>('full');\n\n const isMobileWidth = (width: ScreenWidth) => width === 'mobile-s' || width === 'mobile-l';\n\n // Find initial simulation from URL params\n const initialSimulationName = useMemo(() => {\n const defaultName = simulationNames[0] ?? '';\n if (!urlParams.simulation) return defaultName;\n return urlParams.simulation in simulations ? urlParams.simulation : defaultName;\n }, [urlParams.simulation, simulations, simulationNames]);\n\n const [selectedSimulationName, setSelectedSimulationName] =\n React.useState<string>(initialSimulationName);\n\n const selectedSim = simulations[selectedSimulationName];\n\n // ── Host context state ──────────────────────────────────────────\n\n const [theme, setTheme] = useState<McpUiTheme>(urlParams.theme ?? DEFAULT_THEME);\n const [displayMode, _setDisplayMode] = useState<McpUiDisplayMode>(\n urlParams.displayMode ?? DEFAULT_DISPLAY_MODE\n );\n const [locale, setLocale] = useState(urlParams.locale ?? 'en-US');\n const [containerMaxHeight, setContainerMaxHeight] = useState(urlParams.containerMaxHeight ?? 480);\n const [platform, setPlatform] = useState<Platform>(urlParams.platform ?? DEFAULT_PLATFORM);\n const [hover, setHover] = useState(urlParams.deviceCapabilities?.hover ?? true);\n const [touch, setTouch] = useState(urlParams.deviceCapabilities?.touch ?? false);\n const [safeAreaInsets, setSafeAreaInsets] = useState(\n urlParams.safeAreaInsets ?? { top: 0, bottom: 0, left: 0, right: 0 }\n );\n\n // Display mode setter that respects mobile width constraints\n const setDisplayMode = (mode: McpUiDisplayMode) => {\n if (isMobileWidth(screenWidth) && mode === 'pip') {\n _setDisplayMode('fullscreen');\n } else {\n _setDisplayMode(mode);\n }\n };\n\n // Track which display mode the iframe has confirmed rendering.\n // Content is hidden when displayMode !== readyDisplayMode (transition in progress).\n // Initialized to displayMode so there's no transition on first render.\n const [readyDisplayMode, setReadyDisplayMode] = useState<McpUiDisplayMode>(\n urlParams.displayMode ?? DEFAULT_DISPLAY_MODE\n );\n\n const handleDisplayModeReady = useCallback((mode: string) => {\n setReadyDisplayMode(mode as McpUiDisplayMode);\n }, []);\n\n // Build host context from state\n const hostContext = useMemo<McpUiHostContext>(\n () => ({\n theme,\n displayMode,\n locale,\n platform,\n deviceCapabilities: { hover, touch },\n safeAreaInsets,\n ...(displayMode === 'pip' ? { containerDimensions: { maxHeight: containerMaxHeight } } : {}),\n }),\n [theme, displayMode, locale, platform, hover, touch, safeAreaInsets, containerMaxHeight]\n );\n\n // ── Tool data state ─────────────────────────────────────────────\n\n // Parsed tool data (sent to host/iframe)\n const [toolInput, setToolInput] = useState<Record<string, unknown>>(\n () => selectedSim?.toolInput ?? {}\n );\n const [toolResult, setToolResult] = useState<CallToolResult | undefined>(\n () => selectedSim?.toolResult as CallToolResult | undefined\n );\n\n // Editable JSON strings for sidebar\n const [toolInputJson, setToolInputJson] = useState(() => JSON.stringify(toolInput, null, 2));\n const [toolResultJson, setToolResultJson] = useState(() =>\n JSON.stringify(toolResult ?? null, null, 2)\n );\n\n // Model context - bidirectional: shows what app sends, editable to inject state back\n // When edited, gets merged into toolResult.structuredContent to send to app\n const [modelContextJson, setModelContextJson] = useState<string>('null');\n const [modelContext, setModelContext] = useState<Record<string, unknown> | null>(null);\n\n // Track which field is being edited to prevent reset loops\n const [editingField, setEditingField] = useState<string | null>(null);\n\n // JSON validation errors\n const [toolInputError, setToolInputError] = useState('');\n const [toolResultError, setToolResultError] = useState('');\n const [modelContextError, setModelContextError] = useState('');\n\n // Reset tool data when simulation changes\n // Note: editingField is intentionally NOT in deps - we check it inside to guard\n // against overwriting user edits, but we don't want changes to editingField\n // to trigger a re-run (which would reset values when editing ends)\n useEffect(() => {\n const newInput = selectedSim?.toolInput ?? {};\n const newResult = (selectedSim?.toolResult as CallToolResult | undefined) ?? undefined;\n setToolInput(newInput);\n setToolResult(newResult);\n if (editingField !== 'toolInput') {\n setToolInputJson(JSON.stringify(newInput, null, 2));\n setToolInputError('');\n }\n if (editingField !== 'toolResult') {\n setToolResultJson(JSON.stringify(newResult ?? null, null, 2));\n setToolResultError('');\n }\n if (editingField !== 'modelContext') {\n setModelContextJson('null');\n setModelContext(null);\n setModelContextError('');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selectedSimulationName, selectedSim]);\n\n // Disallow PiP on mobile widths\n useEffect(() => {\n if (isMobileWidth(screenWidth) && displayMode === 'pip') {\n _setDisplayMode('fullscreen');\n }\n }, [screenWidth, displayMode]);\n\n // ── Host callbacks ──────────────────────────────────────────────\n\n const handleDisplayModeChange = (mode: McpUiDisplayMode) => {\n setDisplayMode(mode);\n };\n\n const handleUpdateModelContext = (content: unknown[], structuredContent?: unknown) => {\n setModelContextJson(JSON.stringify(structuredContent ?? content, null, 2));\n };\n\n // ── JSON helpers ────────────────────────────────────────────────\n\n const validateJSON = (\n json: string,\n setJson: (value: string) => void,\n setError: (error: string) => void\n ) => {\n setJson(json);\n try {\n if (json.trim() !== '') JSON.parse(json);\n setError('');\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Invalid JSON');\n }\n };\n\n const commitJSON = (\n json: string,\n setError: (error: string) => void,\n updateFn: (value: Record<string, unknown> | null) => void\n ) => {\n try {\n const parsed = json.trim() === '' ? null : JSON.parse(json);\n setError('');\n updateFn(parsed);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Invalid JSON');\n } finally {\n setEditingField(null);\n }\n };\n\n // ── Content rendering ───────────────────────────────────────────\n\n // Merge modelContext into toolResult.structuredContent when sending to app\n // This simulates a host that round-trips app state (like ChatGPT's widgetState)\n const effectiveToolResult = useMemo((): CallToolResult | undefined => {\n if (!toolResult && !modelContext) return undefined;\n if (!modelContext) return toolResult;\n\n // Merge modelContext into structuredContent\n const baseResult = toolResult ?? { content: [] };\n const baseStructured = (baseResult.structuredContent as Record<string, unknown>) ?? {};\n return {\n ...baseResult,\n structuredContent: { ...baseStructured, ...modelContext },\n };\n }, [toolResult, modelContext]);\n\n // Get resource URL (dev mode) or script URL (production)\n const resourceUrl = selectedSim?.resourceUrl;\n const resourceScript = selectedSim?.resourceScript;\n\n const csp = selectedSim ? extractResourceCSP(selectedSim.resource) : undefined;\n\n // Build content based on rendering mode.\n // All rendering goes through IframeResource for consistent behavior with ChatGPT.\n const hasIframeContent = !!(resourceUrl || resourceScript);\n\n // Content is transitioning when the display mode has changed but the iframe\n // hasn't yet confirmed it has rendered with the new mode.\n // For non-iframe content (children), there's no async rendering so no transition.\n const isTransitioning = hasIframeContent && displayMode !== readyDisplayMode;\n\n let content: React.ReactNode;\n if (resourceUrl) {\n // Dev mode: load HTML page directly (supports Vite HMR)\n content = (\n <IframeResource\n src={resourceUrl}\n hostContext={hostContext}\n toolInput={toolInput}\n toolResult={effectiveToolResult}\n hostOptions={{\n onDisplayModeChange: handleDisplayModeChange,\n onUpdateModelContext: handleUpdateModelContext,\n }}\n onDisplayModeReady={handleDisplayModeReady}\n debugInjectState={modelContext}\n className=\"h-full w-full\"\n />\n );\n } else if (resourceScript) {\n // Production mode: generate HTML wrapper for script\n content = (\n <IframeResource\n scriptSrc={resourceScript}\n hostContext={hostContext}\n toolInput={toolInput}\n toolResult={effectiveToolResult}\n csp={csp}\n hostOptions={{\n onDisplayModeChange: handleDisplayModeChange,\n onUpdateModelContext: handleUpdateModelContext,\n }}\n onDisplayModeReady={handleDisplayModeReady}\n debugInjectState={modelContext}\n className=\"h-full w-full\"\n />\n );\n } else {\n content = children;\n }\n\n return (\n <ThemeProvider theme={theme}>\n <SimpleSidebar\n controls={\n <div className=\"space-y-2\">\n {simulationNames.length > 1 && (\n <SidebarControl label=\"Simulation\">\n <SidebarSelect\n value={selectedSimulationName}\n onChange={(value) => setSelectedSimulationName(value)}\n options={simulationNames.map((name) => {\n const sim = simulations[name];\n const resourceTitle =\n (sim.resource.title as string | undefined) || sim.resource.name;\n const toolTitle = (sim.tool.title as string | undefined) || sim.tool.name;\n return {\n value: name,\n label: `${resourceTitle}: ${toolTitle}`,\n };\n })}\n />\n </SidebarControl>\n )}\n\n <SidebarControl label=\"Simulation Width\">\n <SidebarSelect\n value={screenWidth}\n onChange={(value) => setScreenWidth(value as ScreenWidth)}\n options={[\n { value: 'mobile-s', label: 'Mobile S (375px)' },\n { value: 'mobile-l', label: 'Mobile L (425px)' },\n { value: 'tablet', label: 'Tablet (768px)' },\n { value: 'full', label: '100% (Full)' },\n ]}\n />\n </SidebarControl>\n\n <SidebarCollapsibleControl label=\"Host Context\" defaultCollapsed={false}>\n <div className=\"space-y-2\">\n <SidebarControl label=\"Theme\">\n <SidebarToggle\n value={theme}\n onChange={(value) => setTheme(value as McpUiTheme)}\n options={[\n { value: 'light', label: 'Light' },\n { value: 'dark', label: 'Dark' },\n ]}\n />\n </SidebarControl>\n\n <SidebarControl label=\"Display Mode\">\n <SidebarToggle\n value={displayMode}\n onChange={(value) => setDisplayMode(value as McpUiDisplayMode)}\n options={[\n { value: 'inline', label: 'Inline' },\n { value: 'pip', label: 'PiP' },\n { value: 'fullscreen', label: 'Full' },\n ]}\n />\n </SidebarControl>\n\n <div className=\"grid grid-cols-2 gap-2\">\n <SidebarControl label=\"Locale\">\n <SidebarInput\n value={locale}\n onChange={(value) => setLocale(value)}\n placeholder=\"e.g. en-US\"\n />\n </SidebarControl>\n\n <SidebarControl label=\"Max Height (PiP)\">\n <SidebarInput\n type=\"number\"\n value={\n displayMode === 'pip' && containerMaxHeight !== undefined\n ? String(containerMaxHeight)\n : ''\n }\n onChange={(value) => {\n if (displayMode === 'pip') {\n setContainerMaxHeight(value ? Number(value) : 480);\n }\n }}\n placeholder={displayMode === 'pip' ? '480' : '-'}\n disabled={displayMode !== 'pip'}\n />\n </SidebarControl>\n </div>\n\n <SidebarControl label=\"Platform\">\n <SidebarSelect\n value={platform}\n onChange={(value) => {\n const p = value as Platform;\n setPlatform(p);\n // Set appropriate default capabilities based on platform\n if (p === 'mobile') {\n setHover(false);\n setTouch(true);\n } else if (p === 'desktop') {\n setHover(true);\n setTouch(false);\n } else {\n setHover(true);\n setTouch(false);\n }\n }}\n options={[\n { value: 'mobile', label: 'Mobile' },\n { value: 'desktop', label: 'Desktop' },\n { value: 'web', label: 'Web' },\n ]}\n />\n </SidebarControl>\n\n <div className=\"pl-4\">\n <SidebarControl label=\"Device Capabilities\">\n <div className=\"flex gap-2\">\n <SidebarCheckbox checked={hover} onChange={setHover} label=\"Hover\" />\n <SidebarCheckbox checked={touch} onChange={setTouch} label=\"Touch\" />\n </div>\n </SidebarControl>\n </div>\n\n <SidebarControl label=\"Safe Area Insets\">\n <div className=\"grid grid-cols-4 gap-1\">\n <div className=\"flex items-center gap-0.5\">\n <span\n className=\"text-[10px]\"\n style={{ color: 'var(--color-text-secondary)' }}\n >\n ↑\n </span>\n <SidebarInput\n type=\"number\"\n value={String(safeAreaInsets.top)}\n onChange={(value) =>\n setSafeAreaInsets((prev) => ({ ...prev, top: Number(value) }))\n }\n />\n </div>\n <div className=\"flex items-center gap-0.5\">\n <span\n className=\"text-[10px]\"\n style={{ color: 'var(--color-text-secondary)' }}\n >\n ↓\n </span>\n <SidebarInput\n type=\"number\"\n value={String(safeAreaInsets.bottom)}\n onChange={(value) =>\n setSafeAreaInsets((prev) => ({ ...prev, bottom: Number(value) }))\n }\n />\n </div>\n <div className=\"flex items-center gap-0.5\">\n <span\n className=\"text-[10px]\"\n style={{ color: 'var(--color-text-secondary)' }}\n >\n ←\n </span>\n <SidebarInput\n type=\"number\"\n value={String(safeAreaInsets.left)}\n onChange={(value) =>\n setSafeAreaInsets((prev) => ({ ...prev, left: Number(value) }))\n }\n />\n </div>\n <div className=\"flex items-center gap-0.5\">\n <span\n className=\"text-[10px]\"\n style={{ color: 'var(--color-text-secondary)' }}\n >\n →\n </span>\n <SidebarInput\n type=\"number\"\n value={String(safeAreaInsets.right)}\n onChange={(value) =>\n setSafeAreaInsets((prev) => ({ ...prev, right: Number(value) }))\n }\n />\n </div>\n </div>\n </SidebarControl>\n </div>\n </SidebarCollapsibleControl>\n\n <SidebarCollapsibleControl label=\"App Context\" defaultCollapsed>\n <SidebarTextarea\n value={modelContextJson}\n onChange={(json) => validateJSON(json, setModelContextJson, setModelContextError)}\n onFocus={() => setEditingField('modelContext')}\n onBlur={() =>\n commitJSON(modelContextJson, setModelContextError, (parsed) => {\n setModelContext(parsed as Record<string, unknown> | null);\n })\n }\n error={modelContextError}\n maxRows={8}\n />\n </SidebarCollapsibleControl>\n\n <SidebarCollapsibleControl label=\"Tool Input (JSON)\">\n <SidebarTextarea\n value={toolInputJson}\n onChange={(json) => validateJSON(json, setToolInputJson, setToolInputError)}\n onFocus={() => setEditingField('toolInput')}\n onBlur={() =>\n commitJSON(toolInputJson, setToolInputError, (parsed) =>\n setToolInput((parsed as Record<string, unknown>) ?? {})\n )\n }\n error={toolInputError}\n maxRows={8}\n />\n </SidebarCollapsibleControl>\n\n <SidebarCollapsibleControl label=\"Tool Result (JSON)\">\n <SidebarTextarea\n value={toolResultJson}\n onChange={(json) => validateJSON(json, setToolResultJson, setToolResultError)}\n onFocus={() => setEditingField('toolResult')}\n onBlur={() =>\n commitJSON(toolResultJson, setToolResultError, (parsed) => {\n if (parsed === null) {\n setToolResult(undefined);\n } else {\n // Wrap raw object as structuredContent in a CallToolResult\n const result = parsed as Record<string, unknown>;\n if ('content' in result || 'structuredContent' in result) {\n setToolResult(result as CallToolResult);\n } else {\n setToolResult({ content: [], structuredContent: result });\n }\n }\n })\n }\n error={toolResultError}\n maxRows={8}\n />\n </SidebarCollapsibleControl>\n </div>\n }\n >\n <Conversation\n screenWidth={screenWidth}\n displayMode={displayMode}\n platform={platform}\n onRequestDisplayMode={handleDisplayModeChange}\n appName={appName}\n appIcon={appIcon}\n userMessage={selectedSim?.userMessage}\n isTransitioning={isTransitioning}\n key={selectedSimulationName}\n >\n {content}\n </Conversation>\n </SimpleSidebar>\n </ThemeProvider>\n );\n}\n"],"names":["useMemo","React","useState","useCallback","useEffect","content","extractResourceCSP","jsx","IframeResource","ThemeProvider","SimpleSidebar","jsxs","SidebarControl","SidebarSelect","SidebarCollapsibleControl","SidebarToggle","SidebarInput","SidebarCheckbox","SidebarTextarea","Conversation"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-ByfnqReC.cjs","sources":["../src/chatgpt/chatgpt-simulator.tsx"],"sourcesContent":["import * as React from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n SimpleSidebar,\n SidebarControl,\n SidebarCollapsibleControl,\n SidebarSelect,\n SidebarInput,\n SidebarCheckbox,\n SidebarTextarea,\n SidebarToggle,\n} from '../simulator/simple-sidebar';\nimport { Conversation } from './chatgpt-conversation';\nimport { IframeResource, extractResourceCSP } from '../simulator/iframe-resource';\nimport { ThemeProvider } from '../simulator/theme-provider';\nimport type {\n McpUiHostContext,\n McpUiDisplayMode,\n McpUiTheme,\n} from '@modelcontextprotocol/ext-apps';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ScreenWidth } from '../simulator/simulator-types';\nimport type { Simulation } from '../types/simulation';\n\ntype Platform = NonNullable<McpUiHostContext['platform']>;\n\nconst DEFAULT_THEME: McpUiTheme = 'dark';\nconst DEFAULT_DISPLAY_MODE: McpUiDisplayMode = 'inline';\nconst DEFAULT_PLATFORM: Platform = 'desktop';\n\ninterface ChatGPTSimulatorProps {\n children?: React.ReactNode;\n simulations?: Record<string, Simulation>;\n appName?: string;\n appIcon?: string;\n}\n\n/**\n * Parse URL params for initial simulator values.\n * Supported params:\n * - simulation: simulation name (e.g., 'show-albums')\n * - theme: 'light' | 'dark'\n * - displayMode: 'inline' | 'pip' | 'fullscreen'\n * - locale: e.g., 'en-US'\n * - maxHeight: number (for pip mode)\n * - deviceType: 'mobile' | 'tablet' | 'desktop' → maps to platform\n * - hover: 'true' | 'false'\n * - touch: 'true' | 'false'\n * - safeAreaTop, safeAreaBottom, safeAreaLeft, safeAreaRight: number\n * - host: 'chatgpt' | 'claude'\n */\nfunction parseUrlParams(): {\n simulation?: string;\n theme?: McpUiTheme;\n displayMode?: McpUiDisplayMode;\n locale?: string;\n containerMaxHeight?: number;\n platform?: Platform;\n deviceCapabilities?: { hover?: boolean; touch?: boolean };\n safeAreaInsets?: { top: number; bottom: number; left: number; right: number };\n} {\n if (typeof window === 'undefined') return {};\n\n const params = new URLSearchParams(window.location.search);\n\n const simulation = params.get('simulation') ?? undefined;\n const theme = params.get('theme') as McpUiTheme | null;\n const displayMode = params.get('displayMode') as McpUiDisplayMode | null;\n const locale = params.get('locale');\n const maxHeightParam = params.get('maxHeight');\n const containerMaxHeight = maxHeightParam ? Number(maxHeightParam) : undefined;\n\n // Map deviceType param to MCP Apps platform\n const deviceType = params.get('deviceType');\n let platform: Platform | undefined;\n if (deviceType === 'mobile' || deviceType === 'tablet') {\n platform = 'mobile';\n } else if (deviceType === 'desktop') {\n platform = 'desktop';\n }\n\n // Device capabilities\n const hoverParam = params.get('hover');\n const touchParam = params.get('touch');\n const hasCapParams = hoverParam || touchParam;\n const deviceCapabilities = hasCapParams\n ? {\n hover: hoverParam === 'false' ? false : true,\n touch: touchParam === 'true' ? true : false,\n }\n : undefined;\n\n // Safe area insets\n const safeAreaTop = params.get('safeAreaTop');\n const safeAreaBottom = params.get('safeAreaBottom');\n const safeAreaLeft = params.get('safeAreaLeft');\n const safeAreaRight = params.get('safeAreaRight');\n const hasSafeAreaParams = safeAreaTop || safeAreaBottom || safeAreaLeft || safeAreaRight;\n const safeAreaInsets = hasSafeAreaParams\n ? {\n top: safeAreaTop ? Number(safeAreaTop) : 0,\n bottom: safeAreaBottom ? Number(safeAreaBottom) : 0,\n left: safeAreaLeft ? Number(safeAreaLeft) : 0,\n right: safeAreaRight ? Number(safeAreaRight) : 0,\n }\n : undefined;\n\n return {\n simulation,\n theme: theme ?? undefined,\n displayMode: displayMode ?? undefined,\n locale: locale ?? undefined,\n containerMaxHeight,\n platform,\n deviceCapabilities,\n safeAreaInsets,\n };\n}\n\nexport function ChatGPTSimulator({\n children,\n simulations = {},\n appName = 'Sunpeak',\n appIcon,\n}: ChatGPTSimulatorProps) {\n const simulationNames = Object.keys(simulations);\n const urlParams = useMemo(() => parseUrlParams(), []);\n const [screenWidth, setScreenWidth] = React.useState<ScreenWidth>('full');\n\n const isMobileWidth = (width: ScreenWidth) => width === 'mobile-s' || width === 'mobile-l';\n\n // Find initial simulation from URL params\n const initialSimulationName = useMemo(() => {\n const defaultName = simulationNames[0] ?? '';\n if (!urlParams.simulation) return defaultName;\n return urlParams.simulation in simulations ? urlParams.simulation : defaultName;\n }, [urlParams.simulation, simulations, simulationNames]);\n\n const [selectedSimulationName, setSelectedSimulationName] =\n React.useState<string>(initialSimulationName);\n\n const selectedSim = simulations[selectedSimulationName];\n\n // ── Host context state ──────────────────────────────────────────\n\n const [theme, setTheme] = useState<McpUiTheme>(urlParams.theme ?? DEFAULT_THEME);\n const [displayMode, _setDisplayMode] = useState<McpUiDisplayMode>(\n urlParams.displayMode ?? DEFAULT_DISPLAY_MODE\n );\n const [locale, setLocale] = useState(urlParams.locale ?? 'en-US');\n const [containerMaxHeight, setContainerMaxHeight] = useState(urlParams.containerMaxHeight ?? 480);\n const [platform, setPlatform] = useState<Platform>(urlParams.platform ?? DEFAULT_PLATFORM);\n const [hover, setHover] = useState(urlParams.deviceCapabilities?.hover ?? true);\n const [touch, setTouch] = useState(urlParams.deviceCapabilities?.touch ?? false);\n const [safeAreaInsets, setSafeAreaInsets] = useState(\n urlParams.safeAreaInsets ?? { top: 0, bottom: 0, left: 0, right: 0 }\n );\n\n // Display mode setter that respects mobile width constraints\n const setDisplayMode = (mode: McpUiDisplayMode) => {\n if (isMobileWidth(screenWidth) && mode === 'pip') {\n _setDisplayMode('fullscreen');\n } else {\n _setDisplayMode(mode);\n }\n };\n\n // Track which display mode the iframe has confirmed rendering.\n // Content is hidden when displayMode !== readyDisplayMode (transition in progress).\n // Initialized to displayMode so there's no transition on first render.\n const [readyDisplayMode, setReadyDisplayMode] = useState<McpUiDisplayMode>(\n urlParams.displayMode ?? DEFAULT_DISPLAY_MODE\n );\n\n const handleDisplayModeReady = useCallback((mode: string) => {\n setReadyDisplayMode(mode as McpUiDisplayMode);\n }, []);\n\n // Build host context from state\n const hostContext = useMemo<McpUiHostContext>(\n () => ({\n theme,\n displayMode,\n locale,\n platform,\n deviceCapabilities: { hover, touch },\n safeAreaInsets,\n ...(displayMode === 'pip' ? { containerDimensions: { maxHeight: containerMaxHeight } } : {}),\n }),\n [theme, displayMode, locale, platform, hover, touch, safeAreaInsets, containerMaxHeight]\n );\n\n // ── Tool data state ─────────────────────────────────────────────\n\n // Parsed tool data (sent to host/iframe)\n const [toolInput, setToolInput] = useState<Record<string, unknown>>(\n () => selectedSim?.toolInput ?? {}\n );\n const [toolResult, setToolResult] = useState<CallToolResult | undefined>(\n () => selectedSim?.toolResult as CallToolResult | undefined\n );\n\n // Editable JSON strings for sidebar\n const [toolInputJson, setToolInputJson] = useState(() => JSON.stringify(toolInput, null, 2));\n const [toolResultJson, setToolResultJson] = useState(() =>\n JSON.stringify(toolResult ?? null, null, 2)\n );\n\n // Model context - bidirectional: shows what app sends, editable to inject state back\n // When edited, gets merged into toolResult.structuredContent to send to app\n const [modelContextJson, setModelContextJson] = useState<string>('null');\n const [modelContext, setModelContext] = useState<Record<string, unknown> | null>(null);\n\n // Track which field is being edited to prevent reset loops\n const [editingField, setEditingField] = useState<string | null>(null);\n\n // JSON validation errors\n const [toolInputError, setToolInputError] = useState('');\n const [toolResultError, setToolResultError] = useState('');\n const [modelContextError, setModelContextError] = useState('');\n\n // Reset tool data when simulation changes\n // Note: editingField is intentionally NOT in deps - we check it inside to guard\n // against overwriting user edits, but we don't want changes to editingField\n // to trigger a re-run (which would reset values when editing ends)\n useEffect(() => {\n const newInput = selectedSim?.toolInput ?? {};\n const newResult = (selectedSim?.toolResult as CallToolResult | undefined) ?? undefined;\n setToolInput(newInput);\n setToolResult(newResult);\n if (editingField !== 'toolInput') {\n setToolInputJson(JSON.stringify(newInput, null, 2));\n setToolInputError('');\n }\n if (editingField !== 'toolResult') {\n setToolResultJson(JSON.stringify(newResult ?? null, null, 2));\n setToolResultError('');\n }\n if (editingField !== 'modelContext') {\n setModelContextJson('null');\n setModelContext(null);\n setModelContextError('');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selectedSimulationName, selectedSim]);\n\n // Disallow PiP on mobile widths\n useEffect(() => {\n if (isMobileWidth(screenWidth) && displayMode === 'pip') {\n _setDisplayMode('fullscreen');\n }\n }, [screenWidth, displayMode]);\n\n // ── Host callbacks ──────────────────────────────────────────────\n\n const handleDisplayModeChange = (mode: McpUiDisplayMode) => {\n setDisplayMode(mode);\n };\n\n const handleUpdateModelContext = (content: unknown[], structuredContent?: unknown) => {\n setModelContextJson(JSON.stringify(structuredContent ?? content, null, 2));\n };\n\n // ── JSON helpers ────────────────────────────────────────────────\n\n const validateJSON = (\n json: string,\n setJson: (value: string) => void,\n setError: (error: string) => void\n ) => {\n setJson(json);\n try {\n if (json.trim() !== '') JSON.parse(json);\n setError('');\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Invalid JSON');\n }\n };\n\n const commitJSON = (\n json: string,\n setError: (error: string) => void,\n updateFn: (value: Record<string, unknown> | null) => void\n ) => {\n try {\n const parsed = json.trim() === '' ? null : JSON.parse(json);\n setError('');\n updateFn(parsed);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Invalid JSON');\n } finally {\n setEditingField(null);\n }\n };\n\n // ── Content rendering ───────────────────────────────────────────\n\n // Merge modelContext into toolResult.structuredContent when sending to app\n // This simulates a host that round-trips app state (like ChatGPT's widgetState)\n const effectiveToolResult = useMemo((): CallToolResult | undefined => {\n if (!toolResult && !modelContext) return undefined;\n if (!modelContext) return toolResult;\n\n // Merge modelContext into structuredContent\n const baseResult = toolResult ?? { content: [] };\n const baseStructured = (baseResult.structuredContent as Record<string, unknown>) ?? {};\n return {\n ...baseResult,\n structuredContent: { ...baseStructured, ...modelContext },\n };\n }, [toolResult, modelContext]);\n\n // Get resource URL (dev mode) or script URL (production)\n const resourceUrl = selectedSim?.resourceUrl;\n const resourceScript = selectedSim?.resourceScript;\n\n const csp = selectedSim ? extractResourceCSP(selectedSim.resource) : undefined;\n\n // Build content based on rendering mode.\n // All rendering goes through IframeResource for consistent behavior with ChatGPT.\n const hasIframeContent = !!(resourceUrl || resourceScript);\n\n // Content is transitioning when the display mode has changed but the iframe\n // hasn't yet confirmed it has rendered with the new mode.\n // For non-iframe content (children), there's no async rendering so no transition.\n const isTransitioning = hasIframeContent && displayMode !== readyDisplayMode;\n\n let content: React.ReactNode;\n if (resourceUrl) {\n // Dev mode: load HTML page directly (supports Vite HMR)\n content = (\n <IframeResource\n src={resourceUrl}\n hostContext={hostContext}\n toolInput={toolInput}\n toolResult={effectiveToolResult}\n hostOptions={{\n onDisplayModeChange: handleDisplayModeChange,\n onUpdateModelContext: handleUpdateModelContext,\n }}\n onDisplayModeReady={handleDisplayModeReady}\n debugInjectState={modelContext}\n className=\"h-full w-full\"\n />\n );\n } else if (resourceScript) {\n // Production mode: generate HTML wrapper for script\n content = (\n <IframeResource\n scriptSrc={resourceScript}\n hostContext={hostContext}\n toolInput={toolInput}\n toolResult={effectiveToolResult}\n csp={csp}\n hostOptions={{\n onDisplayModeChange: handleDisplayModeChange,\n onUpdateModelContext: handleUpdateModelContext,\n }}\n onDisplayModeReady={handleDisplayModeReady}\n debugInjectState={modelContext}\n className=\"h-full w-full\"\n />\n );\n } else {\n content = children;\n }\n\n return (\n <ThemeProvider theme={theme}>\n <SimpleSidebar\n controls={\n <div className=\"space-y-2\">\n {simulationNames.length > 1 && (\n <SidebarControl label=\"Simulation\">\n <SidebarSelect\n value={selectedSimulationName}\n onChange={(value) => setSelectedSimulationName(value)}\n options={simulationNames.map((name) => {\n const sim = simulations[name];\n const resourceTitle =\n (sim.resource.title as string | undefined) || sim.resource.name;\n const toolTitle = (sim.tool.title as string | undefined) || sim.tool.name;\n return {\n value: name,\n label: `${resourceTitle}: ${toolTitle}`,\n };\n })}\n />\n </SidebarControl>\n )}\n\n <SidebarControl label=\"Simulation Width\">\n <SidebarSelect\n value={screenWidth}\n onChange={(value) => setScreenWidth(value as ScreenWidth)}\n options={[\n { value: 'mobile-s', label: 'Mobile S (375px)' },\n { value: 'mobile-l', label: 'Mobile L (425px)' },\n { value: 'tablet', label: 'Tablet (768px)' },\n { value: 'full', label: '100% (Full)' },\n ]}\n />\n </SidebarControl>\n\n <SidebarCollapsibleControl label=\"Host Context\" defaultCollapsed={false}>\n <div className=\"space-y-2\">\n <SidebarControl label=\"Theme\">\n <SidebarToggle\n value={theme}\n onChange={(value) => setTheme(value as McpUiTheme)}\n options={[\n { value: 'light', label: 'Light' },\n { value: 'dark', label: 'Dark' },\n ]}\n />\n </SidebarControl>\n\n <SidebarControl label=\"Display Mode\">\n <SidebarToggle\n value={displayMode}\n onChange={(value) => setDisplayMode(value as McpUiDisplayMode)}\n options={[\n { value: 'inline', label: 'Inline' },\n { value: 'pip', label: 'PiP' },\n { value: 'fullscreen', label: 'Full' },\n ]}\n />\n </SidebarControl>\n\n <div className=\"grid grid-cols-2 gap-2\">\n <SidebarControl label=\"Locale\">\n <SidebarInput\n value={locale}\n onChange={(value) => setLocale(value)}\n placeholder=\"e.g. en-US\"\n />\n </SidebarControl>\n\n <SidebarControl label=\"Max Height (PiP)\">\n <SidebarInput\n type=\"number\"\n value={\n displayMode === 'pip' && containerMaxHeight !== undefined\n ? String(containerMaxHeight)\n : ''\n }\n onChange={(value) => {\n if (displayMode === 'pip') {\n setContainerMaxHeight(value ? Number(value) : 480);\n }\n }}\n placeholder={displayMode === 'pip' ? '480' : '-'}\n disabled={displayMode !== 'pip'}\n />\n </SidebarControl>\n </div>\n\n <SidebarControl label=\"Platform\">\n <SidebarSelect\n value={platform}\n onChange={(value) => {\n const p = value as Platform;\n setPlatform(p);\n // Set appropriate default capabilities based on platform\n if (p === 'mobile') {\n setHover(false);\n setTouch(true);\n } else if (p === 'desktop') {\n setHover(true);\n setTouch(false);\n } else {\n setHover(true);\n setTouch(false);\n }\n }}\n options={[\n { value: 'mobile', label: 'Mobile' },\n { value: 'desktop', label: 'Desktop' },\n { value: 'web', label: 'Web' },\n ]}\n />\n </SidebarControl>\n\n <div className=\"pl-4\">\n <SidebarControl label=\"Device Capabilities\">\n <div className=\"flex gap-2\">\n <SidebarCheckbox checked={hover} onChange={setHover} label=\"Hover\" />\n <SidebarCheckbox checked={touch} onChange={setTouch} label=\"Touch\" />\n </div>\n </SidebarControl>\n </div>\n\n <SidebarControl label=\"Safe Area Insets\">\n <div className=\"grid grid-cols-4 gap-1\">\n <div className=\"flex items-center gap-0.5\">\n <span\n className=\"text-[10px]\"\n style={{ color: 'var(--color-text-secondary)' }}\n >\n ↑\n </span>\n <SidebarInput\n type=\"number\"\n value={String(safeAreaInsets.top)}\n onChange={(value) =>\n setSafeAreaInsets((prev) => ({ ...prev, top: Number(value) }))\n }\n />\n </div>\n <div className=\"flex items-center gap-0.5\">\n <span\n className=\"text-[10px]\"\n style={{ color: 'var(--color-text-secondary)' }}\n >\n ↓\n </span>\n <SidebarInput\n type=\"number\"\n value={String(safeAreaInsets.bottom)}\n onChange={(value) =>\n setSafeAreaInsets((prev) => ({ ...prev, bottom: Number(value) }))\n }\n />\n </div>\n <div className=\"flex items-center gap-0.5\">\n <span\n className=\"text-[10px]\"\n style={{ color: 'var(--color-text-secondary)' }}\n >\n ←\n </span>\n <SidebarInput\n type=\"number\"\n value={String(safeAreaInsets.left)}\n onChange={(value) =>\n setSafeAreaInsets((prev) => ({ ...prev, left: Number(value) }))\n }\n />\n </div>\n <div className=\"flex items-center gap-0.5\">\n <span\n className=\"text-[10px]\"\n style={{ color: 'var(--color-text-secondary)' }}\n >\n →\n </span>\n <SidebarInput\n type=\"number\"\n value={String(safeAreaInsets.right)}\n onChange={(value) =>\n setSafeAreaInsets((prev) => ({ ...prev, right: Number(value) }))\n }\n />\n </div>\n </div>\n </SidebarControl>\n </div>\n </SidebarCollapsibleControl>\n\n <SidebarCollapsibleControl label=\"App Context\" defaultCollapsed>\n <SidebarTextarea\n value={modelContextJson}\n onChange={(json) => validateJSON(json, setModelContextJson, setModelContextError)}\n onFocus={() => setEditingField('modelContext')}\n onBlur={() =>\n commitJSON(modelContextJson, setModelContextError, (parsed) => {\n setModelContext(parsed as Record<string, unknown> | null);\n })\n }\n error={modelContextError}\n maxRows={8}\n />\n </SidebarCollapsibleControl>\n\n <SidebarCollapsibleControl label=\"Tool Input (JSON)\">\n <SidebarTextarea\n value={toolInputJson}\n onChange={(json) => validateJSON(json, setToolInputJson, setToolInputError)}\n onFocus={() => setEditingField('toolInput')}\n onBlur={() =>\n commitJSON(toolInputJson, setToolInputError, (parsed) =>\n setToolInput((parsed as Record<string, unknown>) ?? {})\n )\n }\n error={toolInputError}\n maxRows={8}\n />\n </SidebarCollapsibleControl>\n\n <SidebarCollapsibleControl label=\"Tool Result (JSON)\">\n <SidebarTextarea\n value={toolResultJson}\n onChange={(json) => validateJSON(json, setToolResultJson, setToolResultError)}\n onFocus={() => setEditingField('toolResult')}\n onBlur={() =>\n commitJSON(toolResultJson, setToolResultError, (parsed) => {\n if (parsed === null) {\n setToolResult(undefined);\n } else {\n // Wrap raw object as structuredContent in a CallToolResult\n const result = parsed as Record<string, unknown>;\n if ('content' in result || 'structuredContent' in result) {\n setToolResult(result as CallToolResult);\n } else {\n setToolResult({ content: [], structuredContent: result });\n }\n }\n })\n }\n error={toolResultError}\n maxRows={8}\n />\n </SidebarCollapsibleControl>\n </div>\n }\n >\n <Conversation\n screenWidth={screenWidth}\n displayMode={displayMode}\n platform={platform}\n onRequestDisplayMode={handleDisplayModeChange}\n appName={appName}\n appIcon={appIcon}\n userMessage={selectedSim?.userMessage}\n isTransitioning={isTransitioning}\n key={selectedSimulationName}\n >\n {content}\n </Conversation>\n </SimpleSidebar>\n </ThemeProvider>\n );\n}\n"],"names":["useMemo","React","useState","useCallback","useEffect","content","extractResourceCSP","jsx","IframeResource","ThemeProvider","SimpleSidebar","jsxs","SidebarControl","SidebarSelect","SidebarCollapsibleControl","SidebarToggle","SidebarInput","SidebarCheckbox","SidebarTextarea","Conversation"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, b as SidebarCheckbox, c as SidebarCollapsibleControl, d as SidebarControl, e as SidebarInput, f as SidebarSelect, g as SidebarTextarea, h as SidebarToggle, i as SimpleSidebar, S as Simulator, T as ThemeProvider, j as extractResourceCSP, k as getHostShell, l as getRegisteredHosts, r as registerHostShell, u as useSimulatorState, m as useThemeContext } from "./simulator-
|
|
1
|
+
import { I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, b as SidebarCheckbox, c as SidebarCollapsibleControl, d as SidebarControl, e as SidebarInput, f as SidebarSelect, g as SidebarTextarea, h as SidebarToggle, i as SimpleSidebar, S as Simulator, T as ThemeProvider, j as extractResourceCSP, k as getHostShell, l as getRegisteredHosts, r as registerHostShell, u as useSimulatorState, m as useThemeContext } from "./simulator-BGHFdLfD.js";
|
|
2
2
|
import { c as createSimulatorUrl } from "./simulator-url-CuLqtnSS.js";
|
|
3
3
|
import { b as buildDevSimulations, a as buildResourceMap, c as buildSimulations, d as createResourceExports, e as extractResourceKey, f as extractSimulationKey, g as findResourceDirs, h as findResourceKey, i as getComponentName, t as toPascalCase } from "./discovery-CH80W5l9.js";
|
|
4
4
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -37,4 +37,4 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
37
37
|
export {
|
|
38
38
|
index as i
|
|
39
39
|
};
|
|
40
|
-
//# sourceMappingURL=index-
|
|
40
|
+
//# sourceMappingURL=index-CuZQ3nqW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CuZQ3nqW.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const simulator = require("./simulator-
|
|
2
|
+
const simulator = require("./simulator-DYM74GCT.cjs");
|
|
3
3
|
const simulatorUrl = require("./simulator-url-rgg_KYOg.cjs");
|
|
4
4
|
const discovery = require("./discovery-DmB8_4QL.cjs");
|
|
5
5
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -36,4 +36,4 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
36
36
|
useThemeContext: simulator.useThemeContext
|
|
37
37
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
38
38
|
exports.index = index;
|
|
39
|
-
//# sourceMappingURL=index-
|
|
39
|
+
//# sourceMappingURL=index-CvZ0BZ0R.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CvZ0BZ0R.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|