@frontmcp/ui 0.5.0

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 (393) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +438 -0
  3. package/package.json +147 -0
  4. package/src/adapters/index.d.ts +10 -0
  5. package/src/adapters/index.js +18 -0
  6. package/src/adapters/index.js.map +1 -0
  7. package/src/adapters/platform-meta.d.ts +165 -0
  8. package/src/adapters/platform-meta.js +310 -0
  9. package/src/adapters/platform-meta.js.map +1 -0
  10. package/src/base-template/bridge.d.ts +89 -0
  11. package/src/base-template/bridge.js +452 -0
  12. package/src/base-template/bridge.js.map +1 -0
  13. package/src/base-template/default-base-template.d.ts +91 -0
  14. package/src/base-template/default-base-template.js +435 -0
  15. package/src/base-template/default-base-template.js.map +1 -0
  16. package/src/base-template/index.d.ts +14 -0
  17. package/src/base-template/index.js +30 -0
  18. package/src/base-template/index.js.map +1 -0
  19. package/src/base-template/polyfills.d.ts +30 -0
  20. package/src/base-template/polyfills.js +190 -0
  21. package/src/base-template/polyfills.js.map +1 -0
  22. package/src/base-template/theme-styles.d.ts +73 -0
  23. package/src/base-template/theme-styles.js +95 -0
  24. package/src/base-template/theme-styles.js.map +1 -0
  25. package/src/bridge/adapters/base-adapter.d.ts +103 -0
  26. package/src/bridge/adapters/base-adapter.js +314 -0
  27. package/src/bridge/adapters/base-adapter.js.map +1 -0
  28. package/src/bridge/adapters/claude.adapter.d.ts +66 -0
  29. package/src/bridge/adapters/claude.adapter.js +145 -0
  30. package/src/bridge/adapters/claude.adapter.js.map +1 -0
  31. package/src/bridge/adapters/ext-apps.adapter.d.ts +142 -0
  32. package/src/bridge/adapters/ext-apps.adapter.js +416 -0
  33. package/src/bridge/adapters/ext-apps.adapter.js.map +1 -0
  34. package/src/bridge/adapters/gemini.adapter.d.ts +63 -0
  35. package/src/bridge/adapters/gemini.adapter.js +160 -0
  36. package/src/bridge/adapters/gemini.adapter.js.map +1 -0
  37. package/src/bridge/adapters/generic.adapter.d.ts +55 -0
  38. package/src/bridge/adapters/generic.adapter.js +108 -0
  39. package/src/bridge/adapters/generic.adapter.js.map +1 -0
  40. package/src/bridge/adapters/index.d.ts +25 -0
  41. package/src/bridge/adapters/index.js +65 -0
  42. package/src/bridge/adapters/index.js.map +1 -0
  43. package/src/bridge/adapters/openai.adapter.d.ts +64 -0
  44. package/src/bridge/adapters/openai.adapter.js +194 -0
  45. package/src/bridge/adapters/openai.adapter.js.map +1 -0
  46. package/src/bridge/core/adapter-registry.d.ts +121 -0
  47. package/src/bridge/core/adapter-registry.js +271 -0
  48. package/src/bridge/core/adapter-registry.js.map +1 -0
  49. package/src/bridge/core/bridge-factory.d.ts +198 -0
  50. package/src/bridge/core/bridge-factory.js +428 -0
  51. package/src/bridge/core/bridge-factory.js.map +1 -0
  52. package/src/bridge/core/index.d.ts +9 -0
  53. package/src/bridge/core/index.js +22 -0
  54. package/src/bridge/core/index.js.map +1 -0
  55. package/src/bridge/index.d.ts +61 -0
  56. package/src/bridge/index.js +94 -0
  57. package/src/bridge/index.js.map +1 -0
  58. package/src/bridge/runtime/iife-generator.d.ts +61 -0
  59. package/src/bridge/runtime/iife-generator.js +940 -0
  60. package/src/bridge/runtime/iife-generator.js.map +1 -0
  61. package/src/bridge/runtime/index.d.ts +8 -0
  62. package/src/bridge/runtime/index.js +16 -0
  63. package/src/bridge/runtime/index.js.map +1 -0
  64. package/src/bridge/types.d.ts +385 -0
  65. package/src/bridge/types.js +11 -0
  66. package/src/bridge/types.js.map +1 -0
  67. package/src/build/cdn-resources.d.ts +140 -0
  68. package/src/build/cdn-resources.js +314 -0
  69. package/src/build/cdn-resources.js.map +1 -0
  70. package/src/build/index.d.ts +294 -0
  71. package/src/build/index.js +325 -0
  72. package/src/build/index.js.map +1 -0
  73. package/src/build/widget-manifest.d.ts +212 -0
  74. package/src/build/widget-manifest.js +652 -0
  75. package/src/build/widget-manifest.js.map +1 -0
  76. package/src/bundler/bundler.d.ts +110 -0
  77. package/src/bundler/bundler.js +432 -0
  78. package/src/bundler/bundler.js.map +1 -0
  79. package/src/bundler/cache.d.ts +172 -0
  80. package/src/bundler/cache.js +250 -0
  81. package/src/bundler/cache.js.map +1 -0
  82. package/src/bundler/index.d.ts +41 -0
  83. package/src/bundler/index.js +73 -0
  84. package/src/bundler/index.js.map +1 -0
  85. package/src/bundler/sandbox/enclave-adapter.d.ts +120 -0
  86. package/src/bundler/sandbox/enclave-adapter.js +339 -0
  87. package/src/bundler/sandbox/enclave-adapter.js.map +1 -0
  88. package/src/bundler/sandbox/executor.d.ts +13 -0
  89. package/src/bundler/sandbox/executor.js +22 -0
  90. package/src/bundler/sandbox/executor.js.map +1 -0
  91. package/src/bundler/sandbox/policy.d.ts +61 -0
  92. package/src/bundler/sandbox/policy.js +238 -0
  93. package/src/bundler/sandbox/policy.js.map +1 -0
  94. package/src/bundler/types.d.ts +347 -0
  95. package/src/bundler/types.js +132 -0
  96. package/src/bundler/types.js.map +1 -0
  97. package/src/components/alert.d.ts +71 -0
  98. package/src/components/alert.js +189 -0
  99. package/src/components/alert.js.map +1 -0
  100. package/src/components/alert.schema.d.ts +114 -0
  101. package/src/components/alert.schema.js +105 -0
  102. package/src/components/alert.schema.js.map +1 -0
  103. package/src/components/avatar.d.ts +76 -0
  104. package/src/components/avatar.js +176 -0
  105. package/src/components/avatar.js.map +1 -0
  106. package/src/components/avatar.schema.d.ts +169 -0
  107. package/src/components/avatar.schema.js +103 -0
  108. package/src/components/avatar.schema.js.map +1 -0
  109. package/src/components/badge.d.ts +70 -0
  110. package/src/components/badge.js +149 -0
  111. package/src/components/badge.js.map +1 -0
  112. package/src/components/badge.schema.d.ts +109 -0
  113. package/src/components/badge.schema.js +96 -0
  114. package/src/components/badge.schema.js.map +1 -0
  115. package/src/components/button.d.ts +111 -0
  116. package/src/components/button.js +336 -0
  117. package/src/components/button.js.map +1 -0
  118. package/src/components/button.schema.d.ts +148 -0
  119. package/src/components/button.schema.js +121 -0
  120. package/src/components/button.schema.js.map +1 -0
  121. package/src/components/card.d.ts +60 -0
  122. package/src/components/card.js +117 -0
  123. package/src/components/card.js.map +1 -0
  124. package/src/components/card.schema.d.ts +113 -0
  125. package/src/components/card.schema.js +98 -0
  126. package/src/components/card.schema.js.map +1 -0
  127. package/src/components/form.d.ts +239 -0
  128. package/src/components/form.js +420 -0
  129. package/src/components/form.js.map +1 -0
  130. package/src/components/form.schema.d.ts +441 -0
  131. package/src/components/form.schema.js +406 -0
  132. package/src/components/form.schema.js.map +1 -0
  133. package/src/components/index.d.ts +29 -0
  134. package/src/components/index.js +98 -0
  135. package/src/components/index.js.map +1 -0
  136. package/src/components/list.d.ts +127 -0
  137. package/src/components/list.js +279 -0
  138. package/src/components/list.js.map +1 -0
  139. package/src/components/list.schema.d.ts +134 -0
  140. package/src/components/list.schema.js +168 -0
  141. package/src/components/list.schema.js.map +1 -0
  142. package/src/components/modal.d.ts +111 -0
  143. package/src/components/modal.js +260 -0
  144. package/src/components/modal.js.map +1 -0
  145. package/src/components/modal.schema.d.ts +186 -0
  146. package/src/components/modal.schema.js +167 -0
  147. package/src/components/modal.schema.js.map +1 -0
  148. package/src/components/table.d.ts +105 -0
  149. package/src/components/table.js +283 -0
  150. package/src/components/table.js.map +1 -0
  151. package/src/components/table.schema.d.ts +159 -0
  152. package/src/components/table.schema.js +173 -0
  153. package/src/components/table.schema.js.map +1 -0
  154. package/src/handlebars/helpers.d.ts +348 -0
  155. package/src/handlebars/helpers.js +605 -0
  156. package/src/handlebars/helpers.js.map +1 -0
  157. package/src/handlebars/index.d.ts +193 -0
  158. package/src/handlebars/index.js +350 -0
  159. package/src/handlebars/index.js.map +1 -0
  160. package/src/index.d.ts +50 -0
  161. package/src/index.js +192 -0
  162. package/src/index.js.map +1 -0
  163. package/src/layouts/base.d.ts +88 -0
  164. package/src/layouts/base.js +227 -0
  165. package/src/layouts/base.js.map +1 -0
  166. package/src/layouts/index.d.ts +7 -0
  167. package/src/layouts/index.js +25 -0
  168. package/src/layouts/index.js.map +1 -0
  169. package/src/layouts/presets.d.ts +133 -0
  170. package/src/layouts/presets.js +277 -0
  171. package/src/layouts/presets.js.map +1 -0
  172. package/src/pages/consent.d.ts +116 -0
  173. package/src/pages/consent.js +218 -0
  174. package/src/pages/consent.js.map +1 -0
  175. package/src/pages/error.d.ts +100 -0
  176. package/src/pages/error.js +263 -0
  177. package/src/pages/error.js.map +1 -0
  178. package/src/pages/index.d.ts +8 -0
  179. package/src/pages/index.js +27 -0
  180. package/src/pages/index.js.map +1 -0
  181. package/src/react/Alert.d.ts +101 -0
  182. package/src/react/Alert.js +51 -0
  183. package/src/react/Alert.js.map +1 -0
  184. package/src/react/Badge.d.ts +100 -0
  185. package/src/react/Badge.js +55 -0
  186. package/src/react/Badge.js.map +1 -0
  187. package/src/react/Button.d.ts +108 -0
  188. package/src/react/Button.js +52 -0
  189. package/src/react/Button.js.map +1 -0
  190. package/src/react/Card.d.ts +103 -0
  191. package/src/react/Card.js +55 -0
  192. package/src/react/Card.js.map +1 -0
  193. package/src/react/hooks/context.d.ts +178 -0
  194. package/src/react/hooks/context.js +287 -0
  195. package/src/react/hooks/context.js.map +1 -0
  196. package/src/react/hooks/index.d.ts +41 -0
  197. package/src/react/hooks/index.js +61 -0
  198. package/src/react/hooks/index.js.map +1 -0
  199. package/src/react/hooks/tools.d.ts +283 -0
  200. package/src/react/hooks/tools.js +465 -0
  201. package/src/react/hooks/tools.js.map +1 -0
  202. package/src/react/index.d.ts +80 -0
  203. package/src/react/index.js +113 -0
  204. package/src/react/index.js.map +1 -0
  205. package/src/react/types.d.ts +105 -0
  206. package/src/react/types.js +12 -0
  207. package/src/react/types.js.map +1 -0
  208. package/src/react/utils.d.ts +42 -0
  209. package/src/react/utils.js +99 -0
  210. package/src/react/utils.js.map +1 -0
  211. package/src/registry/index.d.ts +45 -0
  212. package/src/registry/index.js +67 -0
  213. package/src/registry/index.js.map +1 -0
  214. package/src/registry/render-template.d.ts +86 -0
  215. package/src/registry/render-template.js +239 -0
  216. package/src/registry/render-template.js.map +1 -0
  217. package/src/registry/tool-ui.registry.d.ts +260 -0
  218. package/src/registry/tool-ui.registry.js +438 -0
  219. package/src/registry/tool-ui.registry.js.map +1 -0
  220. package/src/registry/uri-utils.d.ts +55 -0
  221. package/src/registry/uri-utils.js +97 -0
  222. package/src/registry/uri-utils.js.map +1 -0
  223. package/src/render/index.d.ts +7 -0
  224. package/src/render/index.js +14 -0
  225. package/src/render/index.js.map +1 -0
  226. package/src/render/prerender.d.ts +56 -0
  227. package/src/render/prerender.js +98 -0
  228. package/src/render/prerender.js.map +1 -0
  229. package/src/renderers/cache.d.ts +144 -0
  230. package/src/renderers/cache.js +240 -0
  231. package/src/renderers/cache.js.map +1 -0
  232. package/src/renderers/html.renderer.d.ts +122 -0
  233. package/src/renderers/html.renderer.js +204 -0
  234. package/src/renderers/html.renderer.js.map +1 -0
  235. package/src/renderers/index.d.ts +35 -0
  236. package/src/renderers/index.js +70 -0
  237. package/src/renderers/index.js.map +1 -0
  238. package/src/renderers/mdx.renderer.d.ts +119 -0
  239. package/src/renderers/mdx.renderer.js +305 -0
  240. package/src/renderers/mdx.renderer.js.map +1 -0
  241. package/src/renderers/react.renderer.d.ts +95 -0
  242. package/src/renderers/react.renderer.js +260 -0
  243. package/src/renderers/react.renderer.js.map +1 -0
  244. package/src/renderers/registry.d.ts +133 -0
  245. package/src/renderers/registry.js +232 -0
  246. package/src/renderers/registry.js.map +1 -0
  247. package/src/renderers/types.d.ts +341 -0
  248. package/src/renderers/types.js +9 -0
  249. package/src/renderers/types.js.map +1 -0
  250. package/src/renderers/utils/detect.d.ts +106 -0
  251. package/src/renderers/utils/detect.js +267 -0
  252. package/src/renderers/utils/detect.js.map +1 -0
  253. package/src/renderers/utils/hash.d.ts +39 -0
  254. package/src/renderers/utils/hash.js +75 -0
  255. package/src/renderers/utils/hash.js.map +1 -0
  256. package/src/renderers/utils/index.d.ts +8 -0
  257. package/src/renderers/utils/index.js +28 -0
  258. package/src/renderers/utils/index.js.map +1 -0
  259. package/src/renderers/utils/transpiler.d.ts +88 -0
  260. package/src/renderers/utils/transpiler.js +215 -0
  261. package/src/renderers/utils/transpiler.js.map +1 -0
  262. package/src/runtime/adapters/html.adapter.d.ts +58 -0
  263. package/src/runtime/adapters/html.adapter.js +131 -0
  264. package/src/runtime/adapters/html.adapter.js.map +1 -0
  265. package/src/runtime/adapters/index.d.ts +25 -0
  266. package/src/runtime/adapters/index.js +54 -0
  267. package/src/runtime/adapters/index.js.map +1 -0
  268. package/src/runtime/adapters/mdx.adapter.d.ts +72 -0
  269. package/src/runtime/adapters/mdx.adapter.js +241 -0
  270. package/src/runtime/adapters/mdx.adapter.js.map +1 -0
  271. package/src/runtime/adapters/react.adapter.d.ts +69 -0
  272. package/src/runtime/adapters/react.adapter.js +245 -0
  273. package/src/runtime/adapters/react.adapter.js.map +1 -0
  274. package/src/runtime/adapters/types.d.ts +94 -0
  275. package/src/runtime/adapters/types.js +11 -0
  276. package/src/runtime/adapters/types.js.map +1 -0
  277. package/src/runtime/csp.d.ts +37 -0
  278. package/src/runtime/csp.js +140 -0
  279. package/src/runtime/csp.js.map +1 -0
  280. package/src/runtime/index.d.ts +16 -0
  281. package/src/runtime/index.js +72 -0
  282. package/src/runtime/index.js.map +1 -0
  283. package/src/runtime/mcp-bridge.d.ts +100 -0
  284. package/src/runtime/mcp-bridge.js +581 -0
  285. package/src/runtime/mcp-bridge.js.map +1 -0
  286. package/src/runtime/renderer-runtime.d.ts +132 -0
  287. package/src/runtime/renderer-runtime.js +389 -0
  288. package/src/runtime/renderer-runtime.js.map +1 -0
  289. package/src/runtime/sanitizer.d.ts +171 -0
  290. package/src/runtime/sanitizer.js +318 -0
  291. package/src/runtime/sanitizer.js.map +1 -0
  292. package/src/runtime/types.d.ts +414 -0
  293. package/src/runtime/types.js +12 -0
  294. package/src/runtime/types.js.map +1 -0
  295. package/src/runtime/wrapper.d.ts +375 -0
  296. package/src/runtime/wrapper.js +1793 -0
  297. package/src/runtime/wrapper.js.map +1 -0
  298. package/src/styles/index.d.ts +7 -0
  299. package/src/styles/index.js +11 -0
  300. package/src/styles/index.js.map +1 -0
  301. package/src/styles/variants.d.ts +50 -0
  302. package/src/styles/variants.js +175 -0
  303. package/src/styles/variants.js.map +1 -0
  304. package/src/theme/cdn.d.ts +194 -0
  305. package/src/theme/cdn.js +375 -0
  306. package/src/theme/cdn.js.map +1 -0
  307. package/src/theme/index.d.ts +17 -0
  308. package/src/theme/index.js +57 -0
  309. package/src/theme/index.js.map +1 -0
  310. package/src/theme/platforms.d.ts +106 -0
  311. package/src/theme/platforms.js +161 -0
  312. package/src/theme/platforms.js.map +1 -0
  313. package/src/theme/presets/github-openai.d.ts +49 -0
  314. package/src/theme/presets/github-openai.js +189 -0
  315. package/src/theme/presets/github-openai.js.map +1 -0
  316. package/src/theme/presets/index.d.ts +10 -0
  317. package/src/theme/presets/index.js +17 -0
  318. package/src/theme/presets/index.js.map +1 -0
  319. package/src/theme/theme.d.ts +395 -0
  320. package/src/theme/theme.js +332 -0
  321. package/src/theme/theme.js.map +1 -0
  322. package/src/tool-template/builder.d.ts +212 -0
  323. package/src/tool-template/builder.js +397 -0
  324. package/src/tool-template/builder.js.map +1 -0
  325. package/src/tool-template/index.d.ts +15 -0
  326. package/src/tool-template/index.js +38 -0
  327. package/src/tool-template/index.js.map +1 -0
  328. package/src/types/index.d.ts +13 -0
  329. package/src/types/index.js +26 -0
  330. package/src/types/index.js.map +1 -0
  331. package/src/types/ui-config.d.ts +357 -0
  332. package/src/types/ui-config.js +12 -0
  333. package/src/types/ui-config.js.map +1 -0
  334. package/src/types/ui-runtime.d.ts +965 -0
  335. package/src/types/ui-runtime.js +117 -0
  336. package/src/types/ui-runtime.js.map +1 -0
  337. package/src/validation/error-box.d.ts +55 -0
  338. package/src/validation/error-box.js +75 -0
  339. package/src/validation/error-box.js.map +1 -0
  340. package/src/validation/index.d.ts +12 -0
  341. package/src/validation/index.js +21 -0
  342. package/src/validation/index.js.map +1 -0
  343. package/src/validation/wrapper.d.ts +96 -0
  344. package/src/validation/wrapper.js +117 -0
  345. package/src/validation/wrapper.js.map +1 -0
  346. package/src/web-components/core/attribute-parser.d.ts +85 -0
  347. package/src/web-components/core/attribute-parser.js +189 -0
  348. package/src/web-components/core/attribute-parser.js.map +1 -0
  349. package/src/web-components/core/base-element.d.ts +197 -0
  350. package/src/web-components/core/base-element.js +289 -0
  351. package/src/web-components/core/base-element.js.map +1 -0
  352. package/src/web-components/core/index.d.ts +8 -0
  353. package/src/web-components/core/index.js +18 -0
  354. package/src/web-components/core/index.js.map +1 -0
  355. package/src/web-components/elements/fmcp-alert.d.ts +45 -0
  356. package/src/web-components/elements/fmcp-alert.js +93 -0
  357. package/src/web-components/elements/fmcp-alert.js.map +1 -0
  358. package/src/web-components/elements/fmcp-badge.d.ts +46 -0
  359. package/src/web-components/elements/fmcp-badge.js +99 -0
  360. package/src/web-components/elements/fmcp-badge.js.map +1 -0
  361. package/src/web-components/elements/fmcp-button.d.ts +124 -0
  362. package/src/web-components/elements/fmcp-button.js +233 -0
  363. package/src/web-components/elements/fmcp-button.js.map +1 -0
  364. package/src/web-components/elements/fmcp-card.d.ts +52 -0
  365. package/src/web-components/elements/fmcp-card.js +115 -0
  366. package/src/web-components/elements/fmcp-card.js.map +1 -0
  367. package/src/web-components/elements/fmcp-input.d.ts +95 -0
  368. package/src/web-components/elements/fmcp-input.js +248 -0
  369. package/src/web-components/elements/fmcp-input.js.map +1 -0
  370. package/src/web-components/elements/fmcp-select.d.ts +99 -0
  371. package/src/web-components/elements/fmcp-select.js +243 -0
  372. package/src/web-components/elements/fmcp-select.js.map +1 -0
  373. package/src/web-components/elements/index.d.ts +12 -0
  374. package/src/web-components/elements/index.js +34 -0
  375. package/src/web-components/elements/index.js.map +1 -0
  376. package/src/web-components/index.d.ts +49 -0
  377. package/src/web-components/index.js +75 -0
  378. package/src/web-components/index.js.map +1 -0
  379. package/src/web-components/register.d.ts +56 -0
  380. package/src/web-components/register.js +80 -0
  381. package/src/web-components/register.js.map +1 -0
  382. package/src/web-components/types.d.ts +121 -0
  383. package/src/web-components/types.js +25 -0
  384. package/src/web-components/types.js.map +1 -0
  385. package/src/widgets/index.d.ts +7 -0
  386. package/src/widgets/index.js +24 -0
  387. package/src/widgets/index.js.map +1 -0
  388. package/src/widgets/progress.d.ts +132 -0
  389. package/src/widgets/progress.js +303 -0
  390. package/src/widgets/progress.js.map +1 -0
  391. package/src/widgets/resource.d.ts +162 -0
  392. package/src/widgets/resource.js +340 -0
  393. package/src/widgets/resource.js.map +1 -0
@@ -0,0 +1,652 @@
1
+ "use strict";
2
+ /**
3
+ * Widget Manifest Builder
4
+ *
5
+ * Builds static widget wrappers with embedded manifests for tool UIs.
6
+ * Produces complete HTML documents with FrontMCP Bridge runtime.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.detectUIType = detectUIType;
12
+ exports.buildCSPForType = buildCSPForType;
13
+ exports.buildCSPMetaContent = buildCSPMetaContent;
14
+ exports.getRendererAssets = getRendererAssets;
15
+ exports.buildToolWidgetManifest = buildToolWidgetManifest;
16
+ exports.batchBuildWidgets = batchBuildWidgets;
17
+ exports.buildToolResponseMeta = buildToolResponseMeta;
18
+ exports.getOutputModeForClient = getOutputModeForClient;
19
+ const ui_runtime_1 = require("../types/ui-runtime");
20
+ const cdn_resources_1 = require("./cdn-resources");
21
+ const wrapper_1 = require("../runtime/wrapper");
22
+ const registry_1 = require("../renderers/registry");
23
+ const renderers_1 = require("../renderers");
24
+ // ============================================
25
+ // UI Type Detection
26
+ // ============================================
27
+ /**
28
+ * Detect the UI type from a template.
29
+ *
30
+ * @param template - Widget template
31
+ * @returns Detected UI type
32
+ */
33
+ function detectUIType(template) {
34
+ const detection = (0, renderers_1.detectTemplateType)(template);
35
+ switch (detection.type) {
36
+ case 'react':
37
+ return 'react';
38
+ case 'mdx':
39
+ return 'mdx';
40
+ case 'jsx-string':
41
+ return 'react'; // JSX strings are rendered as React
42
+ case 'html-string':
43
+ case 'html-function':
44
+ return 'html';
45
+ default:
46
+ return 'auto';
47
+ }
48
+ }
49
+ // ============================================
50
+ // CSP Building
51
+ // ============================================
52
+ /**
53
+ * Build CSP directives for a UI type.
54
+ *
55
+ * @param uiType - UI renderer type
56
+ * @param userCsp - User-provided CSP overrides
57
+ * @returns Complete CSP directives
58
+ */
59
+ function buildCSPForType(uiType, userCsp) {
60
+ const baseCsp = ui_runtime_1.DEFAULT_CSP_BY_TYPE[uiType] ?? ui_runtime_1.DEFAULT_CSP_BY_TYPE['auto'];
61
+ if (!userCsp) {
62
+ return { ...baseCsp };
63
+ }
64
+ // Merge user CSP with base CSP
65
+ return {
66
+ scriptSrc: mergeCspArray(baseCsp.scriptSrc, userCsp.scriptSrc),
67
+ styleSrc: mergeCspArray(baseCsp.styleSrc, userCsp.styleSrc),
68
+ connectSrc: mergeCspArray(baseCsp.connectSrc, userCsp.connectSrc),
69
+ imgSrc: userCsp.imgSrc ?? baseCsp.imgSrc,
70
+ fontSrc: userCsp.fontSrc ?? baseCsp.fontSrc,
71
+ defaultSrc: userCsp.defaultSrc ?? baseCsp.defaultSrc,
72
+ frameSrc: userCsp.frameSrc ?? baseCsp.frameSrc,
73
+ objectSrc: userCsp.objectSrc ?? baseCsp.objectSrc,
74
+ };
75
+ }
76
+ /**
77
+ * Merge CSP arrays, preserving uniqueness.
78
+ */
79
+ function mergeCspArray(base, override) {
80
+ if (!override)
81
+ return [...base];
82
+ const merged = new Set([...base, ...override]);
83
+ return Array.from(merged);
84
+ }
85
+ /**
86
+ * Build CSP meta tag content.
87
+ */
88
+ function buildCSPMetaContent(csp) {
89
+ const directives = [];
90
+ if (csp.defaultSrc?.length) {
91
+ directives.push(`default-src ${csp.defaultSrc.join(' ')}`);
92
+ }
93
+ if (csp.scriptSrc.length) {
94
+ directives.push(`script-src ${csp.scriptSrc.join(' ')}`);
95
+ }
96
+ if (csp.styleSrc.length) {
97
+ directives.push(`style-src ${csp.styleSrc.join(' ')}`);
98
+ }
99
+ if (csp.connectSrc.length) {
100
+ directives.push(`connect-src ${csp.connectSrc.join(' ')}`);
101
+ }
102
+ if (csp.imgSrc?.length) {
103
+ directives.push(`img-src ${csp.imgSrc.join(' ')}`);
104
+ }
105
+ if (csp.fontSrc?.length) {
106
+ directives.push(`font-src ${csp.fontSrc.join(' ')}`);
107
+ }
108
+ if (csp.frameSrc?.length) {
109
+ directives.push(`frame-src ${csp.frameSrc.join(' ')}`);
110
+ }
111
+ if (csp.objectSrc?.length) {
112
+ directives.push(`object-src ${csp.objectSrc.join(' ')}`);
113
+ }
114
+ return directives.join('; ');
115
+ }
116
+ // ============================================
117
+ // Renderer Assets
118
+ // ============================================
119
+ /**
120
+ * Get renderer assets for a UI type.
121
+ *
122
+ * @param uiType - UI renderer type
123
+ * @param resourceMode - Resource loading mode (cdn or inline)
124
+ * @returns Required renderer assets with CDN URLs or inline placeholders
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * // Get CDN-based assets for React
129
+ * const assets = getRendererAssets('react', 'cdn');
130
+ * console.log(assets.react?.url);
131
+ * // "https://unpkg.com/react@18/umd/react.production.min.js"
132
+ *
133
+ * // Get inline-mode assets
134
+ * const inlineAssets = getRendererAssets('react', 'inline');
135
+ * // inlineAssets.mode === 'inline'
136
+ * ```
137
+ */
138
+ function getRendererAssets(uiType, resourceMode = 'cdn') {
139
+ // Use the CDN resources helper which provides proper CDN URLs
140
+ return (0, cdn_resources_1.getDefaultAssets)(uiType, resourceMode);
141
+ }
142
+ // ============================================
143
+ // Hash Generation
144
+ // ============================================
145
+ /**
146
+ * Generate a hash for content.
147
+ */
148
+ async function generateHash(content) {
149
+ // Use Web Crypto API if available
150
+ if (typeof crypto !== 'undefined' && crypto.subtle) {
151
+ const encoder = new TextEncoder();
152
+ const data = encoder.encode(content);
153
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
154
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
155
+ return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
156
+ }
157
+ // Fallback: simple hash
158
+ let hash = 0;
159
+ for (let i = 0; i < content.length; i++) {
160
+ const char = content.charCodeAt(i);
161
+ hash = (hash << 5) - hash + char;
162
+ hash = hash & hash;
163
+ }
164
+ return Math.abs(hash).toString(16).padStart(8, '0');
165
+ }
166
+ // ============================================
167
+ // Main Builder
168
+ // ============================================
169
+ /**
170
+ * Build a widget manifest for a tool.
171
+ *
172
+ * Creates a static widget wrapper with embedded manifest.
173
+ * The widget can be cached and reused across tool invocations.
174
+ *
175
+ * @param options - Build options
176
+ * @returns Build result with HTML, manifest, and metadata
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * import { buildToolWidgetManifest } from '@frontmcp/ui/build';
181
+ *
182
+ * const result = await buildToolWidgetManifest({
183
+ * toolName: 'weather.get',
184
+ * uiConfig: {
185
+ * template: WeatherWidget,
186
+ * uiType: 'react',
187
+ * displayMode: 'inline',
188
+ * widgetAccessible: true,
189
+ * },
190
+ * schema: { type: 'object', properties: { ... } },
191
+ * });
192
+ *
193
+ * // Cache the HTML
194
+ * cache.set(`ui://widget/${result.manifest.tool}.html`, result.html);
195
+ * ```
196
+ */
197
+ async function buildToolWidgetManifest(options) {
198
+ const { toolName, uiConfig, schema, theme, sampleInput, sampleOutput } = options;
199
+ // Resolve UI type
200
+ // Use type assertion to handle complex generic template types
201
+ const uiType = (0, ui_runtime_1.isUIType)(uiConfig.uiType)
202
+ ? uiConfig.uiType
203
+ : detectUIType(uiConfig.template);
204
+ // Resolve display mode
205
+ const displayMode = uiConfig.displayMode ?? 'inline';
206
+ // Resolve bundling mode
207
+ const bundlingMode = uiConfig.bundlingMode ?? 'static';
208
+ // Resolve resource mode (cdn or inline)
209
+ const resourceMode = (0, ui_runtime_1.isResourceMode)(uiConfig.resourceMode)
210
+ ? uiConfig.resourceMode
211
+ : 'cdn';
212
+ // Build CSP
213
+ const csp = buildCSPForType(uiType, uiConfig.csp);
214
+ // Get renderer assets based on resource mode
215
+ const rendererAssets = getRendererAssets(uiType, resourceMode);
216
+ // Render the template to get initial content
217
+ // Cast to generic type to avoid complex type inference issues
218
+ const templateConfig = uiConfig;
219
+ const content = await renderTemplate(templateConfig, {
220
+ input: (sampleInput ?? {}),
221
+ output: (sampleOutput ?? {}),
222
+ uiType,
223
+ });
224
+ // Generate component code for client-side rendering (React/MDX only)
225
+ const componentCode = (uiType === 'react' || uiType === 'mdx')
226
+ ? buildComponentCode(uiConfig.template, toolName)
227
+ : undefined;
228
+ // Build manifest
229
+ // Note: We intentionally omit 'uri' since we're not using resource-based serving.
230
+ // The content/html is returned directly in the tool response.
231
+ const manifestBase = {
232
+ tool: toolName,
233
+ uiType,
234
+ bundlingMode,
235
+ displayMode,
236
+ widgetAccessible: uiConfig.widgetAccessible ?? false,
237
+ schema: schema ?? {},
238
+ csp,
239
+ rendererAssets,
240
+ createdAt: new Date().toISOString(),
241
+ description: uiConfig.widgetDescription,
242
+ };
243
+ // Convert CSPDirectives to UIContentSecurityPolicy for wrapper
244
+ const wrapperCsp = uiConfig.csp ? {
245
+ connectDomains: uiConfig.csp.connectSrc,
246
+ resourceDomains: [
247
+ ...(uiConfig.csp.scriptSrc ?? []),
248
+ ...(uiConfig.csp.styleSrc ?? []),
249
+ ...(uiConfig.csp.imgSrc ?? []),
250
+ ].filter((d) => d !== "'self'" && d !== "'unsafe-inline'"),
251
+ } : undefined;
252
+ // Build manifest script to embed in the page
253
+ const manifestScript = buildManifestScript(manifestBase);
254
+ // Prepend manifest script to content so it's available before the UI renders
255
+ const contentWithManifest = manifestScript + '\n' + content;
256
+ // Build the complete HTML with manifest embedded
257
+ // Use inlineScripts when resourceMode is 'inline' (for blocked-network environments)
258
+ const html = (0, wrapper_1.wrapToolUIUniversal)({
259
+ content: contentWithManifest,
260
+ toolName,
261
+ input: (sampleInput ?? {}),
262
+ output: sampleOutput,
263
+ csp: wrapperCsp,
264
+ widgetAccessible: uiConfig.widgetAccessible,
265
+ includeBridge: true,
266
+ rendererType: uiType,
267
+ inlineScripts: resourceMode === 'inline',
268
+ resourceMode, // Pass resource mode for CDN script generation
269
+ });
270
+ // Generate hash based on tool name + content (for cache invalidation)
271
+ // Including toolName ensures different tools have different hashes even if content is similar
272
+ const hash = await generateHash(`${toolName}:${content}`);
273
+ // Complete manifest with hash
274
+ const manifest = {
275
+ ...manifestBase,
276
+ hash: `sha256-${hash}`,
277
+ };
278
+ // Calculate sizes
279
+ const contentSize = new TextEncoder().encode(content).length;
280
+ const htmlSize = new TextEncoder().encode(html).length;
281
+ const gzipSize = Math.round(htmlSize * 0.25); // Rough estimate
282
+ return {
283
+ // Transpiled content only (for capable clients like OpenAI)
284
+ content,
285
+ // Full HTML document (for limited/unknown MCP clients)
286
+ html,
287
+ manifest,
288
+ hash,
289
+ rendererType: uiType,
290
+ // Component code for client-side rendering (React/MDX only)
291
+ componentCode,
292
+ contentSize,
293
+ htmlSize,
294
+ gzipSize,
295
+ // Deprecated, kept for backwards compatibility
296
+ size: htmlSize,
297
+ };
298
+ }
299
+ /**
300
+ * Build the manifest script tag for embedding in HTML.
301
+ */
302
+ function buildManifestScript(manifest) {
303
+ // Escape for embedding in script tag
304
+ const json = JSON.stringify(manifest)
305
+ .replace(/</g, '\\u003c')
306
+ .replace(/>/g, '\\u003e')
307
+ .replace(/&/g, '\\u0026');
308
+ return `
309
+ <script type="application/json" id="frontmcp-widget-manifest">
310
+ ${json}
311
+ </script>
312
+ <script>
313
+ (function() {
314
+ try {
315
+ var manifest = JSON.parse(document.getElementById('frontmcp-widget-manifest').textContent);
316
+ window.__frontmcp = window.__frontmcp || {};
317
+ window.__frontmcp.widget = window.__frontmcp.widget || {};
318
+ window.__frontmcp.widget.manifest = manifest;
319
+ } catch (e) {
320
+ console.error('[FrontMCP] Failed to parse widget manifest:', e);
321
+ }
322
+ })();
323
+ </script>
324
+ `.trim();
325
+ }
326
+ // ============================================
327
+ // Component Code Builder (for Client-Side Rendering)
328
+ // ============================================
329
+ /**
330
+ * Build client-side component code for React templates.
331
+ *
332
+ * This converts the server-side React component into a string that can be
333
+ * embedded in the widget HTML for client-side rendering when tool output
334
+ * becomes available.
335
+ *
336
+ * @param template - The React component or template
337
+ * @param toolName - Tool name for naming the component
338
+ * @returns JavaScript code string that defines the component
339
+ */
340
+ function buildComponentCode(template, toolName) {
341
+ if (typeof template !== 'function') {
342
+ return undefined;
343
+ }
344
+ // Get the component function as a string
345
+ const componentSource = template.toString();
346
+ // Sanitize tool name for JavaScript variable name
347
+ const safeName = toolName.replace(/[^a-zA-Z0-9_]/g, '_');
348
+ // Build the component code that will be embedded in the HTML
349
+ // The component is registered on window.__frontmcp_component for the render script
350
+ return `
351
+ // FrontMCP Widget Component: ${toolName}
352
+ (function() {
353
+ // The component function
354
+ var ${safeName} = ${componentSource};
355
+
356
+ // Register component globally for client-side rendering
357
+ window.__frontmcp_component = ${safeName};
358
+
359
+ // Also register in __frontmcp_components for multiple components
360
+ window.__frontmcp_components = window.__frontmcp_components || {};
361
+ window.__frontmcp_components['${toolName}'] = ${safeName};
362
+ })();
363
+ `.trim();
364
+ }
365
+ /**
366
+ * Ensure renderers are registered before use.
367
+ * This is called once and ensures React/MDX renderers are available.
368
+ */
369
+ let renderersInitialized = false;
370
+ function ensureRenderersRegistered() {
371
+ if (renderersInitialized) {
372
+ return;
373
+ }
374
+ // Register React renderer if not already registered
375
+ if (!registry_1.rendererRegistry.has('react')) {
376
+ registry_1.rendererRegistry.register(renderers_1.reactRenderer);
377
+ }
378
+ // Register MDX renderer if not already registered
379
+ if (!registry_1.rendererRegistry.has('mdx')) {
380
+ registry_1.rendererRegistry.register(renderers_1.mdxRenderer);
381
+ }
382
+ renderersInitialized = true;
383
+ }
384
+ /**
385
+ * Render template content.
386
+ */
387
+ async function renderTemplate(uiConfig, options) {
388
+ const { input, output, uiType } = options;
389
+ const template = uiConfig.template;
390
+ // Ensure renderers are available
391
+ ensureRenderersRegistered();
392
+ // Build context for template
393
+ const context = {
394
+ input: input,
395
+ output,
396
+ structuredContent: undefined,
397
+ helpers: {
398
+ escapeHtml: (str) => str.replace(/[&<>"']/g, (c) => ({
399
+ '&': '&amp;',
400
+ '<': '&lt;',
401
+ '>': '&gt;',
402
+ '"': '&quot;',
403
+ "'": '&#39;',
404
+ })[c] ?? c),
405
+ formatDate: (date) => new Date(date).toLocaleDateString(),
406
+ formatCurrency: (amount, currency = 'USD') => new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount),
407
+ uniqueId: (prefix = 'id') => `${prefix}-${Math.random().toString(36).slice(2, 9)}`,
408
+ jsonEmbed: (data) => JSON.stringify(data).replace(/</g, '\\u003c').replace(/>/g, '\\u003e'),
409
+ },
410
+ };
411
+ // Try to render using the registry
412
+ try {
413
+ // Use the detected uiType to render with the correct renderer
414
+ if (uiType === 'react' && registry_1.rendererRegistry.has('react')) {
415
+ const result = await registry_1.rendererRegistry.renderWith('react', template, context, {
416
+ mdxComponents: uiConfig.mdxComponents,
417
+ });
418
+ return result.html;
419
+ }
420
+ if (uiType === 'mdx' && registry_1.rendererRegistry.has('mdx')) {
421
+ const result = await registry_1.rendererRegistry.renderWith('mdx', template, context, {
422
+ mdxComponents: uiConfig.mdxComponents,
423
+ });
424
+ return result.html;
425
+ }
426
+ // Auto-detect and render
427
+ const result = await registry_1.rendererRegistry.render(template, context, {
428
+ mdxComponents: uiConfig.mdxComponents,
429
+ });
430
+ return result.html;
431
+ }
432
+ catch (error) {
433
+ // Fallback: simple rendering
434
+ if (typeof template === 'string') {
435
+ return template;
436
+ }
437
+ if (typeof template === 'function') {
438
+ // Check if it's a React component (has prototype or is class)
439
+ const isReact = template.prototype?.isReactComponent ||
440
+ template.$$typeof !== undefined;
441
+ if (!isReact) {
442
+ // It's a template builder function
443
+ return template(context);
444
+ }
445
+ }
446
+ // Log the error for debugging
447
+ console.warn('[FrontMCP] Template rendering failed:', error);
448
+ return `<div class="error">Template rendering failed</div>`;
449
+ }
450
+ }
451
+ /**
452
+ * Build multiple widget manifests in batch.
453
+ *
454
+ * @param options - Batch build options
455
+ * @returns Batch build results
456
+ *
457
+ * @example
458
+ * ```typescript
459
+ * const { results, errors } = await batchBuildWidgets({
460
+ * tools: [
461
+ * { toolName: 'weather.get', uiConfig: weatherConfig },
462
+ * { toolName: 'stock.quote', uiConfig: stockConfig },
463
+ * ],
464
+ * });
465
+ *
466
+ * for (const [name, result] of results) {
467
+ * cache.set(result.manifest.uri, result.html);
468
+ * }
469
+ * ```
470
+ */
471
+ async function batchBuildWidgets(options) {
472
+ const startTime = performance.now();
473
+ const results = new Map();
474
+ const errors = new Map();
475
+ const { tools, theme, parallel = true } = options;
476
+ if (parallel) {
477
+ // Build in parallel
478
+ const promises = tools.map(async (tool) => {
479
+ try {
480
+ const result = await buildToolWidgetManifest({
481
+ toolName: tool.toolName,
482
+ uiConfig: tool.uiConfig,
483
+ schema: tool.schema,
484
+ theme,
485
+ });
486
+ return { toolName: tool.toolName, result, error: null };
487
+ }
488
+ catch (error) {
489
+ return {
490
+ toolName: tool.toolName,
491
+ result: null,
492
+ error: error instanceof Error ? error : new Error(String(error)),
493
+ };
494
+ }
495
+ });
496
+ const outcomes = await Promise.all(promises);
497
+ for (const outcome of outcomes) {
498
+ if (outcome.result) {
499
+ results.set(outcome.toolName, outcome.result);
500
+ }
501
+ else if (outcome.error) {
502
+ errors.set(outcome.toolName, outcome.error);
503
+ }
504
+ }
505
+ }
506
+ else {
507
+ // Build sequentially
508
+ for (const tool of tools) {
509
+ try {
510
+ const result = await buildToolWidgetManifest({
511
+ toolName: tool.toolName,
512
+ uiConfig: tool.uiConfig,
513
+ schema: tool.schema,
514
+ theme,
515
+ });
516
+ results.set(tool.toolName, result);
517
+ }
518
+ catch (error) {
519
+ errors.set(tool.toolName, error instanceof Error ? error : new Error(String(error)));
520
+ }
521
+ }
522
+ }
523
+ return {
524
+ results,
525
+ totalTime: performance.now() - startTime,
526
+ successCount: results.size,
527
+ errors,
528
+ };
529
+ }
530
+ /**
531
+ * Build _meta fields for a tool response.
532
+ *
533
+ * This function generates the proper _meta structure for UI widgets.
534
+ * All UI-related data goes in _meta, NOT in the content array.
535
+ *
536
+ * @param options - Build options
537
+ * @returns _meta fields object to spread into tool response
538
+ *
539
+ * @example
540
+ * ```typescript
541
+ * const buildResult = await buildToolWidgetManifest({...});
542
+ *
543
+ * // For OpenAI (code-only mode)
544
+ * const meta = buildToolResponseMeta({
545
+ * buildResult,
546
+ * outputMode: 'code-only',
547
+ * });
548
+ *
549
+ * return {
550
+ * content: [{ type: 'text', text: 'Weather retrieved' }],
551
+ * _meta: meta,
552
+ * };
553
+ *
554
+ * // For unknown clients (full-ssr mode)
555
+ * const meta = buildToolResponseMeta({
556
+ * buildResult,
557
+ * outputMode: 'full-ssr',
558
+ * });
559
+ * ```
560
+ */
561
+ function buildToolResponseMeta(options) {
562
+ const { buildResult, outputMode = 'code-only', includeOpenAI = true } = options;
563
+ const { manifest, content, html, hash, rendererType } = buildResult;
564
+ // Base UI meta fields
565
+ const meta = {
566
+ 'ui/type': rendererType,
567
+ 'ui/hash': hash,
568
+ };
569
+ // Add content based on output mode
570
+ if (outputMode === 'code-only') {
571
+ meta['ui/content'] = content;
572
+ }
573
+ else {
574
+ meta['ui/html'] = html;
575
+ }
576
+ // Add optional fields from manifest
577
+ if (manifest.displayMode && manifest.displayMode !== 'inline') {
578
+ meta['ui/displayMode'] = manifest.displayMode;
579
+ }
580
+ if (manifest.widgetAccessible) {
581
+ meta['ui/widgetAccessible'] = true;
582
+ }
583
+ if (manifest.description) {
584
+ meta['ui/description'] = manifest.description;
585
+ }
586
+ // Add resource mode if not default
587
+ if (manifest.rendererAssets?.mode && manifest.rendererAssets.mode !== 'cdn') {
588
+ meta['ui/resourceMode'] = manifest.rendererAssets.mode;
589
+ }
590
+ // Add OpenAI-specific fields
591
+ if (includeOpenAI) {
592
+ if (manifest.widgetAccessible) {
593
+ meta['openai/widgetAccessible'] = true;
594
+ }
595
+ if (manifest.description) {
596
+ meta['openai/widgetDescription'] = manifest.description;
597
+ }
598
+ if (manifest.displayMode && manifest.displayMode !== 'inline') {
599
+ meta['openai/displayMode'] = manifest.displayMode;
600
+ }
601
+ // Build OpenAI CSP from manifest CSP
602
+ const csp = manifest.csp;
603
+ if (csp) {
604
+ const openaiCsp = {};
605
+ if (csp.connectSrc && csp.connectSrc.length > 0) {
606
+ openaiCsp.connect_domains = csp.connectSrc.filter((d) => d !== "'self'" && d !== "'none'");
607
+ }
608
+ const resourceDomains = [
609
+ ...(csp.scriptSrc || []),
610
+ ...(csp.styleSrc || []),
611
+ ...(csp.imgSrc || []),
612
+ ].filter((d) => d !== "'self'" && d !== "'unsafe-inline'" && d !== "'none'");
613
+ if (resourceDomains.length > 0) {
614
+ openaiCsp.resource_domains = [...new Set(resourceDomains)];
615
+ }
616
+ if (openaiCsp.connect_domains?.length || openaiCsp.resource_domains?.length) {
617
+ meta['openai/widgetCSP'] = openaiCsp;
618
+ }
619
+ }
620
+ }
621
+ return meta;
622
+ }
623
+ /**
624
+ * Determine the appropriate output mode based on client info.
625
+ *
626
+ * @param clientInfo - MCP client information
627
+ * @returns Recommended output mode
628
+ *
629
+ * @example
630
+ * ```typescript
631
+ * const outputMode = getOutputModeForClient(request.clientInfo);
632
+ * const meta = buildToolResponseMeta({ buildResult, outputMode });
633
+ * ```
634
+ */
635
+ function getOutputModeForClient(clientInfo) {
636
+ if (!clientInfo?.name) {
637
+ // Unknown client - use full SSR for safety
638
+ return 'full-ssr';
639
+ }
640
+ const name = clientInfo.name.toLowerCase();
641
+ // Capable clients that provide their own runtime
642
+ if (name.includes('openai') ||
643
+ name.includes('chatgpt') ||
644
+ name.includes('cursor') ||
645
+ name.includes('claude') // Claude Desktop might support code-only in future
646
+ ) {
647
+ return 'code-only';
648
+ }
649
+ // Default to full SSR for unknown clients
650
+ return 'full-ssr';
651
+ }
652
+ //# sourceMappingURL=widget-manifest.js.map