sunpeak 0.15.4 → 0.16.2

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 (105) hide show
  1. package/README.md +53 -49
  2. package/bin/commands/build.mjs +119 -6
  3. package/bin/commands/dev.mjs +168 -27
  4. package/bin/commands/new.mjs +13 -3
  5. package/bin/commands/start.mjs +215 -0
  6. package/bin/lib/extract-resource.mjs +1 -1
  7. package/bin/lib/extract-tool.mjs +78 -0
  8. package/bin/lib/patterns.mjs +2 -26
  9. package/bin/sunpeak.js +11 -1
  10. package/dist/chatgpt/index.cjs +3 -6
  11. package/dist/chatgpt/index.cjs.map +1 -1
  12. package/dist/chatgpt/index.d.ts +1 -1
  13. package/dist/chatgpt/index.js +6 -9
  14. package/dist/claude/index.cjs +1 -1
  15. package/dist/claude/index.js +1 -1
  16. package/dist/discovery-CH80W5l9.js +217 -0
  17. package/dist/discovery-CH80W5l9.js.map +1 -0
  18. package/dist/discovery-DmB8_4QL.cjs +216 -0
  19. package/dist/discovery-DmB8_4QL.cjs.map +1 -0
  20. package/dist/{index-Cngntkp2.cjs → index-Bll1bszc.cjs} +3 -6
  21. package/dist/{index-Cngntkp2.cjs.map → index-Bll1bszc.cjs.map} +1 -1
  22. package/dist/{index-Ce_5ZIdJ.js → index-CACtnwu2.js} +3 -6
  23. package/dist/{index-Ce_5ZIdJ.js.map → index-CACtnwu2.js.map} +1 -1
  24. package/dist/{index-CutQgPzR.js → index-CLcr8IyR.js} +3 -6
  25. package/dist/index-CLcr8IyR.js.map +1 -0
  26. package/dist/{index-B0dxRJvS.cjs → index-CaQmwZJc.cjs} +3 -6
  27. package/dist/index-CaQmwZJc.cjs.map +1 -0
  28. package/dist/index.cjs +49 -6
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.js +3405 -3362
  32. package/dist/index.js.map +1 -1
  33. package/dist/lib/discovery-cli.cjs +58 -5
  34. package/dist/lib/discovery-cli.cjs.map +1 -1
  35. package/dist/lib/discovery-cli.d.ts +3 -2
  36. package/dist/lib/discovery-cli.js +61 -8
  37. package/dist/lib/discovery-cli.js.map +1 -1
  38. package/dist/lib/discovery.d.ts +42 -43
  39. package/dist/lib/extract-tool.d.ts +12 -0
  40. package/dist/mcp/favicon.d.ts +1 -1
  41. package/dist/mcp/index.cjs +1582 -5
  42. package/dist/mcp/index.cjs.map +1 -1
  43. package/dist/mcp/index.d.ts +3 -1
  44. package/dist/mcp/index.js +1583 -6
  45. package/dist/mcp/index.js.map +1 -1
  46. package/dist/mcp/production-server.d.ts +156 -0
  47. package/dist/mcp/types.d.ts +24 -1
  48. package/dist/platform/chatgpt/index.cjs +1 -1
  49. package/dist/platform/chatgpt/index.js +1 -1
  50. package/dist/{protocol-DFbsCx7E.js → protocol-BD5jDQEx.js} +8 -1
  51. package/dist/{protocol-DFbsCx7E.js.map → protocol-BD5jDQEx.js.map} +1 -1
  52. package/dist/{protocol-CL4_Npj5.cjs → protocol-BOjXuK6l.cjs} +8 -1
  53. package/dist/{protocol-CL4_Npj5.cjs.map → protocol-BOjXuK6l.cjs.map} +1 -1
  54. package/dist/simulator/index.cjs +2 -5
  55. package/dist/simulator/index.cjs.map +1 -1
  56. package/dist/simulator/index.d.ts +1 -1
  57. package/dist/simulator/index.js +5 -8
  58. package/dist/simulator/simulator-url.d.ts +9 -9
  59. package/dist/{simulator-CxrtnguM.js → simulator-B7rw83zP.js} +9 -3
  60. package/dist/{simulator-CxrtnguM.js.map → simulator-B7rw83zP.js.map} +1 -1
  61. package/dist/{simulator-DcfQBRXE.cjs → simulator-DjZNa1MI.cjs} +9 -3
  62. package/dist/{simulator-DcfQBRXE.cjs.map → simulator-DjZNa1MI.cjs.map} +1 -1
  63. package/dist/simulator-url-CuLqtnSS.js.map +1 -1
  64. package/dist/simulator-url-rgg_KYOg.cjs.map +1 -1
  65. package/dist/types/resource-config.d.ts +7 -5
  66. package/dist/{use-app-BnoSPiUT.cjs → use-app-BpAJqzdE.cjs} +50 -21
  67. package/dist/{use-app-BnoSPiUT.cjs.map → use-app-BpAJqzdE.cjs.map} +1 -1
  68. package/dist/{use-app-D_TeaMFG.js → use-app-WOUdh1PR.js} +52 -23
  69. package/dist/{use-app-D_TeaMFG.js.map → use-app-WOUdh1PR.js.map} +1 -1
  70. package/package.json +1 -1
  71. package/template/.sunpeak/dev.tsx +8 -4
  72. package/template/.sunpeak/resource-loader.tsx +2 -1
  73. package/template/README.md +27 -22
  74. package/template/package.json +3 -1
  75. package/template/src/resources/albums/{albums-resource.test.tsx → albums.test.tsx} +1 -1
  76. package/template/src/resources/albums/{albums-resource.tsx → albums.tsx} +0 -1
  77. package/template/src/resources/carousel/{carousel-resource.test.tsx → carousel.test.tsx} +1 -1
  78. package/template/src/resources/carousel/{carousel-resource.tsx → carousel.tsx} +0 -1
  79. package/template/src/resources/index.ts +4 -4
  80. package/template/src/resources/map/{map-resource.test.tsx → map.test.tsx} +1 -1
  81. package/template/src/resources/map/{map-resource.tsx → map.tsx} +0 -1
  82. package/template/src/resources/review/{review-resource.test.tsx → review.test.tsx} +1 -1
  83. package/template/src/resources/review/{review-resource.tsx → review.tsx} +1 -2
  84. package/template/src/server.ts +17 -0
  85. package/template/src/tools/review-diff.ts +24 -0
  86. package/template/src/tools/review-post.ts +26 -0
  87. package/template/src/tools/review-purchase.ts +31 -0
  88. package/template/src/tools/show-albums.ts +22 -0
  89. package/template/src/tools/show-carousel.ts +25 -0
  90. package/template/src/tools/show-map.ts +29 -0
  91. package/template/tests/e2e/albums.spec.ts +6 -6
  92. package/template/tests/e2e/carousel.spec.ts +6 -6
  93. package/template/tests/e2e/map.spec.ts +11 -11
  94. package/template/tests/simulations/{review/review-diff-simulation.json → review-diff.json} +1 -31
  95. package/template/tests/simulations/{review/review-post-simulation.json → review-post.json} +1 -37
  96. package/template/tests/simulations/{review/review-purchase-simulation.json → review-purchase.json} +1 -38
  97. package/template/tests/simulations/{albums/albums-show-simulation.json → show-albums.json} +1 -24
  98. package/template/tests/simulations/{carousel/carousel-show-simulation.json → show-carousel.json} +1 -24
  99. package/template/tests/simulations/{map/map-show-simulation.json → show-map.json} +1 -35
  100. package/dist/discovery-CRR3SlyI.cjs +0 -156
  101. package/dist/discovery-CRR3SlyI.cjs.map +0 -1
  102. package/dist/discovery-DzV3HLXs.js +0 -157
  103. package/dist/discovery-DzV3HLXs.js.map +0 -1
  104. package/dist/index-B0dxRJvS.cjs.map +0 -1
  105. package/dist/index-CutQgPzR.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery-CH80W5l9.js","sources":["../src/lib/discovery.ts"],"sourcesContent":["/**\n * Discovery utilities for auto-discovering resources and simulations\n *\n * These helpers process the results of import.meta.glob() calls to extract\n * keys, build component maps, and connect simulations to resources.\n *\n * The glob calls themselves must remain in the template (Vite compile-time),\n * but all the processing logic lives here for easy updates across templates.\n *\n * Node.js utilities (findResourceDirs, findToolFiles, etc.) can be used\n * by CLI commands for build-time and runtime discovery.\n */\n\nimport type { Simulation } from '../types/simulation.js';\n\n/**\n * Convert a kebab-case string to PascalCase\n * @example toPascalCase('review') // 'Review'\n * @example toPascalCase('album-art') // 'AlbumArt'\n */\nexport function toPascalCase(str: string): string {\n return str\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\n/**\n * Extract the resource key from a resource file path.\n * Matches {name}.tsx (e.g., './albums/albums.tsx' → 'albums')\n */\nexport function extractResourceKey(path: string): string | undefined {\n const match = path.match(/([^/]+)\\.tsx$/);\n return match ? match[1] : undefined;\n}\n\n/**\n * Extract the simulation key from a simulation file path.\n * Matches any *.json file (e.g., './show-albums.json' → 'show-albums')\n */\nexport function extractSimulationKey(path: string): string | undefined {\n const match = path.match(/([^/]+)\\.json$/);\n return match ? match[1] : undefined;\n}\n\n/**\n * Find the best matching resource key for a simulation key.\n * Matches the longest resource name that is a prefix of the simulation key.\n * @example findResourceKey('review-diff', ['review', 'carousel']) // 'review'\n * @example findResourceKey('albums', ['albums', 'review']) // 'albums'\n */\nexport function findResourceKey(simulationKey: string, resourceKeys: string[]): string | undefined {\n // Sort by length descending to find longest match first\n const sorted = [...resourceKeys].sort((a, b) => b.length - a.length);\n for (const resourceKey of sorted) {\n if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + '-')) {\n return resourceKey;\n }\n }\n return undefined;\n}\n\n/**\n * Get the expected component export name for a resource\n * @example getComponentName('review') // 'ReviewResource'\n * @example getComponentName('album-art') // 'AlbumArtResource'\n */\nexport function getComponentName(resourceKey: string): string {\n return `${toPascalCase(resourceKey)}Resource`;\n}\n\n// --- Glob processing helpers ---\n\ntype GlobModules = Record<string, unknown>;\n\n/**\n * Process resource component modules from import.meta.glob() result.\n * Extracts components and exports them with PascalCase names.\n *\n * @example\n * const modules = import.meta.glob('./*\\/*.tsx', { eager: true });\n * export default createResourceExports(modules);\n */\nexport function createResourceExports(modules: GlobModules): Record<string, React.ComponentType> {\n const resources: Record<string, React.ComponentType> = {};\n\n for (const [path, module] of Object.entries(modules)) {\n const key = extractResourceKey(path);\n if (!key) continue;\n\n const exportName = getComponentName(key);\n const mod = module as Record<string, unknown>;\n\n // Try default export first, then named export matching the expected name\n const component = mod.default ?? mod[exportName];\n\n // Accept functions (regular components) or objects (forwardRef/memo components)\n if (component && (typeof component === 'function' || typeof component === 'object')) {\n resources[exportName] = component as React.ComponentType;\n }\n }\n\n return resources;\n}\n\n/**\n * Build a resource metadata map from import.meta.glob() result.\n * Used for connecting simulations to their resource definitions.\n *\n * @example\n * const modules = import.meta.glob('../src/resources/*\\/*.tsx', { eager: true });\n * const resourcesMap = buildResourceMap(modules);\n */\nexport function buildResourceMap<T>(modules: GlobModules): Map<string, T> {\n const map = new Map<string, T>();\n\n for (const [path, module] of Object.entries(modules)) {\n const key = extractResourceKey(path);\n if (key) {\n map.set(key, (module as { resource: T }).resource);\n }\n }\n\n return map;\n}\n\n/**\n * Options for building simulations from discovered modules\n */\nexport interface BuildSimulationsOptions<TResource, TSimulation> {\n /** Glob result of simulation JSON files */\n simulationModules: GlobModules;\n /** Map of resource key -> resource metadata */\n resourcesMap: Map<string, TResource>;\n /** Map of component name -> React component */\n resourceComponents: Record<string, React.ComponentType>;\n /** Create the final simulation object */\n createSimulation: (\n simulationKey: string,\n simulationData: unknown,\n resource: TResource,\n resourceComponent: React.ComponentType\n ) => TSimulation;\n /** Optional warning handler for missing resources */\n onMissingResource?: (simulationKey: string, expectedPrefix: string) => void;\n}\n\n/**\n * Build simulations by connecting simulation data with resources and components.\n * This is the main orchestration function for dev server bootstrap.\n */\nexport function buildSimulations<TResource, TSimulation>(\n options: BuildSimulationsOptions<TResource, TSimulation>\n): Record<string, TSimulation> {\n const {\n simulationModules,\n resourcesMap,\n resourceComponents,\n createSimulation,\n onMissingResource = (key, prefix) =>\n console.warn(\n `No matching resource found for simulation \"${key}\". ` +\n `Expected a resource file like src/resources/${prefix}/${prefix}.tsx`\n ),\n } = options;\n\n const resourceKeys = Array.from(resourcesMap.keys());\n const simulations: Record<string, TSimulation> = {};\n\n for (const [path, module] of Object.entries(simulationModules)) {\n const simulationKey = extractSimulationKey(path);\n if (!simulationKey) continue;\n\n const simulationData = (module as { default: unknown }).default;\n\n // Find matching resource\n const resourceKey = findResourceKey(simulationKey, resourceKeys);\n if (!resourceKey) {\n onMissingResource(simulationKey, simulationKey.split('-')[0]);\n continue;\n }\n\n const resource = resourcesMap.get(resourceKey)!;\n\n // Get component\n const componentName = getComponentName(resourceKey);\n const resourceComponent = resourceComponents[componentName];\n\n if (!resourceComponent) {\n console.warn(\n `Resource component \"${componentName}\" not found for resource \"${resourceKey}\". ` +\n `Make sure src/resources/${resourceKey}/${resourceKey}.tsx exists with a default export.`\n );\n continue;\n }\n\n simulations[simulationKey] = createSimulation(\n simulationKey,\n simulationData,\n resource,\n resourceComponent\n );\n }\n\n return simulations;\n}\n\n// --- Dev server helpers ---\n\n/**\n * Resource metadata from resource .tsx files\n */\nexport interface ResourceMetadata {\n name: string;\n [key: string]: unknown;\n}\n\n/**\n * Options for building dev simulations\n */\nexport interface BuildDevSimulationsOptions {\n /** Glob result of simulation JSON files */\n simulationModules: GlobModules;\n /** Resource components map from src/resources/index.ts */\n resourceComponents: Record<string, React.ComponentType>;\n /** Glob result of tool files: import.meta.glob('src/tools/*.ts', { eager: true }) */\n toolModules: GlobModules;\n /** Glob result of resource .tsx files from src/resources/ */\n resourceModules: GlobModules;\n}\n\n/**\n * Tool metadata extracted from a tool module's `tool` export\n */\ninterface ToolModuleInfo {\n tool: Record<string, unknown>;\n /** Resource name string from tool.resource */\n resourceName: string;\n}\n\n/**\n * Build simulations for the dev server from glob results.\n * Simulation JSON has `\"tool\": \"tool-name\"` string referencing a tool file.\n * Tool files have `resource: 'name'` linking to a resource discovered from resourceModules.\n */\nexport function buildDevSimulations(\n options: BuildDevSimulationsOptions\n): Record<string, Simulation> {\n const { simulationModules, resourceComponents, toolModules, resourceModules } = options;\n\n // Build resource metadata map from resource modules (keyed by resource name)\n const resourceMetaByName = new Map<string, ResourceMetadata>();\n const resourceKeyByName = new Map<string, string>();\n for (const [path, module] of Object.entries(resourceModules)) {\n const key = extractResourceKey(path);\n if (!key) continue;\n const mod = module as { resource?: ResourceMetadata };\n if (mod.resource) {\n // Use explicit name if provided, otherwise derive from directory key\n const name = mod.resource.name ?? key;\n resourceMetaByName.set(name, { ...mod.resource, name });\n resourceKeyByName.set(name, key);\n }\n }\n\n // Build tool map from tool modules\n const toolsMap = new Map<string, ToolModuleInfo>();\n if (toolModules) {\n for (const [path, module] of Object.entries(toolModules)) {\n const nameMatch = path.match(/([^/]+)\\.ts$/);\n if (!nameMatch) continue;\n const mod = module as { tool?: Record<string, unknown> };\n if (mod.tool) {\n const resourceName = mod.tool.resource as string | undefined;\n if (resourceName) {\n toolsMap.set(nameMatch[1], { tool: mod.tool, resourceName });\n }\n }\n }\n }\n\n const simulations: Record<string, Simulation> = {};\n\n for (const [path, module] of Object.entries(simulationModules)) {\n const simKey = extractSimulationKey(path);\n if (!simKey) continue;\n\n const simulationData = (module as { default: Record<string, unknown> }).default;\n\n const toolName =\n typeof simulationData.tool === 'string' ? (simulationData.tool as string) : simKey;\n const toolInfo = toolsMap.get(toolName);\n if (!toolInfo) {\n console.warn(\n `Tool \"${toolName}\" not found for simulation \"${simKey}\". ` +\n `Make sure src/tools/${toolName}.ts exists.`\n );\n continue;\n }\n\n // Look up resource metadata by name\n const resourceMeta = resourceMetaByName.get(toolInfo.resourceName);\n const resourceKey = resourceKeyByName.get(toolInfo.resourceName);\n if (!resourceMeta || !resourceKey) {\n console.warn(\n `Resource \"${toolInfo.resourceName}\" not found for tool \"${toolName}\". ` +\n `Make sure a resource with name \"${toolInfo.resourceName}\" exists in src/resources/.`\n );\n continue;\n }\n\n const componentName = getComponentName(resourceKey);\n const resourceComponent = resourceComponents[componentName];\n\n if (!resourceComponent) {\n console.warn(`Resource component \"${componentName}\" not found for tool \"${toolName}\".`);\n continue;\n }\n\n simulations[simKey] = {\n name: simKey,\n userMessage: simulationData.userMessage as string | undefined,\n tool: {\n name: toolName,\n description: (toolInfo.tool.description as string) ?? '',\n inputSchema: { type: 'object' as const },\n ...(toolInfo.tool.title != null ? { title: toolInfo.tool.title as string } : {}),\n ...(toolInfo.tool.annotations != null\n ? { annotations: toolInfo.tool.annotations as Record<string, unknown> }\n : {}),\n ...(toolInfo.tool._meta != null\n ? { _meta: toolInfo.tool._meta as Record<string, unknown> }\n : {}),\n },\n resource: {\n uri: `ui://${resourceKey}`,\n name: resourceKey,\n ...(resourceMeta.title != null ? { title: resourceMeta.title as string } : {}),\n ...(resourceMeta.description != null\n ? { description: resourceMeta.description as string }\n : {}),\n ...(resourceMeta.mimeType != null ? { mimeType: resourceMeta.mimeType as string } : {}),\n ...(resourceMeta._meta != null\n ? { _meta: resourceMeta._meta as Record<string, unknown> }\n : {}),\n },\n toolInput: simulationData.toolInput as Record<string, unknown> | undefined,\n toolResult: simulationData.toolResult as Simulation['toolResult'],\n resourceUrl: `/.sunpeak/resource-loader.html?component=${componentName}`,\n };\n }\n\n return simulations;\n}\n\n// --- Node.js utilities for CLI commands ---\n// These utilities use standard Node.js APIs and can be imported by build/push/mcp commands.\n\n/**\n * Information about a discovered resource directory\n */\nexport interface ResourceDirInfo {\n /** Resource key (directory name), e.g., 'albums', 'carousel' */\n key: string;\n /** Full path to the resource directory */\n dir: string;\n /** Full path to the main resource file (tsx or json depending on context) */\n resourcePath: string;\n}\n\n/**\n * File system operations interface for dependency injection in tests\n */\nexport interface FsOps {\n readdirSync: (\n path: string,\n options: { withFileTypes: true }\n ) => Array<{ name: string; isDirectory: () => boolean }>;\n existsSync: (path: string) => boolean;\n}\n\n/**\n * Find all resource directories in a base directory.\n * Each valid resource directory contains a file matching the expected pattern.\n *\n * @param baseDir - Base directory to scan (e.g., 'src/resources' or 'dist')\n * @param filePattern - Function to generate expected filename from resource key\n * @param fs - File system operations (for testing)\n *\n * @example\n * // Find source resources (tsx files)\n * const resources = findResourceDirs('src/resources', key => `${key}.tsx`);\n *\n * @example\n * // Find built resources (js files)\n * const resources = findResourceDirs('dist', key => `${key}.js`);\n */\nexport function findResourceDirs(\n baseDir: string,\n filePattern: (key: string) => string,\n fs: FsOps\n): ResourceDirInfo[] {\n if (!fs.existsSync(baseDir)) {\n return [];\n }\n\n const entries = fs.readdirSync(baseDir, { withFileTypes: true });\n\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => {\n const key = entry.name;\n const dir = `${baseDir}/${key}`;\n const resourcePath = `${dir}/${filePattern(key)}`;\n\n if (!fs.existsSync(resourcePath)) {\n return null;\n }\n\n return { key, dir, resourcePath };\n })\n .filter((info): info is ResourceDirInfo => info !== null);\n}\n\n// --- Tool files + flat simulations discovery ---\n\n/**\n * Information about a discovered tool file\n */\nexport interface ToolFileInfo {\n /** Tool name derived from filename (e.g., 'show-albums') */\n name: string;\n /** Full path to the tool file */\n path: string;\n}\n\n/**\n * Find all tool files in a tools directory.\n * Matches *.ts files directly in the directory (not recursive).\n *\n * @example\n * findToolFiles('src/tools', fs)\n * // [{ name: 'show-albums', path: 'src/tools/show-albums.ts' }]\n */\nexport function findToolFiles(\n toolsDir: string,\n fs: Pick<FsOps, 'readdirSync' | 'existsSync'>\n): ToolFileInfo[] {\n if (!fs.existsSync(toolsDir)) {\n return [];\n }\n\n const entries = fs.readdirSync(toolsDir, { withFileTypes: true });\n\n return entries\n .filter((entry) => !entry.isDirectory() && entry.name.endsWith('.ts'))\n .map((entry) => ({\n name: entry.name.replace(/\\.ts$/, ''),\n path: `${toolsDir}/${entry.name}`,\n }));\n}\n\n/**\n * Information about a discovered simulation file (flat convention)\n */\nexport interface SimulationFileInfo {\n /** Filename without extension (e.g., 'show-albums') */\n name: string;\n /** Full path to the simulation file */\n path: string;\n}\n\n/**\n * Find all simulation JSON files in a flat simulations directory.\n * Matches any *.json file directly in the directory.\n *\n * @example\n * findSimulationFilesFlat('tests/simulations', fs)\n * // [{ name: 'show-albums', path: 'tests/simulations/show-albums.json' }]\n */\nexport function findSimulationFilesFlat(\n simulationsDir: string,\n fs: Pick<FsOps, 'readdirSync' | 'existsSync'>\n): SimulationFileInfo[] {\n if (!fs.existsSync(simulationsDir)) {\n return [];\n }\n\n const entries = fs.readdirSync(simulationsDir, { withFileTypes: true });\n\n return entries\n .filter((entry) => !entry.isDirectory() && entry.name.endsWith('.json'))\n .map((entry) => ({\n name: entry.name.replace(/\\.json$/, ''),\n path: `${simulationsDir}/${entry.name}`,\n }));\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ function toPascalCase(str) {
3
+ return str.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
4
+ }
5
+ function extractResourceKey(path) {
6
+ const match = path.match(/([^/]+)\.tsx$/);
7
+ return match ? match[1] : void 0;
8
+ }
9
+ function extractSimulationKey(path) {
10
+ const match = path.match(/([^/]+)\.json$/);
11
+ return match ? match[1] : void 0;
12
+ }
13
+ function findResourceKey(simulationKey, resourceKeys) {
14
+ const sorted = [...resourceKeys].sort((a, b) => b.length - a.length);
15
+ for (const resourceKey of sorted) {
16
+ if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + "-")) {
17
+ return resourceKey;
18
+ }
19
+ }
20
+ return void 0;
21
+ }
22
+ function getComponentName(resourceKey) {
23
+ return `${toPascalCase(resourceKey)}Resource`;
24
+ }
25
+ function createResourceExports(modules) {
26
+ const resources = {};
27
+ for (const [path, module2] of Object.entries(modules)) {
28
+ const key = extractResourceKey(path);
29
+ if (!key) continue;
30
+ const exportName = getComponentName(key);
31
+ const mod = module2;
32
+ const component = mod.default ?? mod[exportName];
33
+ if (component && (typeof component === "function" || typeof component === "object")) {
34
+ resources[exportName] = component;
35
+ }
36
+ }
37
+ return resources;
38
+ }
39
+ function buildResourceMap(modules) {
40
+ const map = /* @__PURE__ */ new Map();
41
+ for (const [path, module2] of Object.entries(modules)) {
42
+ const key = extractResourceKey(path);
43
+ if (key) {
44
+ map.set(key, module2.resource);
45
+ }
46
+ }
47
+ return map;
48
+ }
49
+ function buildSimulations(options) {
50
+ const {
51
+ simulationModules,
52
+ resourcesMap,
53
+ resourceComponents,
54
+ createSimulation,
55
+ onMissingResource = (key, prefix) => console.warn(
56
+ `No matching resource found for simulation "${key}". Expected a resource file like src/resources/${prefix}/${prefix}.tsx`
57
+ )
58
+ } = options;
59
+ const resourceKeys = Array.from(resourcesMap.keys());
60
+ const simulations = {};
61
+ for (const [path, module2] of Object.entries(simulationModules)) {
62
+ const simulationKey = extractSimulationKey(path);
63
+ if (!simulationKey) continue;
64
+ const simulationData = module2.default;
65
+ const resourceKey = findResourceKey(simulationKey, resourceKeys);
66
+ if (!resourceKey) {
67
+ onMissingResource(simulationKey, simulationKey.split("-")[0]);
68
+ continue;
69
+ }
70
+ const resource = resourcesMap.get(resourceKey);
71
+ const componentName = getComponentName(resourceKey);
72
+ const resourceComponent = resourceComponents[componentName];
73
+ if (!resourceComponent) {
74
+ console.warn(
75
+ `Resource component "${componentName}" not found for resource "${resourceKey}". Make sure src/resources/${resourceKey}/${resourceKey}.tsx exists with a default export.`
76
+ );
77
+ continue;
78
+ }
79
+ simulations[simulationKey] = createSimulation(
80
+ simulationKey,
81
+ simulationData,
82
+ resource,
83
+ resourceComponent
84
+ );
85
+ }
86
+ return simulations;
87
+ }
88
+ function buildDevSimulations(options) {
89
+ const { simulationModules, resourceComponents, toolModules, resourceModules } = options;
90
+ const resourceMetaByName = /* @__PURE__ */ new Map();
91
+ const resourceKeyByName = /* @__PURE__ */ new Map();
92
+ for (const [path, module2] of Object.entries(resourceModules)) {
93
+ const key = extractResourceKey(path);
94
+ if (!key) continue;
95
+ const mod = module2;
96
+ if (mod.resource) {
97
+ const name = mod.resource.name ?? key;
98
+ resourceMetaByName.set(name, { ...mod.resource, name });
99
+ resourceKeyByName.set(name, key);
100
+ }
101
+ }
102
+ const toolsMap = /* @__PURE__ */ new Map();
103
+ if (toolModules) {
104
+ for (const [path, module2] of Object.entries(toolModules)) {
105
+ const nameMatch = path.match(/([^/]+)\.ts$/);
106
+ if (!nameMatch) continue;
107
+ const mod = module2;
108
+ if (mod.tool) {
109
+ const resourceName = mod.tool.resource;
110
+ if (resourceName) {
111
+ toolsMap.set(nameMatch[1], { tool: mod.tool, resourceName });
112
+ }
113
+ }
114
+ }
115
+ }
116
+ const simulations = {};
117
+ for (const [path, module2] of Object.entries(simulationModules)) {
118
+ const simKey = extractSimulationKey(path);
119
+ if (!simKey) continue;
120
+ const simulationData = module2.default;
121
+ const toolName = typeof simulationData.tool === "string" ? simulationData.tool : simKey;
122
+ const toolInfo = toolsMap.get(toolName);
123
+ if (!toolInfo) {
124
+ console.warn(
125
+ `Tool "${toolName}" not found for simulation "${simKey}". Make sure src/tools/${toolName}.ts exists.`
126
+ );
127
+ continue;
128
+ }
129
+ const resourceMeta = resourceMetaByName.get(toolInfo.resourceName);
130
+ const resourceKey = resourceKeyByName.get(toolInfo.resourceName);
131
+ if (!resourceMeta || !resourceKey) {
132
+ console.warn(
133
+ `Resource "${toolInfo.resourceName}" not found for tool "${toolName}". Make sure a resource with name "${toolInfo.resourceName}" exists in src/resources/.`
134
+ );
135
+ continue;
136
+ }
137
+ const componentName = getComponentName(resourceKey);
138
+ const resourceComponent = resourceComponents[componentName];
139
+ if (!resourceComponent) {
140
+ console.warn(`Resource component "${componentName}" not found for tool "${toolName}".`);
141
+ continue;
142
+ }
143
+ simulations[simKey] = {
144
+ name: simKey,
145
+ userMessage: simulationData.userMessage,
146
+ tool: {
147
+ name: toolName,
148
+ description: toolInfo.tool.description ?? "",
149
+ inputSchema: { type: "object" },
150
+ ...toolInfo.tool.title != null ? { title: toolInfo.tool.title } : {},
151
+ ...toolInfo.tool.annotations != null ? { annotations: toolInfo.tool.annotations } : {},
152
+ ...toolInfo.tool._meta != null ? { _meta: toolInfo.tool._meta } : {}
153
+ },
154
+ resource: {
155
+ uri: `ui://${resourceKey}`,
156
+ name: resourceKey,
157
+ ...resourceMeta.title != null ? { title: resourceMeta.title } : {},
158
+ ...resourceMeta.description != null ? { description: resourceMeta.description } : {},
159
+ ...resourceMeta.mimeType != null ? { mimeType: resourceMeta.mimeType } : {},
160
+ ...resourceMeta._meta != null ? { _meta: resourceMeta._meta } : {}
161
+ },
162
+ toolInput: simulationData.toolInput,
163
+ toolResult: simulationData.toolResult,
164
+ resourceUrl: `/.sunpeak/resource-loader.html?component=${componentName}`
165
+ };
166
+ }
167
+ return simulations;
168
+ }
169
+ function findResourceDirs(baseDir, filePattern, fs) {
170
+ if (!fs.existsSync(baseDir)) {
171
+ return [];
172
+ }
173
+ const entries = fs.readdirSync(baseDir, { withFileTypes: true });
174
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => {
175
+ const key = entry.name;
176
+ const dir = `${baseDir}/${key}`;
177
+ const resourcePath = `${dir}/${filePattern(key)}`;
178
+ if (!fs.existsSync(resourcePath)) {
179
+ return null;
180
+ }
181
+ return { key, dir, resourcePath };
182
+ }).filter((info) => info !== null);
183
+ }
184
+ function findToolFiles(toolsDir, fs) {
185
+ if (!fs.existsSync(toolsDir)) {
186
+ return [];
187
+ }
188
+ const entries = fs.readdirSync(toolsDir, { withFileTypes: true });
189
+ return entries.filter((entry) => !entry.isDirectory() && entry.name.endsWith(".ts")).map((entry) => ({
190
+ name: entry.name.replace(/\.ts$/, ""),
191
+ path: `${toolsDir}/${entry.name}`
192
+ }));
193
+ }
194
+ function findSimulationFilesFlat(simulationsDir, fs) {
195
+ if (!fs.existsSync(simulationsDir)) {
196
+ return [];
197
+ }
198
+ const entries = fs.readdirSync(simulationsDir, { withFileTypes: true });
199
+ return entries.filter((entry) => !entry.isDirectory() && entry.name.endsWith(".json")).map((entry) => ({
200
+ name: entry.name.replace(/\.json$/, ""),
201
+ path: `${simulationsDir}/${entry.name}`
202
+ }));
203
+ }
204
+ exports.buildDevSimulations = buildDevSimulations;
205
+ exports.buildResourceMap = buildResourceMap;
206
+ exports.buildSimulations = buildSimulations;
207
+ exports.createResourceExports = createResourceExports;
208
+ exports.extractResourceKey = extractResourceKey;
209
+ exports.extractSimulationKey = extractSimulationKey;
210
+ exports.findResourceDirs = findResourceDirs;
211
+ exports.findResourceKey = findResourceKey;
212
+ exports.findSimulationFilesFlat = findSimulationFilesFlat;
213
+ exports.findToolFiles = findToolFiles;
214
+ exports.getComponentName = getComponentName;
215
+ exports.toPascalCase = toPascalCase;
216
+ //# sourceMappingURL=discovery-DmB8_4QL.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery-DmB8_4QL.cjs","sources":["../src/lib/discovery.ts"],"sourcesContent":["/**\n * Discovery utilities for auto-discovering resources and simulations\n *\n * These helpers process the results of import.meta.glob() calls to extract\n * keys, build component maps, and connect simulations to resources.\n *\n * The glob calls themselves must remain in the template (Vite compile-time),\n * but all the processing logic lives here for easy updates across templates.\n *\n * Node.js utilities (findResourceDirs, findToolFiles, etc.) can be used\n * by CLI commands for build-time and runtime discovery.\n */\n\nimport type { Simulation } from '../types/simulation.js';\n\n/**\n * Convert a kebab-case string to PascalCase\n * @example toPascalCase('review') // 'Review'\n * @example toPascalCase('album-art') // 'AlbumArt'\n */\nexport function toPascalCase(str: string): string {\n return str\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\n/**\n * Extract the resource key from a resource file path.\n * Matches {name}.tsx (e.g., './albums/albums.tsx' → 'albums')\n */\nexport function extractResourceKey(path: string): string | undefined {\n const match = path.match(/([^/]+)\\.tsx$/);\n return match ? match[1] : undefined;\n}\n\n/**\n * Extract the simulation key from a simulation file path.\n * Matches any *.json file (e.g., './show-albums.json' → 'show-albums')\n */\nexport function extractSimulationKey(path: string): string | undefined {\n const match = path.match(/([^/]+)\\.json$/);\n return match ? match[1] : undefined;\n}\n\n/**\n * Find the best matching resource key for a simulation key.\n * Matches the longest resource name that is a prefix of the simulation key.\n * @example findResourceKey('review-diff', ['review', 'carousel']) // 'review'\n * @example findResourceKey('albums', ['albums', 'review']) // 'albums'\n */\nexport function findResourceKey(simulationKey: string, resourceKeys: string[]): string | undefined {\n // Sort by length descending to find longest match first\n const sorted = [...resourceKeys].sort((a, b) => b.length - a.length);\n for (const resourceKey of sorted) {\n if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + '-')) {\n return resourceKey;\n }\n }\n return undefined;\n}\n\n/**\n * Get the expected component export name for a resource\n * @example getComponentName('review') // 'ReviewResource'\n * @example getComponentName('album-art') // 'AlbumArtResource'\n */\nexport function getComponentName(resourceKey: string): string {\n return `${toPascalCase(resourceKey)}Resource`;\n}\n\n// --- Glob processing helpers ---\n\ntype GlobModules = Record<string, unknown>;\n\n/**\n * Process resource component modules from import.meta.glob() result.\n * Extracts components and exports them with PascalCase names.\n *\n * @example\n * const modules = import.meta.glob('./*\\/*.tsx', { eager: true });\n * export default createResourceExports(modules);\n */\nexport function createResourceExports(modules: GlobModules): Record<string, React.ComponentType> {\n const resources: Record<string, React.ComponentType> = {};\n\n for (const [path, module] of Object.entries(modules)) {\n const key = extractResourceKey(path);\n if (!key) continue;\n\n const exportName = getComponentName(key);\n const mod = module as Record<string, unknown>;\n\n // Try default export first, then named export matching the expected name\n const component = mod.default ?? mod[exportName];\n\n // Accept functions (regular components) or objects (forwardRef/memo components)\n if (component && (typeof component === 'function' || typeof component === 'object')) {\n resources[exportName] = component as React.ComponentType;\n }\n }\n\n return resources;\n}\n\n/**\n * Build a resource metadata map from import.meta.glob() result.\n * Used for connecting simulations to their resource definitions.\n *\n * @example\n * const modules = import.meta.glob('../src/resources/*\\/*.tsx', { eager: true });\n * const resourcesMap = buildResourceMap(modules);\n */\nexport function buildResourceMap<T>(modules: GlobModules): Map<string, T> {\n const map = new Map<string, T>();\n\n for (const [path, module] of Object.entries(modules)) {\n const key = extractResourceKey(path);\n if (key) {\n map.set(key, (module as { resource: T }).resource);\n }\n }\n\n return map;\n}\n\n/**\n * Options for building simulations from discovered modules\n */\nexport interface BuildSimulationsOptions<TResource, TSimulation> {\n /** Glob result of simulation JSON files */\n simulationModules: GlobModules;\n /** Map of resource key -> resource metadata */\n resourcesMap: Map<string, TResource>;\n /** Map of component name -> React component */\n resourceComponents: Record<string, React.ComponentType>;\n /** Create the final simulation object */\n createSimulation: (\n simulationKey: string,\n simulationData: unknown,\n resource: TResource,\n resourceComponent: React.ComponentType\n ) => TSimulation;\n /** Optional warning handler for missing resources */\n onMissingResource?: (simulationKey: string, expectedPrefix: string) => void;\n}\n\n/**\n * Build simulations by connecting simulation data with resources and components.\n * This is the main orchestration function for dev server bootstrap.\n */\nexport function buildSimulations<TResource, TSimulation>(\n options: BuildSimulationsOptions<TResource, TSimulation>\n): Record<string, TSimulation> {\n const {\n simulationModules,\n resourcesMap,\n resourceComponents,\n createSimulation,\n onMissingResource = (key, prefix) =>\n console.warn(\n `No matching resource found for simulation \"${key}\". ` +\n `Expected a resource file like src/resources/${prefix}/${prefix}.tsx`\n ),\n } = options;\n\n const resourceKeys = Array.from(resourcesMap.keys());\n const simulations: Record<string, TSimulation> = {};\n\n for (const [path, module] of Object.entries(simulationModules)) {\n const simulationKey = extractSimulationKey(path);\n if (!simulationKey) continue;\n\n const simulationData = (module as { default: unknown }).default;\n\n // Find matching resource\n const resourceKey = findResourceKey(simulationKey, resourceKeys);\n if (!resourceKey) {\n onMissingResource(simulationKey, simulationKey.split('-')[0]);\n continue;\n }\n\n const resource = resourcesMap.get(resourceKey)!;\n\n // Get component\n const componentName = getComponentName(resourceKey);\n const resourceComponent = resourceComponents[componentName];\n\n if (!resourceComponent) {\n console.warn(\n `Resource component \"${componentName}\" not found for resource \"${resourceKey}\". ` +\n `Make sure src/resources/${resourceKey}/${resourceKey}.tsx exists with a default export.`\n );\n continue;\n }\n\n simulations[simulationKey] = createSimulation(\n simulationKey,\n simulationData,\n resource,\n resourceComponent\n );\n }\n\n return simulations;\n}\n\n// --- Dev server helpers ---\n\n/**\n * Resource metadata from resource .tsx files\n */\nexport interface ResourceMetadata {\n name: string;\n [key: string]: unknown;\n}\n\n/**\n * Options for building dev simulations\n */\nexport interface BuildDevSimulationsOptions {\n /** Glob result of simulation JSON files */\n simulationModules: GlobModules;\n /** Resource components map from src/resources/index.ts */\n resourceComponents: Record<string, React.ComponentType>;\n /** Glob result of tool files: import.meta.glob('src/tools/*.ts', { eager: true }) */\n toolModules: GlobModules;\n /** Glob result of resource .tsx files from src/resources/ */\n resourceModules: GlobModules;\n}\n\n/**\n * Tool metadata extracted from a tool module's `tool` export\n */\ninterface ToolModuleInfo {\n tool: Record<string, unknown>;\n /** Resource name string from tool.resource */\n resourceName: string;\n}\n\n/**\n * Build simulations for the dev server from glob results.\n * Simulation JSON has `\"tool\": \"tool-name\"` string referencing a tool file.\n * Tool files have `resource: 'name'` linking to a resource discovered from resourceModules.\n */\nexport function buildDevSimulations(\n options: BuildDevSimulationsOptions\n): Record<string, Simulation> {\n const { simulationModules, resourceComponents, toolModules, resourceModules } = options;\n\n // Build resource metadata map from resource modules (keyed by resource name)\n const resourceMetaByName = new Map<string, ResourceMetadata>();\n const resourceKeyByName = new Map<string, string>();\n for (const [path, module] of Object.entries(resourceModules)) {\n const key = extractResourceKey(path);\n if (!key) continue;\n const mod = module as { resource?: ResourceMetadata };\n if (mod.resource) {\n // Use explicit name if provided, otherwise derive from directory key\n const name = mod.resource.name ?? key;\n resourceMetaByName.set(name, { ...mod.resource, name });\n resourceKeyByName.set(name, key);\n }\n }\n\n // Build tool map from tool modules\n const toolsMap = new Map<string, ToolModuleInfo>();\n if (toolModules) {\n for (const [path, module] of Object.entries(toolModules)) {\n const nameMatch = path.match(/([^/]+)\\.ts$/);\n if (!nameMatch) continue;\n const mod = module as { tool?: Record<string, unknown> };\n if (mod.tool) {\n const resourceName = mod.tool.resource as string | undefined;\n if (resourceName) {\n toolsMap.set(nameMatch[1], { tool: mod.tool, resourceName });\n }\n }\n }\n }\n\n const simulations: Record<string, Simulation> = {};\n\n for (const [path, module] of Object.entries(simulationModules)) {\n const simKey = extractSimulationKey(path);\n if (!simKey) continue;\n\n const simulationData = (module as { default: Record<string, unknown> }).default;\n\n const toolName =\n typeof simulationData.tool === 'string' ? (simulationData.tool as string) : simKey;\n const toolInfo = toolsMap.get(toolName);\n if (!toolInfo) {\n console.warn(\n `Tool \"${toolName}\" not found for simulation \"${simKey}\". ` +\n `Make sure src/tools/${toolName}.ts exists.`\n );\n continue;\n }\n\n // Look up resource metadata by name\n const resourceMeta = resourceMetaByName.get(toolInfo.resourceName);\n const resourceKey = resourceKeyByName.get(toolInfo.resourceName);\n if (!resourceMeta || !resourceKey) {\n console.warn(\n `Resource \"${toolInfo.resourceName}\" not found for tool \"${toolName}\". ` +\n `Make sure a resource with name \"${toolInfo.resourceName}\" exists in src/resources/.`\n );\n continue;\n }\n\n const componentName = getComponentName(resourceKey);\n const resourceComponent = resourceComponents[componentName];\n\n if (!resourceComponent) {\n console.warn(`Resource component \"${componentName}\" not found for tool \"${toolName}\".`);\n continue;\n }\n\n simulations[simKey] = {\n name: simKey,\n userMessage: simulationData.userMessage as string | undefined,\n tool: {\n name: toolName,\n description: (toolInfo.tool.description as string) ?? '',\n inputSchema: { type: 'object' as const },\n ...(toolInfo.tool.title != null ? { title: toolInfo.tool.title as string } : {}),\n ...(toolInfo.tool.annotations != null\n ? { annotations: toolInfo.tool.annotations as Record<string, unknown> }\n : {}),\n ...(toolInfo.tool._meta != null\n ? { _meta: toolInfo.tool._meta as Record<string, unknown> }\n : {}),\n },\n resource: {\n uri: `ui://${resourceKey}`,\n name: resourceKey,\n ...(resourceMeta.title != null ? { title: resourceMeta.title as string } : {}),\n ...(resourceMeta.description != null\n ? { description: resourceMeta.description as string }\n : {}),\n ...(resourceMeta.mimeType != null ? { mimeType: resourceMeta.mimeType as string } : {}),\n ...(resourceMeta._meta != null\n ? { _meta: resourceMeta._meta as Record<string, unknown> }\n : {}),\n },\n toolInput: simulationData.toolInput as Record<string, unknown> | undefined,\n toolResult: simulationData.toolResult as Simulation['toolResult'],\n resourceUrl: `/.sunpeak/resource-loader.html?component=${componentName}`,\n };\n }\n\n return simulations;\n}\n\n// --- Node.js utilities for CLI commands ---\n// These utilities use standard Node.js APIs and can be imported by build/push/mcp commands.\n\n/**\n * Information about a discovered resource directory\n */\nexport interface ResourceDirInfo {\n /** Resource key (directory name), e.g., 'albums', 'carousel' */\n key: string;\n /** Full path to the resource directory */\n dir: string;\n /** Full path to the main resource file (tsx or json depending on context) */\n resourcePath: string;\n}\n\n/**\n * File system operations interface for dependency injection in tests\n */\nexport interface FsOps {\n readdirSync: (\n path: string,\n options: { withFileTypes: true }\n ) => Array<{ name: string; isDirectory: () => boolean }>;\n existsSync: (path: string) => boolean;\n}\n\n/**\n * Find all resource directories in a base directory.\n * Each valid resource directory contains a file matching the expected pattern.\n *\n * @param baseDir - Base directory to scan (e.g., 'src/resources' or 'dist')\n * @param filePattern - Function to generate expected filename from resource key\n * @param fs - File system operations (for testing)\n *\n * @example\n * // Find source resources (tsx files)\n * const resources = findResourceDirs('src/resources', key => `${key}.tsx`);\n *\n * @example\n * // Find built resources (js files)\n * const resources = findResourceDirs('dist', key => `${key}.js`);\n */\nexport function findResourceDirs(\n baseDir: string,\n filePattern: (key: string) => string,\n fs: FsOps\n): ResourceDirInfo[] {\n if (!fs.existsSync(baseDir)) {\n return [];\n }\n\n const entries = fs.readdirSync(baseDir, { withFileTypes: true });\n\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => {\n const key = entry.name;\n const dir = `${baseDir}/${key}`;\n const resourcePath = `${dir}/${filePattern(key)}`;\n\n if (!fs.existsSync(resourcePath)) {\n return null;\n }\n\n return { key, dir, resourcePath };\n })\n .filter((info): info is ResourceDirInfo => info !== null);\n}\n\n// --- Tool files + flat simulations discovery ---\n\n/**\n * Information about a discovered tool file\n */\nexport interface ToolFileInfo {\n /** Tool name derived from filename (e.g., 'show-albums') */\n name: string;\n /** Full path to the tool file */\n path: string;\n}\n\n/**\n * Find all tool files in a tools directory.\n * Matches *.ts files directly in the directory (not recursive).\n *\n * @example\n * findToolFiles('src/tools', fs)\n * // [{ name: 'show-albums', path: 'src/tools/show-albums.ts' }]\n */\nexport function findToolFiles(\n toolsDir: string,\n fs: Pick<FsOps, 'readdirSync' | 'existsSync'>\n): ToolFileInfo[] {\n if (!fs.existsSync(toolsDir)) {\n return [];\n }\n\n const entries = fs.readdirSync(toolsDir, { withFileTypes: true });\n\n return entries\n .filter((entry) => !entry.isDirectory() && entry.name.endsWith('.ts'))\n .map((entry) => ({\n name: entry.name.replace(/\\.ts$/, ''),\n path: `${toolsDir}/${entry.name}`,\n }));\n}\n\n/**\n * Information about a discovered simulation file (flat convention)\n */\nexport interface SimulationFileInfo {\n /** Filename without extension (e.g., 'show-albums') */\n name: string;\n /** Full path to the simulation file */\n path: string;\n}\n\n/**\n * Find all simulation JSON files in a flat simulations directory.\n * Matches any *.json file directly in the directory.\n *\n * @example\n * findSimulationFilesFlat('tests/simulations', fs)\n * // [{ name: 'show-albums', path: 'tests/simulations/show-albums.json' }]\n */\nexport function findSimulationFilesFlat(\n simulationsDir: string,\n fs: Pick<FsOps, 'readdirSync' | 'existsSync'>\n): SimulationFileInfo[] {\n if (!fs.existsSync(simulationsDir)) {\n return [];\n }\n\n const entries = fs.readdirSync(simulationsDir, { withFileTypes: true });\n\n return entries\n .filter((entry) => !entry.isDirectory() && entry.name.endsWith('.json'))\n .map((entry) => ({\n name: entry.name.replace(/\\.json$/, ''),\n path: `${simulationsDir}/${entry.name}`,\n }));\n}\n"],"names":["module"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
- const simulator = require("./simulator-DcfQBRXE.cjs");
2
+ const simulator = require("./simulator-DjZNa1MI.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");
6
- const discovery = require("./discovery-CRR3SlyI.cjs");
6
+ const discovery = require("./discovery-DmB8_4QL.cjs");
7
7
  function _interopNamespaceDefault(e) {
8
8
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
9
9
  if (e) {
@@ -513,15 +513,12 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
513
513
  extractResourceCSP: simulator.extractResourceCSP,
514
514
  extractResourceKey: discovery.extractResourceKey,
515
515
  extractSimulationKey: discovery.extractSimulationKey,
516
- extractSimulationName: discovery.extractSimulationName,
517
516
  findResourceDirs: discovery.findResourceDirs,
518
517
  findResourceKey: discovery.findResourceKey,
519
- findSimulationFiles: discovery.findSimulationFiles,
520
518
  getComponentName: discovery.getComponentName,
521
- isSimulationFile: discovery.isSimulationFile,
522
519
  toPascalCase: discovery.toPascalCase,
523
520
  useThemeContext: simulator.useThemeContext
524
521
  }, Symbol.toStringTag, { value: "Module" }));
525
522
  exports.ChatGPTSimulator = ChatGPTSimulator;
526
523
  exports.index = index;
527
- //# sourceMappingURL=index-Cngntkp2.cjs.map
524
+ //# sourceMappingURL=index-Bll1bszc.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-Cngntkp2.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., 'albums-show')\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 &uarr;\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 &darr;\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 &larr;\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 &rarr;\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-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 &uarr;\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 &darr;\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 &larr;\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 &rarr;\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,9 +1,9 @@
1
- import { j as extractResourceCSP, T as ThemeProvider, i as SimpleSidebar, C as Conversation, d as SidebarControl, f as SidebarSelect, c as SidebarCollapsibleControl, h as SidebarToggle, e as SidebarInput, b as SidebarCheckbox, g as SidebarTextarea, I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, S as Simulator, m as useThemeContext } from "./simulator-CxrtnguM.js";
1
+ import { j as extractResourceCSP, T as ThemeProvider, i as SimpleSidebar, C as Conversation, d as SidebarControl, f as SidebarSelect, c as SidebarCollapsibleControl, h as SidebarToggle, e as SidebarInput, b as SidebarCheckbox, g as SidebarTextarea, I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, S as Simulator, m as useThemeContext } from "./simulator-B7rw83zP.js";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { useMemo, useState, useCallback, useEffect } from "react";
5
5
  import { c as createSimulatorUrl } from "./simulator-url-CuLqtnSS.js";
6
- import { b as buildDevSimulations, a as buildResourceMap, c as buildSimulations, d as createResourceExports, e as extractResourceKey, f as extractSimulationKey, g as extractSimulationName, h as findResourceDirs, i as findResourceKey, j as findSimulationFiles, k as getComponentName, l as isSimulationFile, t as toPascalCase } from "./discovery-DzV3HLXs.js";
6
+ 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";
7
7
  const DEFAULT_THEME = "dark";
8
8
  const DEFAULT_DISPLAY_MODE = "inline";
9
9
  const DEFAULT_PLATFORM = "desktop";
@@ -496,12 +496,9 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
496
496
  extractResourceCSP,
497
497
  extractResourceKey,
498
498
  extractSimulationKey,
499
- extractSimulationName,
500
499
  findResourceDirs,
501
500
  findResourceKey,
502
- findSimulationFiles,
503
501
  getComponentName,
504
- isSimulationFile,
505
502
  toPascalCase,
506
503
  useThemeContext
507
504
  }, Symbol.toStringTag, { value: "Module" }));
@@ -509,4 +506,4 @@ export {
509
506
  ChatGPTSimulator as C,
510
507
  index as i
511
508
  };
512
- //# sourceMappingURL=index-Ce_5ZIdJ.js.map
509
+ //# sourceMappingURL=index-CACtnwu2.js.map