@frontmcp/ui 0.6.0 → 0.6.1

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 (445) hide show
  1. package/README.md +140 -362
  2. package/bridge/runtime/index.d.ts +2 -1
  3. package/bridge/runtime/index.d.ts.map +1 -1
  4. package/bundler/file-cache/component-builder.d.ts +1 -1
  5. package/bundler/file-cache/component-builder.d.ts.map +1 -1
  6. package/bundler/file-cache/hash-calculator.d.ts +1 -1
  7. package/bundler/file-cache/hash-calculator.d.ts.map +1 -1
  8. package/bundler/file-cache/storage/filesystem.d.ts +1 -1
  9. package/bundler/file-cache/storage/filesystem.d.ts.map +1 -1
  10. package/bundler/file-cache/storage/interface.d.ts +1 -1
  11. package/bundler/file-cache/storage/interface.d.ts.map +1 -1
  12. package/bundler/file-cache/storage/redis.d.ts +1 -1
  13. package/bundler/file-cache/storage/redis.d.ts.map +1 -1
  14. package/bundler/index.js +10 -1057
  15. package/components/alert.schema.d.ts +6 -6
  16. package/components/avatar.schema.d.ts +9 -9
  17. package/components/badge.schema.d.ts +9 -9
  18. package/components/button.schema.d.ts +9 -9
  19. package/components/card.schema.d.ts +7 -7
  20. package/components/form.schema.d.ts +24 -24
  21. package/components/index.js +128 -198
  22. package/components/modal.schema.d.ts +8 -8
  23. package/components/table.schema.d.ts +6 -6
  24. package/esm/bridge/runtime/index.d.ts +2 -1
  25. package/esm/bridge/runtime/index.d.ts.map +1 -1
  26. package/esm/bundler/file-cache/component-builder.d.ts +1 -1
  27. package/esm/bundler/file-cache/component-builder.d.ts.map +1 -1
  28. package/esm/bundler/file-cache/hash-calculator.d.ts +1 -1
  29. package/esm/bundler/file-cache/hash-calculator.d.ts.map +1 -1
  30. package/esm/bundler/file-cache/storage/filesystem.d.ts +1 -1
  31. package/esm/bundler/file-cache/storage/filesystem.d.ts.map +1 -1
  32. package/esm/bundler/file-cache/storage/interface.d.ts +1 -1
  33. package/esm/bundler/file-cache/storage/interface.d.ts.map +1 -1
  34. package/esm/bundler/file-cache/storage/redis.d.ts +1 -1
  35. package/esm/bundler/file-cache/storage/redis.d.ts.map +1 -1
  36. package/esm/bundler/index.js +3 -1050
  37. package/esm/components/alert.schema.d.ts +6 -6
  38. package/esm/components/avatar.schema.d.ts +9 -9
  39. package/esm/components/badge.schema.d.ts +9 -9
  40. package/esm/components/button.schema.d.ts +9 -9
  41. package/esm/components/card.schema.d.ts +7 -7
  42. package/esm/components/form.schema.d.ts +24 -24
  43. package/esm/components/index.js +136 -196
  44. package/esm/components/modal.schema.d.ts +8 -8
  45. package/esm/components/table.schema.d.ts +6 -6
  46. package/esm/index.d.ts +23 -39
  47. package/esm/index.d.ts.map +1 -1
  48. package/esm/index.js +4256 -16441
  49. package/esm/layouts/base.d.ts +2 -2
  50. package/esm/layouts/base.d.ts.map +1 -1
  51. package/esm/layouts/index.js +33 -516
  52. package/esm/package.json +8 -26
  53. package/esm/pages/index.js +100 -627
  54. package/esm/react/Alert.d.ts +1 -2
  55. package/esm/react/Alert.d.ts.map +1 -1
  56. package/esm/react/Badge.d.ts +1 -2
  57. package/esm/react/Badge.d.ts.map +1 -1
  58. package/esm/react/Button.d.ts +1 -2
  59. package/esm/react/Button.d.ts.map +1 -1
  60. package/esm/react/Card.d.ts +1 -2
  61. package/esm/react/Card.d.ts.map +1 -1
  62. package/esm/react/hooks/context.d.ts +1 -1
  63. package/esm/react/hooks/context.d.ts.map +1 -1
  64. package/esm/react/index.d.ts +5 -6
  65. package/esm/react/index.d.ts.map +1 -1
  66. package/esm/react/index.js +2074 -322
  67. package/esm/react/types.d.ts +1 -2
  68. package/esm/react/types.d.ts.map +1 -1
  69. package/esm/renderers/index.d.ts +10 -25
  70. package/esm/renderers/index.d.ts.map +1 -1
  71. package/esm/renderers/index.js +171 -1617
  72. package/esm/{runtime/adapters → renderers}/react.adapter.d.ts +2 -2
  73. package/esm/renderers/react.adapter.d.ts.map +1 -0
  74. package/esm/renderers/react.renderer.d.ts +3 -3
  75. package/esm/renderers/react.renderer.d.ts.map +1 -1
  76. package/esm/universal/index.js +1755 -0
  77. package/esm/web-components/index.js +232 -287
  78. package/esm/widgets/index.js +89 -147
  79. package/index.d.ts +23 -39
  80. package/index.d.ts.map +1 -1
  81. package/index.js +6123 -18539
  82. package/layouts/base.d.ts +2 -2
  83. package/layouts/base.d.ts.map +1 -1
  84. package/layouts/index.js +43 -536
  85. package/package.json +8 -26
  86. package/pages/index.js +111 -648
  87. package/react/Alert.d.ts +1 -2
  88. package/react/Alert.d.ts.map +1 -1
  89. package/react/Badge.d.ts +1 -2
  90. package/react/Badge.d.ts.map +1 -1
  91. package/react/Button.d.ts +1 -2
  92. package/react/Button.d.ts.map +1 -1
  93. package/react/Card.d.ts +1 -2
  94. package/react/Card.d.ts.map +1 -1
  95. package/react/hooks/context.d.ts +1 -1
  96. package/react/hooks/context.d.ts.map +1 -1
  97. package/react/index.d.ts +5 -6
  98. package/react/index.d.ts.map +1 -1
  99. package/react/index.js +2065 -335
  100. package/react/types.d.ts +1 -2
  101. package/react/types.d.ts.map +1 -1
  102. package/renderers/index.d.ts +10 -25
  103. package/renderers/index.d.ts.map +1 -1
  104. package/renderers/index.js +175 -1641
  105. package/{runtime/adapters → renderers}/react.adapter.d.ts +2 -2
  106. package/renderers/react.adapter.d.ts.map +1 -0
  107. package/renderers/react.renderer.d.ts +3 -3
  108. package/renderers/react.renderer.d.ts.map +1 -1
  109. package/universal/index.js +1841 -0
  110. package/web-components/index.js +224 -289
  111. package/widgets/index.js +80 -148
  112. package/adapters/index.d.ts +0 -13
  113. package/adapters/index.d.ts.map +0 -1
  114. package/adapters/index.js +0 -462
  115. package/adapters/platform-meta.d.ts +0 -166
  116. package/adapters/platform-meta.d.ts.map +0 -1
  117. package/adapters/response-builder.d.ts +0 -108
  118. package/adapters/response-builder.d.ts.map +0 -1
  119. package/adapters/serving-mode.d.ts +0 -107
  120. package/adapters/serving-mode.d.ts.map +0 -1
  121. package/base-template/bridge.d.ts +0 -90
  122. package/base-template/bridge.d.ts.map +0 -1
  123. package/base-template/default-base-template.d.ts +0 -92
  124. package/base-template/default-base-template.d.ts.map +0 -1
  125. package/base-template/index.d.ts +0 -15
  126. package/base-template/index.d.ts.map +0 -1
  127. package/base-template/index.js +0 -1398
  128. package/base-template/polyfills.d.ts +0 -31
  129. package/base-template/polyfills.d.ts.map +0 -1
  130. package/base-template/theme-styles.d.ts +0 -74
  131. package/base-template/theme-styles.d.ts.map +0 -1
  132. package/build/cdn-resources.d.ts +0 -243
  133. package/build/cdn-resources.d.ts.map +0 -1
  134. package/build/index.d.ts +0 -295
  135. package/build/index.d.ts.map +0 -1
  136. package/build/index.js +0 -7096
  137. package/build/widget-manifest.d.ts +0 -362
  138. package/build/widget-manifest.d.ts.map +0 -1
  139. package/dependency/cdn-registry.d.ts +0 -98
  140. package/dependency/cdn-registry.d.ts.map +0 -1
  141. package/dependency/import-map.d.ts +0 -186
  142. package/dependency/import-map.d.ts.map +0 -1
  143. package/dependency/import-parser.d.ts +0 -82
  144. package/dependency/import-parser.d.ts.map +0 -1
  145. package/dependency/index.d.ts +0 -17
  146. package/dependency/index.d.ts.map +0 -1
  147. package/dependency/resolver.d.ts +0 -164
  148. package/dependency/resolver.d.ts.map +0 -1
  149. package/dependency/schemas.d.ts +0 -486
  150. package/dependency/schemas.d.ts.map +0 -1
  151. package/dependency/template-loader.d.ts +0 -204
  152. package/dependency/template-loader.d.ts.map +0 -1
  153. package/dependency/template-processor.d.ts +0 -118
  154. package/dependency/template-processor.d.ts.map +0 -1
  155. package/dependency/types.d.ts +0 -739
  156. package/dependency/types.d.ts.map +0 -1
  157. package/esm/adapters/index.d.ts +0 -13
  158. package/esm/adapters/index.d.ts.map +0 -1
  159. package/esm/adapters/index.js +0 -427
  160. package/esm/adapters/platform-meta.d.ts +0 -166
  161. package/esm/adapters/platform-meta.d.ts.map +0 -1
  162. package/esm/adapters/response-builder.d.ts +0 -108
  163. package/esm/adapters/response-builder.d.ts.map +0 -1
  164. package/esm/adapters/serving-mode.d.ts +0 -107
  165. package/esm/adapters/serving-mode.d.ts.map +0 -1
  166. package/esm/base-template/bridge.d.ts +0 -90
  167. package/esm/base-template/bridge.d.ts.map +0 -1
  168. package/esm/base-template/default-base-template.d.ts +0 -92
  169. package/esm/base-template/default-base-template.d.ts.map +0 -1
  170. package/esm/base-template/index.d.ts +0 -15
  171. package/esm/base-template/index.d.ts.map +0 -1
  172. package/esm/base-template/index.js +0 -1364
  173. package/esm/base-template/polyfills.d.ts +0 -31
  174. package/esm/base-template/polyfills.d.ts.map +0 -1
  175. package/esm/base-template/theme-styles.d.ts +0 -74
  176. package/esm/base-template/theme-styles.d.ts.map +0 -1
  177. package/esm/build/cdn-resources.d.ts +0 -243
  178. package/esm/build/cdn-resources.d.ts.map +0 -1
  179. package/esm/build/index.d.ts +0 -295
  180. package/esm/build/index.d.ts.map +0 -1
  181. package/esm/build/index.js +0 -7021
  182. package/esm/build/widget-manifest.d.ts +0 -362
  183. package/esm/build/widget-manifest.d.ts.map +0 -1
  184. package/esm/dependency/cdn-registry.d.ts +0 -98
  185. package/esm/dependency/cdn-registry.d.ts.map +0 -1
  186. package/esm/dependency/import-map.d.ts +0 -186
  187. package/esm/dependency/import-map.d.ts.map +0 -1
  188. package/esm/dependency/import-parser.d.ts +0 -82
  189. package/esm/dependency/import-parser.d.ts.map +0 -1
  190. package/esm/dependency/index.d.ts +0 -17
  191. package/esm/dependency/index.d.ts.map +0 -1
  192. package/esm/dependency/resolver.d.ts +0 -164
  193. package/esm/dependency/resolver.d.ts.map +0 -1
  194. package/esm/dependency/schemas.d.ts +0 -486
  195. package/esm/dependency/schemas.d.ts.map +0 -1
  196. package/esm/dependency/template-loader.d.ts +0 -204
  197. package/esm/dependency/template-loader.d.ts.map +0 -1
  198. package/esm/dependency/template-processor.d.ts +0 -118
  199. package/esm/dependency/template-processor.d.ts.map +0 -1
  200. package/esm/dependency/types.d.ts +0 -739
  201. package/esm/dependency/types.d.ts.map +0 -1
  202. package/esm/handlebars/expression-extractor.d.ts +0 -147
  203. package/esm/handlebars/expression-extractor.d.ts.map +0 -1
  204. package/esm/handlebars/helpers.d.ts +0 -339
  205. package/esm/handlebars/helpers.d.ts.map +0 -1
  206. package/esm/handlebars/index.d.ts +0 -195
  207. package/esm/handlebars/index.d.ts.map +0 -1
  208. package/esm/handlebars/index.js +0 -587
  209. package/esm/registry/index.d.ts +0 -46
  210. package/esm/registry/index.d.ts.map +0 -1
  211. package/esm/registry/index.js +0 -6422
  212. package/esm/registry/render-template.d.ts +0 -91
  213. package/esm/registry/render-template.d.ts.map +0 -1
  214. package/esm/registry/tool-ui.registry.d.ts +0 -294
  215. package/esm/registry/tool-ui.registry.d.ts.map +0 -1
  216. package/esm/registry/uri-utils.d.ts +0 -56
  217. package/esm/registry/uri-utils.d.ts.map +0 -1
  218. package/esm/renderers/cache.d.ts +0 -145
  219. package/esm/renderers/cache.d.ts.map +0 -1
  220. package/esm/renderers/html.renderer.d.ts +0 -123
  221. package/esm/renderers/html.renderer.d.ts.map +0 -1
  222. package/esm/renderers/mdx.renderer.d.ts +0 -120
  223. package/esm/renderers/mdx.renderer.d.ts.map +0 -1
  224. package/esm/renderers/registry.d.ts +0 -134
  225. package/esm/renderers/registry.d.ts.map +0 -1
  226. package/esm/renderers/types.d.ts +0 -342
  227. package/esm/renderers/types.d.ts.map +0 -1
  228. package/esm/renderers/utils/detect.d.ts +0 -107
  229. package/esm/renderers/utils/detect.d.ts.map +0 -1
  230. package/esm/renderers/utils/hash.d.ts +0 -40
  231. package/esm/renderers/utils/hash.d.ts.map +0 -1
  232. package/esm/renderers/utils/index.d.ts +0 -9
  233. package/esm/renderers/utils/index.d.ts.map +0 -1
  234. package/esm/renderers/utils/transpiler.d.ts +0 -89
  235. package/esm/renderers/utils/transpiler.d.ts.map +0 -1
  236. package/esm/runtime/adapters/html.adapter.d.ts +0 -59
  237. package/esm/runtime/adapters/html.adapter.d.ts.map +0 -1
  238. package/esm/runtime/adapters/index.d.ts +0 -26
  239. package/esm/runtime/adapters/index.d.ts.map +0 -1
  240. package/esm/runtime/adapters/mdx.adapter.d.ts +0 -73
  241. package/esm/runtime/adapters/mdx.adapter.d.ts.map +0 -1
  242. package/esm/runtime/adapters/react.adapter.d.ts.map +0 -1
  243. package/esm/runtime/adapters/types.d.ts +0 -95
  244. package/esm/runtime/adapters/types.d.ts.map +0 -1
  245. package/esm/runtime/csp.d.ts +0 -48
  246. package/esm/runtime/csp.d.ts.map +0 -1
  247. package/esm/runtime/index.d.ts +0 -17
  248. package/esm/runtime/index.d.ts.map +0 -1
  249. package/esm/runtime/index.js +0 -5186
  250. package/esm/runtime/mcp-bridge.d.ts +0 -101
  251. package/esm/runtime/mcp-bridge.d.ts.map +0 -1
  252. package/esm/runtime/renderer-runtime.d.ts +0 -133
  253. package/esm/runtime/renderer-runtime.d.ts.map +0 -1
  254. package/esm/runtime/sanitizer.d.ts +0 -172
  255. package/esm/runtime/sanitizer.d.ts.map +0 -1
  256. package/esm/runtime/types.d.ts +0 -415
  257. package/esm/runtime/types.d.ts.map +0 -1
  258. package/esm/runtime/wrapper.d.ts +0 -421
  259. package/esm/runtime/wrapper.d.ts.map +0 -1
  260. package/esm/styles/index.d.ts +0 -8
  261. package/esm/styles/index.d.ts.map +0 -1
  262. package/esm/styles/index.js +0 -171
  263. package/esm/styles/variants.d.ts +0 -51
  264. package/esm/styles/variants.d.ts.map +0 -1
  265. package/esm/theme/cdn.d.ts +0 -195
  266. package/esm/theme/cdn.d.ts.map +0 -1
  267. package/esm/theme/index.d.ts +0 -18
  268. package/esm/theme/index.d.ts.map +0 -1
  269. package/esm/theme/index.js +0 -700
  270. package/esm/theme/platforms.d.ts +0 -107
  271. package/esm/theme/platforms.d.ts.map +0 -1
  272. package/esm/theme/presets/github-openai.d.ts +0 -50
  273. package/esm/theme/presets/github-openai.d.ts.map +0 -1
  274. package/esm/theme/presets/index.d.ts +0 -11
  275. package/esm/theme/presets/index.d.ts.map +0 -1
  276. package/esm/theme/theme.d.ts +0 -396
  277. package/esm/theme/theme.d.ts.map +0 -1
  278. package/esm/tool-template/builder.d.ts +0 -213
  279. package/esm/tool-template/builder.d.ts.map +0 -1
  280. package/esm/tool-template/index.d.ts +0 -16
  281. package/esm/tool-template/index.d.ts.map +0 -1
  282. package/esm/tool-template/index.js +0 -3515
  283. package/esm/types/index.d.ts +0 -14
  284. package/esm/types/index.d.ts.map +0 -1
  285. package/esm/types/index.js +0 -75
  286. package/esm/types/ui-config.d.ts +0 -639
  287. package/esm/types/ui-config.d.ts.map +0 -1
  288. package/esm/types/ui-runtime.d.ts +0 -1007
  289. package/esm/types/ui-runtime.d.ts.map +0 -1
  290. package/esm/typings/cache/cache-adapter.d.ts +0 -125
  291. package/esm/typings/cache/cache-adapter.d.ts.map +0 -1
  292. package/esm/typings/cache/index.d.ts +0 -10
  293. package/esm/typings/cache/index.d.ts.map +0 -1
  294. package/esm/typings/cache/memory-cache.d.ts +0 -92
  295. package/esm/typings/cache/memory-cache.d.ts.map +0 -1
  296. package/esm/typings/dts-parser.d.ts +0 -90
  297. package/esm/typings/dts-parser.d.ts.map +0 -1
  298. package/esm/typings/index.d.ts +0 -48
  299. package/esm/typings/index.d.ts.map +0 -1
  300. package/esm/typings/schemas.d.ts +0 -232
  301. package/esm/typings/schemas.d.ts.map +0 -1
  302. package/esm/typings/type-fetcher.d.ts +0 -89
  303. package/esm/typings/type-fetcher.d.ts.map +0 -1
  304. package/esm/typings/types.d.ts +0 -320
  305. package/esm/typings/types.d.ts.map +0 -1
  306. package/esm/utils/escape-html.d.ts +0 -58
  307. package/esm/utils/escape-html.d.ts.map +0 -1
  308. package/esm/utils/index.d.ts +0 -10
  309. package/esm/utils/index.d.ts.map +0 -1
  310. package/esm/utils/index.js +0 -40
  311. package/esm/utils/safe-stringify.d.ts +0 -30
  312. package/esm/utils/safe-stringify.d.ts.map +0 -1
  313. package/esm/validation/error-box.d.ts +0 -56
  314. package/esm/validation/error-box.d.ts.map +0 -1
  315. package/esm/validation/index.d.ts +0 -13
  316. package/esm/validation/index.d.ts.map +0 -1
  317. package/esm/validation/index.js +0 -562
  318. package/esm/validation/schema-paths.d.ts +0 -118
  319. package/esm/validation/schema-paths.d.ts.map +0 -1
  320. package/esm/validation/template-validator.d.ts +0 -143
  321. package/esm/validation/template-validator.d.ts.map +0 -1
  322. package/esm/validation/wrapper.d.ts +0 -97
  323. package/esm/validation/wrapper.d.ts.map +0 -1
  324. package/handlebars/expression-extractor.d.ts +0 -147
  325. package/handlebars/expression-extractor.d.ts.map +0 -1
  326. package/handlebars/helpers.d.ts +0 -339
  327. package/handlebars/helpers.d.ts.map +0 -1
  328. package/handlebars/index.d.ts +0 -195
  329. package/handlebars/index.d.ts.map +0 -1
  330. package/handlebars/index.js +0 -666
  331. package/registry/index.d.ts +0 -46
  332. package/registry/index.d.ts.map +0 -1
  333. package/registry/index.js +0 -6465
  334. package/registry/render-template.d.ts +0 -91
  335. package/registry/render-template.d.ts.map +0 -1
  336. package/registry/tool-ui.registry.d.ts +0 -294
  337. package/registry/tool-ui.registry.d.ts.map +0 -1
  338. package/registry/uri-utils.d.ts +0 -56
  339. package/registry/uri-utils.d.ts.map +0 -1
  340. package/renderers/cache.d.ts +0 -145
  341. package/renderers/cache.d.ts.map +0 -1
  342. package/renderers/html.renderer.d.ts +0 -123
  343. package/renderers/html.renderer.d.ts.map +0 -1
  344. package/renderers/mdx.renderer.d.ts +0 -120
  345. package/renderers/mdx.renderer.d.ts.map +0 -1
  346. package/renderers/registry.d.ts +0 -134
  347. package/renderers/registry.d.ts.map +0 -1
  348. package/renderers/types.d.ts +0 -342
  349. package/renderers/types.d.ts.map +0 -1
  350. package/renderers/utils/detect.d.ts +0 -107
  351. package/renderers/utils/detect.d.ts.map +0 -1
  352. package/renderers/utils/hash.d.ts +0 -40
  353. package/renderers/utils/hash.d.ts.map +0 -1
  354. package/renderers/utils/index.d.ts +0 -9
  355. package/renderers/utils/index.d.ts.map +0 -1
  356. package/renderers/utils/transpiler.d.ts +0 -89
  357. package/renderers/utils/transpiler.d.ts.map +0 -1
  358. package/runtime/adapters/html.adapter.d.ts +0 -59
  359. package/runtime/adapters/html.adapter.d.ts.map +0 -1
  360. package/runtime/adapters/index.d.ts +0 -26
  361. package/runtime/adapters/index.d.ts.map +0 -1
  362. package/runtime/adapters/mdx.adapter.d.ts +0 -73
  363. package/runtime/adapters/mdx.adapter.d.ts.map +0 -1
  364. package/runtime/adapters/react.adapter.d.ts.map +0 -1
  365. package/runtime/adapters/types.d.ts +0 -95
  366. package/runtime/adapters/types.d.ts.map +0 -1
  367. package/runtime/csp.d.ts +0 -48
  368. package/runtime/csp.d.ts.map +0 -1
  369. package/runtime/index.d.ts +0 -17
  370. package/runtime/index.d.ts.map +0 -1
  371. package/runtime/index.js +0 -5264
  372. package/runtime/mcp-bridge.d.ts +0 -101
  373. package/runtime/mcp-bridge.d.ts.map +0 -1
  374. package/runtime/renderer-runtime.d.ts +0 -133
  375. package/runtime/renderer-runtime.d.ts.map +0 -1
  376. package/runtime/sanitizer.d.ts +0 -172
  377. package/runtime/sanitizer.d.ts.map +0 -1
  378. package/runtime/types.d.ts +0 -415
  379. package/runtime/types.d.ts.map +0 -1
  380. package/runtime/wrapper.d.ts +0 -421
  381. package/runtime/wrapper.d.ts.map +0 -1
  382. package/styles/index.d.ts +0 -8
  383. package/styles/index.d.ts.map +0 -1
  384. package/styles/index.js +0 -222
  385. package/styles/variants.d.ts +0 -51
  386. package/styles/variants.d.ts.map +0 -1
  387. package/theme/cdn.d.ts +0 -195
  388. package/theme/cdn.d.ts.map +0 -1
  389. package/theme/index.d.ts +0 -18
  390. package/theme/index.d.ts.map +0 -1
  391. package/theme/index.js +0 -757
  392. package/theme/platforms.d.ts +0 -107
  393. package/theme/platforms.d.ts.map +0 -1
  394. package/theme/presets/github-openai.d.ts +0 -50
  395. package/theme/presets/github-openai.d.ts.map +0 -1
  396. package/theme/presets/index.d.ts +0 -11
  397. package/theme/presets/index.d.ts.map +0 -1
  398. package/theme/theme.d.ts +0 -396
  399. package/theme/theme.d.ts.map +0 -1
  400. package/tool-template/builder.d.ts +0 -213
  401. package/tool-template/builder.d.ts.map +0 -1
  402. package/tool-template/index.d.ts +0 -16
  403. package/tool-template/index.d.ts.map +0 -1
  404. package/tool-template/index.js +0 -3559
  405. package/types/index.d.ts +0 -14
  406. package/types/index.d.ts.map +0 -1
  407. package/types/index.js +0 -108
  408. package/types/ui-config.d.ts +0 -639
  409. package/types/ui-config.d.ts.map +0 -1
  410. package/types/ui-runtime.d.ts +0 -1007
  411. package/types/ui-runtime.d.ts.map +0 -1
  412. package/typings/cache/cache-adapter.d.ts +0 -125
  413. package/typings/cache/cache-adapter.d.ts.map +0 -1
  414. package/typings/cache/index.d.ts +0 -10
  415. package/typings/cache/index.d.ts.map +0 -1
  416. package/typings/cache/memory-cache.d.ts +0 -92
  417. package/typings/cache/memory-cache.d.ts.map +0 -1
  418. package/typings/dts-parser.d.ts +0 -90
  419. package/typings/dts-parser.d.ts.map +0 -1
  420. package/typings/index.d.ts +0 -48
  421. package/typings/index.d.ts.map +0 -1
  422. package/typings/schemas.d.ts +0 -232
  423. package/typings/schemas.d.ts.map +0 -1
  424. package/typings/type-fetcher.d.ts +0 -89
  425. package/typings/type-fetcher.d.ts.map +0 -1
  426. package/typings/types.d.ts +0 -320
  427. package/typings/types.d.ts.map +0 -1
  428. package/utils/escape-html.d.ts +0 -58
  429. package/utils/escape-html.d.ts.map +0 -1
  430. package/utils/index.d.ts +0 -10
  431. package/utils/index.d.ts.map +0 -1
  432. package/utils/index.js +0 -70
  433. package/utils/safe-stringify.d.ts +0 -30
  434. package/utils/safe-stringify.d.ts.map +0 -1
  435. package/validation/error-box.d.ts +0 -56
  436. package/validation/error-box.d.ts.map +0 -1
  437. package/validation/index.d.ts +0 -13
  438. package/validation/index.d.ts.map +0 -1
  439. package/validation/index.js +0 -603
  440. package/validation/schema-paths.d.ts +0 -118
  441. package/validation/schema-paths.d.ts.map +0 -1
  442. package/validation/template-validator.d.ts +0 -143
  443. package/validation/template-validator.d.ts.map +0 -1
  444. package/validation/wrapper.d.ts +0 -97
  445. package/validation/wrapper.d.ts.map +0 -1
@@ -5,150 +5,12 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
5
5
  throw Error('Dynamic require of "' + x + '" is not supported');
6
6
  });
7
7
 
8
- // libs/ui/src/styles/variants.ts
9
- var CARD_VARIANTS = {
10
- default: "bg-white border border-border rounded-xl shadow-sm",
11
- outlined: "bg-transparent border-2 border-border rounded-xl",
12
- elevated: "bg-white rounded-xl shadow-lg",
13
- filled: "bg-gray-50 rounded-xl",
14
- ghost: "bg-transparent"
15
- };
16
- var CARD_SIZES = {
17
- sm: "p-4",
18
- md: "p-6",
19
- lg: "p-8"
20
- };
21
- function getCardVariantClasses(variant) {
22
- return CARD_VARIANTS[variant];
23
- }
24
- function getCardSizeClasses(size) {
25
- return CARD_SIZES[size];
26
- }
27
- var BADGE_VARIANTS = {
28
- default: "bg-gray-100 text-gray-800",
29
- primary: "bg-primary/10 text-primary",
30
- secondary: "bg-secondary/10 text-secondary",
31
- success: "bg-success/10 text-success",
32
- warning: "bg-warning/10 text-warning",
33
- danger: "bg-danger/10 text-danger",
34
- info: "bg-blue-100 text-blue-800",
35
- outline: "border border-border text-text-primary bg-transparent"
36
- };
37
- var BADGE_SIZES = {
38
- sm: "px-2 py-0.5 text-xs",
39
- md: "px-2.5 py-1 text-xs",
40
- lg: "px-3 py-1.5 text-sm"
41
- };
42
- var BADGE_DOT_SIZES = {
43
- sm: "w-2 h-2",
44
- md: "w-2.5 h-2.5",
45
- lg: "w-3 h-3"
46
- };
47
- var BADGE_DOT_VARIANTS = {
48
- default: "bg-gray-400",
49
- primary: "bg-primary",
50
- secondary: "bg-secondary",
51
- success: "bg-success",
52
- warning: "bg-warning",
53
- danger: "bg-danger",
54
- info: "bg-blue-500",
55
- outline: "border border-current"
56
- };
57
- function getBadgeVariantClasses(variant) {
58
- return BADGE_VARIANTS[variant];
59
- }
60
- function getBadgeSizeClasses(size) {
61
- return BADGE_SIZES[size];
62
- }
63
- function getBadgeDotSizeClasses(size) {
64
- return BADGE_DOT_SIZES[size];
65
- }
66
- function getBadgeDotVariantClasses(variant) {
67
- return BADGE_DOT_VARIANTS[variant];
68
- }
69
- var BUTTON_VARIANTS = {
70
- primary: "bg-primary hover:bg-primary/90 text-white shadow-sm",
71
- secondary: "bg-secondary hover:bg-secondary/90 text-white shadow-sm",
72
- outline: "border-2 border-primary text-primary hover:bg-primary/10",
73
- ghost: "text-text-primary hover:bg-gray-100",
74
- danger: "bg-danger hover:bg-danger/90 text-white shadow-sm",
75
- success: "bg-success hover:bg-success/90 text-white shadow-sm",
76
- link: "text-primary hover:text-primary/80 hover:underline"
77
- };
78
- var BUTTON_SIZES = {
79
- xs: "px-2.5 py-1.5 text-xs",
80
- sm: "px-3 py-2 text-sm",
81
- md: "px-4 py-2.5 text-sm",
82
- lg: "px-5 py-3 text-base",
83
- xl: "px-6 py-3.5 text-lg"
84
- };
85
- var BUTTON_ICON_SIZES = {
86
- xs: "p-1.5",
87
- sm: "p-2",
88
- md: "p-2.5",
89
- lg: "p-3",
90
- xl: "p-4"
91
- };
92
- var BUTTON_BASE_CLASSES = "inline-flex items-center justify-center font-medium rounded-lg transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-primary/50 focus:ring-offset-2";
93
- function getButtonVariantClasses(variant) {
94
- return BUTTON_VARIANTS[variant];
95
- }
96
- function getButtonSizeClasses(size, iconOnly) {
97
- return iconOnly ? BUTTON_ICON_SIZES[size] : BUTTON_SIZES[size];
98
- }
99
- var ALERT_VARIANTS = {
100
- info: {
101
- container: "bg-blue-50 border-blue-200 text-blue-800",
102
- icon: "text-blue-500"
103
- },
104
- success: {
105
- container: "bg-success/10 border-success/30 text-success",
106
- icon: "text-success"
107
- },
108
- warning: {
109
- container: "bg-warning/10 border-warning/30 text-warning",
110
- icon: "text-warning"
111
- },
112
- danger: {
113
- container: "bg-danger/10 border-danger/30 text-danger",
114
- icon: "text-danger"
115
- },
116
- neutral: {
117
- container: "bg-gray-50 border-gray-200 text-gray-800",
118
- icon: "text-gray-500"
119
- }
120
- };
121
- var ALERT_BASE_CLASSES = "rounded-lg border p-4";
122
- function getAlertVariantClasses(variant) {
123
- return ALERT_VARIANTS[variant];
124
- }
125
- var ALERT_ICONS = {
126
- info: `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
127
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
128
- </svg>`,
129
- success: `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
130
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
131
- </svg>`,
132
- warning: `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
133
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
134
- </svg>`,
135
- danger: `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
136
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"/>
137
- </svg>`,
138
- neutral: `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
139
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
140
- </svg>`
141
- };
142
- var CLOSE_ICON = `<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
143
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
144
- </svg>`;
145
- var LOADING_SPINNER = `<svg class="animate-spin -ml-1 mr-2 h-4 w-4" fill="none" viewBox="0 0 24 24">
146
- <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
147
- <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
148
- </svg>`;
149
- function cn(...classes) {
150
- return classes.filter(Boolean).join(" ");
151
- }
8
+ // libs/ui/src/react/Card.tsx
9
+ import {
10
+ getCardVariantClasses,
11
+ getCardSizeClasses,
12
+ cn
13
+ } from "@frontmcp/uipack/styles";
152
14
 
153
15
  // libs/ui/src/render/prerender.ts
154
16
  async function renderToString(element) {
@@ -239,6 +101,13 @@ function renderCardSync(props) {
239
101
  }
240
102
 
241
103
  // libs/ui/src/react/Badge.tsx
104
+ import {
105
+ getBadgeVariantClasses,
106
+ getBadgeSizeClasses,
107
+ getBadgeDotSizeClasses,
108
+ getBadgeDotVariantClasses,
109
+ cn as cn2
110
+ } from "@frontmcp/uipack/styles";
242
111
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
243
112
  function Badge({
244
113
  variant = "default",
@@ -252,7 +121,7 @@ function Badge({
252
121
  children
253
122
  }) {
254
123
  if (dot) {
255
- const dotClasses = cn(
124
+ const dotClasses = cn2(
256
125
  "inline-block rounded-full",
257
126
  getBadgeDotSizeClasses(size),
258
127
  getBadgeDotVariantClasses(variant),
@@ -263,7 +132,7 @@ function Badge({
263
132
  }
264
133
  const variantClasses = getBadgeVariantClasses(variant);
265
134
  const sizeClasses = getBadgeSizeClasses(size);
266
- const baseClasses = cn(
135
+ const baseClasses = cn2(
267
136
  "inline-flex items-center font-medium",
268
137
  pill ? "rounded-full" : "rounded-md",
269
138
  variantClasses,
@@ -297,6 +166,13 @@ function renderBadgeSync(props) {
297
166
  }
298
167
 
299
168
  // libs/ui/src/react/Button.tsx
169
+ import {
170
+ getButtonVariantClasses,
171
+ getButtonSizeClasses,
172
+ BUTTON_BASE_CLASSES,
173
+ LOADING_SPINNER,
174
+ cn as cn3
175
+ } from "@frontmcp/uipack/styles";
300
176
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
301
177
  function Button({
302
178
  variant = "primary",
@@ -316,7 +192,7 @@ function Button({
316
192
  const sizeClasses = getButtonSizeClasses(size, iconOnly);
317
193
  const disabledClasses = disabled || loading ? "opacity-50 cursor-not-allowed" : "";
318
194
  const widthClasses = fullWidth ? "w-full" : "";
319
- const allClasses = cn(BUTTON_BASE_CLASSES, variantClasses, sizeClasses, disabledClasses, widthClasses, className);
195
+ const allClasses = cn3(BUTTON_BASE_CLASSES, variantClasses, sizeClasses, disabledClasses, widthClasses, className);
320
196
  const iconElement = icon && /* @__PURE__ */ jsx3("span", { className: iconPosition === "left" ? "mr-2" : "ml-2", children: icon });
321
197
  return /* @__PURE__ */ jsxs3("button", { type, className: allClasses, disabled: disabled || loading, onClick, children: [
322
198
  loading && /* @__PURE__ */ jsx3("span", { className: "mr-2", dangerouslySetInnerHTML: { __html: LOADING_SPINNER } }),
@@ -337,6 +213,13 @@ function renderButtonSync(props) {
337
213
  }
338
214
 
339
215
  // libs/ui/src/react/Alert.tsx
216
+ import {
217
+ getAlertVariantClasses,
218
+ ALERT_BASE_CLASSES,
219
+ ALERT_ICONS,
220
+ CLOSE_ICON as CLOSE_ICON2,
221
+ cn as cn4
222
+ } from "@frontmcp/uipack/styles";
340
223
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
341
224
  function Alert({
342
225
  variant = "info",
@@ -349,11 +232,11 @@ function Alert({
349
232
  children
350
233
  }) {
351
234
  const variantStyles = getAlertVariantClasses(variant);
352
- const allClasses = cn(ALERT_BASE_CLASSES, variantStyles.container, className);
235
+ const allClasses = cn4(ALERT_BASE_CLASSES, variantStyles.container, className);
353
236
  const iconContent = icon || (showIcon ? /* @__PURE__ */ jsx4(
354
237
  "span",
355
238
  {
356
- className: cn("flex-shrink-0", variantStyles.icon),
239
+ className: cn4("flex-shrink-0", variantStyles.icon),
357
240
  dangerouslySetInnerHTML: { __html: ALERT_ICONS[variant] }
358
241
  }
359
242
  ) : null);
@@ -370,7 +253,7 @@ function Alert({
370
253
  className: "flex-shrink-0 ml-3 hover:opacity-70 transition-opacity",
371
254
  "aria-label": "Dismiss",
372
255
  onClick: onDismiss,
373
- children: /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: CLOSE_ICON } })
256
+ children: /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: CLOSE_ICON2 } })
374
257
  }
375
258
  )
376
259
  ] }) });
@@ -923,161 +806,2058 @@ var FrontMcpBridge = class {
923
806
  }
924
807
  };
925
808
 
926
- // libs/ui/src/react/hooks/context.tsx
927
- import { jsx as jsx5 } from "react/jsx-runtime";
928
- var McpBridgeContext = createContext(null);
929
- function McpBridgeProvider({ children, config, onReady, onError }) {
930
- const [bridge, setBridge] = useState(null);
931
- const [loading, setLoading] = useState(true);
932
- const [error, setError] = useState(null);
933
- useEffect(() => {
934
- let mounted = true;
935
- let bridgeInstance = null;
936
- const initBridge = async () => {
937
- try {
938
- bridgeInstance = new FrontMcpBridge(config);
939
- await bridgeInstance.initialize();
940
- if (mounted) {
941
- setBridge(bridgeInstance);
942
- setLoading(false);
943
- onReady?.(bridgeInstance);
944
- }
945
- } catch (err) {
946
- if (mounted) {
947
- const error2 = err instanceof Error ? err : new Error(String(err));
948
- setError(error2);
949
- setLoading(false);
950
- onError?.(error2);
951
- }
809
+ // libs/ui/src/bridge/adapters/base-adapter.ts
810
+ var DEFAULT_CAPABILITIES = {
811
+ canCallTools: false,
812
+ canSendMessages: false,
813
+ canOpenLinks: false,
814
+ canPersistState: true,
815
+ // localStorage fallback
816
+ hasNetworkAccess: true,
817
+ supportsDisplayModes: false,
818
+ supportsTheme: true
819
+ };
820
+ var DEFAULT_SAFE_AREA = {
821
+ top: 0,
822
+ bottom: 0,
823
+ left: 0,
824
+ right: 0
825
+ };
826
+ var BaseAdapter = class {
827
+ _capabilities = { ...DEFAULT_CAPABILITIES };
828
+ _hostContext;
829
+ _widgetState = {};
830
+ _toolInput = {};
831
+ _toolOutput = void 0;
832
+ _structuredContent = void 0;
833
+ _initialized = false;
834
+ _contextListeners = /* @__PURE__ */ new Set();
835
+ _toolResultListeners = /* @__PURE__ */ new Set();
836
+ constructor() {
837
+ this._hostContext = this._createDefaultHostContext();
838
+ }
839
+ get capabilities() {
840
+ return this._capabilities;
841
+ }
842
+ async initialize() {
843
+ if (this._initialized) return;
844
+ this._loadWidgetState();
845
+ this._readInjectedData();
846
+ this._initialized = true;
847
+ }
848
+ dispose() {
849
+ this._contextListeners.clear();
850
+ this._toolResultListeners.clear();
851
+ this._initialized = false;
852
+ }
853
+ // ============================================
854
+ // Data Access
855
+ // ============================================
856
+ getTheme() {
857
+ return this._hostContext.theme;
858
+ }
859
+ getDisplayMode() {
860
+ return this._hostContext.displayMode;
861
+ }
862
+ getUserAgent() {
863
+ return this._hostContext.userAgent;
864
+ }
865
+ getLocale() {
866
+ return this._hostContext.locale;
867
+ }
868
+ getToolInput() {
869
+ return this._toolInput;
870
+ }
871
+ getToolOutput() {
872
+ return this._toolOutput;
873
+ }
874
+ getStructuredContent() {
875
+ return this._structuredContent;
876
+ }
877
+ getWidgetState() {
878
+ return this._widgetState;
879
+ }
880
+ getSafeArea() {
881
+ return this._hostContext.safeArea;
882
+ }
883
+ getViewport() {
884
+ return this._hostContext.viewport;
885
+ }
886
+ getHostContext() {
887
+ return { ...this._hostContext };
888
+ }
889
+ // ============================================
890
+ // Actions (override in subclasses for real functionality)
891
+ // ============================================
892
+ async callTool(_name, _args) {
893
+ if (!this._capabilities.canCallTools) {
894
+ throw new Error(`Tool calls are not supported by ${this.name} adapter`);
895
+ }
896
+ throw new Error("callTool not implemented");
897
+ }
898
+ async sendMessage(_content) {
899
+ if (!this._capabilities.canSendMessages) {
900
+ throw new Error(`Sending messages is not supported by ${this.name} adapter`);
901
+ }
902
+ throw new Error("sendMessage not implemented");
903
+ }
904
+ async openLink(url) {
905
+ if (!this._capabilities.canOpenLinks) {
906
+ if (typeof window !== "undefined") {
907
+ window.open(url, "_blank", "noopener,noreferrer");
908
+ return;
952
909
  }
910
+ throw new Error(`Opening links is not supported by ${this.name} adapter`);
911
+ }
912
+ throw new Error("openLink not implemented");
913
+ }
914
+ async requestDisplayMode(_mode) {
915
+ if (!this._capabilities.supportsDisplayModes) {
916
+ return;
917
+ }
918
+ throw new Error("requestDisplayMode not implemented");
919
+ }
920
+ async requestClose() {
921
+ }
922
+ setWidgetState(state) {
923
+ this._widgetState = { ...this._widgetState, ...state };
924
+ this._persistWidgetState();
925
+ }
926
+ // ============================================
927
+ // Events
928
+ // ============================================
929
+ onContextChange(callback) {
930
+ this._contextListeners.add(callback);
931
+ return () => {
932
+ this._contextListeners.delete(callback);
953
933
  };
954
- initBridge();
934
+ }
935
+ onToolResult(callback) {
936
+ this._toolResultListeners.add(callback);
955
937
  return () => {
956
- mounted = false;
957
- if (bridgeInstance) {
958
- bridgeInstance.dispose();
959
- }
938
+ this._toolResultListeners.delete(callback);
960
939
  };
961
- }, [config, onReady, onError]);
962
- const contextValue = useMemo(
963
- () => ({
964
- bridge,
965
- loading,
966
- error,
967
- ready: !loading && !error && bridge !== null,
968
- adapterId: bridge?.adapterId,
969
- capabilities: bridge?.capabilities
970
- }),
971
- [bridge, loading, error]
972
- );
973
- return /* @__PURE__ */ jsx5(McpBridgeContext.Provider, { value: contextValue, children });
974
- }
975
- var SSR_DEFAULT_CONTEXT = {
976
- bridge: null,
977
- loading: false,
978
- error: null,
979
- ready: false,
980
- adapterId: void 0,
981
- capabilities: void 0
982
- };
983
- function useMcpBridgeContext() {
984
- const context = useContext(McpBridgeContext);
985
- if (!context) {
986
- return SSR_DEFAULT_CONTEXT;
987
940
  }
988
- return context;
989
- }
990
- function useMcpBridge() {
991
- const { bridge } = useMcpBridgeContext();
992
- return bridge;
993
- }
994
- function useTheme() {
995
- const { bridge, ready } = useMcpBridgeContext();
996
- const [theme, setTheme] = useState("light");
997
- useEffect(() => {
998
- if (!ready || !bridge) return;
999
- setTheme(bridge.getTheme());
1000
- const unsubscribe = bridge.onContextChange((changes) => {
1001
- if (changes.theme) {
1002
- setTheme(changes.theme);
1003
- }
1004
- });
1005
- return unsubscribe;
1006
- }, [bridge, ready]);
1007
- return theme;
1008
- }
1009
- function useDisplayMode() {
1010
- const { bridge, ready } = useMcpBridgeContext();
1011
- const [displayMode, setDisplayMode] = useState("inline");
1012
- useEffect(() => {
1013
- if (!ready || !bridge) return;
1014
- setDisplayMode(bridge.getDisplayMode());
1015
- const unsubscribe = bridge.onContextChange((changes) => {
1016
- if (changes.displayMode) {
1017
- setDisplayMode(changes.displayMode);
1018
- }
1019
- });
1020
- return unsubscribe;
1021
- }, [bridge, ready]);
1022
- return displayMode;
1023
- }
1024
- function useHostContext() {
1025
- const { bridge, ready } = useMcpBridgeContext();
1026
- const [context, setContext] = useState(null);
1027
- useEffect(() => {
1028
- if (!ready || !bridge) return;
1029
- const adapter = bridge.getAdapter?.();
1030
- if (adapter) {
1031
- setContext(adapter.getHostContext());
941
+ // ============================================
942
+ // Protected Helpers
943
+ // ============================================
944
+ /**
945
+ * Create default host context from environment detection.
946
+ */
947
+ _createDefaultHostContext() {
948
+ return {
949
+ theme: this._detectTheme(),
950
+ displayMode: "inline",
951
+ locale: this._detectLocale(),
952
+ userAgent: this._detectUserAgent(),
953
+ safeArea: DEFAULT_SAFE_AREA,
954
+ viewport: this._detectViewport()
955
+ };
956
+ }
957
+ /**
958
+ * Detect theme from CSS media query.
959
+ */
960
+ _detectTheme() {
961
+ if (typeof window !== "undefined" && window.matchMedia) {
962
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
1032
963
  }
1033
- const unsubscribe = bridge.onContextChange((changes) => {
1034
- setContext((prev) => prev ? { ...prev, ...changes } : null);
1035
- });
1036
- return unsubscribe;
1037
- }, [bridge, ready]);
1038
- return context;
1039
- }
1040
- function useCapability(cap) {
1041
- const { capabilities } = useMcpBridgeContext();
1042
- return capabilities?.[cap] === true;
1043
- }
1044
-
1045
- // libs/ui/src/react/hooks/tools.tsx
1046
- import { useState as useState2, useCallback as useCallback2, useEffect as useEffect2 } from "react";
1047
- function useToolInput() {
1048
- const { bridge, ready } = useMcpBridgeContext();
1049
- if (!ready || !bridge) {
1050
- return null;
964
+ return "light";
1051
965
  }
1052
- try {
1053
- return bridge.getToolInput();
1054
- } catch {
1055
- return null;
966
+ /**
967
+ * Detect locale from navigator.
968
+ */
969
+ _detectLocale() {
970
+ if (typeof navigator !== "undefined") {
971
+ return navigator.language || "en-US";
972
+ }
973
+ return "en-US";
1056
974
  }
1057
- }
1058
- function useToolOutput() {
1059
- const { bridge, ready } = useMcpBridgeContext();
1060
- const [output, setOutput] = useState2(null);
1061
- useEffect2(() => {
1062
- if (!ready || !bridge) return;
975
+ /**
976
+ * Detect user agent capabilities.
977
+ */
978
+ _detectUserAgent() {
979
+ if (typeof navigator === "undefined") {
980
+ return { type: "web", hover: true, touch: false };
981
+ }
982
+ const ua = navigator.userAgent || "";
983
+ const isMobile = /iPhone|iPad|iPod|Android/i.test(ua);
984
+ const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
985
+ const hasHover = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(hover: hover)").matches;
986
+ return {
987
+ type: isMobile ? "mobile" : "web",
988
+ hover: hasHover !== false,
989
+ touch: hasTouch
990
+ };
991
+ }
992
+ /**
993
+ * Detect viewport dimensions.
994
+ */
995
+ _detectViewport() {
996
+ if (typeof window !== "undefined") {
997
+ return {
998
+ width: window.innerWidth,
999
+ height: window.innerHeight
1000
+ };
1001
+ }
1002
+ return void 0;
1003
+ }
1004
+ /**
1005
+ * Read injected tool data from window globals.
1006
+ */
1007
+ _readInjectedData() {
1008
+ if (typeof window === "undefined") return;
1009
+ const win = window;
1010
+ if (win.__mcpToolInput) {
1011
+ this._toolInput = win.__mcpToolInput;
1012
+ }
1013
+ if (win.__mcpToolOutput) {
1014
+ this._toolOutput = win.__mcpToolOutput;
1015
+ }
1016
+ if (win.__mcpStructuredContent) {
1017
+ this._structuredContent = win.__mcpStructuredContent;
1018
+ }
1019
+ if (win.__mcpHostContext) {
1020
+ this._hostContext = { ...this._hostContext, ...win.__mcpHostContext };
1021
+ }
1022
+ }
1023
+ /**
1024
+ * Load widget state from localStorage.
1025
+ */
1026
+ _loadWidgetState() {
1027
+ if (typeof localStorage === "undefined") return;
1063
1028
  try {
1064
- const initialOutput = bridge.getToolOutput();
1065
- if (initialOutput !== void 0) {
1066
- setOutput(initialOutput);
1029
+ const key = this._getStateKey();
1030
+ const stored = localStorage.getItem(key);
1031
+ if (stored) {
1032
+ this._widgetState = JSON.parse(stored);
1067
1033
  }
1068
1034
  } catch {
1069
1035
  }
1070
- const unsubscribe = bridge.onToolResult((result) => {
1071
- setOutput(result);
1072
- });
1073
- return unsubscribe;
1074
- }, [bridge, ready]);
1075
- return output;
1076
- }
1077
- function useStructuredContent() {
1078
- const { bridge, ready } = useMcpBridgeContext();
1079
- if (!ready || !bridge) {
1080
- return null;
1036
+ }
1037
+ /**
1038
+ * Persist widget state to localStorage.
1039
+ */
1040
+ _persistWidgetState() {
1041
+ if (typeof localStorage === "undefined") return;
1042
+ try {
1043
+ const key = this._getStateKey();
1044
+ localStorage.setItem(key, JSON.stringify(this._widgetState));
1045
+ } catch {
1046
+ }
1047
+ }
1048
+ /**
1049
+ * Get localStorage key for widget state.
1050
+ */
1051
+ _getStateKey() {
1052
+ if (typeof window !== "undefined") {
1053
+ const toolName = window.__mcpToolName || "unknown";
1054
+ return `frontmcp:widget:${toolName}`;
1055
+ }
1056
+ return "frontmcp:widget:unknown";
1057
+ }
1058
+ /**
1059
+ * Notify context change listeners.
1060
+ */
1061
+ _notifyContextChange(changes) {
1062
+ this._hostContext = { ...this._hostContext, ...changes };
1063
+ this._contextListeners.forEach((cb) => {
1064
+ try {
1065
+ cb(changes);
1066
+ } catch (e) {
1067
+ console.error("[FrontMcpBridge] Context change listener error:", e);
1068
+ }
1069
+ });
1070
+ }
1071
+ /**
1072
+ * Notify tool result listeners.
1073
+ */
1074
+ _notifyToolResult(result) {
1075
+ this._toolOutput = result;
1076
+ this._toolResultListeners.forEach((cb) => {
1077
+ try {
1078
+ cb(result);
1079
+ } catch (e) {
1080
+ console.error("[FrontMcpBridge] Tool result listener error:", e);
1081
+ }
1082
+ });
1083
+ }
1084
+ };
1085
+
1086
+ // libs/ui/src/bridge/adapters/openai.adapter.ts
1087
+ var OpenAIAdapter = class extends BaseAdapter {
1088
+ id = "openai";
1089
+ name = "OpenAI ChatGPT";
1090
+ priority = 100;
1091
+ // Highest priority
1092
+ _openai;
1093
+ _unsubscribeContext;
1094
+ _unsubscribeToolResult;
1095
+ constructor() {
1096
+ super();
1097
+ this._capabilities = {
1098
+ ...DEFAULT_CAPABILITIES,
1099
+ canCallTools: true,
1100
+ canSendMessages: true,
1101
+ canOpenLinks: true,
1102
+ canPersistState: true,
1103
+ hasNetworkAccess: true,
1104
+ supportsDisplayModes: true,
1105
+ supportsTheme: true
1106
+ };
1107
+ }
1108
+ /**
1109
+ * Check if OpenAI Apps SDK is available.
1110
+ */
1111
+ canHandle() {
1112
+ if (typeof window === "undefined") return false;
1113
+ const win = window;
1114
+ return Boolean(win.openai?.canvas);
1115
+ }
1116
+ /**
1117
+ * Initialize the OpenAI adapter.
1118
+ */
1119
+ async initialize() {
1120
+ if (this._initialized) return;
1121
+ this._openai = window.openai;
1122
+ await super.initialize();
1123
+ this._syncContextFromSDK();
1124
+ if (this._openai?.canvas?.onContextChange) {
1125
+ this._unsubscribeContext = this._openai.canvas.onContextChange((changes) => {
1126
+ this._notifyContextChange(changes);
1127
+ });
1128
+ }
1129
+ if (this._openai?.canvas?.onToolResult) {
1130
+ this._unsubscribeToolResult = this._openai.canvas.onToolResult((result) => {
1131
+ this._notifyToolResult(result);
1132
+ });
1133
+ }
1134
+ }
1135
+ /**
1136
+ * Dispose adapter resources.
1137
+ */
1138
+ dispose() {
1139
+ if (this._unsubscribeContext) {
1140
+ this._unsubscribeContext();
1141
+ this._unsubscribeContext = void 0;
1142
+ }
1143
+ if (this._unsubscribeToolResult) {
1144
+ this._unsubscribeToolResult();
1145
+ this._unsubscribeToolResult = void 0;
1146
+ }
1147
+ this._openai = void 0;
1148
+ super.dispose();
1149
+ }
1150
+ // ============================================
1151
+ // Data Access (override with SDK calls)
1152
+ // ============================================
1153
+ getTheme() {
1154
+ if (this._openai?.canvas?.getTheme) {
1155
+ const theme = this._openai.canvas.getTheme();
1156
+ return theme === "dark" ? "dark" : "light";
1157
+ }
1158
+ return super.getTheme();
1159
+ }
1160
+ getDisplayMode() {
1161
+ if (this._openai?.canvas?.getDisplayMode) {
1162
+ const mode = this._openai.canvas.getDisplayMode();
1163
+ if (mode === "fullscreen" || mode === "pip" || mode === "carousel") {
1164
+ return mode;
1165
+ }
1166
+ return "inline";
1167
+ }
1168
+ return super.getDisplayMode();
1169
+ }
1170
+ // ============================================
1171
+ // Actions (proxy to SDK)
1172
+ // ============================================
1173
+ async callTool(name, args) {
1174
+ if (!this._openai?.canvas?.callServerTool) {
1175
+ throw new Error("callServerTool not available in OpenAI SDK");
1176
+ }
1177
+ return this._openai.canvas.callServerTool(name, args);
1178
+ }
1179
+ async sendMessage(content) {
1180
+ if (!this._openai?.canvas?.sendMessage) {
1181
+ throw new Error("sendMessage not available in OpenAI SDK");
1182
+ }
1183
+ await this._openai.canvas.sendMessage(content);
1184
+ }
1185
+ async openLink(url) {
1186
+ if (!this._openai?.canvas?.openLink) {
1187
+ return super.openLink(url);
1188
+ }
1189
+ await this._openai.canvas.openLink(url);
1190
+ }
1191
+ async requestDisplayMode(mode) {
1192
+ if (!this._openai?.canvas?.setDisplayMode) {
1193
+ return super.requestDisplayMode(mode);
1194
+ }
1195
+ await this._openai.canvas.setDisplayMode(mode);
1196
+ this._hostContext = { ...this._hostContext, displayMode: mode };
1197
+ }
1198
+ async requestClose() {
1199
+ if (this._openai?.canvas?.close) {
1200
+ await this._openai.canvas.close();
1201
+ }
1202
+ }
1203
+ // ============================================
1204
+ // Private Helpers
1205
+ // ============================================
1206
+ /**
1207
+ * Sync context from OpenAI SDK.
1208
+ */
1209
+ _syncContextFromSDK() {
1210
+ if (!this._openai?.canvas) return;
1211
+ if (this._openai.canvas.getTheme) {
1212
+ const theme = this._openai.canvas.getTheme();
1213
+ this._hostContext.theme = theme === "dark" ? "dark" : "light";
1214
+ }
1215
+ if (this._openai.canvas.getDisplayMode) {
1216
+ const mode = this._openai.canvas.getDisplayMode();
1217
+ if (mode === "fullscreen" || mode === "pip" || mode === "carousel" || mode === "inline") {
1218
+ this._hostContext.displayMode = mode;
1219
+ }
1220
+ }
1221
+ if (this._openai.canvas.getContext) {
1222
+ const ctx = this._openai.canvas.getContext();
1223
+ if (ctx) {
1224
+ this._hostContext = { ...this._hostContext, ...ctx };
1225
+ }
1226
+ }
1227
+ }
1228
+ };
1229
+ function createOpenAIAdapter() {
1230
+ return new OpenAIAdapter();
1231
+ }
1232
+
1233
+ // libs/ui/src/bridge/adapters/ext-apps.adapter.ts
1234
+ var ExtAppsAdapter = class extends BaseAdapter {
1235
+ id = "ext-apps";
1236
+ name = "ext-apps (SEP-1865)";
1237
+ priority = 80;
1238
+ // High priority, but below OpenAI native
1239
+ _config;
1240
+ _messageListener;
1241
+ _pendingRequests = /* @__PURE__ */ new Map();
1242
+ _requestId = 0;
1243
+ _trustedOrigin;
1244
+ _hostCapabilities = {};
1245
+ constructor(config) {
1246
+ super();
1247
+ this._config = config || {};
1248
+ this._capabilities = {
1249
+ ...DEFAULT_CAPABILITIES,
1250
+ canPersistState: true,
1251
+ hasNetworkAccess: true,
1252
+ // ext-apps usually allows network
1253
+ supportsTheme: true
1254
+ };
1255
+ }
1256
+ /**
1257
+ * Check if we're in an iframe (potential ext-apps context).
1258
+ */
1259
+ canHandle() {
1260
+ if (typeof window === "undefined") return false;
1261
+ const inIframe = window.parent !== window;
1262
+ if (!inIframe) return false;
1263
+ const win = window;
1264
+ if (win.openai?.canvas) return false;
1265
+ if (win.__mcpPlatform === "ext-apps") return true;
1266
+ return true;
1267
+ }
1268
+ /**
1269
+ * Initialize the ext-apps adapter with protocol handshake.
1270
+ */
1271
+ async initialize() {
1272
+ if (this._initialized) return;
1273
+ this._setupMessageListener();
1274
+ await super.initialize();
1275
+ await this._performHandshake();
1276
+ this._initialized = true;
1277
+ }
1278
+ /**
1279
+ * Dispose adapter resources.
1280
+ */
1281
+ dispose() {
1282
+ if (this._messageListener && typeof window !== "undefined") {
1283
+ window.removeEventListener("message", this._messageListener);
1284
+ this._messageListener = void 0;
1285
+ }
1286
+ for (const [id, pending] of this._pendingRequests) {
1287
+ clearTimeout(pending.timeout);
1288
+ pending.reject(new Error("Adapter disposed"));
1289
+ }
1290
+ this._pendingRequests.clear();
1291
+ super.dispose();
1292
+ }
1293
+ // ============================================
1294
+ // Actions (via JSON-RPC)
1295
+ // ============================================
1296
+ async callTool(name, args) {
1297
+ if (!this._hostCapabilities.serverToolProxy) {
1298
+ throw new Error("Server tool proxy not supported by host");
1299
+ }
1300
+ return this._sendRequest("ui/callServerTool", {
1301
+ name,
1302
+ arguments: args
1303
+ });
1304
+ }
1305
+ async sendMessage(content) {
1306
+ await this._sendRequest("ui/message", { content });
1307
+ }
1308
+ async openLink(url) {
1309
+ if (!this._hostCapabilities.openLink) {
1310
+ return super.openLink(url);
1311
+ }
1312
+ await this._sendRequest("ui/openLink", { url });
1313
+ }
1314
+ async requestDisplayMode(mode) {
1315
+ await this._sendRequest("ui/setDisplayMode", { mode });
1316
+ this._hostContext = { ...this._hostContext, displayMode: mode };
1317
+ }
1318
+ async requestClose() {
1319
+ await this._sendRequest("ui/close", {});
1320
+ }
1321
+ // ============================================
1322
+ // Private: Message Handling
1323
+ // ============================================
1324
+ /**
1325
+ * Setup postMessage listener for incoming messages.
1326
+ */
1327
+ _setupMessageListener() {
1328
+ if (typeof window === "undefined") return;
1329
+ this._messageListener = (event) => {
1330
+ this._handleMessage(event);
1331
+ };
1332
+ window.addEventListener("message", this._messageListener);
1333
+ }
1334
+ /**
1335
+ * Handle incoming postMessage events.
1336
+ */
1337
+ _handleMessage(event) {
1338
+ if (!this._isOriginTrusted(event.origin)) {
1339
+ return;
1340
+ }
1341
+ const data = event.data;
1342
+ if (!data || typeof data !== "object") return;
1343
+ if (data.jsonrpc !== "2.0") return;
1344
+ if ("id" in data && (data.result !== void 0 || data.error !== void 0)) {
1345
+ this._handleResponse(data);
1346
+ return;
1347
+ }
1348
+ if ("method" in data && !("id" in data)) {
1349
+ this._handleNotification(data);
1350
+ return;
1351
+ }
1352
+ }
1353
+ /**
1354
+ * Handle JSON-RPC response.
1355
+ */
1356
+ _handleResponse(response) {
1357
+ const pending = this._pendingRequests.get(response.id);
1358
+ if (!pending) return;
1359
+ clearTimeout(pending.timeout);
1360
+ this._pendingRequests.delete(response.id);
1361
+ if (response.error) {
1362
+ pending.reject(new Error(`${response.error.message} (code: ${response.error.code})`));
1363
+ } else {
1364
+ pending.resolve(response.result);
1365
+ }
1366
+ }
1367
+ /**
1368
+ * Handle JSON-RPC notification from host.
1369
+ */
1370
+ _handleNotification(notification) {
1371
+ switch (notification.method) {
1372
+ case "ui/notifications/tool-input":
1373
+ this._handleToolInput(notification.params);
1374
+ break;
1375
+ case "ui/notifications/tool-input-partial":
1376
+ this._handleToolInputPartial(notification.params);
1377
+ break;
1378
+ case "ui/notifications/tool-result":
1379
+ this._handleToolResult(notification.params);
1380
+ break;
1381
+ case "ui/notifications/host-context-changed":
1382
+ this._handleHostContextChange(notification.params);
1383
+ break;
1384
+ case "ui/notifications/initialized":
1385
+ break;
1386
+ case "ui/notifications/cancelled":
1387
+ this._handleCancelled(notification.params);
1388
+ break;
1389
+ }
1390
+ }
1391
+ /**
1392
+ * Handle tool input notification.
1393
+ */
1394
+ _handleToolInput(params) {
1395
+ this._toolInput = params.arguments || {};
1396
+ this._emitBridgeEvent("tool:input", { arguments: this._toolInput });
1397
+ }
1398
+ /**
1399
+ * Handle partial tool input (streaming).
1400
+ */
1401
+ _handleToolInputPartial(params) {
1402
+ this._toolInput = { ...this._toolInput, ...params.arguments };
1403
+ this._emitBridgeEvent("tool:input-partial", { arguments: this._toolInput });
1404
+ }
1405
+ /**
1406
+ * Handle tool result notification.
1407
+ */
1408
+ _handleToolResult(params) {
1409
+ this._toolOutput = params.content;
1410
+ this._structuredContent = params.structuredContent;
1411
+ this._notifyToolResult(params.content);
1412
+ this._emitBridgeEvent("tool:result", {
1413
+ content: params.content,
1414
+ structuredContent: params.structuredContent
1415
+ });
1416
+ }
1417
+ /**
1418
+ * Handle host context change notification.
1419
+ */
1420
+ _handleHostContextChange(params) {
1421
+ const changes = {};
1422
+ if (params.theme !== void 0) {
1423
+ changes.theme = params.theme;
1424
+ }
1425
+ if (params.displayMode !== void 0) {
1426
+ changes.displayMode = params.displayMode;
1427
+ }
1428
+ if (params.viewport !== void 0) {
1429
+ changes.viewport = params.viewport;
1430
+ }
1431
+ if (params.locale !== void 0) {
1432
+ changes.locale = params.locale;
1433
+ }
1434
+ if (params.timezone !== void 0) {
1435
+ changes.timezone = params.timezone;
1436
+ }
1437
+ this._notifyContextChange(changes);
1438
+ }
1439
+ /**
1440
+ * Handle cancellation notification.
1441
+ */
1442
+ _handleCancelled(params) {
1443
+ const reason = params?.reason;
1444
+ this._emitBridgeEvent("tool:cancelled", { reason });
1445
+ }
1446
+ // ============================================
1447
+ // Private: JSON-RPC Transport
1448
+ // ============================================
1449
+ /**
1450
+ * Send a JSON-RPC request to the host.
1451
+ */
1452
+ _sendRequest(method, params) {
1453
+ return new Promise((resolve, reject) => {
1454
+ const id = ++this._requestId;
1455
+ const timeout = this._config.options?.initTimeout || 1e4;
1456
+ const request = {
1457
+ jsonrpc: "2.0",
1458
+ id,
1459
+ method,
1460
+ params
1461
+ };
1462
+ const timeoutHandle = setTimeout(() => {
1463
+ this._pendingRequests.delete(id);
1464
+ reject(new Error(`Request ${method} timed out after ${timeout}ms`));
1465
+ }, timeout);
1466
+ this._pendingRequests.set(id, {
1467
+ resolve,
1468
+ reject,
1469
+ timeout: timeoutHandle
1470
+ });
1471
+ this._postMessage(request);
1472
+ });
1473
+ }
1474
+ /**
1475
+ * Send a JSON-RPC notification (no response expected).
1476
+ */
1477
+ _sendNotification(method, params) {
1478
+ const notification = {
1479
+ jsonrpc: "2.0",
1480
+ method,
1481
+ params
1482
+ };
1483
+ this._postMessage(notification);
1484
+ }
1485
+ /**
1486
+ * Post a message to the parent window.
1487
+ */
1488
+ _postMessage(message) {
1489
+ if (typeof window === "undefined") return;
1490
+ const targetOrigin = this._trustedOrigin || "*";
1491
+ window.parent.postMessage(message, targetOrigin);
1492
+ }
1493
+ // ============================================
1494
+ // Private: Handshake
1495
+ // ============================================
1496
+ /**
1497
+ * Perform the ui/initialize handshake with the host.
1498
+ */
1499
+ async _performHandshake() {
1500
+ const params = {
1501
+ appInfo: {
1502
+ name: this._config.options?.appName || "FrontMCP Widget",
1503
+ version: this._config.options?.appVersion || "1.0.0"
1504
+ },
1505
+ appCapabilities: {
1506
+ tools: {
1507
+ listChanged: false
1508
+ }
1509
+ },
1510
+ protocolVersion: this._config.options?.protocolVersion || "2024-11-05"
1511
+ };
1512
+ try {
1513
+ const result = await this._sendRequest("ui/initialize", params);
1514
+ this._hostCapabilities = result.hostCapabilities || {};
1515
+ this._capabilities = {
1516
+ ...this._capabilities,
1517
+ canCallTools: Boolean(this._hostCapabilities.serverToolProxy),
1518
+ canSendMessages: true,
1519
+ canOpenLinks: Boolean(this._hostCapabilities.openLink),
1520
+ supportsDisplayModes: true
1521
+ };
1522
+ if (result.hostContext) {
1523
+ this._hostContext = {
1524
+ ...this._hostContext,
1525
+ ...result.hostContext
1526
+ };
1527
+ }
1528
+ if (!this._config.options?.trustedOrigins?.length) {
1529
+ }
1530
+ } catch (error) {
1531
+ throw new Error(`ext-apps handshake failed: ${error}`);
1532
+ }
1533
+ }
1534
+ // ============================================
1535
+ // Private: Origin Security
1536
+ // ============================================
1537
+ /**
1538
+ * Check if an origin is trusted.
1539
+ * Uses trust-on-first-use if no explicit origins configured.
1540
+ */
1541
+ _isOriginTrusted(origin) {
1542
+ const trustedOrigins = this._config.options?.trustedOrigins;
1543
+ if (trustedOrigins && trustedOrigins.length > 0) {
1544
+ return trustedOrigins.includes(origin);
1545
+ }
1546
+ if (!this._trustedOrigin) {
1547
+ this._trustedOrigin = origin;
1548
+ return true;
1549
+ }
1550
+ return this._trustedOrigin === origin;
1551
+ }
1552
+ // ============================================
1553
+ // Private: Events
1554
+ // ============================================
1555
+ /**
1556
+ * Emit a bridge event via CustomEvent.
1557
+ */
1558
+ _emitBridgeEvent(type, detail) {
1559
+ if (typeof window !== "undefined" && typeof CustomEvent !== "undefined") {
1560
+ try {
1561
+ const event = new CustomEvent(type, { detail });
1562
+ window.dispatchEvent(event);
1563
+ } catch {
1564
+ }
1565
+ }
1566
+ }
1567
+ };
1568
+ function createExtAppsAdapter(config) {
1569
+ return new ExtAppsAdapter(config);
1570
+ }
1571
+
1572
+ // libs/ui/src/bridge/adapters/claude.adapter.ts
1573
+ var ClaudeAdapter = class extends BaseAdapter {
1574
+ id = "claude";
1575
+ name = "Claude (Anthropic)";
1576
+ priority = 60;
1577
+ constructor() {
1578
+ super();
1579
+ this._capabilities = {
1580
+ ...DEFAULT_CAPABILITIES,
1581
+ canCallTools: false,
1582
+ // Claude artifacts can't call tools
1583
+ canSendMessages: false,
1584
+ // Can't send messages back to conversation
1585
+ canOpenLinks: true,
1586
+ // Can open links via window.open
1587
+ canPersistState: true,
1588
+ // localStorage works
1589
+ hasNetworkAccess: false,
1590
+ // Network is blocked
1591
+ supportsDisplayModes: false,
1592
+ // No display mode control
1593
+ supportsTheme: true
1594
+ // Can detect system theme
1595
+ };
1596
+ }
1597
+ /**
1598
+ * Check if we're running in a Claude artifact/widget context.
1599
+ */
1600
+ canHandle() {
1601
+ if (typeof window === "undefined") return false;
1602
+ const win = window;
1603
+ if (win.__mcpPlatform === "claude") return true;
1604
+ if (win.claude) return true;
1605
+ if (win.__claudeArtifact) return true;
1606
+ if (typeof location !== "undefined") {
1607
+ const href = location.href;
1608
+ if (href.includes("claude.ai") || href.includes("anthropic.com")) {
1609
+ return true;
1610
+ }
1611
+ }
1612
+ return false;
1613
+ }
1614
+ /**
1615
+ * Initialize the Claude adapter.
1616
+ */
1617
+ async initialize() {
1618
+ if (this._initialized) return;
1619
+ await super.initialize();
1620
+ this._setupThemeListener();
1621
+ }
1622
+ /**
1623
+ * Open a link in a new tab.
1624
+ * This is one of the few actions available in Claude artifacts.
1625
+ */
1626
+ async openLink(url) {
1627
+ if (typeof window !== "undefined") {
1628
+ window.open(url, "_blank", "noopener,noreferrer");
1629
+ }
1630
+ }
1631
+ /**
1632
+ * Request display mode change (no-op for Claude).
1633
+ */
1634
+ async requestDisplayMode(_mode) {
1635
+ }
1636
+ /**
1637
+ * Request close (no-op for Claude).
1638
+ */
1639
+ async requestClose() {
1640
+ }
1641
+ // ============================================
1642
+ // Private Helpers
1643
+ // ============================================
1644
+ /**
1645
+ * Setup listener for system theme changes.
1646
+ */
1647
+ _setupThemeListener() {
1648
+ if (typeof window === "undefined" || !window.matchMedia) return;
1649
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
1650
+ const handleChange = (e) => {
1651
+ const newTheme = e.matches ? "dark" : "light";
1652
+ if (newTheme !== this._hostContext.theme) {
1653
+ this._notifyContextChange({ theme: newTheme });
1654
+ }
1655
+ };
1656
+ if (mediaQuery.addEventListener) {
1657
+ mediaQuery.addEventListener("change", handleChange);
1658
+ } else if (mediaQuery.addListener) {
1659
+ mediaQuery.addListener(handleChange);
1660
+ }
1661
+ }
1662
+ };
1663
+ function createClaudeAdapter() {
1664
+ return new ClaudeAdapter();
1665
+ }
1666
+
1667
+ // libs/ui/src/bridge/adapters/gemini.adapter.ts
1668
+ var GeminiAdapter = class extends BaseAdapter {
1669
+ id = "gemini";
1670
+ name = "Google Gemini";
1671
+ priority = 40;
1672
+ _gemini;
1673
+ constructor() {
1674
+ super();
1675
+ this._capabilities = {
1676
+ ...DEFAULT_CAPABILITIES,
1677
+ canCallTools: false,
1678
+ // May be enabled if SDK supports it
1679
+ canSendMessages: false,
1680
+ // May be enabled if SDK supports it
1681
+ canOpenLinks: true,
1682
+ canPersistState: true,
1683
+ hasNetworkAccess: true,
1684
+ supportsDisplayModes: false,
1685
+ supportsTheme: true
1686
+ };
1687
+ }
1688
+ /**
1689
+ * Check if we're running in a Gemini context.
1690
+ */
1691
+ canHandle() {
1692
+ if (typeof window === "undefined") return false;
1693
+ const win = window;
1694
+ if (win.__mcpPlatform === "gemini") return true;
1695
+ if (win.gemini) return true;
1696
+ if (typeof location !== "undefined") {
1697
+ const href = location.href;
1698
+ if (href.includes("gemini.google.com") || href.includes("bard.google.com")) {
1699
+ return true;
1700
+ }
1701
+ }
1702
+ return false;
1703
+ }
1704
+ /**
1705
+ * Initialize the Gemini adapter.
1706
+ */
1707
+ async initialize() {
1708
+ if (this._initialized) return;
1709
+ const win = window;
1710
+ this._gemini = win.gemini;
1711
+ if (this._gemini?.ui) {
1712
+ if (this._gemini.ui.sendMessage) {
1713
+ this._capabilities = { ...this._capabilities, canSendMessages: true };
1714
+ }
1715
+ }
1716
+ await super.initialize();
1717
+ this._setupThemeListener();
1718
+ }
1719
+ /**
1720
+ * Get current theme.
1721
+ */
1722
+ getTheme() {
1723
+ if (this._gemini?.ui?.getTheme) {
1724
+ const theme = this._gemini.ui.getTheme();
1725
+ return theme === "dark" ? "dark" : "light";
1726
+ }
1727
+ return super.getTheme();
1728
+ }
1729
+ /**
1730
+ * Send a message (if supported by SDK).
1731
+ */
1732
+ async sendMessage(content) {
1733
+ if (this._gemini?.ui?.sendMessage) {
1734
+ await this._gemini.ui.sendMessage(content);
1735
+ return;
1736
+ }
1737
+ throw new Error("Sending messages is not supported by Gemini adapter");
1738
+ }
1739
+ /**
1740
+ * Open a link.
1741
+ */
1742
+ async openLink(url) {
1743
+ if (this._gemini?.ui?.openLink) {
1744
+ await this._gemini.ui.openLink(url);
1745
+ return;
1746
+ }
1747
+ return super.openLink(url);
1748
+ }
1749
+ // ============================================
1750
+ // Private Helpers
1751
+ // ============================================
1752
+ /**
1753
+ * Setup listener for system theme changes.
1754
+ */
1755
+ _setupThemeListener() {
1756
+ if (typeof window === "undefined" || !window.matchMedia) return;
1757
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
1758
+ const handleChange = (e) => {
1759
+ if (!this._gemini?.ui?.getTheme) {
1760
+ const newTheme = e.matches ? "dark" : "light";
1761
+ if (newTheme !== this._hostContext.theme) {
1762
+ this._notifyContextChange({ theme: newTheme });
1763
+ }
1764
+ }
1765
+ };
1766
+ if (mediaQuery.addEventListener) {
1767
+ mediaQuery.addEventListener("change", handleChange);
1768
+ } else if (mediaQuery.addListener) {
1769
+ mediaQuery.addListener(handleChange);
1770
+ }
1771
+ }
1772
+ };
1773
+ function createGeminiAdapter() {
1774
+ return new GeminiAdapter();
1775
+ }
1776
+
1777
+ // libs/ui/src/bridge/adapters/generic.adapter.ts
1778
+ var GenericAdapter = class extends BaseAdapter {
1779
+ id = "generic";
1780
+ name = "Generic Web";
1781
+ priority = 0;
1782
+ // Lowest priority - fallback only
1783
+ constructor() {
1784
+ super();
1785
+ this._capabilities = {
1786
+ ...DEFAULT_CAPABILITIES,
1787
+ canCallTools: false,
1788
+ canSendMessages: false,
1789
+ canOpenLinks: true,
1790
+ // window.open works
1791
+ canPersistState: true,
1792
+ // localStorage works
1793
+ hasNetworkAccess: true,
1794
+ // Assume network available
1795
+ supportsDisplayModes: false,
1796
+ supportsTheme: true
1797
+ // System theme detection
1798
+ };
1799
+ }
1800
+ /**
1801
+ * Generic adapter can always handle the environment.
1802
+ * It serves as the fallback when no other adapter matches.
1803
+ */
1804
+ canHandle() {
1805
+ return typeof window !== "undefined";
1806
+ }
1807
+ /**
1808
+ * Initialize the generic adapter.
1809
+ */
1810
+ async initialize() {
1811
+ if (this._initialized) return;
1812
+ await super.initialize();
1813
+ this._setupThemeListener();
1814
+ }
1815
+ /**
1816
+ * Open a link using window.open.
1817
+ */
1818
+ async openLink(url) {
1819
+ if (typeof window !== "undefined") {
1820
+ window.open(url, "_blank", "noopener,noreferrer");
1821
+ }
1822
+ }
1823
+ // ============================================
1824
+ // Private Helpers
1825
+ // ============================================
1826
+ /**
1827
+ * Setup listener for system theme changes.
1828
+ */
1829
+ _setupThemeListener() {
1830
+ if (typeof window === "undefined" || !window.matchMedia) return;
1831
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
1832
+ const handleChange = (e) => {
1833
+ const newTheme = e.matches ? "dark" : "light";
1834
+ if (newTheme !== this._hostContext.theme) {
1835
+ this._notifyContextChange({ theme: newTheme });
1836
+ }
1837
+ };
1838
+ if (mediaQuery.addEventListener) {
1839
+ mediaQuery.addEventListener("change", handleChange);
1840
+ } else if (mediaQuery.addListener) {
1841
+ mediaQuery.addListener(handleChange);
1842
+ }
1843
+ }
1844
+ };
1845
+ function createGenericAdapter() {
1846
+ return new GenericAdapter();
1847
+ }
1848
+
1849
+ // libs/ui/src/bridge/adapters/index.ts
1850
+ function registerBuiltInAdapters() {
1851
+ defaultRegistry.register("openai", createOpenAIAdapter);
1852
+ defaultRegistry.register("ext-apps", createExtAppsAdapter);
1853
+ defaultRegistry.register("claude", createClaudeAdapter);
1854
+ defaultRegistry.register("gemini", createGeminiAdapter);
1855
+ defaultRegistry.register("generic", createGenericAdapter);
1856
+ }
1857
+ registerBuiltInAdapters();
1858
+
1859
+ // libs/ui/src/bridge/runtime/iife-generator.ts
1860
+ function generateBridgeIIFE(options = {}) {
1861
+ const { debug = false, trustedOrigins = [], minify = false } = options;
1862
+ const adapters = options.adapters || ["openai", "ext-apps", "claude", "gemini", "generic"];
1863
+ const parts = [];
1864
+ parts.push("(function() {");
1865
+ parts.push('"use strict";');
1866
+ parts.push("");
1867
+ if (debug) {
1868
+ parts.push('function log(msg) { console.log("[FrontMcpBridge] " + msg); }');
1869
+ } else {
1870
+ parts.push("function log() {}");
1871
+ }
1872
+ parts.push("");
1873
+ parts.push("var DEFAULT_SAFE_AREA = { top: 0, bottom: 0, left: 0, right: 0 };");
1874
+ parts.push("");
1875
+ parts.push(generateContextDetection());
1876
+ parts.push("");
1877
+ parts.push(generateBaseCapabilities());
1878
+ parts.push("");
1879
+ if (adapters.includes("openai")) {
1880
+ parts.push(generateOpenAIAdapter());
1881
+ parts.push("");
1882
+ }
1883
+ if (adapters.includes("ext-apps")) {
1884
+ parts.push(generateExtAppsAdapter(trustedOrigins));
1885
+ parts.push("");
1886
+ }
1887
+ if (adapters.includes("claude")) {
1888
+ parts.push(generateClaudeAdapter());
1889
+ parts.push("");
1890
+ }
1891
+ if (adapters.includes("gemini")) {
1892
+ parts.push(generateGeminiAdapter());
1893
+ parts.push("");
1894
+ }
1895
+ if (adapters.includes("generic")) {
1896
+ parts.push(generateGenericAdapter());
1897
+ parts.push("");
1898
+ }
1899
+ parts.push(generatePlatformDetection(adapters));
1900
+ parts.push("");
1901
+ parts.push(generateBridgeClass());
1902
+ parts.push("");
1903
+ parts.push("var bridge = new FrontMcpBridge();");
1904
+ parts.push("bridge.initialize().then(function() {");
1905
+ parts.push(' log("Bridge initialized with adapter: " + bridge.adapterId);');
1906
+ parts.push(' window.dispatchEvent(new CustomEvent("bridge:ready", { detail: { adapter: bridge.adapterId } }));');
1907
+ parts.push("}).catch(function(err) {");
1908
+ parts.push(' console.error("[FrontMcpBridge] Init failed:", err);');
1909
+ parts.push(' window.dispatchEvent(new CustomEvent("bridge:error", { detail: { error: err } }));');
1910
+ parts.push("});");
1911
+ parts.push("");
1912
+ parts.push("window.FrontMcpBridge = bridge;");
1913
+ parts.push("})();");
1914
+ const code = parts.join("\n");
1915
+ if (minify) {
1916
+ return minifyJS(code);
1917
+ }
1918
+ return code;
1919
+ }
1920
+ function generateContextDetection() {
1921
+ return `
1922
+ function detectTheme() {
1923
+ if (typeof window !== 'undefined' && window.matchMedia) {
1924
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
1925
+ }
1926
+ return 'light';
1927
+ }
1928
+
1929
+ function detectLocale() {
1930
+ if (typeof navigator !== 'undefined') {
1931
+ return navigator.language || 'en-US';
1932
+ }
1933
+ return 'en-US';
1934
+ }
1935
+
1936
+ function detectUserAgent() {
1937
+ if (typeof navigator === 'undefined') {
1938
+ return { type: 'web', hover: true, touch: false };
1939
+ }
1940
+ var ua = navigator.userAgent || '';
1941
+ var isMobile = /iPhone|iPad|iPod|Android/i.test(ua);
1942
+ var hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
1943
+ var hasHover = window.matchMedia && window.matchMedia('(hover: hover)').matches;
1944
+ return { type: isMobile ? 'mobile' : 'web', hover: hasHover !== false, touch: hasTouch };
1945
+ }
1946
+
1947
+ function detectViewport() {
1948
+ if (typeof window !== 'undefined') {
1949
+ return { width: window.innerWidth, height: window.innerHeight };
1950
+ }
1951
+ return undefined;
1952
+ }
1953
+
1954
+ function readInjectedData() {
1955
+ var data = { toolInput: {}, toolOutput: undefined, structuredContent: undefined };
1956
+ if (typeof window !== 'undefined') {
1957
+ if (window.__mcpToolInput) data.toolInput = window.__mcpToolInput;
1958
+ if (window.__mcpToolOutput) data.toolOutput = window.__mcpToolOutput;
1959
+ if (window.__mcpStructuredContent) data.structuredContent = window.__mcpStructuredContent;
1960
+ }
1961
+ return data;
1962
+ }
1963
+ `.trim();
1964
+ }
1965
+ function generateBaseCapabilities() {
1966
+ return `
1967
+ var DEFAULT_CAPABILITIES = {
1968
+ canCallTools: false,
1969
+ canSendMessages: false,
1970
+ canOpenLinks: false,
1971
+ canPersistState: true,
1972
+ hasNetworkAccess: true,
1973
+ supportsDisplayModes: false,
1974
+ supportsTheme: true
1975
+ };
1976
+ `.trim();
1977
+ }
1978
+ function generateOpenAIAdapter() {
1979
+ return `
1980
+ var OpenAIAdapter = {
1981
+ id: 'openai',
1982
+ name: 'OpenAI ChatGPT',
1983
+ priority: 100,
1984
+ capabilities: Object.assign({}, DEFAULT_CAPABILITIES, {
1985
+ canCallTools: true,
1986
+ canSendMessages: true,
1987
+ canOpenLinks: true,
1988
+ supportsDisplayModes: true
1989
+ }),
1990
+ canHandle: function() {
1991
+ if (typeof window === 'undefined') return false;
1992
+ // Check for window.openai.callTool (the actual OpenAI SDK API)
1993
+ if (window.openai && typeof window.openai.callTool === 'function') return true;
1994
+ // Also check if we're being injected with tool metadata (OpenAI injects toolOutput)
1995
+ if (window.openai && (window.openai.toolOutput !== undefined || window.openai.toolInput !== undefined)) return true;
1996
+ return false;
1997
+ },
1998
+ initialize: function(context) {
1999
+ var sdk = window.openai;
2000
+ context.sdk = sdk;
2001
+ // OpenAI SDK exposes theme and displayMode directly as properties
2002
+ if (sdk.theme) {
2003
+ context.hostContext.theme = sdk.theme;
2004
+ }
2005
+ if (sdk.displayMode) {
2006
+ context.hostContext.displayMode = sdk.displayMode;
2007
+ }
2008
+ // Note: OpenAI SDK does not have an onContextChange equivalent
2009
+ return Promise.resolve();
2010
+ },
2011
+ callTool: function(context, name, args) {
2012
+ return context.sdk.callTool(name, args);
2013
+ },
2014
+ sendMessage: function(context, content) {
2015
+ if (typeof context.sdk.sendFollowUpMessage === 'function') {
2016
+ return context.sdk.sendFollowUpMessage(content);
2017
+ }
2018
+ return Promise.reject(new Error('Messages not supported'));
2019
+ },
2020
+ openLink: function(context, url) {
2021
+ window.open(url, '_blank', 'noopener,noreferrer');
2022
+ return Promise.resolve();
2023
+ },
2024
+ requestDisplayMode: function(context, mode) {
2025
+ return Promise.resolve();
2026
+ },
2027
+ requestClose: function(context) {
2028
+ return Promise.resolve();
2029
+ }
2030
+ };
2031
+ `.trim();
2032
+ }
2033
+ function generateExtAppsAdapter(trustedOrigins) {
2034
+ const originsArray = trustedOrigins.length > 0 ? JSON.stringify(trustedOrigins) : "[]";
2035
+ return `
2036
+ var ExtAppsAdapter = {
2037
+ id: 'ext-apps',
2038
+ name: 'ext-apps (SEP-1865)',
2039
+ priority: 80,
2040
+ capabilities: Object.assign({}, DEFAULT_CAPABILITIES, { canPersistState: true, hasNetworkAccess: true }),
2041
+ trustedOrigins: ${originsArray},
2042
+ trustedOrigin: null,
2043
+ pendingRequests: {},
2044
+ requestId: 0,
2045
+ hostCapabilities: {},
2046
+ canHandle: function() {
2047
+ if (typeof window === 'undefined') return false;
2048
+ if (window.parent === window) return false;
2049
+ // Check for OpenAI SDK (window.openai.callTool) - defer to OpenAIAdapter
2050
+ if (window.openai && typeof window.openai.callTool === 'function') return false;
2051
+ if (window.__mcpPlatform === 'ext-apps') return true;
2052
+ return true;
2053
+ },
2054
+ initialize: function(context) {
2055
+ var self = this;
2056
+ context.extApps = this;
2057
+
2058
+ window.addEventListener('message', function(event) {
2059
+ self.handleMessage(context, event);
2060
+ });
2061
+
2062
+ return self.performHandshake(context);
2063
+ },
2064
+ handleMessage: function(context, event) {
2065
+ if (!this.isOriginTrusted(event.origin)) return;
2066
+ var data = event.data;
2067
+ if (!data || typeof data !== 'object' || data.jsonrpc !== '2.0') return;
2068
+
2069
+ if ('id' in data && (data.result !== undefined || data.error !== undefined)) {
2070
+ var pending = this.pendingRequests[data.id];
2071
+ if (pending) {
2072
+ clearTimeout(pending.timeout);
2073
+ delete this.pendingRequests[data.id];
2074
+ if (data.error) {
2075
+ pending.reject(new Error(data.error.message + ' (code: ' + data.error.code + ')'));
2076
+ } else {
2077
+ pending.resolve(data.result);
2078
+ }
2079
+ }
2080
+ return;
2081
+ }
2082
+
2083
+ if ('method' in data && !('id' in data)) {
2084
+ this.handleNotification(context, data);
2085
+ }
2086
+ },
2087
+ handleNotification: function(context, notification) {
2088
+ var params = notification.params || {};
2089
+ switch (notification.method) {
2090
+ case 'ui/notifications/tool-input':
2091
+ context.toolInput = params.arguments || {};
2092
+ window.dispatchEvent(new CustomEvent('tool:input', { detail: { arguments: context.toolInput } }));
2093
+ break;
2094
+ case 'ui/notifications/tool-result':
2095
+ context.toolOutput = params.content;
2096
+ context.structuredContent = params.structuredContent;
2097
+ context.notifyToolResult(params.content);
2098
+ window.dispatchEvent(new CustomEvent('tool:result', { detail: params }));
2099
+ break;
2100
+ case 'ui/notifications/host-context-changed':
2101
+ Object.assign(context.hostContext, params);
2102
+ context.notifyContextChange(params);
2103
+ break;
2104
+ }
2105
+ },
2106
+ isOriginTrusted: function(origin) {
2107
+ if (this.trustedOrigins.length > 0) {
2108
+ return this.trustedOrigins.indexOf(origin) !== -1;
2109
+ }
2110
+ // When no trusted origins configured, only trust first message in iframe context
2111
+ // This helps mitigate race conditions where a malicious iframe could establish trust
2112
+ if (!this.trustedOrigin) {
2113
+ if (window.parent !== window && origin) {
2114
+ this.trustedOrigin = origin;
2115
+ return true;
2116
+ }
2117
+ return false;
2118
+ }
2119
+ return this.trustedOrigin === origin;
2120
+ },
2121
+ sendRequest: function(method, params) {
2122
+ var self = this;
2123
+ return new Promise(function(resolve, reject) {
2124
+ // Security: Require trusted origin before sending requests to prevent message leaks
2125
+ if (!self.trustedOrigin && self.trustedOrigins.length === 0) {
2126
+ reject(new Error('Cannot send request: no trusted origin established'));
2127
+ return;
2128
+ }
2129
+
2130
+ var id = ++self.requestId;
2131
+ var timeout = setTimeout(function() {
2132
+ delete self.pendingRequests[id];
2133
+ reject(new Error('Request ' + method + ' timed out'));
2134
+ }, 10000);
2135
+
2136
+ self.pendingRequests[id] = { resolve: resolve, reject: reject, timeout: timeout };
2137
+
2138
+ var targetOrigin = self.trustedOrigin || self.trustedOrigins[0];
2139
+ window.parent.postMessage({ jsonrpc: '2.0', id: id, method: method, params: params }, targetOrigin);
2140
+ });
2141
+ },
2142
+ performHandshake: function(context) {
2143
+ var self = this;
2144
+ var params = {
2145
+ appInfo: { name: 'FrontMCP Widget', version: '1.0.0' },
2146
+ appCapabilities: { tools: { listChanged: false } },
2147
+ protocolVersion: '2024-11-05'
2148
+ };
2149
+
2150
+ return this.sendRequest('ui/initialize', params).then(function(result) {
2151
+ self.hostCapabilities = result.hostCapabilities || {};
2152
+ self.capabilities = Object.assign({}, self.capabilities, {
2153
+ canCallTools: Boolean(self.hostCapabilities.serverToolProxy),
2154
+ canSendMessages: true,
2155
+ canOpenLinks: Boolean(self.hostCapabilities.openLink),
2156
+ supportsDisplayModes: true
2157
+ });
2158
+ if (result.hostContext) {
2159
+ Object.assign(context.hostContext, result.hostContext);
2160
+ }
2161
+ });
2162
+ },
2163
+ callTool: function(context, name, args) {
2164
+ if (!this.hostCapabilities.serverToolProxy) {
2165
+ return Promise.reject(new Error('Server tool proxy not supported'));
2166
+ }
2167
+ return this.sendRequest('ui/callServerTool', { name: name, arguments: args });
2168
+ },
2169
+ sendMessage: function(context, content) {
2170
+ return this.sendRequest('ui/message', { content: content });
2171
+ },
2172
+ openLink: function(context, url) {
2173
+ if (!this.hostCapabilities.openLink) {
2174
+ window.open(url, '_blank', 'noopener,noreferrer');
2175
+ return Promise.resolve();
2176
+ }
2177
+ return this.sendRequest('ui/openLink', { url: url });
2178
+ },
2179
+ requestDisplayMode: function(context, mode) {
2180
+ return this.sendRequest('ui/setDisplayMode', { mode: mode });
2181
+ },
2182
+ requestClose: function(context) {
2183
+ return this.sendRequest('ui/close', {});
2184
+ }
2185
+ };
2186
+ `.trim();
2187
+ }
2188
+ function generateClaudeAdapter() {
2189
+ return `
2190
+ var ClaudeAdapter = {
2191
+ id: 'claude',
2192
+ name: 'Claude (Anthropic)',
2193
+ priority: 60,
2194
+ capabilities: Object.assign({}, DEFAULT_CAPABILITIES, {
2195
+ canCallTools: false,
2196
+ canSendMessages: false,
2197
+ canOpenLinks: true,
2198
+ hasNetworkAccess: false,
2199
+ supportsDisplayModes: false
2200
+ }),
2201
+ canHandle: function() {
2202
+ if (typeof window === 'undefined') return false;
2203
+ if (window.__mcpPlatform === 'claude') return true;
2204
+ if (window.claude) return true;
2205
+ if (window.__claudeArtifact) return true;
2206
+ if (typeof location !== 'undefined') {
2207
+ var href = location.href;
2208
+ if (href.indexOf('claude.ai') !== -1 || href.indexOf('anthropic.com') !== -1) return true;
2209
+ }
2210
+ return false;
2211
+ },
2212
+ initialize: function(context) {
2213
+ return Promise.resolve();
2214
+ },
2215
+ callTool: function() {
2216
+ return Promise.reject(new Error('Tool calls not supported in Claude'));
2217
+ },
2218
+ sendMessage: function() {
2219
+ return Promise.reject(new Error('Messages not supported in Claude'));
2220
+ },
2221
+ openLink: function(context, url) {
2222
+ window.open(url, '_blank', 'noopener,noreferrer');
2223
+ return Promise.resolve();
2224
+ },
2225
+ requestDisplayMode: function() {
2226
+ return Promise.resolve();
2227
+ },
2228
+ requestClose: function() {
2229
+ return Promise.resolve();
2230
+ }
2231
+ };
2232
+ `.trim();
2233
+ }
2234
+ function generateGeminiAdapter() {
2235
+ return `
2236
+ var GeminiAdapter = {
2237
+ id: 'gemini',
2238
+ name: 'Google Gemini',
2239
+ priority: 40,
2240
+ capabilities: Object.assign({}, DEFAULT_CAPABILITIES, {
2241
+ canOpenLinks: true,
2242
+ hasNetworkAccess: true
2243
+ }),
2244
+ canHandle: function() {
2245
+ if (typeof window === 'undefined') return false;
2246
+ if (window.__mcpPlatform === 'gemini') return true;
2247
+ if (window.gemini) return true;
2248
+ if (typeof location !== 'undefined') {
2249
+ var href = location.href;
2250
+ if (href.indexOf('gemini.google.com') !== -1 || href.indexOf('bard.google.com') !== -1) return true;
2251
+ }
2252
+ return false;
2253
+ },
2254
+ initialize: function(context) {
2255
+ if (window.gemini && window.gemini.ui && window.gemini.ui.getTheme) {
2256
+ context.hostContext.theme = window.gemini.ui.getTheme() === 'dark' ? 'dark' : 'light';
2257
+ }
2258
+ return Promise.resolve();
2259
+ },
2260
+ callTool: function() {
2261
+ return Promise.reject(new Error('Tool calls not supported in Gemini'));
2262
+ },
2263
+ sendMessage: function(context, content) {
2264
+ if (window.gemini && window.gemini.ui && window.gemini.ui.sendMessage) {
2265
+ return window.gemini.ui.sendMessage(content);
2266
+ }
2267
+ return Promise.reject(new Error('Messages not supported in Gemini'));
2268
+ },
2269
+ openLink: function(context, url) {
2270
+ if (window.gemini && window.gemini.ui && window.gemini.ui.openLink) {
2271
+ return window.gemini.ui.openLink(url);
2272
+ }
2273
+ window.open(url, '_blank', 'noopener,noreferrer');
2274
+ return Promise.resolve();
2275
+ },
2276
+ requestDisplayMode: function() {
2277
+ return Promise.resolve();
2278
+ },
2279
+ requestClose: function() {
2280
+ return Promise.resolve();
2281
+ }
2282
+ };
2283
+ `.trim();
2284
+ }
2285
+ function generateGenericAdapter() {
2286
+ return `
2287
+ var GenericAdapter = {
2288
+ id: 'generic',
2289
+ name: 'Generic Web',
2290
+ priority: 0,
2291
+ capabilities: Object.assign({}, DEFAULT_CAPABILITIES, {
2292
+ canOpenLinks: true,
2293
+ hasNetworkAccess: true
2294
+ }),
2295
+ canHandle: function() {
2296
+ return typeof window !== 'undefined';
2297
+ },
2298
+ initialize: function(context) {
2299
+ return Promise.resolve();
2300
+ },
2301
+ callTool: function() {
2302
+ return Promise.reject(new Error('Tool calls not supported'));
2303
+ },
2304
+ sendMessage: function() {
2305
+ return Promise.reject(new Error('Messages not supported'));
2306
+ },
2307
+ openLink: function(context, url) {
2308
+ window.open(url, '_blank', 'noopener,noreferrer');
2309
+ return Promise.resolve();
2310
+ },
2311
+ requestDisplayMode: function() {
2312
+ return Promise.resolve();
2313
+ },
2314
+ requestClose: function() {
2315
+ return Promise.resolve();
2316
+ }
2317
+ };
2318
+ `.trim();
2319
+ }
2320
+ function generatePlatformDetection(adapters) {
2321
+ const adapterVars = adapters.map((a) => {
2322
+ switch (a) {
2323
+ case "openai":
2324
+ return "OpenAIAdapter";
2325
+ case "ext-apps":
2326
+ return "ExtAppsAdapter";
2327
+ case "claude":
2328
+ return "ClaudeAdapter";
2329
+ case "gemini":
2330
+ return "GeminiAdapter";
2331
+ case "generic":
2332
+ return "GenericAdapter";
2333
+ default:
2334
+ return "";
2335
+ }
2336
+ }).filter(Boolean);
2337
+ return `
2338
+ var ADAPTERS = [${adapterVars.join(", ")}].sort(function(a, b) { return b.priority - a.priority; });
2339
+
2340
+ function detectPlatform() {
2341
+ for (var i = 0; i < ADAPTERS.length; i++) {
2342
+ if (ADAPTERS[i].canHandle()) {
2343
+ log('Detected platform: ' + ADAPTERS[i].id);
2344
+ return ADAPTERS[i];
2345
+ }
2346
+ }
2347
+ log('No platform detected, using generic');
2348
+ return GenericAdapter;
2349
+ }
2350
+ `.trim();
2351
+ }
2352
+ function generateBridgeClass() {
2353
+ return `
2354
+ function FrontMcpBridge() {
2355
+ this._adapter = null;
2356
+ this._initialized = false;
2357
+ this._context = {
2358
+ hostContext: {
2359
+ theme: detectTheme(),
2360
+ displayMode: 'inline',
2361
+ locale: detectLocale(),
2362
+ userAgent: detectUserAgent(),
2363
+ safeArea: DEFAULT_SAFE_AREA,
2364
+ viewport: detectViewport()
2365
+ },
2366
+ toolInput: {},
2367
+ toolOutput: undefined,
2368
+ structuredContent: undefined,
2369
+ widgetState: {},
2370
+ contextListeners: [],
2371
+ toolResultListeners: [],
2372
+ notifyContextChange: function(changes) {
2373
+ Object.assign(this.hostContext, changes);
2374
+ for (var i = 0; i < this.contextListeners.length; i++) {
2375
+ try { this.contextListeners[i](changes); } catch(e) {}
2376
+ }
2377
+ },
2378
+ notifyToolResult: function(result) {
2379
+ this.toolOutput = result;
2380
+ for (var i = 0; i < this.toolResultListeners.length; i++) {
2381
+ try { this.toolResultListeners[i](result); } catch(e) {}
2382
+ }
2383
+ }
2384
+ };
2385
+
2386
+ var injected = readInjectedData();
2387
+ this._context.toolInput = injected.toolInput;
2388
+ this._context.toolOutput = injected.toolOutput;
2389
+ this._context.structuredContent = injected.structuredContent;
2390
+
2391
+ this._loadWidgetState();
2392
+ }
2393
+
2394
+ FrontMcpBridge.prototype._loadWidgetState = function() {
2395
+ try {
2396
+ var key = 'frontmcp:widget:' + (window.__mcpToolName || 'unknown');
2397
+ var stored = localStorage.getItem(key);
2398
+ if (stored) this._context.widgetState = JSON.parse(stored);
2399
+ } catch(e) {}
2400
+ };
2401
+
2402
+ FrontMcpBridge.prototype._saveWidgetState = function() {
2403
+ try {
2404
+ var key = 'frontmcp:widget:' + (window.__mcpToolName || 'unknown');
2405
+ localStorage.setItem(key, JSON.stringify(this._context.widgetState));
2406
+ } catch(e) {}
2407
+ };
2408
+
2409
+ FrontMcpBridge.prototype.initialize = function() {
2410
+ if (this._initialized) return Promise.resolve();
2411
+ var self = this;
2412
+ this._adapter = detectPlatform();
2413
+ return this._adapter.initialize(this._context).then(function() {
2414
+ self._initialized = true;
2415
+ // Set up the data-tool-call click handler after initialization
2416
+ self._setupDataToolCallHandler();
2417
+ });
2418
+ };
2419
+
2420
+ Object.defineProperty(FrontMcpBridge.prototype, 'initialized', { get: function() { return this._initialized; } });
2421
+ Object.defineProperty(FrontMcpBridge.prototype, 'adapterId', { get: function() { return this._adapter ? this._adapter.id : undefined; } });
2422
+ Object.defineProperty(FrontMcpBridge.prototype, 'capabilities', { get: function() { return this._adapter ? this._adapter.capabilities : DEFAULT_CAPABILITIES; } });
2423
+
2424
+ FrontMcpBridge.prototype.getTheme = function() { return this._context.hostContext.theme; };
2425
+ FrontMcpBridge.prototype.getDisplayMode = function() { return this._context.hostContext.displayMode; };
2426
+ FrontMcpBridge.prototype.getToolInput = function() { return this._context.toolInput; };
2427
+ FrontMcpBridge.prototype.getToolOutput = function() { return this._context.toolOutput; };
2428
+ FrontMcpBridge.prototype.getStructuredContent = function() { return this._context.structuredContent; };
2429
+ FrontMcpBridge.prototype.getWidgetState = function() { return this._context.widgetState; };
2430
+ FrontMcpBridge.prototype.getHostContext = function() { return Object.assign({}, this._context.hostContext); };
2431
+ FrontMcpBridge.prototype.hasCapability = function(cap) { return this._adapter && this._adapter.capabilities[cap] === true; };
2432
+
2433
+ // Get tool response metadata (platform-agnostic)
2434
+ // Used by inline mode widgets to detect when ui/html arrives
2435
+ FrontMcpBridge.prototype.getToolResponseMetadata = function() {
2436
+ // OpenAI injects toolResponseMetadata for widget-producing tools
2437
+ if (typeof window !== 'undefined' && window.openai && window.openai.toolResponseMetadata) {
2438
+ return window.openai.toolResponseMetadata;
2439
+ }
2440
+ // Claude (future support)
2441
+ if (typeof window !== 'undefined' && window.claude && window.claude.toolResponseMetadata) {
2442
+ return window.claude.toolResponseMetadata;
2443
+ }
2444
+ // FrontMCP direct injection (for testing/ext-apps)
2445
+ if (typeof window !== 'undefined' && window.__mcpToolResponseMetadata) {
2446
+ return window.__mcpToolResponseMetadata;
2447
+ }
2448
+ return null;
2449
+ };
2450
+
2451
+ // Subscribe to tool response metadata changes (for inline mode injection)
2452
+ FrontMcpBridge.prototype.onToolResponseMetadata = function(callback) {
2453
+ var self = this;
2454
+ var called = false;
2455
+
2456
+ // Check if already available
2457
+ var existing = self.getToolResponseMetadata();
2458
+ if (existing) {
2459
+ called = true;
2460
+ callback(existing);
2461
+ }
2462
+
2463
+ // Set up property interceptors for OpenAI
2464
+ if (typeof window !== 'undefined') {
2465
+ // OpenAI: Intercept toolResponseMetadata assignment
2466
+ if (!window.__frontmcpMetadataIntercepted) {
2467
+ window.__frontmcpMetadataIntercepted = true;
2468
+ window.__frontmcpMetadataCallbacks = [];
2469
+
2470
+ // Create openai object if it doesn't exist
2471
+ if (!window.openai) window.openai = {};
2472
+
2473
+ var originalMetadata = window.openai.toolResponseMetadata;
2474
+ Object.defineProperty(window.openai, 'toolResponseMetadata', {
2475
+ get: function() { return originalMetadata; },
2476
+ set: function(val) {
2477
+ originalMetadata = val;
2478
+ log('toolResponseMetadata set, notifying ' + window.__frontmcpMetadataCallbacks.length + ' listeners');
2479
+ for (var i = 0; i < window.__frontmcpMetadataCallbacks.length; i++) {
2480
+ try { window.__frontmcpMetadataCallbacks[i](val); } catch(e) {}
2481
+ }
2482
+ },
2483
+ configurable: true
2484
+ });
2485
+ }
2486
+
2487
+ // Register callback wrapper (store reference for unsubscribe)
2488
+ var wrapper = function(metadata) {
2489
+ if (!called) {
2490
+ called = true;
2491
+ callback(metadata);
2492
+ }
2493
+ };
2494
+ window.__frontmcpMetadataCallbacks.push(wrapper);
2495
+
2496
+ // Return unsubscribe function that removes the wrapper (not the original callback)
2497
+ return function() {
2498
+ if (window.__frontmcpMetadataCallbacks) {
2499
+ var idx = window.__frontmcpMetadataCallbacks.indexOf(wrapper);
2500
+ if (idx !== -1) window.__frontmcpMetadataCallbacks.splice(idx, 1);
2501
+ }
2502
+ };
2503
+ }
2504
+
2505
+ // Return no-op unsubscribe for non-window environments
2506
+ return function() {};
2507
+ };
2508
+
2509
+ FrontMcpBridge.prototype.callTool = function(name, args) {
2510
+ // Priority 1: Direct OpenAI SDK call (most reliable in OpenAI iframe)
2511
+ // This bypasses adapter abstraction for maximum compatibility
2512
+ if (typeof window !== 'undefined' && window.openai && typeof window.openai.callTool === 'function') {
2513
+ log('callTool: Using OpenAI SDK directly');
2514
+ return window.openai.callTool(name, args);
2515
+ }
2516
+
2517
+ // Priority 2: Use adapter (if initialized and supports tool calls)
2518
+ if (this._adapter && this._adapter.capabilities && this._adapter.capabilities.canCallTools) {
2519
+ log('callTool: Using adapter ' + this._adapter.id);
2520
+ return this._adapter.callTool(this._context, name, args);
2521
+ }
2522
+
2523
+ // Not initialized or no tool support
2524
+ if (!this._adapter) {
2525
+ return Promise.reject(new Error('Bridge not initialized. Wait for bridge:ready event.'));
2526
+ }
2527
+ return Promise.reject(new Error('Tool calls not supported on this platform (' + this._adapter.id + ')'));
2528
+ };
2529
+
2530
+ FrontMcpBridge.prototype.sendMessage = function(content) {
2531
+ if (!this._adapter) return Promise.reject(new Error('Not initialized'));
2532
+ return this._adapter.sendMessage(this._context, content);
2533
+ };
2534
+
2535
+ FrontMcpBridge.prototype.openLink = function(url) {
2536
+ if (!this._adapter) return Promise.reject(new Error('Not initialized'));
2537
+ return this._adapter.openLink(this._context, url);
2538
+ };
2539
+
2540
+ FrontMcpBridge.prototype.requestDisplayMode = function(mode) {
2541
+ if (!this._adapter) return Promise.reject(new Error('Not initialized'));
2542
+ var self = this;
2543
+ return this._adapter.requestDisplayMode(this._context, mode).then(function() {
2544
+ self._context.hostContext.displayMode = mode;
2545
+ });
2546
+ };
2547
+
2548
+ FrontMcpBridge.prototype.requestClose = function() {
2549
+ if (!this._adapter) return Promise.reject(new Error('Not initialized'));
2550
+ return this._adapter.requestClose(this._context);
2551
+ };
2552
+
2553
+ FrontMcpBridge.prototype.setWidgetState = function(state) {
2554
+ Object.assign(this._context.widgetState, state);
2555
+ this._saveWidgetState();
2556
+ };
2557
+
2558
+ FrontMcpBridge.prototype.onContextChange = function(callback) {
2559
+ var listeners = this._context.contextListeners;
2560
+ listeners.push(callback);
2561
+ return function() {
2562
+ var idx = listeners.indexOf(callback);
2563
+ if (idx !== -1) listeners.splice(idx, 1);
2564
+ };
2565
+ };
2566
+
2567
+ FrontMcpBridge.prototype.onToolResult = function(callback) {
2568
+ var listeners = this._context.toolResultListeners;
2569
+ listeners.push(callback);
2570
+ return function() {
2571
+ var idx = listeners.indexOf(callback);
2572
+ if (idx !== -1) listeners.splice(idx, 1);
2573
+ };
2574
+ };
2575
+
2576
+ // ==================== data-tool-call Click Handler ====================
2577
+
2578
+ FrontMcpBridge.prototype._setupDataToolCallHandler = function() {
2579
+ var self = this;
2580
+
2581
+ document.addEventListener('click', function(e) {
2582
+ // Find the closest element with data-tool-call attribute
2583
+ var target = e.target;
2584
+ while (target && target !== document) {
2585
+ if (target.hasAttribute && target.hasAttribute('data-tool-call')) {
2586
+ var toolName = target.getAttribute('data-tool-call');
2587
+ var argsAttr = target.getAttribute('data-tool-args');
2588
+ var args = {};
2589
+
2590
+ try {
2591
+ if (argsAttr) {
2592
+ args = JSON.parse(argsAttr);
2593
+ }
2594
+ } catch (parseErr) {
2595
+ console.error('[frontmcp] Failed to parse data-tool-args:', parseErr);
2596
+ }
2597
+
2598
+ log('data-tool-call clicked: ' + toolName);
2599
+
2600
+ // Show loading state - save original content first
2601
+ var originalContent = target.innerHTML;
2602
+ var originalDisabled = target.disabled;
2603
+ target.disabled = true;
2604
+ target.classList.add('opacity-50', 'cursor-not-allowed');
2605
+
2606
+ // Add spinner for buttons
2607
+ var spinner = '<svg class="animate-spin -ml-1 mr-2 h-4 w-4 inline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>';
2608
+ if (target.tagName === 'BUTTON') {
2609
+ target.innerHTML = spinner + 'Loading...';
2610
+ }
2611
+
2612
+ // Helper to reset button state
2613
+ function resetButton() {
2614
+ target.innerHTML = originalContent;
2615
+ target.disabled = originalDisabled;
2616
+ target.classList.remove('opacity-50', 'cursor-not-allowed');
2617
+ }
2618
+
2619
+ // Determine how to call the tool
2620
+ var toolCallPromise;
2621
+
2622
+ // Priority 1: Direct OpenAI SDK call (bypasses adapter abstraction)
2623
+ if (typeof window !== 'undefined' && window.openai && typeof window.openai.callTool === 'function') {
2624
+ log('Using OpenAI SDK directly for tool call');
2625
+ toolCallPromise = window.openai.callTool(toolName, args);
2626
+ }
2627
+ // Priority 2: Use adapter (if it supports tool calls)
2628
+ else if (self.hasCapability('canCallTools')) {
2629
+ log('Using adapter for tool call');
2630
+ toolCallPromise = self.callTool(toolName, args);
2631
+ }
2632
+ // No tool call capability
2633
+ else {
2634
+ console.error('[frontmcp] Tool calls not supported on this platform (' + self.adapterId + ')');
2635
+ resetButton();
2636
+ target.dispatchEvent(new CustomEvent('tool:error', {
2637
+ detail: { name: toolName, args: args, error: 'Tool calls not supported on this platform' },
2638
+ bubbles: true
2639
+ }));
2640
+ e.preventDefault();
2641
+ return;
2642
+ }
2643
+
2644
+ // Handle the tool call result
2645
+ toolCallPromise.then(function(result) {
2646
+ log('Tool call succeeded: ' + toolName);
2647
+ resetButton();
2648
+
2649
+ // Update bridge state to trigger widget re-render
2650
+ // React isn't hydrated in OpenAI iframe, so useState doesn't work
2651
+ // Instead, we use the bridge's reactive state system
2652
+ if (result && window.__frontmcp && window.__frontmcp.bridge && typeof window.__frontmcp.bridge.setWidgetState === 'function') {
2653
+ var newData = result.structuredContent || result;
2654
+ log('Updating bridge state with new data');
2655
+ window.__frontmcp.bridge.setWidgetState(newData);
2656
+ }
2657
+
2658
+ // Dispatch success event
2659
+ target.dispatchEvent(new CustomEvent('tool:success', {
2660
+ detail: { name: toolName, args: args, result: result },
2661
+ bubbles: true
2662
+ }));
2663
+ }).catch(function(err) {
2664
+ console.error('[frontmcp] Tool call failed: ' + toolName, err);
2665
+ resetButton();
2666
+ // Dispatch error event
2667
+ target.dispatchEvent(new CustomEvent('tool:error', {
2668
+ detail: { name: toolName, args: args, error: err.message || err },
2669
+ bubbles: true
2670
+ }));
2671
+ });
2672
+
2673
+ // Prevent default behavior (e.g., form submission)
2674
+ e.preventDefault();
2675
+ return;
2676
+ }
2677
+ target = target.parentElement;
2678
+ }
2679
+ }, true); // Use capture phase to handle before React handlers
2680
+ };
2681
+ `.trim();
2682
+ }
2683
+ function minifyJS(code) {
2684
+ return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").replace(/\s+/g, " ").replace(/\s*([{};,:()[\]])\s*/g, "$1").replace(/;\}/g, "}").trim();
2685
+ }
2686
+ function generatePlatformBundle(platform, options = {}) {
2687
+ const platformAdapters = {
2688
+ chatgpt: ["openai", "generic"],
2689
+ claude: ["claude", "generic"],
2690
+ gemini: ["gemini", "generic"],
2691
+ universal: ["openai", "ext-apps", "claude", "gemini", "generic"]
2692
+ };
2693
+ return generateBridgeIIFE({
2694
+ ...options,
2695
+ adapters: platformAdapters[platform]
2696
+ });
2697
+ }
2698
+ var UNIVERSAL_BRIDGE_SCRIPT = generateBridgeIIFE();
2699
+ var BRIDGE_SCRIPT_TAGS = {
2700
+ universal: `<script>${UNIVERSAL_BRIDGE_SCRIPT}</script>`,
2701
+ chatgpt: `<script>${generatePlatformBundle("chatgpt")}</script>`,
2702
+ claude: `<script>${generatePlatformBundle("claude")}</script>`,
2703
+ gemini: `<script>${generatePlatformBundle("gemini")}</script>`
2704
+ };
2705
+
2706
+ // libs/ui/src/react/hooks/context.tsx
2707
+ import { jsx as jsx5 } from "react/jsx-runtime";
2708
+ var McpBridgeContext = createContext(null);
2709
+ function McpBridgeProvider({ children, config, onReady, onError }) {
2710
+ const [bridge, setBridge] = useState(null);
2711
+ const [loading, setLoading] = useState(true);
2712
+ const [error, setError] = useState(null);
2713
+ useEffect(() => {
2714
+ let mounted = true;
2715
+ let bridgeInstance = null;
2716
+ const initBridge = async () => {
2717
+ try {
2718
+ bridgeInstance = new FrontMcpBridge(config);
2719
+ await bridgeInstance.initialize();
2720
+ if (mounted) {
2721
+ setBridge(bridgeInstance);
2722
+ setLoading(false);
2723
+ onReady?.(bridgeInstance);
2724
+ }
2725
+ } catch (err) {
2726
+ if (mounted) {
2727
+ const error2 = err instanceof Error ? err : new Error(String(err));
2728
+ setError(error2);
2729
+ setLoading(false);
2730
+ onError?.(error2);
2731
+ }
2732
+ }
2733
+ };
2734
+ initBridge();
2735
+ return () => {
2736
+ mounted = false;
2737
+ if (bridgeInstance) {
2738
+ bridgeInstance.dispose();
2739
+ }
2740
+ };
2741
+ }, [config, onReady, onError]);
2742
+ const contextValue = useMemo(
2743
+ () => ({
2744
+ bridge,
2745
+ loading,
2746
+ error,
2747
+ ready: !loading && !error && bridge !== null,
2748
+ adapterId: bridge?.adapterId,
2749
+ capabilities: bridge?.capabilities
2750
+ }),
2751
+ [bridge, loading, error]
2752
+ );
2753
+ return /* @__PURE__ */ jsx5(McpBridgeContext.Provider, { value: contextValue, children });
2754
+ }
2755
+ var SSR_DEFAULT_CONTEXT = {
2756
+ bridge: null,
2757
+ loading: false,
2758
+ error: null,
2759
+ ready: false,
2760
+ adapterId: void 0,
2761
+ capabilities: void 0
2762
+ };
2763
+ function useMcpBridgeContext() {
2764
+ const context = useContext(McpBridgeContext);
2765
+ if (!context) {
2766
+ return SSR_DEFAULT_CONTEXT;
2767
+ }
2768
+ return context;
2769
+ }
2770
+ function useMcpBridge() {
2771
+ const { bridge } = useMcpBridgeContext();
2772
+ return bridge;
2773
+ }
2774
+ function useTheme() {
2775
+ const { bridge, ready } = useMcpBridgeContext();
2776
+ const [theme, setTheme] = useState("light");
2777
+ useEffect(() => {
2778
+ if (!ready || !bridge) return;
2779
+ setTheme(bridge.getTheme());
2780
+ const unsubscribe = bridge.onContextChange((changes) => {
2781
+ if (changes.theme) {
2782
+ setTheme(changes.theme);
2783
+ }
2784
+ });
2785
+ return unsubscribe;
2786
+ }, [bridge, ready]);
2787
+ return theme;
2788
+ }
2789
+ function useDisplayMode() {
2790
+ const { bridge, ready } = useMcpBridgeContext();
2791
+ const [displayMode, setDisplayMode] = useState("inline");
2792
+ useEffect(() => {
2793
+ if (!ready || !bridge) return;
2794
+ setDisplayMode(bridge.getDisplayMode());
2795
+ const unsubscribe = bridge.onContextChange((changes) => {
2796
+ if (changes.displayMode) {
2797
+ setDisplayMode(changes.displayMode);
2798
+ }
2799
+ });
2800
+ return unsubscribe;
2801
+ }, [bridge, ready]);
2802
+ return displayMode;
2803
+ }
2804
+ function useHostContext() {
2805
+ const { bridge, ready } = useMcpBridgeContext();
2806
+ const [context, setContext] = useState(null);
2807
+ useEffect(() => {
2808
+ if (!ready || !bridge) return;
2809
+ const adapter = bridge.getAdapter?.();
2810
+ if (adapter) {
2811
+ setContext(adapter.getHostContext());
2812
+ }
2813
+ const unsubscribe = bridge.onContextChange((changes) => {
2814
+ setContext((prev) => prev ? { ...prev, ...changes } : null);
2815
+ });
2816
+ return unsubscribe;
2817
+ }, [bridge, ready]);
2818
+ return context;
2819
+ }
2820
+ function useCapability(cap) {
2821
+ const { capabilities } = useMcpBridgeContext();
2822
+ return capabilities?.[cap] === true;
2823
+ }
2824
+
2825
+ // libs/ui/src/react/hooks/tools.tsx
2826
+ import { useState as useState2, useCallback as useCallback2, useEffect as useEffect2 } from "react";
2827
+ function useToolInput() {
2828
+ const { bridge, ready } = useMcpBridgeContext();
2829
+ if (!ready || !bridge) {
2830
+ return null;
2831
+ }
2832
+ try {
2833
+ return bridge.getToolInput();
2834
+ } catch {
2835
+ return null;
2836
+ }
2837
+ }
2838
+ function useToolOutput() {
2839
+ const { bridge, ready } = useMcpBridgeContext();
2840
+ const [output, setOutput] = useState2(null);
2841
+ useEffect2(() => {
2842
+ if (!ready || !bridge) return;
2843
+ try {
2844
+ const initialOutput = bridge.getToolOutput();
2845
+ if (initialOutput !== void 0) {
2846
+ setOutput(initialOutput);
2847
+ }
2848
+ } catch {
2849
+ }
2850
+ const unsubscribe = bridge.onToolResult((result) => {
2851
+ setOutput(result);
2852
+ });
2853
+ return unsubscribe;
2854
+ }, [bridge, ready]);
2855
+ return output;
2856
+ }
2857
+ function useStructuredContent() {
2858
+ const { bridge, ready } = useMcpBridgeContext();
2859
+ if (!ready || !bridge) {
2860
+ return null;
1081
2861
  }
1082
2862
  try {
1083
2863
  const adapter = bridge.getAdapter?.();
@@ -1269,36 +3049,8 @@ function useOpenLink() {
1269
3049
  );
1270
3050
  }
1271
3051
 
1272
- // libs/ui/src/theme/platforms.ts
1273
- var CLAUDE_PLATFORM = {
1274
- id: "claude",
1275
- name: "Claude (Artifacts)",
1276
- supportsWidgets: true,
1277
- supportsTailwind: true,
1278
- supportsHtmx: false,
1279
- // Network blocked, HTMX won't work for API calls
1280
- networkMode: "blocked",
1281
- scriptStrategy: "inline",
1282
- maxInlineSize: 100 * 1024,
1283
- // 100KB limit for artifacts
1284
- cspRestrictions: ["script-src 'unsafe-inline'", "connect-src 'none'"],
1285
- options: {
1286
- mode: "artifacts",
1287
- framework: "react"
1288
- // Claude artifacts prefer React
1289
- }
1290
- };
1291
-
1292
- // libs/ui/src/utils/escape-html.ts
1293
- function escapeHtml(str) {
1294
- if (str === null || str === void 0) {
1295
- return "";
1296
- }
1297
- const s = String(str);
1298
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
1299
- }
1300
-
1301
3052
  // libs/ui/src/react/utils.ts
3053
+ import { escapeHtml } from "@frontmcp/uipack/utils";
1302
3054
  var cachedReactDOMServer = null;
1303
3055
  function getReactDOMServer() {
1304
3056
  if (!cachedReactDOMServer) {