@creature-ai/sdk 0.1.22 → 0.1.23

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.
@@ -43,6 +43,12 @@ interface CreaturePluginOptions {
43
43
  interface HmrConfig {
44
44
  port: number;
45
45
  }
46
+ /**
47
+ * Offset added to MCP_PORT to derive the HMR port.
48
+ * When MCP_PORT is set (by Creature), both Vite and the SDK server
49
+ * can independently calculate the same HMR port without coordination.
50
+ */
51
+ declare const HMR_PORT_OFFSET = 1000;
46
52
  /**
47
53
  * Vite plugin for Creature MCP Apps.
48
54
  *
@@ -60,4 +66,4 @@ interface HmrConfig {
60
66
  */
61
67
  declare function creature(options?: CreaturePluginOptions): Plugin;
62
68
 
63
- export { type CreaturePluginOptions, type HmrConfig, creature, creature as default, generateHmrClientScript, generateHmrClientScriptTag };
69
+ export { type CreaturePluginOptions, HMR_PORT_OFFSET, type HmrConfig, creature, creature as default, generateHmrClientScript, generateHmrClientScriptTag };
@@ -90,6 +90,7 @@ function generateHmrClientScriptTag(port) {
90
90
  }
91
91
 
92
92
  // src/vite/index.ts
93
+ var HMR_PORT_OFFSET = 1e3;
93
94
  function findAvailablePort(startPort) {
94
95
  return new Promise((resolve2) => {
95
96
  const server = createNetServer();
@@ -287,7 +288,8 @@ createRoot(document.getElementById("root")!).render(createElement(Page));
287
288
  if (!tempDir) return;
288
289
  isWatchMode = this.meta.watchMode === true;
289
290
  if (isWatchMode && !hmrServer) {
290
- hmrPort = await findAvailablePort(preferredHmrPort);
291
+ const mcpPort = process.env.MCP_PORT ? parseInt(process.env.MCP_PORT, 10) : null;
292
+ hmrPort = mcpPort ? mcpPort + HMR_PORT_OFFSET : await findAvailablePort(preferredHmrPort);
291
293
  startHmrServer(hmrPort);
292
294
  mkdirSync(tempDir, { recursive: true });
293
295
  const hmrConfig = { port: hmrPort };
@@ -351,6 +353,7 @@ ${exports.join("\n\n")}
351
353
  }
352
354
  var vite_default = creature;
353
355
  export {
356
+ HMR_PORT_OFFSET,
354
357
  creature,
355
358
  vite_default as default,
356
359
  generateHmrClientScript,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/vite/index.ts","../../src/vite/hmr-client.ts"],"sourcesContent":["import { resolve, join, relative } from \"node:path\";\nimport { readdirSync, statSync, existsSync, writeFileSync, mkdirSync, rmSync, readFileSync } from \"node:fs\";\nimport { createServer as createNetServer } from \"node:net\";\nimport { createServer as createHttpServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { createHash } from \"node:crypto\";\nimport { spawnSync } from \"node:child_process\";\nimport type { Duplex } from \"node:stream\";\nimport type { Plugin, UserConfig } from \"vite\";\n\nexport interface CreaturePluginOptions {\n uiDir?: string;\n outDir?: string;\n hmrPort?: number;\n /**\n * Generate a JS module exporting bundled HTML for serverless deployments.\n * When enabled, creates `dist/ui/bundle.js` with named exports for each page.\n * \n * @example\n * // In server code:\n * import { main } from \"./dist/ui/bundle.js\";\n * app.resource({ html: main });\n * \n * @default false\n */\n generateBundle?: boolean;\n}\n\nexport interface HmrConfig {\n port: number;\n}\n\nfunction findAvailablePort(startPort: number): Promise<number> {\n return new Promise((resolve) => {\n const server = createNetServer();\n server.listen(startPort, () => {\n const port = (server.address() as { port: number }).port;\n server.close(() => resolve(port));\n });\n server.on(\"error\", () => {\n resolve(findAvailablePort(startPort + 1));\n });\n });\n}\n\ninterface EntryPoint {\n name: string;\n pagePath: string;\n}\n\nfunction findPages(dir: string, baseDir: string): EntryPoint[] {\n const entries: EntryPoint[] = [];\n if (!existsSync(dir)) return entries;\n\n const items = readdirSync(dir);\n\n if (items.includes(\"page.tsx\")) {\n const relativePath = dir.slice(baseDir.length + 1);\n entries.push({\n name: relativePath || \"main\",\n pagePath: join(dir, \"page.tsx\"),\n });\n }\n\n for (const item of items) {\n const fullPath = join(dir, item);\n if (statSync(fullPath).isDirectory() && !item.startsWith(\"_\") && item !== \"node_modules\") {\n entries.push(...findPages(fullPath, baseDir));\n }\n }\n\n return entries;\n}\n\nlet hmrServer: ReturnType<typeof createHttpServer> | null = null;\nlet hmrClients: Set<Duplex> = new Set();\n\nfunction sendWebSocketFrame(socket: Duplex, data: string): void {\n const payload = Buffer.from(data);\n const length = payload.length;\n \n let frame: Buffer;\n if (length < 126) {\n frame = Buffer.alloc(2 + length);\n frame[0] = 0x81;\n frame[1] = length;\n payload.copy(frame, 2);\n } else if (length < 65536) {\n frame = Buffer.alloc(4 + length);\n frame[0] = 0x81;\n frame[1] = 126;\n frame.writeUInt16BE(length, 2);\n payload.copy(frame, 4);\n } else {\n frame = Buffer.alloc(10 + length);\n frame[0] = 0x81;\n frame[1] = 127;\n frame.writeBigUInt64BE(BigInt(length), 2);\n payload.copy(frame, 10);\n }\n \n socket.write(frame);\n}\n\nfunction startHmrServer(port: number): void {\n if (hmrServer) return;\n \n hmrServer = createHttpServer((_req: IncomingMessage, res: ServerResponse) => {\n res.writeHead(200);\n res.end(\"Creature HMR Server\");\n });\n \n hmrServer.on(\"upgrade\", (req: IncomingMessage, socket: Duplex, head: Buffer) => {\n const key = req.headers[\"sec-websocket-key\"];\n if (!key) {\n socket.destroy();\n return;\n }\n \n const acceptKey = createHash(\"sha1\")\n .update(key + \"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\")\n .digest(\"base64\");\n \n socket.write(\n \"HTTP/1.1 101 Switching Protocols\\r\\n\" +\n \"Upgrade: websocket\\r\\n\" +\n \"Connection: Upgrade\\r\\n\" +\n `Sec-WebSocket-Accept: ${acceptKey}\\r\\n` +\n \"\\r\\n\"\n );\n \n hmrClients.add(socket);\n sendWebSocketFrame(socket, JSON.stringify({ type: \"connected\" }));\n \n socket.on(\"close\", () => {\n hmrClients.delete(socket);\n });\n \n socket.on(\"error\", () => {\n hmrClients.delete(socket);\n });\n });\n \n hmrServer.listen(port);\n}\n\nfunction notifyHmrClients(): void {\n const message = JSON.stringify({ type: \"full-reload\" });\n const toRemove: Duplex[] = [];\n \n for (const client of hmrClients) {\n try {\n if (!client.destroyed) {\n sendWebSocketFrame(client, message);\n } else {\n toRemove.push(client);\n }\n } catch {\n toRemove.push(client);\n }\n }\n \n for (const client of toRemove) {\n hmrClients.delete(client);\n }\n \n if (hmrClients.size > 0) {\n console.log(\"App UI reloaded\");\n }\n}\n\n/**\n * Vite plugin for Creature MCP Apps.\n * \n * Just write page.tsx files - no HTML or entry files needed.\n * \n * ```\n * src/ui/\n * ├── page.tsx → dist/ui/main.html\n * ├── inline/page.tsx → dist/ui/inline.html\n * └── _components/ → ignored\n * ```\n * \n * When using vite-plugin-singlefile, multiple pages are built automatically\n * via sequential builds (singlefile requires single entry per build).\n */\nexport function creature(options: CreaturePluginOptions = {}): Plugin {\n const uiDir = options.uiDir || \"src/ui\";\n const outDir = options.outDir || \"dist/ui\";\n const preferredHmrPort = options.hmrPort || 5899;\n const generateBundle = options.generateBundle || false;\n \n let root: string;\n let tempDir: string;\n let entries: EntryPoint[] = [];\n let hasSingleFilePlugin = false;\n let hmrPort: number | null = null;\n let isWatchMode = false;\n let remainingPages: string[] = [];\n\n return {\n name: \"creature\",\n \n async config(config) {\n root = config.root || process.cwd();\n const uiPath = resolve(root, uiDir);\n entries = findPages(uiPath, uiPath);\n\n if (entries.length === 0) {\n return;\n }\n\n const plugins = config.plugins?.flat() || [];\n hasSingleFilePlugin = plugins.some(p => p && typeof p === 'object' && 'name' in p && p.name === 'vite:singlefile');\n\n tempDir = resolve(root, \"node_modules/.creature\");\n \n const selectedPage = process.env.CREATURE_PAGE;\n \n if (!selectedPage) {\n rmSync(tempDir, { recursive: true, force: true });\n }\n mkdirSync(tempDir, { recursive: true });\n\n for (const entry of entries) {\n const relativePagePath = relative(tempDir, entry.pagePath).replace(/\\\\/g, \"/\");\n writeFileSync(join(tempDir, `${entry.name}.entry.tsx`), \n`import { createElement } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport Page from \"${relativePagePath.replace(/\\.tsx$/, \"\")}\";\ncreateRoot(document.getElementById(\"root\")!).render(createElement(Page));\n`);\n\n writeFileSync(join(tempDir, `${entry.name}.html`),\n`<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${entry.name}</title>\n</head>\n<body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"./${entry.name}.entry.tsx\"></script>\n</body>\n</html>`);\n }\n \n let inputs: Record<string, string>;\n \n if (hasSingleFilePlugin) {\n const targetEntry = selectedPage \n ? entries.find(e => e.name === selectedPage)\n : entries[0];\n \n if (!targetEntry) {\n console.error(`Page \"${selectedPage}\" not found`);\n return;\n }\n \n inputs = { [targetEntry.name]: join(tempDir, `${targetEntry.name}.html`) };\n \n if (!selectedPage && entries.length > 1) {\n remainingPages = entries.slice(1).map(e => e.name);\n }\n } else {\n inputs = Object.fromEntries(\n entries.map(e => [e.name, join(tempDir, `${e.name}.html`)])\n );\n }\n\n return {\n root: tempDir,\n publicDir: false,\n logLevel: \"silent\" as const,\n build: {\n outDir: resolve(root, outDir),\n emptyOutDir: !selectedPage,\n rollupOptions: { input: inputs },\n reportCompressedSize: false,\n },\n } satisfies UserConfig;\n },\n\n async buildStart() {\n if (!tempDir) return;\n \n isWatchMode = this.meta.watchMode === true;\n \n if (isWatchMode && !hmrServer) {\n hmrPort = await findAvailablePort(preferredHmrPort);\n startHmrServer(hmrPort);\n \n mkdirSync(tempDir, { recursive: true });\n const hmrConfig: HmrConfig = { port: hmrPort };\n writeFileSync(\n join(tempDir, \"hmr.json\"),\n JSON.stringify(hmrConfig, null, 2)\n );\n }\n },\n\n writeBundle() {\n if (!hasSingleFilePlugin || remainingPages.length === 0) {\n if (isWatchMode) notifyHmrClients();\n return;\n }\n \n for (const pageName of remainingPages) {\n spawnSync(\"npx\", [\"vite\", \"build\"], {\n cwd: root,\n env: { ...process.env, CREATURE_PAGE: pageName },\n stdio: \"inherit\",\n });\n }\n \n if (isWatchMode) {\n notifyHmrClients();\n } else {\n remainingPages = [];\n }\n },\n\n closeBundle() {\n if (isWatchMode) return;\n \n // Generate bundle.js for serverless deployments\n if (generateBundle && entries.length > 0 && !process.env.CREATURE_PAGE) {\n const bundleOutputDir = resolve(root, outDir);\n const exports: string[] = [];\n \n for (const entry of entries) {\n const htmlPath = join(bundleOutputDir, `${entry.name}.html`);\n if (existsSync(htmlPath)) {\n const html = readFileSync(htmlPath, \"utf-8\");\n // Escape backticks and ${} for template literal\n const escaped = html.replace(/\\\\/g, \"\\\\\\\\\").replace(/`/g, \"\\\\`\").replace(/\\$\\{/g, \"\\\\${\");\n exports.push(`export const ${entry.name.replace(/-/g, \"_\")} = \\`${escaped}\\`;`);\n }\n }\n \n if (exports.length > 0) {\n const bundleContent = `/**\n * Auto-generated UI bundle for serverless deployments.\n * Import these exports in your MCP server for Vercel/Lambda.\n * \n * @example\n * import { main } from \"./dist/ui/bundle.js\";\n * app.resource({ html: main });\n */\n${exports.join(\"\\n\\n\")}\n`;\n writeFileSync(join(bundleOutputDir, \"bundle.js\"), bundleContent);\n console.log(`Generated ${outDir}/bundle.js for serverless`);\n }\n }\n \n if (tempDir && existsSync(tempDir) && !process.env.CREATURE_PAGE) {\n rmSync(tempDir, { recursive: true, force: true });\n }\n },\n };\n}\n\nexport { generateHmrClientScript, generateHmrClientScriptTag } from \"./hmr-client.js\";\n\nexport default creature;\n","/**\n * HMR Client Script\n * \n * This script is injected into MCP App HTML during development mode.\n * It connects to Vite's HMR WebSocket and notifies the parent frame\n * when a full reload is needed.\n * \n * The parent frame (Creature host) will then:\n * 1. Save current widget state\n * 2. Re-fetch fresh HTML from the MCP server\n * 3. Reload the iframe with new content\n * 4. Restore widget state\n */\n\n/**\n * Generate the HMR client script as a string.\n * The port is injected at generation time.\n */\nexport function generateHmrClientScript(port: number): string {\n return `\n(function() {\n if (window.parent === window) {\n console.log('[Creature HMR] Not in iframe, skipping HMR client');\n return;\n }\n if (window.__CREATURE_HMR_CONNECTED__) {\n console.log('[Creature HMR] Already connected, skipping');\n return;\n }\n window.__CREATURE_HMR_CONNECTED__ = true;\n\n var HMR_PORT = ${port};\n var reconnectAttempts = 0;\n var maxReconnectAttempts = 10;\n var reconnectDelay = 1000;\n\n console.log('[Creature HMR] Initializing HMR client, will connect to port ' + HMR_PORT);\n\n function connect() {\n if (reconnectAttempts >= maxReconnectAttempts) {\n console.log('[Creature HMR] Max reconnection attempts reached, giving up');\n return;\n }\n\n console.log('[Creature HMR] Attempting to connect to ws://localhost:' + HMR_PORT + ' (attempt ' + (reconnectAttempts + 1) + ')');\n var ws = new WebSocket('ws://localhost:' + HMR_PORT);\n\n ws.onopen = function() {\n console.log('[Creature HMR] Connected to HMR server on port ' + HMR_PORT);\n reconnectAttempts = 0;\n };\n\n ws.onmessage = function(event) {\n console.log('[Creature HMR] Received message:', event.data);\n try {\n var data = JSON.parse(event.data);\n \n if (data.type === 'full-reload') {\n console.log('[Creature HMR] Full reload triggered, notifying parent');\n notifyParent();\n } else if (data.type === 'update') {\n console.log('[Creature HMR] Update detected, notifying parent');\n notifyParent();\n } else if (data.type === 'connected') {\n console.log('[Creature HMR] Server acknowledged connection');\n }\n } catch (e) {\n console.log('[Creature HMR] Failed to parse message:', e);\n }\n };\n\n ws.onclose = function() {\n console.log('[Creature HMR] Disconnected, reconnecting in ' + reconnectDelay + 'ms...');\n reconnectAttempts++;\n setTimeout(connect, reconnectDelay);\n };\n\n ws.onerror = function(err) {\n console.log('[Creature HMR] WebSocket error:', err);\n };\n }\n\n function notifyParent() {\n console.log('[Creature HMR] Sending hmr-reload to parent frame');\n window.parent.postMessage({\n jsonrpc: '2.0',\n method: 'ui/notifications/hmr-reload',\n params: {}\n }, '*');\n }\n\n // Start connection\n connect();\n})();\n`.trim();\n}\n\n/**\n * Generate a script tag with the HMR client code.\n */\nexport function generateHmrClientScriptTag(port: number): string {\n return `<script>${generateHmrClientScript(port)}</script>`;\n}\n"],"mappings":"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","names":["resolve"]}
1
+ {"version":3,"sources":["../../src/vite/index.ts","../../src/vite/hmr-client.ts"],"sourcesContent":["import { resolve, join, relative } from \"node:path\";\nimport { readdirSync, statSync, existsSync, writeFileSync, mkdirSync, rmSync, readFileSync } from \"node:fs\";\nimport { createServer as createNetServer } from \"node:net\";\nimport { createServer as createHttpServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { createHash } from \"node:crypto\";\nimport { spawnSync } from \"node:child_process\";\nimport type { Duplex } from \"node:stream\";\nimport type { Plugin, UserConfig } from \"vite\";\n\nexport interface CreaturePluginOptions {\n uiDir?: string;\n outDir?: string;\n hmrPort?: number;\n /**\n * Generate a JS module exporting bundled HTML for serverless deployments.\n * When enabled, creates `dist/ui/bundle.js` with named exports for each page.\n * \n * @example\n * // In server code:\n * import { main } from \"./dist/ui/bundle.js\";\n * app.resource({ html: main });\n * \n * @default false\n */\n generateBundle?: boolean;\n}\n\nexport interface HmrConfig {\n port: number;\n}\n\n/**\n * Offset added to MCP_PORT to derive the HMR port.\n * When MCP_PORT is set (by Creature), both Vite and the SDK server\n * can independently calculate the same HMR port without coordination.\n */\nexport const HMR_PORT_OFFSET = 1000;\n\nfunction findAvailablePort(startPort: number): Promise<number> {\n return new Promise((resolve) => {\n const server = createNetServer();\n server.listen(startPort, () => {\n const port = (server.address() as { port: number }).port;\n server.close(() => resolve(port));\n });\n server.on(\"error\", () => {\n resolve(findAvailablePort(startPort + 1));\n });\n });\n}\n\ninterface EntryPoint {\n name: string;\n pagePath: string;\n}\n\nfunction findPages(dir: string, baseDir: string): EntryPoint[] {\n const entries: EntryPoint[] = [];\n if (!existsSync(dir)) return entries;\n\n const items = readdirSync(dir);\n\n if (items.includes(\"page.tsx\")) {\n const relativePath = dir.slice(baseDir.length + 1);\n entries.push({\n name: relativePath || \"main\",\n pagePath: join(dir, \"page.tsx\"),\n });\n }\n\n for (const item of items) {\n const fullPath = join(dir, item);\n if (statSync(fullPath).isDirectory() && !item.startsWith(\"_\") && item !== \"node_modules\") {\n entries.push(...findPages(fullPath, baseDir));\n }\n }\n\n return entries;\n}\n\nlet hmrServer: ReturnType<typeof createHttpServer> | null = null;\nlet hmrClients: Set<Duplex> = new Set();\n\nfunction sendWebSocketFrame(socket: Duplex, data: string): void {\n const payload = Buffer.from(data);\n const length = payload.length;\n \n let frame: Buffer;\n if (length < 126) {\n frame = Buffer.alloc(2 + length);\n frame[0] = 0x81;\n frame[1] = length;\n payload.copy(frame, 2);\n } else if (length < 65536) {\n frame = Buffer.alloc(4 + length);\n frame[0] = 0x81;\n frame[1] = 126;\n frame.writeUInt16BE(length, 2);\n payload.copy(frame, 4);\n } else {\n frame = Buffer.alloc(10 + length);\n frame[0] = 0x81;\n frame[1] = 127;\n frame.writeBigUInt64BE(BigInt(length), 2);\n payload.copy(frame, 10);\n }\n \n socket.write(frame);\n}\n\nfunction startHmrServer(port: number): void {\n if (hmrServer) return;\n \n hmrServer = createHttpServer((_req: IncomingMessage, res: ServerResponse) => {\n res.writeHead(200);\n res.end(\"Creature HMR Server\");\n });\n \n hmrServer.on(\"upgrade\", (req: IncomingMessage, socket: Duplex, head: Buffer) => {\n const key = req.headers[\"sec-websocket-key\"];\n if (!key) {\n socket.destroy();\n return;\n }\n \n const acceptKey = createHash(\"sha1\")\n .update(key + \"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\")\n .digest(\"base64\");\n \n socket.write(\n \"HTTP/1.1 101 Switching Protocols\\r\\n\" +\n \"Upgrade: websocket\\r\\n\" +\n \"Connection: Upgrade\\r\\n\" +\n `Sec-WebSocket-Accept: ${acceptKey}\\r\\n` +\n \"\\r\\n\"\n );\n \n hmrClients.add(socket);\n sendWebSocketFrame(socket, JSON.stringify({ type: \"connected\" }));\n \n socket.on(\"close\", () => {\n hmrClients.delete(socket);\n });\n \n socket.on(\"error\", () => {\n hmrClients.delete(socket);\n });\n });\n \n hmrServer.listen(port);\n}\n\nfunction notifyHmrClients(): void {\n const message = JSON.stringify({ type: \"full-reload\" });\n const toRemove: Duplex[] = [];\n \n for (const client of hmrClients) {\n try {\n if (!client.destroyed) {\n sendWebSocketFrame(client, message);\n } else {\n toRemove.push(client);\n }\n } catch {\n toRemove.push(client);\n }\n }\n \n for (const client of toRemove) {\n hmrClients.delete(client);\n }\n \n if (hmrClients.size > 0) {\n console.log(\"App UI reloaded\");\n }\n}\n\n/**\n * Vite plugin for Creature MCP Apps.\n * \n * Just write page.tsx files - no HTML or entry files needed.\n * \n * ```\n * src/ui/\n * ├── page.tsx → dist/ui/main.html\n * ├── inline/page.tsx → dist/ui/inline.html\n * └── _components/ → ignored\n * ```\n * \n * When using vite-plugin-singlefile, multiple pages are built automatically\n * via sequential builds (singlefile requires single entry per build).\n */\nexport function creature(options: CreaturePluginOptions = {}): Plugin {\n const uiDir = options.uiDir || \"src/ui\";\n const outDir = options.outDir || \"dist/ui\";\n const preferredHmrPort = options.hmrPort || 5899;\n const generateBundle = options.generateBundle || false;\n \n let root: string;\n let tempDir: string;\n let entries: EntryPoint[] = [];\n let hasSingleFilePlugin = false;\n let hmrPort: number | null = null;\n let isWatchMode = false;\n let remainingPages: string[] = [];\n\n return {\n name: \"creature\",\n \n async config(config) {\n root = config.root || process.cwd();\n const uiPath = resolve(root, uiDir);\n entries = findPages(uiPath, uiPath);\n\n if (entries.length === 0) {\n return;\n }\n\n const plugins = config.plugins?.flat() || [];\n hasSingleFilePlugin = plugins.some(p => p && typeof p === 'object' && 'name' in p && p.name === 'vite:singlefile');\n\n tempDir = resolve(root, \"node_modules/.creature\");\n \n const selectedPage = process.env.CREATURE_PAGE;\n \n if (!selectedPage) {\n rmSync(tempDir, { recursive: true, force: true });\n }\n mkdirSync(tempDir, { recursive: true });\n\n for (const entry of entries) {\n const relativePagePath = relative(tempDir, entry.pagePath).replace(/\\\\/g, \"/\");\n writeFileSync(join(tempDir, `${entry.name}.entry.tsx`), \n`import { createElement } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport Page from \"${relativePagePath.replace(/\\.tsx$/, \"\")}\";\ncreateRoot(document.getElementById(\"root\")!).render(createElement(Page));\n`);\n\n writeFileSync(join(tempDir, `${entry.name}.html`),\n`<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${entry.name}</title>\n</head>\n<body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"./${entry.name}.entry.tsx\"></script>\n</body>\n</html>`);\n }\n \n let inputs: Record<string, string>;\n \n if (hasSingleFilePlugin) {\n const targetEntry = selectedPage \n ? entries.find(e => e.name === selectedPage)\n : entries[0];\n \n if (!targetEntry) {\n console.error(`Page \"${selectedPage}\" not found`);\n return;\n }\n \n inputs = { [targetEntry.name]: join(tempDir, `${targetEntry.name}.html`) };\n \n if (!selectedPage && entries.length > 1) {\n remainingPages = entries.slice(1).map(e => e.name);\n }\n } else {\n inputs = Object.fromEntries(\n entries.map(e => [e.name, join(tempDir, `${e.name}.html`)])\n );\n }\n\n return {\n root: tempDir,\n publicDir: false,\n logLevel: \"silent\" as const,\n build: {\n outDir: resolve(root, outDir),\n emptyOutDir: !selectedPage,\n rollupOptions: { input: inputs },\n reportCompressedSize: false,\n },\n } satisfies UserConfig;\n },\n\n async buildStart() {\n if (!tempDir) return;\n \n isWatchMode = this.meta.watchMode === true;\n \n if (isWatchMode && !hmrServer) {\n // Derive HMR port from MCP_PORT when available (set by Creature).\n // This allows the SDK server to know the HMR port immediately without\n // waiting for hmr.json to be written, eliminating the race condition.\n const mcpPort = process.env.MCP_PORT ? parseInt(process.env.MCP_PORT, 10) : null;\n hmrPort = mcpPort ? mcpPort + HMR_PORT_OFFSET : await findAvailablePort(preferredHmrPort);\n startHmrServer(hmrPort);\n \n // Still write hmr.json for non-Creature environments (manual npm run dev)\n mkdirSync(tempDir, { recursive: true });\n const hmrConfig: HmrConfig = { port: hmrPort };\n writeFileSync(\n join(tempDir, \"hmr.json\"),\n JSON.stringify(hmrConfig, null, 2)\n );\n }\n },\n\n writeBundle() {\n if (!hasSingleFilePlugin || remainingPages.length === 0) {\n if (isWatchMode) notifyHmrClients();\n return;\n }\n \n for (const pageName of remainingPages) {\n spawnSync(\"npx\", [\"vite\", \"build\"], {\n cwd: root,\n env: { ...process.env, CREATURE_PAGE: pageName },\n stdio: \"inherit\",\n });\n }\n \n if (isWatchMode) {\n notifyHmrClients();\n } else {\n remainingPages = [];\n }\n },\n\n closeBundle() {\n if (isWatchMode) return;\n \n // Generate bundle.js for serverless deployments\n if (generateBundle && entries.length > 0 && !process.env.CREATURE_PAGE) {\n const bundleOutputDir = resolve(root, outDir);\n const exports: string[] = [];\n \n for (const entry of entries) {\n const htmlPath = join(bundleOutputDir, `${entry.name}.html`);\n if (existsSync(htmlPath)) {\n const html = readFileSync(htmlPath, \"utf-8\");\n // Escape backticks and ${} for template literal\n const escaped = html.replace(/\\\\/g, \"\\\\\\\\\").replace(/`/g, \"\\\\`\").replace(/\\$\\{/g, \"\\\\${\");\n exports.push(`export const ${entry.name.replace(/-/g, \"_\")} = \\`${escaped}\\`;`);\n }\n }\n \n if (exports.length > 0) {\n const bundleContent = `/**\n * Auto-generated UI bundle for serverless deployments.\n * Import these exports in your MCP server for Vercel/Lambda.\n * \n * @example\n * import { main } from \"./dist/ui/bundle.js\";\n * app.resource({ html: main });\n */\n${exports.join(\"\\n\\n\")}\n`;\n writeFileSync(join(bundleOutputDir, \"bundle.js\"), bundleContent);\n console.log(`Generated ${outDir}/bundle.js for serverless`);\n }\n }\n \n if (tempDir && existsSync(tempDir) && !process.env.CREATURE_PAGE) {\n rmSync(tempDir, { recursive: true, force: true });\n }\n },\n };\n}\n\nexport { generateHmrClientScript, generateHmrClientScriptTag } from \"./hmr-client.js\";\n\nexport default creature;\n","/**\n * HMR Client Script\n * \n * This script is injected into MCP App HTML during development mode.\n * It connects to Vite's HMR WebSocket and notifies the parent frame\n * when a full reload is needed.\n * \n * The parent frame (Creature host) will then:\n * 1. Save current widget state\n * 2. Re-fetch fresh HTML from the MCP server\n * 3. Reload the iframe with new content\n * 4. Restore widget state\n */\n\n/**\n * Generate the HMR client script as a string.\n * The port is injected at generation time.\n */\nexport function generateHmrClientScript(port: number): string {\n return `\n(function() {\n if (window.parent === window) {\n console.log('[Creature HMR] Not in iframe, skipping HMR client');\n return;\n }\n if (window.__CREATURE_HMR_CONNECTED__) {\n console.log('[Creature HMR] Already connected, skipping');\n return;\n }\n window.__CREATURE_HMR_CONNECTED__ = true;\n\n var HMR_PORT = ${port};\n var reconnectAttempts = 0;\n var maxReconnectAttempts = 10;\n var reconnectDelay = 1000;\n\n console.log('[Creature HMR] Initializing HMR client, will connect to port ' + HMR_PORT);\n\n function connect() {\n if (reconnectAttempts >= maxReconnectAttempts) {\n console.log('[Creature HMR] Max reconnection attempts reached, giving up');\n return;\n }\n\n console.log('[Creature HMR] Attempting to connect to ws://localhost:' + HMR_PORT + ' (attempt ' + (reconnectAttempts + 1) + ')');\n var ws = new WebSocket('ws://localhost:' + HMR_PORT);\n\n ws.onopen = function() {\n console.log('[Creature HMR] Connected to HMR server on port ' + HMR_PORT);\n reconnectAttempts = 0;\n };\n\n ws.onmessage = function(event) {\n console.log('[Creature HMR] Received message:', event.data);\n try {\n var data = JSON.parse(event.data);\n \n if (data.type === 'full-reload') {\n console.log('[Creature HMR] Full reload triggered, notifying parent');\n notifyParent();\n } else if (data.type === 'update') {\n console.log('[Creature HMR] Update detected, notifying parent');\n notifyParent();\n } else if (data.type === 'connected') {\n console.log('[Creature HMR] Server acknowledged connection');\n }\n } catch (e) {\n console.log('[Creature HMR] Failed to parse message:', e);\n }\n };\n\n ws.onclose = function() {\n console.log('[Creature HMR] Disconnected, reconnecting in ' + reconnectDelay + 'ms...');\n reconnectAttempts++;\n setTimeout(connect, reconnectDelay);\n };\n\n ws.onerror = function(err) {\n console.log('[Creature HMR] WebSocket error:', err);\n };\n }\n\n function notifyParent() {\n console.log('[Creature HMR] Sending hmr-reload to parent frame');\n window.parent.postMessage({\n jsonrpc: '2.0',\n method: 'ui/notifications/hmr-reload',\n params: {}\n }, '*');\n }\n\n // Start connection\n connect();\n})();\n`.trim();\n}\n\n/**\n * Generate a script tag with the HMR client code.\n */\nexport function generateHmrClientScriptTag(port: number): string {\n return `<script>${generateHmrClientScript(port)}</script>`;\n}\n"],"mappings":"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","names":["resolve"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@creature-ai/sdk",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "description": "SDK for building MCP Apps that work on both Creature and ChatGPT",
5
5
  "type": "module",
6
6
  "exports": {