@frontmcp/ui 0.6.0 → 0.6.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 (650) hide show
  1. package/README.md +140 -362
  2. package/bridge/core/bridge-factory.d.ts +1 -0
  3. package/bridge/core/bridge-factory.d.ts.map +1 -1
  4. package/bridge/index.d.ts +1 -1
  5. package/bridge/index.d.ts.map +1 -1
  6. package/bridge/index.js +39 -881
  7. package/bridge/runtime/index.d.ts +2 -1
  8. package/bridge/runtime/index.d.ts.map +1 -1
  9. package/bundler/browser-components.d.ts +42 -0
  10. package/bundler/browser-components.d.ts.map +1 -0
  11. package/bundler/bundler.d.ts +78 -4
  12. package/bundler/bundler.d.ts.map +1 -1
  13. package/bundler/index.d.ts +8 -8
  14. package/bundler/index.d.ts.map +1 -1
  15. package/bundler/index.js +1411 -2997
  16. package/bundler/types.d.ts +188 -7
  17. package/bundler/types.d.ts.map +1 -1
  18. package/components/alert.schema.d.ts +6 -6
  19. package/components/avatar.schema.d.ts +9 -9
  20. package/components/badge.schema.d.ts +9 -9
  21. package/components/button.schema.d.ts +9 -9
  22. package/components/card.schema.d.ts +7 -7
  23. package/components/form.schema.d.ts +24 -24
  24. package/components/index.js +128 -198
  25. package/components/modal.schema.d.ts +8 -8
  26. package/components/table.schema.d.ts +6 -6
  27. package/esm/bridge/{index.js → index.mjs} +40 -877
  28. package/esm/bundler/index.mjs +3136 -0
  29. package/esm/components/{index.js → index.mjs} +136 -196
  30. package/esm/index.mjs +5450 -0
  31. package/esm/layouts/index.mjs +409 -0
  32. package/esm/package.json +15 -32
  33. package/esm/react/{index.js → index.mjs} +71 -260
  34. package/esm/renderers/index.mjs +611 -0
  35. package/esm/universal/index.mjs +1951 -0
  36. package/esm/web-components/{index.js → index.mjs} +232 -287
  37. package/index.d.ts +22 -41
  38. package/index.d.ts.map +1 -1
  39. package/index.js +4286 -19607
  40. package/layouts/base.d.ts +2 -2
  41. package/layouts/base.d.ts.map +1 -1
  42. package/layouts/index.js +46 -539
  43. package/layouts/presets.d.ts.map +1 -1
  44. package/package.json +15 -32
  45. package/react/Alert.d.ts +1 -2
  46. package/react/Alert.d.ts.map +1 -1
  47. package/react/Badge.d.ts +1 -2
  48. package/react/Badge.d.ts.map +1 -1
  49. package/react/Button.d.ts +1 -2
  50. package/react/Button.d.ts.map +1 -1
  51. package/react/Card.d.ts +1 -2
  52. package/react/Card.d.ts.map +1 -1
  53. package/react/hooks/context.d.ts +1 -1
  54. package/react/hooks/context.d.ts.map +1 -1
  55. package/react/index.d.ts +5 -7
  56. package/react/index.d.ts.map +1 -1
  57. package/react/index.js +55 -269
  58. package/react/types.d.ts +1 -2
  59. package/react/types.d.ts.map +1 -1
  60. package/renderers/index.d.ts +15 -25
  61. package/renderers/index.d.ts.map +1 -1
  62. package/renderers/index.js +393 -1619
  63. package/renderers/mdx.renderer.d.ts +13 -34
  64. package/renderers/mdx.renderer.d.ts.map +1 -1
  65. package/{esm/runtime/adapters → renderers}/react.adapter.d.ts +2 -2
  66. package/renderers/react.adapter.d.ts.map +1 -0
  67. package/renderers/react.renderer.d.ts +25 -16
  68. package/renderers/react.renderer.d.ts.map +1 -1
  69. package/renderers/transpiler.d.ts +49 -0
  70. package/renderers/transpiler.d.ts.map +1 -0
  71. package/universal/cached-runtime.d.ts +25 -1
  72. package/universal/cached-runtime.d.ts.map +1 -1
  73. package/universal/index.js +2037 -0
  74. package/universal/runtime-builder.d.ts.map +1 -1
  75. package/universal/types.d.ts.map +1 -1
  76. package/web-components/elements/fmcp-input.d.ts.map +1 -1
  77. package/web-components/elements/fmcp-select.d.ts.map +1 -1
  78. package/web-components/index.d.ts +0 -1
  79. package/web-components/index.d.ts.map +1 -1
  80. package/web-components/index.js +224 -289
  81. package/adapters/index.d.ts +0 -13
  82. package/adapters/index.d.ts.map +0 -1
  83. package/adapters/index.js +0 -462
  84. package/adapters/platform-meta.d.ts +0 -166
  85. package/adapters/platform-meta.d.ts.map +0 -1
  86. package/adapters/response-builder.d.ts +0 -108
  87. package/adapters/response-builder.d.ts.map +0 -1
  88. package/adapters/serving-mode.d.ts +0 -107
  89. package/adapters/serving-mode.d.ts.map +0 -1
  90. package/base-template/bridge.d.ts +0 -90
  91. package/base-template/bridge.d.ts.map +0 -1
  92. package/base-template/default-base-template.d.ts +0 -92
  93. package/base-template/default-base-template.d.ts.map +0 -1
  94. package/base-template/index.d.ts +0 -15
  95. package/base-template/index.d.ts.map +0 -1
  96. package/base-template/index.js +0 -1398
  97. package/base-template/polyfills.d.ts +0 -31
  98. package/base-template/polyfills.d.ts.map +0 -1
  99. package/base-template/theme-styles.d.ts +0 -74
  100. package/base-template/theme-styles.d.ts.map +0 -1
  101. package/build/cdn-resources.d.ts +0 -243
  102. package/build/cdn-resources.d.ts.map +0 -1
  103. package/build/index.d.ts +0 -295
  104. package/build/index.d.ts.map +0 -1
  105. package/build/index.js +0 -7096
  106. package/build/widget-manifest.d.ts +0 -362
  107. package/build/widget-manifest.d.ts.map +0 -1
  108. package/bundler/cache.d.ts +0 -173
  109. package/bundler/cache.d.ts.map +0 -1
  110. package/bundler/file-cache/component-builder.d.ts +0 -167
  111. package/bundler/file-cache/component-builder.d.ts.map +0 -1
  112. package/bundler/file-cache/hash-calculator.d.ts +0 -155
  113. package/bundler/file-cache/hash-calculator.d.ts.map +0 -1
  114. package/bundler/file-cache/index.d.ts +0 -12
  115. package/bundler/file-cache/index.d.ts.map +0 -1
  116. package/bundler/file-cache/storage/filesystem.d.ts +0 -149
  117. package/bundler/file-cache/storage/filesystem.d.ts.map +0 -1
  118. package/bundler/file-cache/storage/index.d.ts +0 -11
  119. package/bundler/file-cache/storage/index.d.ts.map +0 -1
  120. package/bundler/file-cache/storage/interface.d.ts +0 -152
  121. package/bundler/file-cache/storage/interface.d.ts.map +0 -1
  122. package/bundler/file-cache/storage/redis.d.ts +0 -139
  123. package/bundler/file-cache/storage/redis.d.ts.map +0 -1
  124. package/bundler/sandbox/enclave-adapter.d.ts +0 -121
  125. package/bundler/sandbox/enclave-adapter.d.ts.map +0 -1
  126. package/bundler/sandbox/executor.d.ts +0 -14
  127. package/bundler/sandbox/executor.d.ts.map +0 -1
  128. package/bundler/sandbox/policy.d.ts +0 -62
  129. package/bundler/sandbox/policy.d.ts.map +0 -1
  130. package/dependency/cdn-registry.d.ts +0 -98
  131. package/dependency/cdn-registry.d.ts.map +0 -1
  132. package/dependency/import-map.d.ts +0 -186
  133. package/dependency/import-map.d.ts.map +0 -1
  134. package/dependency/import-parser.d.ts +0 -82
  135. package/dependency/import-parser.d.ts.map +0 -1
  136. package/dependency/index.d.ts +0 -17
  137. package/dependency/index.d.ts.map +0 -1
  138. package/dependency/resolver.d.ts +0 -164
  139. package/dependency/resolver.d.ts.map +0 -1
  140. package/dependency/schemas.d.ts +0 -486
  141. package/dependency/schemas.d.ts.map +0 -1
  142. package/dependency/template-loader.d.ts +0 -204
  143. package/dependency/template-loader.d.ts.map +0 -1
  144. package/dependency/template-processor.d.ts +0 -118
  145. package/dependency/template-processor.d.ts.map +0 -1
  146. package/dependency/types.d.ts +0 -739
  147. package/dependency/types.d.ts.map +0 -1
  148. package/esm/adapters/index.d.ts +0 -13
  149. package/esm/adapters/index.d.ts.map +0 -1
  150. package/esm/adapters/index.js +0 -427
  151. package/esm/adapters/platform-meta.d.ts +0 -166
  152. package/esm/adapters/platform-meta.d.ts.map +0 -1
  153. package/esm/adapters/response-builder.d.ts +0 -108
  154. package/esm/adapters/response-builder.d.ts.map +0 -1
  155. package/esm/adapters/serving-mode.d.ts +0 -107
  156. package/esm/adapters/serving-mode.d.ts.map +0 -1
  157. package/esm/base-template/bridge.d.ts +0 -90
  158. package/esm/base-template/bridge.d.ts.map +0 -1
  159. package/esm/base-template/default-base-template.d.ts +0 -92
  160. package/esm/base-template/default-base-template.d.ts.map +0 -1
  161. package/esm/base-template/index.d.ts +0 -15
  162. package/esm/base-template/index.d.ts.map +0 -1
  163. package/esm/base-template/index.js +0 -1364
  164. package/esm/base-template/polyfills.d.ts +0 -31
  165. package/esm/base-template/polyfills.d.ts.map +0 -1
  166. package/esm/base-template/theme-styles.d.ts +0 -74
  167. package/esm/base-template/theme-styles.d.ts.map +0 -1
  168. package/esm/bridge/adapters/base-adapter.d.ts +0 -104
  169. package/esm/bridge/adapters/base-adapter.d.ts.map +0 -1
  170. package/esm/bridge/adapters/claude.adapter.d.ts +0 -67
  171. package/esm/bridge/adapters/claude.adapter.d.ts.map +0 -1
  172. package/esm/bridge/adapters/ext-apps.adapter.d.ts +0 -143
  173. package/esm/bridge/adapters/ext-apps.adapter.d.ts.map +0 -1
  174. package/esm/bridge/adapters/gemini.adapter.d.ts +0 -64
  175. package/esm/bridge/adapters/gemini.adapter.d.ts.map +0 -1
  176. package/esm/bridge/adapters/generic.adapter.d.ts +0 -56
  177. package/esm/bridge/adapters/generic.adapter.d.ts.map +0 -1
  178. package/esm/bridge/adapters/index.d.ts +0 -26
  179. package/esm/bridge/adapters/index.d.ts.map +0 -1
  180. package/esm/bridge/adapters/openai.adapter.d.ts +0 -65
  181. package/esm/bridge/adapters/openai.adapter.d.ts.map +0 -1
  182. package/esm/bridge/core/adapter-registry.d.ts +0 -122
  183. package/esm/bridge/core/adapter-registry.d.ts.map +0 -1
  184. package/esm/bridge/core/bridge-factory.d.ts +0 -199
  185. package/esm/bridge/core/bridge-factory.d.ts.map +0 -1
  186. package/esm/bridge/core/index.d.ts +0 -10
  187. package/esm/bridge/core/index.d.ts.map +0 -1
  188. package/esm/bridge/index.d.ts +0 -62
  189. package/esm/bridge/index.d.ts.map +0 -1
  190. package/esm/bridge/runtime/iife-generator.d.ts +0 -62
  191. package/esm/bridge/runtime/iife-generator.d.ts.map +0 -1
  192. package/esm/bridge/runtime/index.d.ts +0 -9
  193. package/esm/bridge/runtime/index.d.ts.map +0 -1
  194. package/esm/bridge/types.d.ts +0 -386
  195. package/esm/bridge/types.d.ts.map +0 -1
  196. package/esm/build/cdn-resources.d.ts +0 -243
  197. package/esm/build/cdn-resources.d.ts.map +0 -1
  198. package/esm/build/index.d.ts +0 -295
  199. package/esm/build/index.d.ts.map +0 -1
  200. package/esm/build/index.js +0 -7021
  201. package/esm/build/widget-manifest.d.ts +0 -362
  202. package/esm/build/widget-manifest.d.ts.map +0 -1
  203. package/esm/bundler/bundler.d.ts +0 -208
  204. package/esm/bundler/bundler.d.ts.map +0 -1
  205. package/esm/bundler/cache.d.ts +0 -173
  206. package/esm/bundler/cache.d.ts.map +0 -1
  207. package/esm/bundler/file-cache/component-builder.d.ts +0 -167
  208. package/esm/bundler/file-cache/component-builder.d.ts.map +0 -1
  209. package/esm/bundler/file-cache/hash-calculator.d.ts +0 -155
  210. package/esm/bundler/file-cache/hash-calculator.d.ts.map +0 -1
  211. package/esm/bundler/file-cache/index.d.ts +0 -12
  212. package/esm/bundler/file-cache/index.d.ts.map +0 -1
  213. package/esm/bundler/file-cache/storage/filesystem.d.ts +0 -149
  214. package/esm/bundler/file-cache/storage/filesystem.d.ts.map +0 -1
  215. package/esm/bundler/file-cache/storage/index.d.ts +0 -11
  216. package/esm/bundler/file-cache/storage/index.d.ts.map +0 -1
  217. package/esm/bundler/file-cache/storage/interface.d.ts +0 -152
  218. package/esm/bundler/file-cache/storage/interface.d.ts.map +0 -1
  219. package/esm/bundler/file-cache/storage/redis.d.ts +0 -139
  220. package/esm/bundler/file-cache/storage/redis.d.ts.map +0 -1
  221. package/esm/bundler/index.d.ts +0 -43
  222. package/esm/bundler/index.d.ts.map +0 -1
  223. package/esm/bundler/index.js +0 -4687
  224. package/esm/bundler/sandbox/enclave-adapter.d.ts +0 -121
  225. package/esm/bundler/sandbox/enclave-adapter.d.ts.map +0 -1
  226. package/esm/bundler/sandbox/executor.d.ts +0 -14
  227. package/esm/bundler/sandbox/executor.d.ts.map +0 -1
  228. package/esm/bundler/sandbox/policy.d.ts +0 -62
  229. package/esm/bundler/sandbox/policy.d.ts.map +0 -1
  230. package/esm/bundler/types.d.ts +0 -702
  231. package/esm/bundler/types.d.ts.map +0 -1
  232. package/esm/components/alert.d.ts +0 -66
  233. package/esm/components/alert.d.ts.map +0 -1
  234. package/esm/components/alert.schema.d.ts +0 -98
  235. package/esm/components/alert.schema.d.ts.map +0 -1
  236. package/esm/components/avatar.d.ts +0 -77
  237. package/esm/components/avatar.d.ts.map +0 -1
  238. package/esm/components/avatar.schema.d.ts +0 -170
  239. package/esm/components/avatar.schema.d.ts.map +0 -1
  240. package/esm/components/badge.d.ts +0 -64
  241. package/esm/components/badge.d.ts.map +0 -1
  242. package/esm/components/badge.schema.d.ts +0 -91
  243. package/esm/components/badge.schema.d.ts.map +0 -1
  244. package/esm/components/button.d.ts +0 -100
  245. package/esm/components/button.d.ts.map +0 -1
  246. package/esm/components/button.schema.d.ts +0 -120
  247. package/esm/components/button.schema.d.ts.map +0 -1
  248. package/esm/components/card.d.ts +0 -53
  249. package/esm/components/card.d.ts.map +0 -1
  250. package/esm/components/card.schema.d.ts +0 -93
  251. package/esm/components/card.schema.d.ts.map +0 -1
  252. package/esm/components/form.d.ts +0 -212
  253. package/esm/components/form.d.ts.map +0 -1
  254. package/esm/components/form.schema.d.ts +0 -365
  255. package/esm/components/form.schema.d.ts.map +0 -1
  256. package/esm/components/index.d.ts +0 -29
  257. package/esm/components/index.d.ts.map +0 -1
  258. package/esm/components/list.d.ts +0 -121
  259. package/esm/components/list.d.ts.map +0 -1
  260. package/esm/components/list.schema.d.ts +0 -129
  261. package/esm/components/list.schema.d.ts.map +0 -1
  262. package/esm/components/modal.d.ts +0 -100
  263. package/esm/components/modal.d.ts.map +0 -1
  264. package/esm/components/modal.schema.d.ts +0 -151
  265. package/esm/components/modal.schema.d.ts.map +0 -1
  266. package/esm/components/table.d.ts +0 -91
  267. package/esm/components/table.d.ts.map +0 -1
  268. package/esm/components/table.schema.d.ts +0 -123
  269. package/esm/components/table.schema.d.ts.map +0 -1
  270. package/esm/dependency/cdn-registry.d.ts +0 -98
  271. package/esm/dependency/cdn-registry.d.ts.map +0 -1
  272. package/esm/dependency/import-map.d.ts +0 -186
  273. package/esm/dependency/import-map.d.ts.map +0 -1
  274. package/esm/dependency/import-parser.d.ts +0 -82
  275. package/esm/dependency/import-parser.d.ts.map +0 -1
  276. package/esm/dependency/index.d.ts +0 -17
  277. package/esm/dependency/index.d.ts.map +0 -1
  278. package/esm/dependency/resolver.d.ts +0 -164
  279. package/esm/dependency/resolver.d.ts.map +0 -1
  280. package/esm/dependency/schemas.d.ts +0 -486
  281. package/esm/dependency/schemas.d.ts.map +0 -1
  282. package/esm/dependency/template-loader.d.ts +0 -204
  283. package/esm/dependency/template-loader.d.ts.map +0 -1
  284. package/esm/dependency/template-processor.d.ts +0 -118
  285. package/esm/dependency/template-processor.d.ts.map +0 -1
  286. package/esm/dependency/types.d.ts +0 -739
  287. package/esm/dependency/types.d.ts.map +0 -1
  288. package/esm/handlebars/expression-extractor.d.ts +0 -147
  289. package/esm/handlebars/expression-extractor.d.ts.map +0 -1
  290. package/esm/handlebars/helpers.d.ts +0 -339
  291. package/esm/handlebars/helpers.d.ts.map +0 -1
  292. package/esm/handlebars/index.d.ts +0 -195
  293. package/esm/handlebars/index.d.ts.map +0 -1
  294. package/esm/handlebars/index.js +0 -587
  295. package/esm/index.d.ts +0 -56
  296. package/esm/index.d.ts.map +0 -1
  297. package/esm/index.js +0 -20511
  298. package/esm/layouts/base.d.ts +0 -86
  299. package/esm/layouts/base.d.ts.map +0 -1
  300. package/esm/layouts/index.d.ts +0 -8
  301. package/esm/layouts/index.d.ts.map +0 -1
  302. package/esm/layouts/index.js +0 -892
  303. package/esm/layouts/presets.d.ts +0 -134
  304. package/esm/layouts/presets.d.ts.map +0 -1
  305. package/esm/pages/consent.d.ts +0 -117
  306. package/esm/pages/consent.d.ts.map +0 -1
  307. package/esm/pages/error.d.ts +0 -101
  308. package/esm/pages/error.d.ts.map +0 -1
  309. package/esm/pages/index.d.ts +0 -9
  310. package/esm/pages/index.d.ts.map +0 -1
  311. package/esm/pages/index.js +0 -1563
  312. package/esm/react/Alert.d.ts +0 -102
  313. package/esm/react/Alert.d.ts.map +0 -1
  314. package/esm/react/Badge.d.ts +0 -101
  315. package/esm/react/Badge.d.ts.map +0 -1
  316. package/esm/react/Button.d.ts +0 -109
  317. package/esm/react/Button.d.ts.map +0 -1
  318. package/esm/react/Card.d.ts +0 -104
  319. package/esm/react/Card.d.ts.map +0 -1
  320. package/esm/react/hooks/context.d.ts +0 -179
  321. package/esm/react/hooks/context.d.ts.map +0 -1
  322. package/esm/react/hooks/index.d.ts +0 -42
  323. package/esm/react/hooks/index.d.ts.map +0 -1
  324. package/esm/react/hooks/tools.d.ts +0 -284
  325. package/esm/react/hooks/tools.d.ts.map +0 -1
  326. package/esm/react/index.d.ts +0 -81
  327. package/esm/react/index.d.ts.map +0 -1
  328. package/esm/react/types.d.ts +0 -106
  329. package/esm/react/types.d.ts.map +0 -1
  330. package/esm/react/utils.d.ts +0 -43
  331. package/esm/react/utils.d.ts.map +0 -1
  332. package/esm/registry/index.d.ts +0 -46
  333. package/esm/registry/index.d.ts.map +0 -1
  334. package/esm/registry/index.js +0 -6422
  335. package/esm/registry/render-template.d.ts +0 -91
  336. package/esm/registry/render-template.d.ts.map +0 -1
  337. package/esm/registry/tool-ui.registry.d.ts +0 -294
  338. package/esm/registry/tool-ui.registry.d.ts.map +0 -1
  339. package/esm/registry/uri-utils.d.ts +0 -56
  340. package/esm/registry/uri-utils.d.ts.map +0 -1
  341. package/esm/render/index.d.ts +0 -8
  342. package/esm/render/index.d.ts.map +0 -1
  343. package/esm/render/prerender.d.ts +0 -57
  344. package/esm/render/prerender.d.ts.map +0 -1
  345. package/esm/renderers/cache.d.ts +0 -145
  346. package/esm/renderers/cache.d.ts.map +0 -1
  347. package/esm/renderers/html.renderer.d.ts +0 -123
  348. package/esm/renderers/html.renderer.d.ts.map +0 -1
  349. package/esm/renderers/index.d.ts +0 -36
  350. package/esm/renderers/index.d.ts.map +0 -1
  351. package/esm/renderers/index.js +0 -1827
  352. package/esm/renderers/mdx.renderer.d.ts +0 -120
  353. package/esm/renderers/mdx.renderer.d.ts.map +0 -1
  354. package/esm/renderers/react.renderer.d.ts +0 -96
  355. package/esm/renderers/react.renderer.d.ts.map +0 -1
  356. package/esm/renderers/registry.d.ts +0 -134
  357. package/esm/renderers/registry.d.ts.map +0 -1
  358. package/esm/renderers/types.d.ts +0 -342
  359. package/esm/renderers/types.d.ts.map +0 -1
  360. package/esm/renderers/utils/detect.d.ts +0 -107
  361. package/esm/renderers/utils/detect.d.ts.map +0 -1
  362. package/esm/renderers/utils/hash.d.ts +0 -40
  363. package/esm/renderers/utils/hash.d.ts.map +0 -1
  364. package/esm/renderers/utils/index.d.ts +0 -9
  365. package/esm/renderers/utils/index.d.ts.map +0 -1
  366. package/esm/renderers/utils/transpiler.d.ts +0 -89
  367. package/esm/renderers/utils/transpiler.d.ts.map +0 -1
  368. package/esm/runtime/adapters/html.adapter.d.ts +0 -59
  369. package/esm/runtime/adapters/html.adapter.d.ts.map +0 -1
  370. package/esm/runtime/adapters/index.d.ts +0 -26
  371. package/esm/runtime/adapters/index.d.ts.map +0 -1
  372. package/esm/runtime/adapters/mdx.adapter.d.ts +0 -73
  373. package/esm/runtime/adapters/mdx.adapter.d.ts.map +0 -1
  374. package/esm/runtime/adapters/react.adapter.d.ts.map +0 -1
  375. package/esm/runtime/adapters/types.d.ts +0 -95
  376. package/esm/runtime/adapters/types.d.ts.map +0 -1
  377. package/esm/runtime/csp.d.ts +0 -48
  378. package/esm/runtime/csp.d.ts.map +0 -1
  379. package/esm/runtime/index.d.ts +0 -17
  380. package/esm/runtime/index.d.ts.map +0 -1
  381. package/esm/runtime/index.js +0 -5186
  382. package/esm/runtime/mcp-bridge.d.ts +0 -101
  383. package/esm/runtime/mcp-bridge.d.ts.map +0 -1
  384. package/esm/runtime/renderer-runtime.d.ts +0 -133
  385. package/esm/runtime/renderer-runtime.d.ts.map +0 -1
  386. package/esm/runtime/sanitizer.d.ts +0 -172
  387. package/esm/runtime/sanitizer.d.ts.map +0 -1
  388. package/esm/runtime/types.d.ts +0 -415
  389. package/esm/runtime/types.d.ts.map +0 -1
  390. package/esm/runtime/wrapper.d.ts +0 -421
  391. package/esm/runtime/wrapper.d.ts.map +0 -1
  392. package/esm/styles/index.d.ts +0 -8
  393. package/esm/styles/index.d.ts.map +0 -1
  394. package/esm/styles/index.js +0 -171
  395. package/esm/styles/variants.d.ts +0 -51
  396. package/esm/styles/variants.d.ts.map +0 -1
  397. package/esm/theme/cdn.d.ts +0 -195
  398. package/esm/theme/cdn.d.ts.map +0 -1
  399. package/esm/theme/index.d.ts +0 -18
  400. package/esm/theme/index.d.ts.map +0 -1
  401. package/esm/theme/index.js +0 -700
  402. package/esm/theme/platforms.d.ts +0 -107
  403. package/esm/theme/platforms.d.ts.map +0 -1
  404. package/esm/theme/presets/github-openai.d.ts +0 -50
  405. package/esm/theme/presets/github-openai.d.ts.map +0 -1
  406. package/esm/theme/presets/index.d.ts +0 -11
  407. package/esm/theme/presets/index.d.ts.map +0 -1
  408. package/esm/theme/theme.d.ts +0 -396
  409. package/esm/theme/theme.d.ts.map +0 -1
  410. package/esm/tool-template/builder.d.ts +0 -213
  411. package/esm/tool-template/builder.d.ts.map +0 -1
  412. package/esm/tool-template/index.d.ts +0 -16
  413. package/esm/tool-template/index.d.ts.map +0 -1
  414. package/esm/tool-template/index.js +0 -3515
  415. package/esm/types/index.d.ts +0 -14
  416. package/esm/types/index.d.ts.map +0 -1
  417. package/esm/types/index.js +0 -75
  418. package/esm/types/ui-config.d.ts +0 -639
  419. package/esm/types/ui-config.d.ts.map +0 -1
  420. package/esm/types/ui-runtime.d.ts +0 -1007
  421. package/esm/types/ui-runtime.d.ts.map +0 -1
  422. package/esm/typings/cache/cache-adapter.d.ts +0 -125
  423. package/esm/typings/cache/cache-adapter.d.ts.map +0 -1
  424. package/esm/typings/cache/index.d.ts +0 -10
  425. package/esm/typings/cache/index.d.ts.map +0 -1
  426. package/esm/typings/cache/memory-cache.d.ts +0 -92
  427. package/esm/typings/cache/memory-cache.d.ts.map +0 -1
  428. package/esm/typings/dts-parser.d.ts +0 -90
  429. package/esm/typings/dts-parser.d.ts.map +0 -1
  430. package/esm/typings/index.d.ts +0 -48
  431. package/esm/typings/index.d.ts.map +0 -1
  432. package/esm/typings/schemas.d.ts +0 -232
  433. package/esm/typings/schemas.d.ts.map +0 -1
  434. package/esm/typings/type-fetcher.d.ts +0 -89
  435. package/esm/typings/type-fetcher.d.ts.map +0 -1
  436. package/esm/typings/types.d.ts +0 -320
  437. package/esm/typings/types.d.ts.map +0 -1
  438. package/esm/universal/UniversalApp.d.ts +0 -108
  439. package/esm/universal/UniversalApp.d.ts.map +0 -1
  440. package/esm/universal/cached-runtime.d.ts +0 -115
  441. package/esm/universal/cached-runtime.d.ts.map +0 -1
  442. package/esm/universal/context.d.ts +0 -122
  443. package/esm/universal/context.d.ts.map +0 -1
  444. package/esm/universal/index.d.ts +0 -57
  445. package/esm/universal/index.d.ts.map +0 -1
  446. package/esm/universal/renderers/html.renderer.d.ts +0 -37
  447. package/esm/universal/renderers/html.renderer.d.ts.map +0 -1
  448. package/esm/universal/renderers/index.d.ts +0 -112
  449. package/esm/universal/renderers/index.d.ts.map +0 -1
  450. package/esm/universal/renderers/markdown.renderer.d.ts +0 -33
  451. package/esm/universal/renderers/markdown.renderer.d.ts.map +0 -1
  452. package/esm/universal/renderers/mdx.renderer.d.ts +0 -38
  453. package/esm/universal/renderers/mdx.renderer.d.ts.map +0 -1
  454. package/esm/universal/renderers/react.renderer.d.ts +0 -46
  455. package/esm/universal/renderers/react.renderer.d.ts.map +0 -1
  456. package/esm/universal/runtime-builder.d.ts +0 -33
  457. package/esm/universal/runtime-builder.d.ts.map +0 -1
  458. package/esm/universal/store.d.ts +0 -135
  459. package/esm/universal/store.d.ts.map +0 -1
  460. package/esm/universal/types.d.ts +0 -199
  461. package/esm/universal/types.d.ts.map +0 -1
  462. package/esm/utils/escape-html.d.ts +0 -58
  463. package/esm/utils/escape-html.d.ts.map +0 -1
  464. package/esm/utils/index.d.ts +0 -10
  465. package/esm/utils/index.d.ts.map +0 -1
  466. package/esm/utils/index.js +0 -40
  467. package/esm/utils/safe-stringify.d.ts +0 -30
  468. package/esm/utils/safe-stringify.d.ts.map +0 -1
  469. package/esm/validation/error-box.d.ts +0 -56
  470. package/esm/validation/error-box.d.ts.map +0 -1
  471. package/esm/validation/index.d.ts +0 -13
  472. package/esm/validation/index.d.ts.map +0 -1
  473. package/esm/validation/index.js +0 -562
  474. package/esm/validation/schema-paths.d.ts +0 -118
  475. package/esm/validation/schema-paths.d.ts.map +0 -1
  476. package/esm/validation/template-validator.d.ts +0 -143
  477. package/esm/validation/template-validator.d.ts.map +0 -1
  478. package/esm/validation/wrapper.d.ts +0 -97
  479. package/esm/validation/wrapper.d.ts.map +0 -1
  480. package/esm/web-components/core/attribute-parser.d.ts +0 -82
  481. package/esm/web-components/core/attribute-parser.d.ts.map +0 -1
  482. package/esm/web-components/core/base-element.d.ts +0 -197
  483. package/esm/web-components/core/base-element.d.ts.map +0 -1
  484. package/esm/web-components/core/index.d.ts +0 -9
  485. package/esm/web-components/core/index.d.ts.map +0 -1
  486. package/esm/web-components/elements/fmcp-alert.d.ts +0 -46
  487. package/esm/web-components/elements/fmcp-alert.d.ts.map +0 -1
  488. package/esm/web-components/elements/fmcp-badge.d.ts +0 -47
  489. package/esm/web-components/elements/fmcp-badge.d.ts.map +0 -1
  490. package/esm/web-components/elements/fmcp-button.d.ts +0 -117
  491. package/esm/web-components/elements/fmcp-button.d.ts.map +0 -1
  492. package/esm/web-components/elements/fmcp-card.d.ts +0 -53
  493. package/esm/web-components/elements/fmcp-card.d.ts.map +0 -1
  494. package/esm/web-components/elements/fmcp-input.d.ts +0 -96
  495. package/esm/web-components/elements/fmcp-input.d.ts.map +0 -1
  496. package/esm/web-components/elements/fmcp-select.d.ts +0 -100
  497. package/esm/web-components/elements/fmcp-select.d.ts.map +0 -1
  498. package/esm/web-components/elements/index.d.ts +0 -13
  499. package/esm/web-components/elements/index.d.ts.map +0 -1
  500. package/esm/web-components/index.d.ts +0 -50
  501. package/esm/web-components/index.d.ts.map +0 -1
  502. package/esm/web-components/register.d.ts +0 -57
  503. package/esm/web-components/register.d.ts.map +0 -1
  504. package/esm/web-components/types.d.ts +0 -122
  505. package/esm/web-components/types.d.ts.map +0 -1
  506. package/esm/widgets/index.d.ts +0 -8
  507. package/esm/widgets/index.d.ts.map +0 -1
  508. package/esm/widgets/index.js +0 -941
  509. package/esm/widgets/progress.d.ts +0 -133
  510. package/esm/widgets/progress.d.ts.map +0 -1
  511. package/esm/widgets/resource.d.ts +0 -163
  512. package/esm/widgets/resource.d.ts.map +0 -1
  513. package/handlebars/expression-extractor.d.ts +0 -147
  514. package/handlebars/expression-extractor.d.ts.map +0 -1
  515. package/handlebars/helpers.d.ts +0 -339
  516. package/handlebars/helpers.d.ts.map +0 -1
  517. package/handlebars/index.d.ts +0 -195
  518. package/handlebars/index.d.ts.map +0 -1
  519. package/handlebars/index.js +0 -666
  520. package/pages/consent.d.ts +0 -117
  521. package/pages/consent.d.ts.map +0 -1
  522. package/pages/error.d.ts +0 -101
  523. package/pages/error.d.ts.map +0 -1
  524. package/pages/index.d.ts +0 -9
  525. package/pages/index.d.ts.map +0 -1
  526. package/pages/index.js +0 -1602
  527. package/react/utils.d.ts +0 -43
  528. package/react/utils.d.ts.map +0 -1
  529. package/registry/index.d.ts +0 -46
  530. package/registry/index.d.ts.map +0 -1
  531. package/registry/index.js +0 -6465
  532. package/registry/render-template.d.ts +0 -91
  533. package/registry/render-template.d.ts.map +0 -1
  534. package/registry/tool-ui.registry.d.ts +0 -294
  535. package/registry/tool-ui.registry.d.ts.map +0 -1
  536. package/registry/uri-utils.d.ts +0 -56
  537. package/registry/uri-utils.d.ts.map +0 -1
  538. package/renderers/cache.d.ts +0 -145
  539. package/renderers/cache.d.ts.map +0 -1
  540. package/renderers/html.renderer.d.ts +0 -123
  541. package/renderers/html.renderer.d.ts.map +0 -1
  542. package/renderers/registry.d.ts +0 -134
  543. package/renderers/registry.d.ts.map +0 -1
  544. package/renderers/types.d.ts +0 -342
  545. package/renderers/types.d.ts.map +0 -1
  546. package/renderers/utils/detect.d.ts +0 -107
  547. package/renderers/utils/detect.d.ts.map +0 -1
  548. package/renderers/utils/hash.d.ts +0 -40
  549. package/renderers/utils/hash.d.ts.map +0 -1
  550. package/renderers/utils/index.d.ts +0 -9
  551. package/renderers/utils/index.d.ts.map +0 -1
  552. package/renderers/utils/transpiler.d.ts +0 -89
  553. package/renderers/utils/transpiler.d.ts.map +0 -1
  554. package/runtime/adapters/html.adapter.d.ts +0 -59
  555. package/runtime/adapters/html.adapter.d.ts.map +0 -1
  556. package/runtime/adapters/index.d.ts +0 -26
  557. package/runtime/adapters/index.d.ts.map +0 -1
  558. package/runtime/adapters/mdx.adapter.d.ts +0 -73
  559. package/runtime/adapters/mdx.adapter.d.ts.map +0 -1
  560. package/runtime/adapters/react.adapter.d.ts +0 -70
  561. package/runtime/adapters/react.adapter.d.ts.map +0 -1
  562. package/runtime/adapters/types.d.ts +0 -95
  563. package/runtime/adapters/types.d.ts.map +0 -1
  564. package/runtime/csp.d.ts +0 -48
  565. package/runtime/csp.d.ts.map +0 -1
  566. package/runtime/index.d.ts +0 -17
  567. package/runtime/index.d.ts.map +0 -1
  568. package/runtime/index.js +0 -5264
  569. package/runtime/mcp-bridge.d.ts +0 -101
  570. package/runtime/mcp-bridge.d.ts.map +0 -1
  571. package/runtime/renderer-runtime.d.ts +0 -133
  572. package/runtime/renderer-runtime.d.ts.map +0 -1
  573. package/runtime/sanitizer.d.ts +0 -172
  574. package/runtime/sanitizer.d.ts.map +0 -1
  575. package/runtime/types.d.ts +0 -415
  576. package/runtime/types.d.ts.map +0 -1
  577. package/runtime/wrapper.d.ts +0 -421
  578. package/runtime/wrapper.d.ts.map +0 -1
  579. package/styles/index.d.ts +0 -8
  580. package/styles/index.d.ts.map +0 -1
  581. package/styles/index.js +0 -222
  582. package/styles/variants.d.ts +0 -51
  583. package/styles/variants.d.ts.map +0 -1
  584. package/theme/cdn.d.ts +0 -195
  585. package/theme/cdn.d.ts.map +0 -1
  586. package/theme/index.d.ts +0 -18
  587. package/theme/index.d.ts.map +0 -1
  588. package/theme/index.js +0 -757
  589. package/theme/platforms.d.ts +0 -107
  590. package/theme/platforms.d.ts.map +0 -1
  591. package/theme/presets/github-openai.d.ts +0 -50
  592. package/theme/presets/github-openai.d.ts.map +0 -1
  593. package/theme/presets/index.d.ts +0 -11
  594. package/theme/presets/index.d.ts.map +0 -1
  595. package/theme/theme.d.ts +0 -396
  596. package/theme/theme.d.ts.map +0 -1
  597. package/tool-template/builder.d.ts +0 -213
  598. package/tool-template/builder.d.ts.map +0 -1
  599. package/tool-template/index.d.ts +0 -16
  600. package/tool-template/index.d.ts.map +0 -1
  601. package/tool-template/index.js +0 -3559
  602. package/types/index.d.ts +0 -14
  603. package/types/index.d.ts.map +0 -1
  604. package/types/index.js +0 -108
  605. package/types/ui-config.d.ts +0 -639
  606. package/types/ui-config.d.ts.map +0 -1
  607. package/types/ui-runtime.d.ts +0 -1007
  608. package/types/ui-runtime.d.ts.map +0 -1
  609. package/typings/cache/cache-adapter.d.ts +0 -125
  610. package/typings/cache/cache-adapter.d.ts.map +0 -1
  611. package/typings/cache/index.d.ts +0 -10
  612. package/typings/cache/index.d.ts.map +0 -1
  613. package/typings/cache/memory-cache.d.ts +0 -92
  614. package/typings/cache/memory-cache.d.ts.map +0 -1
  615. package/typings/dts-parser.d.ts +0 -90
  616. package/typings/dts-parser.d.ts.map +0 -1
  617. package/typings/index.d.ts +0 -48
  618. package/typings/index.d.ts.map +0 -1
  619. package/typings/schemas.d.ts +0 -232
  620. package/typings/schemas.d.ts.map +0 -1
  621. package/typings/type-fetcher.d.ts +0 -89
  622. package/typings/type-fetcher.d.ts.map +0 -1
  623. package/typings/types.d.ts +0 -320
  624. package/typings/types.d.ts.map +0 -1
  625. package/utils/escape-html.d.ts +0 -58
  626. package/utils/escape-html.d.ts.map +0 -1
  627. package/utils/index.d.ts +0 -10
  628. package/utils/index.d.ts.map +0 -1
  629. package/utils/index.js +0 -70
  630. package/utils/safe-stringify.d.ts +0 -30
  631. package/utils/safe-stringify.d.ts.map +0 -1
  632. package/validation/error-box.d.ts +0 -56
  633. package/validation/error-box.d.ts.map +0 -1
  634. package/validation/index.d.ts +0 -13
  635. package/validation/index.d.ts.map +0 -1
  636. package/validation/index.js +0 -603
  637. package/validation/schema-paths.d.ts +0 -118
  638. package/validation/schema-paths.d.ts.map +0 -1
  639. package/validation/template-validator.d.ts +0 -143
  640. package/validation/template-validator.d.ts.map +0 -1
  641. package/validation/wrapper.d.ts +0 -97
  642. package/validation/wrapper.d.ts.map +0 -1
  643. package/widgets/index.d.ts +0 -8
  644. package/widgets/index.d.ts.map +0 -1
  645. package/widgets/index.js +0 -978
  646. package/widgets/progress.d.ts +0 -133
  647. package/widgets/progress.d.ts.map +0 -1
  648. package/widgets/resource.d.ts +0 -163
  649. package/widgets/resource.d.ts.map +0 -1
  650. /package/esm/render/{index.js → index.mjs} +0 -0
package/bundler/index.js CHANGED
@@ -5,9 +5,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __esm = (fn, res) => function __init() {
9
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
- };
11
8
  var __export = (target, all) => {
12
9
  for (var name in all)
13
10
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -30,678 +27,56 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
27
  ));
31
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
29
 
33
- // libs/ui/src/bundler/file-cache/storage/interface.ts
34
- function calculateManifestSize(manifest) {
35
- try {
36
- return Buffer.byteLength(JSON.stringify(manifest), "utf8");
37
- } catch {
38
- return 0;
39
- }
40
- }
41
- var DEFAULT_STORAGE_OPTIONS;
42
- var init_interface = __esm({
43
- "libs/ui/src/bundler/file-cache/storage/interface.ts"() {
44
- "use strict";
45
- DEFAULT_STORAGE_OPTIONS = {
46
- maxEntries: 1e3,
47
- maxSize: 100 * 1024 * 1024,
48
- // 100MB
49
- defaultTtl: 24 * 60 * 60,
50
- // 24 hours
51
- compress: false
52
- };
53
- }
54
- });
55
-
56
- // libs/ui/src/bundler/file-cache/storage/filesystem.ts
57
- var filesystem_exports = {};
58
- __export(filesystem_exports, {
59
- CacheInitializationError: () => CacheInitializationError,
60
- CacheOperationError: () => CacheOperationError,
61
- FilesystemStorage: () => FilesystemStorage,
62
- StorageNotInitializedError: () => StorageNotInitializedError,
63
- createFilesystemStorage: () => createFilesystemStorage
64
- });
65
- function createFilesystemStorage(options) {
66
- return new FilesystemStorage(options);
67
- }
68
- var import_promises, import_path, import_fs, import_crypto, CacheInitializationError, CacheOperationError, StorageNotInitializedError, DEFAULT_FS_OPTIONS, FilesystemStorage;
69
- var init_filesystem = __esm({
70
- "libs/ui/src/bundler/file-cache/storage/filesystem.ts"() {
71
- "use strict";
72
- import_promises = require("fs/promises");
73
- import_path = require("path");
74
- import_fs = require("fs");
75
- import_crypto = require("crypto");
76
- init_interface();
77
- CacheInitializationError = class extends Error {
78
- cause;
79
- constructor(message, cause) {
80
- super(message);
81
- this.name = "CacheInitializationError";
82
- this.cause = cause;
83
- }
84
- };
85
- CacheOperationError = class extends Error {
86
- cause;
87
- constructor(message, cause) {
88
- super(message);
89
- this.name = "CacheOperationError";
90
- this.cause = cause;
91
- }
92
- };
93
- StorageNotInitializedError = class extends Error {
94
- constructor() {
95
- super("Storage not initialized. Call initialize() first.");
96
- this.name = "StorageNotInitializedError";
97
- }
98
- };
99
- DEFAULT_FS_OPTIONS = {
100
- ...DEFAULT_STORAGE_OPTIONS,
101
- cacheDir: ".frontmcp-cache/builds",
102
- extension: ".json"
103
- };
104
- FilesystemStorage = class {
105
- type = "filesystem";
106
- options;
107
- initialized = false;
108
- stats = {
109
- entries: 0,
110
- totalSize: 0,
111
- hits: 0,
112
- misses: 0,
113
- hitRate: 0
114
- };
115
- constructor(options = {}) {
116
- this.options = {
117
- ...DEFAULT_FS_OPTIONS,
118
- ...options
119
- };
120
- }
121
- /**
122
- * Initialize the storage directory.
123
- */
124
- async initialize() {
125
- if (this.initialized) return;
126
- try {
127
- await (0, import_promises.mkdir)(this.options.cacheDir, { recursive: true });
128
- await this.loadStats();
129
- this.initialized = true;
130
- } catch (error) {
131
- throw new CacheInitializationError(`Failed to initialize cache directory: ${error}`, error);
132
- }
133
- }
134
- /**
135
- * Get a cached manifest.
136
- */
137
- async get(key) {
138
- this.ensureInitialized();
139
- const filePath = this.getFilePath(key);
140
- try {
141
- if (!(0, import_fs.existsSync)(filePath)) {
142
- this.stats.misses++;
143
- this.updateHitRate();
144
- return void 0;
145
- }
146
- const content = await (0, import_promises.readFile)(filePath, "utf8");
147
- const entry = JSON.parse(content);
148
- if (Date.now() > entry.metadata.expiresAt) {
149
- await this.delete(key);
150
- this.stats.misses++;
151
- this.updateHitRate();
152
- return void 0;
153
- }
154
- entry.metadata.lastAccessedAt = Date.now();
155
- entry.metadata.accessCount++;
156
- this.writeEntry(filePath, entry).catch((err) => {
157
- if (process.env["DEBUG"]) {
158
- console.debug(`[FilesystemStorage] Failed to update cache metadata for ${key}: ${err}`);
159
- }
160
- });
161
- this.stats.hits++;
162
- this.updateHitRate();
163
- return entry.data;
164
- } catch {
165
- this.stats.misses++;
166
- this.updateHitRate();
167
- return void 0;
168
- }
169
- }
170
- /**
171
- * Store a manifest in cache.
172
- */
173
- async set(key, manifest, ttl) {
174
- this.ensureInitialized();
175
- const filePath = this.getFilePath(key);
176
- const size = calculateManifestSize(manifest);
177
- const effectiveTtl = ttl ?? this.options.defaultTtl;
178
- await this.ensureCapacity(size);
179
- const entry = {
180
- data: manifest,
181
- metadata: {
182
- key,
183
- size,
184
- createdAt: Date.now(),
185
- expiresAt: Date.now() + effectiveTtl * 1e3,
186
- lastAccessedAt: Date.now(),
187
- accessCount: 0
188
- }
189
- };
190
- await this.writeEntry(filePath, entry);
191
- this.stats.entries++;
192
- this.stats.totalSize += size;
193
- }
194
- /**
195
- * Check if a key exists.
196
- */
197
- async has(key) {
198
- this.ensureInitialized();
199
- const filePath = this.getFilePath(key);
200
- try {
201
- if (!(0, import_fs.existsSync)(filePath)) return false;
202
- const content = await (0, import_promises.readFile)(filePath, "utf8");
203
- const entry = JSON.parse(content);
204
- if (Date.now() > entry.metadata.expiresAt) {
205
- await this.delete(key);
206
- return false;
207
- }
208
- return true;
209
- } catch {
210
- return false;
211
- }
212
- }
213
- /**
214
- * Delete a cached entry.
215
- */
216
- async delete(key) {
217
- this.ensureInitialized();
218
- const filePath = this.getFilePath(key);
219
- try {
220
- if (!(0, import_fs.existsSync)(filePath)) return false;
221
- const content = await (0, import_promises.readFile)(filePath, "utf8");
222
- const entry = JSON.parse(content);
223
- await (0, import_promises.unlink)(filePath);
224
- this.stats.entries = Math.max(0, this.stats.entries - 1);
225
- this.stats.totalSize = Math.max(0, this.stats.totalSize - entry.metadata.size);
226
- return true;
227
- } catch {
228
- return false;
229
- }
230
- }
231
- /**
232
- * Clear all cached entries.
233
- */
234
- async clear() {
235
- this.ensureInitialized();
236
- try {
237
- await (0, import_promises.rm)(this.options.cacheDir, { recursive: true, force: true });
238
- await (0, import_promises.mkdir)(this.options.cacheDir, { recursive: true });
239
- this.stats = {
240
- entries: 0,
241
- totalSize: 0,
242
- hits: 0,
243
- misses: 0,
244
- hitRate: 0
245
- };
246
- } catch (error) {
247
- throw new CacheOperationError(`Failed to clear cache: ${error}`, error);
248
- }
249
- }
250
- /**
251
- * Get cache statistics.
252
- */
253
- async getStats() {
254
- return { ...this.stats };
255
- }
256
- /**
257
- * Clean up expired entries.
258
- */
259
- async cleanup() {
260
- this.ensureInitialized();
261
- let removed = 0;
262
- try {
263
- const files = await (0, import_promises.readdir)(this.options.cacheDir);
264
- for (const file of files) {
265
- if (!file.endsWith(this.options.extension)) continue;
266
- const filePath = (0, import_path.join)(this.options.cacheDir, file);
267
- try {
268
- const content = await (0, import_promises.readFile)(filePath, "utf8");
269
- const entry = JSON.parse(content);
270
- if (Date.now() > entry.metadata.expiresAt) {
271
- await (0, import_promises.unlink)(filePath);
272
- this.stats.entries = Math.max(0, this.stats.entries - 1);
273
- this.stats.totalSize = Math.max(0, this.stats.totalSize - entry.metadata.size);
274
- removed++;
275
- }
276
- } catch {
277
- await (0, import_promises.unlink)(filePath).catch(() => {
278
- });
279
- removed++;
280
- }
281
- }
282
- } catch {
283
- }
284
- return removed;
285
- }
286
- /**
287
- * Close the storage (no-op for filesystem).
288
- */
289
- async close() {
290
- }
291
- /**
292
- * Get the file path for a cache key.
293
- * Uses SHA-256 hash to avoid collisions from key sanitization.
294
- */
295
- getFilePath(key) {
296
- const hash = (0, import_crypto.createHash)("sha256").update(key).digest("hex").slice(0, 16);
297
- return (0, import_path.join)(this.options.cacheDir, `${hash}${this.options.extension}`);
298
- }
299
- /**
300
- * Write a cache entry to disk.
301
- */
302
- async writeEntry(filePath, entry) {
303
- await (0, import_promises.mkdir)((0, import_path.dirname)(filePath), { recursive: true });
304
- await (0, import_promises.writeFile)(filePath, JSON.stringify(entry, null, 2), "utf8");
305
- }
306
- /**
307
- * Ensure the storage is initialized.
308
- */
309
- ensureInitialized() {
310
- if (!this.initialized) {
311
- throw new StorageNotInitializedError();
312
- }
313
- }
314
- /**
315
- * Load stats from existing cache files.
316
- * Reads entry metadata to get accurate manifest sizes.
317
- */
318
- async loadStats() {
319
- try {
320
- const files = await (0, import_promises.readdir)(this.options.cacheDir);
321
- let entries = 0;
322
- let totalSize = 0;
323
- for (const file of files) {
324
- if (!file.endsWith(this.options.extension)) continue;
325
- const filePath = (0, import_path.join)(this.options.cacheDir, file);
326
- try {
327
- const content = await (0, import_promises.readFile)(filePath, "utf8");
328
- const entry = JSON.parse(content);
329
- entries++;
330
- totalSize += entry.metadata.size;
331
- } catch {
332
- }
333
- }
334
- this.stats.entries = entries;
335
- this.stats.totalSize = totalSize;
336
- } catch {
337
- }
338
- }
339
- /**
340
- * Ensure there's capacity for a new entry.
341
- */
342
- async ensureCapacity(newEntrySize) {
343
- if (this.stats.entries >= this.options.maxEntries) {
344
- await this.evictLRU();
345
- }
346
- while (this.stats.totalSize + newEntrySize > this.options.maxSize) {
347
- const evicted = await this.evictLRU();
348
- if (!evicted) break;
349
- }
350
- }
351
- /**
352
- * Evict the least recently used entry.
353
- */
354
- async evictLRU() {
355
- try {
356
- const files = await (0, import_promises.readdir)(this.options.cacheDir);
357
- let oldestKey = null;
358
- let oldestTime = Infinity;
359
- let corruptedFile = null;
360
- for (const file of files) {
361
- if (!file.endsWith(this.options.extension)) continue;
362
- const filePath = (0, import_path.join)(this.options.cacheDir, file);
363
- try {
364
- const content = await (0, import_promises.readFile)(filePath, "utf8");
365
- const entry = JSON.parse(content);
366
- if (entry.metadata.lastAccessedAt < oldestTime) {
367
- oldestTime = entry.metadata.lastAccessedAt;
368
- oldestKey = entry.metadata.key;
369
- }
370
- } catch {
371
- corruptedFile = filePath;
372
- }
373
- }
374
- if (corruptedFile) {
375
- try {
376
- await (0, import_promises.unlink)(corruptedFile);
377
- this.stats.entries = Math.max(0, this.stats.entries - 1);
378
- return true;
379
- } catch {
380
- return false;
381
- }
382
- }
383
- if (oldestKey) {
384
- return await this.delete(oldestKey);
385
- }
386
- return false;
387
- } catch {
388
- return false;
389
- }
390
- }
391
- /**
392
- * Update hit rate statistic.
393
- */
394
- updateHitRate() {
395
- const total = this.stats.hits + this.stats.misses;
396
- this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;
397
- }
398
- };
399
- }
400
- });
401
-
402
- // libs/ui/src/bundler/file-cache/storage/redis.ts
403
- var redis_exports = {};
404
- __export(redis_exports, {
405
- RedisStorage: () => RedisStorage,
406
- createRedisStorage: () => createRedisStorage
407
- });
408
- function createRedisStorage(options) {
409
- return new RedisStorage(options);
410
- }
411
- var STATS_KEY_SUFFIX, RedisStorage;
412
- var init_redis = __esm({
413
- "libs/ui/src/bundler/file-cache/storage/redis.ts"() {
414
- "use strict";
415
- init_interface();
416
- STATS_KEY_SUFFIX = ":__stats__";
417
- RedisStorage = class {
418
- type = "redis";
419
- options;
420
- initialized = false;
421
- localStats = {
422
- entries: 0,
423
- totalSize: 0,
424
- hits: 0,
425
- misses: 0,
426
- hitRate: 0
427
- };
428
- constructor(options) {
429
- if (!options.client) {
430
- throw new Error("Redis client is required");
431
- }
432
- this.options = {
433
- ...DEFAULT_STORAGE_OPTIONS,
434
- keyPrefix: "frontmcp:ui:build:",
435
- json: true,
436
- ...options
437
- };
438
- }
439
- /**
440
- * Initialize the Redis connection.
441
- */
442
- async initialize() {
443
- if (this.initialized) return;
444
- try {
445
- await this.options.client.ping();
446
- await this.loadStats();
447
- this.initialized = true;
448
- } catch (error) {
449
- throw new Error(`Failed to connect to Redis: ${error}`);
450
- }
451
- }
452
- /**
453
- * Get a cached manifest.
454
- */
455
- async get(key) {
456
- this.ensureInitialized();
457
- const redisKey = this.getRedisKey(key);
458
- try {
459
- const data = await this.options.client.get(redisKey);
460
- if (!data) {
461
- this.localStats.misses++;
462
- this.updateHitRate();
463
- await this.persistStats();
464
- return void 0;
465
- }
466
- const entry = JSON.parse(data);
467
- entry.metadata.lastAccessedAt = Date.now();
468
- entry.metadata.accessCount++;
469
- const ttl = await this.options.client.ttl(redisKey);
470
- if (ttl > 0) {
471
- const serialized = JSON.stringify(entry);
472
- await this.options.client.setex(redisKey, ttl, serialized);
473
- }
474
- this.localStats.hits++;
475
- this.updateHitRate();
476
- await this.persistStats();
477
- return entry.data;
478
- } catch (error) {
479
- console.warn?.(`Redis cache get failed for key "${key}": ${error}`);
480
- this.localStats.misses++;
481
- this.updateHitRate();
482
- await this.persistStats().catch(() => {
483
- });
484
- return void 0;
485
- }
486
- }
487
- /**
488
- * Store a manifest in cache.
489
- */
490
- async set(key, manifest, ttl) {
491
- this.ensureInitialized();
492
- const redisKey = this.getRedisKey(key);
493
- const size = calculateManifestSize(manifest);
494
- const effectiveTtl = ttl ?? this.options.defaultTtl;
495
- const entry = {
496
- data: manifest,
497
- metadata: {
498
- key,
499
- size,
500
- createdAt: Date.now(),
501
- expiresAt: Date.now() + effectiveTtl * 1e3,
502
- lastAccessedAt: Date.now(),
503
- accessCount: 0
504
- }
505
- };
506
- const serialized = JSON.stringify(entry);
507
- await this.options.client.setex(redisKey, effectiveTtl, serialized);
508
- this.localStats.entries++;
509
- this.localStats.totalSize += size;
510
- await this.persistStats();
511
- }
512
- /**
513
- * Check if a key exists.
514
- */
515
- async has(key) {
516
- this.ensureInitialized();
517
- const redisKey = this.getRedisKey(key);
518
- const exists = await this.options.client.exists(redisKey);
519
- return exists > 0;
520
- }
521
- /**
522
- * Delete a cached entry.
523
- */
524
- async delete(key) {
525
- this.ensureInitialized();
526
- const redisKey = this.getRedisKey(key);
527
- try {
528
- const data = await this.options.client.get(redisKey);
529
- if (data) {
530
- const entry = JSON.parse(data);
531
- this.localStats.totalSize = Math.max(0, this.localStats.totalSize - entry.metadata.size);
532
- }
533
- } catch {
534
- }
535
- const deleted = await this.options.client.del(redisKey);
536
- if (deleted > 0) {
537
- this.localStats.entries = Math.max(0, this.localStats.entries - 1);
538
- await this.persistStats();
539
- return true;
540
- }
541
- return false;
542
- }
543
- /**
544
- * Clear all cached entries.
545
- */
546
- async clear() {
547
- this.ensureInitialized();
548
- const pattern = `${this.options.keyPrefix}*`;
549
- const keys = await this.options.client.keys(pattern);
550
- if (keys.length > 0) {
551
- await this.options.client.del(keys);
552
- }
553
- this.localStats = {
554
- entries: 0,
555
- totalSize: 0,
556
- hits: 0,
557
- misses: 0,
558
- hitRate: 0
559
- };
560
- await this.persistStats();
561
- }
562
- /**
563
- * Get cache statistics.
564
- */
565
- async getStats() {
566
- await this.loadStats();
567
- return { ...this.localStats };
568
- }
569
- /**
570
- * Clean up expired entries.
571
- * Redis handles TTL expiration automatically, so this just refreshes stats.
572
- */
573
- async cleanup() {
574
- this.ensureInitialized();
575
- const pattern = `${this.options.keyPrefix}*`;
576
- const keys = await this.options.client.keys(pattern);
577
- const dataKeys = keys.filter((k) => !k.endsWith(STATS_KEY_SUFFIX));
578
- const previousCount = this.localStats.entries;
579
- this.localStats.entries = dataKeys.length;
580
- let totalSize = 0;
581
- for (const key of dataKeys) {
582
- try {
583
- const data = await this.options.client.get(key);
584
- if (data) {
585
- const entry = JSON.parse(data);
586
- totalSize += entry.metadata.size;
587
- }
588
- } catch {
589
- }
590
- }
591
- this.localStats.totalSize = totalSize;
592
- await this.persistStats();
593
- return Math.max(0, previousCount - this.localStats.entries);
594
- }
595
- /**
596
- * Close the Redis connection.
597
- */
598
- async close() {
599
- await this.options.client.quit();
600
- }
601
- /**
602
- * Get the Redis key for a cache key.
603
- */
604
- getRedisKey(key) {
605
- return `${this.options.keyPrefix}${key}`;
606
- }
607
- /**
608
- * Get the Redis key for stats.
609
- */
610
- getStatsKey() {
611
- return `${this.options.keyPrefix}${STATS_KEY_SUFFIX}`;
612
- }
613
- /**
614
- * Ensure the storage is initialized.
615
- */
616
- ensureInitialized() {
617
- if (!this.initialized) {
618
- throw new Error("Storage not initialized. Call initialize() first.");
619
- }
620
- }
621
- /**
622
- * Load stats from Redis.
623
- */
624
- async loadStats() {
625
- try {
626
- const statsKey = this.getStatsKey();
627
- const data = await this.options.client.get(statsKey);
628
- if (data) {
629
- const savedStats = JSON.parse(data);
630
- this.localStats = {
631
- ...this.localStats,
632
- ...savedStats
633
- };
634
- }
635
- } catch {
636
- }
637
- }
638
- /**
639
- * Persist stats to Redis.
640
- */
641
- async persistStats() {
642
- try {
643
- const statsKey = this.getStatsKey();
644
- const serialized = JSON.stringify(this.localStats);
645
- await this.options.client.set(statsKey, serialized);
646
- } catch {
647
- }
648
- }
649
- /**
650
- * Update hit rate statistic.
651
- */
652
- updateHitRate() {
653
- const total = this.localStats.hits + this.localStats.misses;
654
- this.localStats.hitRate = total > 0 ? this.localStats.hits / total : 0;
655
- }
656
- };
657
- }
658
- });
659
-
660
30
  // libs/ui/src/bundler/index.ts
661
31
  var bundler_exports = {};
662
32
  __export(bundler_exports, {
663
- BundlerCache: () => BundlerCache,
664
- ComponentBuilder: () => ComponentBuilder,
33
+ ALL_PLATFORMS: () => ALL_PLATFORMS,
34
+ BundlerCache: () => import_bundler4.BundlerCache,
35
+ ComponentBuilder: () => import_bundler7.ComponentBuilder,
665
36
  DEFAULT_BUNDLER_OPTIONS: () => DEFAULT_BUNDLER_OPTIONS,
666
37
  DEFAULT_BUNDLE_OPTIONS: () => DEFAULT_BUNDLE_OPTIONS,
667
38
  DEFAULT_SECURITY_POLICY: () => DEFAULT_SECURITY_POLICY,
668
39
  DEFAULT_STATIC_HTML_OPTIONS: () => DEFAULT_STATIC_HTML_OPTIONS,
669
- DEFAULT_STORAGE_OPTIONS: () => DEFAULT_STORAGE_OPTIONS,
670
- ExecutionError: () => ExecutionError,
671
- FilesystemStorage: () => FilesystemStorage,
40
+ DEFAULT_STORAGE_OPTIONS: () => import_bundler7.DEFAULT_STORAGE_OPTIONS,
41
+ ExecutionError: () => import_bundler2.ExecutionError,
42
+ FilesystemStorage: () => import_bundler7.FilesystemStorage,
43
+ HYBRID_DATA_PLACEHOLDER: () => HYBRID_DATA_PLACEHOLDER,
44
+ HYBRID_INPUT_PLACEHOLDER: () => HYBRID_INPUT_PLACEHOLDER,
672
45
  InMemoryBundler: () => InMemoryBundler,
673
- RedisStorage: () => RedisStorage,
46
+ RedisStorage: () => import_bundler7.RedisStorage,
674
47
  STATIC_HTML_CDN: () => STATIC_HTML_CDN,
675
- SecurityError: () => SecurityError,
676
- buildIdFromHash: () => buildIdFromHash,
677
- calculateComponentHash: () => calculateComponentHash,
678
- calculateManifestSize: () => calculateManifestSize,
679
- calculateQuickHash: () => calculateQuickHash,
48
+ SecurityError: () => import_bundler2.SecurityError,
49
+ buildIdFromHash: () => import_bundler7.buildIdFromHash,
50
+ calculateComponentHash: () => import_bundler7.calculateComponentHash,
51
+ calculateManifestSize: () => import_bundler7.calculateManifestSize,
52
+ calculateQuickHash: () => import_bundler7.calculateQuickHash,
680
53
  createBundler: () => createBundler,
681
- createCacheKey: () => createCacheKey,
682
- createFilesystemBuilder: () => createFilesystemBuilder,
683
- createFilesystemStorage: () => createFilesystemStorage,
684
- createRedisBuilder: () => createRedisBuilder,
685
- createRedisStorage: () => createRedisStorage,
686
- executeCode: () => executeCode,
687
- executeDefault: () => executeDefault,
688
- generateBuildId: () => generateBuildId,
54
+ createCacheKey: () => import_bundler4.createCacheKey,
55
+ createFilesystemBuilder: () => import_bundler7.createFilesystemBuilder,
56
+ createFilesystemStorage: () => import_bundler7.createFilesystemStorage,
57
+ createRedisBuilder: () => import_bundler7.createRedisBuilder,
58
+ createRedisStorage: () => import_bundler7.createRedisStorage,
59
+ executeCode: () => import_bundler6.executeCode,
60
+ executeDefault: () => import_bundler6.executeDefault,
61
+ generateBuildId: () => import_bundler7.generateBuildId,
689
62
  getCdnTypeForPlatform: () => getCdnTypeForPlatform,
690
- hashContent: () => hashContent,
691
- hashFile: () => hashFile,
692
- hashFiles: () => hashFiles,
693
- isExecutionError: () => isExecutionError,
694
- mergePolicy: () => mergePolicy,
695
- sha256: () => sha256,
696
- sha256Buffer: () => sha256Buffer,
697
- throwOnViolations: () => throwOnViolations,
698
- validateImports: () => validateImports,
699
- validateSize: () => validateSize,
700
- validateSource: () => validateSource
63
+ hashContent: () => import_bundler4.hashContent,
64
+ hashFile: () => import_bundler7.hashFile,
65
+ hashFiles: () => import_bundler7.hashFiles,
66
+ isExecutionError: () => import_bundler6.isExecutionError,
67
+ mergePolicy: () => import_bundler5.mergePolicy,
68
+ sha256: () => import_bundler7.sha256,
69
+ sha256Buffer: () => import_bundler7.sha256Buffer,
70
+ throwOnViolations: () => import_bundler5.throwOnViolations,
71
+ validateImports: () => import_bundler5.validateImports,
72
+ validateSize: () => import_bundler5.validateSize,
73
+ validateSource: () => import_bundler5.validateSource
701
74
  });
702
75
  module.exports = __toCommonJS(bundler_exports);
703
76
 
704
77
  // libs/ui/src/bundler/types.ts
78
+ var HYBRID_DATA_PLACEHOLDER = "__FRONTMCP_OUTPUT_PLACEHOLDER__";
79
+ var HYBRID_INPUT_PLACEHOLDER = "__FRONTMCP_INPUT_PLACEHOLDER__";
705
80
  var DEFAULT_SECURITY_POLICY = {
706
81
  allowedImports: [/^react$/, /^react-dom$/, /^react\/jsx-runtime$/, /^react\/jsx-dev-runtime$/, /^@frontmcp\/ui/],
707
82
  blockedImports: [
@@ -814,6 +189,13 @@ var DEFAULT_BUNDLER_OPTIONS = {
814
189
  verbose: false,
815
190
  esbuildOptions: {}
816
191
  };
192
+ var ALL_PLATFORMS = [
193
+ "openai",
194
+ "claude",
195
+ "cursor",
196
+ "ext-apps",
197
+ "generic"
198
+ ];
817
199
  var STATIC_HTML_CDN = {
818
200
  /**
819
201
  * ES modules from esm.sh (React 19, modern platforms)
@@ -829,11 +211,6 @@ var STATIC_HTML_CDN = {
829
211
  react: "https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js",
830
212
  reactDom: "https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"
831
213
  },
832
- /**
833
- * Tailwind CSS from cdnjs (cloudflare) - works on all platforms
834
- * Using CSS file instead of JS browser version to avoid style normalization issues
835
- */
836
- tailwind: "https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/3.4.1/tailwind.min.css",
837
214
  /**
838
215
  * Font CDN URLs
839
216
  */
@@ -863,656 +240,63 @@ var DEFAULT_STATIC_HTML_OPTIONS = {
863
240
  universal: false,
864
241
  contentType: "auto",
865
242
  includeMarkdown: false,
866
- includeMdx: false
243
+ includeMdx: false,
244
+ // Build mode defaults
245
+ buildMode: "static"
867
246
  };
868
247
 
869
- // libs/ui/src/bundler/cache.ts
870
- var BundlerCache = class {
871
- cache = /* @__PURE__ */ new Map();
872
- options;
873
- stats = {
874
- hits: 0,
875
- misses: 0,
876
- evictions: 0
877
- };
878
- constructor(options = {}) {
879
- this.options = {
880
- maxSize: options.maxSize ?? 100,
881
- ttl: options.ttl ?? 3e5
882
- };
883
- }
884
- /**
885
- * Get a cached bundle result.
886
- *
887
- * @param key - Cache key (typically content hash)
888
- * @returns Cached result or undefined if not found/expired
889
- */
890
- get(key) {
891
- const entry = this.cache.get(key);
892
- if (!entry) {
893
- this.stats.misses++;
894
- return void 0;
895
- }
896
- if (this.isExpired(entry)) {
897
- this.cache.delete(key);
898
- this.stats.misses++;
899
- this.stats.evictions++;
900
- return void 0;
901
- }
902
- entry.lastAccessedAt = Date.now();
903
- entry.accessCount++;
904
- this.stats.hits++;
905
- this.cache.delete(key);
906
- this.cache.set(key, entry);
907
- return entry.result;
908
- }
909
- /**
910
- * Store a bundle result in the cache.
911
- *
912
- * @param key - Cache key (typically content hash)
913
- * @param result - Bundle result to cache
914
- */
915
- set(key, result) {
916
- while (this.cache.size >= this.options.maxSize) {
917
- this.evictOldest();
918
- }
919
- const now = Date.now();
920
- const entry = {
921
- result,
922
- createdAt: now,
923
- lastAccessedAt: now,
924
- accessCount: 1
925
- };
926
- this.cache.set(key, entry);
927
- }
928
- /**
929
- * Check if a key exists in the cache (and is not expired).
930
- *
931
- * @param key - Cache key to check
932
- * @returns true if key exists and is not expired
933
- */
934
- has(key) {
935
- const entry = this.cache.get(key);
936
- if (!entry) return false;
937
- if (this.isExpired(entry)) {
938
- this.cache.delete(key);
939
- this.stats.evictions++;
940
- return false;
941
- }
942
- return true;
943
- }
944
- /**
945
- * Delete a specific entry from the cache.
946
- *
947
- * @param key - Cache key to delete
948
- * @returns true if the key was found and deleted
949
- */
950
- delete(key) {
951
- return this.cache.delete(key);
952
- }
953
- /**
954
- * Clear all entries from the cache.
955
- */
956
- clear() {
957
- this.cache.clear();
958
- this.stats = {
959
- hits: 0,
960
- misses: 0,
961
- evictions: 0
962
- };
963
- }
964
- /**
965
- * Get cache statistics.
966
- *
967
- * @returns Current cache statistics
968
- */
969
- getStats() {
970
- const total = this.stats.hits + this.stats.misses;
971
- const hitRate = total > 0 ? this.stats.hits / total : 0;
972
- let memoryUsage = 0;
973
- for (const entry of this.cache.values()) {
974
- memoryUsage += entry.result.size;
975
- if (entry.result.map) {
976
- memoryUsage += entry.result.map.length;
977
- }
978
- }
979
- return {
980
- size: this.cache.size,
981
- hits: this.stats.hits,
982
- misses: this.stats.misses,
983
- hitRate,
984
- evictions: this.stats.evictions,
985
- memoryUsage
986
- };
987
- }
988
- /**
989
- * Remove expired entries from the cache.
990
- *
991
- * @returns Number of entries removed
992
- */
993
- cleanup() {
994
- let removed = 0;
995
- for (const [key, entry] of this.cache.entries()) {
996
- if (this.isExpired(entry)) {
997
- this.cache.delete(key);
998
- removed++;
999
- }
1000
- }
1001
- this.stats.evictions += removed;
1002
- return removed;
1003
- }
1004
- /**
1005
- * Get all cache keys.
1006
- *
1007
- * @returns Array of cache keys
1008
- */
1009
- keys() {
1010
- return Array.from(this.cache.keys());
1011
- }
1012
- /**
1013
- * Get the number of entries in the cache.
1014
- */
1015
- get size() {
1016
- return this.cache.size;
1017
- }
1018
- /**
1019
- * Check if an entry is expired.
1020
- */
1021
- isExpired(entry) {
1022
- return Date.now() - entry.createdAt > this.options.ttl;
1023
- }
1024
- /**
1025
- * Evict the oldest (least recently used) entry.
1026
- */
1027
- evictOldest() {
1028
- const oldestKey = this.cache.keys().next().value;
1029
- if (oldestKey !== void 0) {
1030
- this.cache.delete(oldestKey);
1031
- this.stats.evictions++;
1032
- }
1033
- }
1034
- };
1035
- function hashContent(content) {
1036
- let hash = 2166136261;
1037
- for (let i = 0; i < content.length; i++) {
1038
- hash ^= content.charCodeAt(i);
1039
- hash = Math.imul(hash, 16777619);
1040
- }
1041
- return (hash >>> 0).toString(16).padStart(8, "0");
1042
- }
1043
- function createCacheKey(source, options) {
1044
- const sourceHash = hashContent(source);
1045
- const optionsHash = hashContent(
1046
- JSON.stringify({
1047
- sourceType: options.sourceType,
1048
- format: options.format,
1049
- minify: options.minify,
1050
- externals: options.externals?.sort(),
1051
- target: options.target
1052
- })
1053
- );
1054
- return `${sourceHash}-${optionsHash}`;
1055
- }
248
+ // libs/ui/src/bundler/bundler.ts
249
+ var import_adapters = require("@frontmcp/uipack/adapters");
250
+ var import_theme = require("@frontmcp/uipack/theme");
251
+ var import_bundler = require("@frontmcp/uipack/bundler");
252
+ var import_utils = require("@frontmcp/uipack/utils");
1056
253
 
1057
- // libs/ui/src/bundler/sandbox/policy.ts
1058
- var UNSAFE_PATTERNS = {
1059
- eval: /\beval\s*\(/g,
1060
- functionConstructor: /\bnew\s+Function\s*\(/g,
1061
- dynamicImport: /\bimport\s*\(/g,
1062
- require: /\brequire\s*\(/g,
1063
- processEnv: /\bprocess\.env\b/g,
1064
- globalThis: /\bglobalThis\b/g,
1065
- windowLocation: /\bwindow\.location\b/g,
1066
- documentCookie: /\bdocument\.cookie\b/g,
1067
- innerHTML: /\.innerHTML\s*=/g,
1068
- outerHTML: /\.outerHTML\s*=/g,
1069
- document_write: /\bdocument\.write\s*\(/g
1070
- };
1071
- function validateSource(source, policy = DEFAULT_SECURITY_POLICY) {
1072
- const violations = [];
1073
- if (policy.noEval !== false) {
1074
- const evalMatches = [...source.matchAll(UNSAFE_PATTERNS.eval)];
1075
- for (const match of evalMatches) {
1076
- violations.push({
1077
- type: "eval-usage",
1078
- message: "eval() is not allowed for security reasons",
1079
- location: getLocation(source, match.index ?? 0),
1080
- value: match[0]
1081
- });
1082
- }
1083
- const fnMatches = [...source.matchAll(UNSAFE_PATTERNS.functionConstructor)];
1084
- for (const match of fnMatches) {
1085
- violations.push({
1086
- type: "eval-usage",
1087
- message: "new Function() is not allowed for security reasons",
1088
- location: getLocation(source, match.index ?? 0),
1089
- value: match[0]
1090
- });
1091
- }
1092
- }
1093
- if (policy.noDynamicImports !== false) {
1094
- const matches = [...source.matchAll(UNSAFE_PATTERNS.dynamicImport)];
1095
- for (const match of matches) {
1096
- violations.push({
1097
- type: "dynamic-import",
1098
- message: "Dynamic imports are not allowed for security reasons",
1099
- location: getLocation(source, match.index ?? 0),
1100
- value: match[0]
1101
- });
1102
- }
1103
- }
1104
- if (policy.noRequire !== false) {
1105
- const matches = [...source.matchAll(UNSAFE_PATTERNS.require)];
1106
- for (const match of matches) {
1107
- violations.push({
1108
- type: "require-usage",
1109
- message: "require() is not allowed for security reasons",
1110
- location: getLocation(source, match.index ?? 0),
1111
- value: match[0]
1112
- });
1113
- }
1114
- }
1115
- const importViolations = validateImports(source, policy);
1116
- violations.push(...importViolations);
1117
- return violations;
1118
- }
1119
- function validateImports(source, policy = DEFAULT_SECURITY_POLICY) {
1120
- const violations = [];
1121
- const importPattern = /import\s+(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?['"]([^'"]+)['"]/g;
1122
- const imports = [];
1123
- let match;
1124
- while ((match = importPattern.exec(source)) !== null) {
1125
- imports.push({ module: match[1], index: match.index });
254
+ // libs/ui/src/universal/types.ts
255
+ var UNIVERSAL_CDN = {
256
+ esm: {
257
+ reactMarkdown: "https://esm.sh/react-markdown@9",
258
+ mdxReact: "https://esm.sh/@mdx-js/react@3",
259
+ remarkGfm: "https://esm.sh/remark-gfm@4"
1126
260
  }
1127
- const requirePattern = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
1128
- while ((match = requirePattern.exec(source)) !== null) {
1129
- imports.push({ module: match[1], index: match.index });
261
+ // Note: These libraries are not available on cdnjs
262
+ // For Claude, we use inline implementations
263
+ };
264
+ function detectContentType(source) {
265
+ if (typeof source === "function") {
266
+ return "react";
1130
267
  }
1131
- for (const imp of imports) {
1132
- if (policy.blockedImports) {
1133
- for (const blocked of policy.blockedImports) {
1134
- if (blocked.test(imp.module)) {
1135
- violations.push({
1136
- type: "blocked-import",
1137
- message: `Import '${imp.module}' is blocked by security policy`,
1138
- location: getLocation(source, imp.index),
1139
- value: imp.module
1140
- });
1141
- break;
1142
- }
1143
- }
1144
- }
1145
- if (policy.allowedImports && policy.allowedImports.length > 0) {
1146
- const isAllowed = policy.allowedImports.some((pattern) => pattern.test(imp.module));
1147
- if (!isAllowed) {
1148
- const alreadyBlocked = violations.some((v) => v.type === "blocked-import" && v.value === imp.module);
1149
- if (!alreadyBlocked) {
1150
- violations.push({
1151
- type: "disallowed-import",
1152
- message: `Import '${imp.module}' is not in the allowed imports list`,
1153
- location: getLocation(source, imp.index),
1154
- value: imp.module
1155
- });
1156
- }
1157
- }
1158
- }
268
+ if (typeof source !== "string") {
269
+ return "html";
1159
270
  }
1160
- return violations;
1161
- }
1162
- function validateSize(size, policy = DEFAULT_SECURITY_POLICY) {
1163
- const maxSize = policy.maxBundleSize ?? DEFAULT_SECURITY_POLICY.maxBundleSize ?? 512e3;
1164
- if (size > maxSize) {
1165
- return {
1166
- type: "size-exceeded",
1167
- message: `Bundle size (${formatBytes(size)}) exceeds maximum allowed (${formatBytes(maxSize)})`,
1168
- value: String(size)
1169
- };
271
+ const hasModuleSyntax = /^import\s+/m.test(source) || /^export\s+(default\s+)?/m.test(source) || /^const\s+\w+\s*=\s*\([^)]*\)\s*=>/m.test(source) || // Arrow function components
272
+ /^function\s+\w+\s*\(/m.test(source);
273
+ const hasJsxTags = /<[A-Z][a-zA-Z]*/.test(source);
274
+ const hasMarkdown = /^#{1,6}\s/m.test(source) || /^\*\s/m.test(source) || /^-\s/m.test(source) || /^\d+\.\s/m.test(source);
275
+ if (hasModuleSyntax && hasJsxTags) {
276
+ return "react";
1170
277
  }
1171
- return void 0;
1172
- }
1173
- function mergePolicy(userPolicy) {
1174
- if (!userPolicy) {
1175
- return { ...DEFAULT_SECURITY_POLICY };
278
+ if (hasJsxTags && hasMarkdown && !hasModuleSyntax) {
279
+ return "mdx";
1176
280
  }
1177
- return {
1178
- allowedImports: userPolicy.allowedImports ?? DEFAULT_SECURITY_POLICY.allowedImports,
1179
- blockedImports: userPolicy.blockedImports ?? DEFAULT_SECURITY_POLICY.blockedImports,
1180
- maxBundleSize: userPolicy.maxBundleSize ?? DEFAULT_SECURITY_POLICY.maxBundleSize,
1181
- maxTransformTime: userPolicy.maxTransformTime ?? DEFAULT_SECURITY_POLICY.maxTransformTime,
1182
- noEval: userPolicy.noEval ?? DEFAULT_SECURITY_POLICY.noEval,
1183
- noDynamicImports: userPolicy.noDynamicImports ?? DEFAULT_SECURITY_POLICY.noDynamicImports,
1184
- noRequire: userPolicy.noRequire ?? DEFAULT_SECURITY_POLICY.noRequire,
1185
- allowedGlobals: userPolicy.allowedGlobals ?? DEFAULT_SECURITY_POLICY.allowedGlobals
1186
- };
1187
- }
1188
- function getLocation(source, index) {
1189
- const lines = source.slice(0, index).split("\n");
1190
- return {
1191
- line: lines.length,
1192
- column: lines[lines.length - 1].length + 1
1193
- };
1194
- }
1195
- function formatBytes(bytes) {
1196
- if (bytes < 1024) return `${bytes} B`;
1197
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1198
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1199
- }
1200
- var SecurityError = class extends Error {
1201
- violations;
1202
- constructor(message, violations) {
1203
- super(message);
1204
- this.name = "SecurityError";
1205
- this.violations = violations;
281
+ if (hasMarkdown || /\*\*[^*]+\*\*/.test(source) || /\[[^\]]+\]\([^)]+\)/.test(source)) {
282
+ return "markdown";
1206
283
  }
1207
- };
1208
- function throwOnViolations(violations) {
1209
- if (violations.length > 0) {
1210
- const message = violations.map((v) => v.message).join("; ");
1211
- throw new SecurityError(`Security policy violation: ${message}`, violations);
284
+ if (hasJsxTags && !hasModuleSyntax) {
285
+ return "mdx";
1212
286
  }
287
+ return "html";
1213
288
  }
1214
289
 
1215
- // libs/ui/src/bundler/sandbox/enclave-adapter.ts
1216
- var import_enclave_vm = require("enclave-vm");
1217
- var DEFAULT_ENCLAVE_OPTIONS = {
1218
- securityLevel: "SECURE",
1219
- timeout: 5e3,
1220
- maxIterations: 1e4,
1221
- validate: true,
1222
- transform: true
1223
- };
1224
- var STRICT_SECURITY_BLOCKED_IMPORTS_THRESHOLD = 10;
1225
- function mapSecurityLevel(policy) {
1226
- if (policy?.blockedImports && policy.blockedImports.length > STRICT_SECURITY_BLOCKED_IMPORTS_THRESHOLD) {
1227
- return "STRICT";
1228
- }
1229
- return "SECURE";
1230
- }
1231
- function createJSXRuntime(React) {
1232
- const R = React;
1233
- return {
1234
- jsx: (type, props, key) => {
1235
- const { children, ...rest } = props;
1236
- return R.createElement(type, key ? { ...rest, key } : rest, children);
1237
- },
1238
- jsxs: (type, props, key) => {
1239
- const { children, ...rest } = props;
1240
- return R.createElement(type, key ? { ...rest, key } : rest, children);
1241
- },
1242
- jsxDEV: (type, props, key, _isStaticChildren, _source, _self) => {
1243
- const { children, ...rest } = props;
1244
- return R.createElement(type, key ? { ...rest, key } : rest, children);
1245
- },
1246
- Fragment: R.Fragment
1247
- };
1248
- }
1249
- var DANGEROUS_GLOBAL_KEYS = /* @__PURE__ */ new Set([
1250
- "process",
1251
- "require",
1252
- "__dirname",
1253
- "__filename",
1254
- "Buffer",
1255
- "eval",
1256
- "Function",
1257
- "constructor",
1258
- "global",
1259
- "globalThis",
1260
- "module",
1261
- "exports",
1262
- "__proto__"
1263
- ]);
1264
- function sanitizeGlobalKey(key) {
1265
- return key.replace(/[^a-zA-Z0-9_$]/g, "_");
1266
- }
1267
- function buildGlobals(context) {
1268
- const globals = {};
1269
- if (context.React) {
1270
- globals["React"] = context.React;
1271
- }
1272
- if (context.ReactDOM) {
1273
- globals["ReactDOM"] = context.ReactDOM;
1274
- }
1275
- if (context.React) {
1276
- const jsxRuntime = createJSXRuntime(context.React);
1277
- globals["__jsx"] = jsxRuntime["jsx"];
1278
- globals["__jsxs"] = jsxRuntime["jsxs"];
1279
- globals["__jsxDEV"] = jsxRuntime["jsxDEV"];
1280
- globals["Fragment"] = jsxRuntime["Fragment"];
1281
- }
1282
- if (context.modules) {
1283
- for (const [key, value] of Object.entries(context.modules)) {
1284
- const sanitizedKey = sanitizeGlobalKey(key);
1285
- if (DANGEROUS_GLOBAL_KEYS.has(sanitizedKey)) {
1286
- throw new ExecutionError(
1287
- `Dangerous module key '${key}' (sanitized: '${sanitizedKey}') is not allowed in execution context`,
1288
- { code: "SECURITY_VIOLATION" }
1289
- );
1290
- }
1291
- globals[sanitizedKey] = value;
1292
- }
1293
- }
1294
- if (context.globals) {
1295
- for (const [key, value] of Object.entries(context.globals)) {
1296
- if (DANGEROUS_GLOBAL_KEYS.has(key)) {
1297
- throw new ExecutionError(`Dangerous global key '${key}' is not allowed in execution context`, {
1298
- code: "SECURITY_VIOLATION"
1299
- });
1300
- }
1301
- const sanitizedKey = sanitizeGlobalKey(key);
1302
- if (DANGEROUS_GLOBAL_KEYS.has(sanitizedKey)) {
1303
- throw new ExecutionError(
1304
- `Dangerous global key '${key}' (sanitized: '${sanitizedKey}') is not allowed in execution context`,
1305
- { code: "SECURITY_VIOLATION" }
1306
- );
1307
- }
1308
- globals[sanitizedKey] = value;
1309
- }
1310
- }
1311
- return globals;
1312
- }
1313
- function buildRequireFunction(context) {
1314
- const normalizedContextModules = {};
1315
- if (context.modules) {
1316
- for (const [key, value] of Object.entries(context.modules)) {
1317
- normalizedContextModules[key.toLowerCase()] = value;
1318
- }
1319
- }
1320
- const modules = {
1321
- react: context.React,
1322
- "react-dom": context.ReactDOM,
1323
- "react/jsx-runtime": context.React ? createJSXRuntime(context.React) : void 0,
1324
- "react/jsx-dev-runtime": context.React ? createJSXRuntime(context.React) : void 0,
1325
- ...normalizedContextModules
1326
- };
1327
- return (id) => {
1328
- const normalizedId = id.toLowerCase();
1329
- if (normalizedId in modules) {
1330
- const mod = modules[normalizedId];
1331
- if (mod === void 0) {
1332
- throw new Error(`Module '${id}' is not available. Did you forget to provide it in the context?`);
1333
- }
1334
- return mod;
1335
- }
1336
- throw new Error(`Module '${id}' is not available in the sandbox environment`);
1337
- };
1338
- }
1339
- async function executeCode(code, context = {}) {
1340
- const consoleOutput = [];
1341
- const globals = buildGlobals(context);
1342
- globals["console"] = {
1343
- log: (...args) => {
1344
- consoleOutput.push(args.map(String).join(" "));
1345
- },
1346
- info: (...args) => {
1347
- consoleOutput.push(`[INFO] ${args.map(String).join(" ")}`);
1348
- },
1349
- warn: (...args) => {
1350
- consoleOutput.push(`[WARN] ${args.map(String).join(" ")}`);
1351
- },
1352
- error: (...args) => {
1353
- consoleOutput.push(`[ERROR] ${args.map(String).join(" ")}`);
1354
- },
1355
- debug: (...args) => {
1356
- consoleOutput.push(`[DEBUG] ${args.map(String).join(" ")}`);
1357
- },
1358
- trace: () => {
1359
- },
1360
- dir: () => {
1361
- },
1362
- table: () => {
1363
- },
1364
- group: () => {
1365
- },
1366
- groupEnd: () => {
1367
- },
1368
- time: () => {
1369
- },
1370
- timeEnd: () => {
1371
- },
1372
- assert: () => {
1373
- },
1374
- clear: () => {
1375
- },
1376
- count: () => {
1377
- },
1378
- countReset: () => {
1379
- }
1380
- };
1381
- globals["require"] = buildRequireFunction(context);
1382
- const enclave = new import_enclave_vm.Enclave({
1383
- ...DEFAULT_ENCLAVE_OPTIONS,
1384
- timeout: context.timeout ?? DEFAULT_ENCLAVE_OPTIONS.timeout,
1385
- maxIterations: context.maxIterations ?? DEFAULT_ENCLAVE_OPTIONS.maxIterations,
1386
- securityLevel: mapSecurityLevel(context.security),
1387
- globals,
1388
- allowFunctionsInGlobals: true
1389
- // Required for React components
1390
- });
1391
- try {
1392
- const wrappedCode = `
1393
- const module = { exports: {} };
1394
- const exports = module.exports;
1395
- const __filename = 'widget.js';
1396
- const __dirname = '/';
1397
- ${code}
1398
- return module.exports;
1399
- `;
1400
- const result = await enclave.run(wrappedCode);
1401
- if (!result.success) {
1402
- const errorMessage = result.error?.message ?? "Execution failed";
1403
- const errorCode = result.error?.code;
1404
- if (errorCode === "TIMEOUT") {
1405
- throw new ExecutionError(`Execution timed out after ${context.timeout ?? DEFAULT_ENCLAVE_OPTIONS.timeout}ms`, {
1406
- code: "TIMEOUT"
1407
- });
1408
- }
1409
- if (errorCode === "MAX_ITERATIONS") {
1410
- throw new ExecutionError(
1411
- `Maximum iterations exceeded (${context.maxIterations ?? DEFAULT_ENCLAVE_OPTIONS.maxIterations})`,
1412
- {
1413
- code: "MAX_ITERATIONS"
1414
- }
1415
- );
1416
- }
1417
- if (errorCode === "VALIDATION_ERROR") {
1418
- throw new ExecutionError(`Security validation failed: ${errorMessage}`, { code: "SECURITY_VIOLATION" });
1419
- }
1420
- throw new ExecutionError(errorMessage, result.error);
1421
- }
1422
- return {
1423
- exports: result.value,
1424
- executionTime: result.stats.duration,
1425
- consoleOutput: consoleOutput.length > 0 ? consoleOutput : void 0
1426
- };
1427
- } finally {
1428
- enclave.dispose();
1429
- }
1430
- }
1431
- async function executeDefault(code, context = {}) {
1432
- const result = await executeCode(code, context);
1433
- if ("default" in result.exports) {
1434
- return result.exports.default;
1435
- }
1436
- const exportKeys = Object.keys(result.exports);
1437
- if (exportKeys.length === 0) {
1438
- throw new ExecutionError("Code did not export any values");
1439
- }
1440
- if (exportKeys.length === 1) {
1441
- return result.exports[exportKeys[0]];
1442
- }
1443
- return result.exports;
1444
- }
1445
- var ExecutionError = class extends Error {
1446
- /** Error code for categorization */
1447
- code;
1448
- constructor(message, cause) {
1449
- super(message, { cause });
1450
- this.name = "ExecutionError";
1451
- if (cause && typeof cause === "object" && "code" in cause) {
1452
- this.code = cause.code;
1453
- }
1454
- }
1455
- };
1456
- function isExecutionError(error) {
1457
- return error instanceof ExecutionError;
1458
- }
1459
-
1460
- // libs/ui/src/utils/escape-html.ts
1461
- function escapeHtml(str) {
1462
- if (str === null || str === void 0) {
1463
- return "";
1464
- }
1465
- const s = String(str);
1466
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
1467
- }
1468
- function escapeHtmlAttr(str) {
1469
- return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
1470
- }
1471
-
1472
- // libs/ui/src/universal/types.ts
1473
- var UNIVERSAL_CDN = {
1474
- esm: {
1475
- reactMarkdown: "https://esm.sh/react-markdown@9",
1476
- mdxReact: "https://esm.sh/@mdx-js/react@3",
1477
- remarkGfm: "https://esm.sh/remark-gfm@4"
1478
- }
1479
- // Note: These libraries are not available on cdnjs
1480
- // For Claude, we use inline implementations
1481
- };
1482
- function detectContentType(source) {
1483
- if (typeof source === "function") {
1484
- return "react";
1485
- }
1486
- if (typeof source !== "string") {
1487
- return "html";
1488
- }
1489
- const hasModuleSyntax = /^import\s+/m.test(source) || /^export\s+(default\s+)?/m.test(source) || /^const\s+\w+\s*=\s*\([^)]*\)\s*=>/m.test(source) || // Arrow function components
1490
- /^function\s+\w+\s*\(/m.test(source);
1491
- const hasJsxTags = /<[A-Z][a-zA-Z]*/.test(source);
1492
- const hasMarkdown = /^#{1,6}\s/m.test(source) || /^\*\s/m.test(source) || /^-\s/m.test(source) || /^\d+\.\s/m.test(source);
1493
- if (hasModuleSyntax && hasJsxTags) {
1494
- return "react";
1495
- }
1496
- if (hasJsxTags && hasMarkdown && !hasModuleSyntax) {
1497
- return "mdx";
1498
- }
1499
- if (hasMarkdown || /\*\*[^*]+\*\*/.test(source) || /\[[^\]]+\]\([^)]+\)/.test(source)) {
1500
- return "markdown";
1501
- }
1502
- if (hasJsxTags && !hasModuleSyntax) {
1503
- return "mdx";
1504
- }
1505
- return "html";
1506
- }
1507
-
1508
- // libs/ui/src/universal/cached-runtime.ts
1509
- var RUNTIME_PLACEHOLDERS = {
1510
- /** Placeholder for transpiled component code */
1511
- COMPONENT_CODE: "/*__FRONTMCP_COMPONENT_CODE__*/",
1512
- /** Placeholder for data injection */
1513
- DATA_INJECTION: "/*__FRONTMCP_DATA_INJECTION__*/",
1514
- /** Placeholder for custom components */
1515
- CUSTOM_COMPONENTS: "/*__FRONTMCP_CUSTOM_COMPONENTS__*/"
290
+ // libs/ui/src/universal/cached-runtime.ts
291
+ var import_runtime = require("@frontmcp/uipack/runtime");
292
+ var import_build = require("@frontmcp/uipack/build");
293
+ var RUNTIME_PLACEHOLDERS = {
294
+ /** Placeholder for transpiled component code */
295
+ COMPONENT_CODE: "/*__FRONTMCP_COMPONENT_CODE__*/",
296
+ /** Placeholder for data injection */
297
+ DATA_INJECTION: "/*__FRONTMCP_DATA_INJECTION__*/",
298
+ /** Placeholder for custom components */
299
+ CUSTOM_COMPONENTS: "/*__FRONTMCP_CUSTOM_COMPONENTS__*/"
1516
300
  };
1517
301
  var runtimeCache = /* @__PURE__ */ new Map();
1518
302
  var DEFAULT_CACHE_CONFIG = {
@@ -1531,6 +315,7 @@ function generateCacheKey(options) {
1531
315
  options.includeMarkdown ? "md" : "",
1532
316
  options.includeMdx ? "mdx" : "",
1533
317
  options.minify ? "min" : "",
318
+ options.includeBridge ? "bridge" : "",
1534
319
  securityKey
1535
320
  ].filter(Boolean).join(":");
1536
321
  }
@@ -1574,6 +359,17 @@ function buildStoreRuntime() {
1574
359
  context: state,
1575
360
  setContext: function(ctx) {
1576
361
  this.setState(ctx);
362
+ },
363
+ // Dynamic mode: update output and re-render
364
+ updateOutput: function(output) {
365
+ this.setState({ output: output, loading: false });
366
+ // Also update the global window variable for compatibility
367
+ window.__mcpToolOutput = output;
368
+ },
369
+ // Dynamic mode: update input and re-render
370
+ updateInput: function(input) {
371
+ this.setState({ input: input });
372
+ window.__mcpToolInput = input;
1577
373
  }
1578
374
  };
1579
375
 
@@ -1598,6 +394,32 @@ function buildStoreRuntime() {
1598
394
  window.useContent = function() {
1599
395
  return window.useFrontMCPStore().content;
1600
396
  };
397
+
398
+ // Connect to MCP Bridge for platform data detection
399
+ function initFromBridge() {
400
+ // Check for data from mcpBridge (handles OpenAI, ext-apps, etc.)
401
+ if (window.mcpBridge && window.mcpBridge.toolOutput != null) {
402
+ window.__frontmcp.setState({
403
+ output: window.mcpBridge.toolOutput,
404
+ loading: false
405
+ });
406
+ }
407
+
408
+ // Subscribe to bridge updates via onToolResult
409
+ if (window.mcpBridge && window.mcpBridge.onToolResult) {
410
+ window.mcpBridge.onToolResult(function(result) {
411
+ window.__frontmcp.updateOutput(result);
412
+ });
413
+ }
414
+ }
415
+
416
+ // Initialize from bridge when ready
417
+ if (window.mcpBridge) {
418
+ initFromBridge();
419
+ } else {
420
+ // Wait for bridge to be ready
421
+ window.addEventListener('mcp:bridge-ready', initFromBridge);
422
+ }
1601
423
  })();
1602
424
  `;
1603
425
  }
@@ -1817,71 +639,7 @@ function buildRenderersRuntime(options) {
1817
639
  `;
1818
640
  }
1819
641
  function buildUIComponentsRuntime() {
1820
- return `
1821
- // UI Components (Vendor)
1822
- (function() {
1823
- window.Card = function(props) {
1824
- var children = props.children;
1825
- var title = props.title;
1826
- var className = props.className || '';
1827
- return React.createElement('div', {
1828
- className: 'bg-white rounded-lg shadow border border-gray-200 overflow-hidden ' + className
1829
- }, [
1830
- title && React.createElement('div', {
1831
- key: 'header',
1832
- className: 'px-4 py-3 border-b border-gray-200 bg-gray-50'
1833
- }, React.createElement('h3', { className: 'text-sm font-medium text-gray-900' }, title)),
1834
- React.createElement('div', { key: 'body', className: 'p-4' }, children)
1835
- ]);
1836
- };
1837
-
1838
- window.Badge = function(props) {
1839
- var children = props.children;
1840
- var variant = props.variant || 'default';
1841
- var variantClasses = {
1842
- default: 'bg-gray-100 text-gray-800',
1843
- success: 'bg-green-100 text-green-800',
1844
- warning: 'bg-yellow-100 text-yellow-800',
1845
- error: 'bg-red-100 text-red-800',
1846
- info: 'bg-blue-100 text-blue-800'
1847
- };
1848
- return React.createElement('span', {
1849
- className: 'inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ' + (variantClasses[variant] || variantClasses.default)
1850
- }, children);
1851
- };
1852
-
1853
- window.Button = function(props) {
1854
- var children = props.children;
1855
- var variant = props.variant || 'primary';
1856
- var onClick = props.onClick;
1857
- var disabled = props.disabled;
1858
- var variantClasses = {
1859
- primary: 'bg-blue-600 text-white hover:bg-blue-700',
1860
- secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200',
1861
- outline: 'border border-gray-300 text-gray-700 hover:bg-gray-50',
1862
- danger: 'bg-red-600 text-white hover:bg-red-700'
1863
- };
1864
- return React.createElement('button', {
1865
- className: 'px-4 py-2 rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ' +
1866
- (disabled ? 'opacity-50 cursor-not-allowed ' : '') +
1867
- (variantClasses[variant] || variantClasses.primary),
1868
- onClick: onClick,
1869
- disabled: disabled
1870
- }, children);
1871
- };
1872
-
1873
- // Export to namespace
1874
- window.frontmcp_ui_namespaceObject = Object.assign({}, window.React || {}, {
1875
- useToolOutput: window.useToolOutput,
1876
- useToolInput: window.useToolInput,
1877
- useMcpBridgeContext: function() { return window.__frontmcp.context; },
1878
- useCallTool: function() { return function() { return Promise.resolve(null); }; },
1879
- Card: window.Card,
1880
- Badge: window.Badge,
1881
- Button: window.Button
1882
- });
1883
- })();
1884
- `;
642
+ return (0, import_build.buildUIComponentsRuntime)();
1885
643
  }
1886
644
  function buildUniversalAppRuntime() {
1887
645
  return `
@@ -2006,7 +764,11 @@ function getCachedRuntime(options, config = {}) {
2006
764
  }
2007
765
  runtimeCache.delete(cacheKey);
2008
766
  }
2009
- const vendorParts = [buildStoreRuntime(), buildRequireShim()];
767
+ const vendorParts = [];
768
+ if (options.includeBridge) {
769
+ vendorParts.push((0, import_runtime.getMCPBridgeScript)());
770
+ }
771
+ vendorParts.push(buildStoreRuntime(), buildRequireShim());
2010
772
  if (options.cdnType === "umd" || options.includeMarkdown) {
2011
773
  vendorParts.push(buildInlineMarkdownParser(options));
2012
774
  }
@@ -2045,12 +807,51 @@ function buildAppTemplate() {
2045
807
  return [buildCustomComponentsWrapper(), buildComponentWrapper(), buildDataInjectionWrapper()].join("\n");
2046
808
  }
2047
809
  function minifyScript(script) {
2048
- return script.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/\n\s*\n/g, "\n").replace(/^\s+/gm, "").trim();
810
+ return script.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/[^\n]*$/gm, "").replace(/\n\s*\n/g, "\n").replace(/^\s+/gm, "").trim();
2049
811
  }
2050
812
  function buildAppScript(appTemplate, componentCode, dataInjection, customComponents = "") {
2051
813
  return appTemplate.replace(RUNTIME_PLACEHOLDERS.CUSTOM_COMPONENTS, customComponents || "// No custom components").replace(RUNTIME_PLACEHOLDERS.COMPONENT_CODE, componentCode || "// No component code").replace(RUNTIME_PLACEHOLDERS.DATA_INJECTION, dataInjection);
2052
814
  }
2053
- function buildDataInjectionCode(toolName, input, output, structuredContent, contentType, source, hasComponent) {
815
+ var DEFAULT_OUTPUT_PLACEHOLDER = "__FRONTMCP_OUTPUT_PLACEHOLDER__";
816
+ var DEFAULT_INPUT_PLACEHOLDER = "__FRONTMCP_INPUT_PLACEHOLDER__";
817
+ function buildDataInjectionCode(toolName, input, output, structuredContent, contentType, source, hasComponent, options) {
818
+ const buildMode = options?.buildMode ?? "static";
819
+ const cdnType = options?.cdnType ?? "esm";
820
+ switch (buildMode) {
821
+ case "dynamic":
822
+ return buildDynamicDataInjectionCode(
823
+ toolName,
824
+ input,
825
+ output,
826
+ structuredContent,
827
+ contentType,
828
+ source,
829
+ hasComponent,
830
+ cdnType,
831
+ options?.dynamicOptions
832
+ );
833
+ case "hybrid":
834
+ return buildHybridDataInjectionCode(
835
+ toolName,
836
+ structuredContent,
837
+ contentType,
838
+ source,
839
+ hasComponent,
840
+ options?.hybridOptions
841
+ );
842
+ default:
843
+ return buildStaticDataInjectionCode(
844
+ toolName,
845
+ input,
846
+ output,
847
+ structuredContent,
848
+ contentType,
849
+ source,
850
+ hasComponent
851
+ );
852
+ }
853
+ }
854
+ function buildStaticDataInjectionCode(toolName, input, output, structuredContent, contentType, source, hasComponent) {
2054
855
  const safeJson = (value) => {
2055
856
  try {
2056
857
  return JSON.stringify(value);
@@ -2060,6 +861,7 @@ function buildDataInjectionCode(toolName, input, output, structuredContent, cont
2060
861
  };
2061
862
  if (hasComponent) {
2062
863
  return `
864
+ // Static Mode - Data baked at build time
2063
865
  window.__frontmcp.setState({
2064
866
  toolName: ${safeJson(toolName)},
2065
867
  input: ${safeJson(input ?? null)},
@@ -2074,6 +876,7 @@ function buildDataInjectionCode(toolName, input, output, structuredContent, cont
2074
876
  });`;
2075
877
  }
2076
878
  return `
879
+ // Static Mode - Data baked at build time
2077
880
  window.__frontmcp.setState({
2078
881
  toolName: ${safeJson(toolName)},
2079
882
  input: ${safeJson(input ?? null)},
@@ -2087,6 +890,181 @@ function buildDataInjectionCode(toolName, input, output, structuredContent, cont
2087
890
  error: null
2088
891
  });`;
2089
892
  }
893
+ function buildDynamicDataInjectionCode(toolName, input, output, structuredContent, contentType, source, hasComponent, cdnType, dynamicOptions) {
894
+ if (cdnType === "umd") {
895
+ return buildDynamicWithPlaceholdersCode(
896
+ toolName,
897
+ structuredContent,
898
+ contentType,
899
+ source,
900
+ hasComponent,
901
+ dynamicOptions
902
+ );
903
+ }
904
+ return buildDynamicWithSubscriptionCode(
905
+ toolName,
906
+ input,
907
+ output,
908
+ structuredContent,
909
+ contentType,
910
+ source,
911
+ hasComponent,
912
+ dynamicOptions
913
+ );
914
+ }
915
+ function buildDynamicWithPlaceholdersCode(toolName, structuredContent, contentType, source, hasComponent, dynamicOptions) {
916
+ const safeJson = (value) => {
917
+ try {
918
+ return JSON.stringify(value);
919
+ } catch {
920
+ return "null";
921
+ }
922
+ };
923
+ const outputPlaceholder = DEFAULT_OUTPUT_PLACEHOLDER;
924
+ const inputPlaceholder = DEFAULT_INPUT_PLACEHOLDER;
925
+ const includeInitialData = dynamicOptions?.includeInitialData ?? true;
926
+ const contentBlock = hasComponent ? `content: { type: 'react', source: window.__frontmcp_component }` : `content: { type: ${safeJson(contentType)}, source: ${safeJson(source)} }`;
927
+ return `
928
+ // Dynamic Mode - Placeholder-based for non-OpenAI platforms
929
+ var __outputRaw = "${outputPlaceholder}";
930
+ var __inputRaw = "${inputPlaceholder}";
931
+ var __output = null;
932
+ var __input = null;
933
+ var __error = null;
934
+ var __outputNotReplaced = false;
935
+ var __includeInitialData = ${includeInitialData};
936
+
937
+ // Parse output placeholder
938
+ if (typeof __outputRaw === 'string' && __outputRaw !== "${outputPlaceholder}") {
939
+ try { __output = JSON.parse(__outputRaw); } catch (e) {
940
+ console.warn('[FrontMCP] Failed to parse output:', e);
941
+ __error = 'Failed to parse output data';
942
+ }
943
+ } else if (__outputRaw === "${outputPlaceholder}") {
944
+ __outputNotReplaced = true;
945
+ }
946
+
947
+ // Parse input placeholder
948
+ if (typeof __inputRaw === 'string' && __inputRaw !== "${inputPlaceholder}") {
949
+ try { __input = JSON.parse(__inputRaw); } catch (e) { console.warn('[FrontMCP] Failed to parse input:', e); }
950
+ }
951
+
952
+ // Handle placeholder not replaced - show error if expecting initial data
953
+ if (__outputNotReplaced && __includeInitialData) {
954
+ __error = 'No data provided. The output placeholder was not replaced.';
955
+ }
956
+
957
+ window.__frontmcp.setState({
958
+ toolName: ${safeJson(toolName)},
959
+ input: __input,
960
+ output: __output,
961
+ structuredContent: ${safeJson(structuredContent ?? null)},
962
+ ${contentBlock},
963
+ loading: !__includeInitialData && __output === null && !__error,
964
+ error: __error
965
+ });`;
966
+ }
967
+ function buildDynamicWithSubscriptionCode(toolName, input, output, structuredContent, contentType, source, hasComponent, dynamicOptions) {
968
+ const safeJson = (value) => {
969
+ try {
970
+ return JSON.stringify(value);
971
+ } catch {
972
+ return "null";
973
+ }
974
+ };
975
+ const includeInitialData = dynamicOptions?.includeInitialData ?? true;
976
+ const subscribeToUpdates = dynamicOptions?.subscribeToUpdates ?? true;
977
+ const contentBlock = hasComponent ? `content: { type: 'react', source: window.__frontmcp_component }` : `content: { type: ${safeJson(contentType)}, source: ${safeJson(source)} }`;
978
+ const initialState = includeInitialData ? `{
979
+ toolName: ${safeJson(toolName)},
980
+ input: ${safeJson(input ?? null)},
981
+ output: ${safeJson(output ?? null)},
982
+ structuredContent: ${safeJson(structuredContent ?? null)},
983
+ ${contentBlock},
984
+ loading: false,
985
+ error: null
986
+ }` : `{
987
+ toolName: ${safeJson(toolName)},
988
+ input: ${safeJson(input ?? null)},
989
+ output: null,
990
+ structuredContent: ${safeJson(structuredContent ?? null)},
991
+ ${contentBlock},
992
+ loading: true,
993
+ error: null
994
+ }`;
995
+ const subscriptionBlock = subscribeToUpdates ? `
996
+ // Subscribe to platform tool result events
997
+ (function() {
998
+ function subscribeToUpdates() {
999
+ if (window.openai && window.openai.canvas && window.openai.canvas.onToolResult) {
1000
+ window.openai.canvas.onToolResult(function(result) {
1001
+ window.__frontmcp.updateOutput(result);
1002
+ window.dispatchEvent(new CustomEvent('frontmcp:toolResult', { detail: result }));
1003
+ });
1004
+ }
1005
+ }
1006
+ if (document.readyState === 'loading') {
1007
+ document.addEventListener('DOMContentLoaded', subscribeToUpdates);
1008
+ } else {
1009
+ subscribeToUpdates();
1010
+ }
1011
+ })();` : "";
1012
+ return `
1013
+ // Dynamic Mode - OpenAI Subscription
1014
+ window.__frontmcp.setState(${initialState});
1015
+ ${subscriptionBlock}`;
1016
+ }
1017
+ function buildHybridDataInjectionCode(toolName, structuredContent, contentType, source, hasComponent, hybridOptions) {
1018
+ const safeJson = (value) => {
1019
+ try {
1020
+ return JSON.stringify(value);
1021
+ } catch {
1022
+ return "null";
1023
+ }
1024
+ };
1025
+ const outputPlaceholder = hybridOptions?.placeholder ?? DEFAULT_OUTPUT_PLACEHOLDER;
1026
+ const inputPlaceholder = hybridOptions?.inputPlaceholder ?? DEFAULT_INPUT_PLACEHOLDER;
1027
+ const contentBlock = hasComponent ? `content: { type: 'react', source: window.__frontmcp_component }` : `content: { type: ${safeJson(contentType)}, source: ${safeJson(source)} }`;
1028
+ return `
1029
+ // Hybrid Mode - Placeholders replaced at runtime
1030
+ var __outputRaw = "${outputPlaceholder}";
1031
+ var __inputRaw = "${inputPlaceholder}";
1032
+ var __output = null;
1033
+ var __input = null;
1034
+ var __error = null;
1035
+ var __outputNotReplaced = false;
1036
+
1037
+ // Parse output placeholder
1038
+ if (typeof __outputRaw === 'string' && __outputRaw !== "${outputPlaceholder}") {
1039
+ try { __output = JSON.parse(__outputRaw); } catch (e) {
1040
+ console.warn('[FrontMCP] Failed to parse output:', e);
1041
+ __error = 'Failed to parse output data';
1042
+ }
1043
+ } else if (__outputRaw === "${outputPlaceholder}") {
1044
+ // Placeholder not replaced - no data was injected
1045
+ __outputNotReplaced = true;
1046
+ }
1047
+
1048
+ // Parse input placeholder
1049
+ if (typeof __inputRaw === 'string' && __inputRaw !== "${inputPlaceholder}") {
1050
+ try { __input = JSON.parse(__inputRaw); } catch (e) { console.warn('[FrontMCP] Failed to parse input:', e); }
1051
+ }
1052
+
1053
+ // Set error if output placeholder was not replaced (no data provided)
1054
+ if (__outputNotReplaced) {
1055
+ __error = 'No data provided. The output placeholder was not replaced.';
1056
+ }
1057
+
1058
+ window.__frontmcp.setState({
1059
+ toolName: ${safeJson(toolName)},
1060
+ input: __input,
1061
+ output: __output,
1062
+ structuredContent: ${safeJson(structuredContent ?? null)},
1063
+ ${contentBlock},
1064
+ loading: false,
1065
+ error: __error
1066
+ });`;
1067
+ }
2090
1068
  function buildComponentCode(transpiledCode) {
2091
1069
  return `
2092
1070
  // CommonJS module shim
@@ -2101,24 +1079,395 @@ function buildComponentCode(transpiledCode) {
2101
1079
  }
2102
1080
 
2103
1081
  // libs/ui/src/bundler/bundler.ts
2104
- var esbuildTransform = null;
2105
- async function loadEsbuild() {
2106
- if (esbuildTransform !== null) {
2107
- return esbuildTransform;
1082
+ var import_build2 = require("@frontmcp/uipack/build");
1083
+
1084
+ // libs/ui/src/bundler/browser-components.ts
1085
+ var path = __toESM(require("path"));
1086
+ var cachedBrowserComponents = null;
1087
+ var buildingPromise = null;
1088
+ function getComponentsEntrySource() {
1089
+ return `
1090
+ // Browser Components Entry Point
1091
+ // This gets transpiled by esbuild to create browser-compatible code
1092
+
1093
+ import {
1094
+ // Card styles
1095
+ CARD_VARIANTS,
1096
+ CARD_SIZES,
1097
+ // Button styles
1098
+ BUTTON_VARIANTS,
1099
+ BUTTON_SIZES,
1100
+ BUTTON_ICON_SIZES,
1101
+ BUTTON_BASE_CLASSES,
1102
+ LOADING_SPINNER,
1103
+ // Badge styles
1104
+ BADGE_VARIANTS,
1105
+ BADGE_SIZES,
1106
+ BADGE_DOT_SIZES,
1107
+ BADGE_DOT_VARIANTS,
1108
+ // Alert styles
1109
+ ALERT_VARIANTS,
1110
+ ALERT_BASE_CLASSES,
1111
+ ALERT_ICONS,
1112
+ CLOSE_ICON,
1113
+ // Utility
1114
+ cn,
1115
+ } from '@frontmcp/uipack/styles';
1116
+
1117
+ // Re-export for the IIFE
1118
+ export {
1119
+ CARD_VARIANTS,
1120
+ CARD_SIZES,
1121
+ BUTTON_VARIANTS,
1122
+ BUTTON_SIZES,
1123
+ BUTTON_ICON_SIZES,
1124
+ BUTTON_BASE_CLASSES,
1125
+ LOADING_SPINNER,
1126
+ BADGE_VARIANTS,
1127
+ BADGE_SIZES,
1128
+ BADGE_DOT_SIZES,
1129
+ BADGE_DOT_VARIANTS,
1130
+ ALERT_VARIANTS,
1131
+ ALERT_BASE_CLASSES,
1132
+ ALERT_ICONS,
1133
+ CLOSE_ICON,
1134
+ cn,
1135
+ };
1136
+
1137
+ // Card Component
1138
+ export function Card(props: any) {
1139
+ const {
1140
+ title,
1141
+ subtitle,
1142
+ headerActions,
1143
+ footer,
1144
+ variant = 'default',
1145
+ size = 'md',
1146
+ className,
1147
+ id,
1148
+ clickable,
1149
+ href,
1150
+ children,
1151
+ } = props;
1152
+
1153
+ const variantClasses = CARD_VARIANTS[variant] || CARD_VARIANTS.default;
1154
+ const sizeClasses = CARD_SIZES[size] || CARD_SIZES.md;
1155
+ const clickableClasses = clickable ? 'cursor-pointer hover:shadow-md transition-shadow' : '';
1156
+ const allClasses = cn(variantClasses, sizeClasses, clickableClasses, className);
1157
+
1158
+ const hasHeader = title || subtitle || headerActions;
1159
+
1160
+ const headerElement = hasHeader ? React.createElement('div', {
1161
+ className: 'flex items-start justify-between mb-4'
1162
+ }, [
1163
+ React.createElement('div', { key: 'titles' }, [
1164
+ title && React.createElement('h3', {
1165
+ key: 'title',
1166
+ className: 'text-lg font-semibold text-text-primary'
1167
+ }, title),
1168
+ subtitle && React.createElement('p', {
1169
+ key: 'subtitle',
1170
+ className: 'text-sm text-text-secondary mt-1'
1171
+ }, subtitle)
1172
+ ]),
1173
+ headerActions && React.createElement('div', {
1174
+ key: 'actions',
1175
+ className: 'flex items-center gap-2'
1176
+ }, headerActions)
1177
+ ]) : null;
1178
+
1179
+ const footerElement = footer ? React.createElement('div', {
1180
+ className: 'mt-4 pt-4 border-t border-divider'
1181
+ }, footer) : null;
1182
+
1183
+ const content = React.createElement(React.Fragment, null, headerElement, children, footerElement);
1184
+
1185
+ if (href) {
1186
+ return React.createElement('a', { href, className: allClasses, id }, content);
1187
+ }
1188
+
1189
+ return React.createElement('div', { className: allClasses, id }, content);
1190
+ }
1191
+
1192
+ // Button Component
1193
+ export function Button(props: any) {
1194
+ const {
1195
+ variant = 'primary',
1196
+ size = 'md',
1197
+ disabled = false,
1198
+ loading = false,
1199
+ fullWidth = false,
1200
+ iconPosition = 'left',
1201
+ icon,
1202
+ iconOnly = false,
1203
+ type = 'button',
1204
+ className,
1205
+ onClick,
1206
+ children,
1207
+ } = props;
1208
+
1209
+ const variantClasses = BUTTON_VARIANTS[variant] || BUTTON_VARIANTS.primary;
1210
+ const sizeClasses = iconOnly
1211
+ ? (BUTTON_ICON_SIZES[size] || BUTTON_ICON_SIZES.md)
1212
+ : (BUTTON_SIZES[size] || BUTTON_SIZES.md);
1213
+
1214
+ const disabledClasses = (disabled || loading) ? 'opacity-50 cursor-not-allowed' : '';
1215
+ const widthClasses = fullWidth ? 'w-full' : '';
1216
+
1217
+ const allClasses = cn(BUTTON_BASE_CLASSES, variantClasses, sizeClasses, disabledClasses, widthClasses, className);
1218
+
1219
+ const iconElement = icon ? React.createElement('span', {
1220
+ className: iconPosition === 'left' ? 'mr-2' : 'ml-2'
1221
+ }, icon) : null;
1222
+
1223
+ const loadingSpinner = loading ? React.createElement('span', {
1224
+ className: 'mr-2',
1225
+ dangerouslySetInnerHTML: { __html: LOADING_SPINNER }
1226
+ }) : null;
1227
+
1228
+ return React.createElement('button', {
1229
+ type,
1230
+ className: allClasses,
1231
+ disabled: disabled || loading,
1232
+ onClick
1233
+ },
1234
+ loadingSpinner,
1235
+ !loading && icon && iconPosition === 'left' ? iconElement : null,
1236
+ !iconOnly ? children : null,
1237
+ !loading && icon && iconPosition === 'right' ? iconElement : null
1238
+ );
1239
+ }
1240
+
1241
+ // Badge Component
1242
+ export function Badge(props: any) {
1243
+ const {
1244
+ variant = 'default',
1245
+ size = 'md',
1246
+ pill = false,
1247
+ icon,
1248
+ dot = false,
1249
+ className,
1250
+ removable = false,
1251
+ onRemove,
1252
+ children,
1253
+ } = props;
1254
+
1255
+ // Handle dot badge
1256
+ if (dot) {
1257
+ const dotSizeClasses = BADGE_DOT_SIZES[size] || BADGE_DOT_SIZES.md;
1258
+ const dotVariantClasses = BADGE_DOT_VARIANTS[variant] || BADGE_DOT_VARIANTS.default;
1259
+ const dotClasses = cn('inline-block rounded-full', dotSizeClasses, dotVariantClasses, className);
1260
+ const label = typeof children === 'string' ? children : undefined;
1261
+ return React.createElement('span', {
1262
+ className: dotClasses,
1263
+ 'aria-label': label,
1264
+ title: label
1265
+ });
2108
1266
  }
2109
- try {
2110
- const esbuild = await import("esbuild");
2111
- esbuildTransform = esbuild.transform;
2112
- return esbuildTransform;
2113
- } catch {
2114
- try {
2115
- const swc = await import("@swc/core");
2116
- esbuildTransform = async (source, options) => {
2117
- const opts = options;
2118
- const result = await swc.transform(source, {
2119
- jsc: {
2120
- parser: {
2121
- syntax: "typescript",
1267
+
1268
+ const variantClasses = BADGE_VARIANTS[variant] || BADGE_VARIANTS.default;
1269
+ const sizeClasses = BADGE_SIZES[size] || BADGE_SIZES.md;
1270
+
1271
+ const baseClasses = cn(
1272
+ 'inline-flex items-center font-medium',
1273
+ pill ? 'rounded-full' : 'rounded-md',
1274
+ variantClasses,
1275
+ sizeClasses,
1276
+ className
1277
+ );
1278
+
1279
+ const closeButton = removable ? React.createElement('button', {
1280
+ type: 'button',
1281
+ className: 'ml-1.5 -mr-1 hover:opacity-70 transition-opacity',
1282
+ 'aria-label': 'Remove',
1283
+ onClick: onRemove
1284
+ }, React.createElement('svg', {
1285
+ className: 'w-3 h-3',
1286
+ fill: 'none',
1287
+ stroke: 'currentColor',
1288
+ viewBox: '0 0 24 24'
1289
+ }, React.createElement('path', {
1290
+ strokeLinecap: 'round',
1291
+ strokeLinejoin: 'round',
1292
+ strokeWidth: '2',
1293
+ d: 'M6 18L18 6M6 6l12 12'
1294
+ }))) : null;
1295
+
1296
+ return React.createElement('span', { className: baseClasses },
1297
+ icon ? React.createElement('span', { className: 'mr-1' }, icon) : null,
1298
+ children,
1299
+ closeButton
1300
+ );
1301
+ }
1302
+
1303
+ // Alert Component
1304
+ export function Alert(props: any) {
1305
+ const {
1306
+ variant = 'info',
1307
+ title,
1308
+ icon,
1309
+ showIcon = true,
1310
+ dismissible = false,
1311
+ onDismiss,
1312
+ className,
1313
+ children,
1314
+ } = props;
1315
+
1316
+ const variantStyles = ALERT_VARIANTS[variant] || ALERT_VARIANTS.info;
1317
+ const allClasses = cn(ALERT_BASE_CLASSES, variantStyles.container, className);
1318
+
1319
+ const iconContent = icon || (showIcon ? React.createElement('span', {
1320
+ className: cn('flex-shrink-0', variantStyles.icon),
1321
+ dangerouslySetInnerHTML: { __html: ALERT_ICONS[variant] || ALERT_ICONS.info }
1322
+ }) : null);
1323
+
1324
+ const dismissButton = dismissible ? React.createElement('button', {
1325
+ type: 'button',
1326
+ className: 'flex-shrink-0 ml-3 hover:opacity-70 transition-opacity',
1327
+ 'aria-label': 'Dismiss',
1328
+ onClick: onDismiss
1329
+ }, React.createElement('span', {
1330
+ dangerouslySetInnerHTML: { __html: CLOSE_ICON }
1331
+ })) : null;
1332
+
1333
+ return React.createElement('div', { className: allClasses, role: 'alert' },
1334
+ React.createElement('div', { className: 'flex' },
1335
+ iconContent ? React.createElement('div', { className: 'flex-shrink-0 mr-3' }, iconContent) : null,
1336
+ React.createElement('div', { className: 'flex-1' },
1337
+ title ? React.createElement('h4', { className: 'font-semibold mb-1' }, title) : null,
1338
+ React.createElement('div', { className: 'text-sm' }, children)
1339
+ ),
1340
+ dismissButton
1341
+ )
1342
+ );
1343
+ }
1344
+ `;
1345
+ }
1346
+ function getBrowserRuntimeWrapper() {
1347
+ return `
1348
+ // Assign components to window for require() shim
1349
+ window.Card = Card;
1350
+ window.Button = Button;
1351
+ window.Badge = Badge;
1352
+ window.Alert = Alert;
1353
+
1354
+ // Build the namespace object for @frontmcp/ui/react imports
1355
+ window.frontmcp_ui_namespaceObject = Object.assign({}, window.React || {}, {
1356
+ // Hooks
1357
+ useToolOutput: window.useToolOutput,
1358
+ useToolInput: window.useToolInput,
1359
+ useMcpBridgeContext: function() { return window.__frontmcp.context; },
1360
+ useMcpBridge: function() { return window.__frontmcp.context; },
1361
+ useCallTool: function() {
1362
+ return function(name, args) {
1363
+ if (window.__frontmcp.context && window.__frontmcp.context.callTool) {
1364
+ return window.__frontmcp.context.callTool(name, args);
1365
+ }
1366
+ console.warn('[FrontMCP] callTool not available');
1367
+ return Promise.resolve(null);
1368
+ };
1369
+ },
1370
+ useTheme: function() { return window.__frontmcp.theme || 'light'; },
1371
+ useDisplayMode: function() { return window.__frontmcp.displayMode || 'embedded'; },
1372
+ useHostContext: function() { return window.__frontmcp.hostContext || {}; },
1373
+ useCapability: function(cap) { return window.__frontmcp.capabilities && window.__frontmcp.capabilities[cap] || false; },
1374
+ useStructuredContent: function() { return window.__frontmcp.getState().structuredContent; },
1375
+ useToolCalls: function() { return []; },
1376
+ useSendMessage: function() { return function() { return Promise.resolve(); }; },
1377
+ useOpenLink: function() { return function() {}; },
1378
+
1379
+ // Components
1380
+ Card: window.Card,
1381
+ Badge: window.Badge,
1382
+ Button: window.Button,
1383
+ Alert: window.Alert,
1384
+
1385
+ // Re-export React for convenience
1386
+ createElement: React.createElement,
1387
+ Fragment: React.Fragment,
1388
+ useState: React.useState,
1389
+ useEffect: React.useEffect,
1390
+ useCallback: React.useCallback,
1391
+ useMemo: React.useMemo,
1392
+ useRef: React.useRef,
1393
+ useContext: React.useContext
1394
+ });
1395
+ `;
1396
+ }
1397
+ async function buildWithEsbuild() {
1398
+ try {
1399
+ const esbuild = await import("esbuild");
1400
+ const stylesPath = require.resolve("@frontmcp/uipack/styles");
1401
+ const entrySource = getComponentsEntrySource();
1402
+ const result = await esbuild.build({
1403
+ stdin: {
1404
+ contents: entrySource,
1405
+ loader: "tsx",
1406
+ resolveDir: path.dirname(stylesPath)
1407
+ },
1408
+ bundle: true,
1409
+ format: "iife",
1410
+ globalName: "__frontmcp_components",
1411
+ target: "es2020",
1412
+ minify: false,
1413
+ write: false,
1414
+ external: ["react", "react-dom"],
1415
+ define: {
1416
+ React: "window.React"
1417
+ },
1418
+ platform: "browser"
1419
+ });
1420
+ if (result.outputFiles && result.outputFiles.length > 0) {
1421
+ let code = result.outputFiles[0].text;
1422
+ code += "\n" + getBrowserRuntimeWrapper();
1423
+ return code;
1424
+ }
1425
+ throw new Error("No output from esbuild");
1426
+ } catch (error) {
1427
+ console.warn(
1428
+ `[FrontMCP] esbuild bundle failed, falling back to manual components: ${error instanceof Error ? error.message : String(error)}`
1429
+ );
1430
+ throw error;
1431
+ }
1432
+ }
1433
+ async function getBrowserComponents() {
1434
+ if (cachedBrowserComponents !== null) {
1435
+ return cachedBrowserComponents;
1436
+ }
1437
+ if (buildingPromise !== null) {
1438
+ return buildingPromise;
1439
+ }
1440
+ buildingPromise = buildWithEsbuild().then((code) => {
1441
+ cachedBrowserComponents = code;
1442
+ buildingPromise = null;
1443
+ return code;
1444
+ }).catch((error) => {
1445
+ buildingPromise = null;
1446
+ throw error;
1447
+ });
1448
+ return buildingPromise;
1449
+ }
1450
+
1451
+ // libs/ui/src/bundler/bundler.ts
1452
+ var import_bundler2 = require("@frontmcp/uipack/bundler");
1453
+ var esbuildTransform = null;
1454
+ async function loadEsbuild() {
1455
+ if (esbuildTransform !== null) {
1456
+ return esbuildTransform;
1457
+ }
1458
+ try {
1459
+ const esbuild = await import("esbuild");
1460
+ esbuildTransform = esbuild.transform;
1461
+ return esbuildTransform;
1462
+ } catch {
1463
+ try {
1464
+ const swc = await import("@swc/core");
1465
+ esbuildTransform = async (source, options) => {
1466
+ const opts = options;
1467
+ const result = await swc.transform(source, {
1468
+ jsc: {
1469
+ parser: {
1470
+ syntax: "typescript",
2122
1471
  tsx: opts.loader === "tsx" || opts.loader === "jsx"
2123
1472
  },
2124
1473
  transform: {
@@ -2169,11 +1518,11 @@ var InMemoryBundler = class {
2169
1518
  ...options.cache
2170
1519
  }
2171
1520
  };
2172
- this.cache = new BundlerCache({
1521
+ this.cache = new import_bundler.BundlerCache({
2173
1522
  maxSize: this.options.cache.maxSize,
2174
1523
  ttl: this.options.cache.ttl
2175
1524
  });
2176
- this.defaultSecurity = mergePolicy(options.defaultSecurity);
1525
+ this.defaultSecurity = (0, import_bundler.mergePolicy)(options.defaultSecurity);
2177
1526
  }
2178
1527
  /**
2179
1528
  * Bundle source code.
@@ -2185,7 +1534,7 @@ var InMemoryBundler = class {
2185
1534
  const startTime = performance.now();
2186
1535
  const opts = this.mergeOptions(options);
2187
1536
  if (!opts.skipCache && !this.options.cache.disabled) {
2188
- const cacheKey = options.cacheKey ?? createCacheKey(options.source, opts);
1537
+ const cacheKey = options.cacheKey ?? (0, import_bundler.createCacheKey)(options.source, opts);
2189
1538
  const cached = this.cache.get(cacheKey);
2190
1539
  if (cached) {
2191
1540
  return {
@@ -2198,18 +1547,18 @@ var InMemoryBundler = class {
2198
1547
  };
2199
1548
  }
2200
1549
  }
2201
- const security = mergePolicy(options.security ?? this.defaultSecurity);
2202
- const violations = validateSource(options.source, security);
2203
- throwOnViolations(violations);
1550
+ const security = (0, import_bundler.mergePolicy)(options.security ?? this.defaultSecurity);
1551
+ const violations = (0, import_bundler.validateSource)(options.source, security);
1552
+ (0, import_bundler.throwOnViolations)(violations);
2204
1553
  const sourceType = opts.sourceType === "auto" ? this.detectSourceType(options.source) : opts.sourceType;
2205
1554
  const transformStart = performance.now();
2206
1555
  const transformed = await this.transform(options.source, sourceType, opts);
2207
1556
  const transformTime = performance.now() - transformStart;
2208
- const sizeViolation = validateSize(transformed.code.length, security);
1557
+ const sizeViolation = (0, import_bundler.validateSize)(transformed.code.length, security);
2209
1558
  if (sizeViolation) {
2210
- throwOnViolations([sizeViolation]);
1559
+ (0, import_bundler.throwOnViolations)([sizeViolation]);
2211
1560
  }
2212
- const hash = hashContent(transformed.code);
1561
+ const hash = (0, import_bundler.hashContent)(transformed.code);
2213
1562
  const result = {
2214
1563
  code: transformed.code,
2215
1564
  hash,
@@ -2226,7 +1575,7 @@ var InMemoryBundler = class {
2226
1575
  format: opts.format
2227
1576
  };
2228
1577
  if (!this.options.cache.disabled) {
2229
- const cacheKey = options.cacheKey ?? createCacheKey(options.source, opts);
1578
+ const cacheKey = options.cacheKey ?? (0, import_bundler.createCacheKey)(options.source, opts);
2230
1579
  this.cache.set(cacheKey, result);
2231
1580
  }
2232
1581
  return result;
@@ -2253,16 +1602,16 @@ var InMemoryBundler = class {
2253
1602
  throw new Error("React and react-dom/server are required for SSR. Install them: npm install react react-dom");
2254
1603
  }
2255
1604
  const renderStart = performance.now();
2256
- const Component = await executeDefault(bundleResult.code, {
1605
+ const Component = await (0, import_bundler.executeDefault)(bundleResult.code, {
2257
1606
  React,
2258
- security: mergePolicy(options.security ?? this.defaultSecurity)
1607
+ security: (0, import_bundler.mergePolicy)(options.security ?? this.defaultSecurity)
2259
1608
  });
2260
1609
  let html;
2261
1610
  try {
2262
1611
  const element = React.createElement(Component, options.context ?? {});
2263
1612
  html = ReactDOMServer.renderToString(element);
2264
1613
  } catch (error) {
2265
- throw new ExecutionError(
1614
+ throw new import_bundler.ExecutionError(
2266
1615
  `SSR rendering failed: ${error instanceof Error ? error.message : String(error)}`,
2267
1616
  error
2268
1617
  );
@@ -2303,10 +1652,10 @@ var InMemoryBundler = class {
2303
1652
  React = await import("react");
2304
1653
  } catch {
2305
1654
  }
2306
- return executeDefault(result.code, {
1655
+ return (0, import_bundler.executeDefault)(result.code, {
2307
1656
  React,
2308
1657
  globals: context,
2309
- security: mergePolicy(options.security ?? this.defaultSecurity)
1658
+ security: (0, import_bundler.mergePolicy)(options.security ?? this.defaultSecurity)
2310
1659
  });
2311
1660
  }
2312
1661
  /**
@@ -2357,10 +1706,19 @@ var InMemoryBundler = class {
2357
1706
  security: opts.security,
2358
1707
  skipCache: opts.skipCache
2359
1708
  });
2360
- const head = this.buildStaticHTMLHead({ externals: opts.externals, customCss: opts.customCss });
1709
+ const head = this.buildStaticHTMLHead({ externals: opts.externals, customCss: opts.customCss, theme: opts.theme });
2361
1710
  const reactRuntime = this.buildReactRuntimeScripts(opts.externals, platform, cdnType);
2362
- const frontmcpRuntime = this.buildFrontMCPRuntime();
2363
- const dataScript = this.buildDataInjectionScript(opts.toolName, opts.input, opts.output, opts.structuredContent);
1711
+ const frontmcpRuntime = await this.buildFrontMCPRuntime();
1712
+ const dataScript = this.buildDataInjectionScript(
1713
+ opts.toolName,
1714
+ opts.input,
1715
+ opts.output,
1716
+ opts.structuredContent,
1717
+ opts.buildMode,
1718
+ cdnType,
1719
+ opts.dynamicOptions,
1720
+ opts.hybridOptions
1721
+ );
2364
1722
  const componentScript = this.buildComponentRenderScript(bundleResult.code, opts.rootId, cdnType);
2365
1723
  const html = this.assembleStaticHTML({
2366
1724
  title: opts.title || `${opts.toolName} - Widget`,
@@ -2372,7 +1730,9 @@ var InMemoryBundler = class {
2372
1730
  rootId: opts.rootId,
2373
1731
  cdnType
2374
1732
  });
2375
- const hash = hashContent(html);
1733
+ const hash = (0, import_bundler.hashContent)(html);
1734
+ const dataPlaceholder = opts.buildMode === "hybrid" ? opts.hybridOptions?.placeholder ?? HYBRID_DATA_PLACEHOLDER : void 0;
1735
+ const inputPlaceholder = opts.buildMode === "hybrid" ? opts.hybridOptions?.inputPlaceholder ?? HYBRID_INPUT_PLACEHOLDER : void 0;
2376
1736
  return {
2377
1737
  html,
2378
1738
  componentCode: bundleResult.code,
@@ -2384,9 +1744,240 @@ var InMemoryBundler = class {
2384
1744
  size: html.length,
2385
1745
  cached: bundleResult.cached,
2386
1746
  sourceType: bundleResult.sourceType,
2387
- targetPlatform: platform
1747
+ targetPlatform: platform,
1748
+ buildMode: opts.buildMode,
1749
+ dataPlaceholder,
1750
+ inputPlaceholder
1751
+ };
1752
+ }
1753
+ /**
1754
+ * Bundle a component to static HTML for all target platforms at once.
1755
+ *
1756
+ * This method is optimized for efficiency:
1757
+ * - Transpiles the component source code only once
1758
+ * - Generates platform-specific HTML variations from the shared transpiled code
1759
+ * - Returns complete platform metadata ready for MCP responses
1760
+ *
1761
+ * @param options - Multi-platform build options
1762
+ * @returns Multi-platform build result with all platforms
1763
+ *
1764
+ * @example
1765
+ * ```typescript
1766
+ * const result = await bundler.bundleToStaticHTMLAll({
1767
+ * source: `
1768
+ * import { Card, useToolOutput } from '@frontmcp/ui/react';
1769
+ * export default function Weather() {
1770
+ * const output = useToolOutput();
1771
+ * return <Card title="Weather">{output?.temperature}°F</Card>;
1772
+ * }
1773
+ * `,
1774
+ * toolName: 'get_weather',
1775
+ * output: { temperature: 72 },
1776
+ * });
1777
+ *
1778
+ * // Access platform-specific results
1779
+ * const openaiHtml = result.platforms.openai.html;
1780
+ * const claudeHtml = result.platforms.claude.html;
1781
+ *
1782
+ * // Get metadata for MCP response
1783
+ * const openaiMeta = result.platforms.openai.meta;
1784
+ * ```
1785
+ */
1786
+ async bundleToStaticHTMLAll(options) {
1787
+ const startTime = performance.now();
1788
+ const opts = this.mergeStaticHTMLOptions(options);
1789
+ const platforms = options.platforms ?? [...ALL_PLATFORMS];
1790
+ const transpileStart = performance.now();
1791
+ let transpiledCode = null;
1792
+ let bundleResult = null;
1793
+ const isUniversal = opts.universal;
1794
+ const rawContentType = options.contentType ?? "auto";
1795
+ const contentType = isUniversal ? rawContentType === "auto" ? detectContentType(options.source) : rawContentType : "react";
1796
+ if (contentType === "react" || !isUniversal) {
1797
+ bundleResult = await this.bundle({
1798
+ source: options.source,
1799
+ sourceType: opts.sourceType,
1800
+ format: "cjs",
1801
+ minify: opts.minify,
1802
+ sourceMaps: false,
1803
+ externals: ["react", "react-dom", "react/jsx-runtime", "@frontmcp/ui", "@frontmcp/ui/react"],
1804
+ security: opts.security,
1805
+ skipCache: opts.skipCache
1806
+ });
1807
+ transpiledCode = bundleResult.code;
1808
+ }
1809
+ const transpileTime = performance.now() - transpileStart;
1810
+ const generationStart = performance.now();
1811
+ const platformResults = {};
1812
+ for (const platform of platforms) {
1813
+ const platformResult = await this.buildForPlatform({
1814
+ options,
1815
+ opts,
1816
+ platform,
1817
+ transpiledCode,
1818
+ bundleResult,
1819
+ contentType,
1820
+ isUniversal
1821
+ });
1822
+ platformResults[platform] = platformResult;
1823
+ }
1824
+ const generationTime = performance.now() - generationStart;
1825
+ return {
1826
+ platforms: platformResults,
1827
+ sharedComponentCode: transpiledCode ?? "",
1828
+ metrics: {
1829
+ transpileTime,
1830
+ generationTime,
1831
+ totalTime: performance.now() - startTime
1832
+ },
1833
+ cached: bundleResult?.cached ?? false
1834
+ };
1835
+ }
1836
+ /**
1837
+ * Build for a specific platform with pre-transpiled code.
1838
+ * Internal helper for bundleToStaticHTMLAll.
1839
+ */
1840
+ async buildForPlatform(params) {
1841
+ const { options, opts, platform, transpiledCode, bundleResult, contentType, isUniversal } = params;
1842
+ const cdnType = getCdnTypeForPlatform(platform);
1843
+ const buildStart = performance.now();
1844
+ let html;
1845
+ let componentCode;
1846
+ if (isUniversal) {
1847
+ const shouldIncludeBridge = opts.buildMode === "dynamic" || opts.buildMode === "hybrid";
1848
+ const cachedRuntime = getCachedRuntime({
1849
+ cdnType,
1850
+ includeMarkdown: opts.includeMarkdown || contentType === "markdown",
1851
+ includeMdx: opts.includeMdx || contentType === "mdx",
1852
+ minify: opts.minify,
1853
+ includeBridge: shouldIncludeBridge
1854
+ });
1855
+ const componentCodeStr = transpiledCode ? buildComponentCode(transpiledCode) : "";
1856
+ const dataInjectionStr = buildDataInjectionCode(
1857
+ opts.toolName,
1858
+ opts.input,
1859
+ opts.output,
1860
+ opts.structuredContent,
1861
+ contentType,
1862
+ transpiledCode ? null : options.source,
1863
+ transpiledCode !== null,
1864
+ {
1865
+ buildMode: opts.buildMode,
1866
+ cdnType,
1867
+ dynamicOptions: opts.dynamicOptions,
1868
+ hybridOptions: opts.hybridOptions
1869
+ }
1870
+ );
1871
+ const appScript = buildAppScript(
1872
+ cachedRuntime.appTemplate,
1873
+ componentCodeStr,
1874
+ dataInjectionStr,
1875
+ opts.customComponents ?? ""
1876
+ );
1877
+ const head = this.buildStaticHTMLHead({
1878
+ externals: opts.externals,
1879
+ customCss: opts.customCss,
1880
+ theme: opts.theme
1881
+ });
1882
+ const reactRuntime = this.buildReactRuntimeScripts(opts.externals, platform, cdnType);
1883
+ const renderScript = this.buildUniversalRenderScript(opts.rootId, cdnType);
1884
+ html = this.assembleUniversalStaticHTMLCached({
1885
+ title: opts.title || `${opts.toolName} - Widget`,
1886
+ head,
1887
+ reactRuntime,
1888
+ cdnImports: cachedRuntime.cdnImports,
1889
+ vendorScript: cachedRuntime.vendorScript,
1890
+ appScript,
1891
+ renderScript,
1892
+ rootId: opts.rootId,
1893
+ cdnType
1894
+ });
1895
+ componentCode = transpiledCode ?? appScript;
1896
+ } else {
1897
+ if (!transpiledCode) {
1898
+ throw new Error("Failed to transpile component source");
1899
+ }
1900
+ const head = this.buildStaticHTMLHead({
1901
+ externals: opts.externals,
1902
+ customCss: opts.customCss,
1903
+ theme: opts.theme
1904
+ });
1905
+ const reactRuntime = this.buildReactRuntimeScripts(opts.externals, platform, cdnType);
1906
+ const frontmcpRuntime = await this.buildFrontMCPRuntime();
1907
+ const dataScript = this.buildDataInjectionScript(
1908
+ opts.toolName,
1909
+ opts.input,
1910
+ opts.output,
1911
+ opts.structuredContent,
1912
+ opts.buildMode,
1913
+ cdnType,
1914
+ opts.dynamicOptions,
1915
+ opts.hybridOptions
1916
+ );
1917
+ const componentScript = this.buildComponentRenderScript(transpiledCode, opts.rootId, cdnType);
1918
+ html = this.assembleStaticHTML({
1919
+ title: opts.title || `${opts.toolName} - Widget`,
1920
+ head,
1921
+ reactRuntime,
1922
+ frontmcpRuntime,
1923
+ dataScript,
1924
+ componentScript,
1925
+ rootId: opts.rootId,
1926
+ cdnType
1927
+ });
1928
+ componentCode = transpiledCode;
1929
+ }
1930
+ const hash = (0, import_bundler.hashContent)(html);
1931
+ const meta = (0, import_adapters.buildUIMeta)({
1932
+ uiConfig: {
1933
+ template: () => html,
1934
+ widgetAccessible: opts.widgetAccessible
1935
+ },
1936
+ platformType: this.mapTargetPlatformToAIPlatform(platform),
1937
+ html
1938
+ });
1939
+ const dataPlaceholder = opts.buildMode === "hybrid" ? opts.hybridOptions?.placeholder ?? HYBRID_DATA_PLACEHOLDER : void 0;
1940
+ const inputPlaceholder = opts.buildMode === "hybrid" ? opts.hybridOptions?.inputPlaceholder ?? HYBRID_INPUT_PLACEHOLDER : void 0;
1941
+ return {
1942
+ html,
1943
+ componentCode,
1944
+ metrics: bundleResult?.metrics ?? {
1945
+ transformTime: 0,
1946
+ bundleTime: 0,
1947
+ totalTime: performance.now() - buildStart
1948
+ },
1949
+ hash,
1950
+ size: html.length,
1951
+ cached: bundleResult?.cached ?? false,
1952
+ sourceType: bundleResult?.sourceType ?? opts.sourceType,
1953
+ targetPlatform: platform,
1954
+ universal: isUniversal,
1955
+ contentType: isUniversal ? contentType : void 0,
1956
+ buildMode: opts.buildMode,
1957
+ dataPlaceholder,
1958
+ inputPlaceholder,
1959
+ meta
2388
1960
  };
2389
1961
  }
1962
+ /**
1963
+ * Map TargetPlatform to AIPlatformType for metadata generation.
1964
+ */
1965
+ mapTargetPlatformToAIPlatform(platform) {
1966
+ switch (platform) {
1967
+ case "openai":
1968
+ return "openai";
1969
+ case "claude":
1970
+ return "claude";
1971
+ case "cursor":
1972
+ return "cursor";
1973
+ case "ext-apps":
1974
+ return "ext-apps";
1975
+ case "generic":
1976
+ return "generic-mcp";
1977
+ default:
1978
+ return "generic-mcp";
1979
+ }
1980
+ }
2390
1981
  /**
2391
1982
  * Bundle to static HTML with universal rendering mode.
2392
1983
  * Uses the universal renderer that can handle multiple content types.
@@ -2418,11 +2009,13 @@ var InMemoryBundler = class {
2418
2009
  transpiledCode = bundleResult.code;
2419
2010
  transformTime = bundleResult.metrics.transformTime;
2420
2011
  }
2012
+ const shouldIncludeBridge = opts.buildMode === "dynamic" || opts.buildMode === "hybrid";
2421
2013
  const cachedRuntime = getCachedRuntime({
2422
2014
  cdnType,
2423
2015
  includeMarkdown: opts.includeMarkdown || contentType === "markdown",
2424
2016
  includeMdx: opts.includeMdx || contentType === "mdx",
2425
- minify: opts.minify
2017
+ minify: opts.minify,
2018
+ includeBridge: shouldIncludeBridge
2426
2019
  });
2427
2020
  const componentCodeStr = transpiledCode ? buildComponentCode(transpiledCode) : "";
2428
2021
  const dataInjectionStr = buildDataInjectionCode(
@@ -2433,7 +2026,13 @@ var InMemoryBundler = class {
2433
2026
  contentType,
2434
2027
  transpiledCode ? null : options.source,
2435
2028
  // Pass source only if not a component
2436
- transpiledCode !== null
2029
+ transpiledCode !== null,
2030
+ {
2031
+ buildMode: opts.buildMode,
2032
+ cdnType,
2033
+ dynamicOptions: opts.dynamicOptions,
2034
+ hybridOptions: opts.hybridOptions
2035
+ }
2437
2036
  );
2438
2037
  const appScript = buildAppScript(
2439
2038
  cachedRuntime.appTemplate,
@@ -2441,7 +2040,7 @@ var InMemoryBundler = class {
2441
2040
  dataInjectionStr,
2442
2041
  opts.customComponents ?? ""
2443
2042
  );
2444
- const head = this.buildStaticHTMLHead({ externals: opts.externals, customCss: opts.customCss });
2043
+ const head = this.buildStaticHTMLHead({ externals: opts.externals, customCss: opts.customCss, theme: opts.theme });
2445
2044
  const reactRuntime = this.buildReactRuntimeScripts(opts.externals, platform, cdnType);
2446
2045
  const renderScript = this.buildUniversalRenderScript(opts.rootId, cdnType);
2447
2046
  const html = this.assembleUniversalStaticHTMLCached({
@@ -2455,7 +2054,7 @@ var InMemoryBundler = class {
2455
2054
  rootId: opts.rootId,
2456
2055
  cdnType
2457
2056
  });
2458
- const hash = hashContent(html);
2057
+ const hash = (0, import_bundler.hashContent)(html);
2459
2058
  return {
2460
2059
  html,
2461
2060
  componentCode: transpiledCode ?? appScript,
@@ -2485,7 +2084,7 @@ var InMemoryBundler = class {
2485
2084
  return `<!DOCTYPE html>
2486
2085
  <html lang="en">
2487
2086
  <head>
2488
- <title>${escapeHtml(parts.title)}</title>
2087
+ <title>${(0, import_utils.escapeHtml)(parts.title)}</title>
2489
2088
  ${parts.head}
2490
2089
  ${parts.reactRuntime}
2491
2090
  ${parts.cdnImports}
@@ -2509,7 +2108,7 @@ ${parts.appScript}
2509
2108
  return `<!DOCTYPE html>
2510
2109
  <html lang="en">
2511
2110
  <head>
2512
- <title>${escapeHtml(parts.title)}</title>
2111
+ <title>${(0, import_utils.escapeHtml)(parts.title)}</title>
2513
2112
  ${parts.head}
2514
2113
  ${parts.reactRuntime}
2515
2114
  ${parts.cdnImports}
@@ -2691,7 +2290,7 @@ ${parts.appScript}
2691
2290
  return `<!DOCTYPE html>
2692
2291
  <html lang="en">
2693
2292
  <head>
2694
- <title>${escapeHtml(parts.title)}</title>
2293
+ <title>${(0, import_utils.escapeHtml)(parts.title)}</title>
2695
2294
  ${parts.head}
2696
2295
  ${parts.reactRuntime}
2697
2296
  ${parts.frontmcpRuntime ?? ""}
@@ -2870,6 +2469,10 @@ ${parts.appScript}
2870
2469
  contentType: options.contentType ?? DEFAULT_STATIC_HTML_OPTIONS.contentType,
2871
2470
  includeMarkdown: options.includeMarkdown ?? DEFAULT_STATIC_HTML_OPTIONS.includeMarkdown,
2872
2471
  includeMdx: options.includeMdx ?? DEFAULT_STATIC_HTML_OPTIONS.includeMdx,
2472
+ // Build mode options
2473
+ buildMode: options.buildMode ?? DEFAULT_STATIC_HTML_OPTIONS.buildMode,
2474
+ dynamicOptions: options.dynamicOptions,
2475
+ hybridOptions: options.hybridOptions,
2873
2476
  // Pass-through options
2874
2477
  toolName: options.toolName,
2875
2478
  input: options.input,
@@ -2878,7 +2481,8 @@ ${parts.appScript}
2878
2481
  title: options.title,
2879
2482
  security: options.security,
2880
2483
  customCss: options.customCss,
2881
- customComponents: options.customComponents
2484
+ customComponents: options.customComponents,
2485
+ theme: options.theme
2882
2486
  };
2883
2487
  }
2884
2488
  /**
@@ -2892,12 +2496,8 @@ ${parts.appScript}
2892
2496
  parts.push(`<link rel="preconnect" href="${url}" crossorigin>`);
2893
2497
  }
2894
2498
  parts.push(`<link rel="stylesheet" href="${STATIC_HTML_CDN.fonts.inter}">`);
2895
- const tailwindConfig = opts.externals.tailwind ?? "cdn";
2896
- if (tailwindConfig === "cdn") {
2897
- parts.push(`<link rel="stylesheet" href="${STATIC_HTML_CDN.tailwind}">`);
2898
- } else if (tailwindConfig !== "inline" && tailwindConfig) {
2899
- parts.push(`<link rel="stylesheet" href="${tailwindConfig}">`);
2900
- }
2499
+ parts.push((0, import_build2.buildCDNScriptTag)(import_build2.CLOUDFLARE_CDN.tailwindCss));
2500
+ parts.push(this.buildThemeStyleBlock(opts.theme));
2901
2501
  parts.push(`<style>
2902
2502
  body { margin: 0; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
2903
2503
  .frontmcp-loading { display: flex; align-items: center; justify-content: center; min-height: 200px; }
@@ -2911,6 +2511,18 @@ ${sanitizeCss(opts.customCss)}
2911
2511
  }
2912
2512
  return parts.join("\n ");
2913
2513
  }
2514
+ /**
2515
+ * Build theme CSS variables as a :root style block.
2516
+ * Uses DEFAULT_THEME if no theme is provided.
2517
+ */
2518
+ buildThemeStyleBlock(theme = import_theme.DEFAULT_THEME) {
2519
+ const cssVars = (0, import_theme.buildThemeCss)(theme);
2520
+ return `<style>
2521
+ :root {
2522
+ ${cssVars}
2523
+ }
2524
+ </style>`;
2525
+ }
2914
2526
  /**
2915
2527
  * Build React runtime scripts for static HTML.
2916
2528
  */
@@ -2975,9 +2587,17 @@ ${sanitizeCss(opts.customCss)}
2975
2587
  }
2976
2588
  /**
2977
2589
  * Build FrontMCP runtime (hooks and UI components).
2590
+ * Uses esbuild to transpile real React components at first use, then caches.
2591
+ * Falls back to manual implementation if esbuild fails.
2978
2592
  * Always inlined for reliability across platforms.
2979
2593
  */
2980
- buildFrontMCPRuntime() {
2594
+ async buildFrontMCPRuntime() {
2595
+ let uiComponents;
2596
+ try {
2597
+ uiComponents = await getBrowserComponents();
2598
+ } catch {
2599
+ uiComponents = (0, import_build2.buildUIComponentsRuntime)();
2600
+ }
2981
2601
  return `
2982
2602
  <!-- FrontMCP Runtime (always inline) -->
2983
2603
  <script>
@@ -2997,8 +2617,8 @@ ${sanitizeCss(opts.customCss)}
2997
2617
  'react-dom/client': function() { return window.ReactDOM; },
2998
2618
  'react/jsx-runtime': function() { return window.jsx_runtime_namespaceObject; },
2999
2619
  'react/jsx-dev-runtime': function() { return window.jsx_runtime_namespaceObject; },
3000
- '@frontmcp/ui': function() { return window.react_namespaceObject; },
3001
- '@frontmcp/ui/react': function() { return window.react_namespaceObject; },
2620
+ '@frontmcp/ui': function() { return window.frontmcp_ui_namespaceObject; },
2621
+ '@frontmcp/ui/react': function() { return window.frontmcp_ui_namespaceObject; },
3002
2622
  };
3003
2623
 
3004
2624
  var resolver = moduleMap[moduleName];
@@ -3029,7 +2649,7 @@ ${sanitizeCss(opts.customCss)}
3029
2649
  });
3030
2650
  };
3031
2651
 
3032
- // FrontMCP Hook implementations
2652
+ // FrontMCP Hook implementations and state
3033
2653
  window.__frontmcp = {
3034
2654
  // Context for MCP bridge
3035
2655
  context: {
@@ -3040,10 +2660,35 @@ ${sanitizeCss(opts.customCss)}
3040
2660
  callTool: null,
3041
2661
  },
3042
2662
 
2663
+ // Theme and display settings
2664
+ theme: 'light',
2665
+ displayMode: 'embedded',
2666
+ hostContext: {},
2667
+ capabilities: {},
2668
+
3043
2669
  // Set context from data injection
3044
2670
  setContext: function(ctx) {
3045
2671
  Object.assign(this.context, ctx);
3046
2672
  },
2673
+
2674
+ // State management (for universal mode compatibility)
2675
+ getState: function() {
2676
+ return {
2677
+ toolName: this.context.toolName,
2678
+ input: this.context.toolInput,
2679
+ output: this.context.toolOutput,
2680
+ structuredContent: this.context.structuredContent,
2681
+ loading: false,
2682
+ error: null
2683
+ };
2684
+ },
2685
+
2686
+ setState: function(partial) {
2687
+ if (partial.toolName !== undefined) this.context.toolName = partial.toolName;
2688
+ if (partial.input !== undefined) this.context.toolInput = partial.input;
2689
+ if (partial.output !== undefined) this.context.toolOutput = partial.output;
2690
+ if (partial.structuredContent !== undefined) this.context.structuredContent = partial.structuredContent;
2691
+ }
3047
2692
  };
3048
2693
 
3049
2694
  // Hook: useToolOutput - returns the tool output data
@@ -3071,74 +2716,31 @@ ${sanitizeCss(opts.customCss)}
3071
2716
  return Promise.resolve(null);
3072
2717
  };
3073
2718
  };
3074
-
3075
- // UI Components (simplified inline versions)
3076
- window.Card = function(props) {
3077
- var children = props.children;
3078
- var title = props.title;
3079
- var className = props.className || '';
3080
- return React.createElement('div', {
3081
- className: 'bg-white rounded-lg shadow border border-gray-200 overflow-hidden ' + className
3082
- }, [
3083
- title && React.createElement('div', {
3084
- key: 'header',
3085
- className: 'px-4 py-3 border-b border-gray-200 bg-gray-50'
3086
- }, React.createElement('h3', { className: 'text-sm font-medium text-gray-900' }, title)),
3087
- React.createElement('div', { key: 'body', className: 'p-4' }, children)
3088
- ]);
3089
- };
3090
-
3091
- window.Badge = function(props) {
3092
- var children = props.children;
3093
- var variant = props.variant || 'default';
3094
- var variantClasses = {
3095
- default: 'bg-gray-100 text-gray-800',
3096
- success: 'bg-green-100 text-green-800',
3097
- warning: 'bg-yellow-100 text-yellow-800',
3098
- error: 'bg-red-100 text-red-800',
3099
- info: 'bg-blue-100 text-blue-800',
3100
- };
3101
- return React.createElement('span', {
3102
- className: 'inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ' + (variantClasses[variant] || variantClasses.default)
3103
- }, children);
3104
- };
3105
-
3106
- window.Button = function(props) {
3107
- var children = props.children;
3108
- var variant = props.variant || 'primary';
3109
- var onClick = props.onClick;
3110
- var disabled = props.disabled;
3111
- var variantClasses = {
3112
- primary: 'bg-blue-600 text-white hover:bg-blue-700',
3113
- secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200',
3114
- outline: 'border border-gray-300 text-gray-700 hover:bg-gray-50',
3115
- danger: 'bg-red-600 text-white hover:bg-red-700',
3116
- };
3117
- return React.createElement('button', {
3118
- className: 'px-4 py-2 rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ' +
3119
- (disabled ? 'opacity-50 cursor-not-allowed ' : '') +
3120
- (variantClasses[variant] || variantClasses.primary),
3121
- onClick: onClick,
3122
- disabled: disabled,
3123
- }, children);
3124
- };
3125
-
3126
- // Make hooks available on react_namespaceObject for bundled imports
3127
- window.react_namespaceObject = Object.assign({}, window.React || {}, {
3128
- useToolOutput: window.useToolOutput,
3129
- useToolInput: window.useToolInput,
3130
- useMcpBridgeContext: window.useMcpBridgeContext,
3131
- useCallTool: window.useCallTool,
3132
- Card: window.Card,
3133
- Badge: window.Badge,
3134
- Button: window.Button,
3135
- });
2719
+ </script>
2720
+ <!-- UI Components (Full-Featured, Browser-Compatible) -->
2721
+ <script>
2722
+ ${uiComponents}
3136
2723
  </script>`;
3137
2724
  }
3138
2725
  /**
3139
2726
  * Build data injection script for tool input/output.
2727
+ * Dispatches to mode-specific builders based on buildMode.
2728
+ */
2729
+ buildDataInjectionScript(toolName, input, output, structuredContent, buildMode = "static", cdnType = "esm", dynamicOptions, hybridOptions) {
2730
+ switch (buildMode) {
2731
+ case "dynamic":
2732
+ return this.buildDynamicDataScript(toolName, input, output, structuredContent, cdnType, dynamicOptions);
2733
+ case "hybrid":
2734
+ return this.buildHybridDataScript(toolName, input, structuredContent, hybridOptions);
2735
+ case "static":
2736
+ default:
2737
+ return this.buildStaticDataScript(toolName, input, output, structuredContent);
2738
+ }
2739
+ }
2740
+ /**
2741
+ * Build static data injection - data baked in at build time (current default).
3140
2742
  */
3141
- buildDataInjectionScript(toolName, input, output, structuredContent) {
2743
+ buildStaticDataScript(toolName, input, output, structuredContent) {
3142
2744
  const safeJson = (value) => {
3143
2745
  try {
3144
2746
  return JSON.stringify(value);
@@ -3147,7 +2749,7 @@ ${sanitizeCss(opts.customCss)}
3147
2749
  }
3148
2750
  };
3149
2751
  return `
3150
- <!-- Tool Data Injection -->
2752
+ <!-- Tool Data Injection (Static Mode) -->
3151
2753
  <script>
3152
2754
  window.__mcpToolName = ${safeJson(toolName)};
3153
2755
  window.__mcpToolInput = ${safeJson(input ?? null)};
@@ -3164,1555 +2766,365 @@ ${sanitizeCss(opts.customCss)}
3164
2766
  </script>`;
3165
2767
  }
3166
2768
  /**
3167
- * Build component render script.
3168
- * Wraps CommonJS code with module/exports shim to capture the component.
2769
+ * Build dynamic data injection - platform-aware.
2770
+ * For OpenAI (ESM): subscribes to platform events for updates.
2771
+ * For non-OpenAI (UMD/Claude): uses placeholders for data injection.
3169
2772
  */
3170
- buildComponentRenderScript(componentCode, rootId, cdnType) {
3171
- const wrappedCode = `
3172
- // CommonJS module shim
3173
- var module = { exports: {} };
3174
- var exports = module.exports;
3175
-
3176
- // Execute transpiled component code (CommonJS format)
3177
- ${componentCode}
3178
-
3179
- // Capture the component export
3180
- window.__frontmcp_component = module.exports;
3181
- `;
2773
+ buildDynamicDataScript(toolName, input, output, structuredContent, cdnType = "esm", options) {
3182
2774
  if (cdnType === "umd") {
3183
- return `
3184
- <!-- Component Render Script (UMD - synchronous) -->
2775
+ return this.buildDynamicWithPlaceholdersScript(toolName, structuredContent, options);
2776
+ }
2777
+ return this.buildDynamicWithSubscriptionScript(toolName, input, output, structuredContent, options);
2778
+ }
2779
+ /**
2780
+ * Build dynamic data injection for non-OpenAI platforms using placeholders.
2781
+ * Similar to hybrid mode but with platform-appropriate loading/error states.
2782
+ */
2783
+ buildDynamicWithPlaceholdersScript(toolName, structuredContent, options) {
2784
+ const safeJson = (value) => {
2785
+ try {
2786
+ return JSON.stringify(value);
2787
+ } catch {
2788
+ return "null";
2789
+ }
2790
+ };
2791
+ const outputPlaceholder = HYBRID_DATA_PLACEHOLDER;
2792
+ const inputPlaceholder = HYBRID_INPUT_PLACEHOLDER;
2793
+ const includeInitialData = options?.includeInitialData !== false;
2794
+ return `
2795
+ <!-- Tool Data Injection (Dynamic Mode - Placeholder-based for non-OpenAI) -->
3185
2796
  <script>
3186
- (function() {
3187
- ${wrappedCode}
2797
+ window.__mcpToolName = ${safeJson(toolName)};
2798
+ window.__mcpToolInput = "${inputPlaceholder}";
2799
+ window.__mcpToolOutput = "${outputPlaceholder}";
2800
+ window.__mcpStructuredContent = ${safeJson(structuredContent ?? null)};
2801
+ window.__mcpHybridError = null;
3188
2802
 
3189
- // Get the component
3190
- var Component = window.__frontmcp_component.default || window.__frontmcp_component;
2803
+ (function() {
2804
+ var outputNotReplaced = false;
2805
+ var includeInitialData = ${includeInitialData};
3191
2806
 
3192
- // Render the component
3193
- var container = document.getElementById('${rootId}');
3194
- if (container && window.ReactDOM && window.ReactDOM.createRoot) {
3195
- var root = window.ReactDOM.createRoot(container);
3196
- root.render(React.createElement(Component, {
3197
- output: window.__mcpToolOutput,
3198
- input: window.__mcpToolInput,
3199
- }));
3200
- } else if (container && window.ReactDOM && window.ReactDOM.render) {
3201
- // Fallback for React 17
3202
- window.ReactDOM.render(
3203
- React.createElement(Component, {
3204
- output: window.__mcpToolOutput,
3205
- input: window.__mcpToolInput,
3206
- }),
3207
- container
3208
- );
2807
+ // Parse output placeholder
2808
+ var rawOutput = window.__mcpToolOutput;
2809
+ if (typeof rawOutput === 'string' && rawOutput !== "${outputPlaceholder}") {
2810
+ try {
2811
+ window.__mcpToolOutput = JSON.parse(rawOutput);
2812
+ } catch (e) {
2813
+ console.warn('[FrontMCP] Failed to parse injected output data:', e);
2814
+ window.__mcpToolOutput = null;
2815
+ window.__mcpHybridError = 'Failed to parse output data';
2816
+ }
2817
+ } else if (rawOutput === "${outputPlaceholder}") {
2818
+ window.__mcpToolOutput = null;
2819
+ outputNotReplaced = true;
3209
2820
  }
3210
- })();
3211
- </script>`;
3212
- } else {
3213
- return `
3214
- <!-- Component Render Script (ESM - waits for React) -->
3215
- <script type="module">
3216
- function renderComponent() {
3217
- ${wrappedCode}
3218
2821
 
3219
- // Get the component
3220
- var Component = window.__frontmcp_component.default || window.__frontmcp_component;
2822
+ // Parse input placeholder
2823
+ var rawInput = window.__mcpToolInput;
2824
+ if (typeof rawInput === 'string' && rawInput !== "${inputPlaceholder}") {
2825
+ try {
2826
+ window.__mcpToolInput = JSON.parse(rawInput);
2827
+ } catch (e) {
2828
+ console.warn('[FrontMCP] Failed to parse injected input data:', e);
2829
+ window.__mcpToolInput = null;
2830
+ }
2831
+ } else if (rawInput === "${inputPlaceholder}") {
2832
+ window.__mcpToolInput = null;
2833
+ }
3221
2834
 
3222
- // Render the component
3223
- var container = document.getElementById('${rootId}');
3224
- if (container && window.ReactDOM && window.ReactDOM.createRoot) {
3225
- var root = window.ReactDOM.createRoot(container);
3226
- root.render(React.createElement(Component, {
3227
- output: window.__mcpToolOutput,
3228
- input: window.__mcpToolInput,
3229
- }));
2835
+ // Handle placeholder not replaced - show error if expecting initial data
2836
+ if (outputNotReplaced && includeInitialData) {
2837
+ window.__mcpHybridError = 'No data provided. The output placeholder was not replaced.';
3230
2838
  }
3231
- }
2839
+ })();
3232
2840
 
3233
- // Wait for React to be ready
3234
- if (window.__reactReady) {
3235
- renderComponent();
3236
- } else {
3237
- window.addEventListener('react:ready', renderComponent);
2841
+ // Initialize FrontMCP context with appropriate loading/error state
2842
+ if (window.__frontmcp && window.__frontmcp.setContext) {
2843
+ window.__frontmcp.setContext({
2844
+ toolName: window.__mcpToolName,
2845
+ toolInput: window.__mcpToolInput,
2846
+ toolOutput: window.__mcpToolOutput,
2847
+ structuredContent: window.__mcpStructuredContent,
2848
+ loading: ${!includeInitialData} && window.__mcpToolOutput === null && !window.__mcpHybridError,
2849
+ error: window.__mcpHybridError,
2850
+ });
3238
2851
  }
3239
2852
  </script>`;
3240
- }
3241
2853
  }
3242
2854
  /**
3243
- * Assemble the complete static HTML document.
2855
+ * Build dynamic data injection for OpenAI using subscription pattern.
3244
2856
  */
3245
- assembleStaticHTML(parts) {
3246
- return `<!DOCTYPE html>
3247
- <html lang="en">
3248
- <head>
3249
- <title>${escapeHtml(parts.title)}</title>
3250
- ${parts.head}
3251
- ${parts.reactRuntime}
3252
- ${parts.frontmcpRuntime}
3253
- ${parts.dataScript}
3254
- </head>
3255
- <body>
3256
- <div id="${parts.rootId}" class="frontmcp-loading">
3257
- <div class="frontmcp-spinner"></div>
3258
- </div>
3259
- ${parts.componentScript}
3260
- </body>
3261
- </html>`;
3262
- }
3263
- };
3264
- function createBundler(options) {
3265
- return new InMemoryBundler(options);
3266
- }
3267
-
3268
- // libs/ui/src/bundler/file-cache/storage/index.ts
3269
- init_interface();
3270
- init_filesystem();
3271
- init_redis();
3272
-
3273
- // libs/ui/src/bundler/file-cache/hash-calculator.ts
3274
- var import_crypto2 = require("crypto");
3275
- var import_promises2 = require("fs/promises");
3276
- var import_fs2 = require("fs");
3277
- var import_path2 = require("path");
3278
- function sha256(content) {
3279
- return (0, import_crypto2.createHash)("sha256").update(content, "utf8").digest("hex");
3280
- }
3281
- function sha256Buffer(buffer) {
3282
- return (0, import_crypto2.createHash)("sha256").update(buffer).digest("hex");
3283
- }
3284
- async function hashFile(filePath) {
3285
- try {
3286
- const content = await (0, import_promises2.readFile)(filePath);
3287
- return sha256Buffer(content);
3288
- } catch {
3289
- return void 0;
3290
- }
3291
- }
3292
- async function hashFiles(filePaths) {
3293
- const hashes = [];
3294
- for (const filePath of filePaths.sort()) {
3295
- const hash = await hashFile(filePath);
3296
- if (hash) {
3297
- hashes.push(`${filePath}:${hash}`);
3298
- }
3299
- }
3300
- return sha256(hashes.join("\n"));
3301
- }
3302
- async function calculateComponentHash(options) {
3303
- const {
3304
- entryPath,
3305
- baseDir = (0, import_path2.dirname)(entryPath),
3306
- externals = [],
3307
- dependencies = {},
3308
- bundleOptions = {},
3309
- maxDepth = 10
3310
- } = options;
3311
- const absoluteEntryPath = (0, import_path2.resolve)(entryPath);
3312
- const files = /* @__PURE__ */ new Set();
3313
- const fileHashes = {};
3314
- await collectLocalDependencies(absoluteEntryPath, baseDir, files, maxDepth, 0);
3315
- for (const file of files) {
3316
- const hash = await hashFile(file);
3317
- if (hash) {
3318
- fileHashes[file] = hash;
3319
- }
3320
- }
3321
- const sortedFiles = Array.from(files).sort();
3322
- const fileHashContent = sortedFiles.map((f) => `${f}:${fileHashes[f] || "missing"}`).join("\n");
3323
- const filesHash = sha256(fileHashContent);
3324
- const optionsHash = sha256(JSON.stringify(sortedObject(bundleOptions)));
3325
- const dependenciesHash = sha256(JSON.stringify(sortedObject(dependencies)));
3326
- const combinedHash = sha256([filesHash, optionsHash, dependenciesHash].join(":"));
3327
- return {
3328
- hash: combinedHash,
3329
- entryHash: fileHashes[absoluteEntryPath] || "",
3330
- files: sortedFiles,
3331
- fileHashes,
3332
- optionsHash,
3333
- dependenciesHash
3334
- };
3335
- }
3336
- async function calculateQuickHash(entryPath, bundleOptions) {
3337
- const entryHash = await hashFile(entryPath);
3338
- const optionsHash = bundleOptions ? sha256(JSON.stringify(sortedObject(bundleOptions))) : "";
3339
- return sha256(`${entryHash || "missing"}:${optionsHash}`);
3340
- }
3341
- async function collectLocalDependencies(filePath, baseDir, collected, maxDepth, currentDepth) {
3342
- if (currentDepth >= maxDepth) return;
3343
- if (collected.has(filePath)) return;
3344
- if (!(0, import_fs2.existsSync)(filePath)) return;
3345
- collected.add(filePath);
3346
- try {
3347
- const content = await (0, import_promises2.readFile)(filePath, "utf8");
3348
- const imports = extractImportPaths(content);
3349
- for (const importPath of imports) {
3350
- if (!importPath.startsWith(".") && !importPath.startsWith("/")) {
3351
- continue;
3352
- }
3353
- const resolvedPath = resolveImportPath(importPath, (0, import_path2.dirname)(filePath));
3354
- if (resolvedPath && (0, import_fs2.existsSync)(resolvedPath)) {
3355
- await collectLocalDependencies(resolvedPath, baseDir, collected, maxDepth, currentDepth + 1);
3356
- }
3357
- }
3358
- } catch {
3359
- }
3360
- }
3361
- function extractImportPaths(source) {
3362
- const paths = [];
3363
- const importRegex = /import\s+(?:[^'"]+\s+from\s+)?['"]([^'"]+)['"]/g;
3364
- let match;
3365
- while ((match = importRegex.exec(source)) !== null) {
3366
- paths.push(match[1]);
3367
- }
3368
- const exportRegex = /export\s+(?:\*|{[^}]+})\s+from\s+['"]([^'"]+)['"]/g;
3369
- while ((match = exportRegex.exec(source)) !== null) {
3370
- paths.push(match[1]);
3371
- }
3372
- const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
3373
- while ((match = requireRegex.exec(source)) !== null) {
3374
- paths.push(match[1]);
3375
- }
3376
- const dynamicRegex = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
3377
- while ((match = dynamicRegex.exec(source)) !== null) {
3378
- paths.push(match[1]);
3379
- }
3380
- return [...new Set(paths)];
3381
- }
3382
- function resolveImportPath(importPath, fromDir) {
3383
- const extensions = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
3384
- for (const ext of extensions) {
3385
- const fullPath = (0, import_path2.join)(fromDir, importPath + ext);
3386
- if ((0, import_fs2.existsSync)(fullPath)) {
3387
- return fullPath;
3388
- }
3389
- }
3390
- for (const ext of extensions) {
3391
- const indexPath = (0, import_path2.join)(fromDir, importPath, `index${ext}`);
3392
- if ((0, import_fs2.existsSync)(indexPath)) {
3393
- return indexPath;
3394
- }
3395
- }
3396
- return void 0;
3397
- }
3398
- function sortedObject(obj) {
3399
- const sorted = {};
3400
- const keys = Object.keys(obj).sort();
3401
- for (const key of keys) {
3402
- const value = obj[key];
3403
- if (value && typeof value === "object" && !Array.isArray(value)) {
3404
- sorted[key] = sortedObject(value);
3405
- } else {
3406
- sorted[key] = value;
3407
- }
3408
- }
3409
- return sorted;
3410
- }
3411
- function generateBuildId() {
3412
- const timestamp = Date.now().toString(36);
3413
- const random = Math.random().toString(36).substring(2, 10);
3414
- return `${timestamp}-${random}`;
3415
- }
3416
- function buildIdFromHash(hash) {
3417
- return hash.substring(0, 12);
3418
- }
3419
-
3420
- // libs/ui/src/bundler/file-cache/component-builder.ts
3421
- var import_promises3 = require("fs/promises");
3422
- var import_fs3 = require("fs");
3423
- var import_path3 = require("path");
3424
- var import_crypto3 = require("crypto");
3425
-
3426
- // libs/ui/src/dependency/cdn-registry.ts
3427
- var DEFAULT_CDN_REGISTRY = {
3428
- // ============================================
3429
- // React Ecosystem
3430
- // ============================================
3431
- react: {
3432
- packageName: "react",
3433
- defaultVersion: "18.3.1",
3434
- providers: {
3435
- cloudflare: {
3436
- url: "https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js",
3437
- integrity: "sha512-Qp8J4Xr8LBZ5CXNJQc/HmLqFrpXz6lNkbzMYkYHKzQx5p1q1yOqPQHntXKoYgPPE/n9m0QF1OkJdXa2ePpO4fw==",
3438
- global: "React",
3439
- crossorigin: "anonymous"
3440
- },
3441
- jsdelivr: {
3442
- url: "https://cdn.jsdelivr.net/npm/react@18.3.1/umd/react.production.min.js",
3443
- global: "React",
3444
- crossorigin: "anonymous"
3445
- },
3446
- unpkg: {
3447
- url: "https://unpkg.com/react@18.3.1/umd/react.production.min.js",
3448
- global: "React",
3449
- crossorigin: "anonymous"
3450
- },
3451
- "esm.sh": {
3452
- url: "https://esm.sh/react@18.3.1",
3453
- esm: true,
3454
- crossorigin: "anonymous"
3455
- }
3456
- },
3457
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
3458
- metadata: {
3459
- description: "A JavaScript library for building user interfaces",
3460
- homepage: "https://react.dev",
3461
- license: "MIT"
3462
- }
3463
- },
3464
- "react-dom": {
3465
- packageName: "react-dom",
3466
- defaultVersion: "18.3.1",
3467
- providers: {
3468
- cloudflare: {
3469
- url: "https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js",
3470
- integrity: "sha512-6s2gVRdS3aT+FDdZTRJSzKlzIPqDXWyYl/5hPQb6hSgzKPGFcQyZhbqjbWVxGrs2dYNrINFXb0k0UD3d+CKPJA==",
3471
- global: "ReactDOM",
3472
- crossorigin: "anonymous",
3473
- peerDependencies: ["react"]
3474
- },
3475
- jsdelivr: {
3476
- url: "https://cdn.jsdelivr.net/npm/react-dom@18.3.1/umd/react-dom.production.min.js",
3477
- global: "ReactDOM",
3478
- crossorigin: "anonymous",
3479
- peerDependencies: ["react"]
3480
- },
3481
- unpkg: {
3482
- url: "https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js",
3483
- global: "ReactDOM",
3484
- crossorigin: "anonymous",
3485
- peerDependencies: ["react"]
3486
- },
3487
- "esm.sh": {
3488
- url: "https://esm.sh/react-dom@18.3.1",
3489
- esm: true,
3490
- crossorigin: "anonymous",
3491
- peerDependencies: ["react"]
3492
- }
3493
- },
3494
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
3495
- metadata: {
3496
- description: "React package for working with the DOM",
3497
- homepage: "https://react.dev",
3498
- license: "MIT"
3499
- }
3500
- },
3501
- // ============================================
3502
- // Charting Libraries
3503
- // ============================================
3504
- "chart.js": {
3505
- packageName: "chart.js",
3506
- defaultVersion: "4.4.7",
3507
- providers: {
3508
- cloudflare: {
3509
- url: "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.7/chart.umd.min.js",
3510
- integrity: "sha512-dMDjIoZjJD6gs0KPBhFYjLQrH3kIohSEn6HzWs6Y6GiO0+L9kk/bM3cR5KNEDK1KvMNpTIZG6pHK9SZfCJHRpQ==",
3511
- global: "Chart",
3512
- crossorigin: "anonymous"
3513
- },
3514
- jsdelivr: {
3515
- url: "https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js",
3516
- global: "Chart",
3517
- crossorigin: "anonymous"
3518
- },
3519
- unpkg: {
3520
- url: "https://unpkg.com/chart.js@4.4.7/dist/chart.umd.min.js",
3521
- global: "Chart",
3522
- crossorigin: "anonymous"
3523
- }
3524
- },
3525
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
3526
- metadata: {
3527
- description: "Simple yet flexible JavaScript charting library",
3528
- homepage: "https://www.chartjs.org",
3529
- license: "MIT"
3530
- }
3531
- },
3532
- "react-chartjs-2": {
3533
- packageName: "react-chartjs-2",
3534
- defaultVersion: "5.3.0",
3535
- providers: {
3536
- cloudflare: {
3537
- url: "https://cdnjs.cloudflare.com/ajax/libs/react-chartjs-2/5.3.0/react-chartjs-2.min.js",
3538
- global: "ReactChartjs2",
3539
- crossorigin: "anonymous",
3540
- peerDependencies: ["react", "chart.js"]
3541
- },
3542
- jsdelivr: {
3543
- url: "https://cdn.jsdelivr.net/npm/react-chartjs-2@5.3.0/dist/index.umd.js",
3544
- global: "ReactChartjs2",
3545
- crossorigin: "anonymous",
3546
- peerDependencies: ["react", "chart.js"]
3547
- },
3548
- "esm.sh": {
3549
- url: "https://esm.sh/react-chartjs-2@5.3.0",
3550
- esm: true,
3551
- crossorigin: "anonymous",
3552
- peerDependencies: ["react", "chart.js"]
3553
- }
3554
- },
3555
- preferredProviders: ["cloudflare", "jsdelivr", "esm.sh"],
3556
- metadata: {
3557
- description: "React components for Chart.js",
3558
- homepage: "https://react-chartjs-2.js.org",
3559
- license: "MIT"
3560
- }
3561
- },
3562
- // ============================================
3563
- // D3.js
3564
- // ============================================
3565
- d3: {
3566
- packageName: "d3",
3567
- defaultVersion: "7.9.0",
3568
- providers: {
3569
- cloudflare: {
3570
- url: "https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js",
3571
- integrity: "sha512-vc58qvvBdrDR4etbxMdlTt4GBQk1qjvyORR2nrsPsFPyrs+/u5c3+1Ct6upOgdZoIl7eq6k3a1UPDSNAQi/32A==",
3572
- global: "d3",
3573
- crossorigin: "anonymous"
3574
- },
3575
- jsdelivr: {
3576
- url: "https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js",
3577
- global: "d3",
3578
- crossorigin: "anonymous"
3579
- },
3580
- unpkg: {
3581
- url: "https://unpkg.com/d3@7.9.0/dist/d3.min.js",
3582
- global: "d3",
3583
- crossorigin: "anonymous"
3584
- }
3585
- },
3586
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
3587
- metadata: {
3588
- description: "Data-Driven Documents",
3589
- homepage: "https://d3js.org",
3590
- license: "ISC"
3591
- }
3592
- },
3593
- // ============================================
3594
- // Utility Libraries
3595
- // ============================================
3596
- lodash: {
3597
- packageName: "lodash",
3598
- defaultVersion: "4.17.21",
3599
- providers: {
3600
- cloudflare: {
3601
- url: "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js",
3602
- integrity: "sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==",
3603
- global: "_",
3604
- crossorigin: "anonymous"
3605
- },
3606
- jsdelivr: {
3607
- url: "https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js",
3608
- global: "_",
3609
- crossorigin: "anonymous"
3610
- },
3611
- unpkg: {
3612
- url: "https://unpkg.com/lodash@4.17.21/lodash.min.js",
3613
- global: "_",
3614
- crossorigin: "anonymous"
3615
- }
3616
- },
3617
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
3618
- metadata: {
3619
- description: "A modern JavaScript utility library",
3620
- homepage: "https://lodash.com",
3621
- license: "MIT"
3622
- }
3623
- },
3624
- "lodash-es": {
3625
- packageName: "lodash-es",
3626
- defaultVersion: "4.17.21",
3627
- providers: {
3628
- "esm.sh": {
3629
- url: "https://esm.sh/lodash-es@4.17.21",
3630
- esm: true,
3631
- crossorigin: "anonymous"
3632
- },
3633
- jsdelivr: {
3634
- url: "https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm",
3635
- esm: true,
3636
- crossorigin: "anonymous"
3637
- }
3638
- },
3639
- preferredProviders: ["esm.sh", "jsdelivr"],
3640
- metadata: {
3641
- description: "Lodash exported as ES modules",
3642
- homepage: "https://lodash.com",
3643
- license: "MIT"
3644
- }
3645
- },
3646
- dayjs: {
3647
- packageName: "dayjs",
3648
- defaultVersion: "1.11.13",
3649
- providers: {
3650
- cloudflare: {
3651
- url: "https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.13/dayjs.min.js",
3652
- integrity: "sha512-Ot7ArUEhJDU0cwoBNNnWe487kjL5wAOsIYig8llY/l0P2TUFwgsAHVmrZMHsT8NGo+HwkjTJsNErS6QqIkBxDw==",
3653
- global: "dayjs",
3654
- crossorigin: "anonymous"
3655
- },
3656
- jsdelivr: {
3657
- url: "https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js",
3658
- global: "dayjs",
3659
- crossorigin: "anonymous"
3660
- },
3661
- unpkg: {
3662
- url: "https://unpkg.com/dayjs@1.11.13/dayjs.min.js",
3663
- global: "dayjs",
3664
- crossorigin: "anonymous"
3665
- }
3666
- },
3667
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
3668
- metadata: {
3669
- description: "Fast 2kB alternative to Moment.js with the same modern API",
3670
- homepage: "https://day.js.org",
3671
- license: "MIT"
3672
- }
3673
- },
3674
- "date-fns": {
3675
- packageName: "date-fns",
3676
- defaultVersion: "4.1.0",
3677
- providers: {
3678
- "esm.sh": {
3679
- url: "https://esm.sh/date-fns@4.1.0",
3680
- esm: true,
3681
- crossorigin: "anonymous"
3682
- },
3683
- jsdelivr: {
3684
- url: "https://cdn.jsdelivr.net/npm/date-fns@4.1.0/+esm",
3685
- esm: true,
3686
- crossorigin: "anonymous"
3687
- }
3688
- },
3689
- preferredProviders: ["esm.sh", "jsdelivr"],
3690
- metadata: {
3691
- description: "Modern JavaScript date utility library",
3692
- homepage: "https://date-fns.org",
3693
- license: "MIT"
3694
- }
3695
- },
3696
- // ============================================
3697
- // Animation Libraries
3698
- // ============================================
3699
- "framer-motion": {
3700
- packageName: "framer-motion",
3701
- defaultVersion: "11.15.0",
3702
- providers: {
3703
- "esm.sh": {
3704
- url: "https://esm.sh/framer-motion@11.15.0",
3705
- esm: true,
3706
- crossorigin: "anonymous",
3707
- peerDependencies: ["react", "react-dom"]
3708
- },
3709
- jsdelivr: {
3710
- url: "https://cdn.jsdelivr.net/npm/framer-motion@11.15.0/dist/framer-motion.js",
3711
- global: "Motion",
3712
- crossorigin: "anonymous",
3713
- peerDependencies: ["react", "react-dom"]
3714
- }
3715
- },
3716
- preferredProviders: ["esm.sh", "jsdelivr"],
3717
- metadata: {
3718
- description: "Production-ready motion library for React",
3719
- homepage: "https://www.framer.com/motion/",
3720
- license: "MIT"
3721
- }
3722
- },
3723
- // ============================================
3724
- // UI Component Libraries
3725
- // ============================================
3726
- "lucide-react": {
3727
- packageName: "lucide-react",
3728
- defaultVersion: "0.468.0",
3729
- providers: {
3730
- "esm.sh": {
3731
- url: "https://esm.sh/lucide-react@0.468.0",
3732
- esm: true,
3733
- crossorigin: "anonymous",
3734
- peerDependencies: ["react"]
3735
- },
3736
- jsdelivr: {
3737
- url: "https://cdn.jsdelivr.net/npm/lucide-react@0.468.0/dist/esm/lucide-react.js",
3738
- esm: true,
3739
- crossorigin: "anonymous",
3740
- peerDependencies: ["react"]
3741
- }
3742
- },
3743
- preferredProviders: ["esm.sh", "jsdelivr"],
3744
- metadata: {
3745
- description: "Beautiful & consistent icon toolkit for React",
3746
- homepage: "https://lucide.dev",
3747
- license: "ISC"
3748
- }
3749
- },
3750
- // ============================================
3751
- // Markdown/Syntax Highlighting
3752
- // ============================================
3753
- marked: {
3754
- packageName: "marked",
3755
- defaultVersion: "15.0.4",
3756
- providers: {
3757
- cloudflare: {
3758
- url: "https://cdnjs.cloudflare.com/ajax/libs/marked/15.0.4/marked.min.js",
3759
- integrity: "sha512-Rn/d0sGeizGbk3VJEiYNDt/mMcfuzYoFkia3iBffv+HX8VUrHMo/0cKjZuxWGoZLPh/VxUcC9ais+RBFZW9EBg==",
3760
- global: "marked",
3761
- crossorigin: "anonymous"
3762
- },
3763
- jsdelivr: {
3764
- url: "https://cdn.jsdelivr.net/npm/marked@15.0.4/marked.min.js",
3765
- global: "marked",
3766
- crossorigin: "anonymous"
3767
- },
3768
- unpkg: {
3769
- url: "https://unpkg.com/marked@15.0.4/marked.min.js",
3770
- global: "marked",
3771
- crossorigin: "anonymous"
3772
- }
3773
- },
3774
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
3775
- metadata: {
3776
- description: "A markdown parser and compiler",
3777
- homepage: "https://marked.js.org",
3778
- license: "MIT"
3779
- }
3780
- },
3781
- "highlight.js": {
3782
- packageName: "highlight.js",
3783
- defaultVersion: "11.10.0",
3784
- providers: {
3785
- cloudflare: {
3786
- url: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js",
3787
- integrity: "sha512-6yoqbrcLAHDWAdQmiRlHG4+m0g/CT/V9AGyxabG8j7Jk8j3v3k6mIP1iN/PvSofcWet2tf8SRn/j3L/+pb7LRQ==",
3788
- global: "hljs",
3789
- crossorigin: "anonymous"
3790
- },
3791
- jsdelivr: {
3792
- url: "https://cdn.jsdelivr.net/npm/highlight.js@11.10.0/lib/core.min.js",
3793
- global: "hljs",
3794
- crossorigin: "anonymous"
3795
- },
3796
- unpkg: {
3797
- url: "https://unpkg.com/highlight.js@11.10.0/lib/core.min.js",
3798
- global: "hljs",
3799
- crossorigin: "anonymous"
3800
- }
3801
- },
3802
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
3803
- metadata: {
3804
- description: "Syntax highlighting for the web",
3805
- homepage: "https://highlightjs.org",
3806
- license: "BSD-3-Clause"
3807
- }
3808
- },
3809
- // ============================================
3810
- // Interactive Libraries
3811
- // ============================================
3812
- "htmx.org": {
3813
- packageName: "htmx.org",
3814
- defaultVersion: "2.0.4",
3815
- providers: {
3816
- cloudflare: {
3817
- url: "https://cdnjs.cloudflare.com/ajax/libs/htmx/2.0.4/htmx.min.js",
3818
- integrity: "sha512-2kIcAizYXhIn5IyXrMC72f2nh0JAtESHRpOieVw5dYPYeHwLCC2eKCqvdZDYRSEgasKrPpEPpRFjL8gqwBZWAA==",
3819
- global: "htmx",
3820
- crossorigin: "anonymous"
3821
- },
3822
- jsdelivr: {
3823
- url: "https://cdn.jsdelivr.net/npm/htmx.org@2.0.4/dist/htmx.min.js",
3824
- global: "htmx",
3825
- crossorigin: "anonymous"
3826
- },
3827
- unpkg: {
3828
- url: "https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js",
3829
- global: "htmx",
3830
- crossorigin: "anonymous"
3831
- }
3832
- },
3833
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
3834
- metadata: {
3835
- description: "High power tools for HTML",
3836
- homepage: "https://htmx.org",
3837
- license: "BSD-2-Clause"
3838
- }
3839
- },
3840
- alpinejs: {
3841
- packageName: "alpinejs",
3842
- defaultVersion: "3.14.3",
3843
- providers: {
3844
- cloudflare: {
3845
- url: "https://cdnjs.cloudflare.com/ajax/libs/alpinejs/3.14.3/cdn.min.js",
3846
- integrity: "sha512-lrQ8FHgsWKFSuQFq8NKPJicjlvJFEIrCqEj8zeX7ZOUlHWltN/Iow4jND+x84jqTdDf9n+hvQpJjGDvOl/eDRA==",
3847
- global: "Alpine",
3848
- crossorigin: "anonymous"
3849
- },
3850
- jsdelivr: {
3851
- url: "https://cdn.jsdelivr.net/npm/alpinejs@3.14.3/dist/cdn.min.js",
3852
- global: "Alpine",
3853
- crossorigin: "anonymous"
3854
- },
3855
- unpkg: {
3856
- url: "https://unpkg.com/alpinejs@3.14.3/dist/cdn.min.js",
3857
- global: "Alpine",
3858
- crossorigin: "anonymous"
3859
- }
3860
- },
3861
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
3862
- metadata: {
3863
- description: "A rugged, minimal framework for composing behavior directly in your markup",
3864
- homepage: "https://alpinejs.dev",
3865
- license: "MIT"
3866
- }
3867
- },
3868
- // ============================================
3869
- // Templating Libraries
3870
- // ============================================
3871
- handlebars: {
3872
- packageName: "handlebars",
3873
- defaultVersion: "4.7.8",
3874
- providers: {
3875
- cloudflare: {
3876
- url: "https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.8/handlebars.min.js",
3877
- integrity: "sha512-E1dSFxg+wsfJ4HKjutk/WaCzK7S2wv1POn1RRPGh8ZK+ag9l244Vqxji3r6wgz9YBf6+vhQEYJZpSjqWFPg9gg==",
3878
- global: "Handlebars",
3879
- crossorigin: "anonymous"
3880
- },
3881
- jsdelivr: {
3882
- url: "https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.min.js",
3883
- global: "Handlebars",
3884
- crossorigin: "anonymous"
3885
- },
3886
- unpkg: {
3887
- url: "https://unpkg.com/handlebars@4.7.8/dist/handlebars.min.js",
3888
- global: "Handlebars",
3889
- crossorigin: "anonymous"
3890
- }
3891
- },
3892
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
3893
- metadata: {
3894
- description: "Minimal templating on steroids",
3895
- homepage: "https://handlebarsjs.com",
3896
- license: "MIT"
3897
- }
3898
- }
3899
- };
3900
- var CDN_PROVIDER_PRIORITY = {
3901
- claude: ["cloudflare"],
3902
- // ONLY cloudflare for Claude
3903
- openai: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
3904
- cursor: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
3905
- gemini: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
3906
- continue: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
3907
- cody: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
3908
- unknown: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"]
3909
- // Default to cloudflare first
3910
- };
3911
- function lookupPackage(packageName, registry = DEFAULT_CDN_REGISTRY) {
3912
- return registry[packageName];
3913
- }
3914
- function mergeRegistries(customRegistry) {
3915
- return {
3916
- ...DEFAULT_CDN_REGISTRY,
3917
- ...customRegistry
3918
- };
3919
- }
3920
- function getPackagePeerDependencies(packageName, registry = DEFAULT_CDN_REGISTRY) {
3921
- const entry = lookupPackage(packageName, registry);
3922
- if (!entry) return [];
3923
- for (const provider of Object.keys(entry.providers)) {
3924
- const config = entry.providers[provider];
3925
- if (config?.peerDependencies) {
3926
- return config.peerDependencies;
3927
- }
3928
- }
3929
- return [];
3930
- }
3931
- function resolveAllDependencies(packageNames, platform = "unknown", registry = DEFAULT_CDN_REGISTRY) {
3932
- const resolved = /* @__PURE__ */ new Set();
3933
- const queue = [...packageNames];
3934
- while (queue.length > 0) {
3935
- const packageName = queue.shift();
3936
- if (!packageName) continue;
3937
- if (resolved.has(packageName)) continue;
3938
- resolved.add(packageName);
3939
- const peers = getPackagePeerDependencies(packageName, registry);
3940
- for (const peer of peers) {
3941
- if (!resolved.has(peer)) {
3942
- queue.push(peer);
3943
- }
3944
- }
3945
- }
3946
- const result = [];
3947
- const remaining = new Set(resolved);
3948
- while (remaining.size > 0) {
3949
- let added = false;
3950
- for (const pkg of remaining) {
3951
- const peers = getPackagePeerDependencies(pkg, registry);
3952
- const allPeersResolved = peers.every((peer) => !remaining.has(peer) || result.includes(peer));
3953
- if (allPeersResolved) {
3954
- if (!result.includes(pkg)) {
3955
- result.push(pkg);
3956
- }
3957
- remaining.delete(pkg);
3958
- added = true;
3959
- }
3960
- }
3961
- if (!added && remaining.size > 0) {
3962
- const next = remaining.values().next().value;
3963
- if (next !== void 0) {
3964
- if (!result.includes(next)) {
3965
- result.push(next);
3966
- }
3967
- remaining.delete(next);
3968
- }
3969
- }
3970
- }
3971
- return result;
3972
- }
3973
-
3974
- // libs/ui/src/dependency/import-parser.ts
3975
- var IMPORT_PATTERNS = {
3976
- /**
3977
- * Named imports: import { foo, bar } from 'module'
3978
- * Also handles renamed imports: import { foo as f } from 'module'
3979
- */
3980
- named: /import\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/g,
3981
- /**
3982
- * Default imports: import foo from 'module'
3983
- */
3984
- default: /import\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,
3985
- /**
3986
- * Namespace imports: import * as foo from 'module'
3987
- */
3988
- namespace: /import\s*\*\s*as\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,
3989
- /**
3990
- * Side-effect imports: import 'module'
3991
- */
3992
- sideEffect: /import\s*['"]([^'"]+)['"]/g,
3993
- /**
3994
- * Dynamic imports: import('module') or await import('module')
3995
- */
3996
- dynamic: /(?:await\s+)?import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
3997
- /**
3998
- * Combined default and named: import foo, { bar } from 'module'
3999
- */
4000
- defaultAndNamed: /import\s+(\w+)\s*,\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/g,
4001
- /**
4002
- * Combined default and namespace: import foo, * as bar from 'module'
4003
- */
4004
- defaultAndNamespace: /import\s+(\w+)\s*,\s*\*\s*as\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,
4005
- /**
4006
- * Re-exports: export { foo } from 'module'
4007
- */
4008
- reExport: /export\s*\{[^}]+\}\s*from\s*['"]([^'"]+)['"]/g,
4009
- /**
4010
- * Re-export all: export * from 'module'
4011
- */
4012
- reExportAll: /export\s*\*\s*from\s*['"]([^'"]+)['"]/g
4013
- };
4014
- function parseNamedImports(namedString) {
4015
- return namedString.split(",").map((s) => s.trim()).filter((s) => s.length > 0).map((s) => {
4016
- const asMatch = s.match(/^(\w+)\s+as\s+\w+$/);
4017
- return asMatch ? asMatch[1] : s;
4018
- });
4019
- }
4020
- function isRelativeImport(specifier) {
4021
- return specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith("/");
4022
- }
4023
- function isExternalImport(specifier) {
4024
- return !isRelativeImport(specifier) && !specifier.startsWith("#");
4025
- }
4026
- function getPackageName(specifier) {
4027
- if (specifier.startsWith("@")) {
4028
- const parts = specifier.split("/");
4029
- if (parts.length >= 2) {
4030
- return `${parts[0]}/${parts[1]}`;
4031
- }
4032
- return specifier;
4033
- }
4034
- const firstSlash = specifier.indexOf("/");
4035
- return firstSlash === -1 ? specifier : specifier.slice(0, firstSlash);
4036
- }
4037
- function getLineNumber(source, index) {
4038
- let line = 1;
4039
- for (let i = 0; i < index && i < source.length; i++) {
4040
- if (source[i] === "\n") {
4041
- line++;
4042
- }
4043
- }
4044
- return line;
4045
- }
4046
- function getColumnNumber(source, index) {
4047
- let column = 0;
4048
- for (let i = index - 1; i >= 0 && source[i] !== "\n"; i--) {
4049
- column++;
4050
- }
4051
- return column;
4052
- }
4053
- function parseImports(source) {
4054
- const imports = [];
4055
- const seenStatements = /* @__PURE__ */ new Set();
4056
- const addImport = (imp) => {
4057
- const key = `${imp.type}:${imp.specifier}:${imp.statement}`;
4058
- if (!seenStatements.has(key)) {
4059
- seenStatements.add(key);
4060
- imports.push(imp);
4061
- }
4062
- };
4063
- let match;
4064
- const defaultAndNamedRegex = new RegExp(IMPORT_PATTERNS.defaultAndNamed.source, "g");
4065
- while ((match = defaultAndNamedRegex.exec(source)) !== null) {
4066
- const [statement, defaultName, namedString, specifier] = match;
4067
- const namedImports = parseNamedImports(namedString);
4068
- addImport({
4069
- statement,
4070
- specifier,
4071
- type: "default",
4072
- defaultImport: defaultName,
4073
- namedImports,
4074
- line: getLineNumber(source, match.index),
4075
- column: getColumnNumber(source, match.index)
4076
- });
4077
- }
4078
- const defaultAndNamespaceRegex = new RegExp(IMPORT_PATTERNS.defaultAndNamespace.source, "g");
4079
- while ((match = defaultAndNamespaceRegex.exec(source)) !== null) {
4080
- const [statement, defaultName, namespaceName, specifier] = match;
4081
- addImport({
4082
- statement,
4083
- specifier,
4084
- type: "default",
4085
- defaultImport: defaultName,
4086
- namespaceImport: namespaceName,
4087
- line: getLineNumber(source, match.index),
4088
- column: getColumnNumber(source, match.index)
4089
- });
4090
- }
4091
- const namedRegex = new RegExp(IMPORT_PATTERNS.named.source, "g");
4092
- while ((match = namedRegex.exec(source)) !== null) {
4093
- const [statement, namedString, specifier] = match;
4094
- const namedImports = parseNamedImports(namedString);
4095
- addImport({
4096
- statement,
4097
- specifier,
4098
- type: "named",
4099
- namedImports,
4100
- line: getLineNumber(source, match.index),
4101
- column: getColumnNumber(source, match.index)
4102
- });
4103
- }
4104
- const defaultRegex = new RegExp(IMPORT_PATTERNS.default.source, "g");
4105
- while ((match = defaultRegex.exec(source)) !== null) {
4106
- const [statement, defaultName, specifier] = match;
4107
- const afterMatch = source.slice(match.index + match[0].length - specifier.length - 2);
4108
- if (afterMatch.startsWith(",")) continue;
4109
- addImport({
4110
- statement,
4111
- specifier,
4112
- type: "default",
4113
- defaultImport: defaultName,
4114
- line: getLineNumber(source, match.index),
4115
- column: getColumnNumber(source, match.index)
4116
- });
4117
- }
4118
- const namespaceRegex = new RegExp(IMPORT_PATTERNS.namespace.source, "g");
4119
- while ((match = namespaceRegex.exec(source)) !== null) {
4120
- const [statement, namespaceName, specifier] = match;
4121
- addImport({
4122
- statement,
4123
- specifier,
4124
- type: "namespace",
4125
- namespaceImport: namespaceName,
4126
- line: getLineNumber(source, match.index),
4127
- column: getColumnNumber(source, match.index)
4128
- });
4129
- }
4130
- const sideEffectRegex = new RegExp(IMPORT_PATTERNS.sideEffect.source, "g");
4131
- while ((match = sideEffectRegex.exec(source)) !== null) {
4132
- const [statement, specifier] = match;
4133
- const beforeMatch = source.slice(Math.max(0, match.index - 50), match.index);
4134
- if (beforeMatch.includes("from")) continue;
4135
- addImport({
4136
- statement,
4137
- specifier,
4138
- type: "side-effect",
4139
- line: getLineNumber(source, match.index),
4140
- column: getColumnNumber(source, match.index)
4141
- });
4142
- }
4143
- const dynamicRegex = new RegExp(IMPORT_PATTERNS.dynamic.source, "g");
4144
- while ((match = dynamicRegex.exec(source)) !== null) {
4145
- const [statement, specifier] = match;
4146
- addImport({
4147
- statement,
4148
- specifier,
4149
- type: "dynamic",
4150
- line: getLineNumber(source, match.index),
4151
- column: getColumnNumber(source, match.index)
4152
- });
4153
- }
4154
- const reExportRegex = new RegExp(IMPORT_PATTERNS.reExport.source, "g");
4155
- while ((match = reExportRegex.exec(source)) !== null) {
4156
- const [statement, specifier] = match;
4157
- addImport({
4158
- statement,
4159
- specifier,
4160
- type: "named",
4161
- line: getLineNumber(source, match.index),
4162
- column: getColumnNumber(source, match.index)
4163
- });
4164
- }
4165
- const reExportAllRegex = new RegExp(IMPORT_PATTERNS.reExportAll.source, "g");
4166
- while ((match = reExportAllRegex.exec(source)) !== null) {
4167
- const [statement, specifier] = match;
4168
- addImport({
4169
- statement,
4170
- specifier,
4171
- type: "namespace",
4172
- line: getLineNumber(source, match.index),
4173
- column: getColumnNumber(source, match.index)
4174
- });
4175
- }
4176
- const externalImports = imports.filter((imp) => isExternalImport(imp.specifier));
4177
- const relativeImports = imports.filter((imp) => isRelativeImport(imp.specifier));
4178
- const externalPackages = [...new Set(externalImports.map((imp) => getPackageName(imp.specifier)))];
4179
- return {
4180
- imports,
4181
- externalImports,
4182
- relativeImports,
4183
- externalPackages
4184
- };
4185
- }
4186
-
4187
- // libs/ui/src/dependency/import-map.ts
4188
- function createImportMap(dependencies) {
4189
- const imports = {};
4190
- const integrity = {};
4191
- for (const dep of dependencies) {
4192
- imports[dep.packageName] = dep.cdnUrl;
4193
- if (dep.integrity) {
4194
- integrity[dep.cdnUrl] = dep.integrity;
4195
- }
4196
- }
4197
- return {
4198
- imports,
4199
- integrity: Object.keys(integrity).length > 0 ? integrity : void 0
4200
- };
4201
- }
4202
- function generateImportMapScriptTag(map) {
4203
- const json = JSON.stringify(map, null, 2);
4204
- return `<script type="importmap">
4205
- ${json}
4206
- </script>`;
4207
- }
4208
- function generateImportMapScriptTagMinified(map) {
4209
- const json = JSON.stringify(map);
4210
- return `<script type="importmap">${json}</script>`;
4211
- }
4212
- function generateUMDShim(dependencies, options = {}) {
4213
- const { safe = true, minify = false } = options;
4214
- const depsWithGlobals = dependencies.filter((d) => d.global && !d.esm);
4215
- if (depsWithGlobals.length === 0) {
4216
- return "";
4217
- }
4218
- const entries = depsWithGlobals.map((dep) => {
4219
- const global = dep.global;
4220
- return `'${dep.packageName}': { default: window.${global}, ...window.${global} }`;
4221
- });
4222
- const shimObject = `{
4223
- ${entries.join(",\n ")}
4224
- }`;
4225
- const code = safe ? `(function() {
4226
- try {
4227
- window.__esm_shim = ${shimObject};
4228
- } catch (e) {
4229
- console.warn('UMD shim failed:', e);
4230
- }
4231
- })();` : `window.__esm_shim = ${shimObject};`;
4232
- return minify ? code.replace(/\s+/g, " ").replace(/\s*([{},:])\s*/g, "$1") : code;
4233
- }
4234
- function generateCDNScriptTags(dependencies) {
4235
- return dependencies.filter((dep) => !dep.esm).map((dep) => {
4236
- const attrs = [`src="${escapeHtmlAttr(dep.cdnUrl)}"`];
4237
- if (dep.integrity) {
4238
- attrs.push(`integrity="${escapeHtmlAttr(dep.integrity)}"`);
4239
- }
4240
- attrs.push('crossorigin="anonymous"');
4241
- return `<script ${attrs.join(" ")}></script>`;
4242
- });
4243
- }
4244
- function generateESMScriptTags(dependencies) {
4245
- return dependencies.filter((dep) => dep.esm).map((dep) => {
4246
- const attrs = ['type="module"', `src="${escapeHtmlAttr(dep.cdnUrl)}"`];
4247
- if (dep.integrity) {
4248
- attrs.push(`integrity="${escapeHtmlAttr(dep.integrity)}"`);
4249
- }
4250
- attrs.push('crossorigin="anonymous"');
4251
- return `<script ${attrs.join(" ")}></script>`;
4252
- });
4253
- }
4254
- function generateDependencyHTML(dependencies, options = {}) {
4255
- const { minify = false, includeShim = true } = options;
4256
- const parts = [];
4257
- const importMap = createImportMap(dependencies);
4258
- const importMapTag = minify ? generateImportMapScriptTagMinified(importMap) : generateImportMapScriptTag(importMap);
4259
- parts.push(importMapTag);
4260
- const umdTags = generateCDNScriptTags(dependencies);
4261
- parts.push(...umdTags);
4262
- if (includeShim) {
4263
- const shim = generateUMDShim(dependencies, { minify });
4264
- if (shim) {
4265
- parts.push(`<script>${shim}</script>`);
4266
- }
4267
- }
4268
- const esmTags = generateESMScriptTags(dependencies);
4269
- parts.push(...esmTags);
4270
- return parts.join(minify ? "" : "\n");
4271
- }
4272
-
4273
- // libs/ui/src/dependency/resolver.ts
4274
- var DependencyResolutionError = class extends Error {
4275
- constructor(packageName, reason) {
4276
- super(`Failed to resolve dependency "${packageName}": ${reason}`);
4277
- this.packageName = packageName;
4278
- this.reason = reason;
4279
- this.name = "DependencyResolutionError";
4280
- }
4281
- };
4282
- var NoProviderError = class extends DependencyResolutionError {
4283
- constructor(packageName, platform) {
4284
- super(packageName, `No CDN provider available for platform "${platform}"`);
4285
- this.platform = platform;
4286
- this.name = "NoProviderError";
4287
- }
4288
- };
4289
- var DependencyResolver = class {
4290
- options;
4291
- registry;
4292
- constructor(options = {}) {
4293
- this.options = {
4294
- platform: options.platform ?? "unknown",
4295
- preferredProviders: options.preferredProviders ?? CDN_PROVIDER_PRIORITY[options.platform ?? "unknown"],
4296
- customRegistry: options.customRegistry ?? {},
4297
- strictMode: options.strictMode ?? true,
4298
- requireIntegrity: options.requireIntegrity ?? false
4299
- };
4300
- this.registry = mergeRegistries(this.options.customRegistry);
4301
- }
4302
- /**
4303
- * Resolve a single package to its CDN dependency.
4304
- *
4305
- * @param packageName - NPM package name
4306
- * @param override - Optional explicit CDN dependency override
4307
- * @returns Resolved dependency, or null in non-strict mode if package is not found (should be bundled)
4308
- * @throws DependencyResolutionError if package cannot be resolved in strict mode
4309
- */
4310
- resolve(packageName, override) {
4311
- if (override) {
4312
- return this.createResolvedDependency(packageName, override, "custom");
4313
- }
4314
- const entry = lookupPackage(packageName, this.registry);
4315
- if (!entry) {
4316
- if (this.options.strictMode) {
4317
- throw new DependencyResolutionError(
4318
- packageName,
4319
- 'Package not found in CDN registry. Add it to "dependencies" for explicit CDN configuration.'
4320
- );
2857
+ buildDynamicWithSubscriptionScript(toolName, input, output, structuredContent, options) {
2858
+ const safeJson = (value) => {
2859
+ try {
2860
+ return JSON.stringify(value);
2861
+ } catch {
2862
+ return "null";
4321
2863
  }
4322
- return null;
4323
- }
4324
- const providerPriority = this.options.preferredProviders;
4325
- for (const provider of providerPriority) {
4326
- const config = entry.providers[provider];
4327
- if (config?.url) {
4328
- if (this.options.requireIntegrity && !config.integrity) {
4329
- continue;
2864
+ };
2865
+ const includeInitial = options?.includeInitialData !== false;
2866
+ const subscribeToUpdates = options?.subscribeToUpdates !== false;
2867
+ const initialDataBlock = includeInitial ? `
2868
+ window.__mcpToolOutput = ${safeJson(output ?? null)};
2869
+ if (window.__frontmcp && window.__frontmcp.setState) {
2870
+ window.__frontmcp.setState({
2871
+ output: window.__mcpToolOutput,
2872
+ loading: false,
2873
+ });
2874
+ }` : `
2875
+ window.__mcpToolOutput = null;
2876
+ if (window.__frontmcp && window.__frontmcp.setState) {
2877
+ window.__frontmcp.setState({
2878
+ output: null,
2879
+ loading: true,
2880
+ });
2881
+ }`;
2882
+ const subscriptionBlock = subscribeToUpdates ? `
2883
+ // Subscribe to platform tool result updates
2884
+ (function() {
2885
+ function subscribeToUpdates() {
2886
+ // OpenAI Apps SDK
2887
+ if (window.openai && window.openai.canvas && window.openai.canvas.onToolResult) {
2888
+ window.openai.canvas.onToolResult(function(result) {
2889
+ window.__mcpToolOutput = result;
2890
+ if (window.__frontmcp && window.__frontmcp.setState) {
2891
+ window.__frontmcp.setState({
2892
+ output: result,
2893
+ loading: false,
2894
+ });
2895
+ }
2896
+ // Dispatch custom event for React hooks
2897
+ window.dispatchEvent(new CustomEvent('frontmcp:toolResult', { detail: result }));
2898
+ });
2899
+ return;
2900
+ }
2901
+
2902
+ // Fallback: listen for custom events (for testing/other platforms)
2903
+ window.addEventListener('frontmcp:injectData', function(e) {
2904
+ if (e.detail && e.detail.output !== undefined) {
2905
+ window.__mcpToolOutput = e.detail.output;
2906
+ if (window.__frontmcp && window.__frontmcp.setState) {
2907
+ window.__frontmcp.setState({
2908
+ output: e.detail.output,
2909
+ loading: false,
2910
+ });
2911
+ }
2912
+ }
2913
+ });
4330
2914
  }
4331
- return this.createResolvedDependency(packageName, config, provider, entry.defaultVersion);
2915
+
2916
+ // Subscribe when DOM is ready
2917
+ if (document.readyState === 'loading') {
2918
+ document.addEventListener('DOMContentLoaded', subscribeToUpdates);
2919
+ } else {
2920
+ subscribeToUpdates();
2921
+ }
2922
+ })();` : "";
2923
+ return `
2924
+ <!-- Tool Data Injection (Dynamic Mode - OpenAI Subscription) -->
2925
+ <script>
2926
+ window.__mcpToolName = ${safeJson(toolName)};
2927
+ window.__mcpToolInput = ${safeJson(input ?? null)};
2928
+ window.__mcpStructuredContent = ${safeJson(structuredContent ?? null)};
2929
+ ${initialDataBlock}
2930
+
2931
+ // Initialize FrontMCP context
2932
+ if (window.__frontmcp && window.__frontmcp.setContext) {
2933
+ window.__frontmcp.setContext({
2934
+ toolName: window.__mcpToolName,
2935
+ toolInput: window.__mcpToolInput,
2936
+ toolOutput: window.__mcpToolOutput,
2937
+ structuredContent: window.__mcpStructuredContent,
2938
+ });
4332
2939
  }
4333
- }
4334
- throw new NoProviderError(packageName, this.options.platform);
2940
+ ${subscriptionBlock}
2941
+ </script>`;
4335
2942
  }
4336
2943
  /**
4337
- * Resolve multiple packages.
4338
- *
4339
- * @param packageNames - Array of package names
4340
- * @param overrides - Optional explicit overrides for specific packages
4341
- * @returns Array of resolved dependencies (in dependency order)
2944
+ * Build hybrid data injection - shell with placeholders for runtime injection.
2945
+ * Use injectHybridData() or injectHybridDataFull() from @frontmcp/uipack to replace the placeholders.
4342
2946
  */
4343
- resolveMany(packageNames, overrides) {
4344
- const allPackages = resolveAllDependencies(packageNames, this.options.platform, this.registry);
4345
- const resolved = [];
4346
- for (const pkgName of allPackages) {
2947
+ buildHybridDataScript(toolName, _input, structuredContent, options) {
2948
+ const safeJson = (value) => {
4347
2949
  try {
4348
- const override = overrides?.[pkgName];
4349
- const dep = this.resolve(pkgName, override);
4350
- if (dep) {
4351
- resolved.push(dep);
4352
- }
4353
- } catch (error) {
4354
- if (this.options.strictMode) {
4355
- throw error;
4356
- }
2950
+ return JSON.stringify(value);
2951
+ } catch {
2952
+ return "null";
4357
2953
  }
4358
- }
4359
- return resolved;
4360
- }
4361
- /**
4362
- * Resolve dependencies from source code.
4363
- *
4364
- * Parses the source to extract imports, then resolves external packages
4365
- * that are in the externals list.
4366
- *
4367
- * @param source - Source code to parse
4368
- * @param externals - Package names to resolve from CDN (others are bundled)
4369
- * @param overrides - Optional explicit CDN overrides
4370
- * @returns Resolved dependencies
4371
- */
4372
- resolveFromSource(source, externals, overrides) {
4373
- const parseResult = parseImports(source);
4374
- const packagesToResolve = parseResult.externalPackages.filter((pkg) => externals.includes(pkg));
4375
- return this.resolveMany(packagesToResolve, overrides);
4376
- }
4377
- /**
4378
- * Generate an import map for resolved dependencies.
4379
- *
4380
- * @param dependencies - Resolved dependencies
4381
- * @returns Browser import map
4382
- */
4383
- generateImportMap(dependencies) {
4384
- return createImportMap(dependencies);
4385
- }
4386
- /**
4387
- * Check if a package can be resolved for the current platform.
4388
- *
4389
- * @param packageName - Package name to check
4390
- * @returns true if the package can be resolved
4391
- */
4392
- canResolve(packageName) {
4393
- try {
4394
- const result = this.resolve(packageName);
4395
- return result !== null;
4396
- } catch {
4397
- return false;
4398
- }
4399
- }
4400
- /**
4401
- * Get the resolved CDN URL for a package.
4402
- *
4403
- * @param packageName - Package name
4404
- * @param override - Optional explicit override
4405
- * @returns CDN URL or undefined if cannot resolve
4406
- */
4407
- getUrl(packageName, override) {
4408
- try {
4409
- const resolved = this.resolve(packageName, override);
4410
- return resolved?.cdnUrl;
4411
- } catch {
4412
- return void 0;
4413
- }
4414
- }
4415
- /**
4416
- * Get peer dependencies for a package.
4417
- */
4418
- getPeerDependencies(packageName) {
4419
- return getPackagePeerDependencies(packageName, this.registry);
4420
- }
4421
- /**
4422
- * Create the current registry (default + custom).
4423
- */
4424
- getRegistry() {
4425
- return this.registry;
4426
- }
4427
- /**
4428
- * Get the current platform.
4429
- */
4430
- getPlatform() {
4431
- return this.options.platform;
4432
- }
4433
- /**
4434
- * Create a resolved dependency object.
4435
- */
4436
- createResolvedDependency(packageName, config, provider, version) {
4437
- return {
4438
- packageName,
4439
- version: version ?? this.extractVersionFromUrl(config.url) ?? "latest",
4440
- cdnUrl: config.url,
4441
- integrity: config.integrity,
4442
- global: config.global,
4443
- esm: config.esm ?? false,
4444
- provider
4445
2954
  };
4446
- }
4447
- /**
4448
- * Try to extract version from CDN URL.
4449
- */
4450
- extractVersionFromUrl(url) {
4451
- const versionMatch = url.match(/@(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
4452
- if (versionMatch) {
4453
- return versionMatch[1];
4454
- }
4455
- const versionMatch2 = url.match(/\/v?(\d+\.\d+\.\d+)\//);
4456
- if (versionMatch2) {
4457
- return versionMatch2[1];
4458
- }
4459
- return void 0;
4460
- }
4461
- };
2955
+ const outputPlaceholder = options?.placeholder ?? HYBRID_DATA_PLACEHOLDER;
2956
+ const inputPlaceholder = options?.inputPlaceholder ?? HYBRID_INPUT_PLACEHOLDER;
2957
+ return `
2958
+ <!-- Tool Data Injection (Hybrid Mode - Replace placeholders with JSON) -->
2959
+ <script>
2960
+ window.__mcpToolName = ${safeJson(toolName)};
2961
+ window.__mcpToolInput = "${inputPlaceholder}";
2962
+ window.__mcpToolOutput = "${outputPlaceholder}";
2963
+ window.__mcpStructuredContent = ${safeJson(structuredContent ?? null)};
2964
+ window.__mcpHybridError = null;
4462
2965
 
4463
- // libs/ui/src/bundler/file-cache/component-builder.ts
4464
- var ComponentBuilder = class {
4465
- storage;
4466
- esbuild = null;
4467
- constructor(storage) {
4468
- this.storage = storage;
4469
- }
4470
- /**
4471
- * Build a component from a file path.
4472
- */
4473
- async build(options) {
4474
- const startTime = performance.now();
4475
- const {
4476
- entryPath,
4477
- toolName,
4478
- externals = [],
4479
- dependencies = {},
4480
- bundleOptions = {},
4481
- platform = "unknown",
4482
- skipCache = false,
4483
- ssr = false,
4484
- ssrContext = {},
4485
- executeCode: executeCode3
4486
- } = options;
4487
- const absoluteEntryPath = (0, import_path3.resolve)(entryPath);
4488
- if (!(0, import_fs3.existsSync)(absoluteEntryPath)) {
4489
- throw new Error(`Entry file not found: ${absoluteEntryPath}`);
4490
- }
4491
- const hashResult = await calculateComponentHash({
4492
- entryPath: absoluteEntryPath,
4493
- externals,
4494
- dependencies,
4495
- bundleOptions
4496
- });
4497
- if (!skipCache) {
4498
- const cached = await this.storage.get(hashResult.hash);
4499
- if (cached) {
4500
- return {
4501
- manifest: cached,
4502
- cached: true,
4503
- buildTimeMs: performance.now() - startTime
4504
- };
4505
- }
4506
- }
4507
- const source = await (0, import_promises3.readFile)(absoluteEntryPath, "utf8");
4508
- const resolver = new DependencyResolver({ platform });
4509
- const resolvedDeps = [];
4510
- for (const pkg of externals) {
4511
- try {
4512
- const override = dependencies[pkg];
4513
- const resolved = resolver.resolve(pkg, override);
4514
- if (resolved) {
4515
- resolvedDeps.push(resolved);
2966
+ // Parse placeholders if they've been replaced with actual JSON
2967
+ (function() {
2968
+ var outputNotReplaced = false;
2969
+
2970
+ // Parse output placeholder
2971
+ var rawOutput = window.__mcpToolOutput;
2972
+ if (typeof rawOutput === 'string' && rawOutput !== "${outputPlaceholder}") {
2973
+ try {
2974
+ window.__mcpToolOutput = JSON.parse(rawOutput);
2975
+ } catch (e) {
2976
+ console.warn('[FrontMCP] Failed to parse injected output data:', e);
2977
+ window.__mcpToolOutput = null;
2978
+ window.__mcpHybridError = 'Failed to parse output data';
2979
+ }
2980
+ } else if (rawOutput === "${outputPlaceholder}") {
2981
+ // Placeholder not replaced - no data was injected
2982
+ window.__mcpToolOutput = null;
2983
+ outputNotReplaced = true;
4516
2984
  }
4517
- } catch (error) {
4518
- console.warn(`Failed to resolve external "${pkg}": ${error}`);
4519
- }
4520
- }
4521
- const allExternals = new Set(externals);
4522
- for (const dep of resolvedDeps) {
4523
- const entry = resolver.getRegistry()[dep.packageName];
4524
- if (entry?.providers) {
4525
- const providerConfig = Object.values(entry.providers)[0];
4526
- if (providerConfig?.peerDependencies) {
4527
- for (const peer of providerConfig.peerDependencies) {
4528
- if (!allExternals.has(peer)) {
4529
- allExternals.add(peer);
4530
- try {
4531
- const peerOverride = dependencies[peer];
4532
- const resolved = resolver.resolve(peer, peerOverride);
4533
- if (resolved) {
4534
- resolvedDeps.push(resolved);
4535
- }
4536
- } catch {
4537
- }
4538
- }
2985
+
2986
+ // Parse input placeholder
2987
+ var rawInput = window.__mcpToolInput;
2988
+ if (typeof rawInput === 'string' && rawInput !== "${inputPlaceholder}") {
2989
+ try {
2990
+ window.__mcpToolInput = JSON.parse(rawInput);
2991
+ } catch (e) {
2992
+ console.warn('[FrontMCP] Failed to parse injected input data:', e);
2993
+ window.__mcpToolInput = null;
4539
2994
  }
2995
+ } else if (rawInput === "${inputPlaceholder}") {
2996
+ window.__mcpToolInput = null;
4540
2997
  }
2998
+
2999
+ // Set error if output placeholder was not replaced (no data provided)
3000
+ if (outputNotReplaced) {
3001
+ window.__mcpHybridError = 'No data provided. The output placeholder was not replaced.';
3002
+ }
3003
+ })();
3004
+
3005
+ // Initialize FrontMCP context with appropriate loading/error state
3006
+ if (window.__frontmcp && window.__frontmcp.setContext) {
3007
+ window.__frontmcp.setContext({
3008
+ toolName: window.__mcpToolName,
3009
+ toolInput: window.__mcpToolInput,
3010
+ toolOutput: window.__mcpToolOutput,
3011
+ structuredContent: window.__mcpStructuredContent,
3012
+ loading: false,
3013
+ error: window.__mcpHybridError,
3014
+ });
4541
3015
  }
4542
- }
4543
- const importMap = createImportMap(resolvedDeps);
4544
- const bundleResult = await this.bundleComponent({
4545
- source,
4546
- entryPath: absoluteEntryPath,
4547
- externals: Array.from(allExternals),
4548
- bundleOptions
4549
- });
4550
- let ssrHtml;
4551
- if (ssr) {
4552
- ssrHtml = await this.renderSSR(bundleResult.code, ssrContext, resolvedDeps, executeCode3);
4553
- }
4554
- const manifest = {
4555
- version: "1.0",
4556
- buildId: (0, import_crypto3.randomUUID)(),
4557
- toolName,
4558
- entryPath: absoluteEntryPath,
4559
- contentHash: hashResult.hash,
4560
- dependencies: resolvedDeps,
4561
- outputs: {
4562
- code: bundleResult.code,
4563
- sourceMap: bundleResult.map,
4564
- ssrHtml
4565
- },
4566
- importMap,
4567
- metadata: {
4568
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4569
- buildTimeMs: performance.now() - startTime,
4570
- totalSize: Buffer.byteLength(bundleResult.code, "utf8"),
4571
- bundlerVersion: bundleResult.bundlerVersion
4572
- }
4573
- };
4574
- await this.storage.set(hashResult.hash, manifest);
4575
- return {
4576
- manifest,
4577
- cached: false,
4578
- buildTimeMs: performance.now() - startTime
4579
- };
4580
- }
4581
- /**
4582
- * Build multiple components.
4583
- */
4584
- async buildMany(options) {
4585
- return Promise.all(options.map((opt) => this.build(opt)));
4586
- }
4587
- /**
4588
- * Check if a component needs rebuilding.
4589
- */
4590
- async needsRebuild(options) {
4591
- const absoluteEntryPath = (0, import_path3.resolve)(options.entryPath);
4592
- const hashResult = await calculateComponentHash({
4593
- entryPath: absoluteEntryPath,
4594
- externals: options.externals,
4595
- dependencies: options.dependencies,
4596
- bundleOptions: options.bundleOptions
4597
- });
4598
- const cached = await this.storage.has(hashResult.hash);
4599
- return !cached;
4600
- }
4601
- /**
4602
- * Get a cached build if it exists.
4603
- */
4604
- async getCached(options) {
4605
- const absoluteEntryPath = (0, import_path3.resolve)(options.entryPath);
4606
- const hashResult = await calculateComponentHash({
4607
- entryPath: absoluteEntryPath,
4608
- externals: options.externals,
4609
- dependencies: options.dependencies,
4610
- bundleOptions: options.bundleOptions
4611
- });
4612
- return this.storage.get(hashResult.hash);
4613
- }
4614
- /**
4615
- * Invalidate a cached build.
4616
- */
4617
- async invalidate(contentHash) {
4618
- return this.storage.delete(contentHash);
4619
- }
4620
- /**
4621
- * Generate complete HTML for a built component.
4622
- */
4623
- generateHTML(manifest, minify = false) {
4624
- const parts = [];
4625
- const dependencyHtml = generateDependencyHTML(manifest.dependencies, { minify });
4626
- parts.push(dependencyHtml);
4627
- parts.push(`<script type="module">${manifest.outputs.code}</script>`);
4628
- return parts.join(minify ? "" : "\n");
3016
+ </script>`;
4629
3017
  }
4630
3018
  /**
4631
- * Bundle a component using esbuild.
3019
+ * Build component render script.
3020
+ * Wraps CommonJS code with module/exports shim to capture the component.
4632
3021
  */
4633
- async bundleComponent(options) {
4634
- const { source, entryPath, externals, bundleOptions } = options;
4635
- if (!this.esbuild) {
4636
- try {
4637
- this.esbuild = await import("esbuild");
4638
- } catch {
4639
- throw new Error("esbuild is required for component building. Install with: npm install esbuild");
3022
+ buildComponentRenderScript(componentCode, rootId, cdnType) {
3023
+ const wrappedCode = `
3024
+ // CommonJS module shim
3025
+ var module = { exports: {} };
3026
+ var exports = module.exports;
3027
+
3028
+ // Execute transpiled component code (CommonJS format)
3029
+ ${componentCode}
3030
+
3031
+ // Capture the component export
3032
+ window.__frontmcp_component = module.exports;
3033
+ `;
3034
+ if (cdnType === "umd") {
3035
+ return `
3036
+ <!-- Component Render Script (UMD - synchronous) -->
3037
+ <script>
3038
+ (function() {
3039
+ ${wrappedCode}
3040
+
3041
+ // Get the component
3042
+ var Component = window.__frontmcp_component.default || window.__frontmcp_component;
3043
+
3044
+ // Render the component
3045
+ var container = document.getElementById('${rootId}');
3046
+ if (container && window.ReactDOM && window.ReactDOM.createRoot) {
3047
+ var root = window.ReactDOM.createRoot(container);
3048
+ root.render(React.createElement(Component, {
3049
+ output: window.__mcpToolOutput,
3050
+ input: window.__mcpToolInput,
3051
+ }));
3052
+ } else if (container && window.ReactDOM && window.ReactDOM.render) {
3053
+ // Fallback for React 17
3054
+ window.ReactDOM.render(
3055
+ React.createElement(Component, {
3056
+ output: window.__mcpToolOutput,
3057
+ input: window.__mcpToolInput,
3058
+ }),
3059
+ container
3060
+ );
3061
+ }
3062
+ })();
3063
+ </script>`;
3064
+ } else {
3065
+ return `
3066
+ <!-- Component Render Script (ESM - waits for React) -->
3067
+ <script type="module">
3068
+ function renderComponent() {
3069
+ ${wrappedCode}
3070
+
3071
+ // Get the component
3072
+ var Component = window.__frontmcp_component.default || window.__frontmcp_component;
3073
+
3074
+ // Render the component
3075
+ var container = document.getElementById('${rootId}');
3076
+ if (container && window.ReactDOM && window.ReactDOM.createRoot) {
3077
+ var root = window.ReactDOM.createRoot(container);
3078
+ root.render(React.createElement(Component, {
3079
+ output: window.__mcpToolOutput,
3080
+ input: window.__mcpToolInput,
3081
+ }));
3082
+ }
4640
3083
  }
4641
- }
4642
- const ext = (0, import_path3.extname)(entryPath).toLowerCase();
4643
- const loader = ext === ".tsx" ? "tsx" : ext === ".ts" ? "ts" : ext === ".jsx" ? "jsx" : "js";
4644
- try {
4645
- const result = await this.esbuild.transform(source, {
4646
- loader,
4647
- format: "esm",
4648
- minify: bundleOptions.minify ?? process.env["NODE_ENV"] === "production",
4649
- sourcemap: bundleOptions.sourceMaps ? "inline" : false,
4650
- target: bundleOptions.target ?? "es2020",
4651
- treeShaking: bundleOptions.treeShake ?? true,
4652
- jsx: "automatic",
4653
- jsxImportSource: bundleOptions.jsxImportSource ?? "react",
4654
- // Mark externals for later import map resolution
4655
- banner: externals.length > 0 ? `/* externals: ${externals.join(", ")} */` : void 0
4656
- });
4657
- return {
4658
- code: result.code,
4659
- map: result.map || void 0,
4660
- bundlerVersion: this.esbuild.version
4661
- };
4662
- } catch (error) {
4663
- throw new Error(`Bundle failed for ${entryPath}: ${error}`);
3084
+
3085
+ // Wait for React to be ready
3086
+ if (window.__reactReady) {
3087
+ renderComponent();
3088
+ } else {
3089
+ window.addEventListener('react:ready', renderComponent);
3090
+ }
3091
+ </script>`;
4664
3092
  }
4665
3093
  }
4666
3094
  /**
4667
- * Perform server-side rendering.
3095
+ * Assemble the complete static HTML document.
4668
3096
  */
4669
- async renderSSR(code, context, dependencies, executeCode3) {
4670
- const hasReact = dependencies.some((d) => d.packageName === "react");
4671
- if (!hasReact) {
4672
- console.warn("SSR requires React as an external dependency");
4673
- return void 0;
4674
- }
4675
- try {
4676
- const React = await import("react");
4677
- const ReactDOMServer = await import("react-dom/server");
4678
- const exports2 = {};
4679
- const module2 = { exports: exports2 };
4680
- if (executeCode3) {
4681
- executeCode3(code, exports2, module2, React);
4682
- } else {
4683
- const fn = new Function("exports", "module", "React", code);
4684
- fn(exports2, module2, React);
4685
- }
4686
- const Component = module2.exports.default || module2.exports;
4687
- if (typeof Component !== "function") {
4688
- console.warn("SSR: No default component export found");
4689
- return void 0;
4690
- }
4691
- const element = React.createElement(Component, context);
4692
- return ReactDOMServer.renderToString(element);
4693
- } catch (error) {
4694
- console.warn(`SSR failed: ${error}`);
4695
- return void 0;
4696
- }
3097
+ assembleStaticHTML(parts) {
3098
+ return `<!DOCTYPE html>
3099
+ <html lang="en">
3100
+ <head>
3101
+ <title>${(0, import_utils.escapeHtml)(parts.title)}</title>
3102
+ ${parts.head}
3103
+ ${parts.reactRuntime}
3104
+ ${parts.frontmcpRuntime}
3105
+ ${parts.dataScript}
3106
+ </head>
3107
+ <body>
3108
+ <div id="${parts.rootId}" class="frontmcp-loading">
3109
+ <div class="frontmcp-spinner"></div>
3110
+ </div>
3111
+ ${parts.componentScript}
3112
+ </body>
3113
+ </html>`;
4697
3114
  }
4698
3115
  };
4699
- async function createFilesystemBuilder(cacheDir = ".frontmcp-cache/builds") {
4700
- const { FilesystemStorage: FilesystemStorage2 } = await Promise.resolve().then(() => (init_filesystem(), filesystem_exports));
4701
- const storage = new FilesystemStorage2({ cacheDir });
4702
- await storage.initialize();
4703
- return new ComponentBuilder(storage);
4704
- }
4705
- async function createRedisBuilder(redisClient, keyPrefix = "frontmcp:ui:build:") {
4706
- const { RedisStorage: RedisStorage2 } = await Promise.resolve().then(() => (init_redis(), redis_exports));
4707
- const storage = new RedisStorage2({
4708
- client: redisClient,
4709
- keyPrefix
4710
- });
4711
- await storage.initialize();
4712
- return new ComponentBuilder(storage);
3116
+ function createBundler(options) {
3117
+ return new InMemoryBundler(options);
4713
3118
  }
3119
+
3120
+ // libs/ui/src/bundler/index.ts
3121
+ var import_bundler4 = require("@frontmcp/uipack/bundler");
3122
+ var import_bundler5 = require("@frontmcp/uipack/bundler");
3123
+ var import_bundler6 = require("@frontmcp/uipack/bundler");
3124
+ var import_bundler7 = require("@frontmcp/uipack/bundler");
4714
3125
  // Annotate the CommonJS export names for ESM import in node:
4715
3126
  0 && (module.exports = {
3127
+ ALL_PLATFORMS,
4716
3128
  BundlerCache,
4717
3129
  ComponentBuilder,
4718
3130
  DEFAULT_BUNDLER_OPTIONS,
@@ -4722,6 +3134,8 @@ async function createRedisBuilder(redisClient, keyPrefix = "frontmcp:ui:build:")
4722
3134
  DEFAULT_STORAGE_OPTIONS,
4723
3135
  ExecutionError,
4724
3136
  FilesystemStorage,
3137
+ HYBRID_DATA_PLACEHOLDER,
3138
+ HYBRID_INPUT_PLACEHOLDER,
4725
3139
  InMemoryBundler,
4726
3140
  RedisStorage,
4727
3141
  STATIC_HTML_CDN,