@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,294 @@
1
+ /**
2
+ * Build-Time API for Tool UI
3
+ *
4
+ * Provides pre-compilation capabilities for tool UI templates.
5
+ * Produces a **universal HTML document** that works across all platforms:
6
+ * - OpenAI ChatGPT (Apps SDK)
7
+ * - Anthropic Claude
8
+ * - MCP Apps (ext-apps / SEP-1865)
9
+ * - Google Gemini
10
+ * - Any MCP-compatible host
11
+ *
12
+ * The build embeds the FrontMCP Bridge which auto-detects the host
13
+ * at runtime and adapts its communication protocol accordingly.
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+ import type { UITemplateConfig } from '../types';
18
+ import type { ThemeConfig, DeepPartial } from '../theme';
19
+ /**
20
+ * Network access mode for the target environment.
21
+ *
22
+ * - `'open'`: Can fetch external resources (CDN scripts, fonts)
23
+ * - `'blocked'`: Network is sandboxed, must inline everything
24
+ */
25
+ export type NetworkMode = 'open' | 'blocked';
26
+ /**
27
+ * Script loading strategy.
28
+ *
29
+ * - `'cdn'`: Load scripts from CDN (smaller HTML, requires network)
30
+ * - `'inline'`: Embed scripts in HTML (larger, works offline)
31
+ * - `'auto'`: Choose based on network mode
32
+ */
33
+ export type ScriptStrategy = 'cdn' | 'inline' | 'auto';
34
+ /**
35
+ * Build configuration options.
36
+ * Capability-based rather than platform-specific.
37
+ */
38
+ export interface BuildConfig {
39
+ /**
40
+ * Network access mode.
41
+ * @default 'open'
42
+ */
43
+ network?: NetworkMode;
44
+ /**
45
+ * Script loading strategy.
46
+ * @default 'auto' (uses 'inline' if network is 'blocked')
47
+ */
48
+ scripts?: ScriptStrategy;
49
+ /**
50
+ * Whether to include the FrontMCP Bridge runtime.
51
+ * The bridge auto-detects the host platform at runtime.
52
+ * @default true
53
+ */
54
+ includeBridge?: boolean;
55
+ /**
56
+ * Whether to minify the output HTML.
57
+ * @default false
58
+ */
59
+ minify?: boolean;
60
+ }
61
+ /**
62
+ * Options for building a tool UI template.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const result = await buildToolUI({
67
+ * template: {
68
+ * template: (ctx) => `<div>${ctx.output.value}</div>`,
69
+ * widgetAccessible: true,
70
+ * },
71
+ * toolName: 'my_tool',
72
+ * input: { query: 'hello' },
73
+ * output: { value: 'world' },
74
+ * });
75
+ *
76
+ * // Universal HTML that works on any platform
77
+ * console.log(result.html);
78
+ * ```
79
+ */
80
+ export interface BuildOptions<In = unknown, Out = unknown> {
81
+ /**
82
+ * UI template configuration.
83
+ */
84
+ template: UITemplateConfig<In, Out>;
85
+ /**
86
+ * Name of the tool this UI is for.
87
+ */
88
+ toolName: string;
89
+ /**
90
+ * Tool input arguments.
91
+ */
92
+ input?: In;
93
+ /**
94
+ * Tool output/result data.
95
+ */
96
+ output?: Out;
97
+ /**
98
+ * Theme configuration override.
99
+ */
100
+ theme?: DeepPartial<ThemeConfig>;
101
+ /**
102
+ * Build configuration.
103
+ * Controls network mode, script strategy, etc.
104
+ */
105
+ config?: BuildConfig;
106
+ /**
107
+ * Title for the HTML document.
108
+ */
109
+ title?: string;
110
+ /** @deprecated Use `input` instead */
111
+ sampleInput?: In;
112
+ /** @deprecated Use `output` instead */
113
+ sampleOutput?: Out;
114
+ /** @deprecated Use `config.includeBridge` instead */
115
+ injectAdapters?: boolean;
116
+ /** @deprecated Use `config.minify` instead */
117
+ minify?: boolean;
118
+ /** @deprecated Platform is now auto-detected at runtime */
119
+ platform?: string;
120
+ }
121
+ /**
122
+ * MIME types for different host platforms.
123
+ * Returned as suggestions - the MCP server response layer decides which to use.
124
+ */
125
+ export interface MimeTypes {
126
+ /** For OpenAI ChatGPT Apps SDK */
127
+ openai: 'text/html+skybridge';
128
+ /** For Claude, MCP Apps, and standard MCP hosts */
129
+ mcp: 'text/html+mcp';
130
+ /** Generic HTML (fallback) */
131
+ html: 'text/html';
132
+ }
133
+ /**
134
+ * Result of building a tool UI template.
135
+ */
136
+ export interface BuildResult {
137
+ /**
138
+ * Complete HTML document string.
139
+ * This is universal - works on all platforms.
140
+ */
141
+ html: string;
142
+ /**
143
+ * Size of the HTML in bytes.
144
+ */
145
+ size: number;
146
+ /**
147
+ * Size of the gzipped HTML in bytes (estimated).
148
+ */
149
+ gzipSize: number;
150
+ /**
151
+ * SHA-256 hash of the HTML content.
152
+ */
153
+ hash: string;
154
+ /**
155
+ * Suggested MIME types for different hosts.
156
+ * The MCP server response layer should select based on detected client.
157
+ */
158
+ mimeTypes: MimeTypes;
159
+ /**
160
+ * Renderer type used (html, react, mdx).
161
+ */
162
+ rendererType: string;
163
+ /**
164
+ * Build timestamp (ISO 8601).
165
+ */
166
+ buildTime: string;
167
+ /**
168
+ * Build configuration used.
169
+ */
170
+ config: Required<BuildConfig>;
171
+ }
172
+ /**
173
+ * Build a tool UI template into a universal HTML document.
174
+ *
175
+ * The output HTML:
176
+ * - Works on ALL platforms (OpenAI, Claude, MCP Apps, Gemini, etc.)
177
+ * - Includes FrontMCP Bridge that auto-detects the host at runtime
178
+ * - Adapts communication protocol based on detected platform
179
+ *
180
+ * @example Basic usage
181
+ * ```typescript
182
+ * import { buildToolUI } from '@frontmcp/ui/build';
183
+ *
184
+ * const result = await buildToolUI({
185
+ * template: { template: WeatherWidget },
186
+ * toolName: 'get_weather',
187
+ * output: { temperature: 72, conditions: 'sunny' },
188
+ * });
189
+ *
190
+ * // Upload to CDN - works everywhere
191
+ * await uploadToCDN('widgets/get_weather.html', result.html);
192
+ * ```
193
+ *
194
+ * @example With blocked network (for Claude Artifacts)
195
+ * ```typescript
196
+ * const result = await buildToolUI({
197
+ * template: { template: WeatherWidget },
198
+ * toolName: 'get_weather',
199
+ * config: { network: 'blocked' }, // Inlines all scripts
200
+ * });
201
+ * ```
202
+ *
203
+ * @example MCP server response
204
+ * ```typescript
205
+ * const result = await buildToolUI({ template, toolName, output });
206
+ *
207
+ * // In MCP server - choose MIME type based on client
208
+ * const mimeType = isOpenAIClient(clientInfo)
209
+ * ? result.mimeTypes.openai // 'text/html+skybridge'
210
+ * : result.mimeTypes.mcp; // 'text/html+mcp'
211
+ *
212
+ * return { content: [{ type: mimeType, data: result.html }] };
213
+ * ```
214
+ */
215
+ export declare function buildToolUI<In = unknown, Out = unknown>(options: BuildOptions<In, Out>): Promise<BuildResult>;
216
+ /**
217
+ * Options for building a static widget that reads from host at runtime.
218
+ */
219
+ export interface StaticWidgetOptions<In = unknown, Out = unknown> {
220
+ /**
221
+ * UI template configuration.
222
+ */
223
+ template: UITemplateConfig<In, Out>;
224
+ /**
225
+ * Name of the tool this UI is for.
226
+ */
227
+ toolName: string;
228
+ /**
229
+ * Theme configuration override.
230
+ */
231
+ theme?: DeepPartial<ThemeConfig>;
232
+ /**
233
+ * Build configuration.
234
+ */
235
+ config?: BuildConfig;
236
+ /**
237
+ * Title for the HTML document.
238
+ */
239
+ title?: string;
240
+ }
241
+ /**
242
+ * Build a static widget that reads data from the host platform at runtime.
243
+ *
244
+ * Unlike buildToolUI which pre-renders with data, this creates a widget
245
+ * that waits for data from the host platform via the FrontMCP Bridge.
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * import { buildStaticWidget } from '@frontmcp/ui/build';
250
+ *
251
+ * const widget = await buildStaticWidget({
252
+ * template: {
253
+ * template: (ctx) => `<div id="weather">${ctx.output?.temperature || 'Loading...'}</div>`,
254
+ * },
255
+ * toolName: 'get_weather',
256
+ * });
257
+ *
258
+ * // This widget will receive data via FrontMCP Bridge
259
+ * await uploadToCDN('widgets/get_weather.html', widget.html);
260
+ * ```
261
+ */
262
+ export declare function buildStaticWidget<In = unknown, Out = unknown>(options: StaticWidgetOptions<In, Out>): Promise<BuildResult>;
263
+ /**
264
+ * @deprecated Use BuildConfig instead
265
+ */
266
+ export type BuildTargetPlatform = 'chatgpt' | 'claude' | 'mcp-apps' | 'universal';
267
+ /**
268
+ * @deprecated Use BuildOptions with config instead
269
+ */
270
+ export interface MultiBuildOptions<In = unknown, Out = unknown> extends Omit<BuildOptions<In, Out>, 'platform'> {
271
+ platforms?: BuildTargetPlatform[];
272
+ }
273
+ /**
274
+ * @deprecated Use BuildResult instead (same result for all platforms now)
275
+ */
276
+ export interface MultiBuildResult {
277
+ bundles: Record<string, BuildResult>;
278
+ totalTime: number;
279
+ }
280
+ /**
281
+ * @deprecated Use buildToolUI with config.network instead
282
+ */
283
+ export declare function buildToolUIMulti<In = unknown, Out = unknown>(options: MultiBuildOptions<In, Out>): Promise<MultiBuildResult>;
284
+ export { createTemplateHelpers } from '../runtime/wrapper';
285
+ export type { UITemplateConfig, UITemplate, TemplateContext, TemplateHelpers, TemplateBuilderFn, UIContentSecurityPolicy, WidgetServingMode, WidgetDisplayMode, } from '../types';
286
+ export type { ThemeConfig, PlatformCapabilities, DeepPartial } from '../theme';
287
+ export { DEFAULT_THEME, OPENAI_PLATFORM, CLAUDE_PLATFORM } from '../theme';
288
+ export { buildToolWidgetManifest, batchBuildWidgets, detectUIType, buildCSPForType, buildCSPMetaContent, getRendererAssets, buildToolResponseMeta, getOutputModeForClient, } from './widget-manifest';
289
+ export type { BatchBuildOptions, BatchBuildResult, BuildMetaOptions } from './widget-manifest';
290
+ export type { UIType, BundlingMode, DisplayMode, OutputMode, CSPDirectives, RendererAssets, WidgetManifest, WidgetConfig, BuildManifestResult, BuildManifestOptions, UIMetaFields, OpenAIMetaFields, ToolResponseMeta, RuntimePayload, } from '../types/ui-runtime';
291
+ export { DEFAULT_CSP_BY_TYPE, DEFAULT_RENDERER_ASSETS, isUIType, isBundlingMode, isDisplayMode, isResourceMode, isOutputMode, } from '../types/ui-runtime';
292
+ export type { ResourceMode, CDNResource } from '../types/ui-runtime';
293
+ export { REACT_CDN, REACT_DOM_CDN, MARKED_CDN, HANDLEBARS_CDN, MDX_RUNTIME_CDN, TAILWIND_CDN, getDefaultAssets, buildCDNScriptTag, buildScriptsForUIType, buildTailwindScriptTag, hasInlineScripts, getURLsToPreFetch, buildCDNInfoForUIType, } from './cdn-resources';
294
+ export type { CDNInfo } from './cdn-resources';
@@ -0,0 +1,325 @@
1
+ "use strict";
2
+ /**
3
+ * Build-Time API for Tool UI
4
+ *
5
+ * Provides pre-compilation capabilities for tool UI templates.
6
+ * Produces a **universal HTML document** that works across all platforms:
7
+ * - OpenAI ChatGPT (Apps SDK)
8
+ * - Anthropic Claude
9
+ * - MCP Apps (ext-apps / SEP-1865)
10
+ * - Google Gemini
11
+ * - Any MCP-compatible host
12
+ *
13
+ * The build embeds the FrontMCP Bridge which auto-detects the host
14
+ * at runtime and adapts its communication protocol accordingly.
15
+ *
16
+ * @packageDocumentation
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.buildCDNInfoForUIType = exports.getURLsToPreFetch = exports.hasInlineScripts = exports.buildTailwindScriptTag = exports.buildScriptsForUIType = exports.buildCDNScriptTag = exports.getDefaultAssets = exports.TAILWIND_CDN = exports.MDX_RUNTIME_CDN = exports.HANDLEBARS_CDN = exports.MARKED_CDN = exports.REACT_DOM_CDN = exports.REACT_CDN = exports.isOutputMode = exports.isResourceMode = exports.isDisplayMode = exports.isBundlingMode = exports.isUIType = exports.DEFAULT_RENDERER_ASSETS = exports.DEFAULT_CSP_BY_TYPE = exports.getOutputModeForClient = exports.buildToolResponseMeta = exports.getRendererAssets = exports.buildCSPMetaContent = exports.buildCSPForType = exports.detectUIType = exports.batchBuildWidgets = exports.buildToolWidgetManifest = exports.CLAUDE_PLATFORM = exports.OPENAI_PLATFORM = exports.DEFAULT_THEME = exports.createTemplateHelpers = void 0;
20
+ exports.buildToolUI = buildToolUI;
21
+ exports.buildStaticWidget = buildStaticWidget;
22
+ exports.buildToolUIMulti = buildToolUIMulti;
23
+ const wrapper_1 = require("../runtime/wrapper");
24
+ const registry_1 = require("../renderers/registry");
25
+ const renderers_1 = require("../renderers");
26
+ // ============================================
27
+ // Build Functions
28
+ // ============================================
29
+ /**
30
+ * Build a tool UI template into a universal HTML document.
31
+ *
32
+ * The output HTML:
33
+ * - Works on ALL platforms (OpenAI, Claude, MCP Apps, Gemini, etc.)
34
+ * - Includes FrontMCP Bridge that auto-detects the host at runtime
35
+ * - Adapts communication protocol based on detected platform
36
+ *
37
+ * @example Basic usage
38
+ * ```typescript
39
+ * import { buildToolUI } from '@frontmcp/ui/build';
40
+ *
41
+ * const result = await buildToolUI({
42
+ * template: { template: WeatherWidget },
43
+ * toolName: 'get_weather',
44
+ * output: { temperature: 72, conditions: 'sunny' },
45
+ * });
46
+ *
47
+ * // Upload to CDN - works everywhere
48
+ * await uploadToCDN('widgets/get_weather.html', result.html);
49
+ * ```
50
+ *
51
+ * @example With blocked network (for Claude Artifacts)
52
+ * ```typescript
53
+ * const result = await buildToolUI({
54
+ * template: { template: WeatherWidget },
55
+ * toolName: 'get_weather',
56
+ * config: { network: 'blocked' }, // Inlines all scripts
57
+ * });
58
+ * ```
59
+ *
60
+ * @example MCP server response
61
+ * ```typescript
62
+ * const result = await buildToolUI({ template, toolName, output });
63
+ *
64
+ * // In MCP server - choose MIME type based on client
65
+ * const mimeType = isOpenAIClient(clientInfo)
66
+ * ? result.mimeTypes.openai // 'text/html+skybridge'
67
+ * : result.mimeTypes.mcp; // 'text/html+mcp'
68
+ *
69
+ * return { content: [{ type: mimeType, data: result.html }] };
70
+ * ```
71
+ */
72
+ async function buildToolUI(options) {
73
+ const startTime = Date.now();
74
+ // Normalize options (handle legacy aliases)
75
+ const { template: uiConfig, toolName, input = options.sampleInput ?? {}, output = options.sampleOutput ?? {}, theme, title, config: userConfig = {}, injectAdapters, minify: legacyMinify, } = options;
76
+ // Build final config with defaults
77
+ const config = {
78
+ network: userConfig.network ?? 'open',
79
+ scripts: userConfig.scripts ?? 'auto',
80
+ includeBridge: userConfig.includeBridge ?? injectAdapters ?? true,
81
+ minify: userConfig.minify ?? legacyMinify ?? false,
82
+ };
83
+ // Resolve script strategy
84
+ const useInlineScripts = config.scripts === 'inline' || (config.scripts === 'auto' && config.network === 'blocked');
85
+ // Build template context
86
+ const ctx = buildTemplateContext(input, output);
87
+ // Render the template content
88
+ const { html: content, rendererType } = await renderTemplate(uiConfig.template, ctx, {
89
+ mdxComponents: uiConfig.mdxComponents,
90
+ });
91
+ // Wrap in universal HTML document
92
+ const html = (0, wrapper_1.wrapToolUIUniversal)({
93
+ content,
94
+ toolName,
95
+ input: input,
96
+ output,
97
+ csp: uiConfig.csp,
98
+ widgetAccessible: uiConfig.widgetAccessible,
99
+ title: title || `${toolName} Widget`,
100
+ theme,
101
+ includeBridge: config.includeBridge,
102
+ inlineScripts: useInlineScripts,
103
+ rendererType,
104
+ });
105
+ // Optionally minify
106
+ const finalHtml = config.minify ? minifyHtml(html) : html;
107
+ // Calculate size and hash
108
+ const size = Buffer.byteLength(finalHtml, 'utf8');
109
+ const gzipSize = estimateGzipSize(finalHtml);
110
+ const hash = await calculateHash(finalHtml);
111
+ return {
112
+ html: finalHtml,
113
+ size,
114
+ gzipSize,
115
+ hash,
116
+ mimeTypes: {
117
+ openai: 'text/html+skybridge',
118
+ mcp: 'text/html+mcp',
119
+ html: 'text/html',
120
+ },
121
+ rendererType,
122
+ buildTime: new Date(startTime).toISOString(),
123
+ config,
124
+ };
125
+ }
126
+ // ============================================
127
+ // Helper Functions
128
+ // ============================================
129
+ /**
130
+ * Build template context from input/output.
131
+ */
132
+ function buildTemplateContext(input, output, structuredContent) {
133
+ return {
134
+ input,
135
+ output,
136
+ structuredContent,
137
+ helpers: (0, wrapper_1.createTemplateHelpers)(),
138
+ };
139
+ }
140
+ /**
141
+ * Render a template using the appropriate renderer.
142
+ */
143
+ async function renderTemplate(template, ctx, options) {
144
+ // Detect template type
145
+ const detection = (0, renderers_1.detectTemplateType)(template);
146
+ // For simple HTML templates, use direct execution (sync, faster)
147
+ if (detection.type === 'html-function' || detection.type === 'html-string') {
148
+ const html = typeof template === 'function'
149
+ ? template(ctx)
150
+ : template;
151
+ return { html, rendererType: 'html' };
152
+ }
153
+ // For React/MDX, use the renderer registry
154
+ try {
155
+ const result = await registry_1.rendererRegistry.render(template, ctx, {
156
+ mdxComponents: options?.mdxComponents,
157
+ });
158
+ return { html: result.html, rendererType: result.rendererType };
159
+ }
160
+ catch (error) {
161
+ // Fallback to HTML if renderer fails
162
+ console.warn(`[@frontmcp/ui/build] Renderer failed for ${detection.type}, falling back to HTML:`, error instanceof Error ? error.message : error);
163
+ if (typeof template === 'function') {
164
+ try {
165
+ const html = template(ctx);
166
+ return { html, rendererType: 'html-fallback' };
167
+ }
168
+ catch {
169
+ return {
170
+ html: `<div class="error">Template rendering failed</div>`,
171
+ rendererType: 'error',
172
+ };
173
+ }
174
+ }
175
+ return { html: String(template), rendererType: 'html-fallback' };
176
+ }
177
+ }
178
+ /**
179
+ * Simple HTML minification (remove whitespace between tags).
180
+ */
181
+ function minifyHtml(html) {
182
+ return html
183
+ .replace(/>\s+</g, '><') // Remove whitespace between tags
184
+ .replace(/\s{2,}/g, ' ') // Collapse multiple spaces
185
+ .trim();
186
+ }
187
+ /**
188
+ * Estimate gzipped size (rough approximation).
189
+ */
190
+ function estimateGzipSize(content) {
191
+ // Rough estimate: gzip typically achieves 70-90% compression on HTML
192
+ // We use 75% as a middle ground
193
+ return Math.round(Buffer.byteLength(content, 'utf8') * 0.25);
194
+ }
195
+ /**
196
+ * Calculate SHA-256 hash of content.
197
+ */
198
+ async function calculateHash(content) {
199
+ // Use Web Crypto API if available, otherwise fallback to simple hash
200
+ if (typeof crypto !== 'undefined' && crypto.subtle) {
201
+ const encoder = new TextEncoder();
202
+ const data = encoder.encode(content);
203
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
204
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
205
+ return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
206
+ }
207
+ // Simple fallback hash (not cryptographically secure, but good enough for cache keys)
208
+ let hash = 0;
209
+ for (let i = 0; i < content.length; i++) {
210
+ const char = content.charCodeAt(i);
211
+ hash = (hash << 5) - hash + char;
212
+ hash = hash & hash; // Convert to 32-bit integer
213
+ }
214
+ return Math.abs(hash).toString(16).padStart(8, '0');
215
+ }
216
+ /**
217
+ * Build a static widget that reads data from the host platform at runtime.
218
+ *
219
+ * Unlike buildToolUI which pre-renders with data, this creates a widget
220
+ * that waits for data from the host platform via the FrontMCP Bridge.
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * import { buildStaticWidget } from '@frontmcp/ui/build';
225
+ *
226
+ * const widget = await buildStaticWidget({
227
+ * template: {
228
+ * template: (ctx) => `<div id="weather">${ctx.output?.temperature || 'Loading...'}</div>`,
229
+ * },
230
+ * toolName: 'get_weather',
231
+ * });
232
+ *
233
+ * // This widget will receive data via FrontMCP Bridge
234
+ * await uploadToCDN('widgets/get_weather.html', widget.html);
235
+ * ```
236
+ */
237
+ async function buildStaticWidget(options) {
238
+ const { template, toolName, theme, config, title } = options;
239
+ // Build with empty data - the widget will receive data from host at runtime
240
+ return buildToolUI({
241
+ template,
242
+ toolName,
243
+ input: {},
244
+ output: {},
245
+ theme,
246
+ config,
247
+ title: title || `${toolName} Widget`,
248
+ });
249
+ }
250
+ /**
251
+ * @deprecated Use buildToolUI with config.network instead
252
+ */
253
+ async function buildToolUIMulti(options) {
254
+ const startTime = Date.now();
255
+ const { platforms = ['chatgpt', 'claude'], ...buildOptions } = options;
256
+ // For backwards compatibility, build once and return same result for all platforms
257
+ const result = await buildToolUI(buildOptions);
258
+ const bundles = {};
259
+ for (const platform of platforms) {
260
+ bundles[platform] = {
261
+ ...result,
262
+ // Add legacy mimeType field for compatibility
263
+ mimeType: platform === 'chatgpt' ? 'text/html+skybridge' : 'text/html+mcp',
264
+ };
265
+ }
266
+ return {
267
+ bundles,
268
+ totalTime: Date.now() - startTime,
269
+ };
270
+ }
271
+ // ============================================
272
+ // Re-exports for Convenience
273
+ // ============================================
274
+ var wrapper_2 = require("../runtime/wrapper");
275
+ Object.defineProperty(exports, "createTemplateHelpers", { enumerable: true, get: function () { return wrapper_2.createTemplateHelpers; } });
276
+ var theme_1 = require("../theme");
277
+ Object.defineProperty(exports, "DEFAULT_THEME", { enumerable: true, get: function () { return theme_1.DEFAULT_THEME; } });
278
+ Object.defineProperty(exports, "OPENAI_PLATFORM", { enumerable: true, get: function () { return theme_1.OPENAI_PLATFORM; } });
279
+ Object.defineProperty(exports, "CLAUDE_PLATFORM", { enumerable: true, get: function () { return theme_1.CLAUDE_PLATFORM; } });
280
+ // ============================================
281
+ // Widget Manifest Builder (New API)
282
+ // ============================================
283
+ var widget_manifest_1 = require("./widget-manifest");
284
+ // Main builder
285
+ Object.defineProperty(exports, "buildToolWidgetManifest", { enumerable: true, get: function () { return widget_manifest_1.buildToolWidgetManifest; } });
286
+ Object.defineProperty(exports, "batchBuildWidgets", { enumerable: true, get: function () { return widget_manifest_1.batchBuildWidgets; } });
287
+ // Detection utilities
288
+ Object.defineProperty(exports, "detectUIType", { enumerable: true, get: function () { return widget_manifest_1.detectUIType; } });
289
+ // CSP utilities
290
+ Object.defineProperty(exports, "buildCSPForType", { enumerable: true, get: function () { return widget_manifest_1.buildCSPForType; } });
291
+ Object.defineProperty(exports, "buildCSPMetaContent", { enumerable: true, get: function () { return widget_manifest_1.buildCSPMetaContent; } });
292
+ // Asset utilities
293
+ Object.defineProperty(exports, "getRendererAssets", { enumerable: true, get: function () { return widget_manifest_1.getRendererAssets; } });
294
+ // _meta field builders (NEW)
295
+ Object.defineProperty(exports, "buildToolResponseMeta", { enumerable: true, get: function () { return widget_manifest_1.buildToolResponseMeta; } });
296
+ Object.defineProperty(exports, "getOutputModeForClient", { enumerable: true, get: function () { return widget_manifest_1.getOutputModeForClient; } });
297
+ var ui_runtime_1 = require("../types/ui-runtime");
298
+ Object.defineProperty(exports, "DEFAULT_CSP_BY_TYPE", { enumerable: true, get: function () { return ui_runtime_1.DEFAULT_CSP_BY_TYPE; } });
299
+ Object.defineProperty(exports, "DEFAULT_RENDERER_ASSETS", { enumerable: true, get: function () { return ui_runtime_1.DEFAULT_RENDERER_ASSETS; } });
300
+ Object.defineProperty(exports, "isUIType", { enumerable: true, get: function () { return ui_runtime_1.isUIType; } });
301
+ Object.defineProperty(exports, "isBundlingMode", { enumerable: true, get: function () { return ui_runtime_1.isBundlingMode; } });
302
+ Object.defineProperty(exports, "isDisplayMode", { enumerable: true, get: function () { return ui_runtime_1.isDisplayMode; } });
303
+ Object.defineProperty(exports, "isResourceMode", { enumerable: true, get: function () { return ui_runtime_1.isResourceMode; } });
304
+ Object.defineProperty(exports, "isOutputMode", { enumerable: true, get: function () { return ui_runtime_1.isOutputMode; } });
305
+ // ============================================
306
+ // CDN Resource Utilities
307
+ // ============================================
308
+ var cdn_resources_1 = require("./cdn-resources");
309
+ // CDN URL Constants
310
+ Object.defineProperty(exports, "REACT_CDN", { enumerable: true, get: function () { return cdn_resources_1.REACT_CDN; } });
311
+ Object.defineProperty(exports, "REACT_DOM_CDN", { enumerable: true, get: function () { return cdn_resources_1.REACT_DOM_CDN; } });
312
+ Object.defineProperty(exports, "MARKED_CDN", { enumerable: true, get: function () { return cdn_resources_1.MARKED_CDN; } });
313
+ Object.defineProperty(exports, "HANDLEBARS_CDN", { enumerable: true, get: function () { return cdn_resources_1.HANDLEBARS_CDN; } });
314
+ Object.defineProperty(exports, "MDX_RUNTIME_CDN", { enumerable: true, get: function () { return cdn_resources_1.MDX_RUNTIME_CDN; } });
315
+ Object.defineProperty(exports, "TAILWIND_CDN", { enumerable: true, get: function () { return cdn_resources_1.TAILWIND_CDN; } });
316
+ // Helper Functions
317
+ Object.defineProperty(exports, "getDefaultAssets", { enumerable: true, get: function () { return cdn_resources_1.getDefaultAssets; } });
318
+ Object.defineProperty(exports, "buildCDNScriptTag", { enumerable: true, get: function () { return cdn_resources_1.buildCDNScriptTag; } });
319
+ Object.defineProperty(exports, "buildScriptsForUIType", { enumerable: true, get: function () { return cdn_resources_1.buildScriptsForUIType; } });
320
+ Object.defineProperty(exports, "buildTailwindScriptTag", { enumerable: true, get: function () { return cdn_resources_1.buildTailwindScriptTag; } });
321
+ Object.defineProperty(exports, "hasInlineScripts", { enumerable: true, get: function () { return cdn_resources_1.hasInlineScripts; } });
322
+ Object.defineProperty(exports, "getURLsToPreFetch", { enumerable: true, get: function () { return cdn_resources_1.getURLsToPreFetch; } });
323
+ // CDN Info for tools/list _meta
324
+ Object.defineProperty(exports, "buildCDNInfoForUIType", { enumerable: true, get: function () { return cdn_resources_1.buildCDNInfoForUIType; } });
325
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/build/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AA6OH,kCA2EC;AA6KD,8CAeC;AA8BD,4CAsBC;AApiBD,gDAAgF;AAChF,oDAAyD;AACzD,4CAAkD;AAwLlD,+CAA+C;AAC/C,kBAAkB;AAClB,+CAA+C;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACI,KAAK,UAAU,WAAW,CAC/B,OAA8B;IAE9B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,4CAA4C;IAC5C,MAAM,EACJ,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EACR,KAAK,GAAG,OAAO,CAAC,WAAW,IAAK,EAAS,EACzC,MAAM,GAAG,OAAO,CAAC,YAAY,IAAK,EAAU,EAC5C,KAAK,EACL,KAAK,EACL,MAAM,EAAE,UAAU,GAAG,EAAE,EACvB,cAAc,EACd,MAAM,EAAE,YAAY,GACrB,GAAG,OAAO,CAAC;IAEZ,mCAAmC;IACnC,MAAM,MAAM,GAA0B;QACpC,OAAO,EAAE,UAAU,CAAC,OAAO,IAAI,MAAM;QACrC,OAAO,EAAE,UAAU,CAAC,OAAO,IAAI,MAAM;QACrC,aAAa,EAAE,UAAU,CAAC,aAAa,IAAI,cAAc,IAAI,IAAI;QACjE,MAAM,EAAE,UAAU,CAAC,MAAM,IAAI,YAAY,IAAI,KAAK;KACnD,CAAC;IAEF,0BAA0B;IAC1B,MAAM,gBAAgB,GACpB,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,OAAO,KAAK,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;IAE7F,yBAAyB;IACzB,MAAM,GAAG,GAAG,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAEhD,8BAA8B;IAC9B,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;QACnF,aAAa,EAAE,QAAQ,CAAC,aAAa;KACtC,CAAC,CAAC;IAEH,kCAAkC;IAClC,MAAM,IAAI,GAAG,IAAA,6BAAmB,EAAC;QAC/B,OAAO;QACP,QAAQ;QACR,KAAK,EAAE,KAAgC;QACvC,MAAM;QACN,GAAG,EAAE,QAAQ,CAAC,GAAG;QACjB,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;QAC3C,KAAK,EAAE,KAAK,IAAI,GAAG,QAAQ,SAAS;QACpC,KAAK;QACL,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,aAAa,EAAE,gBAAgB;QAC/B,YAAY;KACb,CAAC,CAAC;IAEH,oBAAoB;IACpB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE1D,0BAA0B;IAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;IAE5C,OAAO;QACL,IAAI,EAAE,SAAS;QACf,IAAI;QACJ,QAAQ;QACR,IAAI;QACJ,SAAS,EAAE;YACT,MAAM,EAAE,qBAAqB;YAC7B,GAAG,EAAE,eAAe;YACpB,IAAI,EAAE,WAAW;SAClB;QACD,YAAY;QACZ,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE;QAC5C,MAAM;KACP,CAAC;AACJ,CAAC;AAED,+CAA+C;AAC/C,mBAAmB;AACnB,+CAA+C;AAE/C;;GAEG;AACH,SAAS,oBAAoB,CAC3B,KAAS,EACT,MAAW,EACX,iBAA2B;IAE3B,OAAO;QACL,KAAK;QACL,MAAM;QACN,iBAAiB;QACjB,OAAO,EAAE,IAAA,+BAAqB,GAAE;KACjC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAC3B,QAA+C,EAC/C,GAA6B,EAC7B,OAGC;IAED,uBAAuB;IACvB,MAAM,SAAS,GAAG,IAAA,8BAAkB,EAAC,QAAQ,CAAC,CAAC;IAE/C,iEAAiE;IACjE,IAAI,SAAS,CAAC,IAAI,KAAK,eAAe,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QAC3E,MAAM,IAAI,GACR,OAAO,QAAQ,KAAK,UAAU;YAC5B,CAAC,CAAE,QAAuC,CAAC,GAAG,CAAC;YAC/C,CAAC,CAAE,QAAmB,CAAC;QAE3B,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;IACxC,CAAC;IAED,2CAA2C;IAC3C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,2BAAgB,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC1D,aAAa,EAAE,OAAO,EAAE,aAAa;SACtC,CAAC,CAAC;QAEH,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;IAClE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,qCAAqC;QACrC,OAAO,CAAC,IAAI,CACV,4CAA4C,SAAS,CAAC,IAAI,yBAAyB,EACnF,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC/C,CAAC;QAEF,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAI,QAAuC,CAAC,GAAG,CAAC,CAAC;gBAC3D,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC;YACjD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;oBACL,IAAI,EAAE,oDAAoD;oBAC1D,YAAY,EAAE,OAAO;iBACtB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC;IACnE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI;SACR,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,iCAAiC;SACzD,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,2BAA2B;SACnD,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,OAAe;IACvC,qEAAqE;IACrE,gCAAgC;IAChC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa,CAAC,OAAe;IAC1C,qEAAqE;IACrE,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACnD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QACzD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,sFAAsF;IACtF,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACnC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;QACjC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,4BAA4B;IAClD,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACtD,CAAC;AAoCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACI,KAAK,UAAU,iBAAiB,CACrC,OAAqC;IAErC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAE7D,4EAA4E;IAC5E,OAAO,WAAW,CAAC;QACjB,QAAQ;QACR,QAAQ;QACR,KAAK,EAAE,EAAQ;QACf,MAAM,EAAE,EAAS;QACjB,KAAK;QACL,MAAM;QACN,KAAK,EAAE,KAAK,IAAI,GAAG,QAAQ,SAAS;KACrC,CAAC,CAAC;AACL,CAAC;AA2BD;;GAEG;AACI,KAAK,UAAU,gBAAgB,CACpC,OAAmC;IAEnC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC;IAEvE,mFAAmF;IACnF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAgC,EAAE,CAAC;IAChD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,OAAO,CAAC,QAAQ,CAAC,GAAG;YAClB,GAAG,MAAM;YACT,8CAA8C;YAC9C,QAAQ,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,eAAe;SACrC,CAAC;IAC1C,CAAC;IAED,OAAO;QACL,OAAO;QACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;KAClC,CAAC;AACJ,CAAC;AAED,+CAA+C;AAC/C,6BAA6B;AAC7B,+CAA+C;AAE/C,8CAA2D;AAAlD,gHAAA,qBAAqB,OAAA;AAY9B,kCAA2E;AAAlE,sGAAA,aAAa,OAAA;AAAE,wGAAA,eAAe,OAAA;AAAE,wGAAA,eAAe,OAAA;AAExD,+CAA+C;AAC/C,oCAAoC;AACpC,+CAA+C;AAE/C,qDAc2B;AAbzB,eAAe;AACf,0HAAA,uBAAuB,OAAA;AACvB,oHAAA,iBAAiB,OAAA;AACjB,sBAAsB;AACtB,+GAAA,YAAY,OAAA;AACZ,gBAAgB;AAChB,kHAAA,eAAe,OAAA;AACf,sHAAA,mBAAmB,OAAA;AACnB,kBAAkB;AAClB,oHAAA,iBAAiB,OAAA;AACjB,6BAA6B;AAC7B,wHAAA,qBAAqB,OAAA;AACrB,yHAAA,sBAAsB,OAAA;AAyBxB,kDAQ6B;AAP3B,iHAAA,mBAAmB,OAAA;AACnB,qHAAA,uBAAuB,OAAA;AACvB,sGAAA,QAAQ,OAAA;AACR,4GAAA,cAAc,OAAA;AACd,2GAAA,aAAa,OAAA;AACb,4GAAA,cAAc,OAAA;AACd,0GAAA,YAAY,OAAA;AAKd,+CAA+C;AAC/C,yBAAyB;AACzB,+CAA+C;AAE/C,iDAiByB;AAhBvB,oBAAoB;AACpB,0GAAA,SAAS,OAAA;AACT,8GAAA,aAAa,OAAA;AACb,2GAAA,UAAU,OAAA;AACV,+GAAA,cAAc,OAAA;AACd,gHAAA,eAAe,OAAA;AACf,6GAAA,YAAY,OAAA;AACZ,mBAAmB;AACnB,iHAAA,gBAAgB,OAAA;AAChB,kHAAA,iBAAiB,OAAA;AACjB,sHAAA,qBAAqB,OAAA;AACrB,uHAAA,sBAAsB,OAAA;AACtB,iHAAA,gBAAgB,OAAA;AAChB,kHAAA,iBAAiB,OAAA;AACjB,gCAAgC;AAChC,sHAAA,qBAAqB,OAAA","sourcesContent":["/**\n * Build-Time API for Tool UI\n *\n * Provides pre-compilation capabilities for tool UI templates.\n * Produces a **universal HTML document** that works across all platforms:\n * - OpenAI ChatGPT (Apps SDK)\n * - Anthropic Claude\n * - MCP Apps (ext-apps / SEP-1865)\n * - Google Gemini\n * - Any MCP-compatible host\n *\n * The build embeds the FrontMCP Bridge which auto-detects the host\n * at runtime and adapts its communication protocol accordingly.\n *\n * @packageDocumentation\n */\n\nimport type { UITemplateConfig, TemplateContext } from '../types';\nimport type { ThemeConfig, DeepPartial } from '../theme';\nimport { wrapToolUIUniversal, createTemplateHelpers } from '../runtime/wrapper';\nimport { rendererRegistry } from '../renderers/registry';\nimport { detectTemplateType } from '../renderers';\nimport type { TemplateBuilderFn } from '../types';\n\n// ============================================\n// Build Types\n// ============================================\n\n/**\n * Network access mode for the target environment.\n *\n * - `'open'`: Can fetch external resources (CDN scripts, fonts)\n * - `'blocked'`: Network is sandboxed, must inline everything\n */\nexport type NetworkMode = 'open' | 'blocked';\n\n/**\n * Script loading strategy.\n *\n * - `'cdn'`: Load scripts from CDN (smaller HTML, requires network)\n * - `'inline'`: Embed scripts in HTML (larger, works offline)\n * - `'auto'`: Choose based on network mode\n */\nexport type ScriptStrategy = 'cdn' | 'inline' | 'auto';\n\n/**\n * Build configuration options.\n * Capability-based rather than platform-specific.\n */\nexport interface BuildConfig {\n /**\n * Network access mode.\n * @default 'open'\n */\n network?: NetworkMode;\n\n /**\n * Script loading strategy.\n * @default 'auto' (uses 'inline' if network is 'blocked')\n */\n scripts?: ScriptStrategy;\n\n /**\n * Whether to include the FrontMCP Bridge runtime.\n * The bridge auto-detects the host platform at runtime.\n * @default true\n */\n includeBridge?: boolean;\n\n /**\n * Whether to minify the output HTML.\n * @default false\n */\n minify?: boolean;\n}\n\n/**\n * Options for building a tool UI template.\n *\n * @example\n * ```typescript\n * const result = await buildToolUI({\n * template: {\n * template: (ctx) => `<div>${ctx.output.value}</div>`,\n * widgetAccessible: true,\n * },\n * toolName: 'my_tool',\n * input: { query: 'hello' },\n * output: { value: 'world' },\n * });\n *\n * // Universal HTML that works on any platform\n * console.log(result.html);\n * ```\n */\nexport interface BuildOptions<In = unknown, Out = unknown> {\n /**\n * UI template configuration.\n */\n template: UITemplateConfig<In, Out>;\n\n /**\n * Name of the tool this UI is for.\n */\n toolName: string;\n\n /**\n * Tool input arguments.\n */\n input?: In;\n\n /**\n * Tool output/result data.\n */\n output?: Out;\n\n /**\n * Theme configuration override.\n */\n theme?: DeepPartial<ThemeConfig>;\n\n /**\n * Build configuration.\n * Controls network mode, script strategy, etc.\n */\n config?: BuildConfig;\n\n /**\n * Title for the HTML document.\n */\n title?: string;\n\n // Legacy aliases for backwards compatibility\n /** @deprecated Use `input` instead */\n sampleInput?: In;\n /** @deprecated Use `output` instead */\n sampleOutput?: Out;\n /** @deprecated Use `config.includeBridge` instead */\n injectAdapters?: boolean;\n /** @deprecated Use `config.minify` instead */\n minify?: boolean;\n /** @deprecated Platform is now auto-detected at runtime */\n platform?: string;\n}\n\n/**\n * MIME types for different host platforms.\n * Returned as suggestions - the MCP server response layer decides which to use.\n */\nexport interface MimeTypes {\n /** For OpenAI ChatGPT Apps SDK */\n openai: 'text/html+skybridge';\n /** For Claude, MCP Apps, and standard MCP hosts */\n mcp: 'text/html+mcp';\n /** Generic HTML (fallback) */\n html: 'text/html';\n}\n\n/**\n * Result of building a tool UI template.\n */\nexport interface BuildResult {\n /**\n * Complete HTML document string.\n * This is universal - works on all platforms.\n */\n html: string;\n\n /**\n * Size of the HTML in bytes.\n */\n size: number;\n\n /**\n * Size of the gzipped HTML in bytes (estimated).\n */\n gzipSize: number;\n\n /**\n * SHA-256 hash of the HTML content.\n */\n hash: string;\n\n /**\n * Suggested MIME types for different hosts.\n * The MCP server response layer should select based on detected client.\n */\n mimeTypes: MimeTypes;\n\n /**\n * Renderer type used (html, react, mdx).\n */\n rendererType: string;\n\n /**\n * Build timestamp (ISO 8601).\n */\n buildTime: string;\n\n /**\n * Build configuration used.\n */\n config: Required<BuildConfig>;\n}\n\n// ============================================\n// Build Functions\n// ============================================\n\n/**\n * Build a tool UI template into a universal HTML document.\n *\n * The output HTML:\n * - Works on ALL platforms (OpenAI, Claude, MCP Apps, Gemini, etc.)\n * - Includes FrontMCP Bridge that auto-detects the host at runtime\n * - Adapts communication protocol based on detected platform\n *\n * @example Basic usage\n * ```typescript\n * import { buildToolUI } from '@frontmcp/ui/build';\n *\n * const result = await buildToolUI({\n * template: { template: WeatherWidget },\n * toolName: 'get_weather',\n * output: { temperature: 72, conditions: 'sunny' },\n * });\n *\n * // Upload to CDN - works everywhere\n * await uploadToCDN('widgets/get_weather.html', result.html);\n * ```\n *\n * @example With blocked network (for Claude Artifacts)\n * ```typescript\n * const result = await buildToolUI({\n * template: { template: WeatherWidget },\n * toolName: 'get_weather',\n * config: { network: 'blocked' }, // Inlines all scripts\n * });\n * ```\n *\n * @example MCP server response\n * ```typescript\n * const result = await buildToolUI({ template, toolName, output });\n *\n * // In MCP server - choose MIME type based on client\n * const mimeType = isOpenAIClient(clientInfo)\n * ? result.mimeTypes.openai // 'text/html+skybridge'\n * : result.mimeTypes.mcp; // 'text/html+mcp'\n *\n * return { content: [{ type: mimeType, data: result.html }] };\n * ```\n */\nexport async function buildToolUI<In = unknown, Out = unknown>(\n options: BuildOptions<In, Out>\n): Promise<BuildResult> {\n const startTime = Date.now();\n\n // Normalize options (handle legacy aliases)\n const {\n template: uiConfig,\n toolName,\n input = options.sampleInput ?? ({} as In),\n output = options.sampleOutput ?? ({} as Out),\n theme,\n title,\n config: userConfig = {},\n injectAdapters,\n minify: legacyMinify,\n } = options;\n\n // Build final config with defaults\n const config: Required<BuildConfig> = {\n network: userConfig.network ?? 'open',\n scripts: userConfig.scripts ?? 'auto',\n includeBridge: userConfig.includeBridge ?? injectAdapters ?? true,\n minify: userConfig.minify ?? legacyMinify ?? false,\n };\n\n // Resolve script strategy\n const useInlineScripts =\n config.scripts === 'inline' || (config.scripts === 'auto' && config.network === 'blocked');\n\n // Build template context\n const ctx = buildTemplateContext(input, output);\n\n // Render the template content\n const { html: content, rendererType } = await renderTemplate(uiConfig.template, ctx, {\n mdxComponents: uiConfig.mdxComponents,\n });\n\n // Wrap in universal HTML document\n const html = wrapToolUIUniversal({\n content,\n toolName,\n input: input as Record<string, unknown>,\n output,\n csp: uiConfig.csp,\n widgetAccessible: uiConfig.widgetAccessible,\n title: title || `${toolName} Widget`,\n theme,\n includeBridge: config.includeBridge,\n inlineScripts: useInlineScripts,\n rendererType,\n });\n\n // Optionally minify\n const finalHtml = config.minify ? minifyHtml(html) : html;\n\n // Calculate size and hash\n const size = Buffer.byteLength(finalHtml, 'utf8');\n const gzipSize = estimateGzipSize(finalHtml);\n const hash = await calculateHash(finalHtml);\n\n return {\n html: finalHtml,\n size,\n gzipSize,\n hash,\n mimeTypes: {\n openai: 'text/html+skybridge',\n mcp: 'text/html+mcp',\n html: 'text/html',\n },\n rendererType,\n buildTime: new Date(startTime).toISOString(),\n config,\n };\n}\n\n// ============================================\n// Helper Functions\n// ============================================\n\n/**\n * Build template context from input/output.\n */\nfunction buildTemplateContext<In = unknown, Out = unknown>(\n input: In,\n output: Out,\n structuredContent?: unknown\n): TemplateContext<In, Out> {\n return {\n input,\n output,\n structuredContent,\n helpers: createTemplateHelpers(),\n };\n}\n\n/**\n * Render a template using the appropriate renderer.\n */\nasync function renderTemplate<In = unknown, Out = unknown>(\n template: UITemplateConfig<In, Out>['template'],\n ctx: TemplateContext<In, Out>,\n options?: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n mdxComponents?: Record<string, any>;\n }\n): Promise<{ html: string; rendererType: string }> {\n // Detect template type\n const detection = detectTemplateType(template);\n\n // For simple HTML templates, use direct execution (sync, faster)\n if (detection.type === 'html-function' || detection.type === 'html-string') {\n const html =\n typeof template === 'function'\n ? (template as TemplateBuilderFn<In, Out>)(ctx)\n : (template as string);\n\n return { html, rendererType: 'html' };\n }\n\n // For React/MDX, use the renderer registry\n try {\n const result = await rendererRegistry.render(template, ctx, {\n mdxComponents: options?.mdxComponents,\n });\n\n return { html: result.html, rendererType: result.rendererType };\n } catch (error) {\n // Fallback to HTML if renderer fails\n console.warn(\n `[@frontmcp/ui/build] Renderer failed for ${detection.type}, falling back to HTML:`,\n error instanceof Error ? error.message : error\n );\n\n if (typeof template === 'function') {\n try {\n const html = (template as TemplateBuilderFn<In, Out>)(ctx);\n return { html, rendererType: 'html-fallback' };\n } catch {\n return {\n html: `<div class=\"error\">Template rendering failed</div>`,\n rendererType: 'error',\n };\n }\n }\n\n return { html: String(template), rendererType: 'html-fallback' };\n }\n}\n\n/**\n * Simple HTML minification (remove whitespace between tags).\n */\nfunction minifyHtml(html: string): string {\n return html\n .replace(/>\\s+</g, '><') // Remove whitespace between tags\n .replace(/\\s{2,}/g, ' ') // Collapse multiple spaces\n .trim();\n}\n\n/**\n * Estimate gzipped size (rough approximation).\n */\nfunction estimateGzipSize(content: string): number {\n // Rough estimate: gzip typically achieves 70-90% compression on HTML\n // We use 75% as a middle ground\n return Math.round(Buffer.byteLength(content, 'utf8') * 0.25);\n}\n\n/**\n * Calculate SHA-256 hash of content.\n */\nasync function calculateHash(content: string): Promise<string> {\n // Use Web Crypto API if available, otherwise fallback to simple hash\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const encoder = new TextEncoder();\n const data = encoder.encode(content);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n }\n\n // Simple fallback hash (not cryptographically secure, but good enough for cache keys)\n let hash = 0;\n for (let i = 0; i < content.length; i++) {\n const char = content.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32-bit integer\n }\n return Math.abs(hash).toString(16).padStart(8, '0');\n}\n\n// ============================================\n// Static Widget Builder\n// ============================================\n\n/**\n * Options for building a static widget that reads from host at runtime.\n */\nexport interface StaticWidgetOptions<In = unknown, Out = unknown> {\n /**\n * UI template configuration.\n */\n template: UITemplateConfig<In, Out>;\n\n /**\n * Name of the tool this UI is for.\n */\n toolName: string;\n\n /**\n * Theme configuration override.\n */\n theme?: DeepPartial<ThemeConfig>;\n\n /**\n * Build configuration.\n */\n config?: BuildConfig;\n\n /**\n * Title for the HTML document.\n */\n title?: string;\n}\n\n/**\n * Build a static widget that reads data from the host platform at runtime.\n *\n * Unlike buildToolUI which pre-renders with data, this creates a widget\n * that waits for data from the host platform via the FrontMCP Bridge.\n *\n * @example\n * ```typescript\n * import { buildStaticWidget } from '@frontmcp/ui/build';\n *\n * const widget = await buildStaticWidget({\n * template: {\n * template: (ctx) => `<div id=\"weather\">${ctx.output?.temperature || 'Loading...'}</div>`,\n * },\n * toolName: 'get_weather',\n * });\n *\n * // This widget will receive data via FrontMCP Bridge\n * await uploadToCDN('widgets/get_weather.html', widget.html);\n * ```\n */\nexport async function buildStaticWidget<In = unknown, Out = unknown>(\n options: StaticWidgetOptions<In, Out>\n): Promise<BuildResult> {\n const { template, toolName, theme, config, title } = options;\n\n // Build with empty data - the widget will receive data from host at runtime\n return buildToolUI({\n template,\n toolName,\n input: {} as In,\n output: {} as Out,\n theme,\n config,\n title: title || `${toolName} Widget`,\n });\n}\n\n// ============================================\n// Legacy Compatibility\n// ============================================\n\n/**\n * @deprecated Use BuildConfig instead\n */\nexport type BuildTargetPlatform = 'chatgpt' | 'claude' | 'mcp-apps' | 'universal';\n\n/**\n * @deprecated Use BuildOptions with config instead\n */\nexport interface MultiBuildOptions<In = unknown, Out = unknown>\n extends Omit<BuildOptions<In, Out>, 'platform'> {\n platforms?: BuildTargetPlatform[];\n}\n\n/**\n * @deprecated Use BuildResult instead (same result for all platforms now)\n */\nexport interface MultiBuildResult {\n bundles: Record<string, BuildResult>;\n totalTime: number;\n}\n\n/**\n * @deprecated Use buildToolUI with config.network instead\n */\nexport async function buildToolUIMulti<In = unknown, Out = unknown>(\n options: MultiBuildOptions<In, Out>\n): Promise<MultiBuildResult> {\n const startTime = Date.now();\n const { platforms = ['chatgpt', 'claude'], ...buildOptions } = options;\n\n // For backwards compatibility, build once and return same result for all platforms\n const result = await buildToolUI(buildOptions);\n\n const bundles: Record<string, BuildResult> = {};\n for (const platform of platforms) {\n bundles[platform] = {\n ...result,\n // Add legacy mimeType field for compatibility\n mimeType: platform === 'chatgpt' ? 'text/html+skybridge' : 'text/html+mcp',\n } as BuildResult & { mimeType: string };\n }\n\n return {\n bundles,\n totalTime: Date.now() - startTime,\n };\n}\n\n// ============================================\n// Re-exports for Convenience\n// ============================================\n\nexport { createTemplateHelpers } from '../runtime/wrapper';\nexport type {\n UITemplateConfig,\n UITemplate,\n TemplateContext,\n TemplateHelpers,\n TemplateBuilderFn,\n UIContentSecurityPolicy,\n WidgetServingMode,\n WidgetDisplayMode,\n} from '../types';\nexport type { ThemeConfig, PlatformCapabilities, DeepPartial } from '../theme';\nexport { DEFAULT_THEME, OPENAI_PLATFORM, CLAUDE_PLATFORM } from '../theme';\n\n// ============================================\n// Widget Manifest Builder (New API)\n// ============================================\n\nexport {\n // Main builder\n buildToolWidgetManifest,\n batchBuildWidgets,\n // Detection utilities\n detectUIType,\n // CSP utilities\n buildCSPForType,\n buildCSPMetaContent,\n // Asset utilities\n getRendererAssets,\n // _meta field builders (NEW)\n buildToolResponseMeta,\n getOutputModeForClient,\n} from './widget-manifest';\n\nexport type { BatchBuildOptions, BatchBuildResult, BuildMetaOptions } from './widget-manifest';\n\n// Re-export runtime types for convenience\nexport type {\n UIType,\n BundlingMode,\n DisplayMode,\n OutputMode,\n CSPDirectives,\n RendererAssets,\n WidgetManifest,\n WidgetConfig,\n BuildManifestResult,\n BuildManifestOptions,\n // _meta field types (NEW)\n UIMetaFields,\n OpenAIMetaFields,\n ToolResponseMeta,\n // Deprecated\n RuntimePayload,\n} from '../types/ui-runtime';\n\nexport {\n DEFAULT_CSP_BY_TYPE,\n DEFAULT_RENDERER_ASSETS,\n isUIType,\n isBundlingMode,\n isDisplayMode,\n isResourceMode,\n isOutputMode,\n} from '../types/ui-runtime';\n\nexport type { ResourceMode, CDNResource } from '../types/ui-runtime';\n\n// ============================================\n// CDN Resource Utilities\n// ============================================\n\nexport {\n // CDN URL Constants\n REACT_CDN,\n REACT_DOM_CDN,\n MARKED_CDN,\n HANDLEBARS_CDN,\n MDX_RUNTIME_CDN,\n TAILWIND_CDN,\n // Helper Functions\n getDefaultAssets,\n buildCDNScriptTag,\n buildScriptsForUIType,\n buildTailwindScriptTag,\n hasInlineScripts,\n getURLsToPreFetch,\n // CDN Info for tools/list _meta\n buildCDNInfoForUIType,\n} from './cdn-resources';\n\nexport type { CDNInfo } from './cdn-resources';\n"]}