@frontmcp/ui 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bridge/core/bridge-factory.d.ts +1 -0
- package/bridge/core/bridge-factory.d.ts.map +1 -1
- package/bridge/index.d.ts +1 -1
- package/bridge/index.d.ts.map +1 -1
- package/bridge/index.js +39 -881
- package/bundler/browser-components.d.ts +42 -0
- package/bundler/browser-components.d.ts.map +1 -0
- package/bundler/bundler.d.ts +78 -4
- package/bundler/bundler.d.ts.map +1 -1
- package/bundler/index.d.ts +8 -8
- package/bundler/index.d.ts.map +1 -1
- package/bundler/index.js +1315 -1854
- package/bundler/types.d.ts +188 -7
- package/bundler/types.d.ts.map +1 -1
- package/esm/bridge/{index.js → index.mjs} +40 -877
- package/esm/bundler/{index.js → index.mjs} +1391 -1895
- package/esm/{index.js → index.mjs} +215 -3091
- package/esm/layouts/{index.js → index.mjs} +3 -3
- package/esm/package.json +9 -8
- package/esm/react/index.mjs +1183 -0
- package/esm/renderers/index.mjs +611 -0
- package/esm/universal/{index.js → index.mjs} +266 -70
- package/index.d.ts +1 -4
- package/index.d.ts.map +1 -1
- package/index.js +208 -3113
- package/layouts/base.d.ts.map +1 -1
- package/layouts/index.js +3 -3
- package/layouts/presets.d.ts.map +1 -1
- package/package.json +9 -8
- package/react/Badge.d.ts.map +1 -1
- package/react/hooks/context.d.ts.map +1 -1
- package/react/index.d.ts +0 -1
- package/react/index.d.ts.map +1 -1
- package/react/index.js +57 -2001
- package/react/types.d.ts.map +1 -1
- package/renderers/index.d.ts +9 -4
- package/renderers/index.d.ts.map +1 -1
- package/renderers/index.js +328 -88
- package/renderers/mdx.renderer.d.ts +99 -0
- package/renderers/mdx.renderer.d.ts.map +1 -0
- package/renderers/react.renderer.d.ts +22 -13
- package/renderers/react.renderer.d.ts.map +1 -1
- package/renderers/transpiler.d.ts +49 -0
- package/renderers/transpiler.d.ts.map +1 -0
- package/universal/cached-runtime.d.ts +25 -1
- package/universal/cached-runtime.d.ts.map +1 -1
- package/universal/index.js +266 -70
- package/universal/runtime-builder.d.ts.map +1 -1
- package/universal/types.d.ts.map +1 -1
- package/web-components/elements/fmcp-input.d.ts.map +1 -1
- package/web-components/elements/fmcp-select.d.ts.map +1 -1
- package/web-components/index.d.ts +0 -1
- package/web-components/index.d.ts.map +1 -1
- package/bundler/cache.d.ts +0 -173
- package/bundler/cache.d.ts.map +0 -1
- package/bundler/file-cache/component-builder.d.ts +0 -167
- package/bundler/file-cache/component-builder.d.ts.map +0 -1
- package/bundler/file-cache/hash-calculator.d.ts +0 -155
- package/bundler/file-cache/hash-calculator.d.ts.map +0 -1
- package/bundler/file-cache/index.d.ts +0 -12
- package/bundler/file-cache/index.d.ts.map +0 -1
- package/bundler/file-cache/storage/filesystem.d.ts +0 -149
- package/bundler/file-cache/storage/filesystem.d.ts.map +0 -1
- package/bundler/file-cache/storage/index.d.ts +0 -11
- package/bundler/file-cache/storage/index.d.ts.map +0 -1
- package/bundler/file-cache/storage/interface.d.ts +0 -152
- package/bundler/file-cache/storage/interface.d.ts.map +0 -1
- package/bundler/file-cache/storage/redis.d.ts +0 -139
- package/bundler/file-cache/storage/redis.d.ts.map +0 -1
- package/bundler/sandbox/enclave-adapter.d.ts +0 -121
- package/bundler/sandbox/enclave-adapter.d.ts.map +0 -1
- package/bundler/sandbox/executor.d.ts +0 -14
- package/bundler/sandbox/executor.d.ts.map +0 -1
- package/bundler/sandbox/policy.d.ts +0 -62
- package/bundler/sandbox/policy.d.ts.map +0 -1
- package/esm/bridge/adapters/base-adapter.d.ts +0 -104
- package/esm/bridge/adapters/base-adapter.d.ts.map +0 -1
- package/esm/bridge/adapters/claude.adapter.d.ts +0 -67
- package/esm/bridge/adapters/claude.adapter.d.ts.map +0 -1
- package/esm/bridge/adapters/ext-apps.adapter.d.ts +0 -143
- package/esm/bridge/adapters/ext-apps.adapter.d.ts.map +0 -1
- package/esm/bridge/adapters/gemini.adapter.d.ts +0 -64
- package/esm/bridge/adapters/gemini.adapter.d.ts.map +0 -1
- package/esm/bridge/adapters/generic.adapter.d.ts +0 -56
- package/esm/bridge/adapters/generic.adapter.d.ts.map +0 -1
- package/esm/bridge/adapters/index.d.ts +0 -26
- package/esm/bridge/adapters/index.d.ts.map +0 -1
- package/esm/bridge/adapters/openai.adapter.d.ts +0 -65
- package/esm/bridge/adapters/openai.adapter.d.ts.map +0 -1
- package/esm/bridge/core/adapter-registry.d.ts +0 -122
- package/esm/bridge/core/adapter-registry.d.ts.map +0 -1
- package/esm/bridge/core/bridge-factory.d.ts +0 -199
- package/esm/bridge/core/bridge-factory.d.ts.map +0 -1
- package/esm/bridge/core/index.d.ts +0 -10
- package/esm/bridge/core/index.d.ts.map +0 -1
- package/esm/bridge/index.d.ts +0 -62
- package/esm/bridge/index.d.ts.map +0 -1
- package/esm/bridge/runtime/iife-generator.d.ts +0 -62
- package/esm/bridge/runtime/iife-generator.d.ts.map +0 -1
- package/esm/bridge/runtime/index.d.ts +0 -10
- package/esm/bridge/runtime/index.d.ts.map +0 -1
- package/esm/bridge/types.d.ts +0 -386
- package/esm/bridge/types.d.ts.map +0 -1
- package/esm/bundler/bundler.d.ts +0 -208
- package/esm/bundler/bundler.d.ts.map +0 -1
- package/esm/bundler/cache.d.ts +0 -173
- package/esm/bundler/cache.d.ts.map +0 -1
- package/esm/bundler/file-cache/component-builder.d.ts +0 -167
- package/esm/bundler/file-cache/component-builder.d.ts.map +0 -1
- package/esm/bundler/file-cache/hash-calculator.d.ts +0 -155
- package/esm/bundler/file-cache/hash-calculator.d.ts.map +0 -1
- package/esm/bundler/file-cache/index.d.ts +0 -12
- package/esm/bundler/file-cache/index.d.ts.map +0 -1
- package/esm/bundler/file-cache/storage/filesystem.d.ts +0 -149
- package/esm/bundler/file-cache/storage/filesystem.d.ts.map +0 -1
- package/esm/bundler/file-cache/storage/index.d.ts +0 -11
- package/esm/bundler/file-cache/storage/index.d.ts.map +0 -1
- package/esm/bundler/file-cache/storage/interface.d.ts +0 -152
- package/esm/bundler/file-cache/storage/interface.d.ts.map +0 -1
- package/esm/bundler/file-cache/storage/redis.d.ts +0 -139
- package/esm/bundler/file-cache/storage/redis.d.ts.map +0 -1
- package/esm/bundler/index.d.ts +0 -43
- package/esm/bundler/index.d.ts.map +0 -1
- package/esm/bundler/sandbox/enclave-adapter.d.ts +0 -121
- package/esm/bundler/sandbox/enclave-adapter.d.ts.map +0 -1
- package/esm/bundler/sandbox/executor.d.ts +0 -14
- package/esm/bundler/sandbox/executor.d.ts.map +0 -1
- package/esm/bundler/sandbox/policy.d.ts +0 -62
- package/esm/bundler/sandbox/policy.d.ts.map +0 -1
- package/esm/bundler/types.d.ts +0 -702
- package/esm/bundler/types.d.ts.map +0 -1
- package/esm/components/alert.d.ts +0 -66
- package/esm/components/alert.d.ts.map +0 -1
- package/esm/components/alert.schema.d.ts +0 -98
- package/esm/components/alert.schema.d.ts.map +0 -1
- package/esm/components/avatar.d.ts +0 -77
- package/esm/components/avatar.d.ts.map +0 -1
- package/esm/components/avatar.schema.d.ts +0 -170
- package/esm/components/avatar.schema.d.ts.map +0 -1
- package/esm/components/badge.d.ts +0 -64
- package/esm/components/badge.d.ts.map +0 -1
- package/esm/components/badge.schema.d.ts +0 -91
- package/esm/components/badge.schema.d.ts.map +0 -1
- package/esm/components/button.d.ts +0 -100
- package/esm/components/button.d.ts.map +0 -1
- package/esm/components/button.schema.d.ts +0 -120
- package/esm/components/button.schema.d.ts.map +0 -1
- package/esm/components/card.d.ts +0 -53
- package/esm/components/card.d.ts.map +0 -1
- package/esm/components/card.schema.d.ts +0 -93
- package/esm/components/card.schema.d.ts.map +0 -1
- package/esm/components/form.d.ts +0 -212
- package/esm/components/form.d.ts.map +0 -1
- package/esm/components/form.schema.d.ts +0 -365
- package/esm/components/form.schema.d.ts.map +0 -1
- package/esm/components/index.d.ts +0 -29
- package/esm/components/index.d.ts.map +0 -1
- package/esm/components/list.d.ts +0 -121
- package/esm/components/list.d.ts.map +0 -1
- package/esm/components/list.schema.d.ts +0 -129
- package/esm/components/list.schema.d.ts.map +0 -1
- package/esm/components/modal.d.ts +0 -100
- package/esm/components/modal.d.ts.map +0 -1
- package/esm/components/modal.schema.d.ts +0 -151
- package/esm/components/modal.schema.d.ts.map +0 -1
- package/esm/components/table.d.ts +0 -91
- package/esm/components/table.d.ts.map +0 -1
- package/esm/components/table.schema.d.ts +0 -123
- package/esm/components/table.schema.d.ts.map +0 -1
- package/esm/index.d.ts +0 -40
- package/esm/index.d.ts.map +0 -1
- package/esm/layouts/base.d.ts +0 -86
- package/esm/layouts/base.d.ts.map +0 -1
- package/esm/layouts/index.d.ts +0 -8
- package/esm/layouts/index.d.ts.map +0 -1
- package/esm/layouts/presets.d.ts +0 -134
- package/esm/layouts/presets.d.ts.map +0 -1
- package/esm/pages/consent.d.ts +0 -117
- package/esm/pages/consent.d.ts.map +0 -1
- package/esm/pages/error.d.ts +0 -101
- package/esm/pages/error.d.ts.map +0 -1
- package/esm/pages/index.d.ts +0 -9
- package/esm/pages/index.d.ts.map +0 -1
- package/esm/pages/index.js +0 -1036
- package/esm/react/Alert.d.ts +0 -101
- package/esm/react/Alert.d.ts.map +0 -1
- package/esm/react/Badge.d.ts +0 -100
- package/esm/react/Badge.d.ts.map +0 -1
- package/esm/react/Button.d.ts +0 -108
- package/esm/react/Button.d.ts.map +0 -1
- package/esm/react/Card.d.ts +0 -103
- package/esm/react/Card.d.ts.map +0 -1
- package/esm/react/hooks/context.d.ts +0 -179
- package/esm/react/hooks/context.d.ts.map +0 -1
- package/esm/react/hooks/index.d.ts +0 -42
- package/esm/react/hooks/index.d.ts.map +0 -1
- package/esm/react/hooks/tools.d.ts +0 -284
- package/esm/react/hooks/tools.d.ts.map +0 -1
- package/esm/react/index.d.ts +0 -80
- package/esm/react/index.d.ts.map +0 -1
- package/esm/react/index.js +0 -3124
- package/esm/react/types.d.ts +0 -105
- package/esm/react/types.d.ts.map +0 -1
- package/esm/react/utils.d.ts +0 -43
- package/esm/react/utils.d.ts.map +0 -1
- package/esm/render/index.d.ts +0 -8
- package/esm/render/index.d.ts.map +0 -1
- package/esm/render/prerender.d.ts +0 -57
- package/esm/render/prerender.d.ts.map +0 -1
- package/esm/renderers/index.d.ts +0 -21
- package/esm/renderers/index.d.ts.map +0 -1
- package/esm/renderers/index.js +0 -381
- package/esm/renderers/react.adapter.d.ts +0 -70
- package/esm/renderers/react.adapter.d.ts.map +0 -1
- package/esm/renderers/react.renderer.d.ts +0 -96
- package/esm/renderers/react.renderer.d.ts.map +0 -1
- package/esm/universal/UniversalApp.d.ts +0 -108
- package/esm/universal/UniversalApp.d.ts.map +0 -1
- package/esm/universal/cached-runtime.d.ts +0 -115
- package/esm/universal/cached-runtime.d.ts.map +0 -1
- package/esm/universal/context.d.ts +0 -122
- package/esm/universal/context.d.ts.map +0 -1
- package/esm/universal/index.d.ts +0 -57
- package/esm/universal/index.d.ts.map +0 -1
- package/esm/universal/renderers/html.renderer.d.ts +0 -37
- package/esm/universal/renderers/html.renderer.d.ts.map +0 -1
- package/esm/universal/renderers/index.d.ts +0 -112
- package/esm/universal/renderers/index.d.ts.map +0 -1
- package/esm/universal/renderers/markdown.renderer.d.ts +0 -33
- package/esm/universal/renderers/markdown.renderer.d.ts.map +0 -1
- package/esm/universal/renderers/mdx.renderer.d.ts +0 -38
- package/esm/universal/renderers/mdx.renderer.d.ts.map +0 -1
- package/esm/universal/renderers/react.renderer.d.ts +0 -46
- package/esm/universal/renderers/react.renderer.d.ts.map +0 -1
- package/esm/universal/runtime-builder.d.ts +0 -33
- package/esm/universal/runtime-builder.d.ts.map +0 -1
- package/esm/universal/store.d.ts +0 -135
- package/esm/universal/store.d.ts.map +0 -1
- package/esm/universal/types.d.ts +0 -199
- package/esm/universal/types.d.ts.map +0 -1
- package/esm/web-components/core/attribute-parser.d.ts +0 -82
- package/esm/web-components/core/attribute-parser.d.ts.map +0 -1
- package/esm/web-components/core/base-element.d.ts +0 -197
- package/esm/web-components/core/base-element.d.ts.map +0 -1
- package/esm/web-components/core/index.d.ts +0 -9
- package/esm/web-components/core/index.d.ts.map +0 -1
- package/esm/web-components/elements/fmcp-alert.d.ts +0 -46
- package/esm/web-components/elements/fmcp-alert.d.ts.map +0 -1
- package/esm/web-components/elements/fmcp-badge.d.ts +0 -47
- package/esm/web-components/elements/fmcp-badge.d.ts.map +0 -1
- package/esm/web-components/elements/fmcp-button.d.ts +0 -117
- package/esm/web-components/elements/fmcp-button.d.ts.map +0 -1
- package/esm/web-components/elements/fmcp-card.d.ts +0 -53
- package/esm/web-components/elements/fmcp-card.d.ts.map +0 -1
- package/esm/web-components/elements/fmcp-input.d.ts +0 -96
- package/esm/web-components/elements/fmcp-input.d.ts.map +0 -1
- package/esm/web-components/elements/fmcp-select.d.ts +0 -100
- package/esm/web-components/elements/fmcp-select.d.ts.map +0 -1
- package/esm/web-components/elements/index.d.ts +0 -13
- package/esm/web-components/elements/index.d.ts.map +0 -1
- package/esm/web-components/index.d.ts +0 -50
- package/esm/web-components/index.d.ts.map +0 -1
- package/esm/web-components/register.d.ts +0 -57
- package/esm/web-components/register.d.ts.map +0 -1
- package/esm/web-components/types.d.ts +0 -122
- package/esm/web-components/types.d.ts.map +0 -1
- package/esm/widgets/index.d.ts +0 -8
- package/esm/widgets/index.d.ts.map +0 -1
- package/esm/widgets/index.js +0 -883
- package/esm/widgets/progress.d.ts +0 -133
- package/esm/widgets/progress.d.ts.map +0 -1
- package/esm/widgets/resource.d.ts +0 -163
- package/esm/widgets/resource.d.ts.map +0 -1
- package/pages/consent.d.ts +0 -117
- package/pages/consent.d.ts.map +0 -1
- package/pages/error.d.ts +0 -101
- package/pages/error.d.ts.map +0 -1
- package/pages/index.d.ts +0 -9
- package/pages/index.d.ts.map +0 -1
- package/pages/index.js +0 -1065
- package/react/utils.d.ts +0 -43
- package/react/utils.d.ts.map +0 -1
- package/widgets/index.d.ts +0 -8
- package/widgets/index.d.ts.map +0 -1
- package/widgets/index.js +0 -910
- package/widgets/progress.d.ts +0 -133
- package/widgets/progress.d.ts.map +0 -1
- package/widgets/resource.d.ts +0 -163
- package/widgets/resource.d.ts.map +0 -1
- /package/esm/components/{index.js → index.mjs} +0 -0
- /package/esm/render/{index.js → index.mjs} +0 -0
- /package/esm/web-components/{index.js → index.mjs} +0 -0
|
@@ -0,0 +1,1183 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// libs/ui/src/react/Card.tsx
|
|
9
|
+
import {
|
|
10
|
+
getCardVariantClasses,
|
|
11
|
+
getCardSizeClasses,
|
|
12
|
+
cn
|
|
13
|
+
} from "@frontmcp/uipack/styles";
|
|
14
|
+
|
|
15
|
+
// libs/ui/src/render/prerender.ts
|
|
16
|
+
async function renderToString(element) {
|
|
17
|
+
const { prerender } = await import("react-dom/static");
|
|
18
|
+
const { prelude } = await prerender(element);
|
|
19
|
+
const reader = prelude.getReader();
|
|
20
|
+
const chunks = [];
|
|
21
|
+
while (true) {
|
|
22
|
+
const { done, value } = await reader.read();
|
|
23
|
+
if (done) break;
|
|
24
|
+
if (value) chunks.push(value);
|
|
25
|
+
}
|
|
26
|
+
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
27
|
+
const combined = new Uint8Array(totalLength);
|
|
28
|
+
let offset = 0;
|
|
29
|
+
for (const chunk of chunks) {
|
|
30
|
+
combined.set(chunk, offset);
|
|
31
|
+
offset += chunk.length;
|
|
32
|
+
}
|
|
33
|
+
return new TextDecoder().decode(combined);
|
|
34
|
+
}
|
|
35
|
+
function renderToStringSync(element) {
|
|
36
|
+
const ReactDOMServer = __require("react-dom/server");
|
|
37
|
+
return ReactDOMServer.renderToStaticMarkup(element);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// libs/ui/src/react/Card.tsx
|
|
41
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
42
|
+
function Card({
|
|
43
|
+
title,
|
|
44
|
+
subtitle,
|
|
45
|
+
headerActions,
|
|
46
|
+
footer,
|
|
47
|
+
variant = "default",
|
|
48
|
+
size = "md",
|
|
49
|
+
className,
|
|
50
|
+
id,
|
|
51
|
+
clickable,
|
|
52
|
+
href,
|
|
53
|
+
children
|
|
54
|
+
}) {
|
|
55
|
+
const variantClasses = getCardVariantClasses(variant);
|
|
56
|
+
const sizeClasses = getCardSizeClasses(size);
|
|
57
|
+
const clickableClasses = clickable ? "cursor-pointer hover:shadow-md transition-shadow" : "";
|
|
58
|
+
const allClasses = cn(variantClasses, sizeClasses, clickableClasses, className);
|
|
59
|
+
const hasHeader = title || subtitle || headerActions;
|
|
60
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
61
|
+
hasHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-4", children: [
|
|
62
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
63
|
+
title && /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-text-primary", children: title }),
|
|
64
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary mt-1", children: subtitle })
|
|
65
|
+
] }),
|
|
66
|
+
headerActions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: headerActions })
|
|
67
|
+
] }),
|
|
68
|
+
children,
|
|
69
|
+
footer && /* @__PURE__ */ jsx("div", { className: "mt-4 pt-4 border-t border-divider", children: footer })
|
|
70
|
+
] });
|
|
71
|
+
if (href) {
|
|
72
|
+
return /* @__PURE__ */ jsx("a", { href, className: allClasses, id, children: content });
|
|
73
|
+
}
|
|
74
|
+
return /* @__PURE__ */ jsx("div", { className: allClasses, id, children: content });
|
|
75
|
+
}
|
|
76
|
+
async function renderCard(props) {
|
|
77
|
+
const { children, headerActions, footer, ...rest } = props;
|
|
78
|
+
const element = /* @__PURE__ */ jsx(
|
|
79
|
+
Card,
|
|
80
|
+
{
|
|
81
|
+
...rest,
|
|
82
|
+
headerActions: headerActions ? /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: headerActions } }) : void 0,
|
|
83
|
+
footer: footer ? /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: footer } }) : void 0,
|
|
84
|
+
children: children ? /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: children } }) : void 0
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
return renderToString(element);
|
|
88
|
+
}
|
|
89
|
+
function renderCardSync(props) {
|
|
90
|
+
const { children, headerActions, footer, ...rest } = props;
|
|
91
|
+
const element = /* @__PURE__ */ jsx(
|
|
92
|
+
Card,
|
|
93
|
+
{
|
|
94
|
+
...rest,
|
|
95
|
+
headerActions: headerActions ? /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: headerActions } }) : void 0,
|
|
96
|
+
footer: footer ? /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: footer } }) : void 0,
|
|
97
|
+
children: children ? /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: children } }) : void 0
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
return renderToStringSync(element);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// libs/ui/src/react/Badge.tsx
|
|
104
|
+
import {
|
|
105
|
+
getBadgeVariantClasses,
|
|
106
|
+
getBadgeSizeClasses,
|
|
107
|
+
getBadgeDotSizeClasses,
|
|
108
|
+
getBadgeDotVariantClasses,
|
|
109
|
+
cn as cn2
|
|
110
|
+
} from "@frontmcp/uipack/styles";
|
|
111
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
112
|
+
function Badge({
|
|
113
|
+
variant = "default",
|
|
114
|
+
size = "md",
|
|
115
|
+
pill = false,
|
|
116
|
+
icon,
|
|
117
|
+
dot = false,
|
|
118
|
+
className,
|
|
119
|
+
removable = false,
|
|
120
|
+
onRemove,
|
|
121
|
+
children
|
|
122
|
+
}) {
|
|
123
|
+
if (dot) {
|
|
124
|
+
const dotClasses = cn2(
|
|
125
|
+
"inline-block rounded-full",
|
|
126
|
+
getBadgeDotSizeClasses(size),
|
|
127
|
+
getBadgeDotVariantClasses(variant),
|
|
128
|
+
className
|
|
129
|
+
);
|
|
130
|
+
const label = typeof children === "string" ? children : void 0;
|
|
131
|
+
return /* @__PURE__ */ jsx2("span", { className: dotClasses, "aria-label": label, title: label });
|
|
132
|
+
}
|
|
133
|
+
const variantClasses = getBadgeVariantClasses(variant);
|
|
134
|
+
const sizeClasses = getBadgeSizeClasses(size);
|
|
135
|
+
const baseClasses = cn2(
|
|
136
|
+
"inline-flex items-center font-medium",
|
|
137
|
+
pill ? "rounded-full" : "rounded-md",
|
|
138
|
+
variantClasses,
|
|
139
|
+
sizeClasses,
|
|
140
|
+
className
|
|
141
|
+
);
|
|
142
|
+
return /* @__PURE__ */ jsxs2("span", { className: baseClasses, children: [
|
|
143
|
+
icon && /* @__PURE__ */ jsx2("span", { className: "mr-1", children: icon }),
|
|
144
|
+
children,
|
|
145
|
+
removable && /* @__PURE__ */ jsx2(
|
|
146
|
+
"button",
|
|
147
|
+
{
|
|
148
|
+
type: "button",
|
|
149
|
+
className: "ml-1.5 -mr-1 hover:opacity-70 transition-opacity",
|
|
150
|
+
"aria-label": "Remove",
|
|
151
|
+
onClick: onRemove,
|
|
152
|
+
children: /* @__PURE__ */ jsx2("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
|
|
153
|
+
}
|
|
154
|
+
)
|
|
155
|
+
] });
|
|
156
|
+
}
|
|
157
|
+
async function renderBadge(props) {
|
|
158
|
+
const { children, icon, ...rest } = props;
|
|
159
|
+
const element = /* @__PURE__ */ jsx2(Badge, { ...rest, icon: icon ? /* @__PURE__ */ jsx2("span", { dangerouslySetInnerHTML: { __html: icon } }) : void 0, children });
|
|
160
|
+
return renderToString(element);
|
|
161
|
+
}
|
|
162
|
+
function renderBadgeSync(props) {
|
|
163
|
+
const { children, icon, ...rest } = props;
|
|
164
|
+
const element = /* @__PURE__ */ jsx2(Badge, { ...rest, icon: icon ? /* @__PURE__ */ jsx2("span", { dangerouslySetInnerHTML: { __html: icon } }) : void 0, children });
|
|
165
|
+
return renderToStringSync(element);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// libs/ui/src/react/Button.tsx
|
|
169
|
+
import {
|
|
170
|
+
getButtonVariantClasses,
|
|
171
|
+
getButtonSizeClasses,
|
|
172
|
+
BUTTON_BASE_CLASSES,
|
|
173
|
+
LOADING_SPINNER,
|
|
174
|
+
cn as cn3
|
|
175
|
+
} from "@frontmcp/uipack/styles";
|
|
176
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
177
|
+
function Button({
|
|
178
|
+
variant = "primary",
|
|
179
|
+
size = "md",
|
|
180
|
+
disabled = false,
|
|
181
|
+
loading = false,
|
|
182
|
+
fullWidth = false,
|
|
183
|
+
iconPosition = "left",
|
|
184
|
+
icon,
|
|
185
|
+
iconOnly = false,
|
|
186
|
+
type = "button",
|
|
187
|
+
className,
|
|
188
|
+
onClick,
|
|
189
|
+
children
|
|
190
|
+
}) {
|
|
191
|
+
const variantClasses = getButtonVariantClasses(variant);
|
|
192
|
+
const sizeClasses = getButtonSizeClasses(size, iconOnly);
|
|
193
|
+
const disabledClasses = disabled || loading ? "opacity-50 cursor-not-allowed" : "";
|
|
194
|
+
const widthClasses = fullWidth ? "w-full" : "";
|
|
195
|
+
const allClasses = cn3(BUTTON_BASE_CLASSES, variantClasses, sizeClasses, disabledClasses, widthClasses, className);
|
|
196
|
+
const iconElement = icon && /* @__PURE__ */ jsx3("span", { className: iconPosition === "left" ? "mr-2" : "ml-2", children: icon });
|
|
197
|
+
return /* @__PURE__ */ jsxs3("button", { type, className: allClasses, disabled: disabled || loading, onClick, children: [
|
|
198
|
+
loading && /* @__PURE__ */ jsx3("span", { className: "mr-2", dangerouslySetInnerHTML: { __html: LOADING_SPINNER } }),
|
|
199
|
+
!loading && icon && iconPosition === "left" && iconElement,
|
|
200
|
+
!iconOnly && children,
|
|
201
|
+
!loading && icon && iconPosition === "right" && iconElement
|
|
202
|
+
] });
|
|
203
|
+
}
|
|
204
|
+
async function renderButton(props) {
|
|
205
|
+
const { children, icon, ...rest } = props;
|
|
206
|
+
const element = /* @__PURE__ */ jsx3(Button, { ...rest, icon: icon ? /* @__PURE__ */ jsx3("span", { dangerouslySetInnerHTML: { __html: icon } }) : void 0, children });
|
|
207
|
+
return renderToString(element);
|
|
208
|
+
}
|
|
209
|
+
function renderButtonSync(props) {
|
|
210
|
+
const { children, icon, ...rest } = props;
|
|
211
|
+
const element = /* @__PURE__ */ jsx3(Button, { ...rest, icon: icon ? /* @__PURE__ */ jsx3("span", { dangerouslySetInnerHTML: { __html: icon } }) : void 0, children });
|
|
212
|
+
return renderToStringSync(element);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// libs/ui/src/react/Alert.tsx
|
|
216
|
+
import {
|
|
217
|
+
getAlertVariantClasses,
|
|
218
|
+
ALERT_BASE_CLASSES,
|
|
219
|
+
ALERT_ICONS,
|
|
220
|
+
CLOSE_ICON,
|
|
221
|
+
cn as cn4
|
|
222
|
+
} from "@frontmcp/uipack/styles";
|
|
223
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
224
|
+
function Alert({
|
|
225
|
+
variant = "info",
|
|
226
|
+
title,
|
|
227
|
+
icon,
|
|
228
|
+
showIcon = true,
|
|
229
|
+
dismissible = false,
|
|
230
|
+
onDismiss,
|
|
231
|
+
className,
|
|
232
|
+
children
|
|
233
|
+
}) {
|
|
234
|
+
const variantStyles = getAlertVariantClasses(variant);
|
|
235
|
+
const allClasses = cn4(ALERT_BASE_CLASSES, variantStyles.container, className);
|
|
236
|
+
const iconContent = icon || (showIcon ? /* @__PURE__ */ jsx4(
|
|
237
|
+
"span",
|
|
238
|
+
{
|
|
239
|
+
className: cn4("flex-shrink-0", variantStyles.icon),
|
|
240
|
+
dangerouslySetInnerHTML: { __html: ALERT_ICONS[variant] }
|
|
241
|
+
}
|
|
242
|
+
) : null);
|
|
243
|
+
return /* @__PURE__ */ jsx4("div", { className: allClasses, role: "alert", children: /* @__PURE__ */ jsxs4("div", { className: "flex", children: [
|
|
244
|
+
iconContent && /* @__PURE__ */ jsx4("div", { className: "flex-shrink-0 mr-3", children: iconContent }),
|
|
245
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex-1", children: [
|
|
246
|
+
title && /* @__PURE__ */ jsx4("h4", { className: "font-semibold mb-1", children: title }),
|
|
247
|
+
/* @__PURE__ */ jsx4("div", { className: "text-sm", children })
|
|
248
|
+
] }),
|
|
249
|
+
dismissible && /* @__PURE__ */ jsx4(
|
|
250
|
+
"button",
|
|
251
|
+
{
|
|
252
|
+
type: "button",
|
|
253
|
+
className: "flex-shrink-0 ml-3 hover:opacity-70 transition-opacity",
|
|
254
|
+
"aria-label": "Dismiss",
|
|
255
|
+
onClick: onDismiss,
|
|
256
|
+
children: /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: CLOSE_ICON } })
|
|
257
|
+
}
|
|
258
|
+
)
|
|
259
|
+
] }) });
|
|
260
|
+
}
|
|
261
|
+
async function renderAlert(props) {
|
|
262
|
+
const { children, icon, ...rest } = props;
|
|
263
|
+
const element = /* @__PURE__ */ jsx4(Alert, { ...rest, icon: icon ? /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: icon } }) : void 0, children });
|
|
264
|
+
return renderToString(element);
|
|
265
|
+
}
|
|
266
|
+
function renderAlertSync(props) {
|
|
267
|
+
const { children, icon, ...rest } = props;
|
|
268
|
+
const element = /* @__PURE__ */ jsx4(Alert, { ...rest, icon: icon ? /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: icon } }) : void 0, children });
|
|
269
|
+
return renderToStringSync(element);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// libs/ui/src/react/hooks/context.tsx
|
|
273
|
+
import { createContext, useContext, useEffect, useState, useMemo } from "react";
|
|
274
|
+
|
|
275
|
+
// libs/ui/src/bridge/core/adapter-registry.ts
|
|
276
|
+
var AdapterRegistry = class {
|
|
277
|
+
_adapters = /* @__PURE__ */ new Map();
|
|
278
|
+
_disabledAdapters = /* @__PURE__ */ new Set();
|
|
279
|
+
_adapterConfigs = /* @__PURE__ */ new Map();
|
|
280
|
+
_debug = false;
|
|
281
|
+
/**
|
|
282
|
+
* Enable or disable debug logging.
|
|
283
|
+
*/
|
|
284
|
+
setDebug(enabled) {
|
|
285
|
+
this._debug = enabled;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Register an adapter factory with the registry.
|
|
289
|
+
* @param id - Unique adapter identifier
|
|
290
|
+
* @param factory - Factory function that creates the adapter
|
|
291
|
+
* @param defaultConfig - Optional default configuration
|
|
292
|
+
*/
|
|
293
|
+
register(id, factory, defaultConfig) {
|
|
294
|
+
if (this._adapters.has(id)) {
|
|
295
|
+
this._log(`Overwriting existing adapter: ${id}`);
|
|
296
|
+
}
|
|
297
|
+
this._adapters.set(id, {
|
|
298
|
+
id,
|
|
299
|
+
factory,
|
|
300
|
+
defaultConfig
|
|
301
|
+
});
|
|
302
|
+
this._log(`Registered adapter: ${id}`);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Unregister an adapter from the registry.
|
|
306
|
+
* @param id - Adapter identifier to remove
|
|
307
|
+
*/
|
|
308
|
+
unregister(id) {
|
|
309
|
+
const removed = this._adapters.delete(id);
|
|
310
|
+
if (removed) {
|
|
311
|
+
this._log(`Unregistered adapter: ${id}`);
|
|
312
|
+
}
|
|
313
|
+
return removed;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Check if an adapter is registered.
|
|
317
|
+
* @param id - Adapter identifier
|
|
318
|
+
*/
|
|
319
|
+
has(id) {
|
|
320
|
+
return this._adapters.has(id);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Get all registered adapter IDs.
|
|
324
|
+
*/
|
|
325
|
+
getRegisteredIds() {
|
|
326
|
+
return Array.from(this._adapters.keys());
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Disable specific adapters (they won't be selected during auto-detection).
|
|
330
|
+
* @param ids - Adapter IDs to disable
|
|
331
|
+
*/
|
|
332
|
+
disable(...ids) {
|
|
333
|
+
for (const id of ids) {
|
|
334
|
+
this._disabledAdapters.add(id);
|
|
335
|
+
this._log(`Disabled adapter: ${id}`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Enable previously disabled adapters.
|
|
340
|
+
* @param ids - Adapter IDs to enable
|
|
341
|
+
*/
|
|
342
|
+
enable(...ids) {
|
|
343
|
+
for (const id of ids) {
|
|
344
|
+
this._disabledAdapters.delete(id);
|
|
345
|
+
this._log(`Enabled adapter: ${id}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Check if an adapter is disabled.
|
|
350
|
+
* @param id - Adapter identifier
|
|
351
|
+
*/
|
|
352
|
+
isDisabled(id) {
|
|
353
|
+
return this._disabledAdapters.has(id);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Set adapter-specific configuration.
|
|
357
|
+
* @param id - Adapter identifier
|
|
358
|
+
* @param config - Configuration to apply
|
|
359
|
+
*/
|
|
360
|
+
configure(id, config) {
|
|
361
|
+
this._adapterConfigs.set(id, config);
|
|
362
|
+
this._log(`Configured adapter: ${id}`);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Get an adapter instance by ID.
|
|
366
|
+
* @param id - Adapter identifier
|
|
367
|
+
* @returns Adapter instance or undefined if not found/disabled
|
|
368
|
+
*/
|
|
369
|
+
get(id) {
|
|
370
|
+
if (this._disabledAdapters.has(id)) {
|
|
371
|
+
this._log(`Adapter ${id} is disabled`);
|
|
372
|
+
return void 0;
|
|
373
|
+
}
|
|
374
|
+
const registration = this._adapters.get(id);
|
|
375
|
+
if (!registration) {
|
|
376
|
+
this._log(`Adapter ${id} not found`);
|
|
377
|
+
return void 0;
|
|
378
|
+
}
|
|
379
|
+
const config = this._mergeConfig(registration.defaultConfig, this._adapterConfigs.get(id));
|
|
380
|
+
if (config?.enabled === false) {
|
|
381
|
+
this._log(`Adapter ${id} is disabled via config`);
|
|
382
|
+
return void 0;
|
|
383
|
+
}
|
|
384
|
+
return registration.factory(config);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Auto-detect and return the best adapter for the current environment.
|
|
388
|
+
* Adapters are checked in priority order (highest first).
|
|
389
|
+
* @returns The first adapter that can handle the current environment, or undefined
|
|
390
|
+
*/
|
|
391
|
+
detect() {
|
|
392
|
+
const candidates = this._getSortedCandidates();
|
|
393
|
+
for (const registration of candidates) {
|
|
394
|
+
if (this._disabledAdapters.has(registration.id)) {
|
|
395
|
+
this._log(`Skipping disabled adapter: ${registration.id}`);
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
const config = this._mergeConfig(registration.defaultConfig, this._adapterConfigs.get(registration.id));
|
|
399
|
+
if (config?.enabled === false) {
|
|
400
|
+
this._log(`Skipping adapter disabled via config: ${registration.id}`);
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
try {
|
|
404
|
+
const adapter = registration.factory(config);
|
|
405
|
+
if (adapter.canHandle()) {
|
|
406
|
+
this._log(`Detected adapter: ${registration.id} (priority: ${adapter.priority})`);
|
|
407
|
+
return adapter;
|
|
408
|
+
}
|
|
409
|
+
this._log(`Adapter ${registration.id} cannot handle current environment`);
|
|
410
|
+
} catch (error) {
|
|
411
|
+
this._log(`Error creating adapter ${registration.id}: ${error}`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
this._log("No suitable adapter detected");
|
|
415
|
+
return void 0;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Get all adapters that can handle the current environment.
|
|
419
|
+
* Useful for debugging or showing available options.
|
|
420
|
+
* @returns Array of compatible adapters sorted by priority (highest first)
|
|
421
|
+
*/
|
|
422
|
+
detectAll() {
|
|
423
|
+
const candidates = this._getSortedCandidates();
|
|
424
|
+
const compatible = [];
|
|
425
|
+
for (const registration of candidates) {
|
|
426
|
+
if (this._disabledAdapters.has(registration.id)) {
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
const config = this._mergeConfig(registration.defaultConfig, this._adapterConfigs.get(registration.id));
|
|
430
|
+
if (config?.enabled === false) {
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
try {
|
|
434
|
+
const adapter = registration.factory(config);
|
|
435
|
+
if (adapter.canHandle()) {
|
|
436
|
+
compatible.push(adapter);
|
|
437
|
+
}
|
|
438
|
+
} catch {
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return compatible;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Clear all registered adapters.
|
|
445
|
+
*/
|
|
446
|
+
clear() {
|
|
447
|
+
this._adapters.clear();
|
|
448
|
+
this._disabledAdapters.clear();
|
|
449
|
+
this._adapterConfigs.clear();
|
|
450
|
+
this._log("Cleared all adapters");
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Get sorted candidate adapters by priority (highest first).
|
|
454
|
+
*/
|
|
455
|
+
_getSortedCandidates() {
|
|
456
|
+
const registrations = Array.from(this._adapters.values());
|
|
457
|
+
const withPriority = registrations.map((reg) => {
|
|
458
|
+
try {
|
|
459
|
+
const adapter = reg.factory(reg.defaultConfig);
|
|
460
|
+
return { registration: reg, priority: adapter.priority };
|
|
461
|
+
} catch {
|
|
462
|
+
return { registration: reg, priority: -1 };
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
withPriority.sort((a, b) => b.priority - a.priority);
|
|
466
|
+
return withPriority.map((item) => item.registration);
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Merge default config with user config.
|
|
470
|
+
*/
|
|
471
|
+
_mergeConfig(defaultConfig, userConfig) {
|
|
472
|
+
if (!defaultConfig && !userConfig) {
|
|
473
|
+
return void 0;
|
|
474
|
+
}
|
|
475
|
+
return {
|
|
476
|
+
...defaultConfig,
|
|
477
|
+
...userConfig,
|
|
478
|
+
options: {
|
|
479
|
+
...defaultConfig?.options,
|
|
480
|
+
...userConfig?.options
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Log debug message if debugging is enabled.
|
|
486
|
+
*/
|
|
487
|
+
_log(message) {
|
|
488
|
+
if (this._debug) {
|
|
489
|
+
console.log(`[AdapterRegistry] ${message}`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
var defaultRegistry = new AdapterRegistry();
|
|
494
|
+
|
|
495
|
+
// libs/ui/src/bridge/core/bridge-factory.ts
|
|
496
|
+
var DEFAULT_CONFIG = {
|
|
497
|
+
debug: false,
|
|
498
|
+
initTimeout: 5e3
|
|
499
|
+
};
|
|
500
|
+
var FrontMcpBridge = class {
|
|
501
|
+
_config;
|
|
502
|
+
_registry;
|
|
503
|
+
_adapter;
|
|
504
|
+
_initialized = false;
|
|
505
|
+
_initPromise;
|
|
506
|
+
/**
|
|
507
|
+
* Create a new FrontMcpBridge instance.
|
|
508
|
+
* @param config - Bridge configuration
|
|
509
|
+
* @param registry - Optional custom adapter registry (uses default if not provided)
|
|
510
|
+
*/
|
|
511
|
+
constructor(config = {}, registry) {
|
|
512
|
+
this._config = { ...DEFAULT_CONFIG, ...config };
|
|
513
|
+
this._registry = registry || defaultRegistry;
|
|
514
|
+
if (this._config.debug) {
|
|
515
|
+
this._registry.setDebug(true);
|
|
516
|
+
}
|
|
517
|
+
if (this._config.disabledAdapters) {
|
|
518
|
+
this._registry.disable(...this._config.disabledAdapters);
|
|
519
|
+
}
|
|
520
|
+
if (this._config.adapterConfigs) {
|
|
521
|
+
for (const [id, adapterConfig] of Object.entries(this._config.adapterConfigs)) {
|
|
522
|
+
this._registry.configure(id, adapterConfig);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
// ============================================
|
|
527
|
+
// Public Properties
|
|
528
|
+
// ============================================
|
|
529
|
+
/**
|
|
530
|
+
* Whether the bridge has been initialized.
|
|
531
|
+
*/
|
|
532
|
+
get initialized() {
|
|
533
|
+
return this._initialized;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Current adapter ID, or undefined if not initialized.
|
|
537
|
+
*/
|
|
538
|
+
get adapterId() {
|
|
539
|
+
return this._adapter?.id;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Current adapter capabilities, or undefined if not initialized.
|
|
543
|
+
*/
|
|
544
|
+
get capabilities() {
|
|
545
|
+
return this._adapter?.capabilities;
|
|
546
|
+
}
|
|
547
|
+
// ============================================
|
|
548
|
+
// Lifecycle
|
|
549
|
+
// ============================================
|
|
550
|
+
/**
|
|
551
|
+
* Initialize the bridge.
|
|
552
|
+
* Auto-detects the best adapter for the current platform unless
|
|
553
|
+
* `forceAdapter` is specified in the config.
|
|
554
|
+
*
|
|
555
|
+
* @throws Error if no suitable adapter is found
|
|
556
|
+
*/
|
|
557
|
+
async initialize() {
|
|
558
|
+
if (this._initPromise) {
|
|
559
|
+
return this._initPromise;
|
|
560
|
+
}
|
|
561
|
+
if (this._initialized) {
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
this._initPromise = this._doInitialize();
|
|
565
|
+
try {
|
|
566
|
+
await this._initPromise;
|
|
567
|
+
} finally {
|
|
568
|
+
this._initPromise = void 0;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Internal initialization logic.
|
|
573
|
+
*/
|
|
574
|
+
async _doInitialize() {
|
|
575
|
+
this._log("Initializing FrontMcpBridge...");
|
|
576
|
+
if (this._config.forceAdapter) {
|
|
577
|
+
this._adapter = this._registry.get(this._config.forceAdapter);
|
|
578
|
+
if (!this._adapter) {
|
|
579
|
+
throw new Error(`Forced adapter "${this._config.forceAdapter}" not found or disabled`);
|
|
580
|
+
}
|
|
581
|
+
this._log(`Using forced adapter: ${this._config.forceAdapter}`);
|
|
582
|
+
} else {
|
|
583
|
+
this._adapter = this._registry.detect();
|
|
584
|
+
if (!this._adapter) {
|
|
585
|
+
throw new Error("No suitable adapter detected for current environment");
|
|
586
|
+
}
|
|
587
|
+
this._log(`Auto-detected adapter: ${this._adapter.id}`);
|
|
588
|
+
}
|
|
589
|
+
try {
|
|
590
|
+
await this._withTimeout(this._adapter.initialize(), this._config.initTimeout || 5e3);
|
|
591
|
+
this._initialized = true;
|
|
592
|
+
this._log(`Bridge initialized with adapter: ${this._adapter.id}`);
|
|
593
|
+
this._emitEvent("bridge:ready", { adapter: this._adapter.id });
|
|
594
|
+
} catch (error) {
|
|
595
|
+
this._emitEvent("bridge:error", {
|
|
596
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
597
|
+
adapter: this._adapter?.id
|
|
598
|
+
});
|
|
599
|
+
throw error;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Dispose the bridge and release resources.
|
|
604
|
+
*/
|
|
605
|
+
dispose() {
|
|
606
|
+
if (this._adapter) {
|
|
607
|
+
this._adapter.dispose();
|
|
608
|
+
this._log(`Disposed adapter: ${this._adapter.id}`);
|
|
609
|
+
}
|
|
610
|
+
this._adapter = void 0;
|
|
611
|
+
this._initialized = false;
|
|
612
|
+
}
|
|
613
|
+
// ============================================
|
|
614
|
+
// Adapter Access
|
|
615
|
+
// ============================================
|
|
616
|
+
/**
|
|
617
|
+
* Get the active adapter instance.
|
|
618
|
+
*/
|
|
619
|
+
getAdapter() {
|
|
620
|
+
return this._adapter;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Check if a specific capability is available.
|
|
624
|
+
* @param cap - Capability key to check
|
|
625
|
+
*/
|
|
626
|
+
hasCapability(cap) {
|
|
627
|
+
return this._adapter?.capabilities[cap] === true;
|
|
628
|
+
}
|
|
629
|
+
// ============================================
|
|
630
|
+
// Data Access (delegate to adapter)
|
|
631
|
+
// ============================================
|
|
632
|
+
/**
|
|
633
|
+
* Get current theme.
|
|
634
|
+
*/
|
|
635
|
+
getTheme() {
|
|
636
|
+
const adapter = this._ensureInitialized();
|
|
637
|
+
return adapter.getTheme();
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Get current display mode.
|
|
641
|
+
*/
|
|
642
|
+
getDisplayMode() {
|
|
643
|
+
const adapter = this._ensureInitialized();
|
|
644
|
+
return adapter.getDisplayMode();
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Get tool input arguments.
|
|
648
|
+
*/
|
|
649
|
+
getToolInput() {
|
|
650
|
+
const adapter = this._ensureInitialized();
|
|
651
|
+
return adapter.getToolInput();
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Get tool output/result.
|
|
655
|
+
*/
|
|
656
|
+
getToolOutput() {
|
|
657
|
+
const adapter = this._ensureInitialized();
|
|
658
|
+
return adapter.getToolOutput();
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Get structured content (parsed output).
|
|
662
|
+
*/
|
|
663
|
+
getStructuredContent() {
|
|
664
|
+
const adapter = this._ensureInitialized();
|
|
665
|
+
return adapter.getStructuredContent();
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Get persisted widget state.
|
|
669
|
+
*/
|
|
670
|
+
getWidgetState() {
|
|
671
|
+
const adapter = this._ensureInitialized();
|
|
672
|
+
return adapter.getWidgetState();
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Get full host context.
|
|
676
|
+
*/
|
|
677
|
+
getHostContext() {
|
|
678
|
+
const adapter = this._ensureInitialized();
|
|
679
|
+
return adapter.getHostContext();
|
|
680
|
+
}
|
|
681
|
+
// ============================================
|
|
682
|
+
// Actions (delegate to adapter)
|
|
683
|
+
// ============================================
|
|
684
|
+
/**
|
|
685
|
+
* Call a tool on the MCP server.
|
|
686
|
+
* @param name - Tool name
|
|
687
|
+
* @param args - Tool arguments
|
|
688
|
+
*/
|
|
689
|
+
async callTool(name, args) {
|
|
690
|
+
const adapter = this._ensureInitialized();
|
|
691
|
+
if (!this.hasCapability("canCallTools")) {
|
|
692
|
+
throw new Error("Tool calls are not supported by the current adapter");
|
|
693
|
+
}
|
|
694
|
+
return adapter.callTool(name, args);
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Send a follow-up message to the conversation.
|
|
698
|
+
* @param content - Message content
|
|
699
|
+
*/
|
|
700
|
+
async sendMessage(content) {
|
|
701
|
+
const adapter = this._ensureInitialized();
|
|
702
|
+
if (!this.hasCapability("canSendMessages")) {
|
|
703
|
+
throw new Error("Sending messages is not supported by the current adapter");
|
|
704
|
+
}
|
|
705
|
+
return adapter.sendMessage(content);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Open an external link.
|
|
709
|
+
* @param url - URL to open
|
|
710
|
+
*/
|
|
711
|
+
async openLink(url) {
|
|
712
|
+
const adapter = this._ensureInitialized();
|
|
713
|
+
return adapter.openLink(url);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Request a display mode change.
|
|
717
|
+
* @param mode - Desired display mode
|
|
718
|
+
*/
|
|
719
|
+
async requestDisplayMode(mode) {
|
|
720
|
+
const adapter = this._ensureInitialized();
|
|
721
|
+
return adapter.requestDisplayMode(mode);
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Request widget close.
|
|
725
|
+
*/
|
|
726
|
+
async requestClose() {
|
|
727
|
+
const adapter = this._ensureInitialized();
|
|
728
|
+
return adapter.requestClose();
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Set widget state (persisted across sessions).
|
|
732
|
+
* @param state - State object to persist
|
|
733
|
+
*/
|
|
734
|
+
setWidgetState(state) {
|
|
735
|
+
const adapter = this._ensureInitialized();
|
|
736
|
+
adapter.setWidgetState(state);
|
|
737
|
+
}
|
|
738
|
+
// ============================================
|
|
739
|
+
// Events (delegate to adapter)
|
|
740
|
+
// ============================================
|
|
741
|
+
/**
|
|
742
|
+
* Subscribe to host context changes.
|
|
743
|
+
* @param callback - Called when context changes
|
|
744
|
+
* @returns Unsubscribe function
|
|
745
|
+
*/
|
|
746
|
+
onContextChange(callback) {
|
|
747
|
+
const adapter = this._ensureInitialized();
|
|
748
|
+
return adapter.onContextChange(callback);
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Subscribe to tool result updates.
|
|
752
|
+
* @param callback - Called when tool result is received
|
|
753
|
+
* @returns Unsubscribe function
|
|
754
|
+
*/
|
|
755
|
+
onToolResult(callback) {
|
|
756
|
+
const adapter = this._ensureInitialized();
|
|
757
|
+
return adapter.onToolResult(callback);
|
|
758
|
+
}
|
|
759
|
+
// ============================================
|
|
760
|
+
// Private Helpers
|
|
761
|
+
// ============================================
|
|
762
|
+
/**
|
|
763
|
+
* Ensure the bridge is initialized before operations.
|
|
764
|
+
* Returns the adapter for type-safe access.
|
|
765
|
+
*/
|
|
766
|
+
_ensureInitialized() {
|
|
767
|
+
if (!this._initialized || !this._adapter) {
|
|
768
|
+
throw new Error("FrontMcpBridge is not initialized. Call initialize() first.");
|
|
769
|
+
}
|
|
770
|
+
return this._adapter;
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Wrap a promise with a timeout.
|
|
774
|
+
*/
|
|
775
|
+
_withTimeout(promise, ms) {
|
|
776
|
+
return new Promise((resolve, reject) => {
|
|
777
|
+
const timer = setTimeout(() => {
|
|
778
|
+
reject(new Error(`Operation timed out after ${ms}ms`));
|
|
779
|
+
}, ms);
|
|
780
|
+
promise.then((result) => {
|
|
781
|
+
clearTimeout(timer);
|
|
782
|
+
resolve(result);
|
|
783
|
+
}).catch((error) => {
|
|
784
|
+
clearTimeout(timer);
|
|
785
|
+
reject(error);
|
|
786
|
+
});
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Emit a bridge event via CustomEvent.
|
|
791
|
+
*/
|
|
792
|
+
_emitEvent(type, payload) {
|
|
793
|
+
if (typeof window !== "undefined" && typeof CustomEvent !== "undefined") {
|
|
794
|
+
try {
|
|
795
|
+
const event = new CustomEvent(type, { detail: payload });
|
|
796
|
+
window.dispatchEvent(event);
|
|
797
|
+
} catch {
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Log debug message if debugging is enabled.
|
|
803
|
+
*/
|
|
804
|
+
_log(message) {
|
|
805
|
+
if (this._config.debug) {
|
|
806
|
+
console.log(`[FrontMcpBridge] ${message}`);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
// libs/ui/src/react/hooks/context.tsx
|
|
812
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
813
|
+
var McpBridgeContext = createContext(null);
|
|
814
|
+
function McpBridgeProvider({ children, config, onReady, onError }) {
|
|
815
|
+
const [bridge, setBridge] = useState(null);
|
|
816
|
+
const [loading, setLoading] = useState(true);
|
|
817
|
+
const [error, setError] = useState(null);
|
|
818
|
+
useEffect(() => {
|
|
819
|
+
let mounted = true;
|
|
820
|
+
let bridgeInstance = null;
|
|
821
|
+
const initBridge = async () => {
|
|
822
|
+
try {
|
|
823
|
+
bridgeInstance = new FrontMcpBridge(config);
|
|
824
|
+
await bridgeInstance.initialize();
|
|
825
|
+
if (mounted) {
|
|
826
|
+
setBridge(bridgeInstance);
|
|
827
|
+
setLoading(false);
|
|
828
|
+
onReady?.(bridgeInstance);
|
|
829
|
+
}
|
|
830
|
+
} catch (err) {
|
|
831
|
+
if (mounted) {
|
|
832
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
833
|
+
setError(error2);
|
|
834
|
+
setLoading(false);
|
|
835
|
+
onError?.(error2);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
initBridge();
|
|
840
|
+
return () => {
|
|
841
|
+
mounted = false;
|
|
842
|
+
if (bridgeInstance) {
|
|
843
|
+
bridgeInstance.dispose();
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
}, [config, onReady, onError]);
|
|
847
|
+
const contextValue = useMemo(
|
|
848
|
+
() => ({
|
|
849
|
+
bridge,
|
|
850
|
+
loading,
|
|
851
|
+
error,
|
|
852
|
+
ready: !loading && !error && bridge !== null,
|
|
853
|
+
adapterId: bridge?.adapterId,
|
|
854
|
+
capabilities: bridge?.capabilities
|
|
855
|
+
}),
|
|
856
|
+
[bridge, loading, error]
|
|
857
|
+
);
|
|
858
|
+
return /* @__PURE__ */ jsx5(McpBridgeContext.Provider, { value: contextValue, children });
|
|
859
|
+
}
|
|
860
|
+
var SSR_DEFAULT_CONTEXT = {
|
|
861
|
+
bridge: null,
|
|
862
|
+
loading: false,
|
|
863
|
+
error: null,
|
|
864
|
+
ready: false,
|
|
865
|
+
adapterId: void 0,
|
|
866
|
+
capabilities: void 0
|
|
867
|
+
};
|
|
868
|
+
function useMcpBridgeContext() {
|
|
869
|
+
const context = useContext(McpBridgeContext);
|
|
870
|
+
if (!context) {
|
|
871
|
+
return SSR_DEFAULT_CONTEXT;
|
|
872
|
+
}
|
|
873
|
+
return context;
|
|
874
|
+
}
|
|
875
|
+
function useMcpBridge() {
|
|
876
|
+
const { bridge } = useMcpBridgeContext();
|
|
877
|
+
return bridge;
|
|
878
|
+
}
|
|
879
|
+
function useTheme() {
|
|
880
|
+
const { bridge, ready } = useMcpBridgeContext();
|
|
881
|
+
const [theme, setTheme] = useState("light");
|
|
882
|
+
useEffect(() => {
|
|
883
|
+
if (!ready || !bridge) return;
|
|
884
|
+
setTheme(bridge.getTheme());
|
|
885
|
+
const unsubscribe = bridge.onContextChange((changes) => {
|
|
886
|
+
if (changes.theme) {
|
|
887
|
+
setTheme(changes.theme);
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
return unsubscribe;
|
|
891
|
+
}, [bridge, ready]);
|
|
892
|
+
return theme;
|
|
893
|
+
}
|
|
894
|
+
function useDisplayMode() {
|
|
895
|
+
const { bridge, ready } = useMcpBridgeContext();
|
|
896
|
+
const [displayMode, setDisplayMode] = useState("inline");
|
|
897
|
+
useEffect(() => {
|
|
898
|
+
if (!ready || !bridge) return;
|
|
899
|
+
setDisplayMode(bridge.getDisplayMode());
|
|
900
|
+
const unsubscribe = bridge.onContextChange((changes) => {
|
|
901
|
+
if (changes.displayMode) {
|
|
902
|
+
setDisplayMode(changes.displayMode);
|
|
903
|
+
}
|
|
904
|
+
});
|
|
905
|
+
return unsubscribe;
|
|
906
|
+
}, [bridge, ready]);
|
|
907
|
+
return displayMode;
|
|
908
|
+
}
|
|
909
|
+
function useHostContext() {
|
|
910
|
+
const { bridge, ready } = useMcpBridgeContext();
|
|
911
|
+
const [context, setContext] = useState(null);
|
|
912
|
+
useEffect(() => {
|
|
913
|
+
if (!ready || !bridge) return;
|
|
914
|
+
const adapter = bridge.getAdapter?.();
|
|
915
|
+
if (adapter) {
|
|
916
|
+
setContext(adapter.getHostContext());
|
|
917
|
+
}
|
|
918
|
+
const unsubscribe = bridge.onContextChange((changes) => {
|
|
919
|
+
setContext((prev) => prev ? { ...prev, ...changes } : null);
|
|
920
|
+
});
|
|
921
|
+
return unsubscribe;
|
|
922
|
+
}, [bridge, ready]);
|
|
923
|
+
return context;
|
|
924
|
+
}
|
|
925
|
+
function useCapability(cap) {
|
|
926
|
+
const { capabilities } = useMcpBridgeContext();
|
|
927
|
+
return capabilities?.[cap] === true;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
// libs/ui/src/react/hooks/tools.tsx
|
|
931
|
+
import { useState as useState2, useCallback, useEffect as useEffect2 } from "react";
|
|
932
|
+
function useToolInput() {
|
|
933
|
+
const { bridge, ready } = useMcpBridgeContext();
|
|
934
|
+
if (!ready || !bridge) {
|
|
935
|
+
return null;
|
|
936
|
+
}
|
|
937
|
+
try {
|
|
938
|
+
return bridge.getToolInput();
|
|
939
|
+
} catch {
|
|
940
|
+
return null;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
function useToolOutput() {
|
|
944
|
+
const { bridge, ready } = useMcpBridgeContext();
|
|
945
|
+
const [output, setOutput] = useState2(null);
|
|
946
|
+
useEffect2(() => {
|
|
947
|
+
if (!ready || !bridge) return;
|
|
948
|
+
try {
|
|
949
|
+
const initialOutput = bridge.getToolOutput();
|
|
950
|
+
if (initialOutput !== void 0) {
|
|
951
|
+
setOutput(initialOutput);
|
|
952
|
+
}
|
|
953
|
+
} catch {
|
|
954
|
+
}
|
|
955
|
+
const unsubscribe = bridge.onToolResult((result) => {
|
|
956
|
+
setOutput(result);
|
|
957
|
+
});
|
|
958
|
+
return unsubscribe;
|
|
959
|
+
}, [bridge, ready]);
|
|
960
|
+
return output;
|
|
961
|
+
}
|
|
962
|
+
function useStructuredContent() {
|
|
963
|
+
const { bridge, ready } = useMcpBridgeContext();
|
|
964
|
+
if (!ready || !bridge) {
|
|
965
|
+
return null;
|
|
966
|
+
}
|
|
967
|
+
try {
|
|
968
|
+
const adapter = bridge.getAdapter?.();
|
|
969
|
+
if (adapter) {
|
|
970
|
+
return adapter.getStructuredContent();
|
|
971
|
+
}
|
|
972
|
+
return null;
|
|
973
|
+
} catch {
|
|
974
|
+
return null;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
function useCallTool(toolName, options = {}) {
|
|
978
|
+
const { bridge, ready } = useMcpBridgeContext();
|
|
979
|
+
const { onSuccess, onError, resetOnToolChange = true } = options;
|
|
980
|
+
console.log("useCallTool", toolName, bridge);
|
|
981
|
+
const [state, setState] = useState2({
|
|
982
|
+
data: null,
|
|
983
|
+
loading: false,
|
|
984
|
+
error: null,
|
|
985
|
+
called: false
|
|
986
|
+
});
|
|
987
|
+
useEffect2(() => {
|
|
988
|
+
if (resetOnToolChange) {
|
|
989
|
+
setState({
|
|
990
|
+
data: null,
|
|
991
|
+
loading: false,
|
|
992
|
+
error: null,
|
|
993
|
+
called: false
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
}, [toolName, resetOnToolChange]);
|
|
997
|
+
const reset = useCallback(() => {
|
|
998
|
+
setState({
|
|
999
|
+
data: null,
|
|
1000
|
+
loading: false,
|
|
1001
|
+
error: null,
|
|
1002
|
+
called: false
|
|
1003
|
+
});
|
|
1004
|
+
}, []);
|
|
1005
|
+
const callTool = useCallback(
|
|
1006
|
+
async (args) => {
|
|
1007
|
+
if (!ready || !bridge) {
|
|
1008
|
+
const error = new Error("Bridge not initialized");
|
|
1009
|
+
setState((prev) => ({ ...prev, error, called: true }));
|
|
1010
|
+
onError?.(error);
|
|
1011
|
+
return null;
|
|
1012
|
+
}
|
|
1013
|
+
setState((prev) => ({
|
|
1014
|
+
...prev,
|
|
1015
|
+
loading: true,
|
|
1016
|
+
error: null,
|
|
1017
|
+
called: true
|
|
1018
|
+
}));
|
|
1019
|
+
try {
|
|
1020
|
+
const result = await bridge.callTool(toolName, args);
|
|
1021
|
+
const data = result;
|
|
1022
|
+
setState({
|
|
1023
|
+
data,
|
|
1024
|
+
loading: false,
|
|
1025
|
+
error: null,
|
|
1026
|
+
called: true
|
|
1027
|
+
});
|
|
1028
|
+
onSuccess?.(data);
|
|
1029
|
+
return data;
|
|
1030
|
+
} catch (err) {
|
|
1031
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1032
|
+
setState({
|
|
1033
|
+
data: null,
|
|
1034
|
+
loading: false,
|
|
1035
|
+
error,
|
|
1036
|
+
called: true
|
|
1037
|
+
});
|
|
1038
|
+
onError?.(error);
|
|
1039
|
+
return null;
|
|
1040
|
+
}
|
|
1041
|
+
},
|
|
1042
|
+
[bridge, ready, toolName, onSuccess, onError]
|
|
1043
|
+
);
|
|
1044
|
+
return [callTool, state, reset];
|
|
1045
|
+
}
|
|
1046
|
+
function useToolCalls(toolMap) {
|
|
1047
|
+
const bridge = useMcpBridge();
|
|
1048
|
+
const [states, setStates] = useState2(() => {
|
|
1049
|
+
const initial = {};
|
|
1050
|
+
for (const key of Object.keys(toolMap)) {
|
|
1051
|
+
initial[key] = { data: null, loading: false, error: null, called: false };
|
|
1052
|
+
}
|
|
1053
|
+
return initial;
|
|
1054
|
+
});
|
|
1055
|
+
const createCallFn = useCallback(
|
|
1056
|
+
(key, toolName) => async (args) => {
|
|
1057
|
+
if (!bridge) {
|
|
1058
|
+
setStates((prev) => ({
|
|
1059
|
+
...prev,
|
|
1060
|
+
[key]: {
|
|
1061
|
+
...prev[key],
|
|
1062
|
+
error: new Error("Bridge not initialized"),
|
|
1063
|
+
called: true
|
|
1064
|
+
}
|
|
1065
|
+
}));
|
|
1066
|
+
return null;
|
|
1067
|
+
}
|
|
1068
|
+
setStates((prev) => ({
|
|
1069
|
+
...prev,
|
|
1070
|
+
[key]: { ...prev[key], loading: true, error: null, called: true }
|
|
1071
|
+
}));
|
|
1072
|
+
try {
|
|
1073
|
+
const result2 = await bridge.callTool(toolName, args);
|
|
1074
|
+
setStates((prev) => ({
|
|
1075
|
+
...prev,
|
|
1076
|
+
[key]: { data: result2, loading: false, error: null, called: true }
|
|
1077
|
+
}));
|
|
1078
|
+
return result2;
|
|
1079
|
+
} catch (err) {
|
|
1080
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1081
|
+
setStates((prev) => ({
|
|
1082
|
+
...prev,
|
|
1083
|
+
[key]: { data: null, loading: false, error, called: true }
|
|
1084
|
+
}));
|
|
1085
|
+
return null;
|
|
1086
|
+
}
|
|
1087
|
+
},
|
|
1088
|
+
[bridge]
|
|
1089
|
+
);
|
|
1090
|
+
const createResetFn = useCallback(
|
|
1091
|
+
(key) => () => {
|
|
1092
|
+
setStates((prev) => ({
|
|
1093
|
+
...prev,
|
|
1094
|
+
[key]: { data: null, loading: false, error: null, called: false }
|
|
1095
|
+
}));
|
|
1096
|
+
},
|
|
1097
|
+
[]
|
|
1098
|
+
);
|
|
1099
|
+
const result = {};
|
|
1100
|
+
for (const [key, toolName] of Object.entries(toolMap)) {
|
|
1101
|
+
const state = states[key] || {
|
|
1102
|
+
data: null,
|
|
1103
|
+
loading: false,
|
|
1104
|
+
error: null,
|
|
1105
|
+
called: false
|
|
1106
|
+
};
|
|
1107
|
+
result[key] = {
|
|
1108
|
+
call: createCallFn(key, toolName),
|
|
1109
|
+
data: state.data,
|
|
1110
|
+
loading: state.loading,
|
|
1111
|
+
error: state.error,
|
|
1112
|
+
reset: createResetFn(key)
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
return result;
|
|
1116
|
+
}
|
|
1117
|
+
function useSendMessage() {
|
|
1118
|
+
const bridge = useMcpBridge();
|
|
1119
|
+
const [state, setState] = useState2({
|
|
1120
|
+
loading: false,
|
|
1121
|
+
error: null,
|
|
1122
|
+
sent: false
|
|
1123
|
+
});
|
|
1124
|
+
const sendMessage = useCallback(
|
|
1125
|
+
async (content) => {
|
|
1126
|
+
if (!bridge) {
|
|
1127
|
+
setState({ loading: false, error: new Error("Bridge not initialized"), sent: false });
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
setState({ loading: true, error: null, sent: false });
|
|
1131
|
+
try {
|
|
1132
|
+
await bridge.sendMessage(content);
|
|
1133
|
+
setState({ loading: false, error: null, sent: true });
|
|
1134
|
+
} catch (err) {
|
|
1135
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1136
|
+
setState({ loading: false, error, sent: false });
|
|
1137
|
+
}
|
|
1138
|
+
},
|
|
1139
|
+
[bridge]
|
|
1140
|
+
);
|
|
1141
|
+
return [sendMessage, state];
|
|
1142
|
+
}
|
|
1143
|
+
function useOpenLink() {
|
|
1144
|
+
const bridge = useMcpBridge();
|
|
1145
|
+
return useCallback(
|
|
1146
|
+
async (url) => {
|
|
1147
|
+
if (!bridge) {
|
|
1148
|
+
console.warn("Bridge not initialized, cannot open link");
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
await bridge.openLink(url);
|
|
1152
|
+
},
|
|
1153
|
+
[bridge]
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1156
|
+
export {
|
|
1157
|
+
Alert,
|
|
1158
|
+
Badge,
|
|
1159
|
+
Button,
|
|
1160
|
+
Card,
|
|
1161
|
+
McpBridgeProvider,
|
|
1162
|
+
renderAlert,
|
|
1163
|
+
renderAlertSync,
|
|
1164
|
+
renderBadge,
|
|
1165
|
+
renderBadgeSync,
|
|
1166
|
+
renderButton,
|
|
1167
|
+
renderButtonSync,
|
|
1168
|
+
renderCard,
|
|
1169
|
+
renderCardSync,
|
|
1170
|
+
useCallTool,
|
|
1171
|
+
useCapability,
|
|
1172
|
+
useDisplayMode,
|
|
1173
|
+
useHostContext,
|
|
1174
|
+
useMcpBridge,
|
|
1175
|
+
useMcpBridgeContext,
|
|
1176
|
+
useOpenLink,
|
|
1177
|
+
useSendMessage,
|
|
1178
|
+
useStructuredContent,
|
|
1179
|
+
useTheme,
|
|
1180
|
+
useToolCalls,
|
|
1181
|
+
useToolInput,
|
|
1182
|
+
useToolOutput
|
|
1183
|
+
};
|