@frontmcp/ui 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/index.d.ts +13 -0
- package/adapters/index.d.ts.map +1 -0
- package/adapters/index.js +462 -0
- package/adapters/platform-meta.d.ts +166 -0
- package/adapters/platform-meta.d.ts.map +1 -0
- package/adapters/response-builder.d.ts +108 -0
- package/adapters/response-builder.d.ts.map +1 -0
- package/adapters/serving-mode.d.ts +107 -0
- package/adapters/serving-mode.d.ts.map +1 -0
- package/base-template/bridge.d.ts +90 -0
- package/base-template/bridge.d.ts.map +1 -0
- package/base-template/default-base-template.d.ts +92 -0
- package/base-template/default-base-template.d.ts.map +1 -0
- package/base-template/index.d.ts +15 -0
- package/base-template/index.d.ts.map +1 -0
- package/base-template/index.js +1398 -0
- package/base-template/polyfills.d.ts +31 -0
- package/base-template/polyfills.d.ts.map +1 -0
- package/base-template/theme-styles.d.ts +74 -0
- package/base-template/theme-styles.d.ts.map +1 -0
- package/bridge/adapters/base-adapter.d.ts +104 -0
- package/bridge/adapters/base-adapter.d.ts.map +1 -0
- package/bridge/adapters/claude.adapter.d.ts +67 -0
- package/bridge/adapters/claude.adapter.d.ts.map +1 -0
- package/bridge/adapters/ext-apps.adapter.d.ts +143 -0
- package/bridge/adapters/ext-apps.adapter.d.ts.map +1 -0
- package/bridge/adapters/gemini.adapter.d.ts +64 -0
- package/bridge/adapters/gemini.adapter.d.ts.map +1 -0
- package/bridge/adapters/generic.adapter.d.ts +56 -0
- package/bridge/adapters/generic.adapter.d.ts.map +1 -0
- package/bridge/adapters/index.d.ts +26 -0
- package/bridge/adapters/index.d.ts.map +1 -0
- package/bridge/adapters/openai.adapter.d.ts +65 -0
- package/bridge/adapters/openai.adapter.d.ts.map +1 -0
- package/bridge/core/adapter-registry.d.ts +122 -0
- package/bridge/core/adapter-registry.d.ts.map +1 -0
- package/bridge/core/bridge-factory.d.ts +199 -0
- package/bridge/core/bridge-factory.d.ts.map +1 -0
- package/bridge/core/index.d.ts +10 -0
- package/bridge/core/index.d.ts.map +1 -0
- package/bridge/index.d.ts +62 -0
- package/bridge/index.d.ts.map +1 -0
- package/bridge/index.js +2540 -0
- package/bridge/runtime/iife-generator.d.ts +62 -0
- package/bridge/runtime/iife-generator.d.ts.map +1 -0
- package/bridge/runtime/index.d.ts +9 -0
- package/bridge/runtime/index.d.ts.map +1 -0
- package/bridge/types.d.ts +386 -0
- package/bridge/types.d.ts.map +1 -0
- package/build/cdn-resources.d.ts +243 -0
- package/build/cdn-resources.d.ts.map +1 -0
- package/build/index.d.ts +295 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +7096 -0
- package/build/widget-manifest.d.ts +362 -0
- package/build/widget-manifest.d.ts.map +1 -0
- package/bundler/bundler.d.ts +208 -0
- package/bundler/bundler.d.ts.map +1 -0
- package/bundler/cache.d.ts +173 -0
- package/bundler/cache.d.ts.map +1 -0
- package/bundler/file-cache/component-builder.d.ts +167 -0
- package/bundler/file-cache/component-builder.d.ts.map +1 -0
- package/bundler/file-cache/hash-calculator.d.ts +155 -0
- package/bundler/file-cache/hash-calculator.d.ts.map +1 -0
- package/bundler/file-cache/index.d.ts +12 -0
- package/bundler/file-cache/index.d.ts.map +1 -0
- package/bundler/file-cache/storage/filesystem.d.ts +149 -0
- package/bundler/file-cache/storage/filesystem.d.ts.map +1 -0
- package/bundler/file-cache/storage/index.d.ts +11 -0
- package/bundler/file-cache/storage/index.d.ts.map +1 -0
- package/bundler/file-cache/storage/interface.d.ts +152 -0
- package/bundler/file-cache/storage/interface.d.ts.map +1 -0
- package/bundler/file-cache/storage/redis.d.ts +139 -0
- package/bundler/file-cache/storage/redis.d.ts.map +1 -0
- package/bundler/index.d.ts +43 -0
- package/bundler/index.d.ts.map +1 -0
- package/bundler/index.js +4754 -0
- package/bundler/sandbox/enclave-adapter.d.ts +121 -0
- package/bundler/sandbox/enclave-adapter.d.ts.map +1 -0
- package/bundler/sandbox/executor.d.ts +14 -0
- package/bundler/sandbox/executor.d.ts.map +1 -0
- package/bundler/sandbox/policy.d.ts +62 -0
- package/bundler/sandbox/policy.d.ts.map +1 -0
- package/bundler/types.d.ts +702 -0
- package/bundler/types.d.ts.map +1 -0
- package/components/alert.d.ts +66 -0
- package/components/alert.d.ts.map +1 -0
- package/components/alert.schema.d.ts +98 -0
- package/components/alert.schema.d.ts.map +1 -0
- package/components/avatar.d.ts +77 -0
- package/components/avatar.d.ts.map +1 -0
- package/components/avatar.schema.d.ts +170 -0
- package/components/avatar.schema.d.ts.map +1 -0
- package/components/badge.d.ts +64 -0
- package/components/badge.d.ts.map +1 -0
- package/components/badge.schema.d.ts +91 -0
- package/components/badge.schema.d.ts.map +1 -0
- package/components/button.d.ts +100 -0
- package/components/button.d.ts.map +1 -0
- package/components/button.schema.d.ts +120 -0
- package/components/button.schema.d.ts.map +1 -0
- package/components/card.d.ts +53 -0
- package/components/card.d.ts.map +1 -0
- package/components/card.schema.d.ts +93 -0
- package/components/card.schema.d.ts.map +1 -0
- package/components/form.d.ts +212 -0
- package/components/form.d.ts.map +1 -0
- package/components/form.schema.d.ts +365 -0
- package/components/form.schema.d.ts.map +1 -0
- package/components/index.d.ts +29 -0
- package/components/index.d.ts.map +1 -0
- package/components/index.js +2595 -0
- package/components/list.d.ts +121 -0
- package/components/list.d.ts.map +1 -0
- package/components/list.schema.d.ts +129 -0
- package/components/list.schema.d.ts.map +1 -0
- package/components/modal.d.ts +100 -0
- package/components/modal.d.ts.map +1 -0
- package/components/modal.schema.d.ts +151 -0
- package/components/modal.schema.d.ts.map +1 -0
- package/components/table.d.ts +91 -0
- package/components/table.d.ts.map +1 -0
- package/components/table.schema.d.ts +123 -0
- package/components/table.schema.d.ts.map +1 -0
- package/dependency/cdn-registry.d.ts +98 -0
- package/dependency/cdn-registry.d.ts.map +1 -0
- package/dependency/import-map.d.ts +186 -0
- package/dependency/import-map.d.ts.map +1 -0
- package/dependency/import-parser.d.ts +82 -0
- package/dependency/import-parser.d.ts.map +1 -0
- package/dependency/index.d.ts +17 -0
- package/dependency/index.d.ts.map +1 -0
- package/dependency/resolver.d.ts +164 -0
- package/dependency/resolver.d.ts.map +1 -0
- package/dependency/schemas.d.ts +486 -0
- package/dependency/schemas.d.ts.map +1 -0
- package/dependency/template-loader.d.ts +204 -0
- package/dependency/template-loader.d.ts.map +1 -0
- package/dependency/template-processor.d.ts +118 -0
- package/dependency/template-processor.d.ts.map +1 -0
- package/dependency/types.d.ts +739 -0
- package/dependency/types.d.ts.map +1 -0
- package/esm/adapters/index.d.ts +13 -0
- package/esm/adapters/index.d.ts.map +1 -0
- package/esm/adapters/index.js +427 -0
- package/esm/adapters/platform-meta.d.ts +166 -0
- package/esm/adapters/platform-meta.d.ts.map +1 -0
- package/esm/adapters/response-builder.d.ts +108 -0
- package/esm/adapters/response-builder.d.ts.map +1 -0
- package/esm/adapters/serving-mode.d.ts +107 -0
- package/esm/adapters/serving-mode.d.ts.map +1 -0
- package/esm/base-template/bridge.d.ts +90 -0
- package/esm/base-template/bridge.d.ts.map +1 -0
- package/esm/base-template/default-base-template.d.ts +92 -0
- package/esm/base-template/default-base-template.d.ts.map +1 -0
- package/esm/base-template/index.d.ts +15 -0
- package/esm/base-template/index.d.ts.map +1 -0
- package/esm/base-template/index.js +1364 -0
- package/esm/base-template/polyfills.d.ts +31 -0
- package/esm/base-template/polyfills.d.ts.map +1 -0
- package/esm/base-template/theme-styles.d.ts +74 -0
- package/esm/base-template/theme-styles.d.ts.map +1 -0
- package/esm/bridge/adapters/base-adapter.d.ts +104 -0
- package/esm/bridge/adapters/base-adapter.d.ts.map +1 -0
- package/esm/bridge/adapters/claude.adapter.d.ts +67 -0
- package/esm/bridge/adapters/claude.adapter.d.ts.map +1 -0
- package/esm/bridge/adapters/ext-apps.adapter.d.ts +143 -0
- package/esm/bridge/adapters/ext-apps.adapter.d.ts.map +1 -0
- package/esm/bridge/adapters/gemini.adapter.d.ts +64 -0
- package/esm/bridge/adapters/gemini.adapter.d.ts.map +1 -0
- package/esm/bridge/adapters/generic.adapter.d.ts +56 -0
- package/esm/bridge/adapters/generic.adapter.d.ts.map +1 -0
- package/esm/bridge/adapters/index.d.ts +26 -0
- package/esm/bridge/adapters/index.d.ts.map +1 -0
- package/esm/bridge/adapters/openai.adapter.d.ts +65 -0
- package/esm/bridge/adapters/openai.adapter.d.ts.map +1 -0
- package/esm/bridge/core/adapter-registry.d.ts +122 -0
- package/esm/bridge/core/adapter-registry.d.ts.map +1 -0
- package/esm/bridge/core/bridge-factory.d.ts +199 -0
- package/esm/bridge/core/bridge-factory.d.ts.map +1 -0
- package/esm/bridge/core/index.d.ts +10 -0
- package/esm/bridge/core/index.d.ts.map +1 -0
- package/esm/bridge/index.d.ts +62 -0
- package/esm/bridge/index.d.ts.map +1 -0
- package/esm/bridge/index.js +2487 -0
- package/esm/bridge/runtime/iife-generator.d.ts +62 -0
- package/esm/bridge/runtime/iife-generator.d.ts.map +1 -0
- package/esm/bridge/runtime/index.d.ts +9 -0
- package/esm/bridge/runtime/index.d.ts.map +1 -0
- package/esm/bridge/types.d.ts +386 -0
- package/esm/bridge/types.d.ts.map +1 -0
- package/esm/build/cdn-resources.d.ts +243 -0
- package/esm/build/cdn-resources.d.ts.map +1 -0
- package/esm/build/index.d.ts +295 -0
- package/esm/build/index.d.ts.map +1 -0
- package/esm/build/index.js +7021 -0
- package/esm/build/widget-manifest.d.ts +362 -0
- package/esm/build/widget-manifest.d.ts.map +1 -0
- package/esm/bundler/bundler.d.ts +208 -0
- package/esm/bundler/bundler.d.ts.map +1 -0
- package/esm/bundler/cache.d.ts +173 -0
- package/esm/bundler/cache.d.ts.map +1 -0
- package/esm/bundler/file-cache/component-builder.d.ts +167 -0
- package/esm/bundler/file-cache/component-builder.d.ts.map +1 -0
- package/esm/bundler/file-cache/hash-calculator.d.ts +155 -0
- package/esm/bundler/file-cache/hash-calculator.d.ts.map +1 -0
- package/esm/bundler/file-cache/index.d.ts +12 -0
- package/esm/bundler/file-cache/index.d.ts.map +1 -0
- package/esm/bundler/file-cache/storage/filesystem.d.ts +149 -0
- package/esm/bundler/file-cache/storage/filesystem.d.ts.map +1 -0
- package/esm/bundler/file-cache/storage/index.d.ts +11 -0
- package/esm/bundler/file-cache/storage/index.d.ts.map +1 -0
- package/esm/bundler/file-cache/storage/interface.d.ts +152 -0
- package/esm/bundler/file-cache/storage/interface.d.ts.map +1 -0
- package/esm/bundler/file-cache/storage/redis.d.ts +139 -0
- package/esm/bundler/file-cache/storage/redis.d.ts.map +1 -0
- package/esm/bundler/index.d.ts +43 -0
- package/esm/bundler/index.d.ts.map +1 -0
- package/esm/bundler/index.js +4687 -0
- package/esm/bundler/sandbox/enclave-adapter.d.ts +121 -0
- package/esm/bundler/sandbox/enclave-adapter.d.ts.map +1 -0
- package/esm/bundler/sandbox/executor.d.ts +14 -0
- package/esm/bundler/sandbox/executor.d.ts.map +1 -0
- package/esm/bundler/sandbox/policy.d.ts +62 -0
- package/esm/bundler/sandbox/policy.d.ts.map +1 -0
- package/esm/bundler/types.d.ts +702 -0
- package/esm/bundler/types.d.ts.map +1 -0
- package/esm/components/alert.d.ts +66 -0
- package/esm/components/alert.d.ts.map +1 -0
- package/esm/components/alert.schema.d.ts +98 -0
- package/esm/components/alert.schema.d.ts.map +1 -0
- package/esm/components/avatar.d.ts +77 -0
- package/esm/components/avatar.d.ts.map +1 -0
- package/esm/components/avatar.schema.d.ts +170 -0
- package/esm/components/avatar.schema.d.ts.map +1 -0
- package/esm/components/badge.d.ts +64 -0
- package/esm/components/badge.d.ts.map +1 -0
- package/esm/components/badge.schema.d.ts +91 -0
- package/esm/components/badge.schema.d.ts.map +1 -0
- package/esm/components/button.d.ts +100 -0
- package/esm/components/button.d.ts.map +1 -0
- package/esm/components/button.schema.d.ts +120 -0
- package/esm/components/button.schema.d.ts.map +1 -0
- package/esm/components/card.d.ts +53 -0
- package/esm/components/card.d.ts.map +1 -0
- package/esm/components/card.schema.d.ts +93 -0
- package/esm/components/card.schema.d.ts.map +1 -0
- package/esm/components/form.d.ts +212 -0
- package/esm/components/form.d.ts.map +1 -0
- package/esm/components/form.schema.d.ts +365 -0
- package/esm/components/form.schema.d.ts.map +1 -0
- package/esm/components/index.d.ts +29 -0
- package/esm/components/index.d.ts.map +1 -0
- package/esm/components/index.js +2456 -0
- package/esm/components/list.d.ts +121 -0
- package/esm/components/list.d.ts.map +1 -0
- package/esm/components/list.schema.d.ts +129 -0
- package/esm/components/list.schema.d.ts.map +1 -0
- package/esm/components/modal.d.ts +100 -0
- package/esm/components/modal.d.ts.map +1 -0
- package/esm/components/modal.schema.d.ts +151 -0
- package/esm/components/modal.schema.d.ts.map +1 -0
- package/esm/components/table.d.ts +91 -0
- package/esm/components/table.d.ts.map +1 -0
- package/esm/components/table.schema.d.ts +123 -0
- package/esm/components/table.schema.d.ts.map +1 -0
- package/esm/dependency/cdn-registry.d.ts +98 -0
- package/esm/dependency/cdn-registry.d.ts.map +1 -0
- package/esm/dependency/import-map.d.ts +186 -0
- package/esm/dependency/import-map.d.ts.map +1 -0
- package/esm/dependency/import-parser.d.ts +82 -0
- package/esm/dependency/import-parser.d.ts.map +1 -0
- package/esm/dependency/index.d.ts +17 -0
- package/esm/dependency/index.d.ts.map +1 -0
- package/esm/dependency/resolver.d.ts +164 -0
- package/esm/dependency/resolver.d.ts.map +1 -0
- package/esm/dependency/schemas.d.ts +486 -0
- package/esm/dependency/schemas.d.ts.map +1 -0
- package/esm/dependency/template-loader.d.ts +204 -0
- package/esm/dependency/template-loader.d.ts.map +1 -0
- package/esm/dependency/template-processor.d.ts +118 -0
- package/esm/dependency/template-processor.d.ts.map +1 -0
- package/esm/dependency/types.d.ts +739 -0
- package/esm/dependency/types.d.ts.map +1 -0
- package/esm/handlebars/expression-extractor.d.ts +147 -0
- package/esm/handlebars/expression-extractor.d.ts.map +1 -0
- package/esm/handlebars/helpers.d.ts +339 -0
- package/esm/handlebars/helpers.d.ts.map +1 -0
- package/esm/handlebars/index.d.ts +195 -0
- package/esm/handlebars/index.d.ts.map +1 -0
- package/esm/handlebars/index.js +587 -0
- package/esm/index.d.ts +56 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +20511 -0
- package/esm/layouts/base.d.ts +86 -0
- package/esm/layouts/base.d.ts.map +1 -0
- package/esm/layouts/index.d.ts +8 -0
- package/esm/layouts/index.d.ts.map +1 -0
- package/esm/layouts/index.js +892 -0
- package/esm/layouts/presets.d.ts +134 -0
- package/esm/layouts/presets.d.ts.map +1 -0
- package/esm/package.json +90 -0
- package/esm/pages/consent.d.ts +117 -0
- package/esm/pages/consent.d.ts.map +1 -0
- package/esm/pages/error.d.ts +101 -0
- package/esm/pages/error.d.ts.map +1 -0
- package/esm/pages/index.d.ts +9 -0
- package/esm/pages/index.d.ts.map +1 -0
- package/esm/pages/index.js +1563 -0
- package/esm/react/Alert.d.ts +102 -0
- package/esm/react/Alert.d.ts.map +1 -0
- package/esm/react/Badge.d.ts +101 -0
- package/esm/react/Badge.d.ts.map +1 -0
- package/esm/react/Button.d.ts +109 -0
- package/esm/react/Button.d.ts.map +1 -0
- package/esm/react/Card.d.ts +104 -0
- package/esm/react/Card.d.ts.map +1 -0
- package/esm/react/hooks/context.d.ts +179 -0
- package/esm/react/hooks/context.d.ts.map +1 -0
- package/esm/react/hooks/index.d.ts +42 -0
- package/esm/react/hooks/index.d.ts.map +1 -0
- package/esm/react/hooks/tools.d.ts +284 -0
- package/esm/react/hooks/tools.d.ts.map +1 -0
- package/esm/react/index.d.ts +81 -0
- package/esm/react/index.d.ts.map +1 -0
- package/esm/react/index.js +1372 -0
- package/esm/react/types.d.ts +106 -0
- package/esm/react/types.d.ts.map +1 -0
- package/esm/react/utils.d.ts +43 -0
- package/esm/react/utils.d.ts.map +1 -0
- package/esm/registry/index.d.ts +46 -0
- package/esm/registry/index.d.ts.map +1 -0
- package/esm/registry/index.js +6422 -0
- package/esm/registry/render-template.d.ts +91 -0
- package/esm/registry/render-template.d.ts.map +1 -0
- package/esm/registry/tool-ui.registry.d.ts +294 -0
- package/esm/registry/tool-ui.registry.d.ts.map +1 -0
- package/esm/registry/uri-utils.d.ts +56 -0
- package/esm/registry/uri-utils.d.ts.map +1 -0
- package/esm/render/index.d.ts +8 -0
- package/esm/render/index.d.ts.map +1 -0
- package/esm/render/index.js +45 -0
- package/esm/render/prerender.d.ts +57 -0
- package/esm/render/prerender.d.ts.map +1 -0
- package/esm/renderers/cache.d.ts +145 -0
- package/esm/renderers/cache.d.ts.map +1 -0
- package/esm/renderers/html.renderer.d.ts +123 -0
- package/esm/renderers/html.renderer.d.ts.map +1 -0
- package/esm/renderers/index.d.ts +36 -0
- package/esm/renderers/index.d.ts.map +1 -0
- package/esm/renderers/index.js +1827 -0
- package/esm/renderers/mdx.renderer.d.ts +120 -0
- package/esm/renderers/mdx.renderer.d.ts.map +1 -0
- package/esm/renderers/react.renderer.d.ts +96 -0
- package/esm/renderers/react.renderer.d.ts.map +1 -0
- package/esm/renderers/registry.d.ts +134 -0
- package/esm/renderers/registry.d.ts.map +1 -0
- package/esm/renderers/types.d.ts +342 -0
- package/esm/renderers/types.d.ts.map +1 -0
- package/esm/renderers/utils/detect.d.ts +107 -0
- package/esm/renderers/utils/detect.d.ts.map +1 -0
- package/esm/renderers/utils/hash.d.ts +40 -0
- package/esm/renderers/utils/hash.d.ts.map +1 -0
- package/esm/renderers/utils/index.d.ts +9 -0
- package/esm/renderers/utils/index.d.ts.map +1 -0
- package/esm/renderers/utils/transpiler.d.ts +89 -0
- package/esm/renderers/utils/transpiler.d.ts.map +1 -0
- package/esm/runtime/adapters/html.adapter.d.ts +59 -0
- package/esm/runtime/adapters/html.adapter.d.ts.map +1 -0
- package/esm/runtime/adapters/index.d.ts +26 -0
- package/esm/runtime/adapters/index.d.ts.map +1 -0
- package/esm/runtime/adapters/mdx.adapter.d.ts +73 -0
- package/esm/runtime/adapters/mdx.adapter.d.ts.map +1 -0
- package/esm/runtime/adapters/react.adapter.d.ts +70 -0
- package/esm/runtime/adapters/react.adapter.d.ts.map +1 -0
- package/esm/runtime/adapters/types.d.ts +95 -0
- package/esm/runtime/adapters/types.d.ts.map +1 -0
- package/esm/runtime/csp.d.ts +48 -0
- package/esm/runtime/csp.d.ts.map +1 -0
- package/esm/runtime/index.d.ts +17 -0
- package/esm/runtime/index.d.ts.map +1 -0
- package/esm/runtime/index.js +5186 -0
- package/esm/runtime/mcp-bridge.d.ts +101 -0
- package/esm/runtime/mcp-bridge.d.ts.map +1 -0
- package/esm/runtime/renderer-runtime.d.ts +133 -0
- package/esm/runtime/renderer-runtime.d.ts.map +1 -0
- package/esm/runtime/sanitizer.d.ts +172 -0
- package/esm/runtime/sanitizer.d.ts.map +1 -0
- package/esm/runtime/types.d.ts +415 -0
- package/esm/runtime/types.d.ts.map +1 -0
- package/esm/runtime/wrapper.d.ts +421 -0
- package/esm/runtime/wrapper.d.ts.map +1 -0
- package/esm/styles/index.d.ts +8 -0
- package/esm/styles/index.d.ts.map +1 -0
- package/esm/styles/index.js +171 -0
- package/esm/styles/variants.d.ts +51 -0
- package/esm/styles/variants.d.ts.map +1 -0
- package/esm/theme/cdn.d.ts +195 -0
- package/esm/theme/cdn.d.ts.map +1 -0
- package/esm/theme/index.d.ts +18 -0
- package/esm/theme/index.d.ts.map +1 -0
- package/esm/theme/index.js +700 -0
- package/esm/theme/platforms.d.ts +107 -0
- package/esm/theme/platforms.d.ts.map +1 -0
- package/esm/theme/presets/github-openai.d.ts +50 -0
- package/esm/theme/presets/github-openai.d.ts.map +1 -0
- package/esm/theme/presets/index.d.ts +11 -0
- package/esm/theme/presets/index.d.ts.map +1 -0
- package/esm/theme/theme.d.ts +396 -0
- package/esm/theme/theme.d.ts.map +1 -0
- package/esm/tool-template/builder.d.ts +213 -0
- package/esm/tool-template/builder.d.ts.map +1 -0
- package/esm/tool-template/index.d.ts +16 -0
- package/esm/tool-template/index.d.ts.map +1 -0
- package/esm/tool-template/index.js +3515 -0
- package/esm/types/index.d.ts +14 -0
- package/esm/types/index.d.ts.map +1 -0
- package/esm/types/index.js +75 -0
- package/esm/types/ui-config.d.ts +639 -0
- package/esm/types/ui-config.d.ts.map +1 -0
- package/esm/types/ui-runtime.d.ts +1007 -0
- package/esm/types/ui-runtime.d.ts.map +1 -0
- package/esm/typings/cache/cache-adapter.d.ts +125 -0
- package/esm/typings/cache/cache-adapter.d.ts.map +1 -0
- package/esm/typings/cache/index.d.ts +10 -0
- package/esm/typings/cache/index.d.ts.map +1 -0
- package/esm/typings/cache/memory-cache.d.ts +92 -0
- package/esm/typings/cache/memory-cache.d.ts.map +1 -0
- package/esm/typings/dts-parser.d.ts +90 -0
- package/esm/typings/dts-parser.d.ts.map +1 -0
- package/esm/typings/index.d.ts +48 -0
- package/esm/typings/index.d.ts.map +1 -0
- package/esm/typings/schemas.d.ts +232 -0
- package/esm/typings/schemas.d.ts.map +1 -0
- package/esm/typings/type-fetcher.d.ts +89 -0
- package/esm/typings/type-fetcher.d.ts.map +1 -0
- package/esm/typings/types.d.ts +320 -0
- package/esm/typings/types.d.ts.map +1 -0
- package/esm/universal/UniversalApp.d.ts +108 -0
- package/esm/universal/UniversalApp.d.ts.map +1 -0
- package/esm/universal/cached-runtime.d.ts +115 -0
- package/esm/universal/cached-runtime.d.ts.map +1 -0
- package/esm/universal/context.d.ts +122 -0
- package/esm/universal/context.d.ts.map +1 -0
- package/esm/universal/index.d.ts +57 -0
- package/esm/universal/index.d.ts.map +1 -0
- package/esm/universal/renderers/html.renderer.d.ts +37 -0
- package/esm/universal/renderers/html.renderer.d.ts.map +1 -0
- package/esm/universal/renderers/index.d.ts +112 -0
- package/esm/universal/renderers/index.d.ts.map +1 -0
- package/esm/universal/renderers/markdown.renderer.d.ts +33 -0
- package/esm/universal/renderers/markdown.renderer.d.ts.map +1 -0
- package/esm/universal/renderers/mdx.renderer.d.ts +38 -0
- package/esm/universal/renderers/mdx.renderer.d.ts.map +1 -0
- package/esm/universal/renderers/react.renderer.d.ts +46 -0
- package/esm/universal/renderers/react.renderer.d.ts.map +1 -0
- package/esm/universal/runtime-builder.d.ts +33 -0
- package/esm/universal/runtime-builder.d.ts.map +1 -0
- package/esm/universal/store.d.ts +135 -0
- package/esm/universal/store.d.ts.map +1 -0
- package/esm/universal/types.d.ts +199 -0
- package/esm/universal/types.d.ts.map +1 -0
- package/esm/utils/escape-html.d.ts +58 -0
- package/esm/utils/escape-html.d.ts.map +1 -0
- package/esm/utils/index.d.ts +10 -0
- package/esm/utils/index.d.ts.map +1 -0
- package/esm/utils/index.js +40 -0
- package/esm/utils/safe-stringify.d.ts +30 -0
- package/esm/utils/safe-stringify.d.ts.map +1 -0
- package/esm/validation/error-box.d.ts +56 -0
- package/esm/validation/error-box.d.ts.map +1 -0
- package/esm/validation/index.d.ts +13 -0
- package/esm/validation/index.d.ts.map +1 -0
- package/esm/validation/index.js +562 -0
- package/esm/validation/schema-paths.d.ts +118 -0
- package/esm/validation/schema-paths.d.ts.map +1 -0
- package/esm/validation/template-validator.d.ts +143 -0
- package/esm/validation/template-validator.d.ts.map +1 -0
- package/esm/validation/wrapper.d.ts +97 -0
- package/esm/validation/wrapper.d.ts.map +1 -0
- package/esm/web-components/core/attribute-parser.d.ts +82 -0
- package/esm/web-components/core/attribute-parser.d.ts.map +1 -0
- package/esm/web-components/core/base-element.d.ts +197 -0
- package/esm/web-components/core/base-element.d.ts.map +1 -0
- package/esm/web-components/core/index.d.ts +9 -0
- package/esm/web-components/core/index.d.ts.map +1 -0
- package/esm/web-components/elements/fmcp-alert.d.ts +46 -0
- package/esm/web-components/elements/fmcp-alert.d.ts.map +1 -0
- package/esm/web-components/elements/fmcp-badge.d.ts +47 -0
- package/esm/web-components/elements/fmcp-badge.d.ts.map +1 -0
- package/esm/web-components/elements/fmcp-button.d.ts +117 -0
- package/esm/web-components/elements/fmcp-button.d.ts.map +1 -0
- package/esm/web-components/elements/fmcp-card.d.ts +53 -0
- package/esm/web-components/elements/fmcp-card.d.ts.map +1 -0
- package/esm/web-components/elements/fmcp-input.d.ts +96 -0
- package/esm/web-components/elements/fmcp-input.d.ts.map +1 -0
- package/esm/web-components/elements/fmcp-select.d.ts +100 -0
- package/esm/web-components/elements/fmcp-select.d.ts.map +1 -0
- package/esm/web-components/elements/index.d.ts +13 -0
- package/esm/web-components/elements/index.d.ts.map +1 -0
- package/esm/web-components/index.d.ts +50 -0
- package/esm/web-components/index.d.ts.map +1 -0
- package/esm/web-components/index.js +2048 -0
- package/esm/web-components/register.d.ts +57 -0
- package/esm/web-components/register.d.ts.map +1 -0
- package/esm/web-components/types.d.ts +122 -0
- package/esm/web-components/types.d.ts.map +1 -0
- package/esm/widgets/index.d.ts +8 -0
- package/esm/widgets/index.d.ts.map +1 -0
- package/esm/widgets/index.js +941 -0
- package/esm/widgets/progress.d.ts +133 -0
- package/esm/widgets/progress.d.ts.map +1 -0
- package/esm/widgets/resource.d.ts +163 -0
- package/esm/widgets/resource.d.ts.map +1 -0
- package/handlebars/expression-extractor.d.ts +147 -0
- package/handlebars/expression-extractor.d.ts.map +1 -0
- package/handlebars/helpers.d.ts +339 -0
- package/handlebars/helpers.d.ts.map +1 -0
- package/handlebars/index.d.ts +195 -0
- package/handlebars/index.d.ts.map +1 -0
- package/handlebars/index.js +666 -0
- package/index.d.ts +56 -0
- package/index.d.ts.map +1 -0
- package/index.js +20942 -0
- package/layouts/base.d.ts +86 -0
- package/layouts/base.d.ts.map +1 -0
- package/layouts/index.d.ts +8 -0
- package/layouts/index.d.ts.map +1 -0
- package/layouts/index.js +930 -0
- package/layouts/presets.d.ts +134 -0
- package/layouts/presets.d.ts.map +1 -0
- package/package.json +28 -87
- package/pages/consent.d.ts +117 -0
- package/pages/consent.d.ts.map +1 -0
- package/pages/error.d.ts +101 -0
- package/pages/error.d.ts.map +1 -0
- package/pages/index.d.ts +9 -0
- package/pages/index.d.ts.map +1 -0
- package/pages/index.js +1602 -0
- package/react/Alert.d.ts +102 -0
- package/react/Alert.d.ts.map +1 -0
- package/react/Badge.d.ts +101 -0
- package/react/Badge.d.ts.map +1 -0
- package/react/Button.d.ts +109 -0
- package/react/Button.d.ts.map +1 -0
- package/react/Card.d.ts +104 -0
- package/react/Card.d.ts.map +1 -0
- package/react/hooks/context.d.ts +179 -0
- package/react/hooks/context.d.ts.map +1 -0
- package/react/hooks/index.d.ts +42 -0
- package/react/hooks/index.d.ts.map +1 -0
- package/react/hooks/tools.d.ts +284 -0
- package/react/hooks/tools.d.ts.map +1 -0
- package/react/index.d.ts +81 -0
- package/react/index.d.ts.map +1 -0
- package/react/index.js +1430 -0
- package/react/types.d.ts +106 -0
- package/react/types.d.ts.map +1 -0
- package/react/utils.d.ts +43 -0
- package/react/utils.d.ts.map +1 -0
- package/registry/index.d.ts +46 -0
- package/registry/index.d.ts.map +1 -0
- package/registry/index.js +6465 -0
- package/registry/render-template.d.ts +91 -0
- package/registry/render-template.d.ts.map +1 -0
- package/registry/tool-ui.registry.d.ts +294 -0
- package/registry/tool-ui.registry.d.ts.map +1 -0
- package/registry/uri-utils.d.ts +56 -0
- package/registry/uri-utils.d.ts.map +1 -0
- package/render/index.d.ts +8 -0
- package/render/index.d.ts.map +1 -0
- package/render/index.js +77 -0
- package/render/prerender.d.ts +57 -0
- package/render/prerender.d.ts.map +1 -0
- package/renderers/cache.d.ts +145 -0
- package/renderers/cache.d.ts.map +1 -0
- package/renderers/html.renderer.d.ts +123 -0
- package/renderers/html.renderer.d.ts.map +1 -0
- package/renderers/index.d.ts +36 -0
- package/renderers/index.d.ts.map +1 -0
- package/renderers/index.js +1882 -0
- package/renderers/mdx.renderer.d.ts +120 -0
- package/renderers/mdx.renderer.d.ts.map +1 -0
- package/renderers/react.renderer.d.ts +96 -0
- package/renderers/react.renderer.d.ts.map +1 -0
- package/renderers/registry.d.ts +134 -0
- package/renderers/registry.d.ts.map +1 -0
- package/renderers/types.d.ts +342 -0
- package/renderers/types.d.ts.map +1 -0
- package/renderers/utils/detect.d.ts +107 -0
- package/renderers/utils/detect.d.ts.map +1 -0
- package/renderers/utils/hash.d.ts +40 -0
- package/renderers/utils/hash.d.ts.map +1 -0
- package/renderers/utils/index.d.ts +9 -0
- package/renderers/utils/index.d.ts.map +1 -0
- package/renderers/utils/transpiler.d.ts +89 -0
- package/renderers/utils/transpiler.d.ts.map +1 -0
- package/runtime/adapters/html.adapter.d.ts +59 -0
- package/runtime/adapters/html.adapter.d.ts.map +1 -0
- package/runtime/adapters/index.d.ts +26 -0
- package/runtime/adapters/index.d.ts.map +1 -0
- package/runtime/adapters/mdx.adapter.d.ts +73 -0
- package/runtime/adapters/mdx.adapter.d.ts.map +1 -0
- package/runtime/adapters/react.adapter.d.ts +70 -0
- package/runtime/adapters/react.adapter.d.ts.map +1 -0
- package/runtime/adapters/types.d.ts +95 -0
- package/runtime/adapters/types.d.ts.map +1 -0
- package/runtime/csp.d.ts +48 -0
- package/runtime/csp.d.ts.map +1 -0
- package/runtime/index.d.ts +17 -0
- package/runtime/index.d.ts.map +1 -0
- package/runtime/index.js +5264 -0
- package/runtime/mcp-bridge.d.ts +101 -0
- package/runtime/mcp-bridge.d.ts.map +1 -0
- package/runtime/renderer-runtime.d.ts +133 -0
- package/runtime/renderer-runtime.d.ts.map +1 -0
- package/runtime/sanitizer.d.ts +172 -0
- package/runtime/sanitizer.d.ts.map +1 -0
- package/runtime/types.d.ts +415 -0
- package/runtime/types.d.ts.map +1 -0
- package/runtime/wrapper.d.ts +421 -0
- package/runtime/wrapper.d.ts.map +1 -0
- package/styles/index.d.ts +8 -0
- package/styles/index.d.ts.map +1 -0
- package/styles/index.js +222 -0
- package/styles/variants.d.ts +51 -0
- package/styles/variants.d.ts.map +1 -0
- package/theme/cdn.d.ts +195 -0
- package/theme/cdn.d.ts.map +1 -0
- package/theme/index.d.ts +18 -0
- package/theme/index.d.ts.map +1 -0
- package/theme/index.js +757 -0
- package/theme/platforms.d.ts +107 -0
- package/theme/platforms.d.ts.map +1 -0
- package/theme/presets/github-openai.d.ts +50 -0
- package/theme/presets/github-openai.d.ts.map +1 -0
- package/theme/presets/index.d.ts +11 -0
- package/theme/presets/index.d.ts.map +1 -0
- package/theme/theme.d.ts +396 -0
- package/theme/theme.d.ts.map +1 -0
- package/tool-template/builder.d.ts +213 -0
- package/tool-template/builder.d.ts.map +1 -0
- package/tool-template/index.d.ts +16 -0
- package/tool-template/index.d.ts.map +1 -0
- package/tool-template/index.js +3559 -0
- package/types/index.d.ts +14 -0
- package/types/index.d.ts.map +1 -0
- package/types/index.js +108 -0
- package/types/ui-config.d.ts +639 -0
- package/types/ui-config.d.ts.map +1 -0
- package/types/ui-runtime.d.ts +1007 -0
- package/types/ui-runtime.d.ts.map +1 -0
- package/typings/cache/cache-adapter.d.ts +125 -0
- package/typings/cache/cache-adapter.d.ts.map +1 -0
- package/typings/cache/index.d.ts +10 -0
- package/typings/cache/index.d.ts.map +1 -0
- package/typings/cache/memory-cache.d.ts +92 -0
- package/typings/cache/memory-cache.d.ts.map +1 -0
- package/typings/dts-parser.d.ts +90 -0
- package/typings/dts-parser.d.ts.map +1 -0
- package/typings/index.d.ts +48 -0
- package/typings/index.d.ts.map +1 -0
- package/typings/schemas.d.ts +232 -0
- package/typings/schemas.d.ts.map +1 -0
- package/typings/type-fetcher.d.ts +89 -0
- package/typings/type-fetcher.d.ts.map +1 -0
- package/typings/types.d.ts +320 -0
- package/typings/types.d.ts.map +1 -0
- package/universal/UniversalApp.d.ts +108 -0
- package/universal/UniversalApp.d.ts.map +1 -0
- package/universal/cached-runtime.d.ts +115 -0
- package/universal/cached-runtime.d.ts.map +1 -0
- package/universal/context.d.ts +122 -0
- package/universal/context.d.ts.map +1 -0
- package/universal/index.d.ts +57 -0
- package/universal/index.d.ts.map +1 -0
- package/universal/renderers/html.renderer.d.ts +37 -0
- package/universal/renderers/html.renderer.d.ts.map +1 -0
- package/universal/renderers/index.d.ts +112 -0
- package/universal/renderers/index.d.ts.map +1 -0
- package/universal/renderers/markdown.renderer.d.ts +33 -0
- package/universal/renderers/markdown.renderer.d.ts.map +1 -0
- package/universal/renderers/mdx.renderer.d.ts +38 -0
- package/universal/renderers/mdx.renderer.d.ts.map +1 -0
- package/universal/renderers/react.renderer.d.ts +46 -0
- package/universal/renderers/react.renderer.d.ts.map +1 -0
- package/universal/runtime-builder.d.ts +33 -0
- package/universal/runtime-builder.d.ts.map +1 -0
- package/universal/store.d.ts +135 -0
- package/universal/store.d.ts.map +1 -0
- package/universal/types.d.ts +199 -0
- package/universal/types.d.ts.map +1 -0
- package/utils/escape-html.d.ts +58 -0
- package/utils/escape-html.d.ts.map +1 -0
- package/utils/index.d.ts +10 -0
- package/utils/index.d.ts.map +1 -0
- package/utils/index.js +70 -0
- package/utils/safe-stringify.d.ts +30 -0
- package/utils/safe-stringify.d.ts.map +1 -0
- package/validation/error-box.d.ts +56 -0
- package/validation/error-box.d.ts.map +1 -0
- package/validation/index.d.ts +13 -0
- package/validation/index.d.ts.map +1 -0
- package/validation/index.js +603 -0
- package/validation/schema-paths.d.ts +118 -0
- package/validation/schema-paths.d.ts.map +1 -0
- package/validation/template-validator.d.ts +143 -0
- package/validation/template-validator.d.ts.map +1 -0
- package/validation/wrapper.d.ts +97 -0
- package/validation/wrapper.d.ts.map +1 -0
- package/web-components/core/attribute-parser.d.ts +82 -0
- package/web-components/core/attribute-parser.d.ts.map +1 -0
- package/web-components/core/base-element.d.ts +197 -0
- package/web-components/core/base-element.d.ts.map +1 -0
- package/web-components/core/index.d.ts +9 -0
- package/web-components/core/index.d.ts.map +1 -0
- package/web-components/elements/fmcp-alert.d.ts +46 -0
- package/web-components/elements/fmcp-alert.d.ts.map +1 -0
- package/web-components/elements/fmcp-badge.d.ts +47 -0
- package/web-components/elements/fmcp-badge.d.ts.map +1 -0
- package/web-components/elements/fmcp-button.d.ts +117 -0
- package/web-components/elements/fmcp-button.d.ts.map +1 -0
- package/web-components/elements/fmcp-card.d.ts +53 -0
- package/web-components/elements/fmcp-card.d.ts.map +1 -0
- package/web-components/elements/fmcp-input.d.ts +96 -0
- package/web-components/elements/fmcp-input.d.ts.map +1 -0
- package/web-components/elements/fmcp-select.d.ts +100 -0
- package/web-components/elements/fmcp-select.d.ts.map +1 -0
- package/web-components/elements/index.d.ts +13 -0
- package/web-components/elements/index.d.ts.map +1 -0
- package/web-components/index.d.ts +50 -0
- package/web-components/index.d.ts.map +1 -0
- package/web-components/index.js +2093 -0
- package/web-components/register.d.ts +57 -0
- package/web-components/register.d.ts.map +1 -0
- package/web-components/types.d.ts +122 -0
- package/web-components/types.d.ts.map +1 -0
- package/widgets/index.d.ts +8 -0
- package/widgets/index.d.ts.map +1 -0
- package/widgets/index.js +978 -0
- package/widgets/progress.d.ts +133 -0
- package/widgets/progress.d.ts.map +1 -0
- package/widgets/resource.d.ts +163 -0
- package/widgets/resource.d.ts.map +1 -0
- package/src/adapters/index.d.ts +0 -10
- package/src/adapters/index.js +0 -18
- package/src/adapters/index.js.map +0 -1
- package/src/adapters/platform-meta.d.ts +0 -165
- package/src/adapters/platform-meta.js +0 -310
- package/src/adapters/platform-meta.js.map +0 -1
- package/src/base-template/bridge.d.ts +0 -89
- package/src/base-template/bridge.js +0 -452
- package/src/base-template/bridge.js.map +0 -1
- package/src/base-template/default-base-template.d.ts +0 -91
- package/src/base-template/default-base-template.js +0 -435
- package/src/base-template/default-base-template.js.map +0 -1
- package/src/base-template/index.d.ts +0 -14
- package/src/base-template/index.js +0 -30
- package/src/base-template/index.js.map +0 -1
- package/src/base-template/polyfills.d.ts +0 -30
- package/src/base-template/polyfills.js +0 -190
- package/src/base-template/polyfills.js.map +0 -1
- package/src/base-template/theme-styles.d.ts +0 -73
- package/src/base-template/theme-styles.js +0 -95
- package/src/base-template/theme-styles.js.map +0 -1
- package/src/bridge/adapters/base-adapter.d.ts +0 -103
- package/src/bridge/adapters/base-adapter.js +0 -314
- package/src/bridge/adapters/base-adapter.js.map +0 -1
- package/src/bridge/adapters/claude.adapter.d.ts +0 -66
- package/src/bridge/adapters/claude.adapter.js +0 -145
- package/src/bridge/adapters/claude.adapter.js.map +0 -1
- package/src/bridge/adapters/ext-apps.adapter.d.ts +0 -142
- package/src/bridge/adapters/ext-apps.adapter.js +0 -416
- package/src/bridge/adapters/ext-apps.adapter.js.map +0 -1
- package/src/bridge/adapters/gemini.adapter.d.ts +0 -63
- package/src/bridge/adapters/gemini.adapter.js +0 -160
- package/src/bridge/adapters/gemini.adapter.js.map +0 -1
- package/src/bridge/adapters/generic.adapter.d.ts +0 -55
- package/src/bridge/adapters/generic.adapter.js +0 -108
- package/src/bridge/adapters/generic.adapter.js.map +0 -1
- package/src/bridge/adapters/index.d.ts +0 -25
- package/src/bridge/adapters/index.js +0 -65
- package/src/bridge/adapters/index.js.map +0 -1
- package/src/bridge/adapters/openai.adapter.d.ts +0 -64
- package/src/bridge/adapters/openai.adapter.js +0 -194
- package/src/bridge/adapters/openai.adapter.js.map +0 -1
- package/src/bridge/core/adapter-registry.d.ts +0 -121
- package/src/bridge/core/adapter-registry.js +0 -271
- package/src/bridge/core/adapter-registry.js.map +0 -1
- package/src/bridge/core/bridge-factory.d.ts +0 -198
- package/src/bridge/core/bridge-factory.js +0 -428
- package/src/bridge/core/bridge-factory.js.map +0 -1
- package/src/bridge/core/index.d.ts +0 -9
- package/src/bridge/core/index.js +0 -22
- package/src/bridge/core/index.js.map +0 -1
- package/src/bridge/index.d.ts +0 -61
- package/src/bridge/index.js +0 -94
- package/src/bridge/index.js.map +0 -1
- package/src/bridge/runtime/iife-generator.d.ts +0 -61
- package/src/bridge/runtime/iife-generator.js +0 -940
- package/src/bridge/runtime/iife-generator.js.map +0 -1
- package/src/bridge/runtime/index.d.ts +0 -8
- package/src/bridge/runtime/index.js +0 -16
- package/src/bridge/runtime/index.js.map +0 -1
- package/src/bridge/types.d.ts +0 -385
- package/src/bridge/types.js +0 -11
- package/src/bridge/types.js.map +0 -1
- package/src/build/cdn-resources.d.ts +0 -140
- package/src/build/cdn-resources.js +0 -314
- package/src/build/cdn-resources.js.map +0 -1
- package/src/build/index.d.ts +0 -294
- package/src/build/index.js +0 -325
- package/src/build/index.js.map +0 -1
- package/src/build/widget-manifest.d.ts +0 -212
- package/src/build/widget-manifest.js +0 -652
- package/src/build/widget-manifest.js.map +0 -1
- package/src/bundler/bundler.d.ts +0 -110
- package/src/bundler/bundler.js +0 -432
- package/src/bundler/bundler.js.map +0 -1
- package/src/bundler/cache.d.ts +0 -172
- package/src/bundler/cache.js +0 -250
- package/src/bundler/cache.js.map +0 -1
- package/src/bundler/index.d.ts +0 -41
- package/src/bundler/index.js +0 -73
- package/src/bundler/index.js.map +0 -1
- package/src/bundler/sandbox/enclave-adapter.d.ts +0 -120
- package/src/bundler/sandbox/enclave-adapter.js +0 -339
- package/src/bundler/sandbox/enclave-adapter.js.map +0 -1
- package/src/bundler/sandbox/executor.d.ts +0 -13
- package/src/bundler/sandbox/executor.js +0 -22
- package/src/bundler/sandbox/executor.js.map +0 -1
- package/src/bundler/sandbox/policy.d.ts +0 -61
- package/src/bundler/sandbox/policy.js +0 -238
- package/src/bundler/sandbox/policy.js.map +0 -1
- package/src/bundler/types.d.ts +0 -347
- package/src/bundler/types.js +0 -132
- package/src/bundler/types.js.map +0 -1
- package/src/components/alert.d.ts +0 -71
- package/src/components/alert.js +0 -189
- package/src/components/alert.js.map +0 -1
- package/src/components/alert.schema.d.ts +0 -114
- package/src/components/alert.schema.js +0 -105
- package/src/components/alert.schema.js.map +0 -1
- package/src/components/avatar.d.ts +0 -76
- package/src/components/avatar.js +0 -176
- package/src/components/avatar.js.map +0 -1
- package/src/components/avatar.schema.d.ts +0 -169
- package/src/components/avatar.schema.js +0 -103
- package/src/components/avatar.schema.js.map +0 -1
- package/src/components/badge.d.ts +0 -70
- package/src/components/badge.js +0 -149
- package/src/components/badge.js.map +0 -1
- package/src/components/badge.schema.d.ts +0 -109
- package/src/components/badge.schema.js +0 -96
- package/src/components/badge.schema.js.map +0 -1
- package/src/components/button.d.ts +0 -111
- package/src/components/button.js +0 -336
- package/src/components/button.js.map +0 -1
- package/src/components/button.schema.d.ts +0 -148
- package/src/components/button.schema.js +0 -121
- package/src/components/button.schema.js.map +0 -1
- package/src/components/card.d.ts +0 -60
- package/src/components/card.js +0 -117
- package/src/components/card.js.map +0 -1
- package/src/components/card.schema.d.ts +0 -113
- package/src/components/card.schema.js +0 -98
- package/src/components/card.schema.js.map +0 -1
- package/src/components/form.d.ts +0 -239
- package/src/components/form.js +0 -420
- package/src/components/form.js.map +0 -1
- package/src/components/form.schema.d.ts +0 -441
- package/src/components/form.schema.js +0 -406
- package/src/components/form.schema.js.map +0 -1
- package/src/components/index.d.ts +0 -29
- package/src/components/index.js +0 -98
- package/src/components/index.js.map +0 -1
- package/src/components/list.d.ts +0 -127
- package/src/components/list.js +0 -279
- package/src/components/list.js.map +0 -1
- package/src/components/list.schema.d.ts +0 -134
- package/src/components/list.schema.js +0 -168
- package/src/components/list.schema.js.map +0 -1
- package/src/components/modal.d.ts +0 -111
- package/src/components/modal.js +0 -260
- package/src/components/modal.js.map +0 -1
- package/src/components/modal.schema.d.ts +0 -186
- package/src/components/modal.schema.js +0 -167
- package/src/components/modal.schema.js.map +0 -1
- package/src/components/table.d.ts +0 -105
- package/src/components/table.js +0 -283
- package/src/components/table.js.map +0 -1
- package/src/components/table.schema.d.ts +0 -159
- package/src/components/table.schema.js +0 -173
- package/src/components/table.schema.js.map +0 -1
- package/src/handlebars/helpers.d.ts +0 -348
- package/src/handlebars/helpers.js +0 -605
- package/src/handlebars/helpers.js.map +0 -1
- package/src/handlebars/index.d.ts +0 -193
- package/src/handlebars/index.js +0 -350
- package/src/handlebars/index.js.map +0 -1
- package/src/index.d.ts +0 -50
- package/src/index.js +0 -192
- package/src/index.js.map +0 -1
- package/src/layouts/base.d.ts +0 -88
- package/src/layouts/base.js +0 -227
- package/src/layouts/base.js.map +0 -1
- package/src/layouts/index.d.ts +0 -7
- package/src/layouts/index.js +0 -25
- package/src/layouts/index.js.map +0 -1
- package/src/layouts/presets.d.ts +0 -133
- package/src/layouts/presets.js +0 -277
- package/src/layouts/presets.js.map +0 -1
- package/src/pages/consent.d.ts +0 -116
- package/src/pages/consent.js +0 -218
- package/src/pages/consent.js.map +0 -1
- package/src/pages/error.d.ts +0 -100
- package/src/pages/error.js +0 -263
- package/src/pages/error.js.map +0 -1
- package/src/pages/index.d.ts +0 -8
- package/src/pages/index.js +0 -27
- package/src/pages/index.js.map +0 -1
- package/src/react/Alert.d.ts +0 -101
- package/src/react/Alert.js +0 -51
- package/src/react/Alert.js.map +0 -1
- package/src/react/Badge.d.ts +0 -100
- package/src/react/Badge.js +0 -55
- package/src/react/Badge.js.map +0 -1
- package/src/react/Button.d.ts +0 -108
- package/src/react/Button.js +0 -52
- package/src/react/Button.js.map +0 -1
- package/src/react/Card.d.ts +0 -103
- package/src/react/Card.js +0 -55
- package/src/react/Card.js.map +0 -1
- package/src/react/hooks/context.d.ts +0 -178
- package/src/react/hooks/context.js +0 -287
- package/src/react/hooks/context.js.map +0 -1
- package/src/react/hooks/index.d.ts +0 -41
- package/src/react/hooks/index.js +0 -61
- package/src/react/hooks/index.js.map +0 -1
- package/src/react/hooks/tools.d.ts +0 -283
- package/src/react/hooks/tools.js +0 -465
- package/src/react/hooks/tools.js.map +0 -1
- package/src/react/index.d.ts +0 -80
- package/src/react/index.js +0 -113
- package/src/react/index.js.map +0 -1
- package/src/react/types.d.ts +0 -105
- package/src/react/types.js +0 -12
- package/src/react/types.js.map +0 -1
- package/src/react/utils.d.ts +0 -42
- package/src/react/utils.js +0 -99
- package/src/react/utils.js.map +0 -1
- package/src/registry/index.d.ts +0 -45
- package/src/registry/index.js +0 -67
- package/src/registry/index.js.map +0 -1
- package/src/registry/render-template.d.ts +0 -86
- package/src/registry/render-template.js +0 -239
- package/src/registry/render-template.js.map +0 -1
- package/src/registry/tool-ui.registry.d.ts +0 -260
- package/src/registry/tool-ui.registry.js +0 -438
- package/src/registry/tool-ui.registry.js.map +0 -1
- package/src/registry/uri-utils.d.ts +0 -55
- package/src/registry/uri-utils.js +0 -97
- package/src/registry/uri-utils.js.map +0 -1
- package/src/render/index.d.ts +0 -7
- package/src/render/index.js +0 -14
- package/src/render/index.js.map +0 -1
- package/src/render/prerender.d.ts +0 -56
- package/src/render/prerender.js +0 -98
- package/src/render/prerender.js.map +0 -1
- package/src/renderers/cache.d.ts +0 -144
- package/src/renderers/cache.js +0 -240
- package/src/renderers/cache.js.map +0 -1
- package/src/renderers/html.renderer.d.ts +0 -122
- package/src/renderers/html.renderer.js +0 -204
- package/src/renderers/html.renderer.js.map +0 -1
- package/src/renderers/index.d.ts +0 -35
- package/src/renderers/index.js +0 -70
- package/src/renderers/index.js.map +0 -1
- package/src/renderers/mdx.renderer.d.ts +0 -119
- package/src/renderers/mdx.renderer.js +0 -305
- package/src/renderers/mdx.renderer.js.map +0 -1
- package/src/renderers/react.renderer.d.ts +0 -95
- package/src/renderers/react.renderer.js +0 -260
- package/src/renderers/react.renderer.js.map +0 -1
- package/src/renderers/registry.d.ts +0 -133
- package/src/renderers/registry.js +0 -232
- package/src/renderers/registry.js.map +0 -1
- package/src/renderers/types.d.ts +0 -341
- package/src/renderers/types.js +0 -9
- package/src/renderers/types.js.map +0 -1
- package/src/renderers/utils/detect.d.ts +0 -106
- package/src/renderers/utils/detect.js +0 -267
- package/src/renderers/utils/detect.js.map +0 -1
- package/src/renderers/utils/hash.d.ts +0 -39
- package/src/renderers/utils/hash.js +0 -75
- package/src/renderers/utils/hash.js.map +0 -1
- package/src/renderers/utils/index.d.ts +0 -8
- package/src/renderers/utils/index.js +0 -28
- package/src/renderers/utils/index.js.map +0 -1
- package/src/renderers/utils/transpiler.d.ts +0 -88
- package/src/renderers/utils/transpiler.js +0 -215
- package/src/renderers/utils/transpiler.js.map +0 -1
- package/src/runtime/adapters/html.adapter.d.ts +0 -58
- package/src/runtime/adapters/html.adapter.js +0 -131
- package/src/runtime/adapters/html.adapter.js.map +0 -1
- package/src/runtime/adapters/index.d.ts +0 -25
- package/src/runtime/adapters/index.js +0 -54
- package/src/runtime/adapters/index.js.map +0 -1
- package/src/runtime/adapters/mdx.adapter.d.ts +0 -72
- package/src/runtime/adapters/mdx.adapter.js +0 -241
- package/src/runtime/adapters/mdx.adapter.js.map +0 -1
- package/src/runtime/adapters/react.adapter.d.ts +0 -69
- package/src/runtime/adapters/react.adapter.js +0 -245
- package/src/runtime/adapters/react.adapter.js.map +0 -1
- package/src/runtime/adapters/types.d.ts +0 -94
- package/src/runtime/adapters/types.js +0 -11
- package/src/runtime/adapters/types.js.map +0 -1
- package/src/runtime/csp.d.ts +0 -37
- package/src/runtime/csp.js +0 -140
- package/src/runtime/csp.js.map +0 -1
- package/src/runtime/index.d.ts +0 -16
- package/src/runtime/index.js +0 -72
- package/src/runtime/index.js.map +0 -1
- package/src/runtime/mcp-bridge.d.ts +0 -100
- package/src/runtime/mcp-bridge.js +0 -581
- package/src/runtime/mcp-bridge.js.map +0 -1
- package/src/runtime/renderer-runtime.d.ts +0 -132
- package/src/runtime/renderer-runtime.js +0 -389
- package/src/runtime/renderer-runtime.js.map +0 -1
- package/src/runtime/sanitizer.d.ts +0 -171
- package/src/runtime/sanitizer.js +0 -318
- package/src/runtime/sanitizer.js.map +0 -1
- package/src/runtime/types.d.ts +0 -414
- package/src/runtime/types.js +0 -12
- package/src/runtime/types.js.map +0 -1
- package/src/runtime/wrapper.d.ts +0 -375
- package/src/runtime/wrapper.js +0 -1793
- package/src/runtime/wrapper.js.map +0 -1
- package/src/styles/index.d.ts +0 -7
- package/src/styles/index.js +0 -11
- package/src/styles/index.js.map +0 -1
- package/src/styles/variants.d.ts +0 -50
- package/src/styles/variants.js +0 -175
- package/src/styles/variants.js.map +0 -1
- package/src/theme/cdn.d.ts +0 -194
- package/src/theme/cdn.js +0 -375
- package/src/theme/cdn.js.map +0 -1
- package/src/theme/index.d.ts +0 -17
- package/src/theme/index.js +0 -57
- package/src/theme/index.js.map +0 -1
- package/src/theme/platforms.d.ts +0 -106
- package/src/theme/platforms.js +0 -161
- package/src/theme/platforms.js.map +0 -1
- package/src/theme/presets/github-openai.d.ts +0 -49
- package/src/theme/presets/github-openai.js +0 -189
- package/src/theme/presets/github-openai.js.map +0 -1
- package/src/theme/presets/index.d.ts +0 -10
- package/src/theme/presets/index.js +0 -17
- package/src/theme/presets/index.js.map +0 -1
- package/src/theme/theme.d.ts +0 -395
- package/src/theme/theme.js +0 -332
- package/src/theme/theme.js.map +0 -1
- package/src/tool-template/builder.d.ts +0 -212
- package/src/tool-template/builder.js +0 -397
- package/src/tool-template/builder.js.map +0 -1
- package/src/tool-template/index.d.ts +0 -15
- package/src/tool-template/index.js +0 -38
- package/src/tool-template/index.js.map +0 -1
- package/src/types/index.d.ts +0 -13
- package/src/types/index.js +0 -26
- package/src/types/index.js.map +0 -1
- package/src/types/ui-config.d.ts +0 -357
- package/src/types/ui-config.js +0 -12
- package/src/types/ui-config.js.map +0 -1
- package/src/types/ui-runtime.d.ts +0 -965
- package/src/types/ui-runtime.js +0 -117
- package/src/types/ui-runtime.js.map +0 -1
- package/src/validation/error-box.d.ts +0 -55
- package/src/validation/error-box.js +0 -75
- package/src/validation/error-box.js.map +0 -1
- package/src/validation/index.d.ts +0 -12
- package/src/validation/index.js +0 -21
- package/src/validation/index.js.map +0 -1
- package/src/validation/wrapper.d.ts +0 -96
- package/src/validation/wrapper.js +0 -117
- package/src/validation/wrapper.js.map +0 -1
- package/src/web-components/core/attribute-parser.d.ts +0 -85
- package/src/web-components/core/attribute-parser.js +0 -189
- package/src/web-components/core/attribute-parser.js.map +0 -1
- package/src/web-components/core/base-element.d.ts +0 -197
- package/src/web-components/core/base-element.js +0 -289
- package/src/web-components/core/base-element.js.map +0 -1
- package/src/web-components/core/index.d.ts +0 -8
- package/src/web-components/core/index.js +0 -18
- package/src/web-components/core/index.js.map +0 -1
- package/src/web-components/elements/fmcp-alert.d.ts +0 -45
- package/src/web-components/elements/fmcp-alert.js +0 -93
- package/src/web-components/elements/fmcp-alert.js.map +0 -1
- package/src/web-components/elements/fmcp-badge.d.ts +0 -46
- package/src/web-components/elements/fmcp-badge.js +0 -99
- package/src/web-components/elements/fmcp-badge.js.map +0 -1
- package/src/web-components/elements/fmcp-button.d.ts +0 -124
- package/src/web-components/elements/fmcp-button.js +0 -233
- package/src/web-components/elements/fmcp-button.js.map +0 -1
- package/src/web-components/elements/fmcp-card.d.ts +0 -52
- package/src/web-components/elements/fmcp-card.js +0 -115
- package/src/web-components/elements/fmcp-card.js.map +0 -1
- package/src/web-components/elements/fmcp-input.d.ts +0 -95
- package/src/web-components/elements/fmcp-input.js +0 -248
- package/src/web-components/elements/fmcp-input.js.map +0 -1
- package/src/web-components/elements/fmcp-select.d.ts +0 -99
- package/src/web-components/elements/fmcp-select.js +0 -243
- package/src/web-components/elements/fmcp-select.js.map +0 -1
- package/src/web-components/elements/index.d.ts +0 -12
- package/src/web-components/elements/index.js +0 -34
- package/src/web-components/elements/index.js.map +0 -1
- package/src/web-components/index.d.ts +0 -49
- package/src/web-components/index.js +0 -75
- package/src/web-components/index.js.map +0 -1
- package/src/web-components/register.d.ts +0 -56
- package/src/web-components/register.js +0 -80
- package/src/web-components/register.js.map +0 -1
- package/src/web-components/types.d.ts +0 -121
- package/src/web-components/types.js +0 -25
- package/src/web-components/types.js.map +0 -1
- package/src/widgets/index.d.ts +0 -7
- package/src/widgets/index.js +0 -24
- package/src/widgets/index.js.map +0 -1
- package/src/widgets/progress.d.ts +0 -132
- package/src/widgets/progress.js +0 -303
- package/src/widgets/progress.js.map +0 -1
- package/src/widgets/resource.d.ts +0 -162
- package/src/widgets/resource.js +0 -340
- package/src/widgets/resource.js.map +0 -1
package/src/runtime/wrapper.js
DELETED
|
@@ -1,1793 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Tool UI Wrapper
|
|
4
|
-
*
|
|
5
|
-
* Wraps tool UI templates with the MCP Bridge runtime and
|
|
6
|
-
* integrates with the existing layout system for consistent styling.
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.createTemplateHelpers = createTemplateHelpers;
|
|
10
|
-
exports.wrapToolUI = wrapToolUI;
|
|
11
|
-
exports.wrapToolUIUniversal = wrapToolUIUniversal;
|
|
12
|
-
exports.wrapToolUIMinimal = wrapToolUIMinimal;
|
|
13
|
-
exports.wrapLeanWidgetShell = wrapLeanWidgetShell;
|
|
14
|
-
exports.wrapHybridWidgetShell = wrapHybridWidgetShell;
|
|
15
|
-
exports.wrapStaticWidgetUniversal = wrapStaticWidgetUniversal;
|
|
16
|
-
exports.buildOpenAIMeta = buildOpenAIMeta;
|
|
17
|
-
exports.getToolUIMimeType = getToolUIMimeType;
|
|
18
|
-
const mcp_bridge_1 = require("./mcp-bridge");
|
|
19
|
-
const csp_1 = require("./csp");
|
|
20
|
-
const theme_1 = require("../theme");
|
|
21
|
-
const base_1 = require("../layouts/base");
|
|
22
|
-
const sanitizer_1 = require("./sanitizer");
|
|
23
|
-
const iife_generator_1 = require("../bridge/runtime/iife-generator");
|
|
24
|
-
// ============================================
|
|
25
|
-
// Template Helpers Implementation
|
|
26
|
-
// ============================================
|
|
27
|
-
/**
|
|
28
|
-
* Create template helpers for use in template builder functions
|
|
29
|
-
*/
|
|
30
|
-
function createTemplateHelpers() {
|
|
31
|
-
let idCounter = 0;
|
|
32
|
-
return {
|
|
33
|
-
/**
|
|
34
|
-
* Escape HTML special characters to prevent XSS
|
|
35
|
-
*/
|
|
36
|
-
escapeHtml: base_1.escapeHtml,
|
|
37
|
-
/**
|
|
38
|
-
* Format a date for display
|
|
39
|
-
*/
|
|
40
|
-
formatDate: (date, format) => {
|
|
41
|
-
const d = typeof date === 'string' ? new Date(date) : date;
|
|
42
|
-
if (isNaN(d.getTime()))
|
|
43
|
-
return String(date);
|
|
44
|
-
if (format === 'iso') {
|
|
45
|
-
return d.toISOString();
|
|
46
|
-
}
|
|
47
|
-
if (format === 'time') {
|
|
48
|
-
return d.toLocaleTimeString();
|
|
49
|
-
}
|
|
50
|
-
if (format === 'datetime') {
|
|
51
|
-
return d.toLocaleString();
|
|
52
|
-
}
|
|
53
|
-
// Default: localized date
|
|
54
|
-
return d.toLocaleDateString();
|
|
55
|
-
},
|
|
56
|
-
/**
|
|
57
|
-
* Format a number as currency
|
|
58
|
-
*/
|
|
59
|
-
formatCurrency: (amount, currency = 'USD') => {
|
|
60
|
-
return new Intl.NumberFormat('en-US', {
|
|
61
|
-
style: 'currency',
|
|
62
|
-
currency,
|
|
63
|
-
}).format(amount);
|
|
64
|
-
},
|
|
65
|
-
/**
|
|
66
|
-
* Generate a unique ID for DOM elements
|
|
67
|
-
*/
|
|
68
|
-
uniqueId: (prefix = 'mcp') => {
|
|
69
|
-
return `${prefix}-${++idCounter}-${Date.now().toString(36)}`;
|
|
70
|
-
},
|
|
71
|
-
/**
|
|
72
|
-
* Safely embed JSON data in HTML
|
|
73
|
-
* Escapes characters that could break out of script tags or HTML
|
|
74
|
-
*/
|
|
75
|
-
jsonEmbed: (data) => {
|
|
76
|
-
// JSON.stringify returns undefined for undefined input, handle it
|
|
77
|
-
const json = JSON.stringify(data);
|
|
78
|
-
if (json === undefined) {
|
|
79
|
-
return 'undefined';
|
|
80
|
-
}
|
|
81
|
-
return json.replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026').replace(/'/g, '\\u0027');
|
|
82
|
-
},
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
// ============================================
|
|
86
|
-
// Main Wrapper Function
|
|
87
|
-
// ============================================
|
|
88
|
-
/**
|
|
89
|
-
* Wrap tool UI content in a complete HTML document with MCP Bridge runtime.
|
|
90
|
-
*
|
|
91
|
-
* This function creates a standalone HTML document that:
|
|
92
|
-
* - Includes the MCP Bridge runtime for cross-platform compatibility
|
|
93
|
-
* - Applies Content Security Policy meta tags
|
|
94
|
-
* - Injects tool input/output data
|
|
95
|
-
* - Uses the FrontMCP theme system for consistent styling
|
|
96
|
-
*
|
|
97
|
-
* @param options - Options for wrapping the template
|
|
98
|
-
* @returns Complete HTML document string
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* ```typescript
|
|
102
|
-
* const html = wrapToolUI({
|
|
103
|
-
* content: '<div class="p-4">Weather: 72°F</div>',
|
|
104
|
-
* toolName: 'get_weather',
|
|
105
|
-
* input: { location: 'San Francisco' },
|
|
106
|
-
* output: { temperature: 72, conditions: 'sunny' },
|
|
107
|
-
* csp: { connectDomains: ['https://api.weather.com'] },
|
|
108
|
-
* });
|
|
109
|
-
* ```
|
|
110
|
-
*/
|
|
111
|
-
function wrapToolUI(options) {
|
|
112
|
-
const { content, toolName, input = {}, output, structuredContent, csp, widgetAccessible = false, title, theme: themeOverrides, platform = theme_1.OPENAI_PLATFORM, hostContext, sanitizeInput: sanitizeOption, rendererType, hydrate = false, // Disabled by default to prevent React hydration Error #418 in MCP clients
|
|
113
|
-
skipCspMeta = false, } = options;
|
|
114
|
-
// Apply input sanitization if enabled
|
|
115
|
-
let sanitizedInput = input;
|
|
116
|
-
if (sanitizeOption) {
|
|
117
|
-
const sanitizeMode = sanitizeOption === true ? true : sanitizeOption;
|
|
118
|
-
sanitizedInput = (0, sanitizer_1.sanitizeInput)(input, sanitizeMode);
|
|
119
|
-
}
|
|
120
|
-
// Merge theme
|
|
121
|
-
const theme = themeOverrides ? (0, theme_1.mergeThemes)(theme_1.DEFAULT_THEME, themeOverrides) : theme_1.DEFAULT_THEME;
|
|
122
|
-
// Check CDN capabilities
|
|
123
|
-
const useCdn = (0, theme_1.canUseCdn)(platform);
|
|
124
|
-
const useInline = (0, theme_1.needsInlineScripts)(platform);
|
|
125
|
-
// Build font links (skip for blocked network)
|
|
126
|
-
const fontPreconnect = useCdn ? (0, theme_1.buildFontPreconnect)() : '';
|
|
127
|
-
const fontStylesheets = useCdn ? (0, theme_1.buildFontStylesheets)({ inter: true }) : '';
|
|
128
|
-
// Build scripts (Tailwind only - no HTMX needed for basic widgets)
|
|
129
|
-
const scripts = (0, theme_1.buildCdnScripts)({
|
|
130
|
-
tailwind: platform.supportsTailwind,
|
|
131
|
-
htmx: false,
|
|
132
|
-
alpine: false,
|
|
133
|
-
icons: false,
|
|
134
|
-
inline: useInline,
|
|
135
|
-
});
|
|
136
|
-
// Build framework runtime scripts (React/MDX)
|
|
137
|
-
const frameworkScripts = buildFrameworkRuntimeScripts({
|
|
138
|
-
rendererType,
|
|
139
|
-
hydrate,
|
|
140
|
-
platform,
|
|
141
|
-
});
|
|
142
|
-
// Build theme CSS
|
|
143
|
-
const themeCss = (0, theme_1.buildThemeCss)(theme);
|
|
144
|
-
const customCss = theme.customCss || '';
|
|
145
|
-
// Build Tailwind style block
|
|
146
|
-
const styleBlock = platform.supportsTailwind
|
|
147
|
-
? `<style type="text/tailwindcss">
|
|
148
|
-
@theme {
|
|
149
|
-
${themeCss}
|
|
150
|
-
}
|
|
151
|
-
${customCss}
|
|
152
|
-
</style>`
|
|
153
|
-
: '';
|
|
154
|
-
// Build CSP meta tag (skip for platforms like OpenAI that handle CSP via _meta)
|
|
155
|
-
const cspMetaTag = skipCspMeta ? '' : (0, csp_1.buildCSPMetaTag)(csp);
|
|
156
|
-
// Build data injection script
|
|
157
|
-
const dataScript = buildDataInjectionScript({
|
|
158
|
-
toolName,
|
|
159
|
-
input: sanitizedInput,
|
|
160
|
-
output,
|
|
161
|
-
structuredContent,
|
|
162
|
-
widgetAccessible,
|
|
163
|
-
hostContext,
|
|
164
|
-
});
|
|
165
|
-
// Page title
|
|
166
|
-
const pageTitle = title || `${(0, base_1.escapeHtml)(toolName)} - Tool Result`;
|
|
167
|
-
return `<!DOCTYPE html>
|
|
168
|
-
<html lang="en">
|
|
169
|
-
<head>
|
|
170
|
-
<meta charset="UTF-8">
|
|
171
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
172
|
-
<title>${pageTitle}</title>
|
|
173
|
-
${cspMetaTag}
|
|
174
|
-
|
|
175
|
-
<!-- Fonts -->
|
|
176
|
-
${fontPreconnect}
|
|
177
|
-
${fontStylesheets}
|
|
178
|
-
|
|
179
|
-
<!-- Tailwind CSS -->
|
|
180
|
-
${scripts}
|
|
181
|
-
${styleBlock}
|
|
182
|
-
|
|
183
|
-
<!-- Framework Runtime -->
|
|
184
|
-
${frameworkScripts}
|
|
185
|
-
|
|
186
|
-
<!-- Tool Data -->
|
|
187
|
-
${dataScript}
|
|
188
|
-
|
|
189
|
-
<!-- MCP Bridge Runtime -->
|
|
190
|
-
${mcp_bridge_1.MCP_BRIDGE_RUNTIME}
|
|
191
|
-
</head>
|
|
192
|
-
<body class="bg-background text-text-primary font-sans antialiased">
|
|
193
|
-
${content}
|
|
194
|
-
</body>
|
|
195
|
-
</html>`;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Build framework-specific runtime scripts (React, MDX).
|
|
199
|
-
* Only included when using React/MDX renderers with hydration enabled.
|
|
200
|
-
*/
|
|
201
|
-
function buildFrameworkRuntimeScripts(options) {
|
|
202
|
-
const { rendererType, hydrate, platform } = options;
|
|
203
|
-
// No framework scripts needed for HTML templates
|
|
204
|
-
if (!rendererType || rendererType === 'html' || rendererType === 'html-fallback') {
|
|
205
|
-
return '';
|
|
206
|
-
}
|
|
207
|
-
// Only include runtime if hydration is enabled
|
|
208
|
-
if (!hydrate) {
|
|
209
|
-
return '';
|
|
210
|
-
}
|
|
211
|
-
// React/MDX both need React runtime for hydration
|
|
212
|
-
if (rendererType === 'react' || rendererType === 'mdx') {
|
|
213
|
-
const useCdn = (0, theme_1.canUseCdn)(platform);
|
|
214
|
-
if (useCdn) {
|
|
215
|
-
// Use CDN for platforms with network access
|
|
216
|
-
return `
|
|
217
|
-
<!-- React Runtime (for hydration) -->
|
|
218
|
-
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
|
219
|
-
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
|
220
|
-
<script>
|
|
221
|
-
// Hydration script for React/MDX components
|
|
222
|
-
(function() {
|
|
223
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
224
|
-
var hydratables = document.querySelectorAll('[data-hydrate], [data-mdx-hydrate]');
|
|
225
|
-
if (hydratables.length > 0 && window.__frontmcp_components) {
|
|
226
|
-
hydratables.forEach(function(el) {
|
|
227
|
-
var componentName = el.getAttribute('data-hydrate');
|
|
228
|
-
var propsJson = el.getAttribute('data-props');
|
|
229
|
-
var props = propsJson ? JSON.parse(propsJson) : {};
|
|
230
|
-
|
|
231
|
-
if (window.__frontmcp_components[componentName]) {
|
|
232
|
-
try {
|
|
233
|
-
ReactDOM.hydrateRoot(el, React.createElement(
|
|
234
|
-
window.__frontmcp_components[componentName],
|
|
235
|
-
props
|
|
236
|
-
));
|
|
237
|
-
} catch (e) {
|
|
238
|
-
console.error('[FrontMCP] Hydration failed:', e);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
})();
|
|
245
|
-
</script>`;
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
// For blocked-network platforms, SSR only (no hydration)
|
|
249
|
-
return `
|
|
250
|
-
<!-- React hydration not available on blocked-network platforms -->
|
|
251
|
-
<script>
|
|
252
|
-
console.warn('[FrontMCP] React hydration disabled - platform does not support external scripts');
|
|
253
|
-
</script>`;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return '';
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Build the data injection script that sets up globals before MCP Bridge runs
|
|
260
|
-
*/
|
|
261
|
-
function buildDataInjectionScript(options) {
|
|
262
|
-
const { toolName, input, output, structuredContent, widgetAccessible, hostContext } = options;
|
|
263
|
-
const helpers = createTemplateHelpers();
|
|
264
|
-
// Build the context object
|
|
265
|
-
const contextData = {
|
|
266
|
-
theme: hostContext?.theme || 'light',
|
|
267
|
-
displayMode: hostContext?.displayMode || 'inline',
|
|
268
|
-
...hostContext,
|
|
269
|
-
};
|
|
270
|
-
return `<script>
|
|
271
|
-
// Tool metadata
|
|
272
|
-
window.__mcpToolName = ${helpers.jsonEmbed(toolName)};
|
|
273
|
-
window.__mcpToolInput = ${helpers.jsonEmbed(input)};
|
|
274
|
-
window.__mcpToolOutput = ${helpers.jsonEmbed(output)};
|
|
275
|
-
window.__mcpStructuredContent = ${helpers.jsonEmbed(structuredContent)};
|
|
276
|
-
window.__mcpWidgetAccessible = ${helpers.jsonEmbed(widgetAccessible)};
|
|
277
|
-
window.__mcpHostContext = ${helpers.jsonEmbed(contextData)};
|
|
278
|
-
</script>`;
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Wrap tool UI content in a universal HTML document.
|
|
282
|
-
*
|
|
283
|
-
* This wrapper produces HTML that works on ALL platforms:
|
|
284
|
-
* - OpenAI ChatGPT (Apps SDK)
|
|
285
|
-
* - Anthropic Claude
|
|
286
|
-
* - MCP Apps (ext-apps / SEP-1865)
|
|
287
|
-
* - Google Gemini
|
|
288
|
-
* - Any MCP-compatible host
|
|
289
|
-
*
|
|
290
|
-
* The FrontMCP Bridge auto-detects the host at runtime and adapts
|
|
291
|
-
* its communication protocol accordingly.
|
|
292
|
-
*
|
|
293
|
-
* @param options - Universal wrapper options
|
|
294
|
-
* @returns Complete HTML document string
|
|
295
|
-
*
|
|
296
|
-
* @example
|
|
297
|
-
* ```typescript
|
|
298
|
-
* const html = wrapToolUIUniversal({
|
|
299
|
-
* content: '<div class="p-4">Weather: 72°F</div>',
|
|
300
|
-
* toolName: 'get_weather',
|
|
301
|
-
* output: { temperature: 72 },
|
|
302
|
-
* });
|
|
303
|
-
* ```
|
|
304
|
-
*/
|
|
305
|
-
function wrapToolUIUniversal(options) {
|
|
306
|
-
const { content, toolName, input = {}, output, structuredContent, csp, widgetAccessible = false, title, theme: themeOverrides, includeBridge = true, inlineScripts = false, rendererType, hydrate = false, // Disabled by default to prevent React hydration Error #418 in MCP clients
|
|
307
|
-
skipCspMeta = false, resourceMode = inlineScripts ? 'inline' : 'cdn', } = options;
|
|
308
|
-
// Determine if we should use inline scripts based on resourceMode
|
|
309
|
-
const useInlineScripts = resourceMode === 'inline' || inlineScripts;
|
|
310
|
-
// Merge theme
|
|
311
|
-
const theme = themeOverrides ? (0, theme_1.mergeThemes)(theme_1.DEFAULT_THEME, themeOverrides) : theme_1.DEFAULT_THEME;
|
|
312
|
-
// Build font links (skip for inline mode / blocked network)
|
|
313
|
-
const fontPreconnect = useInlineScripts ? '' : (0, theme_1.buildFontPreconnect)();
|
|
314
|
-
const fontStylesheets = useInlineScripts ? '' : (0, theme_1.buildFontStylesheets)({ inter: true });
|
|
315
|
-
// Build CDN scripts
|
|
316
|
-
const scripts = (0, theme_1.buildCdnScripts)({
|
|
317
|
-
tailwind: true,
|
|
318
|
-
htmx: false,
|
|
319
|
-
alpine: false,
|
|
320
|
-
icons: false,
|
|
321
|
-
inline: useInlineScripts,
|
|
322
|
-
});
|
|
323
|
-
// Build theme CSS
|
|
324
|
-
const themeCss = (0, theme_1.buildThemeCss)(theme);
|
|
325
|
-
const customCss = theme.customCss || '';
|
|
326
|
-
// Build Tailwind style block
|
|
327
|
-
const styleBlock = `<style type="text/tailwindcss">
|
|
328
|
-
@theme {
|
|
329
|
-
${themeCss}
|
|
330
|
-
}
|
|
331
|
-
${customCss}
|
|
332
|
-
</style>`;
|
|
333
|
-
// Build CSP meta tag (skip for platforms like OpenAI that handle CSP via _meta)
|
|
334
|
-
const cspMetaTag = skipCspMeta ? '' : (0, csp_1.buildCSPMetaTag)(csp);
|
|
335
|
-
// Build data injection script
|
|
336
|
-
const dataScript = buildDataInjectionScript({
|
|
337
|
-
toolName,
|
|
338
|
-
input,
|
|
339
|
-
output,
|
|
340
|
-
structuredContent,
|
|
341
|
-
widgetAccessible,
|
|
342
|
-
});
|
|
343
|
-
// Build framework runtime (for React/MDX hydration)
|
|
344
|
-
// When resourceMode is 'cdn', we use CDN URLs for React/ReactDOM
|
|
345
|
-
const frameworkScripts = buildFrameworkRuntimeScriptsUniversal({
|
|
346
|
-
rendererType,
|
|
347
|
-
hydrate,
|
|
348
|
-
inlineScripts: useInlineScripts,
|
|
349
|
-
resourceMode,
|
|
350
|
-
});
|
|
351
|
-
// Universal bridge script (works on all platforms)
|
|
352
|
-
const bridgeScript = includeBridge ? iife_generator_1.BRIDGE_SCRIPT_TAGS.universal : '';
|
|
353
|
-
// Page title
|
|
354
|
-
const pageTitle = title || `${(0, base_1.escapeHtml)(toolName)} - Tool Result`;
|
|
355
|
-
return `<!DOCTYPE html>
|
|
356
|
-
<html lang="en">
|
|
357
|
-
<head>
|
|
358
|
-
<meta charset="UTF-8">
|
|
359
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
360
|
-
<title>${pageTitle}</title>
|
|
361
|
-
${cspMetaTag}
|
|
362
|
-
|
|
363
|
-
<!-- Fonts -->
|
|
364
|
-
${fontPreconnect}
|
|
365
|
-
${fontStylesheets}
|
|
366
|
-
|
|
367
|
-
<!-- Tailwind CSS -->
|
|
368
|
-
${scripts}
|
|
369
|
-
${styleBlock}
|
|
370
|
-
|
|
371
|
-
<!-- Framework Runtime -->
|
|
372
|
-
${frameworkScripts}
|
|
373
|
-
|
|
374
|
-
<!-- Tool Data -->
|
|
375
|
-
${dataScript}
|
|
376
|
-
|
|
377
|
-
<!-- FrontMCP Bridge (Universal - Auto-detects host platform) -->
|
|
378
|
-
${bridgeScript}
|
|
379
|
-
</head>
|
|
380
|
-
<body class="bg-background text-text-primary font-sans antialiased">
|
|
381
|
-
${content}
|
|
382
|
-
</body>
|
|
383
|
-
</html>`;
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Build framework runtime scripts for universal wrapper.
|
|
387
|
-
* Supports both CDN mode (lightweight URLs) and inline mode (embedded scripts).
|
|
388
|
-
*/
|
|
389
|
-
function buildFrameworkRuntimeScriptsUniversal(options) {
|
|
390
|
-
const { rendererType, hydrate, inlineScripts, resourceMode = 'cdn' } = options;
|
|
391
|
-
// No framework scripts needed for HTML templates
|
|
392
|
-
if (!rendererType || rendererType === 'html' || rendererType === 'html-fallback') {
|
|
393
|
-
return '';
|
|
394
|
-
}
|
|
395
|
-
// Determine if we're using inline scripts
|
|
396
|
-
const useInline = resourceMode === 'inline' || inlineScripts;
|
|
397
|
-
// React/MDX both need React runtime
|
|
398
|
-
// Include scripts when:
|
|
399
|
-
// 1. Using CDN mode (resourceMode === 'cdn') - scripts are lightweight
|
|
400
|
-
// 2. Hydration is enabled (for client-side interaction)
|
|
401
|
-
if (rendererType === 'react' || rendererType === 'mdx') {
|
|
402
|
-
if (!useInline) {
|
|
403
|
-
// CDN mode: Use ES modules from esm.sh for React 19
|
|
404
|
-
const reactScripts = `
|
|
405
|
-
<!-- React 19 Runtime (ES modules from esm.sh) -->
|
|
406
|
-
<script type="module">
|
|
407
|
-
import React from 'https://esm.sh/react@19';
|
|
408
|
-
import { createRoot } from 'https://esm.sh/react-dom@19/client';
|
|
409
|
-
window.React = React;
|
|
410
|
-
window.ReactDOM = { createRoot };
|
|
411
|
-
</script>`;
|
|
412
|
-
// Add MDX runtime if needed
|
|
413
|
-
const mdxScripts = rendererType === 'mdx'
|
|
414
|
-
? `
|
|
415
|
-
<!-- MDX Runtime (CDN mode) -->
|
|
416
|
-
<script type="module">
|
|
417
|
-
import * as runtime from 'https://esm.sh/@mdx-js/react@3?bundle';
|
|
418
|
-
window.MDXRuntime = runtime;
|
|
419
|
-
</script>`
|
|
420
|
-
: '';
|
|
421
|
-
// Add hydration script if hydration is enabled
|
|
422
|
-
const hydrationScript = hydrate
|
|
423
|
-
? `
|
|
424
|
-
<script>
|
|
425
|
-
// Hydration script for React/MDX components
|
|
426
|
-
(function() {
|
|
427
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
428
|
-
var hydratables = document.querySelectorAll('[data-hydrate], [data-mdx-hydrate]');
|
|
429
|
-
if (hydratables.length > 0 && window.__frontmcp_components) {
|
|
430
|
-
hydratables.forEach(function(el) {
|
|
431
|
-
var componentName = el.getAttribute('data-hydrate');
|
|
432
|
-
var propsJson = el.getAttribute('data-props');
|
|
433
|
-
var props = propsJson ? JSON.parse(propsJson) : {};
|
|
434
|
-
|
|
435
|
-
if (window.__frontmcp_components[componentName]) {
|
|
436
|
-
try {
|
|
437
|
-
ReactDOM.hydrateRoot(el, React.createElement(
|
|
438
|
-
window.__frontmcp_components[componentName],
|
|
439
|
-
props
|
|
440
|
-
));
|
|
441
|
-
} catch (e) {
|
|
442
|
-
console.error('[FrontMCP] Hydration failed:', e);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
});
|
|
448
|
-
})();
|
|
449
|
-
</script>`
|
|
450
|
-
: '';
|
|
451
|
-
return reactScripts + mdxScripts + hydrationScript;
|
|
452
|
-
}
|
|
453
|
-
else {
|
|
454
|
-
// Inline mode: Scripts must be embedded in HTML (for blocked-network environments)
|
|
455
|
-
// Currently not implemented - would require fetching and caching React at build time
|
|
456
|
-
return `
|
|
457
|
-
<!-- React/MDX runtime disabled (inline/blocked-network mode) -->
|
|
458
|
-
<script>
|
|
459
|
-
console.warn('[FrontMCP] React/MDX runtime disabled - inline scripts mode (network blocked). SSR content is static.');
|
|
460
|
-
</script>`;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
return '';
|
|
464
|
-
}
|
|
465
|
-
// ============================================
|
|
466
|
-
// Minimal Wrapper (No Theme)
|
|
467
|
-
// ============================================
|
|
468
|
-
/**
|
|
469
|
-
* Wrap tool UI content with minimal boilerplate.
|
|
470
|
-
* Use this when you need to control all styling yourself.
|
|
471
|
-
*
|
|
472
|
-
* @param options - Minimal wrapper options
|
|
473
|
-
* @returns HTML document string
|
|
474
|
-
*/
|
|
475
|
-
function wrapToolUIMinimal(options) {
|
|
476
|
-
const { content, toolName, input = {}, output, structuredContent, csp, widgetAccessible = false, title, skipCspMeta = false, } = options;
|
|
477
|
-
const helpers = createTemplateHelpers();
|
|
478
|
-
// Build CSP meta tag (skip for platforms like OpenAI that handle CSP via _meta)
|
|
479
|
-
const cspMetaTag = skipCspMeta ? '' : (0, csp_1.buildCSPMetaTag)(csp);
|
|
480
|
-
// Build data injection
|
|
481
|
-
const contextData = { theme: 'light', displayMode: 'inline' };
|
|
482
|
-
const dataScript = `<script>
|
|
483
|
-
window.__mcpToolName = ${helpers.jsonEmbed(toolName)};
|
|
484
|
-
window.__mcpToolInput = ${helpers.jsonEmbed(input)};
|
|
485
|
-
window.__mcpToolOutput = ${helpers.jsonEmbed(output)};
|
|
486
|
-
window.__mcpStructuredContent = ${helpers.jsonEmbed(structuredContent)};
|
|
487
|
-
window.__mcpWidgetAccessible = ${helpers.jsonEmbed(widgetAccessible)};
|
|
488
|
-
window.__mcpHostContext = ${helpers.jsonEmbed(contextData)};
|
|
489
|
-
</script>`;
|
|
490
|
-
const pageTitle = title || `${(0, base_1.escapeHtml)(toolName)} - Tool Result`;
|
|
491
|
-
return `<!DOCTYPE html>
|
|
492
|
-
<html lang="en">
|
|
493
|
-
<head>
|
|
494
|
-
<meta charset="UTF-8">
|
|
495
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
496
|
-
<title>${pageTitle}</title>
|
|
497
|
-
${cspMetaTag}
|
|
498
|
-
${dataScript}
|
|
499
|
-
${mcp_bridge_1.MCP_BRIDGE_RUNTIME}
|
|
500
|
-
</head>
|
|
501
|
-
<body>
|
|
502
|
-
${content}
|
|
503
|
-
</body>
|
|
504
|
-
</html>`;
|
|
505
|
-
}
|
|
506
|
-
/**
|
|
507
|
-
* Create a lean widget shell for inline mode resourceTemplate.
|
|
508
|
-
*
|
|
509
|
-
* This is a minimal HTML document with:
|
|
510
|
-
* - HTML structure with theme CSS and fonts
|
|
511
|
-
* - A placeholder/loading message while waiting for tool response
|
|
512
|
-
* - FrontMCP Bridge for platform-agnostic communication
|
|
513
|
-
* - Injector script that detects ui/html in tool response and replaces the document
|
|
514
|
-
*
|
|
515
|
-
* NO React runtime, NO component code - the actual React widget comes
|
|
516
|
-
* in each tool response via _meta['ui/html'] and is injected by this shell.
|
|
517
|
-
*
|
|
518
|
-
* OpenAI caches this at discovery time. When a tool executes:
|
|
519
|
-
* 1. Tool returns full widget HTML in _meta['ui/html']
|
|
520
|
-
* 2. OpenAI injects this into window.openai.toolResponseMetadata['ui/html']
|
|
521
|
-
* 3. The bridge detects this and calls the injector callback
|
|
522
|
-
* 4. Injector replaces the entire document with the full React widget
|
|
523
|
-
*
|
|
524
|
-
* @param options - Lean widget options
|
|
525
|
-
* @returns Minimal HTML document string with bridge and injector
|
|
526
|
-
*/
|
|
527
|
-
function wrapLeanWidgetShell(options) {
|
|
528
|
-
const { toolName, uiConfig, title, theme: themeOverrides } = options;
|
|
529
|
-
// Merge theme
|
|
530
|
-
const theme = themeOverrides ? (0, theme_1.mergeThemes)(theme_1.DEFAULT_THEME, themeOverrides) : theme_1.DEFAULT_THEME;
|
|
531
|
-
// Build font links
|
|
532
|
-
const fontPreconnect = (0, theme_1.buildFontPreconnect)();
|
|
533
|
-
const fontStylesheets = (0, theme_1.buildFontStylesheets)({ inter: true });
|
|
534
|
-
// Build CDN scripts (only Tailwind for styling)
|
|
535
|
-
const tailwindScript = (0, theme_1.buildCdnScripts)({
|
|
536
|
-
tailwind: true,
|
|
537
|
-
htmx: false,
|
|
538
|
-
alpine: false,
|
|
539
|
-
icons: false,
|
|
540
|
-
inline: false,
|
|
541
|
-
});
|
|
542
|
-
// Build theme CSS
|
|
543
|
-
const themeCss = (0, theme_1.buildThemeCss)(theme);
|
|
544
|
-
const customCss = theme.customCss || '';
|
|
545
|
-
// Build Tailwind style block
|
|
546
|
-
const styleBlock = `<style type="text/tailwindcss">
|
|
547
|
-
@theme {
|
|
548
|
-
${themeCss}
|
|
549
|
-
}
|
|
550
|
-
${customCss}
|
|
551
|
-
</style>`;
|
|
552
|
-
// Placeholder content with loading indicator
|
|
553
|
-
const placeholderContent = `
|
|
554
|
-
<div id="frontmcp-widget-root" class="flex items-center justify-center min-h-[200px] p-4">
|
|
555
|
-
<div class="text-center text-gray-500">
|
|
556
|
-
<svg class="animate-spin mx-auto mb-2" style="width: 1.5rem; height: 1.5rem; color: #9ca3af;" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
557
|
-
<circle style="opacity: 0.25;" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
558
|
-
<path style="opacity: 0.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>
|
|
559
|
-
</svg>
|
|
560
|
-
<p class="text-sm">Loading widget...</p>
|
|
561
|
-
</div>
|
|
562
|
-
</div>
|
|
563
|
-
`;
|
|
564
|
-
// Tool metadata script
|
|
565
|
-
const toolMetaScript = `<script>
|
|
566
|
-
// Lean widget shell for inline mode
|
|
567
|
-
// Actual widget content comes in tool response via ui/html
|
|
568
|
-
window.__mcpToolName = ${JSON.stringify(toolName)};
|
|
569
|
-
window.__mcpWidgetAccessible = ${JSON.stringify(uiConfig.widgetAccessible ?? false)};
|
|
570
|
-
window.__mcpLeanShell = true;
|
|
571
|
-
</script>`;
|
|
572
|
-
// FrontMCP Bridge script (platform-agnostic)
|
|
573
|
-
const bridgeScript = iife_generator_1.BRIDGE_SCRIPT_TAGS.universal;
|
|
574
|
-
// Injector script that uses the bridge to detect and inject ui/html
|
|
575
|
-
const injectorScript = `<script>
|
|
576
|
-
// Lean shell injector for inline mode
|
|
577
|
-
// Uses FrontMCP Bridge (platform-agnostic) to detect tool response HTML
|
|
578
|
-
(function() {
|
|
579
|
-
var injected = false;
|
|
580
|
-
|
|
581
|
-
function injectWidget(metadata) {
|
|
582
|
-
if (injected) return;
|
|
583
|
-
|
|
584
|
-
// Check for ui/html in metadata
|
|
585
|
-
var html = null;
|
|
586
|
-
|
|
587
|
-
if (metadata) {
|
|
588
|
-
// Try different possible locations for the HTML
|
|
589
|
-
html = metadata['ui/html'] || metadata['openai/html'] || metadata.html;
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
if (html && typeof html === 'string') {
|
|
593
|
-
injected = true;
|
|
594
|
-
console.log('[FrontMCP] Lean shell: Injecting inline widget HTML (' + html.length + ' chars)');
|
|
595
|
-
|
|
596
|
-
// Replace entire document with the full React widget HTML
|
|
597
|
-
document.open();
|
|
598
|
-
document.write(html);
|
|
599
|
-
document.close();
|
|
600
|
-
return true;
|
|
601
|
-
}
|
|
602
|
-
return false;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
// Wait for bridge to be ready, then subscribe
|
|
606
|
-
function subscribeAndInject() {
|
|
607
|
-
var bridge = window.FrontMcpBridge;
|
|
608
|
-
if (!bridge) {
|
|
609
|
-
console.warn('[FrontMCP] Lean shell: Bridge not found');
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// Check if data already available (via getToolResponseMetadata)
|
|
614
|
-
if (typeof bridge.getToolResponseMetadata === 'function') {
|
|
615
|
-
var existing = bridge.getToolResponseMetadata();
|
|
616
|
-
if (existing && injectWidget(existing)) {
|
|
617
|
-
return; // Already injected
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// Subscribe to metadata changes (via onToolResponseMetadata)
|
|
622
|
-
if (typeof bridge.onToolResponseMetadata === 'function') {
|
|
623
|
-
console.log('[FrontMCP] Lean shell: Subscribing to tool response metadata');
|
|
624
|
-
bridge.onToolResponseMetadata(function(metadata) {
|
|
625
|
-
console.log('[FrontMCP] Lean shell: Received tool response metadata');
|
|
626
|
-
injectWidget(metadata);
|
|
627
|
-
});
|
|
628
|
-
} else {
|
|
629
|
-
console.warn('[FrontMCP] Lean shell: onToolResponseMetadata not available on bridge');
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// Wait for bridge:ready event
|
|
634
|
-
window.addEventListener('bridge:ready', function() {
|
|
635
|
-
console.log('[FrontMCP] Lean shell: Bridge ready, setting up injector');
|
|
636
|
-
subscribeAndInject();
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
// Also try immediately in case bridge is already ready
|
|
640
|
-
if (window.FrontMcpBridge && window.FrontMcpBridge.initialized) {
|
|
641
|
-
subscribeAndInject();
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
// Fallback: poll for bridge if event doesn't fire
|
|
645
|
-
var bridgeCheckAttempts = 0;
|
|
646
|
-
var bridgeCheckInterval = setInterval(function() {
|
|
647
|
-
bridgeCheckAttempts++;
|
|
648
|
-
if (window.FrontMcpBridge) {
|
|
649
|
-
clearInterval(bridgeCheckInterval);
|
|
650
|
-
if (!injected) {
|
|
651
|
-
subscribeAndInject();
|
|
652
|
-
}
|
|
653
|
-
} else if (bridgeCheckAttempts >= 100) {
|
|
654
|
-
// 10 second timeout
|
|
655
|
-
clearInterval(bridgeCheckInterval);
|
|
656
|
-
console.warn('[FrontMCP] Lean shell: Timeout waiting for bridge');
|
|
657
|
-
}
|
|
658
|
-
}, 100);
|
|
659
|
-
})();
|
|
660
|
-
</script>`;
|
|
661
|
-
// Spinner animation CSS
|
|
662
|
-
const spinnerCss = `<style>
|
|
663
|
-
@keyframes spin { to { transform: rotate(360deg); } }
|
|
664
|
-
.animate-spin { animation: spin 1s linear infinite; }
|
|
665
|
-
</style>`;
|
|
666
|
-
return `<!DOCTYPE html>
|
|
667
|
-
<html lang="en">
|
|
668
|
-
<head>
|
|
669
|
-
<meta charset="UTF-8">
|
|
670
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
671
|
-
<title>${(0, base_1.escapeHtml)(title || toolName)}</title>
|
|
672
|
-
${fontPreconnect}
|
|
673
|
-
${fontStylesheets}
|
|
674
|
-
${tailwindScript}
|
|
675
|
-
${styleBlock}
|
|
676
|
-
${spinnerCss}
|
|
677
|
-
${toolMetaScript}
|
|
678
|
-
${bridgeScript}
|
|
679
|
-
</head>
|
|
680
|
-
<body class="bg-white font-sans antialiased">
|
|
681
|
-
${placeholderContent}
|
|
682
|
-
${injectorScript}
|
|
683
|
-
</body>
|
|
684
|
-
</html>`;
|
|
685
|
-
}
|
|
686
|
-
/**
|
|
687
|
-
* Create a hybrid widget shell for hybrid serving mode.
|
|
688
|
-
*
|
|
689
|
-
* This shell contains:
|
|
690
|
-
* - React 19 runtime from esm.sh CDN
|
|
691
|
-
* - FrontMCP Bridge for platform-agnostic communication
|
|
692
|
-
* - All FrontMCP hooks (useMcpBridgeContext, useToolOutput, useCallTool, etc.)
|
|
693
|
-
* - All FrontMCP UI components (Card, Badge, Button)
|
|
694
|
-
* - Dynamic renderer that imports and renders component code at runtime
|
|
695
|
-
*
|
|
696
|
-
* NO component code is included - it comes in the tool response via `_meta['ui/component']`.
|
|
697
|
-
*
|
|
698
|
-
* Flow:
|
|
699
|
-
* 1. Shell is cached at tools/list (OpenAI caches outputTemplate)
|
|
700
|
-
* 2. Tool response contains component code + structured data
|
|
701
|
-
* 3. Shell imports component via blob URL and renders with data
|
|
702
|
-
* 4. Re-renders on data updates via bridge notifications
|
|
703
|
-
*
|
|
704
|
-
* @param options - Hybrid widget shell options
|
|
705
|
-
* @returns Complete HTML document string with dynamic renderer
|
|
706
|
-
*/
|
|
707
|
-
function wrapHybridWidgetShell(options) {
|
|
708
|
-
const { toolName, uiConfig, title, theme: themeOverrides } = options;
|
|
709
|
-
// Merge theme
|
|
710
|
-
const theme = themeOverrides ? (0, theme_1.mergeThemes)(theme_1.DEFAULT_THEME, themeOverrides) : theme_1.DEFAULT_THEME;
|
|
711
|
-
// Build font links
|
|
712
|
-
const fontPreconnect = (0, theme_1.buildFontPreconnect)();
|
|
713
|
-
const fontStylesheets = (0, theme_1.buildFontStylesheets)({ inter: true });
|
|
714
|
-
// Build CDN scripts (Tailwind for styling)
|
|
715
|
-
const tailwindScript = (0, theme_1.buildCdnScripts)({
|
|
716
|
-
tailwind: true,
|
|
717
|
-
htmx: false,
|
|
718
|
-
alpine: false,
|
|
719
|
-
icons: false,
|
|
720
|
-
inline: false,
|
|
721
|
-
});
|
|
722
|
-
// Build theme CSS
|
|
723
|
-
const themeCss = (0, theme_1.buildThemeCss)(theme);
|
|
724
|
-
const customCss = theme.customCss || '';
|
|
725
|
-
// Build Tailwind style block
|
|
726
|
-
const styleBlock = `<style type="text/tailwindcss">
|
|
727
|
-
@theme {
|
|
728
|
-
${themeCss}
|
|
729
|
-
}
|
|
730
|
-
${customCss}
|
|
731
|
-
</style>`;
|
|
732
|
-
// Loading placeholder content
|
|
733
|
-
const placeholderContent = `
|
|
734
|
-
<div id="frontmcp-widget-root" class="flex items-center justify-center min-h-[200px] p-4">
|
|
735
|
-
<div class="text-center text-gray-500">
|
|
736
|
-
<svg class="animate-spin mx-auto mb-2" style="width: 1.5rem; height: 1.5rem; color: #9ca3af;" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
737
|
-
<circle style="opacity: 0.25;" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
738
|
-
<path style="opacity: 0.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>
|
|
739
|
-
</svg>
|
|
740
|
-
<p class="text-sm">Loading widget...</p>
|
|
741
|
-
</div>
|
|
742
|
-
</div>
|
|
743
|
-
<div id="frontmcp-error" style="display: none; padding: 1rem; margin: 1rem; background: #fef2f2; border: 1px solid #fecaca; border-radius: 0.5rem; color: #dc2626; font-size: 0.875rem;"></div>
|
|
744
|
-
`;
|
|
745
|
-
// Tool metadata script
|
|
746
|
-
const toolMetaScript = `<script>
|
|
747
|
-
// Hybrid widget shell - component comes at tool call time
|
|
748
|
-
window.__mcpToolName = ${JSON.stringify(toolName)};
|
|
749
|
-
window.__mcpWidgetAccessible = ${JSON.stringify(uiConfig.widgetAccessible ?? false)};
|
|
750
|
-
window.__mcpHybridShell = true;
|
|
751
|
-
</script>`;
|
|
752
|
-
// FrontMCP Bridge script (platform-agnostic)
|
|
753
|
-
const bridgeScript = iife_generator_1.BRIDGE_SCRIPT_TAGS.universal;
|
|
754
|
-
// Spinner animation CSS
|
|
755
|
-
const spinnerCss = `<style>
|
|
756
|
-
@keyframes spin { to { transform: rotate(360deg); } }
|
|
757
|
-
.animate-spin { animation: spin 1s linear infinite; }
|
|
758
|
-
</style>`;
|
|
759
|
-
// React 19 runtime + FrontMCP hooks + UI components + dynamic renderer
|
|
760
|
-
// This is the key script that makes hybrid mode work
|
|
761
|
-
const hybridRuntimeScript = `
|
|
762
|
-
<!-- FrontMCP Hybrid Widget Runtime -->
|
|
763
|
-
<script type="module">
|
|
764
|
-
// ============================================
|
|
765
|
-
// 1. Import React 19 from esm.sh
|
|
766
|
-
// ============================================
|
|
767
|
-
import React from 'https://esm.sh/react@19';
|
|
768
|
-
import ReactDOM from 'https://esm.sh/react-dom@19/client';
|
|
769
|
-
|
|
770
|
-
// Make React available globally
|
|
771
|
-
window.React = React;
|
|
772
|
-
window.ReactDOM = ReactDOM;
|
|
773
|
-
|
|
774
|
-
// ============================================
|
|
775
|
-
// 2. Provide webpack namespace objects for transpiled components
|
|
776
|
-
// ============================================
|
|
777
|
-
window.external_react_namespaceObject = React;
|
|
778
|
-
window.jsx_runtime_namespaceObject = {
|
|
779
|
-
jsx: (type, props, key) => {
|
|
780
|
-
if (key !== undefined) props = { ...props, key };
|
|
781
|
-
return React.createElement(type, props);
|
|
782
|
-
},
|
|
783
|
-
jsxs: (type, props, key) => {
|
|
784
|
-
if (key !== undefined) props = { ...props, key };
|
|
785
|
-
return React.createElement(type, props);
|
|
786
|
-
},
|
|
787
|
-
Fragment: React.Fragment,
|
|
788
|
-
};
|
|
789
|
-
window.process = window.process || { env: { NODE_ENV: 'production' } };
|
|
790
|
-
|
|
791
|
-
// ============================================
|
|
792
|
-
// 3. FrontMCP Hooks (platform-agnostic via bridge)
|
|
793
|
-
// ============================================
|
|
794
|
-
function useMcpBridgeContext() {
|
|
795
|
-
return {
|
|
796
|
-
bridge: window.FrontMcpBridge || null,
|
|
797
|
-
loading: false,
|
|
798
|
-
error: null,
|
|
799
|
-
ready: window.FrontMcpBridge?.initialized ?? false,
|
|
800
|
-
adapterId: window.FrontMcpBridge?.adapterId ?? 'unknown',
|
|
801
|
-
capabilities: window.FrontMcpBridge?.capabilities ?? {},
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
function useToolOutput() {
|
|
806
|
-
const [output, setOutput] = React.useState(null);
|
|
807
|
-
React.useEffect(() => {
|
|
808
|
-
const bridge = window.FrontMcpBridge;
|
|
809
|
-
if (!bridge) return;
|
|
810
|
-
|
|
811
|
-
// Get initial output
|
|
812
|
-
const initial = bridge.getToolOutput();
|
|
813
|
-
if (initial) setOutput(initial);
|
|
814
|
-
|
|
815
|
-
// Subscribe to updates
|
|
816
|
-
const unsubscribe = bridge.onToolResult((result) => {
|
|
817
|
-
setOutput(result);
|
|
818
|
-
});
|
|
819
|
-
return unsubscribe;
|
|
820
|
-
}, []);
|
|
821
|
-
return output;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
function useToolInput() {
|
|
825
|
-
const bridge = window.FrontMcpBridge;
|
|
826
|
-
return bridge?.getToolInput() || window.__mcpToolInput || {};
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
function useTheme() {
|
|
830
|
-
const [theme, setTheme] = React.useState('light');
|
|
831
|
-
React.useEffect(() => {
|
|
832
|
-
const bridge = window.FrontMcpBridge;
|
|
833
|
-
if (bridge?.getTheme) setTheme(bridge.getTheme());
|
|
834
|
-
}, []);
|
|
835
|
-
return theme;
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
function useCallTool(toolName, options = {}) {
|
|
839
|
-
const [loading, setLoading] = React.useState(false);
|
|
840
|
-
const [error, setError] = React.useState(null);
|
|
841
|
-
|
|
842
|
-
const isAvailable = !!(
|
|
843
|
-
(window.openai && typeof window.openai.callTool === 'function') ||
|
|
844
|
-
(window.FrontMcpBridge && window.FrontMcpBridge.hasCapability('canCallTools'))
|
|
845
|
-
);
|
|
846
|
-
|
|
847
|
-
const callTool = React.useCallback(async (args) => {
|
|
848
|
-
setLoading(true);
|
|
849
|
-
setError(null);
|
|
850
|
-
try {
|
|
851
|
-
let result;
|
|
852
|
-
if (window.openai && typeof window.openai.callTool === 'function') {
|
|
853
|
-
result = await window.openai.callTool(toolName, args || {});
|
|
854
|
-
} else if (window.FrontMcpBridge) {
|
|
855
|
-
result = await window.FrontMcpBridge.callTool(toolName, args || {});
|
|
856
|
-
} else {
|
|
857
|
-
throw new Error('Tool calling not available');
|
|
858
|
-
}
|
|
859
|
-
options.onSuccess?.(result);
|
|
860
|
-
return result;
|
|
861
|
-
} catch (err) {
|
|
862
|
-
setError(err);
|
|
863
|
-
options.onError?.(err);
|
|
864
|
-
throw err;
|
|
865
|
-
} finally {
|
|
866
|
-
setLoading(false);
|
|
867
|
-
}
|
|
868
|
-
}, [toolName]);
|
|
869
|
-
|
|
870
|
-
return [callTool, { loading, error, available: isAvailable }];
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
// ============================================
|
|
874
|
-
// 4. FrontMCP UI Components
|
|
875
|
-
// ============================================
|
|
876
|
-
function Card({ title, subtitle, variant, size, className, children, footer }) {
|
|
877
|
-
const baseClasses = 'rounded-lg border bg-bg-surface';
|
|
878
|
-
const variantClasses = variant === 'elevated' ? 'shadow-md' : 'border-divider';
|
|
879
|
-
const sizeClasses = { sm: 'p-3', md: 'p-4', lg: 'p-6' }[size || 'md'];
|
|
880
|
-
return React.createElement('div', { className: [baseClasses, variantClasses, sizeClasses, className].filter(Boolean).join(' ') },
|
|
881
|
-
(title || subtitle) && React.createElement('div', { className: 'mb-4' },
|
|
882
|
-
title && React.createElement('h3', { className: 'text-lg font-semibold text-text-primary' }, title),
|
|
883
|
-
subtitle && React.createElement('p', { className: 'text-sm text-text-secondary mt-1' }, subtitle)
|
|
884
|
-
),
|
|
885
|
-
children,
|
|
886
|
-
footer && React.createElement('div', { className: 'mt-4 pt-4 border-t border-divider' }, footer)
|
|
887
|
-
);
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
function Badge({ children, variant, size, pill }) {
|
|
891
|
-
const baseClasses = 'inline-flex items-center font-medium';
|
|
892
|
-
const variantClasses = {
|
|
893
|
-
default: 'bg-bg-secondary text-text-primary',
|
|
894
|
-
success: 'bg-green-100 text-green-800',
|
|
895
|
-
warning: 'bg-yellow-100 text-yellow-800',
|
|
896
|
-
info: 'bg-blue-100 text-blue-800',
|
|
897
|
-
danger: 'bg-red-100 text-red-800',
|
|
898
|
-
}[variant || 'default'];
|
|
899
|
-
const sizeClasses = { sm: 'px-2 py-0.5 text-xs', md: 'px-2.5 py-1 text-sm', lg: 'px-3 py-1.5 text-base' }[size || 'md'];
|
|
900
|
-
const pillClasses = pill ? 'rounded-full' : 'rounded-md';
|
|
901
|
-
return React.createElement('span', {
|
|
902
|
-
className: [baseClasses, variantClasses, sizeClasses, pillClasses].filter(Boolean).join(' ')
|
|
903
|
-
}, children);
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
function Button({ children, variant, size, disabled, onClick, className }) {
|
|
907
|
-
const baseClasses = 'inline-flex items-center justify-center rounded-md font-medium transition-colors';
|
|
908
|
-
const variantClasses = {
|
|
909
|
-
primary: 'bg-primary text-white hover:bg-primary/90',
|
|
910
|
-
secondary: 'bg-bg-secondary text-text-primary hover:bg-bg-secondary/80',
|
|
911
|
-
outline: 'border border-divider bg-transparent hover:bg-bg-secondary',
|
|
912
|
-
ghost: 'bg-transparent hover:bg-bg-secondary',
|
|
913
|
-
}[variant || 'primary'];
|
|
914
|
-
const sizeClasses = { sm: 'px-3 py-1.5 text-sm', md: 'px-4 py-2 text-base', lg: 'px-6 py-3 text-lg' }[size || 'md'];
|
|
915
|
-
const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : '';
|
|
916
|
-
return React.createElement('button', {
|
|
917
|
-
type: 'button',
|
|
918
|
-
className: [baseClasses, variantClasses, sizeClasses, disabledClasses, className].filter(Boolean).join(' '),
|
|
919
|
-
disabled,
|
|
920
|
-
onClick,
|
|
921
|
-
}, children);
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
// Expose via react_namespaceObject for transpiled components
|
|
925
|
-
window.react_namespaceObject = {
|
|
926
|
-
...React,
|
|
927
|
-
useMcpBridgeContext,
|
|
928
|
-
useToolOutput,
|
|
929
|
-
useToolInput,
|
|
930
|
-
useTheme,
|
|
931
|
-
useCallTool,
|
|
932
|
-
Card,
|
|
933
|
-
Badge,
|
|
934
|
-
Button,
|
|
935
|
-
McpBridgeProvider: ({ children }) => children,
|
|
936
|
-
};
|
|
937
|
-
window.react_dom_namespaceObject = ReactDOM;
|
|
938
|
-
|
|
939
|
-
// Template helpers
|
|
940
|
-
window.__frontmcp_helpers = {
|
|
941
|
-
escapeHtml: (str) => String(str).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] || c),
|
|
942
|
-
formatDate: (d) => new Date(d).toLocaleDateString(),
|
|
943
|
-
formatCurrency: (a, c) => new Intl.NumberFormat('en-US', {style:'currency',currency:c||'USD'}).format(a),
|
|
944
|
-
};
|
|
945
|
-
|
|
946
|
-
// Component-specific helpers (for weather demo, etc.)
|
|
947
|
-
window.iconMap = {
|
|
948
|
-
sunny: '\\u2600\\uFE0F', cloudy: '\\u2601\\uFE0F', rainy: '\\uD83C\\uDF27\\uFE0F',
|
|
949
|
-
snowy: '\\u2744\\uFE0F', stormy: '\\u26C8\\uFE0F', windy: '\\uD83D\\uDCA8', foggy: '\\uD83C\\uDF2B\\uFE0F',
|
|
950
|
-
};
|
|
951
|
-
window.getConditionBadgeVariant = function(c) {
|
|
952
|
-
switch(c) { case 'sunny': return 'success'; case 'rainy': case 'snowy': return 'info'; case 'stormy': return 'warning'; default: return 'default'; }
|
|
953
|
-
};
|
|
954
|
-
|
|
955
|
-
console.log('[FrontMCP Hybrid] React 19 runtime loaded with hooks and components');
|
|
956
|
-
|
|
957
|
-
// ============================================
|
|
958
|
-
// 5. Dynamic Renderer
|
|
959
|
-
// ============================================
|
|
960
|
-
let currentComponent = null;
|
|
961
|
-
let reactRoot = null;
|
|
962
|
-
|
|
963
|
-
function hideLoader() {
|
|
964
|
-
const loader = document.querySelector('#frontmcp-widget-root > div');
|
|
965
|
-
if (loader) loader.style.display = 'none';
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
function showError(message) {
|
|
969
|
-
const errorEl = document.getElementById('frontmcp-error');
|
|
970
|
-
if (errorEl) {
|
|
971
|
-
errorEl.textContent = message;
|
|
972
|
-
errorEl.style.display = 'block';
|
|
973
|
-
}
|
|
974
|
-
hideLoader();
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
function render() {
|
|
978
|
-
const bridge = window.FrontMcpBridge;
|
|
979
|
-
const output = bridge?.getToolOutput();
|
|
980
|
-
|
|
981
|
-
if (!currentComponent) {
|
|
982
|
-
console.log('[FrontMCP Hybrid] No component loaded yet');
|
|
983
|
-
return false;
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
if (!output) {
|
|
987
|
-
console.log('[FrontMCP Hybrid] No data available yet');
|
|
988
|
-
return false;
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
const root = document.getElementById('frontmcp-widget-root');
|
|
992
|
-
if (!root) return false;
|
|
993
|
-
|
|
994
|
-
const props = {
|
|
995
|
-
input: bridge.getToolInput() || {},
|
|
996
|
-
output: output,
|
|
997
|
-
structuredContent: bridge.getStructuredContent(),
|
|
998
|
-
helpers: window.__frontmcp_helpers,
|
|
999
|
-
};
|
|
1000
|
-
|
|
1001
|
-
try {
|
|
1002
|
-
hideLoader();
|
|
1003
|
-
const element = React.createElement(currentComponent, props);
|
|
1004
|
-
if (!reactRoot) {
|
|
1005
|
-
reactRoot = ReactDOM.createRoot(root);
|
|
1006
|
-
}
|
|
1007
|
-
reactRoot.render(element);
|
|
1008
|
-
console.log('[FrontMCP Hybrid] Component rendered with data');
|
|
1009
|
-
return true;
|
|
1010
|
-
} catch (err) {
|
|
1011
|
-
console.error('[FrontMCP Hybrid] Render failed:', err);
|
|
1012
|
-
showError('Rendering failed: ' + err.message);
|
|
1013
|
-
return false;
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
async function loadComponent(payload) {
|
|
1018
|
-
if (!payload?.code) {
|
|
1019
|
-
console.warn('[FrontMCP Hybrid] No component code in payload');
|
|
1020
|
-
return;
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
console.log('[FrontMCP Hybrid] Loading component, type:', payload.type);
|
|
1024
|
-
|
|
1025
|
-
try {
|
|
1026
|
-
// Import component via blob URL
|
|
1027
|
-
const blob = new Blob([payload.code], { type: 'application/javascript' });
|
|
1028
|
-
const url = URL.createObjectURL(blob);
|
|
1029
|
-
|
|
1030
|
-
const module = await import(/* webpackIgnore: true */ url);
|
|
1031
|
-
currentComponent = module.default || window.__frontmcp_component;
|
|
1032
|
-
URL.revokeObjectURL(url);
|
|
1033
|
-
|
|
1034
|
-
if (!currentComponent) {
|
|
1035
|
-
throw new Error('Component not found in module');
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
console.log('[FrontMCP Hybrid] Component loaded successfully');
|
|
1039
|
-
render();
|
|
1040
|
-
} catch (err) {
|
|
1041
|
-
console.error('[FrontMCP Hybrid] Failed to load component:', err);
|
|
1042
|
-
showError('Failed to load component: ' + err.message);
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
// ============================================
|
|
1047
|
-
// 6. Bridge Integration
|
|
1048
|
-
// ============================================
|
|
1049
|
-
async function initializeBridge() {
|
|
1050
|
-
// Wait for bridge to be ready
|
|
1051
|
-
if (!window.FrontMcpBridge?.initialized) {
|
|
1052
|
-
await new Promise(resolve => {
|
|
1053
|
-
window.addEventListener('bridge:ready', resolve, { once: true });
|
|
1054
|
-
// Fallback timeout
|
|
1055
|
-
setTimeout(resolve, 5000);
|
|
1056
|
-
});
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
const bridge = window.FrontMcpBridge;
|
|
1060
|
-
if (!bridge) {
|
|
1061
|
-
console.error('[FrontMCP Hybrid] Bridge not available');
|
|
1062
|
-
showError('Bridge initialization failed');
|
|
1063
|
-
return;
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
console.log('[FrontMCP Hybrid] Bridge ready, adapter:', bridge.adapterId);
|
|
1067
|
-
|
|
1068
|
-
// Listen for component code in tool response metadata
|
|
1069
|
-
if (typeof bridge.onToolResponseMetadata === 'function') {
|
|
1070
|
-
bridge.onToolResponseMetadata(function(metadata) {
|
|
1071
|
-
console.log('[FrontMCP Hybrid] Received tool response metadata');
|
|
1072
|
-
|
|
1073
|
-
// Check for component payload
|
|
1074
|
-
const componentPayload = metadata['ui/component'];
|
|
1075
|
-
if (componentPayload) {
|
|
1076
|
-
loadComponent(componentPayload);
|
|
1077
|
-
}
|
|
1078
|
-
});
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
// Listen for data updates (for re-renders)
|
|
1082
|
-
if (typeof bridge.onToolResult === 'function') {
|
|
1083
|
-
bridge.onToolResult(function(result) {
|
|
1084
|
-
console.log('[FrontMCP Hybrid] Received tool result update');
|
|
1085
|
-
render();
|
|
1086
|
-
});
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
// Check if data already available (e.g., page refresh)
|
|
1090
|
-
const existingMetadata = bridge.getToolResponseMetadata?.();
|
|
1091
|
-
if (existingMetadata?.['ui/component']) {
|
|
1092
|
-
loadComponent(existingMetadata['ui/component']);
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
// Start initialization
|
|
1097
|
-
initializeBridge();
|
|
1098
|
-
</script>`;
|
|
1099
|
-
return `<!DOCTYPE html>
|
|
1100
|
-
<html lang="en">
|
|
1101
|
-
<head>
|
|
1102
|
-
<meta charset="UTF-8">
|
|
1103
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1104
|
-
<title>${(0, base_1.escapeHtml)(title || toolName)}</title>
|
|
1105
|
-
${fontPreconnect}
|
|
1106
|
-
${fontStylesheets}
|
|
1107
|
-
${tailwindScript}
|
|
1108
|
-
${styleBlock}
|
|
1109
|
-
${spinnerCss}
|
|
1110
|
-
${toolMetaScript}
|
|
1111
|
-
${bridgeScript}
|
|
1112
|
-
</head>
|
|
1113
|
-
<body class="bg-white font-sans antialiased">
|
|
1114
|
-
${placeholderContent}
|
|
1115
|
-
${hybridRuntimeScript}
|
|
1116
|
-
</body>
|
|
1117
|
-
</html>`;
|
|
1118
|
-
}
|
|
1119
|
-
/**
|
|
1120
|
-
* Wrap a static widget template for MCP resource mode.
|
|
1121
|
-
*
|
|
1122
|
-
* Unlike `wrapToolUIUniversal`, this function creates a widget that:
|
|
1123
|
-
* - Does NOT embed data (input/output/structuredContent)
|
|
1124
|
-
* - Reads data at runtime from the FrontMCP Bridge (window.openai.toolOutput)
|
|
1125
|
-
* - Is cached at server startup and returned for all requests
|
|
1126
|
-
*
|
|
1127
|
-
* This is used for `servingMode: 'static'` where OpenAI caches the
|
|
1128
|
-
* outputTemplate HTML and injects data via window.openai.toolOutput.
|
|
1129
|
-
*
|
|
1130
|
-
* @param options - Static widget options
|
|
1131
|
-
* @returns Complete HTML document string
|
|
1132
|
-
*
|
|
1133
|
-
* @example
|
|
1134
|
-
* ```typescript
|
|
1135
|
-
* const html = wrapStaticWidgetUniversal({
|
|
1136
|
-
* toolName: 'get_weather',
|
|
1137
|
-
* ssrContent: '<div class="weather-card"><!-- Template without data --></div>',
|
|
1138
|
-
* uiConfig: { widgetAccessible: true },
|
|
1139
|
-
* });
|
|
1140
|
-
* ```
|
|
1141
|
-
*/
|
|
1142
|
-
function wrapStaticWidgetUniversal(options) {
|
|
1143
|
-
const { toolName, ssrContent, uiConfig, title, theme: themeOverrides, rendererType, componentCode, embeddedData, selfContained = false, } = options;
|
|
1144
|
-
// Merge theme
|
|
1145
|
-
const theme = themeOverrides ? (0, theme_1.mergeThemes)(theme_1.DEFAULT_THEME, themeOverrides) : theme_1.DEFAULT_THEME;
|
|
1146
|
-
// Build font links
|
|
1147
|
-
const fontPreconnect = (0, theme_1.buildFontPreconnect)();
|
|
1148
|
-
const fontStylesheets = (0, theme_1.buildFontStylesheets)({ inter: true });
|
|
1149
|
-
// Build CDN scripts
|
|
1150
|
-
const scripts = (0, theme_1.buildCdnScripts)({
|
|
1151
|
-
tailwind: true,
|
|
1152
|
-
htmx: false,
|
|
1153
|
-
alpine: false,
|
|
1154
|
-
icons: false,
|
|
1155
|
-
inline: false,
|
|
1156
|
-
});
|
|
1157
|
-
// Build theme CSS
|
|
1158
|
-
const themeCss = (0, theme_1.buildThemeCss)(theme);
|
|
1159
|
-
const customCss = theme.customCss || '';
|
|
1160
|
-
// Build Tailwind style block
|
|
1161
|
-
const styleBlock = `<style type="text/tailwindcss">
|
|
1162
|
-
@theme {
|
|
1163
|
-
${themeCss}
|
|
1164
|
-
}
|
|
1165
|
-
${customCss}
|
|
1166
|
-
</style>`;
|
|
1167
|
-
// Build CSP meta tag (skip for OpenAI - they handle CSP via _meta)
|
|
1168
|
-
// For static widgets, we skip CSP meta tag since OpenAI handles it
|
|
1169
|
-
const cspMetaTag = '';
|
|
1170
|
-
const isReactBased = rendererType === 'react' || rendererType === 'mdx';
|
|
1171
|
-
// For inline mode with embeddedData: embed the data directly in the HTML
|
|
1172
|
-
// For static mode (no embeddedData): data comes from window.openai.toolOutput at runtime
|
|
1173
|
-
const hasEmbeddedData = embeddedData && (embeddedData.output !== undefined || embeddedData.input !== undefined);
|
|
1174
|
-
// Universal bridge script (works on all platforms)
|
|
1175
|
-
// Skip for self-contained/inline mode - data is embedded, no runtime communication needed
|
|
1176
|
-
// Including the bridge triggers OpenAI's wrapper script which destroys our React content
|
|
1177
|
-
// selfContained mode: explicitly skip bridge (inline mode with full React)
|
|
1178
|
-
// hasEmbeddedData: backward compatibility for inline mode detection
|
|
1179
|
-
const includeBridge = !selfContained && !hasEmbeddedData;
|
|
1180
|
-
const bridgeScript = includeBridge ? iife_generator_1.BRIDGE_SCRIPT_TAGS.universal : '';
|
|
1181
|
-
// Tool name injection (for Bridge to know which tool this is)
|
|
1182
|
-
const helpers = createTemplateHelpers();
|
|
1183
|
-
// Build the tool metadata script based on mode
|
|
1184
|
-
// selfContained: inline mode with no bridge - React manages its own state
|
|
1185
|
-
// hasEmbeddedData: backward compat - inline mode with embedded data
|
|
1186
|
-
// neither: static mode - polls for data from host platform
|
|
1187
|
-
const toolNameScript = selfContained && hasEmbeddedData
|
|
1188
|
-
? `<script>
|
|
1189
|
-
// Tool metadata (self-contained inline mode - no bridge, no wrapper interference)
|
|
1190
|
-
window.__mcpToolName = ${helpers.jsonEmbed(toolName)};
|
|
1191
|
-
window.__mcpWidgetAccessible = ${helpers.jsonEmbed(uiConfig.widgetAccessible ?? false)};
|
|
1192
|
-
// Embedded data for immediate rendering
|
|
1193
|
-
window.__mcpToolInput = ${helpers.jsonEmbed(embeddedData.input ?? {})};
|
|
1194
|
-
window.__mcpToolOutput = ${helpers.jsonEmbed(embeddedData.output)};
|
|
1195
|
-
window.__mcpStructuredContent = ${helpers.jsonEmbed(embeddedData.structuredContent)};
|
|
1196
|
-
// Flags for self-contained mode
|
|
1197
|
-
window.__mcpDataEmbedded = true;
|
|
1198
|
-
window.__mcpSelfContained = true;
|
|
1199
|
-
// No bridge included - React component handles state internally via hooks
|
|
1200
|
-
</script>`
|
|
1201
|
-
: hasEmbeddedData
|
|
1202
|
-
? `<script>
|
|
1203
|
-
// Tool metadata (inline mode - data embedded, backward compat)
|
|
1204
|
-
window.__mcpToolName = ${helpers.jsonEmbed(toolName)};
|
|
1205
|
-
window.__mcpWidgetAccessible = ${helpers.jsonEmbed(uiConfig.widgetAccessible ?? false)};
|
|
1206
|
-
window.__mcpToolInput = ${helpers.jsonEmbed(embeddedData.input ?? {})};
|
|
1207
|
-
window.__mcpToolOutput = ${helpers.jsonEmbed(embeddedData.output)};
|
|
1208
|
-
window.__mcpStructuredContent = ${helpers.jsonEmbed(embeddedData.structuredContent)};
|
|
1209
|
-
window.__mcpDataEmbedded = true;
|
|
1210
|
-
</script>`
|
|
1211
|
-
: `<script>
|
|
1212
|
-
// Tool metadata (static mode - data injected by host at runtime)
|
|
1213
|
-
window.__mcpToolName = ${helpers.jsonEmbed(toolName)};
|
|
1214
|
-
window.__mcpWidgetAccessible = ${helpers.jsonEmbed(uiConfig.widgetAccessible ?? false)};
|
|
1215
|
-
// Data will be provided by host platform:
|
|
1216
|
-
// - OpenAI: window.openai.toolOutput
|
|
1217
|
-
// - FrontMCP Bridge: window.__mcpToolOutput, window.__mcpStructuredContent
|
|
1218
|
-
</script>`;
|
|
1219
|
-
// Build the consolidated React module script
|
|
1220
|
-
// Everything runs inside a single ES module for better async/import handling
|
|
1221
|
-
const reactModuleScript = isReactBased && componentCode
|
|
1222
|
-
? `
|
|
1223
|
-
<!-- FrontMCP React Widget Runtime (Single ES Module) -->
|
|
1224
|
-
<script type="module">
|
|
1225
|
-
// ============================================
|
|
1226
|
-
// 1. Import React 19 from esm.sh
|
|
1227
|
-
// ============================================
|
|
1228
|
-
import React from 'https://esm.sh/react@19';
|
|
1229
|
-
import ReactDOM from 'https://esm.sh/react-dom@19/client';
|
|
1230
|
-
|
|
1231
|
-
// Make React available globally for the component code
|
|
1232
|
-
window.React = React;
|
|
1233
|
-
window.ReactDOM = ReactDOM;
|
|
1234
|
-
|
|
1235
|
-
// ============================================
|
|
1236
|
-
// 1b. Provide ALL webpack namespace objects
|
|
1237
|
-
// ============================================
|
|
1238
|
-
// Webpack generates different namespace variable names when bundling:
|
|
1239
|
-
// - external_react_namespaceObject: React marked as external
|
|
1240
|
-
// - jsx_runtime_namespaceObject: react/jsx-runtime
|
|
1241
|
-
// We must provide ALL of these for transpiled components to work.
|
|
1242
|
-
|
|
1243
|
-
// external_react_namespaceObject - for React imports (useState, useEffect, etc.)
|
|
1244
|
-
window.external_react_namespaceObject = React;
|
|
1245
|
-
|
|
1246
|
-
// jsx_runtime_namespaceObject - for JSX transformation (jsx, jsxs functions)
|
|
1247
|
-
window.jsx_runtime_namespaceObject = {
|
|
1248
|
-
jsx: (type, props, key) => {
|
|
1249
|
-
if (key !== undefined) props = { ...props, key };
|
|
1250
|
-
return React.createElement(type, props);
|
|
1251
|
-
},
|
|
1252
|
-
jsxs: (type, props, key) => {
|
|
1253
|
-
if (key !== undefined) props = { ...props, key };
|
|
1254
|
-
return React.createElement(type, props);
|
|
1255
|
-
},
|
|
1256
|
-
Fragment: React.Fragment,
|
|
1257
|
-
};
|
|
1258
|
-
|
|
1259
|
-
// process.env - for development mode checks
|
|
1260
|
-
window.process = window.process || { env: { NODE_ENV: 'production' } };
|
|
1261
|
-
|
|
1262
|
-
// ============================================
|
|
1263
|
-
// 1c. Component-specific helpers
|
|
1264
|
-
// ============================================
|
|
1265
|
-
// These are module-level variables that get lost when calling .toString() on the component.
|
|
1266
|
-
// For the weather component, we need iconMap and getConditionBadgeVariant.
|
|
1267
|
-
|
|
1268
|
-
window.iconMap = {
|
|
1269
|
-
sunny: '\u2600\uFE0F',
|
|
1270
|
-
cloudy: '\u2601\uFE0F',
|
|
1271
|
-
rainy: '\uD83C\uDF27\uFE0F',
|
|
1272
|
-
snowy: '\u2744\uFE0F',
|
|
1273
|
-
stormy: '\u26C8\uFE0F',
|
|
1274
|
-
windy: '\uD83D\uDCA8',
|
|
1275
|
-
foggy: '\uD83C\uDF2B\uFE0F',
|
|
1276
|
-
};
|
|
1277
|
-
|
|
1278
|
-
window.getConditionBadgeVariant = function(conditions) {
|
|
1279
|
-
switch (conditions) {
|
|
1280
|
-
case 'sunny': return 'success';
|
|
1281
|
-
case 'rainy':
|
|
1282
|
-
case 'snowy': return 'info';
|
|
1283
|
-
case 'stormy': return 'warning';
|
|
1284
|
-
default: return 'default';
|
|
1285
|
-
}
|
|
1286
|
-
};
|
|
1287
|
-
|
|
1288
|
-
// ============================================
|
|
1289
|
-
// 2. Provide FrontMCP hooks on the react namespace
|
|
1290
|
-
// ============================================
|
|
1291
|
-
// Transpiled components may call react_namespaceObject.useMcpBridgeContext, etc.
|
|
1292
|
-
// These are FrontMCP hooks that get bundled with React imports.
|
|
1293
|
-
// We provide stub implementations that work with the client-side data.
|
|
1294
|
-
|
|
1295
|
-
// State storage for hooks
|
|
1296
|
-
const hookState = {
|
|
1297
|
-
toolOutput: null,
|
|
1298
|
-
toolInput: null,
|
|
1299
|
-
theme: 'light',
|
|
1300
|
-
ready: false,
|
|
1301
|
-
};
|
|
1302
|
-
|
|
1303
|
-
// useMcpBridgeContext - returns context about the bridge
|
|
1304
|
-
function useMcpBridgeContext() {
|
|
1305
|
-
return {
|
|
1306
|
-
bridge: window.__frontmcp?.bridge || null,
|
|
1307
|
-
loading: false,
|
|
1308
|
-
error: null,
|
|
1309
|
-
ready: hookState.ready,
|
|
1310
|
-
adapterId: 'openai',
|
|
1311
|
-
capabilities: { canCallTools: true, canSendMessages: false },
|
|
1312
|
-
};
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
|
-
// useToolOutput - returns the tool output
|
|
1316
|
-
function useToolOutput() {
|
|
1317
|
-
const [output, setOutput] = React.useState(hookState.toolOutput);
|
|
1318
|
-
React.useEffect(() => {
|
|
1319
|
-
// Update when toolOutput changes
|
|
1320
|
-
const checkOutput = () => {
|
|
1321
|
-
const newOutput = getToolOutput();
|
|
1322
|
-
if (newOutput && newOutput !== output) {
|
|
1323
|
-
setOutput(newOutput);
|
|
1324
|
-
hookState.toolOutput = newOutput;
|
|
1325
|
-
}
|
|
1326
|
-
};
|
|
1327
|
-
const interval = setInterval(checkOutput, 100);
|
|
1328
|
-
checkOutput();
|
|
1329
|
-
return () => clearInterval(interval);
|
|
1330
|
-
}, []);
|
|
1331
|
-
return output;
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
// useToolInput - returns the tool input
|
|
1335
|
-
function useToolInput() {
|
|
1336
|
-
return hookState.toolInput || window.__mcpToolInput || {};
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
// useTheme - returns current theme
|
|
1340
|
-
function useTheme() {
|
|
1341
|
-
const [theme, setTheme] = React.useState(hookState.theme);
|
|
1342
|
-
React.useEffect(() => {
|
|
1343
|
-
// Try to detect theme from host
|
|
1344
|
-
if (window.openai?.theme) {
|
|
1345
|
-
setTheme(window.openai.theme);
|
|
1346
|
-
}
|
|
1347
|
-
}, []);
|
|
1348
|
-
return theme;
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
// useCallTool - returns a function to call tools from within widgets
|
|
1352
|
-
// Supports multiple environments:
|
|
1353
|
-
// - OpenAI: Uses window.openai.callTool directly
|
|
1354
|
-
// - FrontMCP Bridge: Uses window.__frontmcp.callTool
|
|
1355
|
-
// - Other: Falls back gracefully
|
|
1356
|
-
function useCallTool(toolName, options = {}) {
|
|
1357
|
-
const [loading, setLoading] = React.useState(false);
|
|
1358
|
-
const [error, setError] = React.useState(null);
|
|
1359
|
-
|
|
1360
|
-
// Check availability once
|
|
1361
|
-
const isAvailable = !!(
|
|
1362
|
-
(window.openai && typeof window.openai.callTool === 'function') ||
|
|
1363
|
-
(window.__frontmcp && typeof window.__frontmcp.callTool === 'function')
|
|
1364
|
-
);
|
|
1365
|
-
|
|
1366
|
-
const callTool = React.useCallback(async (args) => {
|
|
1367
|
-
setLoading(true);
|
|
1368
|
-
setError(null);
|
|
1369
|
-
try {
|
|
1370
|
-
let result;
|
|
1371
|
-
|
|
1372
|
-
// Priority 1: OpenAI SDK (most reliable in OpenAI iframe)
|
|
1373
|
-
if (window.openai && typeof window.openai.callTool === 'function') {
|
|
1374
|
-
console.log('[FrontMCP] useCallTool: Using OpenAI SDK for', toolName);
|
|
1375
|
-
result = await window.openai.callTool(toolName, args || {});
|
|
1376
|
-
} else if (window.__frontmcp && typeof window.__frontmcp.callTool === 'function') {
|
|
1377
|
-
// Priority 2: FrontMCP bridge
|
|
1378
|
-
console.log('[FrontMCP] useCallTool: Using FrontMCP bridge for', toolName);
|
|
1379
|
-
result = await window.__frontmcp.callTool(toolName, args || {});
|
|
1380
|
-
} else {
|
|
1381
|
-
// Not available - log warning and return null
|
|
1382
|
-
console.warn(
|
|
1383
|
-
'[FrontMCP] useCallTool: No tool calling mechanism available. ' +
|
|
1384
|
-
'Tool: "' + toolName + '". Widget is display-only.'
|
|
1385
|
-
);
|
|
1386
|
-
const notAvailableError = new Error('Tool calling not available in this environment');
|
|
1387
|
-
setError(notAvailableError);
|
|
1388
|
-
options.onError?.(notAvailableError);
|
|
1389
|
-
return null;
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
// Normalize result: ensure structuredContent is available for component callbacks
|
|
1393
|
-
// OpenAI returns raw tool output directly, but components may expect { structuredContent: ... }
|
|
1394
|
-
// This ensures both direct access (result.temperature) and wrapped access (result.structuredContent.temperature) work
|
|
1395
|
-
const normalizedResult = {
|
|
1396
|
-
...result,
|
|
1397
|
-
structuredContent: result.structuredContent ?? result,
|
|
1398
|
-
};
|
|
1399
|
-
|
|
1400
|
-
// For static mode: Update global state so hooks (useToolOutput) pick up the change
|
|
1401
|
-
// For self-contained/inline mode: Skip this - React component handles state internally via setOutput
|
|
1402
|
-
// Updating global state in inline mode could trigger OpenAI's wrapper to overwrite our React component
|
|
1403
|
-
if (!window.__mcpSelfContained && !window.__mcpDataEmbedded) {
|
|
1404
|
-
window.__mcpToolOutput = normalizedResult.structuredContent;
|
|
1405
|
-
window.__mcpStructuredContent = normalizedResult.structuredContent;
|
|
1406
|
-
}
|
|
1407
|
-
|
|
1408
|
-
console.log('[FrontMCP] useCallTool: Tool returned, normalized result:', normalizedResult);
|
|
1409
|
-
options.onSuccess?.(normalizedResult);
|
|
1410
|
-
return normalizedResult;
|
|
1411
|
-
} catch (err) {
|
|
1412
|
-
console.error('[FrontMCP] useCallTool error:', err);
|
|
1413
|
-
setError(err);
|
|
1414
|
-
options.onError?.(err);
|
|
1415
|
-
throw err;
|
|
1416
|
-
} finally {
|
|
1417
|
-
setLoading(false);
|
|
1418
|
-
}
|
|
1419
|
-
}, [toolName]);
|
|
1420
|
-
|
|
1421
|
-
return [callTool, { loading, error, available: isAvailable }];
|
|
1422
|
-
}
|
|
1423
|
-
|
|
1424
|
-
// ============================================
|
|
1425
|
-
// 2b. UI Components (Card, Badge, etc.)
|
|
1426
|
-
// ============================================
|
|
1427
|
-
// These may be bundled from @frontmcp/ui/react and referenced via namespace.
|
|
1428
|
-
// We provide simple stub implementations.
|
|
1429
|
-
|
|
1430
|
-
function Card({ title, subtitle, variant, size, className, children, footer }) {
|
|
1431
|
-
const baseClasses = 'rounded-lg border bg-bg-surface';
|
|
1432
|
-
const variantClasses = variant === 'elevated' ? 'shadow-md' : 'border-divider';
|
|
1433
|
-
const sizeClasses = { sm: 'p-3', md: 'p-4', lg: 'p-6' }[size || 'md'];
|
|
1434
|
-
|
|
1435
|
-
return React.createElement('div', { className: [baseClasses, variantClasses, sizeClasses, className].filter(Boolean).join(' ') },
|
|
1436
|
-
(title || subtitle) && React.createElement('div', { className: 'mb-4' },
|
|
1437
|
-
title && React.createElement('h3', { className: 'text-lg font-semibold text-text-primary' }, title),
|
|
1438
|
-
subtitle && React.createElement('p', { className: 'text-sm text-text-secondary mt-1' }, subtitle)
|
|
1439
|
-
),
|
|
1440
|
-
children,
|
|
1441
|
-
footer && React.createElement('div', { className: 'mt-4 pt-4 border-t border-divider' }, footer)
|
|
1442
|
-
);
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
function Badge({ children, variant, size, pill }) {
|
|
1446
|
-
const baseClasses = 'inline-flex items-center font-medium';
|
|
1447
|
-
const variantClasses = {
|
|
1448
|
-
default: 'bg-bg-secondary text-text-primary',
|
|
1449
|
-
success: 'bg-green-100 text-green-800',
|
|
1450
|
-
warning: 'bg-yellow-100 text-yellow-800',
|
|
1451
|
-
info: 'bg-blue-100 text-blue-800',
|
|
1452
|
-
danger: 'bg-red-100 text-red-800',
|
|
1453
|
-
}[variant || 'default'];
|
|
1454
|
-
const sizeClasses = { sm: 'px-2 py-0.5 text-xs', md: 'px-2.5 py-1 text-sm', lg: 'px-3 py-1.5 text-base' }[size || 'md'];
|
|
1455
|
-
const pillClasses = pill ? 'rounded-full' : 'rounded-md';
|
|
1456
|
-
|
|
1457
|
-
return React.createElement('span', {
|
|
1458
|
-
className: [baseClasses, variantClasses, sizeClasses, pillClasses].filter(Boolean).join(' ')
|
|
1459
|
-
}, children);
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
function Button({ children, variant, size, disabled, onClick, className }) {
|
|
1463
|
-
const baseClasses = 'inline-flex items-center justify-center rounded-md font-medium transition-colors';
|
|
1464
|
-
const variantClasses = {
|
|
1465
|
-
primary: 'bg-primary text-white hover:bg-primary/90',
|
|
1466
|
-
secondary: 'bg-bg-secondary text-text-primary hover:bg-bg-secondary/80',
|
|
1467
|
-
outline: 'border border-divider bg-transparent hover:bg-bg-secondary',
|
|
1468
|
-
ghost: 'bg-transparent hover:bg-bg-secondary',
|
|
1469
|
-
}[variant || 'primary'];
|
|
1470
|
-
const sizeClasses = { sm: 'px-3 py-1.5 text-sm', md: 'px-4 py-2 text-base', lg: 'px-6 py-3 text-lg' }[size || 'md'];
|
|
1471
|
-
const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : '';
|
|
1472
|
-
|
|
1473
|
-
return React.createElement('button', {
|
|
1474
|
-
type: 'button',
|
|
1475
|
-
className: [baseClasses, variantClasses, sizeClasses, disabledClasses, className].filter(Boolean).join(' '),
|
|
1476
|
-
disabled,
|
|
1477
|
-
onClick,
|
|
1478
|
-
}, children);
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
// Provide webpack-style namespace objects that transpiled components may reference
|
|
1482
|
-
// This fixes "react_namespaceObject is not defined" errors
|
|
1483
|
-
// Include both React exports AND FrontMCP hooks/components
|
|
1484
|
-
window.react_namespaceObject = {
|
|
1485
|
-
...React,
|
|
1486
|
-
// FrontMCP hooks
|
|
1487
|
-
useMcpBridgeContext,
|
|
1488
|
-
useToolOutput,
|
|
1489
|
-
useToolInput,
|
|
1490
|
-
useTheme,
|
|
1491
|
-
useCallTool,
|
|
1492
|
-
// FrontMCP UI components
|
|
1493
|
-
Card,
|
|
1494
|
-
Badge,
|
|
1495
|
-
Button,
|
|
1496
|
-
// Also provide as 'McpBridgeProvider' stub (no-op for client)
|
|
1497
|
-
McpBridgeProvider: ({ children }) => children,
|
|
1498
|
-
};
|
|
1499
|
-
window.react_dom_namespaceObject = ReactDOM;
|
|
1500
|
-
|
|
1501
|
-
console.log('[FrontMCP] React 19 loaded from esm.sh with FrontMCP hooks');
|
|
1502
|
-
|
|
1503
|
-
// ============================================
|
|
1504
|
-
// 2. Define the Component
|
|
1505
|
-
// ============================================
|
|
1506
|
-
// Note: The component may reference react_namespaceObject which is now available
|
|
1507
|
-
${componentCode}
|
|
1508
|
-
|
|
1509
|
-
// ============================================
|
|
1510
|
-
// 3. Helper Functions
|
|
1511
|
-
// ============================================
|
|
1512
|
-
function getComponent() {
|
|
1513
|
-
return window.__frontmcp_component;
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1516
|
-
function getToolOutput() {
|
|
1517
|
-
// Try OpenAI's toolOutput first
|
|
1518
|
-
if (window.openai && window.openai.toolOutput) {
|
|
1519
|
-
return window.openai.toolOutput;
|
|
1520
|
-
}
|
|
1521
|
-
// Try FrontMCP bridge
|
|
1522
|
-
if (window.__mcpToolOutput) {
|
|
1523
|
-
return window.__mcpToolOutput;
|
|
1524
|
-
}
|
|
1525
|
-
// Try __frontmcp namespace
|
|
1526
|
-
if (window.__frontmcp && window.__frontmcp.toolOutput) {
|
|
1527
|
-
return window.__frontmcp.toolOutput;
|
|
1528
|
-
}
|
|
1529
|
-
return null;
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1532
|
-
function showLoader() {
|
|
1533
|
-
const loader = document.getElementById('frontmcp-loader');
|
|
1534
|
-
if (loader) loader.style.display = 'flex';
|
|
1535
|
-
}
|
|
1536
|
-
|
|
1537
|
-
function hideLoader() {
|
|
1538
|
-
const loader = document.getElementById('frontmcp-loader');
|
|
1539
|
-
if (loader) loader.style.display = 'none';
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
function showError(message) {
|
|
1543
|
-
const errorEl = document.getElementById('frontmcp-error');
|
|
1544
|
-
if (errorEl) {
|
|
1545
|
-
errorEl.textContent = message;
|
|
1546
|
-
errorEl.style.display = 'block';
|
|
1547
|
-
}
|
|
1548
|
-
hideLoader();
|
|
1549
|
-
}
|
|
1550
|
-
|
|
1551
|
-
// ============================================
|
|
1552
|
-
// 4. Render Function
|
|
1553
|
-
// ============================================
|
|
1554
|
-
function renderComponent() {
|
|
1555
|
-
const Component = getComponent();
|
|
1556
|
-
if (!Component) {
|
|
1557
|
-
console.warn('[FrontMCP] No component registered for client-side rendering');
|
|
1558
|
-
showError('Component not found');
|
|
1559
|
-
return false;
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
const output = getToolOutput();
|
|
1563
|
-
if (!output) {
|
|
1564
|
-
return false; // Not ready yet, keep polling
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
// Find or create widget root
|
|
1568
|
-
// OpenAI may have removed our original root element during iframe setup
|
|
1569
|
-
// when their wrapper script overwrites #widget-root with a loading spinner
|
|
1570
|
-
let root = document.getElementById('frontmcp-widget-root');
|
|
1571
|
-
if (!root) {
|
|
1572
|
-
console.log('[FrontMCP] Widget root not found, creating new element');
|
|
1573
|
-
|
|
1574
|
-
// Look for OpenAI's container first - we should render inside it
|
|
1575
|
-
const openaiRoot = document.getElementById('widget-root');
|
|
1576
|
-
|
|
1577
|
-
if (openaiRoot) {
|
|
1578
|
-
// Clear OpenAI's wrapper content and create our root inside
|
|
1579
|
-
console.log('[FrontMCP] Found OpenAI widget-root, creating frontmcp-widget-root inside it');
|
|
1580
|
-
openaiRoot.innerHTML = '';
|
|
1581
|
-
root = document.createElement('div');
|
|
1582
|
-
root.id = 'frontmcp-widget-root';
|
|
1583
|
-
openaiRoot.appendChild(root);
|
|
1584
|
-
} else {
|
|
1585
|
-
// Fallback: create in body (for MCP Inspector, etc.)
|
|
1586
|
-
console.log('[FrontMCP] No OpenAI widget-root, creating in body');
|
|
1587
|
-
root = document.createElement('div');
|
|
1588
|
-
root.id = 'frontmcp-widget-root';
|
|
1589
|
-
document.body.innerHTML = '';
|
|
1590
|
-
document.body.appendChild(root);
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1593
|
-
|
|
1594
|
-
// Ensure it's visible
|
|
1595
|
-
root.style.display = 'block';
|
|
1596
|
-
|
|
1597
|
-
try {
|
|
1598
|
-
// Build props
|
|
1599
|
-
const props = {
|
|
1600
|
-
input: window.__mcpToolInput || {},
|
|
1601
|
-
output: output,
|
|
1602
|
-
structuredContent: window.__mcpStructuredContent,
|
|
1603
|
-
helpers: {
|
|
1604
|
-
escapeHtml: (str) => String(str).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c] || c),
|
|
1605
|
-
formatDate: (d) => new Date(d).toLocaleDateString(),
|
|
1606
|
-
formatCurrency: (a, c) => new Intl.NumberFormat('en-US', {style:'currency',currency:c||'USD'}).format(a),
|
|
1607
|
-
}
|
|
1608
|
-
};
|
|
1609
|
-
|
|
1610
|
-
// Hide loader and show widget root before rendering
|
|
1611
|
-
hideLoader();
|
|
1612
|
-
root.style.display = 'block';
|
|
1613
|
-
|
|
1614
|
-
// Render with React 19
|
|
1615
|
-
const element = React.createElement(Component, props);
|
|
1616
|
-
const reactRoot = ReactDOM.createRoot(root);
|
|
1617
|
-
reactRoot.render(element);
|
|
1618
|
-
console.log('[FrontMCP] Component rendered successfully with data:', output);
|
|
1619
|
-
|
|
1620
|
-
// Mark React as mounted to prevent OpenAI wrapper from overwriting
|
|
1621
|
-
// This works with the renderContent override in the Tool Metadata script
|
|
1622
|
-
window.__frontmcp = window.__frontmcp || {};
|
|
1623
|
-
window.__frontmcp._reactMounted = true;
|
|
1624
|
-
|
|
1625
|
-
// For inline mode: prevent OpenAI's wrapper from re-rendering over us
|
|
1626
|
-
// The wrapper subscribes to bridge state changes and will overwrite our content
|
|
1627
|
-
// when bridge.setData is called. We disable this after initial render.
|
|
1628
|
-
if (window.__mcpDataEmbedded && window.__frontmcp && window.__frontmcp.bridge) {
|
|
1629
|
-
window.__frontmcp._inlineRendered = true;
|
|
1630
|
-
|
|
1631
|
-
// Override setData to no-op after inline render
|
|
1632
|
-
const originalSetData = window.__frontmcp.bridge.setData;
|
|
1633
|
-
if (originalSetData && !window.__frontmcp._setDataOverridden) {
|
|
1634
|
-
window.__frontmcp._setDataOverridden = true;
|
|
1635
|
-
window.__frontmcp.bridge.setData = function(data) {
|
|
1636
|
-
if (window.__frontmcp._inlineRendered) {
|
|
1637
|
-
console.log('[FrontMCP] Skipping bridge setData - inline mode already rendered');
|
|
1638
|
-
return;
|
|
1639
|
-
}
|
|
1640
|
-
return originalSetData.call(this, data);
|
|
1641
|
-
};
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
|
|
1645
|
-
return true;
|
|
1646
|
-
} catch (e) {
|
|
1647
|
-
console.error('[FrontMCP] React rendering failed:', e);
|
|
1648
|
-
showError('Rendering failed: ' + e.message);
|
|
1649
|
-
return false;
|
|
1650
|
-
}
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
// ============================================
|
|
1654
|
-
// 5. Main: Render immediately or poll for toolOutput
|
|
1655
|
-
// ============================================
|
|
1656
|
-
// For inline mode (embeddedData): data is already embedded, render immediately
|
|
1657
|
-
// For static mode: poll for window.openai.toolOutput
|
|
1658
|
-
|
|
1659
|
-
if (window.__mcpDataEmbedded) {
|
|
1660
|
-
// Inline mode: Data is embedded in HTML, render immediately
|
|
1661
|
-
console.log('[FrontMCP] Inline mode: data embedded, rendering immediately');
|
|
1662
|
-
if (!renderComponent()) {
|
|
1663
|
-
showError('Failed to render component');
|
|
1664
|
-
}
|
|
1665
|
-
} else {
|
|
1666
|
-
// MCP-resource mode: Poll for toolOutput from host platform
|
|
1667
|
-
showLoader();
|
|
1668
|
-
|
|
1669
|
-
let attempts = 0;
|
|
1670
|
-
const maxAttempts = 100; // 10 seconds max
|
|
1671
|
-
const pollInterval = setInterval(() => {
|
|
1672
|
-
attempts++;
|
|
1673
|
-
if (renderComponent()) {
|
|
1674
|
-
clearInterval(pollInterval);
|
|
1675
|
-
} else if (attempts >= maxAttempts) {
|
|
1676
|
-
clearInterval(pollInterval);
|
|
1677
|
-
if (!getToolOutput()) {
|
|
1678
|
-
console.warn('[FrontMCP] Timeout waiting for toolOutput');
|
|
1679
|
-
showError('Timeout waiting for data');
|
|
1680
|
-
}
|
|
1681
|
-
}
|
|
1682
|
-
}, 100);
|
|
1683
|
-
}
|
|
1684
|
-
</script>`
|
|
1685
|
-
: '';
|
|
1686
|
-
// Page title
|
|
1687
|
-
const pageTitle = title || `${(0, base_1.escapeHtml)(toolName)} - Tool Widget`;
|
|
1688
|
-
// Build loading indicator and error display
|
|
1689
|
-
// Skip loader for inline mode - data is already embedded, SSR content is visible immediately
|
|
1690
|
-
const loaderHtml = isReactBased && componentCode && !hasEmbeddedData
|
|
1691
|
-
? `
|
|
1692
|
-
<!-- Loading State -->
|
|
1693
|
-
<div id="frontmcp-loader" style="display: flex; align-items: center; justify-content: center; padding: 2rem; gap: 0.5rem;">
|
|
1694
|
-
<svg class="animate-spin" style="width: 1.25rem; height: 1.25rem; color: #6b7280;" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
1695
|
-
<circle style="opacity: 0.25;" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
1696
|
-
<path style="opacity: 0.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>
|
|
1697
|
-
</svg>
|
|
1698
|
-
<span style="color: #6b7280; font-size: 0.875rem;">Loading widget...</span>
|
|
1699
|
-
</div>
|
|
1700
|
-
<div id="frontmcp-error" style="display: none; padding: 1rem; margin: 1rem; background: #fef2f2; border: 1px solid #fecaca; border-radius: 0.5rem; color: #dc2626; font-size: 0.875rem;"></div>
|
|
1701
|
-
`
|
|
1702
|
-
: '';
|
|
1703
|
-
// Wrap SSR content in a root element for React to render into
|
|
1704
|
-
// For static mode: widget root is hidden until data arrives (loader shows first)
|
|
1705
|
-
// For inline mode: widget root is VISIBLE immediately (data is embedded, SSR is rendered)
|
|
1706
|
-
const widgetRootStyle = hasEmbeddedData ? '' : 'display: none;';
|
|
1707
|
-
const wrappedContent = isReactBased && componentCode
|
|
1708
|
-
? `${loaderHtml}<div id="frontmcp-widget-root" style="${widgetRootStyle}">${ssrContent}</div>`
|
|
1709
|
-
: ssrContent;
|
|
1710
|
-
return `<!DOCTYPE html>
|
|
1711
|
-
<html lang="en">
|
|
1712
|
-
<head>
|
|
1713
|
-
<meta charset="UTF-8">
|
|
1714
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1715
|
-
<title>${pageTitle}</title>
|
|
1716
|
-
${cspMetaTag}
|
|
1717
|
-
|
|
1718
|
-
<!-- Fonts -->
|
|
1719
|
-
${fontPreconnect}
|
|
1720
|
-
${fontStylesheets}
|
|
1721
|
-
|
|
1722
|
-
<!-- Tailwind CSS -->
|
|
1723
|
-
${scripts}
|
|
1724
|
-
${styleBlock}
|
|
1725
|
-
|
|
1726
|
-
<!-- Spinner Animation -->
|
|
1727
|
-
<style>
|
|
1728
|
-
@keyframes spin { to { transform: rotate(360deg); } }
|
|
1729
|
-
.animate-spin { animation: spin 1s linear infinite; }
|
|
1730
|
-
</style>
|
|
1731
|
-
|
|
1732
|
-
<!-- Tool Metadata -->
|
|
1733
|
-
${toolNameScript}
|
|
1734
|
-
|
|
1735
|
-
<!-- FrontMCP Bridge (Universal - Reads data from host at runtime) -->
|
|
1736
|
-
${bridgeScript}
|
|
1737
|
-
</head>
|
|
1738
|
-
<body class="bg-background text-text-primary font-sans antialiased">
|
|
1739
|
-
${wrappedContent}
|
|
1740
|
-
${reactModuleScript}
|
|
1741
|
-
</body>
|
|
1742
|
-
</html>`;
|
|
1743
|
-
}
|
|
1744
|
-
// ============================================
|
|
1745
|
-
// OpenAI-Specific Functions
|
|
1746
|
-
// ============================================
|
|
1747
|
-
/**
|
|
1748
|
-
* Build OpenAI Apps SDK specific meta annotations.
|
|
1749
|
-
* These are placed in _meta field of the tool response.
|
|
1750
|
-
*/
|
|
1751
|
-
function buildOpenAIMeta(options) {
|
|
1752
|
-
const meta = {};
|
|
1753
|
-
// Widget accessibility
|
|
1754
|
-
if (options.widgetAccessible) {
|
|
1755
|
-
meta['openai/widgetAccessible'] = true;
|
|
1756
|
-
}
|
|
1757
|
-
// Widget description
|
|
1758
|
-
if (options.widgetDescription) {
|
|
1759
|
-
meta['openai/widgetDescription'] = options.widgetDescription;
|
|
1760
|
-
}
|
|
1761
|
-
// CSP configuration
|
|
1762
|
-
if (options.csp) {
|
|
1763
|
-
const cspConfig = {};
|
|
1764
|
-
if (options.csp.connectDomains?.length) {
|
|
1765
|
-
cspConfig['connect_domains'] = options.csp.connectDomains;
|
|
1766
|
-
}
|
|
1767
|
-
if (options.csp.resourceDomains?.length) {
|
|
1768
|
-
cspConfig['resource_domains'] = options.csp.resourceDomains;
|
|
1769
|
-
}
|
|
1770
|
-
if (Object.keys(cspConfig).length > 0) {
|
|
1771
|
-
meta['openai/widgetCSP'] = cspConfig;
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
// Display mode hint
|
|
1775
|
-
if (options.displayMode && options.displayMode !== 'inline') {
|
|
1776
|
-
meta['openai/displayMode'] = options.displayMode;
|
|
1777
|
-
}
|
|
1778
|
-
return meta;
|
|
1779
|
-
}
|
|
1780
|
-
/**
|
|
1781
|
-
* Get the MIME type for tool UI responses based on target platform
|
|
1782
|
-
*/
|
|
1783
|
-
function getToolUIMimeType(platform = 'generic') {
|
|
1784
|
-
switch (platform) {
|
|
1785
|
-
case 'openai':
|
|
1786
|
-
return 'text/html+skybridge';
|
|
1787
|
-
case 'ext-apps':
|
|
1788
|
-
return 'text/html+mcp';
|
|
1789
|
-
default:
|
|
1790
|
-
return 'text/html';
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
//# sourceMappingURL=wrapper.js.map
|