@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
@@ -0,0 +1,3136 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // libs/ui/src/bundler/types.ts
9
+ var HYBRID_DATA_PLACEHOLDER = "__FRONTMCP_OUTPUT_PLACEHOLDER__";
10
+ var HYBRID_INPUT_PLACEHOLDER = "__FRONTMCP_INPUT_PLACEHOLDER__";
11
+ var DEFAULT_SECURITY_POLICY = {
12
+ allowedImports: [/^react$/, /^react-dom$/, /^react\/jsx-runtime$/, /^react\/jsx-dev-runtime$/, /^@frontmcp\/ui/],
13
+ blockedImports: [
14
+ /^fs$/,
15
+ /^fs\//,
16
+ /^net$/,
17
+ /^child_process$/,
18
+ /^os$/,
19
+ /^path$/,
20
+ /^crypto$/,
21
+ /^http$/,
22
+ /^https$/,
23
+ /^dgram$/,
24
+ /^dns$/,
25
+ /^cluster$/,
26
+ /^readline$/,
27
+ /^repl$/,
28
+ /^tls$/,
29
+ /^vm$/,
30
+ /^worker_threads$/
31
+ ],
32
+ maxBundleSize: 512e3,
33
+ // 500KB
34
+ maxTransformTime: 5e3,
35
+ // 5s
36
+ noEval: true,
37
+ noDynamicImports: true,
38
+ noRequire: true,
39
+ allowedGlobals: [
40
+ "console",
41
+ "Math",
42
+ "JSON",
43
+ "Date",
44
+ "Array",
45
+ "Object",
46
+ "String",
47
+ "Number",
48
+ "Boolean",
49
+ "Promise",
50
+ "Map",
51
+ "Set",
52
+ "WeakMap",
53
+ "WeakSet",
54
+ "Symbol",
55
+ "Reflect",
56
+ "Proxy",
57
+ "Error",
58
+ "TypeError",
59
+ "RangeError",
60
+ "SyntaxError",
61
+ "ReferenceError",
62
+ "parseInt",
63
+ "parseFloat",
64
+ "isNaN",
65
+ "isFinite",
66
+ "encodeURI",
67
+ "encodeURIComponent",
68
+ "decodeURI",
69
+ "decodeURIComponent",
70
+ "setTimeout",
71
+ "clearTimeout",
72
+ "setInterval",
73
+ "clearInterval",
74
+ "atob",
75
+ "btoa",
76
+ "Intl",
77
+ "TextEncoder",
78
+ "TextDecoder",
79
+ "URL",
80
+ "URLSearchParams",
81
+ "Uint8Array",
82
+ "Int8Array",
83
+ "Uint16Array",
84
+ "Int16Array",
85
+ "Uint32Array",
86
+ "Int32Array",
87
+ "Float32Array",
88
+ "Float64Array",
89
+ "BigInt",
90
+ "BigInt64Array",
91
+ "BigUint64Array",
92
+ "ArrayBuffer",
93
+ "SharedArrayBuffer",
94
+ "DataView",
95
+ "queueMicrotask"
96
+ ]
97
+ };
98
+ var DEFAULT_BUNDLE_OPTIONS = {
99
+ sourceType: "auto",
100
+ format: "iife",
101
+ minify: false,
102
+ sourceMaps: false,
103
+ externals: ["react", "react-dom"],
104
+ jsx: {
105
+ runtime: "automatic",
106
+ importSource: "react"
107
+ },
108
+ target: "es2020",
109
+ globalName: "Widget",
110
+ skipCache: false
111
+ };
112
+ var DEFAULT_BUNDLER_OPTIONS = {
113
+ defaultSecurity: DEFAULT_SECURITY_POLICY,
114
+ cache: {
115
+ maxSize: 100,
116
+ ttl: 3e5,
117
+ // 5 minutes
118
+ disabled: false
119
+ },
120
+ verbose: false,
121
+ esbuildOptions: {}
122
+ };
123
+ var ALL_PLATFORMS = [
124
+ "openai",
125
+ "claude",
126
+ "cursor",
127
+ "ext-apps",
128
+ "generic"
129
+ ];
130
+ var STATIC_HTML_CDN = {
131
+ /**
132
+ * ES modules from esm.sh (React 19, modern platforms)
133
+ */
134
+ esm: {
135
+ react: "https://esm.sh/react@19",
136
+ reactDom: "https://esm.sh/react-dom@19/client"
137
+ },
138
+ /**
139
+ * UMD builds from cdnjs (React 18.2, Claude only trusts cloudflare)
140
+ */
141
+ umd: {
142
+ react: "https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js",
143
+ reactDom: "https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"
144
+ },
145
+ /**
146
+ * Font CDN URLs
147
+ */
148
+ fonts: {
149
+ preconnect: ["https://fonts.googleapis.com", "https://fonts.gstatic.com"],
150
+ inter: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
151
+ }
152
+ };
153
+ function getCdnTypeForPlatform(platform) {
154
+ if (platform === "claude") return "umd";
155
+ return "esm";
156
+ }
157
+ var DEFAULT_STATIC_HTML_OPTIONS = {
158
+ sourceType: "auto",
159
+ targetPlatform: "auto",
160
+ minify: true,
161
+ skipCache: false,
162
+ rootId: "frontmcp-widget-root",
163
+ widgetAccessible: false,
164
+ externals: {
165
+ react: "cdn",
166
+ reactDom: "cdn",
167
+ tailwind: "cdn",
168
+ frontmcpUi: "inline"
169
+ },
170
+ // Universal mode defaults
171
+ universal: false,
172
+ contentType: "auto",
173
+ includeMarkdown: false,
174
+ includeMdx: false,
175
+ // Build mode defaults
176
+ buildMode: "static"
177
+ };
178
+
179
+ // libs/ui/src/bundler/bundler.ts
180
+ import { buildUIMeta } from "@frontmcp/uipack/adapters";
181
+ import { DEFAULT_THEME, buildThemeCss } from "@frontmcp/uipack/theme";
182
+ import {
183
+ BundlerCache,
184
+ createCacheKey,
185
+ hashContent,
186
+ validateSource,
187
+ validateSize,
188
+ mergePolicy,
189
+ throwOnViolations,
190
+ executeDefault,
191
+ ExecutionError
192
+ } from "@frontmcp/uipack/bundler";
193
+ import { escapeHtml } from "@frontmcp/uipack/utils";
194
+
195
+ // libs/ui/src/universal/types.ts
196
+ var UNIVERSAL_CDN = {
197
+ esm: {
198
+ reactMarkdown: "https://esm.sh/react-markdown@9",
199
+ mdxReact: "https://esm.sh/@mdx-js/react@3",
200
+ remarkGfm: "https://esm.sh/remark-gfm@4"
201
+ }
202
+ // Note: These libraries are not available on cdnjs
203
+ // For Claude, we use inline implementations
204
+ };
205
+ function detectContentType(source) {
206
+ if (typeof source === "function") {
207
+ return "react";
208
+ }
209
+ if (typeof source !== "string") {
210
+ return "html";
211
+ }
212
+ 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
213
+ /^function\s+\w+\s*\(/m.test(source);
214
+ const hasJsxTags = /<[A-Z][a-zA-Z]*/.test(source);
215
+ const hasMarkdown = /^#{1,6}\s/m.test(source) || /^\*\s/m.test(source) || /^-\s/m.test(source) || /^\d+\.\s/m.test(source);
216
+ if (hasModuleSyntax && hasJsxTags) {
217
+ return "react";
218
+ }
219
+ if (hasJsxTags && hasMarkdown && !hasModuleSyntax) {
220
+ return "mdx";
221
+ }
222
+ if (hasMarkdown || /\*\*[^*]+\*\*/.test(source) || /\[[^\]]+\]\([^)]+\)/.test(source)) {
223
+ return "markdown";
224
+ }
225
+ if (hasJsxTags && !hasModuleSyntax) {
226
+ return "mdx";
227
+ }
228
+ return "html";
229
+ }
230
+
231
+ // libs/ui/src/universal/cached-runtime.ts
232
+ import { getMCPBridgeScript } from "@frontmcp/uipack/runtime";
233
+ import { buildUIComponentsRuntime as buildBrowserUIComponents } from "@frontmcp/uipack/build";
234
+ var RUNTIME_PLACEHOLDERS = {
235
+ /** Placeholder for transpiled component code */
236
+ COMPONENT_CODE: "/*__FRONTMCP_COMPONENT_CODE__*/",
237
+ /** Placeholder for data injection */
238
+ DATA_INJECTION: "/*__FRONTMCP_DATA_INJECTION__*/",
239
+ /** Placeholder for custom components */
240
+ CUSTOM_COMPONENTS: "/*__FRONTMCP_CUSTOM_COMPONENTS__*/"
241
+ };
242
+ var runtimeCache = /* @__PURE__ */ new Map();
243
+ var DEFAULT_CACHE_CONFIG = {
244
+ maxEntries: 10,
245
+ ttl: 0
246
+ // Forever by default
247
+ };
248
+ function generateCacheKey(options) {
249
+ const securityKey = options.contentSecurity ? [
250
+ options.contentSecurity.allowUnsafeLinks ? "unsafeLinks" : "",
251
+ options.contentSecurity.allowInlineScripts ? "unsafeScripts" : "",
252
+ options.contentSecurity.bypassSanitization ? "bypass" : ""
253
+ ].filter(Boolean).join("+") || "secure" : "secure";
254
+ return [
255
+ options.cdnType,
256
+ options.includeMarkdown ? "md" : "",
257
+ options.includeMdx ? "mdx" : "",
258
+ options.minify ? "min" : "",
259
+ options.includeBridge ? "bridge" : "",
260
+ securityKey
261
+ ].filter(Boolean).join(":");
262
+ }
263
+ function buildStoreRuntime() {
264
+ return `
265
+ // FrontMCP Store (Vendor)
266
+ (function() {
267
+ var state = {
268
+ toolName: null,
269
+ input: null,
270
+ output: null,
271
+ content: null,
272
+ structuredContent: null,
273
+ loading: false,
274
+ error: null
275
+ };
276
+
277
+ var listeners = new Set();
278
+
279
+ window.__frontmcp = {
280
+ getState: function() { return state; },
281
+ setState: function(partial) {
282
+ state = Object.assign({}, state, partial);
283
+ listeners.forEach(function(fn) { fn(); });
284
+ },
285
+ subscribe: function(fn) {
286
+ listeners.add(fn);
287
+ return function() { listeners.delete(fn); };
288
+ },
289
+ reset: function() {
290
+ state = {
291
+ toolName: null,
292
+ input: null,
293
+ output: null,
294
+ content: null,
295
+ structuredContent: null,
296
+ loading: false,
297
+ error: null
298
+ };
299
+ },
300
+ context: state,
301
+ setContext: function(ctx) {
302
+ this.setState(ctx);
303
+ },
304
+ // Dynamic mode: update output and re-render
305
+ updateOutput: function(output) {
306
+ this.setState({ output: output, loading: false });
307
+ // Also update the global window variable for compatibility
308
+ window.__mcpToolOutput = output;
309
+ },
310
+ // Dynamic mode: update input and re-render
311
+ updateInput: function(input) {
312
+ this.setState({ input: input });
313
+ window.__mcpToolInput = input;
314
+ }
315
+ };
316
+
317
+ // React hooks
318
+ window.useFrontMCPStore = function() {
319
+ var store = window.__frontmcp;
320
+ return React.useSyncExternalStore(
321
+ store.subscribe,
322
+ store.getState,
323
+ store.getState
324
+ );
325
+ };
326
+
327
+ window.useToolOutput = function() {
328
+ return window.useFrontMCPStore().output;
329
+ };
330
+
331
+ window.useToolInput = function() {
332
+ return window.useFrontMCPStore().input;
333
+ };
334
+
335
+ window.useContent = function() {
336
+ return window.useFrontMCPStore().content;
337
+ };
338
+
339
+ // Connect to MCP Bridge for platform data detection
340
+ function initFromBridge() {
341
+ // Check for data from mcpBridge (handles OpenAI, ext-apps, etc.)
342
+ if (window.mcpBridge && window.mcpBridge.toolOutput != null) {
343
+ window.__frontmcp.setState({
344
+ output: window.mcpBridge.toolOutput,
345
+ loading: false
346
+ });
347
+ }
348
+
349
+ // Subscribe to bridge updates via onToolResult
350
+ if (window.mcpBridge && window.mcpBridge.onToolResult) {
351
+ window.mcpBridge.onToolResult(function(result) {
352
+ window.__frontmcp.updateOutput(result);
353
+ });
354
+ }
355
+ }
356
+
357
+ // Initialize from bridge when ready
358
+ if (window.mcpBridge) {
359
+ initFromBridge();
360
+ } else {
361
+ // Wait for bridge to be ready
362
+ window.addEventListener('mcp:bridge-ready', initFromBridge);
363
+ }
364
+ })();
365
+ `;
366
+ }
367
+ function buildRequireShim() {
368
+ return `
369
+ // Module Require Shim (Vendor)
370
+ (function() {
371
+ window.__moduleCache = {};
372
+ window.require = function(moduleName) {
373
+ if (window.__moduleCache[moduleName]) {
374
+ return window.__moduleCache[moduleName];
375
+ }
376
+
377
+ var moduleMap = {
378
+ 'react': function() { return window.React; },
379
+ 'react-dom': function() { return window.ReactDOM; },
380
+ 'react-dom/client': function() { return window.ReactDOM; },
381
+ 'react/jsx-runtime': function() { return window.jsx_runtime_namespaceObject; },
382
+ 'react/jsx-dev-runtime': function() { return window.jsx_runtime_namespaceObject; },
383
+ '@frontmcp/ui': function() { return window.frontmcp_ui_namespaceObject; },
384
+ '@frontmcp/ui/react': function() { return window.frontmcp_ui_namespaceObject; }
385
+ };
386
+
387
+ var resolver = moduleMap[moduleName];
388
+ if (resolver) {
389
+ var mod = resolver();
390
+ window.__moduleCache[moduleName] = mod;
391
+ return mod;
392
+ }
393
+
394
+ console.warn('[FrontMCP] Unknown module:', moduleName);
395
+ return {};
396
+ };
397
+ })();
398
+ `;
399
+ }
400
+ function buildInlineMarkdownParser(options) {
401
+ const allowUnsafeLinks = options?.contentSecurity?.bypassSanitization || options?.contentSecurity?.allowUnsafeLinks;
402
+ return `
403
+ // Inline Markdown Parser (Vendor)
404
+ (function() {
405
+ // XSS protection settings (configured at build time)
406
+ // Set to true if contentSecurity.allowUnsafeLinks or bypassSanitization is enabled
407
+ var __allowUnsafeLinks = ${allowUnsafeLinks ? "true" : "false"};
408
+
409
+ // URL scheme validation to prevent XSS via javascript: URLs
410
+ function isSafeUrl(url) {
411
+ // If unsafe links are explicitly allowed, skip validation
412
+ if (__allowUnsafeLinks) return true;
413
+ if (!url) return false;
414
+ var lower = url.toLowerCase().trim();
415
+ return lower.startsWith('http://') ||
416
+ lower.startsWith('https://') ||
417
+ lower.startsWith('/') ||
418
+ lower.startsWith('#') ||
419
+ lower.startsWith('mailto:');
420
+ }
421
+
422
+ function parseMarkdown(md) {
423
+ var html = md;
424
+ html = html.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
425
+ html = html.replace(/^######\\s+(.*)$/gm, '<h6>$1</h6>');
426
+ html = html.replace(/^#####\\s+(.*)$/gm, '<h5>$1</h5>');
427
+ html = html.replace(/^####\\s+(.*)$/gm, '<h4>$1</h4>');
428
+ html = html.replace(/^###\\s+(.*)$/gm, '<h3>$1</h3>');
429
+ html = html.replace(/^##\\s+(.*)$/gm, '<h2>$1</h2>');
430
+ html = html.replace(/^#\\s+(.*)$/gm, '<h1>$1</h1>');
431
+ html = html.replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, '<strong><em>$1</em></strong>');
432
+ html = html.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');
433
+ html = html.replace(/\\*(.+?)\\*/g, '<em>$1</em>');
434
+ html = html.replace(/\`([^\`]+)\`/g, '<code>$1</code>');
435
+ // Links - validate URL scheme to prevent XSS (unless bypassed)
436
+ html = html.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, function(match, text, url) {
437
+ return isSafeUrl(url) ? '<a href="' + url + '">' + text + '</a>' : text;
438
+ });
439
+ html = html.replace(/^[-*]\\s+(.*)$/gm, '<li>$1</li>');
440
+ html = html.replace(/\\n\\n+/g, '</p><p>');
441
+ html = '<p>' + html + '</p>';
442
+ return html;
443
+ }
444
+
445
+ window.__frontmcp.parseMarkdown = parseMarkdown;
446
+
447
+ window.ReactMarkdown = function(props) {
448
+ var html = parseMarkdown(props.children || '');
449
+ return React.createElement('div', {
450
+ className: 'frontmcp-markdown prose',
451
+ dangerouslySetInnerHTML: { __html: html }
452
+ });
453
+ };
454
+ })();
455
+ `;
456
+ }
457
+ function buildRenderersRuntime(options) {
458
+ const bypassSanitization = options?.contentSecurity?.bypassSanitization;
459
+ const allowInlineScripts = bypassSanitization || options?.contentSecurity?.allowInlineScripts;
460
+ return `
461
+ // Universal Renderers (Vendor)
462
+ (function() {
463
+ var renderers = {};
464
+
465
+ // XSS protection settings (configured at build time)
466
+ // Set to true if contentSecurity.allowInlineScripts or bypassSanitization is enabled
467
+ var __allowInlineScripts = ${allowInlineScripts ? "true" : "false"};
468
+
469
+ renderers.html = {
470
+ type: 'html',
471
+ priority: 0,
472
+ canHandle: function(c) { return c.type === 'html'; },
473
+ render: function(c, ctx) {
474
+ var html = c.source;
475
+ // Apply XSS protection unless bypassed
476
+ if (!__allowInlineScripts) {
477
+ // Remove script tags and event handlers to prevent XSS
478
+ html = html.replace(/<script[^>]*>[\\s\\S]*?<\\/script>/gi, '');
479
+ html = html.replace(/\\s+on\\w+\\s*=/gi, ' data-removed-handler=');
480
+ }
481
+ return React.createElement('div', {
482
+ className: 'frontmcp-html-content',
483
+ dangerouslySetInnerHTML: { __html: html }
484
+ });
485
+ }
486
+ };
487
+
488
+ renderers.markdown = {
489
+ type: 'markdown',
490
+ priority: 10,
491
+ canHandle: function(c) {
492
+ if (c.type === 'markdown') return true;
493
+ if (typeof c.source !== 'string') return false;
494
+ var s = c.source;
495
+ return /^#{1,6}\\s/m.test(s) || /^[-*]\\s/m.test(s) || /\\*\\*[^*]+\\*\\*/.test(s);
496
+ },
497
+ render: function(c, ctx) {
498
+ if (window.ReactMarkdown) {
499
+ return React.createElement(window.ReactMarkdown, {
500
+ children: c.source,
501
+ components: Object.assign({}, ctx.components, c.components)
502
+ });
503
+ }
504
+ var html = window.__frontmcp.parseMarkdown ? window.__frontmcp.parseMarkdown(c.source) : c.source;
505
+ return React.createElement('div', {
506
+ className: 'frontmcp-markdown prose',
507
+ dangerouslySetInnerHTML: { __html: html }
508
+ });
509
+ }
510
+ };
511
+
512
+ renderers.react = {
513
+ type: 'react',
514
+ priority: 30,
515
+ canHandle: function(c) { return c.type === 'react' || typeof c.source === 'function'; },
516
+ render: function(c, ctx) {
517
+ var Component = c.source;
518
+ var props = Object.assign({
519
+ output: ctx.output,
520
+ input: ctx.input,
521
+ state: ctx.state,
522
+ data: ctx.output // Alias for convenience
523
+ }, c.props);
524
+ return React.createElement(Component, props);
525
+ }
526
+ };
527
+
528
+ renderers.mdx = {
529
+ type: 'mdx',
530
+ priority: 20,
531
+ canHandle: function(c) {
532
+ if (c.type === 'mdx') return true;
533
+ if (typeof c.source !== 'string') return false;
534
+ var s = c.source;
535
+ return /<[A-Z][a-zA-Z]*/.test(s) && /^#{1,6}\\s/m.test(s);
536
+ },
537
+ render: function(c, ctx) {
538
+ if (typeof c.compiledContent === 'function') {
539
+ var MDXContent = c.compiledContent;
540
+ return React.createElement(MDXContent, {
541
+ output: ctx.output,
542
+ input: ctx.input,
543
+ components: Object.assign({}, ctx.components, c.components)
544
+ });
545
+ }
546
+ return React.createElement('div', { className: 'frontmcp-mdx-fallback' }, [
547
+ React.createElement('div', {
548
+ key: 'warn',
549
+ className: 'bg-yellow-50 border border-yellow-200 rounded p-2 mb-2 text-sm text-yellow-800'
550
+ }, 'MDX requires pre-compilation. Showing raw content.'),
551
+ React.createElement('pre', {
552
+ key: 'pre',
553
+ className: 'bg-gray-100 p-4 rounded text-sm overflow-auto'
554
+ }, c.source)
555
+ ]);
556
+ }
557
+ };
558
+
559
+ var sortedRenderers = [renderers.react, renderers.mdx, renderers.markdown, renderers.html];
560
+
561
+ window.__frontmcp.detectRenderer = function(content) {
562
+ if (content.type && renderers[content.type]) {
563
+ return renderers[content.type];
564
+ }
565
+ for (var i = 0; i < sortedRenderers.length; i++) {
566
+ if (sortedRenderers[i].canHandle(content)) {
567
+ return sortedRenderers[i];
568
+ }
569
+ }
570
+ return renderers.html;
571
+ };
572
+
573
+ window.__frontmcp.renderContent = function(content, context) {
574
+ var renderer = window.__frontmcp.detectRenderer(content);
575
+ return renderer.render(content, context);
576
+ };
577
+
578
+ window.__frontmcp.renderers = renderers;
579
+ })();
580
+ `;
581
+ }
582
+ function buildUIComponentsRuntime() {
583
+ return buildBrowserUIComponents();
584
+ }
585
+ function buildUniversalAppRuntime() {
586
+ return `
587
+ // Universal App (Vendor)
588
+ (function() {
589
+ var LoadingSpinner = function() {
590
+ return React.createElement('div', {
591
+ className: 'frontmcp-loading flex items-center justify-center min-h-[200px]'
592
+ }, React.createElement('div', {
593
+ className: 'frontmcp-spinner w-6 h-6 border-2 border-gray-200 border-t-blue-500 rounded-full animate-spin'
594
+ }));
595
+ };
596
+
597
+ var ErrorDisplay = function(props) {
598
+ return React.createElement('div', {
599
+ className: 'frontmcp-error bg-red-50 border border-red-200 rounded-lg p-4 text-red-800'
600
+ }, [
601
+ React.createElement('div', { key: 'title', className: 'font-medium' }, 'Error'),
602
+ React.createElement('div', { key: 'msg', className: 'text-sm mt-1' }, props.error)
603
+ ]);
604
+ };
605
+
606
+ var EmptyState = function() {
607
+ return React.createElement('div', {
608
+ className: 'frontmcp-empty text-gray-500 text-center py-8'
609
+ }, 'No content to display');
610
+ };
611
+
612
+ window.__frontmcp.UniversalApp = function(props) {
613
+ var state = window.useFrontMCPStore();
614
+
615
+ if (state.loading) {
616
+ return props.fallback || React.createElement(LoadingSpinner);
617
+ }
618
+
619
+ if (state.error) {
620
+ var ErrorComp = props.errorFallback || ErrorDisplay;
621
+ return React.createElement(ErrorComp, { error: state.error });
622
+ }
623
+
624
+ var content = props.content || state.content;
625
+
626
+ if (!content) {
627
+ return React.createElement(EmptyState);
628
+ }
629
+
630
+ var context = {
631
+ output: state.output,
632
+ input: state.input,
633
+ state: state,
634
+ components: props.components || {}
635
+ };
636
+
637
+ var rendered = window.__frontmcp.renderContent(content, context);
638
+ return React.createElement('div', { className: 'frontmcp-content' }, rendered);
639
+ };
640
+
641
+ window.__frontmcp.LoadingSpinner = LoadingSpinner;
642
+ window.__frontmcp.ErrorDisplay = ErrorDisplay;
643
+ window.__frontmcp.EmptyState = EmptyState;
644
+ })();
645
+ `;
646
+ }
647
+ function buildComponentWrapper() {
648
+ return `
649
+ // Component Execution (App Chunk)
650
+ (function() {
651
+ ${RUNTIME_PLACEHOLDERS.COMPONENT_CODE}
652
+ })();
653
+ `;
654
+ }
655
+ function buildDataInjectionWrapper() {
656
+ return `
657
+ // Data Injection (App Chunk)
658
+ (function() {
659
+ ${RUNTIME_PLACEHOLDERS.DATA_INJECTION}
660
+ })();
661
+ `;
662
+ }
663
+ function buildCustomComponentsWrapper() {
664
+ return `
665
+ // Custom Components (App Chunk)
666
+ (function() {
667
+ ${RUNTIME_PLACEHOLDERS.CUSTOM_COMPONENTS}
668
+ })();
669
+ `;
670
+ }
671
+ function buildCdnImports(options) {
672
+ const parts = [];
673
+ if (options.cdnType === "esm") {
674
+ if (options.includeMarkdown) {
675
+ parts.push(`
676
+ <script type="module">
677
+ import ReactMarkdown from '${UNIVERSAL_CDN.esm.reactMarkdown}';
678
+ window.ReactMarkdown = ReactMarkdown;
679
+ </script>`);
680
+ }
681
+ if (options.includeMdx) {
682
+ parts.push(`
683
+ <script type="module">
684
+ import { MDXProvider } from '${UNIVERSAL_CDN.esm.mdxReact}';
685
+ window.MDXProvider = MDXProvider;
686
+ </script>`);
687
+ }
688
+ }
689
+ return parts.join("\n");
690
+ }
691
+ function getCachedRuntime(options, config = {}) {
692
+ const cacheKey = generateCacheKey(options);
693
+ const cacheConfig = { ...DEFAULT_CACHE_CONFIG, ...config };
694
+ const cached = runtimeCache.get(cacheKey);
695
+ if (cached) {
696
+ if (cacheConfig.ttl === 0 || Date.now() - cached.cachedAt < cacheConfig.ttl) {
697
+ return {
698
+ vendorScript: cached.script,
699
+ appTemplate: buildAppTemplate(),
700
+ cdnImports: cached.cdnImports,
701
+ vendorSize: cached.size,
702
+ cached: true,
703
+ cacheKey
704
+ };
705
+ }
706
+ runtimeCache.delete(cacheKey);
707
+ }
708
+ const vendorParts = [];
709
+ if (options.includeBridge) {
710
+ vendorParts.push(getMCPBridgeScript());
711
+ }
712
+ vendorParts.push(buildStoreRuntime(), buildRequireShim());
713
+ if (options.cdnType === "umd" || options.includeMarkdown) {
714
+ vendorParts.push(buildInlineMarkdownParser(options));
715
+ }
716
+ vendorParts.push(buildRenderersRuntime(options));
717
+ vendorParts.push(buildUIComponentsRuntime());
718
+ vendorParts.push(buildUniversalAppRuntime());
719
+ let vendorScript = vendorParts.join("\n");
720
+ if (options.minify) {
721
+ vendorScript = minifyScript(vendorScript);
722
+ }
723
+ const cdnImports = buildCdnImports(options);
724
+ const entry = {
725
+ script: vendorScript,
726
+ cdnImports,
727
+ size: vendorScript.length,
728
+ cacheKey,
729
+ cachedAt: Date.now()
730
+ };
731
+ if (runtimeCache.size >= cacheConfig.maxEntries) {
732
+ const oldestKey = runtimeCache.keys().next().value;
733
+ if (oldestKey) {
734
+ runtimeCache.delete(oldestKey);
735
+ }
736
+ }
737
+ runtimeCache.set(cacheKey, entry);
738
+ return {
739
+ vendorScript,
740
+ appTemplate: buildAppTemplate(),
741
+ cdnImports,
742
+ vendorSize: vendorScript.length,
743
+ cached: false,
744
+ cacheKey
745
+ };
746
+ }
747
+ function buildAppTemplate() {
748
+ return [buildCustomComponentsWrapper(), buildComponentWrapper(), buildDataInjectionWrapper()].join("\n");
749
+ }
750
+ function minifyScript(script) {
751
+ return script.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/[^\n]*$/gm, "").replace(/\n\s*\n/g, "\n").replace(/^\s+/gm, "").trim();
752
+ }
753
+ function buildAppScript(appTemplate, componentCode, dataInjection, customComponents = "") {
754
+ 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);
755
+ }
756
+ var DEFAULT_OUTPUT_PLACEHOLDER = "__FRONTMCP_OUTPUT_PLACEHOLDER__";
757
+ var DEFAULT_INPUT_PLACEHOLDER = "__FRONTMCP_INPUT_PLACEHOLDER__";
758
+ function buildDataInjectionCode(toolName, input, output, structuredContent, contentType, source, hasComponent, options) {
759
+ const buildMode = options?.buildMode ?? "static";
760
+ const cdnType = options?.cdnType ?? "esm";
761
+ switch (buildMode) {
762
+ case "dynamic":
763
+ return buildDynamicDataInjectionCode(
764
+ toolName,
765
+ input,
766
+ output,
767
+ structuredContent,
768
+ contentType,
769
+ source,
770
+ hasComponent,
771
+ cdnType,
772
+ options?.dynamicOptions
773
+ );
774
+ case "hybrid":
775
+ return buildHybridDataInjectionCode(
776
+ toolName,
777
+ structuredContent,
778
+ contentType,
779
+ source,
780
+ hasComponent,
781
+ options?.hybridOptions
782
+ );
783
+ default:
784
+ return buildStaticDataInjectionCode(
785
+ toolName,
786
+ input,
787
+ output,
788
+ structuredContent,
789
+ contentType,
790
+ source,
791
+ hasComponent
792
+ );
793
+ }
794
+ }
795
+ function buildStaticDataInjectionCode(toolName, input, output, structuredContent, contentType, source, hasComponent) {
796
+ const safeJson = (value) => {
797
+ try {
798
+ return JSON.stringify(value);
799
+ } catch {
800
+ return "null";
801
+ }
802
+ };
803
+ if (hasComponent) {
804
+ return `
805
+ // Static Mode - Data baked at build time
806
+ window.__frontmcp.setState({
807
+ toolName: ${safeJson(toolName)},
808
+ input: ${safeJson(input ?? null)},
809
+ output: ${safeJson(output ?? null)},
810
+ structuredContent: ${safeJson(structuredContent ?? null)},
811
+ content: {
812
+ type: 'react',
813
+ source: window.__frontmcp_component
814
+ },
815
+ loading: false,
816
+ error: null
817
+ });`;
818
+ }
819
+ return `
820
+ // Static Mode - Data baked at build time
821
+ window.__frontmcp.setState({
822
+ toolName: ${safeJson(toolName)},
823
+ input: ${safeJson(input ?? null)},
824
+ output: ${safeJson(output ?? null)},
825
+ structuredContent: ${safeJson(structuredContent ?? null)},
826
+ content: {
827
+ type: ${safeJson(contentType)},
828
+ source: ${safeJson(source)}
829
+ },
830
+ loading: false,
831
+ error: null
832
+ });`;
833
+ }
834
+ function buildDynamicDataInjectionCode(toolName, input, output, structuredContent, contentType, source, hasComponent, cdnType, dynamicOptions) {
835
+ if (cdnType === "umd") {
836
+ return buildDynamicWithPlaceholdersCode(
837
+ toolName,
838
+ structuredContent,
839
+ contentType,
840
+ source,
841
+ hasComponent,
842
+ dynamicOptions
843
+ );
844
+ }
845
+ return buildDynamicWithSubscriptionCode(
846
+ toolName,
847
+ input,
848
+ output,
849
+ structuredContent,
850
+ contentType,
851
+ source,
852
+ hasComponent,
853
+ dynamicOptions
854
+ );
855
+ }
856
+ function buildDynamicWithPlaceholdersCode(toolName, structuredContent, contentType, source, hasComponent, dynamicOptions) {
857
+ const safeJson = (value) => {
858
+ try {
859
+ return JSON.stringify(value);
860
+ } catch {
861
+ return "null";
862
+ }
863
+ };
864
+ const outputPlaceholder = DEFAULT_OUTPUT_PLACEHOLDER;
865
+ const inputPlaceholder = DEFAULT_INPUT_PLACEHOLDER;
866
+ const includeInitialData = dynamicOptions?.includeInitialData ?? true;
867
+ const contentBlock = hasComponent ? `content: { type: 'react', source: window.__frontmcp_component }` : `content: { type: ${safeJson(contentType)}, source: ${safeJson(source)} }`;
868
+ return `
869
+ // Dynamic Mode - Placeholder-based for non-OpenAI platforms
870
+ var __outputRaw = "${outputPlaceholder}";
871
+ var __inputRaw = "${inputPlaceholder}";
872
+ var __output = null;
873
+ var __input = null;
874
+ var __error = null;
875
+ var __outputNotReplaced = false;
876
+ var __includeInitialData = ${includeInitialData};
877
+
878
+ // Parse output placeholder
879
+ if (typeof __outputRaw === 'string' && __outputRaw !== "${outputPlaceholder}") {
880
+ try { __output = JSON.parse(__outputRaw); } catch (e) {
881
+ console.warn('[FrontMCP] Failed to parse output:', e);
882
+ __error = 'Failed to parse output data';
883
+ }
884
+ } else if (__outputRaw === "${outputPlaceholder}") {
885
+ __outputNotReplaced = true;
886
+ }
887
+
888
+ // Parse input placeholder
889
+ if (typeof __inputRaw === 'string' && __inputRaw !== "${inputPlaceholder}") {
890
+ try { __input = JSON.parse(__inputRaw); } catch (e) { console.warn('[FrontMCP] Failed to parse input:', e); }
891
+ }
892
+
893
+ // Handle placeholder not replaced - show error if expecting initial data
894
+ if (__outputNotReplaced && __includeInitialData) {
895
+ __error = 'No data provided. The output placeholder was not replaced.';
896
+ }
897
+
898
+ window.__frontmcp.setState({
899
+ toolName: ${safeJson(toolName)},
900
+ input: __input,
901
+ output: __output,
902
+ structuredContent: ${safeJson(structuredContent ?? null)},
903
+ ${contentBlock},
904
+ loading: !__includeInitialData && __output === null && !__error,
905
+ error: __error
906
+ });`;
907
+ }
908
+ function buildDynamicWithSubscriptionCode(toolName, input, output, structuredContent, contentType, source, hasComponent, dynamicOptions) {
909
+ const safeJson = (value) => {
910
+ try {
911
+ return JSON.stringify(value);
912
+ } catch {
913
+ return "null";
914
+ }
915
+ };
916
+ const includeInitialData = dynamicOptions?.includeInitialData ?? true;
917
+ const subscribeToUpdates = dynamicOptions?.subscribeToUpdates ?? true;
918
+ const contentBlock = hasComponent ? `content: { type: 'react', source: window.__frontmcp_component }` : `content: { type: ${safeJson(contentType)}, source: ${safeJson(source)} }`;
919
+ const initialState = includeInitialData ? `{
920
+ toolName: ${safeJson(toolName)},
921
+ input: ${safeJson(input ?? null)},
922
+ output: ${safeJson(output ?? null)},
923
+ structuredContent: ${safeJson(structuredContent ?? null)},
924
+ ${contentBlock},
925
+ loading: false,
926
+ error: null
927
+ }` : `{
928
+ toolName: ${safeJson(toolName)},
929
+ input: ${safeJson(input ?? null)},
930
+ output: null,
931
+ structuredContent: ${safeJson(structuredContent ?? null)},
932
+ ${contentBlock},
933
+ loading: true,
934
+ error: null
935
+ }`;
936
+ const subscriptionBlock = subscribeToUpdates ? `
937
+ // Subscribe to platform tool result events
938
+ (function() {
939
+ function subscribeToUpdates() {
940
+ if (window.openai && window.openai.canvas && window.openai.canvas.onToolResult) {
941
+ window.openai.canvas.onToolResult(function(result) {
942
+ window.__frontmcp.updateOutput(result);
943
+ window.dispatchEvent(new CustomEvent('frontmcp:toolResult', { detail: result }));
944
+ });
945
+ }
946
+ }
947
+ if (document.readyState === 'loading') {
948
+ document.addEventListener('DOMContentLoaded', subscribeToUpdates);
949
+ } else {
950
+ subscribeToUpdates();
951
+ }
952
+ })();` : "";
953
+ return `
954
+ // Dynamic Mode - OpenAI Subscription
955
+ window.__frontmcp.setState(${initialState});
956
+ ${subscriptionBlock}`;
957
+ }
958
+ function buildHybridDataInjectionCode(toolName, structuredContent, contentType, source, hasComponent, hybridOptions) {
959
+ const safeJson = (value) => {
960
+ try {
961
+ return JSON.stringify(value);
962
+ } catch {
963
+ return "null";
964
+ }
965
+ };
966
+ const outputPlaceholder = hybridOptions?.placeholder ?? DEFAULT_OUTPUT_PLACEHOLDER;
967
+ const inputPlaceholder = hybridOptions?.inputPlaceholder ?? DEFAULT_INPUT_PLACEHOLDER;
968
+ const contentBlock = hasComponent ? `content: { type: 'react', source: window.__frontmcp_component }` : `content: { type: ${safeJson(contentType)}, source: ${safeJson(source)} }`;
969
+ return `
970
+ // Hybrid Mode - Placeholders replaced at runtime
971
+ var __outputRaw = "${outputPlaceholder}";
972
+ var __inputRaw = "${inputPlaceholder}";
973
+ var __output = null;
974
+ var __input = null;
975
+ var __error = null;
976
+ var __outputNotReplaced = false;
977
+
978
+ // Parse output placeholder
979
+ if (typeof __outputRaw === 'string' && __outputRaw !== "${outputPlaceholder}") {
980
+ try { __output = JSON.parse(__outputRaw); } catch (e) {
981
+ console.warn('[FrontMCP] Failed to parse output:', e);
982
+ __error = 'Failed to parse output data';
983
+ }
984
+ } else if (__outputRaw === "${outputPlaceholder}") {
985
+ // Placeholder not replaced - no data was injected
986
+ __outputNotReplaced = true;
987
+ }
988
+
989
+ // Parse input placeholder
990
+ if (typeof __inputRaw === 'string' && __inputRaw !== "${inputPlaceholder}") {
991
+ try { __input = JSON.parse(__inputRaw); } catch (e) { console.warn('[FrontMCP] Failed to parse input:', e); }
992
+ }
993
+
994
+ // Set error if output placeholder was not replaced (no data provided)
995
+ if (__outputNotReplaced) {
996
+ __error = 'No data provided. The output placeholder was not replaced.';
997
+ }
998
+
999
+ window.__frontmcp.setState({
1000
+ toolName: ${safeJson(toolName)},
1001
+ input: __input,
1002
+ output: __output,
1003
+ structuredContent: ${safeJson(structuredContent ?? null)},
1004
+ ${contentBlock},
1005
+ loading: false,
1006
+ error: __error
1007
+ });`;
1008
+ }
1009
+ function buildComponentCode(transpiledCode) {
1010
+ return `
1011
+ // CommonJS module shim
1012
+ var module = { exports: {} };
1013
+ var exports = module.exports;
1014
+
1015
+ // Execute transpiled component
1016
+ ${transpiledCode}
1017
+
1018
+ // Capture component
1019
+ window.__frontmcp_component = module.exports.default || module.exports;`;
1020
+ }
1021
+
1022
+ // libs/ui/src/bundler/bundler.ts
1023
+ import {
1024
+ buildCDNScriptTag,
1025
+ CLOUDFLARE_CDN,
1026
+ buildUIComponentsRuntime as buildFallbackUIComponents
1027
+ } from "@frontmcp/uipack/build";
1028
+
1029
+ // libs/ui/src/bundler/browser-components.ts
1030
+ import * as path from "path";
1031
+ var cachedBrowserComponents = null;
1032
+ var buildingPromise = null;
1033
+ function getComponentsEntrySource() {
1034
+ return `
1035
+ // Browser Components Entry Point
1036
+ // This gets transpiled by esbuild to create browser-compatible code
1037
+
1038
+ import {
1039
+ // Card styles
1040
+ CARD_VARIANTS,
1041
+ CARD_SIZES,
1042
+ // Button styles
1043
+ BUTTON_VARIANTS,
1044
+ BUTTON_SIZES,
1045
+ BUTTON_ICON_SIZES,
1046
+ BUTTON_BASE_CLASSES,
1047
+ LOADING_SPINNER,
1048
+ // Badge styles
1049
+ BADGE_VARIANTS,
1050
+ BADGE_SIZES,
1051
+ BADGE_DOT_SIZES,
1052
+ BADGE_DOT_VARIANTS,
1053
+ // Alert styles
1054
+ ALERT_VARIANTS,
1055
+ ALERT_BASE_CLASSES,
1056
+ ALERT_ICONS,
1057
+ CLOSE_ICON,
1058
+ // Utility
1059
+ cn,
1060
+ } from '@frontmcp/uipack/styles';
1061
+
1062
+ // Re-export for the IIFE
1063
+ export {
1064
+ CARD_VARIANTS,
1065
+ CARD_SIZES,
1066
+ BUTTON_VARIANTS,
1067
+ BUTTON_SIZES,
1068
+ BUTTON_ICON_SIZES,
1069
+ BUTTON_BASE_CLASSES,
1070
+ LOADING_SPINNER,
1071
+ BADGE_VARIANTS,
1072
+ BADGE_SIZES,
1073
+ BADGE_DOT_SIZES,
1074
+ BADGE_DOT_VARIANTS,
1075
+ ALERT_VARIANTS,
1076
+ ALERT_BASE_CLASSES,
1077
+ ALERT_ICONS,
1078
+ CLOSE_ICON,
1079
+ cn,
1080
+ };
1081
+
1082
+ // Card Component
1083
+ export function Card(props: any) {
1084
+ const {
1085
+ title,
1086
+ subtitle,
1087
+ headerActions,
1088
+ footer,
1089
+ variant = 'default',
1090
+ size = 'md',
1091
+ className,
1092
+ id,
1093
+ clickable,
1094
+ href,
1095
+ children,
1096
+ } = props;
1097
+
1098
+ const variantClasses = CARD_VARIANTS[variant] || CARD_VARIANTS.default;
1099
+ const sizeClasses = CARD_SIZES[size] || CARD_SIZES.md;
1100
+ const clickableClasses = clickable ? 'cursor-pointer hover:shadow-md transition-shadow' : '';
1101
+ const allClasses = cn(variantClasses, sizeClasses, clickableClasses, className);
1102
+
1103
+ const hasHeader = title || subtitle || headerActions;
1104
+
1105
+ const headerElement = hasHeader ? React.createElement('div', {
1106
+ className: 'flex items-start justify-between mb-4'
1107
+ }, [
1108
+ React.createElement('div', { key: 'titles' }, [
1109
+ title && React.createElement('h3', {
1110
+ key: 'title',
1111
+ className: 'text-lg font-semibold text-text-primary'
1112
+ }, title),
1113
+ subtitle && React.createElement('p', {
1114
+ key: 'subtitle',
1115
+ className: 'text-sm text-text-secondary mt-1'
1116
+ }, subtitle)
1117
+ ]),
1118
+ headerActions && React.createElement('div', {
1119
+ key: 'actions',
1120
+ className: 'flex items-center gap-2'
1121
+ }, headerActions)
1122
+ ]) : null;
1123
+
1124
+ const footerElement = footer ? React.createElement('div', {
1125
+ className: 'mt-4 pt-4 border-t border-divider'
1126
+ }, footer) : null;
1127
+
1128
+ const content = React.createElement(React.Fragment, null, headerElement, children, footerElement);
1129
+
1130
+ if (href) {
1131
+ return React.createElement('a', { href, className: allClasses, id }, content);
1132
+ }
1133
+
1134
+ return React.createElement('div', { className: allClasses, id }, content);
1135
+ }
1136
+
1137
+ // Button Component
1138
+ export function Button(props: any) {
1139
+ const {
1140
+ variant = 'primary',
1141
+ size = 'md',
1142
+ disabled = false,
1143
+ loading = false,
1144
+ fullWidth = false,
1145
+ iconPosition = 'left',
1146
+ icon,
1147
+ iconOnly = false,
1148
+ type = 'button',
1149
+ className,
1150
+ onClick,
1151
+ children,
1152
+ } = props;
1153
+
1154
+ const variantClasses = BUTTON_VARIANTS[variant] || BUTTON_VARIANTS.primary;
1155
+ const sizeClasses = iconOnly
1156
+ ? (BUTTON_ICON_SIZES[size] || BUTTON_ICON_SIZES.md)
1157
+ : (BUTTON_SIZES[size] || BUTTON_SIZES.md);
1158
+
1159
+ const disabledClasses = (disabled || loading) ? 'opacity-50 cursor-not-allowed' : '';
1160
+ const widthClasses = fullWidth ? 'w-full' : '';
1161
+
1162
+ const allClasses = cn(BUTTON_BASE_CLASSES, variantClasses, sizeClasses, disabledClasses, widthClasses, className);
1163
+
1164
+ const iconElement = icon ? React.createElement('span', {
1165
+ className: iconPosition === 'left' ? 'mr-2' : 'ml-2'
1166
+ }, icon) : null;
1167
+
1168
+ const loadingSpinner = loading ? React.createElement('span', {
1169
+ className: 'mr-2',
1170
+ dangerouslySetInnerHTML: { __html: LOADING_SPINNER }
1171
+ }) : null;
1172
+
1173
+ return React.createElement('button', {
1174
+ type,
1175
+ className: allClasses,
1176
+ disabled: disabled || loading,
1177
+ onClick
1178
+ },
1179
+ loadingSpinner,
1180
+ !loading && icon && iconPosition === 'left' ? iconElement : null,
1181
+ !iconOnly ? children : null,
1182
+ !loading && icon && iconPosition === 'right' ? iconElement : null
1183
+ );
1184
+ }
1185
+
1186
+ // Badge Component
1187
+ export function Badge(props: any) {
1188
+ const {
1189
+ variant = 'default',
1190
+ size = 'md',
1191
+ pill = false,
1192
+ icon,
1193
+ dot = false,
1194
+ className,
1195
+ removable = false,
1196
+ onRemove,
1197
+ children,
1198
+ } = props;
1199
+
1200
+ // Handle dot badge
1201
+ if (dot) {
1202
+ const dotSizeClasses = BADGE_DOT_SIZES[size] || BADGE_DOT_SIZES.md;
1203
+ const dotVariantClasses = BADGE_DOT_VARIANTS[variant] || BADGE_DOT_VARIANTS.default;
1204
+ const dotClasses = cn('inline-block rounded-full', dotSizeClasses, dotVariantClasses, className);
1205
+ const label = typeof children === 'string' ? children : undefined;
1206
+ return React.createElement('span', {
1207
+ className: dotClasses,
1208
+ 'aria-label': label,
1209
+ title: label
1210
+ });
1211
+ }
1212
+
1213
+ const variantClasses = BADGE_VARIANTS[variant] || BADGE_VARIANTS.default;
1214
+ const sizeClasses = BADGE_SIZES[size] || BADGE_SIZES.md;
1215
+
1216
+ const baseClasses = cn(
1217
+ 'inline-flex items-center font-medium',
1218
+ pill ? 'rounded-full' : 'rounded-md',
1219
+ variantClasses,
1220
+ sizeClasses,
1221
+ className
1222
+ );
1223
+
1224
+ const closeButton = removable ? React.createElement('button', {
1225
+ type: 'button',
1226
+ className: 'ml-1.5 -mr-1 hover:opacity-70 transition-opacity',
1227
+ 'aria-label': 'Remove',
1228
+ onClick: onRemove
1229
+ }, React.createElement('svg', {
1230
+ className: 'w-3 h-3',
1231
+ fill: 'none',
1232
+ stroke: 'currentColor',
1233
+ viewBox: '0 0 24 24'
1234
+ }, React.createElement('path', {
1235
+ strokeLinecap: 'round',
1236
+ strokeLinejoin: 'round',
1237
+ strokeWidth: '2',
1238
+ d: 'M6 18L18 6M6 6l12 12'
1239
+ }))) : null;
1240
+
1241
+ return React.createElement('span', { className: baseClasses },
1242
+ icon ? React.createElement('span', { className: 'mr-1' }, icon) : null,
1243
+ children,
1244
+ closeButton
1245
+ );
1246
+ }
1247
+
1248
+ // Alert Component
1249
+ export function Alert(props: any) {
1250
+ const {
1251
+ variant = 'info',
1252
+ title,
1253
+ icon,
1254
+ showIcon = true,
1255
+ dismissible = false,
1256
+ onDismiss,
1257
+ className,
1258
+ children,
1259
+ } = props;
1260
+
1261
+ const variantStyles = ALERT_VARIANTS[variant] || ALERT_VARIANTS.info;
1262
+ const allClasses = cn(ALERT_BASE_CLASSES, variantStyles.container, className);
1263
+
1264
+ const iconContent = icon || (showIcon ? React.createElement('span', {
1265
+ className: cn('flex-shrink-0', variantStyles.icon),
1266
+ dangerouslySetInnerHTML: { __html: ALERT_ICONS[variant] || ALERT_ICONS.info }
1267
+ }) : null);
1268
+
1269
+ const dismissButton = dismissible ? React.createElement('button', {
1270
+ type: 'button',
1271
+ className: 'flex-shrink-0 ml-3 hover:opacity-70 transition-opacity',
1272
+ 'aria-label': 'Dismiss',
1273
+ onClick: onDismiss
1274
+ }, React.createElement('span', {
1275
+ dangerouslySetInnerHTML: { __html: CLOSE_ICON }
1276
+ })) : null;
1277
+
1278
+ return React.createElement('div', { className: allClasses, role: 'alert' },
1279
+ React.createElement('div', { className: 'flex' },
1280
+ iconContent ? React.createElement('div', { className: 'flex-shrink-0 mr-3' }, iconContent) : null,
1281
+ React.createElement('div', { className: 'flex-1' },
1282
+ title ? React.createElement('h4', { className: 'font-semibold mb-1' }, title) : null,
1283
+ React.createElement('div', { className: 'text-sm' }, children)
1284
+ ),
1285
+ dismissButton
1286
+ )
1287
+ );
1288
+ }
1289
+ `;
1290
+ }
1291
+ function getBrowserRuntimeWrapper() {
1292
+ return `
1293
+ // Assign components to window for require() shim
1294
+ window.Card = Card;
1295
+ window.Button = Button;
1296
+ window.Badge = Badge;
1297
+ window.Alert = Alert;
1298
+
1299
+ // Build the namespace object for @frontmcp/ui/react imports
1300
+ window.frontmcp_ui_namespaceObject = Object.assign({}, window.React || {}, {
1301
+ // Hooks
1302
+ useToolOutput: window.useToolOutput,
1303
+ useToolInput: window.useToolInput,
1304
+ useMcpBridgeContext: function() { return window.__frontmcp.context; },
1305
+ useMcpBridge: function() { return window.__frontmcp.context; },
1306
+ useCallTool: function() {
1307
+ return function(name, args) {
1308
+ if (window.__frontmcp.context && window.__frontmcp.context.callTool) {
1309
+ return window.__frontmcp.context.callTool(name, args);
1310
+ }
1311
+ console.warn('[FrontMCP] callTool not available');
1312
+ return Promise.resolve(null);
1313
+ };
1314
+ },
1315
+ useTheme: function() { return window.__frontmcp.theme || 'light'; },
1316
+ useDisplayMode: function() { return window.__frontmcp.displayMode || 'embedded'; },
1317
+ useHostContext: function() { return window.__frontmcp.hostContext || {}; },
1318
+ useCapability: function(cap) { return window.__frontmcp.capabilities && window.__frontmcp.capabilities[cap] || false; },
1319
+ useStructuredContent: function() { return window.__frontmcp.getState().structuredContent; },
1320
+ useToolCalls: function() { return []; },
1321
+ useSendMessage: function() { return function() { return Promise.resolve(); }; },
1322
+ useOpenLink: function() { return function() {}; },
1323
+
1324
+ // Components
1325
+ Card: window.Card,
1326
+ Badge: window.Badge,
1327
+ Button: window.Button,
1328
+ Alert: window.Alert,
1329
+
1330
+ // Re-export React for convenience
1331
+ createElement: React.createElement,
1332
+ Fragment: React.Fragment,
1333
+ useState: React.useState,
1334
+ useEffect: React.useEffect,
1335
+ useCallback: React.useCallback,
1336
+ useMemo: React.useMemo,
1337
+ useRef: React.useRef,
1338
+ useContext: React.useContext
1339
+ });
1340
+ `;
1341
+ }
1342
+ async function buildWithEsbuild() {
1343
+ try {
1344
+ const esbuild = await import("esbuild");
1345
+ const stylesPath = __require.resolve("@frontmcp/uipack/styles");
1346
+ const entrySource = getComponentsEntrySource();
1347
+ const result = await esbuild.build({
1348
+ stdin: {
1349
+ contents: entrySource,
1350
+ loader: "tsx",
1351
+ resolveDir: path.dirname(stylesPath)
1352
+ },
1353
+ bundle: true,
1354
+ format: "iife",
1355
+ globalName: "__frontmcp_components",
1356
+ target: "es2020",
1357
+ minify: false,
1358
+ write: false,
1359
+ external: ["react", "react-dom"],
1360
+ define: {
1361
+ React: "window.React"
1362
+ },
1363
+ platform: "browser"
1364
+ });
1365
+ if (result.outputFiles && result.outputFiles.length > 0) {
1366
+ let code = result.outputFiles[0].text;
1367
+ code += "\n" + getBrowserRuntimeWrapper();
1368
+ return code;
1369
+ }
1370
+ throw new Error("No output from esbuild");
1371
+ } catch (error) {
1372
+ console.warn(
1373
+ `[FrontMCP] esbuild bundle failed, falling back to manual components: ${error instanceof Error ? error.message : String(error)}`
1374
+ );
1375
+ throw error;
1376
+ }
1377
+ }
1378
+ async function getBrowserComponents() {
1379
+ if (cachedBrowserComponents !== null) {
1380
+ return cachedBrowserComponents;
1381
+ }
1382
+ if (buildingPromise !== null) {
1383
+ return buildingPromise;
1384
+ }
1385
+ buildingPromise = buildWithEsbuild().then((code) => {
1386
+ cachedBrowserComponents = code;
1387
+ buildingPromise = null;
1388
+ return code;
1389
+ }).catch((error) => {
1390
+ buildingPromise = null;
1391
+ throw error;
1392
+ });
1393
+ return buildingPromise;
1394
+ }
1395
+
1396
+ // libs/ui/src/bundler/bundler.ts
1397
+ import { SecurityError, ExecutionError as ExecutionError2 } from "@frontmcp/uipack/bundler";
1398
+ var esbuildTransform = null;
1399
+ async function loadEsbuild() {
1400
+ if (esbuildTransform !== null) {
1401
+ return esbuildTransform;
1402
+ }
1403
+ try {
1404
+ const esbuild = await import("esbuild");
1405
+ esbuildTransform = esbuild.transform;
1406
+ return esbuildTransform;
1407
+ } catch {
1408
+ try {
1409
+ const swc = await import("@swc/core");
1410
+ esbuildTransform = async (source, options) => {
1411
+ const opts = options;
1412
+ const result = await swc.transform(source, {
1413
+ jsc: {
1414
+ parser: {
1415
+ syntax: "typescript",
1416
+ tsx: opts.loader === "tsx" || opts.loader === "jsx"
1417
+ },
1418
+ transform: {
1419
+ react: {
1420
+ runtime: "automatic",
1421
+ development: false
1422
+ }
1423
+ },
1424
+ target: "es2020",
1425
+ minify: opts.minify ? { compress: true, mangle: true } : void 0
1426
+ },
1427
+ module: {
1428
+ type: "commonjs"
1429
+ },
1430
+ sourceMaps: opts.sourcemap ? true : false
1431
+ });
1432
+ return { code: result.code, map: result.map };
1433
+ };
1434
+ return esbuildTransform;
1435
+ } catch {
1436
+ console.warn(
1437
+ "[@frontmcp/ui/bundler] Neither esbuild nor @swc/core available. Install esbuild for best performance: npm install esbuild"
1438
+ );
1439
+ return null;
1440
+ }
1441
+ }
1442
+ }
1443
+ function sanitizeRootId(rootId) {
1444
+ const safeId = rootId.replace(/[^a-zA-Z0-9_-]/g, "");
1445
+ if (safeId !== rootId) {
1446
+ console.warn("[FrontMCP] rootId sanitized:", { original: rootId, sanitized: safeId });
1447
+ }
1448
+ return safeId || "frontmcp-root";
1449
+ }
1450
+ function sanitizeCss(css) {
1451
+ return css.replace(/<\/style>/gi, "\\3c/style\\3e");
1452
+ }
1453
+ var InMemoryBundler = class {
1454
+ cache;
1455
+ options;
1456
+ defaultSecurity;
1457
+ constructor(options = {}) {
1458
+ this.options = {
1459
+ ...DEFAULT_BUNDLER_OPTIONS,
1460
+ ...options,
1461
+ cache: {
1462
+ ...DEFAULT_BUNDLER_OPTIONS.cache,
1463
+ ...options.cache
1464
+ }
1465
+ };
1466
+ this.cache = new BundlerCache({
1467
+ maxSize: this.options.cache.maxSize,
1468
+ ttl: this.options.cache.ttl
1469
+ });
1470
+ this.defaultSecurity = mergePolicy(options.defaultSecurity);
1471
+ }
1472
+ /**
1473
+ * Bundle source code.
1474
+ *
1475
+ * @param options - Bundle options
1476
+ * @returns Bundle result
1477
+ */
1478
+ async bundle(options) {
1479
+ const startTime = performance.now();
1480
+ const opts = this.mergeOptions(options);
1481
+ if (!opts.skipCache && !this.options.cache.disabled) {
1482
+ const cacheKey = options.cacheKey ?? createCacheKey(options.source, opts);
1483
+ const cached = this.cache.get(cacheKey);
1484
+ if (cached) {
1485
+ return {
1486
+ ...cached,
1487
+ cached: true,
1488
+ metrics: {
1489
+ ...cached.metrics,
1490
+ cacheTime: performance.now() - startTime
1491
+ }
1492
+ };
1493
+ }
1494
+ }
1495
+ const security = mergePolicy(options.security ?? this.defaultSecurity);
1496
+ const violations = validateSource(options.source, security);
1497
+ throwOnViolations(violations);
1498
+ const sourceType = opts.sourceType === "auto" ? this.detectSourceType(options.source) : opts.sourceType;
1499
+ const transformStart = performance.now();
1500
+ const transformed = await this.transform(options.source, sourceType, opts);
1501
+ const transformTime = performance.now() - transformStart;
1502
+ const sizeViolation = validateSize(transformed.code.length, security);
1503
+ if (sizeViolation) {
1504
+ throwOnViolations([sizeViolation]);
1505
+ }
1506
+ const hash = hashContent(transformed.code);
1507
+ const result = {
1508
+ code: transformed.code,
1509
+ hash,
1510
+ cached: false,
1511
+ size: transformed.code.length,
1512
+ map: transformed.map,
1513
+ metrics: {
1514
+ transformTime,
1515
+ bundleTime: 0,
1516
+ // No separate bundle step for transform-only
1517
+ totalTime: performance.now() - startTime
1518
+ },
1519
+ sourceType,
1520
+ format: opts.format
1521
+ };
1522
+ if (!this.options.cache.disabled) {
1523
+ const cacheKey = options.cacheKey ?? createCacheKey(options.source, opts);
1524
+ this.cache.set(cacheKey, result);
1525
+ }
1526
+ return result;
1527
+ }
1528
+ /**
1529
+ * Bundle and execute for SSR.
1530
+ *
1531
+ * @param options - SSR bundle options
1532
+ * @returns SSR result with rendered HTML
1533
+ */
1534
+ async bundleSSR(options) {
1535
+ const startTime = performance.now();
1536
+ const bundleResult = await this.bundle({
1537
+ ...options,
1538
+ format: "cjs"
1539
+ // CommonJS for execution
1540
+ });
1541
+ let React;
1542
+ let ReactDOMServer;
1543
+ try {
1544
+ React = await import("react");
1545
+ ReactDOMServer = await import("react-dom/server");
1546
+ } catch {
1547
+ throw new Error("React and react-dom/server are required for SSR. Install them: npm install react react-dom");
1548
+ }
1549
+ const renderStart = performance.now();
1550
+ const Component = await executeDefault(bundleResult.code, {
1551
+ React,
1552
+ security: mergePolicy(options.security ?? this.defaultSecurity)
1553
+ });
1554
+ let html;
1555
+ try {
1556
+ const element = React.createElement(Component, options.context ?? {});
1557
+ html = ReactDOMServer.renderToString(element);
1558
+ } catch (error) {
1559
+ throw new ExecutionError(
1560
+ `SSR rendering failed: ${error instanceof Error ? error.message : String(error)}`,
1561
+ error
1562
+ );
1563
+ }
1564
+ const renderTime = performance.now() - renderStart;
1565
+ let hydrationScript;
1566
+ if (options.includeHydration) {
1567
+ hydrationScript = this.buildHydrationScript(bundleResult.code, options.context);
1568
+ }
1569
+ return {
1570
+ ...bundleResult,
1571
+ html,
1572
+ hydrationScript,
1573
+ metrics: {
1574
+ ...bundleResult.metrics,
1575
+ totalTime: performance.now() - startTime
1576
+ },
1577
+ ssrMetrics: {
1578
+ renderTime
1579
+ }
1580
+ };
1581
+ }
1582
+ /**
1583
+ * Bundle and execute code, returning the exports.
1584
+ *
1585
+ * @param options - Bundle options
1586
+ * @param context - Execution context
1587
+ * @returns Exported value
1588
+ */
1589
+ async bundleAndExecute(options, context) {
1590
+ const result = await this.bundle({
1591
+ ...options,
1592
+ format: "cjs"
1593
+ // CommonJS for execution
1594
+ });
1595
+ let React;
1596
+ try {
1597
+ React = await import("react");
1598
+ } catch {
1599
+ }
1600
+ return executeDefault(result.code, {
1601
+ React,
1602
+ globals: context,
1603
+ security: mergePolicy(options.security ?? this.defaultSecurity)
1604
+ });
1605
+ }
1606
+ /**
1607
+ * Bundle a component to a self-contained static HTML document.
1608
+ *
1609
+ * Creates a complete HTML page with:
1610
+ * - React runtime (CDN or inline based on platform)
1611
+ * - FrontMCP UI hooks and components (always inline)
1612
+ * - Tool data injection (input/output)
1613
+ * - Transpiled component code
1614
+ * - Client-side rendering via createRoot
1615
+ *
1616
+ * @param options - Static HTML options
1617
+ * @returns Static HTML result with complete document
1618
+ *
1619
+ * @example
1620
+ * ```typescript
1621
+ * const result = await bundler.bundleToStaticHTML({
1622
+ * source: `
1623
+ * import { Card, useToolOutput } from '@frontmcp/ui/react';
1624
+ * export default function Weather() {
1625
+ * const output = useToolOutput();
1626
+ * return <Card title="Weather">{output?.temperature}°F</Card>;
1627
+ * }
1628
+ * `,
1629
+ * toolName: 'get_weather',
1630
+ * output: { temperature: 72 },
1631
+ * });
1632
+ *
1633
+ * // result.html contains the complete HTML document
1634
+ * ```
1635
+ */
1636
+ async bundleToStaticHTML(options) {
1637
+ const startTime = performance.now();
1638
+ const opts = this.mergeStaticHTMLOptions(options);
1639
+ const platform = opts.targetPlatform === "auto" ? "generic" : opts.targetPlatform;
1640
+ const cdnType = getCdnTypeForPlatform(platform);
1641
+ if (opts.universal) {
1642
+ return this.bundleToStaticHTMLUniversal(options, opts, platform, cdnType, startTime);
1643
+ }
1644
+ const bundleResult = await this.bundle({
1645
+ source: options.source,
1646
+ sourceType: opts.sourceType,
1647
+ format: "cjs",
1648
+ minify: opts.minify,
1649
+ sourceMaps: false,
1650
+ externals: ["react", "react-dom", "react/jsx-runtime", "@frontmcp/ui", "@frontmcp/ui/react"],
1651
+ security: opts.security,
1652
+ skipCache: opts.skipCache
1653
+ });
1654
+ const head = this.buildStaticHTMLHead({ externals: opts.externals, customCss: opts.customCss, theme: opts.theme });
1655
+ const reactRuntime = this.buildReactRuntimeScripts(opts.externals, platform, cdnType);
1656
+ const frontmcpRuntime = await this.buildFrontMCPRuntime();
1657
+ const dataScript = this.buildDataInjectionScript(
1658
+ opts.toolName,
1659
+ opts.input,
1660
+ opts.output,
1661
+ opts.structuredContent,
1662
+ opts.buildMode,
1663
+ cdnType,
1664
+ opts.dynamicOptions,
1665
+ opts.hybridOptions
1666
+ );
1667
+ const componentScript = this.buildComponentRenderScript(bundleResult.code, opts.rootId, cdnType);
1668
+ const html = this.assembleStaticHTML({
1669
+ title: opts.title || `${opts.toolName} - Widget`,
1670
+ head,
1671
+ reactRuntime,
1672
+ frontmcpRuntime,
1673
+ dataScript,
1674
+ componentScript,
1675
+ rootId: opts.rootId,
1676
+ cdnType
1677
+ });
1678
+ const hash = hashContent(html);
1679
+ const dataPlaceholder = opts.buildMode === "hybrid" ? opts.hybridOptions?.placeholder ?? HYBRID_DATA_PLACEHOLDER : void 0;
1680
+ const inputPlaceholder = opts.buildMode === "hybrid" ? opts.hybridOptions?.inputPlaceholder ?? HYBRID_INPUT_PLACEHOLDER : void 0;
1681
+ return {
1682
+ html,
1683
+ componentCode: bundleResult.code,
1684
+ metrics: {
1685
+ ...bundleResult.metrics,
1686
+ totalTime: performance.now() - startTime
1687
+ },
1688
+ hash,
1689
+ size: html.length,
1690
+ cached: bundleResult.cached,
1691
+ sourceType: bundleResult.sourceType,
1692
+ targetPlatform: platform,
1693
+ buildMode: opts.buildMode,
1694
+ dataPlaceholder,
1695
+ inputPlaceholder
1696
+ };
1697
+ }
1698
+ /**
1699
+ * Bundle a component to static HTML for all target platforms at once.
1700
+ *
1701
+ * This method is optimized for efficiency:
1702
+ * - Transpiles the component source code only once
1703
+ * - Generates platform-specific HTML variations from the shared transpiled code
1704
+ * - Returns complete platform metadata ready for MCP responses
1705
+ *
1706
+ * @param options - Multi-platform build options
1707
+ * @returns Multi-platform build result with all platforms
1708
+ *
1709
+ * @example
1710
+ * ```typescript
1711
+ * const result = await bundler.bundleToStaticHTMLAll({
1712
+ * source: `
1713
+ * import { Card, useToolOutput } from '@frontmcp/ui/react';
1714
+ * export default function Weather() {
1715
+ * const output = useToolOutput();
1716
+ * return <Card title="Weather">{output?.temperature}°F</Card>;
1717
+ * }
1718
+ * `,
1719
+ * toolName: 'get_weather',
1720
+ * output: { temperature: 72 },
1721
+ * });
1722
+ *
1723
+ * // Access platform-specific results
1724
+ * const openaiHtml = result.platforms.openai.html;
1725
+ * const claudeHtml = result.platforms.claude.html;
1726
+ *
1727
+ * // Get metadata for MCP response
1728
+ * const openaiMeta = result.platforms.openai.meta;
1729
+ * ```
1730
+ */
1731
+ async bundleToStaticHTMLAll(options) {
1732
+ const startTime = performance.now();
1733
+ const opts = this.mergeStaticHTMLOptions(options);
1734
+ const platforms = options.platforms ?? [...ALL_PLATFORMS];
1735
+ const transpileStart = performance.now();
1736
+ let transpiledCode = null;
1737
+ let bundleResult = null;
1738
+ const isUniversal = opts.universal;
1739
+ const rawContentType = options.contentType ?? "auto";
1740
+ const contentType = isUniversal ? rawContentType === "auto" ? detectContentType(options.source) : rawContentType : "react";
1741
+ if (contentType === "react" || !isUniversal) {
1742
+ bundleResult = await this.bundle({
1743
+ source: options.source,
1744
+ sourceType: opts.sourceType,
1745
+ format: "cjs",
1746
+ minify: opts.minify,
1747
+ sourceMaps: false,
1748
+ externals: ["react", "react-dom", "react/jsx-runtime", "@frontmcp/ui", "@frontmcp/ui/react"],
1749
+ security: opts.security,
1750
+ skipCache: opts.skipCache
1751
+ });
1752
+ transpiledCode = bundleResult.code;
1753
+ }
1754
+ const transpileTime = performance.now() - transpileStart;
1755
+ const generationStart = performance.now();
1756
+ const platformResults = {};
1757
+ for (const platform of platforms) {
1758
+ const platformResult = await this.buildForPlatform({
1759
+ options,
1760
+ opts,
1761
+ platform,
1762
+ transpiledCode,
1763
+ bundleResult,
1764
+ contentType,
1765
+ isUniversal
1766
+ });
1767
+ platformResults[platform] = platformResult;
1768
+ }
1769
+ const generationTime = performance.now() - generationStart;
1770
+ return {
1771
+ platforms: platformResults,
1772
+ sharedComponentCode: transpiledCode ?? "",
1773
+ metrics: {
1774
+ transpileTime,
1775
+ generationTime,
1776
+ totalTime: performance.now() - startTime
1777
+ },
1778
+ cached: bundleResult?.cached ?? false
1779
+ };
1780
+ }
1781
+ /**
1782
+ * Build for a specific platform with pre-transpiled code.
1783
+ * Internal helper for bundleToStaticHTMLAll.
1784
+ */
1785
+ async buildForPlatform(params) {
1786
+ const { options, opts, platform, transpiledCode, bundleResult, contentType, isUniversal } = params;
1787
+ const cdnType = getCdnTypeForPlatform(platform);
1788
+ const buildStart = performance.now();
1789
+ let html;
1790
+ let componentCode;
1791
+ if (isUniversal) {
1792
+ const shouldIncludeBridge = opts.buildMode === "dynamic" || opts.buildMode === "hybrid";
1793
+ const cachedRuntime = getCachedRuntime({
1794
+ cdnType,
1795
+ includeMarkdown: opts.includeMarkdown || contentType === "markdown",
1796
+ includeMdx: opts.includeMdx || contentType === "mdx",
1797
+ minify: opts.minify,
1798
+ includeBridge: shouldIncludeBridge
1799
+ });
1800
+ const componentCodeStr = transpiledCode ? buildComponentCode(transpiledCode) : "";
1801
+ const dataInjectionStr = buildDataInjectionCode(
1802
+ opts.toolName,
1803
+ opts.input,
1804
+ opts.output,
1805
+ opts.structuredContent,
1806
+ contentType,
1807
+ transpiledCode ? null : options.source,
1808
+ transpiledCode !== null,
1809
+ {
1810
+ buildMode: opts.buildMode,
1811
+ cdnType,
1812
+ dynamicOptions: opts.dynamicOptions,
1813
+ hybridOptions: opts.hybridOptions
1814
+ }
1815
+ );
1816
+ const appScript = buildAppScript(
1817
+ cachedRuntime.appTemplate,
1818
+ componentCodeStr,
1819
+ dataInjectionStr,
1820
+ opts.customComponents ?? ""
1821
+ );
1822
+ const head = this.buildStaticHTMLHead({
1823
+ externals: opts.externals,
1824
+ customCss: opts.customCss,
1825
+ theme: opts.theme
1826
+ });
1827
+ const reactRuntime = this.buildReactRuntimeScripts(opts.externals, platform, cdnType);
1828
+ const renderScript = this.buildUniversalRenderScript(opts.rootId, cdnType);
1829
+ html = this.assembleUniversalStaticHTMLCached({
1830
+ title: opts.title || `${opts.toolName} - Widget`,
1831
+ head,
1832
+ reactRuntime,
1833
+ cdnImports: cachedRuntime.cdnImports,
1834
+ vendorScript: cachedRuntime.vendorScript,
1835
+ appScript,
1836
+ renderScript,
1837
+ rootId: opts.rootId,
1838
+ cdnType
1839
+ });
1840
+ componentCode = transpiledCode ?? appScript;
1841
+ } else {
1842
+ if (!transpiledCode) {
1843
+ throw new Error("Failed to transpile component source");
1844
+ }
1845
+ const head = this.buildStaticHTMLHead({
1846
+ externals: opts.externals,
1847
+ customCss: opts.customCss,
1848
+ theme: opts.theme
1849
+ });
1850
+ const reactRuntime = this.buildReactRuntimeScripts(opts.externals, platform, cdnType);
1851
+ const frontmcpRuntime = await this.buildFrontMCPRuntime();
1852
+ const dataScript = this.buildDataInjectionScript(
1853
+ opts.toolName,
1854
+ opts.input,
1855
+ opts.output,
1856
+ opts.structuredContent,
1857
+ opts.buildMode,
1858
+ cdnType,
1859
+ opts.dynamicOptions,
1860
+ opts.hybridOptions
1861
+ );
1862
+ const componentScript = this.buildComponentRenderScript(transpiledCode, opts.rootId, cdnType);
1863
+ html = this.assembleStaticHTML({
1864
+ title: opts.title || `${opts.toolName} - Widget`,
1865
+ head,
1866
+ reactRuntime,
1867
+ frontmcpRuntime,
1868
+ dataScript,
1869
+ componentScript,
1870
+ rootId: opts.rootId,
1871
+ cdnType
1872
+ });
1873
+ componentCode = transpiledCode;
1874
+ }
1875
+ const hash = hashContent(html);
1876
+ const meta = buildUIMeta({
1877
+ uiConfig: {
1878
+ template: () => html,
1879
+ widgetAccessible: opts.widgetAccessible
1880
+ },
1881
+ platformType: this.mapTargetPlatformToAIPlatform(platform),
1882
+ html
1883
+ });
1884
+ const dataPlaceholder = opts.buildMode === "hybrid" ? opts.hybridOptions?.placeholder ?? HYBRID_DATA_PLACEHOLDER : void 0;
1885
+ const inputPlaceholder = opts.buildMode === "hybrid" ? opts.hybridOptions?.inputPlaceholder ?? HYBRID_INPUT_PLACEHOLDER : void 0;
1886
+ return {
1887
+ html,
1888
+ componentCode,
1889
+ metrics: bundleResult?.metrics ?? {
1890
+ transformTime: 0,
1891
+ bundleTime: 0,
1892
+ totalTime: performance.now() - buildStart
1893
+ },
1894
+ hash,
1895
+ size: html.length,
1896
+ cached: bundleResult?.cached ?? false,
1897
+ sourceType: bundleResult?.sourceType ?? opts.sourceType,
1898
+ targetPlatform: platform,
1899
+ universal: isUniversal,
1900
+ contentType: isUniversal ? contentType : void 0,
1901
+ buildMode: opts.buildMode,
1902
+ dataPlaceholder,
1903
+ inputPlaceholder,
1904
+ meta
1905
+ };
1906
+ }
1907
+ /**
1908
+ * Map TargetPlatform to AIPlatformType for metadata generation.
1909
+ */
1910
+ mapTargetPlatformToAIPlatform(platform) {
1911
+ switch (platform) {
1912
+ case "openai":
1913
+ return "openai";
1914
+ case "claude":
1915
+ return "claude";
1916
+ case "cursor":
1917
+ return "cursor";
1918
+ case "ext-apps":
1919
+ return "ext-apps";
1920
+ case "generic":
1921
+ return "generic-mcp";
1922
+ default:
1923
+ return "generic-mcp";
1924
+ }
1925
+ }
1926
+ /**
1927
+ * Bundle to static HTML with universal rendering mode.
1928
+ * Uses the universal renderer that can handle multiple content types.
1929
+ *
1930
+ * Optimization: Uses cached runtime (vendor chunk) to avoid rebuilding
1931
+ * static code on every request. Only the user's component is transpiled.
1932
+ */
1933
+ async bundleToStaticHTMLUniversal(options, opts, platform, cdnType, startTime) {
1934
+ let contentType;
1935
+ const rawContentType = options.contentType ?? "auto";
1936
+ if (rawContentType === "auto") {
1937
+ contentType = detectContentType(options.source);
1938
+ } else {
1939
+ contentType = rawContentType;
1940
+ }
1941
+ let transpiledCode = null;
1942
+ let transformTime = 0;
1943
+ if (contentType === "react") {
1944
+ const bundleResult = await this.bundle({
1945
+ source: options.source,
1946
+ sourceType: opts.sourceType,
1947
+ format: "cjs",
1948
+ minify: opts.minify,
1949
+ sourceMaps: false,
1950
+ externals: ["react", "react-dom", "react/jsx-runtime", "@frontmcp/ui", "@frontmcp/ui/react"],
1951
+ security: opts.security,
1952
+ skipCache: opts.skipCache
1953
+ });
1954
+ transpiledCode = bundleResult.code;
1955
+ transformTime = bundleResult.metrics.transformTime;
1956
+ }
1957
+ const shouldIncludeBridge = opts.buildMode === "dynamic" || opts.buildMode === "hybrid";
1958
+ const cachedRuntime = getCachedRuntime({
1959
+ cdnType,
1960
+ includeMarkdown: opts.includeMarkdown || contentType === "markdown",
1961
+ includeMdx: opts.includeMdx || contentType === "mdx",
1962
+ minify: opts.minify,
1963
+ includeBridge: shouldIncludeBridge
1964
+ });
1965
+ const componentCodeStr = transpiledCode ? buildComponentCode(transpiledCode) : "";
1966
+ const dataInjectionStr = buildDataInjectionCode(
1967
+ opts.toolName,
1968
+ opts.input,
1969
+ opts.output,
1970
+ opts.structuredContent,
1971
+ contentType,
1972
+ transpiledCode ? null : options.source,
1973
+ // Pass source only if not a component
1974
+ transpiledCode !== null,
1975
+ {
1976
+ buildMode: opts.buildMode,
1977
+ cdnType,
1978
+ dynamicOptions: opts.dynamicOptions,
1979
+ hybridOptions: opts.hybridOptions
1980
+ }
1981
+ );
1982
+ const appScript = buildAppScript(
1983
+ cachedRuntime.appTemplate,
1984
+ componentCodeStr,
1985
+ dataInjectionStr,
1986
+ opts.customComponents ?? ""
1987
+ );
1988
+ const head = this.buildStaticHTMLHead({ externals: opts.externals, customCss: opts.customCss, theme: opts.theme });
1989
+ const reactRuntime = this.buildReactRuntimeScripts(opts.externals, platform, cdnType);
1990
+ const renderScript = this.buildUniversalRenderScript(opts.rootId, cdnType);
1991
+ const html = this.assembleUniversalStaticHTMLCached({
1992
+ title: opts.title || `${opts.toolName} - Widget`,
1993
+ head,
1994
+ reactRuntime,
1995
+ cdnImports: cachedRuntime.cdnImports,
1996
+ vendorScript: cachedRuntime.vendorScript,
1997
+ appScript,
1998
+ renderScript,
1999
+ rootId: opts.rootId,
2000
+ cdnType
2001
+ });
2002
+ const hash = hashContent(html);
2003
+ return {
2004
+ html,
2005
+ componentCode: transpiledCode ?? appScript,
2006
+ metrics: {
2007
+ transformTime,
2008
+ bundleTime: 0,
2009
+ totalTime: performance.now() - startTime,
2010
+ cacheTime: cachedRuntime.cached ? 0 : void 0
2011
+ },
2012
+ hash,
2013
+ size: html.length,
2014
+ cached: cachedRuntime.cached,
2015
+ sourceType: opts.sourceType === "auto" ? this.detectSourceType(options.source) : opts.sourceType,
2016
+ targetPlatform: platform,
2017
+ universal: true,
2018
+ contentType
2019
+ };
2020
+ }
2021
+ /**
2022
+ * Assemble the complete universal static HTML document using cached runtime.
2023
+ *
2024
+ * For ESM mode (OpenAI), scripts must wait for React to load asynchronously.
2025
+ * For UMD mode (Claude), scripts can execute synchronously.
2026
+ */
2027
+ assembleUniversalStaticHTMLCached(parts) {
2028
+ if (parts.cdnType === "umd") {
2029
+ return `<!DOCTYPE html>
2030
+ <html lang="en">
2031
+ <head>
2032
+ <title>${escapeHtml(parts.title)}</title>
2033
+ ${parts.head}
2034
+ ${parts.reactRuntime}
2035
+ ${parts.cdnImports}
2036
+ <!-- Vendor Runtime (Cached) -->
2037
+ <script>
2038
+ ${parts.vendorScript}
2039
+ </script>
2040
+ <!-- App Script (User Component) -->
2041
+ <script>
2042
+ ${parts.appScript}
2043
+ </script>
2044
+ </head>
2045
+ <body>
2046
+ <div id="${parts.rootId}" class="frontmcp-loading">
2047
+ <div class="frontmcp-spinner"></div>
2048
+ </div>
2049
+ ${parts.renderScript}
2050
+ </body>
2051
+ </html>`;
2052
+ } else {
2053
+ return `<!DOCTYPE html>
2054
+ <html lang="en">
2055
+ <head>
2056
+ <title>${escapeHtml(parts.title)}</title>
2057
+ ${parts.head}
2058
+ ${parts.reactRuntime}
2059
+ ${parts.cdnImports}
2060
+ </head>
2061
+ <body>
2062
+ <div id="${parts.rootId}" class="frontmcp-loading">
2063
+ <div class="frontmcp-spinner"></div>
2064
+ </div>
2065
+ <!-- Scripts wait for React to load (ESM is async) -->
2066
+ <script type="module">
2067
+ // Wait for React to be ready
2068
+ function initFrontMCP() {
2069
+ // Vendor Runtime (Cached)
2070
+ ${parts.vendorScript}
2071
+
2072
+ // App Script (User Component)
2073
+ ${parts.appScript}
2074
+
2075
+ // Render the app
2076
+ var container = document.getElementById('${parts.rootId}');
2077
+ if (container && window.ReactDOM && window.ReactDOM.createRoot && window.__frontmcp.UniversalApp) {
2078
+ var root = window.ReactDOM.createRoot(container);
2079
+ root.render(React.createElement(window.__frontmcp.UniversalApp));
2080
+ }
2081
+ }
2082
+
2083
+ if (window.__reactReady) {
2084
+ initFrontMCP();
2085
+ } else {
2086
+ window.addEventListener('react:ready', initFrontMCP);
2087
+ }
2088
+ </script>
2089
+ </body>
2090
+ </html>`;
2091
+ }
2092
+ }
2093
+ /**
2094
+ * Build the component script for transpiled React/MDX content.
2095
+ * Wraps CommonJS code with module/exports shim to capture the component.
2096
+ */
2097
+ buildUniversalComponentScript(transpiledCode, cdnType) {
2098
+ const wrappedCode = `
2099
+ // CommonJS module shim
2100
+ var module = { exports: {} };
2101
+ var exports = module.exports;
2102
+
2103
+ // Execute transpiled component code (CommonJS format)
2104
+ ${transpiledCode}
2105
+
2106
+ // Capture the component export
2107
+ window.__frontmcp_component = module.exports.default || module.exports;
2108
+ `;
2109
+ if (cdnType === "umd") {
2110
+ return `
2111
+ <!-- Universal Component Script (transpiled) -->
2112
+ <script>
2113
+ (function() {
2114
+ ${wrappedCode}
2115
+ })();
2116
+ </script>`;
2117
+ } else {
2118
+ return `
2119
+ <!-- Universal Component Script (transpiled, ESM) -->
2120
+ <script type="module">
2121
+ function loadComponent() {
2122
+ ${wrappedCode}
2123
+ }
2124
+
2125
+ if (window.__reactReady) {
2126
+ loadComponent();
2127
+ } else {
2128
+ window.addEventListener('react:ready', loadComponent);
2129
+ }
2130
+ </script>`;
2131
+ }
2132
+ }
2133
+ /**
2134
+ * Build the universal runtime script section.
2135
+ */
2136
+ buildUniversalRuntimeScript(runtimeScript) {
2137
+ return `
2138
+ <!-- Universal Runtime -->
2139
+ <script>
2140
+ ${runtimeScript}
2141
+ </script>`;
2142
+ }
2143
+ /**
2144
+ * Build data injection script for universal mode.
2145
+ */
2146
+ buildUniversalDataScript(toolName, input, output, structuredContent, contentType, source, hasTranspiledComponent = false) {
2147
+ const safeJson = (value) => {
2148
+ try {
2149
+ return JSON.stringify(value);
2150
+ } catch {
2151
+ return "null";
2152
+ }
2153
+ };
2154
+ if (hasTranspiledComponent) {
2155
+ return `
2156
+ <!-- Universal Data Injection (React Component) -->
2157
+ <script>
2158
+ window.__frontmcp.setState({
2159
+ toolName: ${safeJson(toolName)},
2160
+ input: ${safeJson(input ?? null)},
2161
+ output: ${safeJson(output ?? null)},
2162
+ structuredContent: ${safeJson(structuredContent ?? null)},
2163
+ content: {
2164
+ type: 'react',
2165
+ source: window.__frontmcp_component
2166
+ },
2167
+ loading: false,
2168
+ error: null
2169
+ });
2170
+ </script>`;
2171
+ }
2172
+ const escapedSource = JSON.stringify(source);
2173
+ return `
2174
+ <!-- Universal Data Injection -->
2175
+ <script>
2176
+ window.__frontmcp.setState({
2177
+ toolName: ${safeJson(toolName)},
2178
+ input: ${safeJson(input ?? null)},
2179
+ output: ${safeJson(output ?? null)},
2180
+ structuredContent: ${safeJson(structuredContent ?? null)},
2181
+ content: {
2182
+ type: ${safeJson(contentType)},
2183
+ source: ${escapedSource}
2184
+ },
2185
+ loading: false,
2186
+ error: null
2187
+ });
2188
+ </script>`;
2189
+ }
2190
+ /**
2191
+ * Build the universal render script.
2192
+ */
2193
+ buildUniversalRenderScript(rootId, cdnType) {
2194
+ if (cdnType === "umd") {
2195
+ return `
2196
+ <!-- Universal Render Script (UMD - synchronous) -->
2197
+ <script>
2198
+ (function() {
2199
+ var container = document.getElementById('${rootId}');
2200
+ if (container && window.ReactDOM && window.ReactDOM.createRoot && window.__frontmcp.UniversalApp) {
2201
+ var root = window.ReactDOM.createRoot(container);
2202
+ root.render(React.createElement(window.__frontmcp.UniversalApp));
2203
+ } else if (container && window.ReactDOM && window.ReactDOM.render && window.__frontmcp.UniversalApp) {
2204
+ window.ReactDOM.render(
2205
+ React.createElement(window.__frontmcp.UniversalApp),
2206
+ container
2207
+ );
2208
+ }
2209
+ })();
2210
+ </script>`;
2211
+ } else {
2212
+ return `
2213
+ <!-- Universal Render Script (ESM - waits for React) -->
2214
+ <script type="module">
2215
+ function renderUniversalApp() {
2216
+ var container = document.getElementById('${rootId}');
2217
+ if (container && window.ReactDOM && window.ReactDOM.createRoot && window.__frontmcp.UniversalApp) {
2218
+ var root = window.ReactDOM.createRoot(container);
2219
+ root.render(React.createElement(window.__frontmcp.UniversalApp));
2220
+ }
2221
+ }
2222
+
2223
+ if (window.__reactReady) {
2224
+ renderUniversalApp();
2225
+ } else {
2226
+ window.addEventListener('react:ready', renderUniversalApp);
2227
+ }
2228
+ </script>`;
2229
+ }
2230
+ }
2231
+ /**
2232
+ * Assemble the complete universal static HTML document.
2233
+ */
2234
+ assembleUniversalStaticHTML(parts) {
2235
+ return `<!DOCTYPE html>
2236
+ <html lang="en">
2237
+ <head>
2238
+ <title>${escapeHtml(parts.title)}</title>
2239
+ ${parts.head}
2240
+ ${parts.reactRuntime}
2241
+ ${parts.frontmcpRuntime ?? ""}
2242
+ ${parts.cdnImports}
2243
+ ${parts.universalRuntimeScript}
2244
+ ${parts.componentScript ?? ""}
2245
+ ${parts.dataScript}
2246
+ </head>
2247
+ <body>
2248
+ <div id="${parts.rootId}" class="frontmcp-loading">
2249
+ <div class="frontmcp-spinner"></div>
2250
+ </div>
2251
+ ${parts.renderScript}
2252
+ </body>
2253
+ </html>`;
2254
+ }
2255
+ /**
2256
+ * Get cache statistics.
2257
+ */
2258
+ getCacheStats() {
2259
+ return this.cache.getStats();
2260
+ }
2261
+ /**
2262
+ * Clear the cache.
2263
+ */
2264
+ clearCache() {
2265
+ this.cache.clear();
2266
+ }
2267
+ /**
2268
+ * Clean up expired cache entries.
2269
+ */
2270
+ cleanupCache() {
2271
+ return this.cache.cleanup();
2272
+ }
2273
+ /**
2274
+ * Transform source code using esbuild/SWC.
2275
+ */
2276
+ async transform(source, sourceType, options) {
2277
+ const transform = await loadEsbuild();
2278
+ if (!transform) {
2279
+ throw new Error("No bundler available. Install esbuild or @swc/core: npm install esbuild");
2280
+ }
2281
+ const loader = this.getLoader(sourceType);
2282
+ const esbuildOptions = {
2283
+ loader,
2284
+ minify: options.minify,
2285
+ sourcemap: options.sourceMaps,
2286
+ target: options.target,
2287
+ format: options.format === "cjs" ? "cjs" : options.format === "esm" ? "esm" : "iife",
2288
+ jsx: "automatic",
2289
+ jsxImportSource: options.jsx.importSource
2290
+ };
2291
+ try {
2292
+ const result = await transform(source, esbuildOptions);
2293
+ return {
2294
+ code: result.code,
2295
+ map: result.map
2296
+ };
2297
+ } catch (error) {
2298
+ throw new Error(`Transform failed: ${error instanceof Error ? error.message : String(error)}`);
2299
+ }
2300
+ }
2301
+ /**
2302
+ * Get esbuild loader for source type.
2303
+ */
2304
+ getLoader(sourceType) {
2305
+ switch (sourceType) {
2306
+ case "jsx":
2307
+ return "jsx";
2308
+ case "tsx":
2309
+ return "tsx";
2310
+ case "mdx":
2311
+ return "tsx";
2312
+ // MDX compiles to JSX/TSX
2313
+ case "html":
2314
+ return "text";
2315
+ default:
2316
+ return "tsx";
2317
+ }
2318
+ }
2319
+ /**
2320
+ * Detect source type from content.
2321
+ */
2322
+ detectSourceType(source) {
2323
+ const hasTypeScript = /:\s*(string|number|boolean|any|unknown|void|never|object)\b/.test(source) || /interface\s+\w+/.test(source) || /type\s+\w+\s*=/.test(source) || /<\w+>/.test(source);
2324
+ const hasJSX = /<[A-Z][a-zA-Z]*/.test(source) || // Component tags
2325
+ /<[a-z]+\s/.test(source) || // HTML tags with attributes
2326
+ /<[a-z]+>/.test(source) || // Self-closing HTML tags
2327
+ /<\/[a-z]+>/.test(source);
2328
+ const hasMDX = /^#\s+/.test(source) || // Markdown heading
2329
+ /^-\s+/.test(source) || // Markdown list
2330
+ /\*\*\w+\*\*/.test(source) || // Bold
2331
+ /```\w*\n/.test(source);
2332
+ if (hasMDX && hasJSX) {
2333
+ return "mdx";
2334
+ }
2335
+ if (hasTypeScript && hasJSX) {
2336
+ return "tsx";
2337
+ }
2338
+ if (hasJSX) {
2339
+ return "jsx";
2340
+ }
2341
+ if (hasTypeScript) {
2342
+ return "tsx";
2343
+ }
2344
+ return "jsx";
2345
+ }
2346
+ /**
2347
+ * Merge bundle options with defaults.
2348
+ */
2349
+ mergeOptions(options) {
2350
+ return {
2351
+ sourceType: options.sourceType ?? DEFAULT_BUNDLE_OPTIONS.sourceType,
2352
+ format: options.format ?? DEFAULT_BUNDLE_OPTIONS.format,
2353
+ minify: options.minify ?? DEFAULT_BUNDLE_OPTIONS.minify,
2354
+ sourceMaps: options.sourceMaps ?? DEFAULT_BUNDLE_OPTIONS.sourceMaps,
2355
+ externals: options.externals ?? DEFAULT_BUNDLE_OPTIONS.externals,
2356
+ jsx: {
2357
+ ...DEFAULT_BUNDLE_OPTIONS.jsx,
2358
+ ...options.jsx
2359
+ },
2360
+ target: options.target ?? DEFAULT_BUNDLE_OPTIONS.target,
2361
+ globalName: options.globalName ?? DEFAULT_BUNDLE_OPTIONS.globalName,
2362
+ skipCache: options.skipCache ?? DEFAULT_BUNDLE_OPTIONS.skipCache
2363
+ };
2364
+ }
2365
+ /**
2366
+ * Build hydration script for client-side React.
2367
+ */
2368
+ buildHydrationScript(bundledCode, context) {
2369
+ const contextJson = context ? JSON.stringify(context) : "{}";
2370
+ return `
2371
+ (function() {
2372
+ var context = ${contextJson};
2373
+ var exports = {};
2374
+ var module = { exports: exports };
2375
+
2376
+ // Execute bundled code
2377
+ (function(exports, module) {
2378
+ ${bundledCode}
2379
+ })(exports, module);
2380
+
2381
+ // Get component
2382
+ var Component = module.exports.default || module.exports;
2383
+
2384
+ // Hydrate
2385
+ if (typeof ReactDOM !== 'undefined' && ReactDOM.hydrateRoot) {
2386
+ var container = document.getElementById('root') || document.body.firstElementChild;
2387
+ if (container) {
2388
+ ReactDOM.hydrateRoot(container, React.createElement(Component, context));
2389
+ }
2390
+ }
2391
+ })();
2392
+ `.trim();
2393
+ }
2394
+ // ============================================
2395
+ // Static HTML Helper Methods
2396
+ // ============================================
2397
+ /**
2398
+ * Merge static HTML options with defaults.
2399
+ */
2400
+ mergeStaticHTMLOptions(options) {
2401
+ return {
2402
+ sourceType: options.sourceType ?? DEFAULT_STATIC_HTML_OPTIONS.sourceType,
2403
+ targetPlatform: options.targetPlatform ?? DEFAULT_STATIC_HTML_OPTIONS.targetPlatform,
2404
+ minify: options.minify ?? DEFAULT_STATIC_HTML_OPTIONS.minify,
2405
+ skipCache: options.skipCache ?? DEFAULT_STATIC_HTML_OPTIONS.skipCache,
2406
+ rootId: sanitizeRootId(options.rootId ?? DEFAULT_STATIC_HTML_OPTIONS.rootId),
2407
+ widgetAccessible: options.widgetAccessible ?? DEFAULT_STATIC_HTML_OPTIONS.widgetAccessible,
2408
+ externals: {
2409
+ ...DEFAULT_STATIC_HTML_OPTIONS.externals,
2410
+ ...options.externals
2411
+ },
2412
+ // Universal mode options
2413
+ universal: options.universal ?? DEFAULT_STATIC_HTML_OPTIONS.universal,
2414
+ contentType: options.contentType ?? DEFAULT_STATIC_HTML_OPTIONS.contentType,
2415
+ includeMarkdown: options.includeMarkdown ?? DEFAULT_STATIC_HTML_OPTIONS.includeMarkdown,
2416
+ includeMdx: options.includeMdx ?? DEFAULT_STATIC_HTML_OPTIONS.includeMdx,
2417
+ // Build mode options
2418
+ buildMode: options.buildMode ?? DEFAULT_STATIC_HTML_OPTIONS.buildMode,
2419
+ dynamicOptions: options.dynamicOptions,
2420
+ hybridOptions: options.hybridOptions,
2421
+ // Pass-through options
2422
+ toolName: options.toolName,
2423
+ input: options.input,
2424
+ output: options.output,
2425
+ structuredContent: options.structuredContent,
2426
+ title: options.title,
2427
+ security: options.security,
2428
+ customCss: options.customCss,
2429
+ customComponents: options.customComponents,
2430
+ theme: options.theme
2431
+ };
2432
+ }
2433
+ /**
2434
+ * Build the <head> section for static HTML.
2435
+ */
2436
+ buildStaticHTMLHead(opts) {
2437
+ const parts = [];
2438
+ parts.push(`<meta charset="UTF-8">`);
2439
+ parts.push(`<meta name="viewport" content="width=device-width, initial-scale=1.0">`);
2440
+ for (const url of STATIC_HTML_CDN.fonts.preconnect) {
2441
+ parts.push(`<link rel="preconnect" href="${url}" crossorigin>`);
2442
+ }
2443
+ parts.push(`<link rel="stylesheet" href="${STATIC_HTML_CDN.fonts.inter}">`);
2444
+ parts.push(buildCDNScriptTag(CLOUDFLARE_CDN.tailwindCss));
2445
+ parts.push(this.buildThemeStyleBlock(opts.theme));
2446
+ parts.push(`<style>
2447
+ body { margin: 0; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
2448
+ .frontmcp-loading { display: flex; align-items: center; justify-content: center; min-height: 200px; }
2449
+ .frontmcp-spinner { width: 24px; height: 24px; border: 2px solid #e5e7eb; border-top-color: #3b82f6; border-radius: 50%; animation: spin 1s linear infinite; }
2450
+ @keyframes spin { to { transform: rotate(360deg); } }
2451
+ </style>`);
2452
+ if (opts.customCss) {
2453
+ parts.push(`<style>
2454
+ ${sanitizeCss(opts.customCss)}
2455
+ </style>`);
2456
+ }
2457
+ return parts.join("\n ");
2458
+ }
2459
+ /**
2460
+ * Build theme CSS variables as a :root style block.
2461
+ * Uses DEFAULT_THEME if no theme is provided.
2462
+ */
2463
+ buildThemeStyleBlock(theme = DEFAULT_THEME) {
2464
+ const cssVars = buildThemeCss(theme);
2465
+ return `<style>
2466
+ :root {
2467
+ ${cssVars}
2468
+ }
2469
+ </style>`;
2470
+ }
2471
+ /**
2472
+ * Build React runtime scripts for static HTML.
2473
+ */
2474
+ buildReactRuntimeScripts(externals, platform, cdnType) {
2475
+ const reactConfig = externals.react ?? "cdn";
2476
+ const reactDomConfig = externals.reactDom ?? "cdn";
2477
+ if (cdnType === "umd") {
2478
+ const reactUrl = reactConfig === "cdn" ? STATIC_HTML_CDN.umd.react : reactConfig;
2479
+ const reactDomUrl = reactDomConfig === "cdn" ? STATIC_HTML_CDN.umd.reactDom : reactDomConfig;
2480
+ return `
2481
+ <!-- React Runtime (UMD from cdnjs - Claude compatible) -->
2482
+ <script src="${reactUrl}"></script>
2483
+ <script src="${reactDomUrl}"></script>
2484
+ <script>
2485
+ // Webpack/esbuild polyfills for transpiled code (UMD globals)
2486
+ window.external_react_namespaceObject = window.React;
2487
+ window.jsx_runtime_namespaceObject = {
2488
+ jsx: function(type, props, key) {
2489
+ if (key !== undefined) props = Object.assign({}, props, { key: key });
2490
+ return React.createElement(type, props);
2491
+ },
2492
+ jsxs: function(type, props, key) {
2493
+ if (key !== undefined) props = Object.assign({}, props, { key: key });
2494
+ return React.createElement(type, props);
2495
+ },
2496
+ Fragment: React.Fragment
2497
+ };
2498
+ window.__reactReady = true;
2499
+ </script>`;
2500
+ } else {
2501
+ const reactUrl = reactConfig === "cdn" ? STATIC_HTML_CDN.esm.react : reactConfig;
2502
+ const reactDomUrl = reactDomConfig === "cdn" ? STATIC_HTML_CDN.esm.reactDom : reactDomConfig;
2503
+ return `
2504
+ <!-- React Runtime (ES modules from esm.sh) -->
2505
+ <script type="module">
2506
+ import React from '${reactUrl}';
2507
+ import { createRoot } from '${reactDomUrl}';
2508
+
2509
+ // Make React available globally
2510
+ window.React = React;
2511
+ window.ReactDOM = { createRoot };
2512
+
2513
+ // Webpack/esbuild polyfills for transpiled code
2514
+ window.external_react_namespaceObject = React;
2515
+ window.jsx_runtime_namespaceObject = {
2516
+ jsx: function(type, props, key) {
2517
+ if (key !== undefined) props = Object.assign({}, props, { key: key });
2518
+ return React.createElement(type, props);
2519
+ },
2520
+ jsxs: function(type, props, key) {
2521
+ if (key !== undefined) props = Object.assign({}, props, { key: key });
2522
+ return React.createElement(type, props);
2523
+ },
2524
+ Fragment: React.Fragment
2525
+ };
2526
+
2527
+ // Signal React is ready
2528
+ window.__reactReady = true;
2529
+ window.dispatchEvent(new CustomEvent('react:ready'));
2530
+ </script>`;
2531
+ }
2532
+ }
2533
+ /**
2534
+ * Build FrontMCP runtime (hooks and UI components).
2535
+ * Uses esbuild to transpile real React components at first use, then caches.
2536
+ * Falls back to manual implementation if esbuild fails.
2537
+ * Always inlined for reliability across platforms.
2538
+ */
2539
+ async buildFrontMCPRuntime() {
2540
+ let uiComponents;
2541
+ try {
2542
+ uiComponents = await getBrowserComponents();
2543
+ } catch {
2544
+ uiComponents = buildFallbackUIComponents();
2545
+ }
2546
+ return `
2547
+ <!-- FrontMCP Runtime (always inline) -->
2548
+ <script>
2549
+ // Custom require() shim for browser - maps module names to globals
2550
+ // This allows esbuild-transpiled code to work in browsers
2551
+ window.__moduleCache = {};
2552
+ window.require = function(moduleName) {
2553
+ // Check cache first
2554
+ if (window.__moduleCache[moduleName]) {
2555
+ return window.__moduleCache[moduleName];
2556
+ }
2557
+
2558
+ // Map module names to browser globals
2559
+ var moduleMap = {
2560
+ 'react': function() { return window.React; },
2561
+ 'react-dom': function() { return window.ReactDOM; },
2562
+ 'react-dom/client': function() { return window.ReactDOM; },
2563
+ 'react/jsx-runtime': function() { return window.jsx_runtime_namespaceObject; },
2564
+ 'react/jsx-dev-runtime': function() { return window.jsx_runtime_namespaceObject; },
2565
+ '@frontmcp/ui': function() { return window.frontmcp_ui_namespaceObject; },
2566
+ '@frontmcp/ui/react': function() { return window.frontmcp_ui_namespaceObject; },
2567
+ };
2568
+
2569
+ var resolver = moduleMap[moduleName];
2570
+ if (resolver) {
2571
+ var mod = resolver();
2572
+ window.__moduleCache[moduleName] = mod;
2573
+ return mod;
2574
+ }
2575
+
2576
+ console.warn('[FrontMCP] Unknown module requested:', moduleName);
2577
+ return {};
2578
+ };
2579
+
2580
+ // Async require for dynamic imports (returns Promise)
2581
+ window.requireAsync = function(moduleName) {
2582
+ return new Promise(function(resolve, reject) {
2583
+ // If module is already loaded, resolve immediately
2584
+ var mod = window.require(moduleName);
2585
+ if (mod && Object.keys(mod).length > 0) {
2586
+ resolve(mod);
2587
+ return;
2588
+ }
2589
+
2590
+ // For now, we don't support dynamic CDN loading
2591
+ // All required modules should be pre-loaded
2592
+ console.warn('[FrontMCP] Async module not available:', moduleName);
2593
+ resolve({});
2594
+ });
2595
+ };
2596
+
2597
+ // FrontMCP Hook implementations and state
2598
+ window.__frontmcp = {
2599
+ // Context for MCP bridge
2600
+ context: {
2601
+ toolName: null,
2602
+ toolInput: null,
2603
+ toolOutput: null,
2604
+ structuredContent: null,
2605
+ callTool: null,
2606
+ },
2607
+
2608
+ // Theme and display settings
2609
+ theme: 'light',
2610
+ displayMode: 'embedded',
2611
+ hostContext: {},
2612
+ capabilities: {},
2613
+
2614
+ // Set context from data injection
2615
+ setContext: function(ctx) {
2616
+ Object.assign(this.context, ctx);
2617
+ },
2618
+
2619
+ // State management (for universal mode compatibility)
2620
+ getState: function() {
2621
+ return {
2622
+ toolName: this.context.toolName,
2623
+ input: this.context.toolInput,
2624
+ output: this.context.toolOutput,
2625
+ structuredContent: this.context.structuredContent,
2626
+ loading: false,
2627
+ error: null
2628
+ };
2629
+ },
2630
+
2631
+ setState: function(partial) {
2632
+ if (partial.toolName !== undefined) this.context.toolName = partial.toolName;
2633
+ if (partial.input !== undefined) this.context.toolInput = partial.input;
2634
+ if (partial.output !== undefined) this.context.toolOutput = partial.output;
2635
+ if (partial.structuredContent !== undefined) this.context.structuredContent = partial.structuredContent;
2636
+ }
2637
+ };
2638
+
2639
+ // Hook: useToolOutput - returns the tool output data
2640
+ window.useToolOutput = function() {
2641
+ return window.__frontmcp.context.toolOutput;
2642
+ };
2643
+
2644
+ // Hook: useToolInput - returns the tool input arguments
2645
+ window.useToolInput = function() {
2646
+ return window.__frontmcp.context.toolInput;
2647
+ };
2648
+
2649
+ // Hook: useMcpBridgeContext - returns full bridge context
2650
+ window.useMcpBridgeContext = function() {
2651
+ return window.__frontmcp.context;
2652
+ };
2653
+
2654
+ // Hook: useCallTool - returns function to call other tools
2655
+ window.useCallTool = function() {
2656
+ return function(name, args) {
2657
+ if (window.__frontmcp.context.callTool) {
2658
+ return window.__frontmcp.context.callTool(name, args);
2659
+ }
2660
+ console.warn('[FrontMCP] callTool not available - widget may not have tool access');
2661
+ return Promise.resolve(null);
2662
+ };
2663
+ };
2664
+ </script>
2665
+ <!-- UI Components (Full-Featured, Browser-Compatible) -->
2666
+ <script>
2667
+ ${uiComponents}
2668
+ </script>`;
2669
+ }
2670
+ /**
2671
+ * Build data injection script for tool input/output.
2672
+ * Dispatches to mode-specific builders based on buildMode.
2673
+ */
2674
+ buildDataInjectionScript(toolName, input, output, structuredContent, buildMode = "static", cdnType = "esm", dynamicOptions, hybridOptions) {
2675
+ switch (buildMode) {
2676
+ case "dynamic":
2677
+ return this.buildDynamicDataScript(toolName, input, output, structuredContent, cdnType, dynamicOptions);
2678
+ case "hybrid":
2679
+ return this.buildHybridDataScript(toolName, input, structuredContent, hybridOptions);
2680
+ case "static":
2681
+ default:
2682
+ return this.buildStaticDataScript(toolName, input, output, structuredContent);
2683
+ }
2684
+ }
2685
+ /**
2686
+ * Build static data injection - data baked in at build time (current default).
2687
+ */
2688
+ buildStaticDataScript(toolName, input, output, structuredContent) {
2689
+ const safeJson = (value) => {
2690
+ try {
2691
+ return JSON.stringify(value);
2692
+ } catch {
2693
+ return "null";
2694
+ }
2695
+ };
2696
+ return `
2697
+ <!-- Tool Data Injection (Static Mode) -->
2698
+ <script>
2699
+ window.__mcpToolName = ${safeJson(toolName)};
2700
+ window.__mcpToolInput = ${safeJson(input ?? null)};
2701
+ window.__mcpToolOutput = ${safeJson(output ?? null)};
2702
+ window.__mcpStructuredContent = ${safeJson(structuredContent ?? null)};
2703
+
2704
+ // Initialize FrontMCP context
2705
+ window.__frontmcp.setContext({
2706
+ toolName: window.__mcpToolName,
2707
+ toolInput: window.__mcpToolInput,
2708
+ toolOutput: window.__mcpToolOutput,
2709
+ structuredContent: window.__mcpStructuredContent,
2710
+ });
2711
+ </script>`;
2712
+ }
2713
+ /**
2714
+ * Build dynamic data injection - platform-aware.
2715
+ * For OpenAI (ESM): subscribes to platform events for updates.
2716
+ * For non-OpenAI (UMD/Claude): uses placeholders for data injection.
2717
+ */
2718
+ buildDynamicDataScript(toolName, input, output, structuredContent, cdnType = "esm", options) {
2719
+ if (cdnType === "umd") {
2720
+ return this.buildDynamicWithPlaceholdersScript(toolName, structuredContent, options);
2721
+ }
2722
+ return this.buildDynamicWithSubscriptionScript(toolName, input, output, structuredContent, options);
2723
+ }
2724
+ /**
2725
+ * Build dynamic data injection for non-OpenAI platforms using placeholders.
2726
+ * Similar to hybrid mode but with platform-appropriate loading/error states.
2727
+ */
2728
+ buildDynamicWithPlaceholdersScript(toolName, structuredContent, options) {
2729
+ const safeJson = (value) => {
2730
+ try {
2731
+ return JSON.stringify(value);
2732
+ } catch {
2733
+ return "null";
2734
+ }
2735
+ };
2736
+ const outputPlaceholder = HYBRID_DATA_PLACEHOLDER;
2737
+ const inputPlaceholder = HYBRID_INPUT_PLACEHOLDER;
2738
+ const includeInitialData = options?.includeInitialData !== false;
2739
+ return `
2740
+ <!-- Tool Data Injection (Dynamic Mode - Placeholder-based for non-OpenAI) -->
2741
+ <script>
2742
+ window.__mcpToolName = ${safeJson(toolName)};
2743
+ window.__mcpToolInput = "${inputPlaceholder}";
2744
+ window.__mcpToolOutput = "${outputPlaceholder}";
2745
+ window.__mcpStructuredContent = ${safeJson(structuredContent ?? null)};
2746
+ window.__mcpHybridError = null;
2747
+
2748
+ (function() {
2749
+ var outputNotReplaced = false;
2750
+ var includeInitialData = ${includeInitialData};
2751
+
2752
+ // Parse output placeholder
2753
+ var rawOutput = window.__mcpToolOutput;
2754
+ if (typeof rawOutput === 'string' && rawOutput !== "${outputPlaceholder}") {
2755
+ try {
2756
+ window.__mcpToolOutput = JSON.parse(rawOutput);
2757
+ } catch (e) {
2758
+ console.warn('[FrontMCP] Failed to parse injected output data:', e);
2759
+ window.__mcpToolOutput = null;
2760
+ window.__mcpHybridError = 'Failed to parse output data';
2761
+ }
2762
+ } else if (rawOutput === "${outputPlaceholder}") {
2763
+ window.__mcpToolOutput = null;
2764
+ outputNotReplaced = true;
2765
+ }
2766
+
2767
+ // Parse input placeholder
2768
+ var rawInput = window.__mcpToolInput;
2769
+ if (typeof rawInput === 'string' && rawInput !== "${inputPlaceholder}") {
2770
+ try {
2771
+ window.__mcpToolInput = JSON.parse(rawInput);
2772
+ } catch (e) {
2773
+ console.warn('[FrontMCP] Failed to parse injected input data:', e);
2774
+ window.__mcpToolInput = null;
2775
+ }
2776
+ } else if (rawInput === "${inputPlaceholder}") {
2777
+ window.__mcpToolInput = null;
2778
+ }
2779
+
2780
+ // Handle placeholder not replaced - show error if expecting initial data
2781
+ if (outputNotReplaced && includeInitialData) {
2782
+ window.__mcpHybridError = 'No data provided. The output placeholder was not replaced.';
2783
+ }
2784
+ })();
2785
+
2786
+ // Initialize FrontMCP context with appropriate loading/error state
2787
+ if (window.__frontmcp && window.__frontmcp.setContext) {
2788
+ window.__frontmcp.setContext({
2789
+ toolName: window.__mcpToolName,
2790
+ toolInput: window.__mcpToolInput,
2791
+ toolOutput: window.__mcpToolOutput,
2792
+ structuredContent: window.__mcpStructuredContent,
2793
+ loading: ${!includeInitialData} && window.__mcpToolOutput === null && !window.__mcpHybridError,
2794
+ error: window.__mcpHybridError,
2795
+ });
2796
+ }
2797
+ </script>`;
2798
+ }
2799
+ /**
2800
+ * Build dynamic data injection for OpenAI using subscription pattern.
2801
+ */
2802
+ buildDynamicWithSubscriptionScript(toolName, input, output, structuredContent, options) {
2803
+ const safeJson = (value) => {
2804
+ try {
2805
+ return JSON.stringify(value);
2806
+ } catch {
2807
+ return "null";
2808
+ }
2809
+ };
2810
+ const includeInitial = options?.includeInitialData !== false;
2811
+ const subscribeToUpdates = options?.subscribeToUpdates !== false;
2812
+ const initialDataBlock = includeInitial ? `
2813
+ window.__mcpToolOutput = ${safeJson(output ?? null)};
2814
+ if (window.__frontmcp && window.__frontmcp.setState) {
2815
+ window.__frontmcp.setState({
2816
+ output: window.__mcpToolOutput,
2817
+ loading: false,
2818
+ });
2819
+ }` : `
2820
+ window.__mcpToolOutput = null;
2821
+ if (window.__frontmcp && window.__frontmcp.setState) {
2822
+ window.__frontmcp.setState({
2823
+ output: null,
2824
+ loading: true,
2825
+ });
2826
+ }`;
2827
+ const subscriptionBlock = subscribeToUpdates ? `
2828
+ // Subscribe to platform tool result updates
2829
+ (function() {
2830
+ function subscribeToUpdates() {
2831
+ // OpenAI Apps SDK
2832
+ if (window.openai && window.openai.canvas && window.openai.canvas.onToolResult) {
2833
+ window.openai.canvas.onToolResult(function(result) {
2834
+ window.__mcpToolOutput = result;
2835
+ if (window.__frontmcp && window.__frontmcp.setState) {
2836
+ window.__frontmcp.setState({
2837
+ output: result,
2838
+ loading: false,
2839
+ });
2840
+ }
2841
+ // Dispatch custom event for React hooks
2842
+ window.dispatchEvent(new CustomEvent('frontmcp:toolResult', { detail: result }));
2843
+ });
2844
+ return;
2845
+ }
2846
+
2847
+ // Fallback: listen for custom events (for testing/other platforms)
2848
+ window.addEventListener('frontmcp:injectData', function(e) {
2849
+ if (e.detail && e.detail.output !== undefined) {
2850
+ window.__mcpToolOutput = e.detail.output;
2851
+ if (window.__frontmcp && window.__frontmcp.setState) {
2852
+ window.__frontmcp.setState({
2853
+ output: e.detail.output,
2854
+ loading: false,
2855
+ });
2856
+ }
2857
+ }
2858
+ });
2859
+ }
2860
+
2861
+ // Subscribe when DOM is ready
2862
+ if (document.readyState === 'loading') {
2863
+ document.addEventListener('DOMContentLoaded', subscribeToUpdates);
2864
+ } else {
2865
+ subscribeToUpdates();
2866
+ }
2867
+ })();` : "";
2868
+ return `
2869
+ <!-- Tool Data Injection (Dynamic Mode - OpenAI Subscription) -->
2870
+ <script>
2871
+ window.__mcpToolName = ${safeJson(toolName)};
2872
+ window.__mcpToolInput = ${safeJson(input ?? null)};
2873
+ window.__mcpStructuredContent = ${safeJson(structuredContent ?? null)};
2874
+ ${initialDataBlock}
2875
+
2876
+ // Initialize FrontMCP context
2877
+ if (window.__frontmcp && window.__frontmcp.setContext) {
2878
+ window.__frontmcp.setContext({
2879
+ toolName: window.__mcpToolName,
2880
+ toolInput: window.__mcpToolInput,
2881
+ toolOutput: window.__mcpToolOutput,
2882
+ structuredContent: window.__mcpStructuredContent,
2883
+ });
2884
+ }
2885
+ ${subscriptionBlock}
2886
+ </script>`;
2887
+ }
2888
+ /**
2889
+ * Build hybrid data injection - shell with placeholders for runtime injection.
2890
+ * Use injectHybridData() or injectHybridDataFull() from @frontmcp/uipack to replace the placeholders.
2891
+ */
2892
+ buildHybridDataScript(toolName, _input, structuredContent, options) {
2893
+ const safeJson = (value) => {
2894
+ try {
2895
+ return JSON.stringify(value);
2896
+ } catch {
2897
+ return "null";
2898
+ }
2899
+ };
2900
+ const outputPlaceholder = options?.placeholder ?? HYBRID_DATA_PLACEHOLDER;
2901
+ const inputPlaceholder = options?.inputPlaceholder ?? HYBRID_INPUT_PLACEHOLDER;
2902
+ return `
2903
+ <!-- Tool Data Injection (Hybrid Mode - Replace placeholders with JSON) -->
2904
+ <script>
2905
+ window.__mcpToolName = ${safeJson(toolName)};
2906
+ window.__mcpToolInput = "${inputPlaceholder}";
2907
+ window.__mcpToolOutput = "${outputPlaceholder}";
2908
+ window.__mcpStructuredContent = ${safeJson(structuredContent ?? null)};
2909
+ window.__mcpHybridError = null;
2910
+
2911
+ // Parse placeholders if they've been replaced with actual JSON
2912
+ (function() {
2913
+ var outputNotReplaced = false;
2914
+
2915
+ // Parse output placeholder
2916
+ var rawOutput = window.__mcpToolOutput;
2917
+ if (typeof rawOutput === 'string' && rawOutput !== "${outputPlaceholder}") {
2918
+ try {
2919
+ window.__mcpToolOutput = JSON.parse(rawOutput);
2920
+ } catch (e) {
2921
+ console.warn('[FrontMCP] Failed to parse injected output data:', e);
2922
+ window.__mcpToolOutput = null;
2923
+ window.__mcpHybridError = 'Failed to parse output data';
2924
+ }
2925
+ } else if (rawOutput === "${outputPlaceholder}") {
2926
+ // Placeholder not replaced - no data was injected
2927
+ window.__mcpToolOutput = null;
2928
+ outputNotReplaced = true;
2929
+ }
2930
+
2931
+ // Parse input placeholder
2932
+ var rawInput = window.__mcpToolInput;
2933
+ if (typeof rawInput === 'string' && rawInput !== "${inputPlaceholder}") {
2934
+ try {
2935
+ window.__mcpToolInput = JSON.parse(rawInput);
2936
+ } catch (e) {
2937
+ console.warn('[FrontMCP] Failed to parse injected input data:', e);
2938
+ window.__mcpToolInput = null;
2939
+ }
2940
+ } else if (rawInput === "${inputPlaceholder}") {
2941
+ window.__mcpToolInput = null;
2942
+ }
2943
+
2944
+ // Set error if output placeholder was not replaced (no data provided)
2945
+ if (outputNotReplaced) {
2946
+ window.__mcpHybridError = 'No data provided. The output placeholder was not replaced.';
2947
+ }
2948
+ })();
2949
+
2950
+ // Initialize FrontMCP context with appropriate loading/error state
2951
+ if (window.__frontmcp && window.__frontmcp.setContext) {
2952
+ window.__frontmcp.setContext({
2953
+ toolName: window.__mcpToolName,
2954
+ toolInput: window.__mcpToolInput,
2955
+ toolOutput: window.__mcpToolOutput,
2956
+ structuredContent: window.__mcpStructuredContent,
2957
+ loading: false,
2958
+ error: window.__mcpHybridError,
2959
+ });
2960
+ }
2961
+ </script>`;
2962
+ }
2963
+ /**
2964
+ * Build component render script.
2965
+ * Wraps CommonJS code with module/exports shim to capture the component.
2966
+ */
2967
+ buildComponentRenderScript(componentCode, rootId, cdnType) {
2968
+ const wrappedCode = `
2969
+ // CommonJS module shim
2970
+ var module = { exports: {} };
2971
+ var exports = module.exports;
2972
+
2973
+ // Execute transpiled component code (CommonJS format)
2974
+ ${componentCode}
2975
+
2976
+ // Capture the component export
2977
+ window.__frontmcp_component = module.exports;
2978
+ `;
2979
+ if (cdnType === "umd") {
2980
+ return `
2981
+ <!-- Component Render Script (UMD - synchronous) -->
2982
+ <script>
2983
+ (function() {
2984
+ ${wrappedCode}
2985
+
2986
+ // Get the component
2987
+ var Component = window.__frontmcp_component.default || window.__frontmcp_component;
2988
+
2989
+ // Render the component
2990
+ var container = document.getElementById('${rootId}');
2991
+ if (container && window.ReactDOM && window.ReactDOM.createRoot) {
2992
+ var root = window.ReactDOM.createRoot(container);
2993
+ root.render(React.createElement(Component, {
2994
+ output: window.__mcpToolOutput,
2995
+ input: window.__mcpToolInput,
2996
+ }));
2997
+ } else if (container && window.ReactDOM && window.ReactDOM.render) {
2998
+ // Fallback for React 17
2999
+ window.ReactDOM.render(
3000
+ React.createElement(Component, {
3001
+ output: window.__mcpToolOutput,
3002
+ input: window.__mcpToolInput,
3003
+ }),
3004
+ container
3005
+ );
3006
+ }
3007
+ })();
3008
+ </script>`;
3009
+ } else {
3010
+ return `
3011
+ <!-- Component Render Script (ESM - waits for React) -->
3012
+ <script type="module">
3013
+ function renderComponent() {
3014
+ ${wrappedCode}
3015
+
3016
+ // Get the component
3017
+ var Component = window.__frontmcp_component.default || window.__frontmcp_component;
3018
+
3019
+ // Render the component
3020
+ var container = document.getElementById('${rootId}');
3021
+ if (container && window.ReactDOM && window.ReactDOM.createRoot) {
3022
+ var root = window.ReactDOM.createRoot(container);
3023
+ root.render(React.createElement(Component, {
3024
+ output: window.__mcpToolOutput,
3025
+ input: window.__mcpToolInput,
3026
+ }));
3027
+ }
3028
+ }
3029
+
3030
+ // Wait for React to be ready
3031
+ if (window.__reactReady) {
3032
+ renderComponent();
3033
+ } else {
3034
+ window.addEventListener('react:ready', renderComponent);
3035
+ }
3036
+ </script>`;
3037
+ }
3038
+ }
3039
+ /**
3040
+ * Assemble the complete static HTML document.
3041
+ */
3042
+ assembleStaticHTML(parts) {
3043
+ return `<!DOCTYPE html>
3044
+ <html lang="en">
3045
+ <head>
3046
+ <title>${escapeHtml(parts.title)}</title>
3047
+ ${parts.head}
3048
+ ${parts.reactRuntime}
3049
+ ${parts.frontmcpRuntime}
3050
+ ${parts.dataScript}
3051
+ </head>
3052
+ <body>
3053
+ <div id="${parts.rootId}" class="frontmcp-loading">
3054
+ <div class="frontmcp-spinner"></div>
3055
+ </div>
3056
+ ${parts.componentScript}
3057
+ </body>
3058
+ </html>`;
3059
+ }
3060
+ };
3061
+ function createBundler(options) {
3062
+ return new InMemoryBundler(options);
3063
+ }
3064
+
3065
+ // libs/ui/src/bundler/index.ts
3066
+ import { BundlerCache as BundlerCache2, hashContent as hashContent2, createCacheKey as createCacheKey2 } from "@frontmcp/uipack/bundler";
3067
+ import {
3068
+ validateSource as validateSource2,
3069
+ validateImports,
3070
+ validateSize as validateSize2,
3071
+ mergePolicy as mergePolicy2,
3072
+ throwOnViolations as throwOnViolations2
3073
+ } from "@frontmcp/uipack/bundler";
3074
+ import { executeCode, executeDefault as executeDefault2, isExecutionError } from "@frontmcp/uipack/bundler";
3075
+ import {
3076
+ DEFAULT_STORAGE_OPTIONS,
3077
+ calculateManifestSize,
3078
+ FilesystemStorage,
3079
+ createFilesystemStorage,
3080
+ RedisStorage,
3081
+ createRedisStorage,
3082
+ sha256,
3083
+ sha256Buffer,
3084
+ hashFile,
3085
+ hashFiles,
3086
+ calculateComponentHash,
3087
+ calculateQuickHash,
3088
+ generateBuildId,
3089
+ buildIdFromHash,
3090
+ ComponentBuilder,
3091
+ createFilesystemBuilder,
3092
+ createRedisBuilder
3093
+ } from "@frontmcp/uipack/bundler";
3094
+ export {
3095
+ ALL_PLATFORMS,
3096
+ BundlerCache2 as BundlerCache,
3097
+ ComponentBuilder,
3098
+ DEFAULT_BUNDLER_OPTIONS,
3099
+ DEFAULT_BUNDLE_OPTIONS,
3100
+ DEFAULT_SECURITY_POLICY,
3101
+ DEFAULT_STATIC_HTML_OPTIONS,
3102
+ DEFAULT_STORAGE_OPTIONS,
3103
+ ExecutionError2 as ExecutionError,
3104
+ FilesystemStorage,
3105
+ HYBRID_DATA_PLACEHOLDER,
3106
+ HYBRID_INPUT_PLACEHOLDER,
3107
+ InMemoryBundler,
3108
+ RedisStorage,
3109
+ STATIC_HTML_CDN,
3110
+ SecurityError,
3111
+ buildIdFromHash,
3112
+ calculateComponentHash,
3113
+ calculateManifestSize,
3114
+ calculateQuickHash,
3115
+ createBundler,
3116
+ createCacheKey2 as createCacheKey,
3117
+ createFilesystemBuilder,
3118
+ createFilesystemStorage,
3119
+ createRedisBuilder,
3120
+ createRedisStorage,
3121
+ executeCode,
3122
+ executeDefault2 as executeDefault,
3123
+ generateBuildId,
3124
+ getCdnTypeForPlatform,
3125
+ hashContent2 as hashContent,
3126
+ hashFile,
3127
+ hashFiles,
3128
+ isExecutionError,
3129
+ mergePolicy2 as mergePolicy,
3130
+ sha256,
3131
+ sha256Buffer,
3132
+ throwOnViolations2 as throwOnViolations,
3133
+ validateImports,
3134
+ validateSize2 as validateSize,
3135
+ validateSource2 as validateSource
3136
+ };