reachat 2.2.0 → 3.0.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/dist/{CSVFileRenderer-BOdL4Jte.js → CSVFileRenderer-C2tuexJf.js} +2 -2
- package/dist/{CSVFileRenderer-BOdL4Jte.js.map → CSVFileRenderer-C2tuexJf.js.map} +1 -1
- package/dist/Chat.d.ts +12 -0
- package/dist/{Markdown/charts/ChartError.d.ts → ComponentCatalog/ComponentError.d.ts} +2 -2
- package/dist/ComponentCatalog/ComponentPre.d.ts +18 -0
- package/dist/ComponentCatalog/ComponentRenderer.d.ts +17 -0
- package/dist/ComponentCatalog/chartComponentDef.d.ts +36 -0
- package/dist/ComponentCatalog/componentCatalog.d.ts +44 -0
- package/dist/ComponentCatalog/componentCatalog.spec.d.ts +1 -0
- package/dist/ComponentCatalog/generatePrompt.d.ts +9 -0
- package/dist/ComponentCatalog/generatePrompt.spec.d.ts +1 -0
- package/dist/ComponentCatalog/index.d.ts +9 -0
- package/dist/ComponentCatalog/types.d.ts +108 -0
- package/dist/ComponentCatalog/validateSpec.d.ts +17 -0
- package/dist/ComponentCatalog/validateSpec.spec.d.ts +1 -0
- package/dist/{DefaultFileRenderer-C2MsQ9wz.js → DefaultFileRenderer-CJ3jwiQa.js} +2 -2
- package/dist/{DefaultFileRenderer-C2MsQ9wz.js.map → DefaultFileRenderer-CJ3jwiQa.js.map} +1 -1
- package/dist/Markdown/charts/ChartRenderer.d.ts +1 -1
- package/dist/Markdown/charts/ComponentError.d.ts +1 -0
- package/dist/Markdown/charts/index.d.ts +2 -6
- package/dist/Markdown/charts/types.d.ts +21 -0
- package/dist/Markdown/plugins/index.d.ts +1 -1
- package/dist/Markdown/plugins/remarkComponent.d.ts +27 -0
- package/dist/docs.json +259 -77
- package/dist/{index-DdRyk11n.js → index-8tlsyFe-.js} +470 -147
- package/dist/index-8tlsyFe-.js.map +1 -0
- package/dist/index.css +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +22 -22
- package/dist/index.umd.cjs +454 -131
- package/dist/index.umd.cjs.map +1 -1
- package/dist/stories/Charts.stories.tsx +118 -130
- package/dist/stories/ComponentCatalog.stories.tsx +509 -0
- package/dist/stories/{ChartError.stories.tsx → ComponentError.stories.tsx} +14 -11
- package/dist/theme.d.ts +3 -0
- package/dist/utils/getChildText.d.ts +10 -0
- package/dist/utils/getChildText.spec.d.ts +1 -0
- package/package.json +4 -6
- package/dist/Markdown/charts/ChartPre.d.ts +0 -6
- package/dist/Markdown/charts/chartHelpers.d.ts +0 -40
- package/dist/Markdown/plugins/remarkChart.d.ts +0 -59
- package/dist/index-DdRyk11n.js.map +0 -1
- package/dist/stories/Integration.stories.tsx +0 -312
- /package/dist/{Markdown/charts/chartHelpers.spec.d.ts → ComponentCatalog/chartComponentDef.spec.d.ts} +0 -0
package/dist/index.umd.cjs
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
}
|
|
12
12
|
})();
|
|
13
13
|
(function(global, factory) {
|
|
14
|
-
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("reablocks"), require("react"), require("motion/react"), require("@tiptap/react"), require("@floating-ui/dom"), require("@tiptap/extension-document"), require("@tiptap/extension-paragraph"), require("@tiptap/extension-text"), require("@tiptap/extension-hard-break"), require("@tiptap/extension-placeholder"), require("@tiptap/extension-mention"), require("@radix-ui/react-slot"), require("react-markdown"), require("react-syntax-highlighter"), require("rehype-katex"), require("rehype-raw"), require("reaviz"), require("mdast-util-find-and-replace"), require("
|
|
15
|
-
})(this, function(exports2, jsxRuntime, reablocks, React, react$1, react, dom, Document, Paragraph, Text, HardBreak, Placeholder, Mention, reactSlot, ReactMarkdown, reactSyntaxHighlighter, rehypeKatex, rehypeRaw, reaviz, mdastUtilFindAndReplace,
|
|
14
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("reablocks"), require("react"), require("motion/react"), require("@tiptap/react"), require("@floating-ui/dom"), require("@tiptap/extension-document"), require("@tiptap/extension-paragraph"), require("@tiptap/extension-text"), require("@tiptap/extension-hard-break"), require("@tiptap/extension-placeholder"), require("@tiptap/extension-mention"), require("@radix-ui/react-slot"), require("react-markdown"), require("react-syntax-highlighter"), require("rehype-katex"), require("rehype-raw"), require("reaviz"), require("mdast-util-find-and-replace"), require("lodash/debounce.js"), require("reakeys"), require("remark-gfm"), require("remark-youtube"), require("remark-math"), require("date-fns"), require("@floating-ui/react"), require("zod")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "reablocks", "react", "motion/react", "@tiptap/react", "@floating-ui/dom", "@tiptap/extension-document", "@tiptap/extension-paragraph", "@tiptap/extension-text", "@tiptap/extension-hard-break", "@tiptap/extension-placeholder", "@tiptap/extension-mention", "@radix-ui/react-slot", "react-markdown", "react-syntax-highlighter", "rehype-katex", "rehype-raw", "reaviz", "mdast-util-find-and-replace", "lodash/debounce.js", "reakeys", "remark-gfm", "remark-youtube", "remark-math", "date-fns", "@floating-ui/react", "zod"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.reachat = {}, global.jsxRuntime, global.reablocks, global.React, global.react$1, global.react, global.dom, global.Document, global.Paragraph, global.Text, global.HardBreak, global.Placeholder, global.Mention, global.reactSlot, global.ReactMarkdown, global.reactSyntaxHighlighter, global.rehypeKatex, global.rehypeRaw, global.reaviz, global.mdastUtilFindAndReplace, global.debounce, global.reakeys, global.remarkGfm, global.remarkYoutube, global.remarkMath, global.dateFns, global.react$2, global.zod));
|
|
15
|
+
})(this, function(exports2, jsxRuntime, reablocks, React, react$1, react, dom, Document, Paragraph, Text, HardBreak, Placeholder, Mention, reactSlot, ReactMarkdown, reactSyntaxHighlighter, rehypeKatex, rehypeRaw, reaviz, mdastUtilFindAndReplace, debounce, reakeys, remarkGfm, remarkYoutube, remarkMath, dateFns, react$2, zod) {
|
|
16
16
|
"use strict";
|
|
17
17
|
function _interopNamespaceDefault(e) {
|
|
18
18
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -320,6 +320,9 @@
|
|
|
320
320
|
].join(" "),
|
|
321
321
|
title: "text-yellow-600 dark:text-yellow-400 text-sm font-medium mb-2"
|
|
322
322
|
}
|
|
323
|
+
},
|
|
324
|
+
component: {
|
|
325
|
+
base: "my-4"
|
|
323
326
|
}
|
|
324
327
|
};
|
|
325
328
|
const POPUP_STYLE = { zIndex: 9999 };
|
|
@@ -1963,6 +1966,8 @@
|
|
|
1963
1966
|
li: (props) => /* @__PURE__ */ jsxRuntime.jsx("li", { ...props, className: reablocks.cn(theme.messages.message.markdown.li) }),
|
|
1964
1967
|
ul: (props) => /* @__PURE__ */ jsxRuntime.jsx("ul", { ...props, className: reablocks.cn(theme.messages.message.markdown.ul) }),
|
|
1965
1968
|
ol: (props) => /* @__PURE__ */ jsxRuntime.jsx("ol", { ...props, className: reablocks.cn(theme.messages.message.markdown.ol) }),
|
|
1969
|
+
// 'redact' is a custom element created by remarkRedact, not a standard
|
|
1970
|
+
// HTML tag, so it falls outside react-markdown's Components type.
|
|
1966
1971
|
redact: (props) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1967
1972
|
reablocks.Redact,
|
|
1968
1973
|
{
|
|
@@ -1988,7 +1993,7 @@
|
|
|
1988
1993
|
}
|
|
1989
1994
|
);
|
|
1990
1995
|
};
|
|
1991
|
-
const
|
|
1996
|
+
const ComponentError = ({
|
|
1992
1997
|
variant = "error",
|
|
1993
1998
|
title,
|
|
1994
1999
|
message,
|
|
@@ -2016,12 +2021,12 @@
|
|
|
2016
2021
|
data: d.data
|
|
2017
2022
|
}));
|
|
2018
2023
|
if (!chartData || chartData.length === 0) {
|
|
2019
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2024
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { variant: "warning", message: "No chart data available" });
|
|
2020
2025
|
}
|
|
2021
2026
|
for (const point of chartData) {
|
|
2022
2027
|
if (typeof point.data !== "number" || isNaN(point.data)) {
|
|
2023
2028
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2024
|
-
|
|
2029
|
+
ComponentError,
|
|
2025
2030
|
{
|
|
2026
2031
|
message: `Invalid data point: ${JSON.stringify(point)}`
|
|
2027
2032
|
}
|
|
@@ -2090,10 +2095,10 @@
|
|
|
2090
2095
|
case "sparkline":
|
|
2091
2096
|
return /* @__PURE__ */ jsxRuntime.jsx(reaviz.SparklineChart, { width, height, data: chartData });
|
|
2092
2097
|
default:
|
|
2093
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2098
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { message: `Unknown chart type: ${type}` });
|
|
2094
2099
|
}
|
|
2095
2100
|
} catch (error) {
|
|
2096
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2101
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { message: `Chart render error: ${String(error)}` });
|
|
2097
2102
|
}
|
|
2098
2103
|
}, [type, data, width, height]);
|
|
2099
2104
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: reablocks.cn(theme.chart.base, className), children: [
|
|
@@ -2101,93 +2106,6 @@
|
|
|
2101
2106
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: theme.chart.content, children: chartElement })
|
|
2102
2107
|
] });
|
|
2103
2108
|
};
|
|
2104
|
-
function validateChartData(data) {
|
|
2105
|
-
if (!Array.isArray(data)) {
|
|
2106
|
-
return null;
|
|
2107
|
-
}
|
|
2108
|
-
const validData = [];
|
|
2109
|
-
for (const item of data) {
|
|
2110
|
-
if (item && typeof item === "object" && "key" in item && "data" in item && typeof item.data === "number") {
|
|
2111
|
-
validData.push({
|
|
2112
|
-
key: String(item.key),
|
|
2113
|
-
data: item.data
|
|
2114
|
-
});
|
|
2115
|
-
} else {
|
|
2116
|
-
return null;
|
|
2117
|
-
}
|
|
2118
|
-
}
|
|
2119
|
-
return validData.length > 0 ? validData : null;
|
|
2120
|
-
}
|
|
2121
|
-
function parseChartConfig(value) {
|
|
2122
|
-
try {
|
|
2123
|
-
const config = JSON.parse(value);
|
|
2124
|
-
if (!config || !config.type || !config.data) {
|
|
2125
|
-
return null;
|
|
2126
|
-
}
|
|
2127
|
-
const validData = validateChartData(config.data);
|
|
2128
|
-
if (!validData) {
|
|
2129
|
-
console.warn("parseChartConfig: Invalid chart data format");
|
|
2130
|
-
return null;
|
|
2131
|
-
}
|
|
2132
|
-
return {
|
|
2133
|
-
...config,
|
|
2134
|
-
data: validData
|
|
2135
|
-
};
|
|
2136
|
-
} catch (error) {
|
|
2137
|
-
console.warn("parseChartConfig: Failed to parse JSON", error);
|
|
2138
|
-
return null;
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
function isChartClassName(className) {
|
|
2142
|
-
return className === "language-chart";
|
|
2143
|
-
}
|
|
2144
|
-
function getChildText(children) {
|
|
2145
|
-
if (children === null || children === void 0) {
|
|
2146
|
-
return "";
|
|
2147
|
-
}
|
|
2148
|
-
if (typeof children === "string") {
|
|
2149
|
-
return children;
|
|
2150
|
-
}
|
|
2151
|
-
if (typeof children === "number") {
|
|
2152
|
-
return String(children);
|
|
2153
|
-
}
|
|
2154
|
-
if (Array.isArray(children)) {
|
|
2155
|
-
return children.map(getChildText).join("");
|
|
2156
|
-
}
|
|
2157
|
-
if (typeof children === "object") {
|
|
2158
|
-
if ("props" in children && children.props) {
|
|
2159
|
-
const element = children;
|
|
2160
|
-
return getChildText(element.props.children);
|
|
2161
|
-
}
|
|
2162
|
-
}
|
|
2163
|
-
return "";
|
|
2164
|
-
}
|
|
2165
|
-
const ChartPre = ({ children, ...props }) => {
|
|
2166
|
-
var _a, _b;
|
|
2167
|
-
if (children && typeof children === "object" && "props" in children) {
|
|
2168
|
-
const codeElement = children;
|
|
2169
|
-
if (isChartClassName((_a = codeElement.props) == null ? void 0 : _a.className)) {
|
|
2170
|
-
const codeContent = getChildText((_b = codeElement.props) == null ? void 0 : _b.children);
|
|
2171
|
-
if (codeContent) {
|
|
2172
|
-
const chartConfig = parseChartConfig(codeContent);
|
|
2173
|
-
if (chartConfig) {
|
|
2174
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ChartRenderer, { config: chartConfig });
|
|
2175
|
-
}
|
|
2176
|
-
}
|
|
2177
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2178
|
-
ChartError,
|
|
2179
|
-
{
|
|
2180
|
-
title: "Failed to parse chart configuration",
|
|
2181
|
-
code: codeContent || "No content"
|
|
2182
|
-
}
|
|
2183
|
-
);
|
|
2184
|
-
}
|
|
2185
|
-
}
|
|
2186
|
-
return /* @__PURE__ */ jsxRuntime.jsx("pre", { ...props, children });
|
|
2187
|
-
};
|
|
2188
|
-
const chartComponents = {
|
|
2189
|
-
pre: ChartPre
|
|
2190
|
-
};
|
|
2191
2109
|
const CVE_REGEX = /(CVE-(19|20)\d{2}-\d{4,7})/gi;
|
|
2192
2110
|
function remarkCve() {
|
|
2193
2111
|
return (tree, _file) => {
|
|
@@ -2208,31 +2126,8 @@
|
|
|
2208
2126
|
];
|
|
2209
2127
|
}
|
|
2210
2128
|
}
|
|
2211
|
-
const
|
|
2212
|
-
|
|
2213
|
-
return (tree) => {
|
|
2214
|
-
unistUtilVisit.visit(tree, "code", (node) => {
|
|
2215
|
-
if (node.lang !== "chart") {
|
|
2216
|
-
return;
|
|
2217
|
-
}
|
|
2218
|
-
try {
|
|
2219
|
-
const config = JSON.parse(node.value);
|
|
2220
|
-
if (!config.type || !config.data) {
|
|
2221
|
-
console.warn(
|
|
2222
|
-
"remarkChart: Invalid chart config - missing type or data"
|
|
2223
|
-
);
|
|
2224
|
-
return;
|
|
2225
|
-
}
|
|
2226
|
-
const chartConfig = {
|
|
2227
|
-
...config,
|
|
2228
|
-
width: config.width ?? defaultWidth,
|
|
2229
|
-
height: config.height ?? defaultHeight
|
|
2230
|
-
};
|
|
2231
|
-
node.value = JSON.stringify(chartConfig);
|
|
2232
|
-
} catch (error) {
|
|
2233
|
-
console.warn("remarkChart: Failed to parse chart config:", error);
|
|
2234
|
-
}
|
|
2235
|
-
});
|
|
2129
|
+
const remarkComponent = (_options = {}) => {
|
|
2130
|
+
return () => {
|
|
2236
2131
|
};
|
|
2237
2132
|
};
|
|
2238
2133
|
function remarkRedact(matchers) {
|
|
@@ -2960,6 +2855,7 @@ ${response}` : ""}`);
|
|
|
2960
2855
|
onNewSession,
|
|
2961
2856
|
remarkPlugins = defaultRemarkPlugins,
|
|
2962
2857
|
markdownComponents,
|
|
2858
|
+
components: componentCatalog2,
|
|
2963
2859
|
disabled,
|
|
2964
2860
|
style,
|
|
2965
2861
|
className
|
|
@@ -3004,12 +2900,23 @@ ${response}` : ""}`);
|
|
|
3004
2900
|
() => sessions.find((session) => session.id === internalActiveSessionID),
|
|
3005
2901
|
[sessions, internalActiveSessionID]
|
|
3006
2902
|
);
|
|
2903
|
+
const mergedRemarkPlugins = React.useMemo(() => {
|
|
2904
|
+
if (!componentCatalog2) return remarkPlugins;
|
|
2905
|
+
return [...remarkPlugins, componentCatalog2.remarkPlugin];
|
|
2906
|
+
}, [remarkPlugins, componentCatalog2]);
|
|
2907
|
+
const mergedMarkdownComponents = React.useMemo(() => {
|
|
2908
|
+
if (!componentCatalog2) return markdownComponents;
|
|
2909
|
+
return {
|
|
2910
|
+
...componentCatalog2.components,
|
|
2911
|
+
...markdownComponents
|
|
2912
|
+
};
|
|
2913
|
+
}, [markdownComponents, componentCatalog2]);
|
|
3007
2914
|
const contextValue = React.useMemo(
|
|
3008
2915
|
() => ({
|
|
3009
2916
|
sessions,
|
|
3010
2917
|
activeSession,
|
|
3011
|
-
remarkPlugins,
|
|
3012
|
-
markdownComponents,
|
|
2918
|
+
remarkPlugins: mergedRemarkPlugins,
|
|
2919
|
+
markdownComponents: mergedMarkdownComponents,
|
|
3013
2920
|
theme,
|
|
3014
2921
|
disabled,
|
|
3015
2922
|
isLoading,
|
|
@@ -3029,8 +2936,8 @@ ${response}` : ""}`);
|
|
|
3029
2936
|
viewType,
|
|
3030
2937
|
disabled,
|
|
3031
2938
|
theme,
|
|
3032
|
-
|
|
3033
|
-
|
|
2939
|
+
mergedRemarkPlugins,
|
|
2940
|
+
mergedMarkdownComponents,
|
|
3034
2941
|
sessions,
|
|
3035
2942
|
activeSession,
|
|
3036
2943
|
internalActiveSessionID,
|
|
@@ -3797,10 +3704,424 @@ ${response}` : ""}`);
|
|
|
3797
3704
|
stopMessage
|
|
3798
3705
|
};
|
|
3799
3706
|
}
|
|
3707
|
+
function validateSpec(raw, definitions) {
|
|
3708
|
+
let parsed;
|
|
3709
|
+
try {
|
|
3710
|
+
parsed = JSON.parse(raw);
|
|
3711
|
+
} catch {
|
|
3712
|
+
return {
|
|
3713
|
+
ok: false,
|
|
3714
|
+
error: {
|
|
3715
|
+
type: "invalid_json",
|
|
3716
|
+
message: "Failed to parse component JSON",
|
|
3717
|
+
raw
|
|
3718
|
+
}
|
|
3719
|
+
};
|
|
3720
|
+
}
|
|
3721
|
+
const specArray = Array.isArray(parsed) ? parsed : [parsed];
|
|
3722
|
+
const validated = [];
|
|
3723
|
+
for (const item of specArray) {
|
|
3724
|
+
const result = validateSingleSpec(item, raw, definitions);
|
|
3725
|
+
if (!result.ok) {
|
|
3726
|
+
return { ok: false, error: result.error };
|
|
3727
|
+
}
|
|
3728
|
+
validated.push(result.spec);
|
|
3729
|
+
}
|
|
3730
|
+
return { ok: true, specs: validated };
|
|
3731
|
+
}
|
|
3732
|
+
function validateSingleSpec(item, raw, definitions) {
|
|
3733
|
+
if (!item || typeof item !== "object" || !("type" in item)) {
|
|
3734
|
+
return {
|
|
3735
|
+
ok: false,
|
|
3736
|
+
error: {
|
|
3737
|
+
type: "invalid_json",
|
|
3738
|
+
message: 'Component spec must be an object with a "type" field',
|
|
3739
|
+
raw
|
|
3740
|
+
}
|
|
3741
|
+
};
|
|
3742
|
+
}
|
|
3743
|
+
const spec = item;
|
|
3744
|
+
if (typeof spec.type !== "string") {
|
|
3745
|
+
return {
|
|
3746
|
+
ok: false,
|
|
3747
|
+
error: {
|
|
3748
|
+
type: "invalid_json",
|
|
3749
|
+
message: '"type" must be a string',
|
|
3750
|
+
raw
|
|
3751
|
+
}
|
|
3752
|
+
};
|
|
3753
|
+
}
|
|
3754
|
+
const componentType = spec.type;
|
|
3755
|
+
const definition = definitions[componentType];
|
|
3756
|
+
if (!definition) {
|
|
3757
|
+
return {
|
|
3758
|
+
ok: false,
|
|
3759
|
+
error: {
|
|
3760
|
+
type: "unknown_component",
|
|
3761
|
+
message: `Unknown component "${componentType}". Available: ${Object.keys(definitions).join(", ")}`,
|
|
3762
|
+
raw,
|
|
3763
|
+
componentType
|
|
3764
|
+
}
|
|
3765
|
+
};
|
|
3766
|
+
}
|
|
3767
|
+
const props = spec.props && typeof spec.props === "object" && !Array.isArray(spec.props) ? spec.props : {};
|
|
3768
|
+
const parseResult = definition.props.safeParse(props);
|
|
3769
|
+
if (!parseResult.success) {
|
|
3770
|
+
return {
|
|
3771
|
+
ok: false,
|
|
3772
|
+
error: {
|
|
3773
|
+
type: "invalid_props",
|
|
3774
|
+
message: `Invalid props for "${componentType}": ${parseResult.error.issues.map((i) => i.message).join(", ")}`,
|
|
3775
|
+
raw,
|
|
3776
|
+
componentType,
|
|
3777
|
+
issues: parseResult.error.issues.map((i) => ({
|
|
3778
|
+
message: i.message,
|
|
3779
|
+
path: i.path
|
|
3780
|
+
}))
|
|
3781
|
+
}
|
|
3782
|
+
};
|
|
3783
|
+
}
|
|
3784
|
+
let validatedChildren;
|
|
3785
|
+
if (spec.children) {
|
|
3786
|
+
if (!Array.isArray(spec.children)) {
|
|
3787
|
+
return {
|
|
3788
|
+
ok: false,
|
|
3789
|
+
error: {
|
|
3790
|
+
type: "invalid_json",
|
|
3791
|
+
message: '"children" must be an array',
|
|
3792
|
+
raw,
|
|
3793
|
+
componentType
|
|
3794
|
+
}
|
|
3795
|
+
};
|
|
3796
|
+
}
|
|
3797
|
+
validatedChildren = [];
|
|
3798
|
+
for (const child of spec.children) {
|
|
3799
|
+
const childResult = validateSingleSpec(child, raw, definitions);
|
|
3800
|
+
if (!childResult.ok) {
|
|
3801
|
+
return childResult;
|
|
3802
|
+
}
|
|
3803
|
+
validatedChildren.push(childResult.spec);
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
return {
|
|
3807
|
+
ok: true,
|
|
3808
|
+
spec: {
|
|
3809
|
+
type: componentType,
|
|
3810
|
+
props: parseResult.data,
|
|
3811
|
+
...validatedChildren ? { children: validatedChildren } : {}
|
|
3812
|
+
}
|
|
3813
|
+
};
|
|
3814
|
+
}
|
|
3815
|
+
const ComponentRenderer = ({
|
|
3816
|
+
raw,
|
|
3817
|
+
definitions,
|
|
3818
|
+
options
|
|
3819
|
+
}) => {
|
|
3820
|
+
var _a, _b;
|
|
3821
|
+
const { theme, sendMessage } = React.useContext(ChatContext);
|
|
3822
|
+
const result = React.useMemo(
|
|
3823
|
+
() => validateSpec(raw, definitions),
|
|
3824
|
+
[raw, definitions]
|
|
3825
|
+
);
|
|
3826
|
+
if (!result.ok) {
|
|
3827
|
+
const error = result.error;
|
|
3828
|
+
const custom = (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, error);
|
|
3829
|
+
if (custom !== void 0) {
|
|
3830
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
|
|
3831
|
+
}
|
|
3832
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3833
|
+
ComponentError,
|
|
3834
|
+
{
|
|
3835
|
+
title: errorTitle(error.type),
|
|
3836
|
+
message: error.message,
|
|
3837
|
+
code: error.raw
|
|
3838
|
+
}
|
|
3839
|
+
);
|
|
3840
|
+
}
|
|
3841
|
+
const specs = result.specs;
|
|
3842
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: (_b = theme.component) == null ? void 0 : _b.base, children: specs.map((spec, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3843
|
+
SpecRenderer,
|
|
3844
|
+
{
|
|
3845
|
+
spec,
|
|
3846
|
+
definitions,
|
|
3847
|
+
options,
|
|
3848
|
+
sendMessage
|
|
3849
|
+
},
|
|
3850
|
+
`${spec.type}-${index}-${stableKey(spec)}`
|
|
3851
|
+
)) });
|
|
3852
|
+
};
|
|
3853
|
+
const SpecRenderer = ({
|
|
3854
|
+
spec,
|
|
3855
|
+
definitions,
|
|
3856
|
+
options,
|
|
3857
|
+
sendMessage
|
|
3858
|
+
}) => {
|
|
3859
|
+
var _a, _b;
|
|
3860
|
+
const definition = definitions[spec.type];
|
|
3861
|
+
if (!definition) {
|
|
3862
|
+
const error = {
|
|
3863
|
+
type: "unknown_component",
|
|
3864
|
+
message: `Unknown component "${spec.type}"`,
|
|
3865
|
+
raw: JSON.stringify(spec),
|
|
3866
|
+
componentType: spec.type
|
|
3867
|
+
};
|
|
3868
|
+
const custom = (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, error);
|
|
3869
|
+
if (custom !== void 0) {
|
|
3870
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
|
|
3871
|
+
}
|
|
3872
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { title: errorTitle(error.type), message: error.message });
|
|
3873
|
+
}
|
|
3874
|
+
const RenderedComponent = definition.component;
|
|
3875
|
+
const children = (_b = spec.children) == null ? void 0 : _b.map((child, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3876
|
+
SpecRenderer,
|
|
3877
|
+
{
|
|
3878
|
+
spec: child,
|
|
3879
|
+
definitions,
|
|
3880
|
+
options,
|
|
3881
|
+
sendMessage
|
|
3882
|
+
},
|
|
3883
|
+
`${child.type}-${index}-${stableKey(child)}`
|
|
3884
|
+
));
|
|
3885
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SpecErrorBoundary, { spec, options, children: /* @__PURE__ */ jsxRuntime.jsx(RenderedComponent, { ...spec.props, sendMessage, children }) });
|
|
3886
|
+
};
|
|
3887
|
+
class SpecErrorBoundary extends React.Component {
|
|
3888
|
+
constructor() {
|
|
3889
|
+
super(...arguments);
|
|
3890
|
+
this.state = { error: null };
|
|
3891
|
+
}
|
|
3892
|
+
static getDerivedStateFromError(error) {
|
|
3893
|
+
return { error };
|
|
3894
|
+
}
|
|
3895
|
+
render() {
|
|
3896
|
+
var _a;
|
|
3897
|
+
if (this.state.error) {
|
|
3898
|
+
const { spec, options } = this.props;
|
|
3899
|
+
const catalogError = {
|
|
3900
|
+
type: "render_error",
|
|
3901
|
+
message: `Error rendering "${spec.type}": ${this.state.error.message}`,
|
|
3902
|
+
raw: JSON.stringify(spec),
|
|
3903
|
+
componentType: spec.type
|
|
3904
|
+
};
|
|
3905
|
+
const custom = (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, catalogError);
|
|
3906
|
+
if (custom !== void 0) {
|
|
3907
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
|
|
3908
|
+
}
|
|
3909
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3910
|
+
ComponentError,
|
|
3911
|
+
{
|
|
3912
|
+
title: errorTitle(catalogError.type),
|
|
3913
|
+
message: catalogError.message
|
|
3914
|
+
}
|
|
3915
|
+
);
|
|
3916
|
+
}
|
|
3917
|
+
return this.props.children;
|
|
3918
|
+
}
|
|
3919
|
+
}
|
|
3920
|
+
function stableKey(spec) {
|
|
3921
|
+
const str = JSON.stringify({
|
|
3922
|
+
t: spec.type,
|
|
3923
|
+
p: spec.props,
|
|
3924
|
+
c: spec.children
|
|
3925
|
+
});
|
|
3926
|
+
let h = 0;
|
|
3927
|
+
for (let i = 0; i < str.length; i++) {
|
|
3928
|
+
h = h * 31 + str.charCodeAt(i) | 0;
|
|
3929
|
+
}
|
|
3930
|
+
return (h >>> 0).toString(36);
|
|
3931
|
+
}
|
|
3932
|
+
function errorTitle(type) {
|
|
3933
|
+
switch (type) {
|
|
3934
|
+
case "unknown_component":
|
|
3935
|
+
return "Unknown Component";
|
|
3936
|
+
case "invalid_props":
|
|
3937
|
+
return "Invalid Props";
|
|
3938
|
+
case "render_error":
|
|
3939
|
+
return "Render Error";
|
|
3940
|
+
default:
|
|
3941
|
+
return "Invalid Component";
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3944
|
+
function getChildText(children) {
|
|
3945
|
+
if (children === null || children === void 0) {
|
|
3946
|
+
return "";
|
|
3947
|
+
}
|
|
3948
|
+
if (typeof children === "string") {
|
|
3949
|
+
return children;
|
|
3950
|
+
}
|
|
3951
|
+
if (typeof children === "number") {
|
|
3952
|
+
return String(children);
|
|
3953
|
+
}
|
|
3954
|
+
if (Array.isArray(children)) {
|
|
3955
|
+
return children.map(getChildText).join("");
|
|
3956
|
+
}
|
|
3957
|
+
if (typeof children === "object") {
|
|
3958
|
+
if ("props" in children && children.props) {
|
|
3959
|
+
const element = children;
|
|
3960
|
+
return getChildText(element.props.children);
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
return "";
|
|
3964
|
+
}
|
|
3965
|
+
function createComponentPre(definitions, options) {
|
|
3966
|
+
const language = (options == null ? void 0 : options.language) ?? "component";
|
|
3967
|
+
const className = `language-${language}`;
|
|
3968
|
+
const ComponentPre = ({ children, ...props }) => {
|
|
3969
|
+
var _a, _b;
|
|
3970
|
+
if (children && typeof children === "object" && "props" in children) {
|
|
3971
|
+
const codeElement = children;
|
|
3972
|
+
if (((_a = codeElement.props) == null ? void 0 : _a.className) === className) {
|
|
3973
|
+
const codeContent = getChildText((_b = codeElement.props) == null ? void 0 : _b.children);
|
|
3974
|
+
if (codeContent) {
|
|
3975
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3976
|
+
ComponentRenderer,
|
|
3977
|
+
{
|
|
3978
|
+
raw: codeContent,
|
|
3979
|
+
definitions,
|
|
3980
|
+
options
|
|
3981
|
+
}
|
|
3982
|
+
);
|
|
3983
|
+
}
|
|
3984
|
+
}
|
|
3985
|
+
}
|
|
3986
|
+
return /* @__PURE__ */ jsxRuntime.jsx("pre", { ...props, children });
|
|
3987
|
+
};
|
|
3988
|
+
ComponentPre.displayName = "ComponentPre";
|
|
3989
|
+
return ComponentPre;
|
|
3990
|
+
}
|
|
3991
|
+
function describeJsonSchemaProperty(prop, indent = "") {
|
|
3992
|
+
const description = prop.description ? ` // ${prop.description}` : "";
|
|
3993
|
+
if (prop.anyOf) {
|
|
3994
|
+
const nonNull = prop.anyOf.filter((s) => !(s.type === "null"));
|
|
3995
|
+
const hasNull = prop.anyOf.some((s) => s.type === "null");
|
|
3996
|
+
if (nonNull.length === 1 && hasNull) {
|
|
3997
|
+
return `${describeJsonSchemaProperty(nonNull[0], indent)} | null${description}`;
|
|
3998
|
+
}
|
|
3999
|
+
const parts = prop.anyOf.map(
|
|
4000
|
+
(s) => describeJsonSchemaProperty(s, indent)
|
|
4001
|
+
);
|
|
4002
|
+
return `${parts.join(" | ")}${description}`;
|
|
4003
|
+
}
|
|
4004
|
+
if (prop.enum) {
|
|
4005
|
+
return `${prop.enum.map((v) => `"${v}"`).join(" | ")}${description}`;
|
|
4006
|
+
}
|
|
4007
|
+
if (prop.type === "array") {
|
|
4008
|
+
const items = prop.items ? describeJsonSchemaProperty(prop.items, indent) : "any";
|
|
4009
|
+
return `${items}[]${description}`;
|
|
4010
|
+
}
|
|
4011
|
+
if (prop.type === "object" && prop.properties) {
|
|
4012
|
+
const required = new Set(prop.required ?? []);
|
|
4013
|
+
const fields = [];
|
|
4014
|
+
for (const [key, value] of Object.entries(prop.properties)) {
|
|
4015
|
+
const opt = required.has(key) ? "" : "?";
|
|
4016
|
+
fields.push(
|
|
4017
|
+
`${indent} ${key}: ${describeJsonSchemaProperty(value, indent + " ")}${opt}`
|
|
4018
|
+
);
|
|
4019
|
+
}
|
|
4020
|
+
return `{
|
|
4021
|
+
${fields.join(",\n")}
|
|
4022
|
+
${indent}}${description}`;
|
|
4023
|
+
}
|
|
4024
|
+
if (prop.type === "string") return `string${description}`;
|
|
4025
|
+
if (prop.type === "number" || prop.type === "integer")
|
|
4026
|
+
return `number${description}`;
|
|
4027
|
+
if (prop.type === "boolean") return `boolean${description}`;
|
|
4028
|
+
if (prop.type === "null") return `null${description}`;
|
|
4029
|
+
return `any${description}`;
|
|
4030
|
+
}
|
|
4031
|
+
function describeProps(schema) {
|
|
4032
|
+
try {
|
|
4033
|
+
const jsonSchema = zod.z.toJSONSchema(schema);
|
|
4034
|
+
if (jsonSchema.type === "object" && jsonSchema.properties) {
|
|
4035
|
+
return describeJsonSchemaProperty(jsonSchema);
|
|
4036
|
+
}
|
|
4037
|
+
return "Record<string, any>";
|
|
4038
|
+
} catch {
|
|
4039
|
+
return "Record<string, any>";
|
|
4040
|
+
}
|
|
4041
|
+
}
|
|
4042
|
+
function generatePrompt(definitions, language = "component") {
|
|
4043
|
+
const names = Object.keys(definitions);
|
|
4044
|
+
if (names.length === 0) {
|
|
4045
|
+
return "";
|
|
4046
|
+
}
|
|
4047
|
+
const componentDocs = names.map((name) => {
|
|
4048
|
+
const def = definitions[name];
|
|
4049
|
+
const propsDesc = describeProps(def.props);
|
|
4050
|
+
return `- **${name}**: ${def.description}
|
|
4051
|
+
Props: ${propsDesc}`;
|
|
4052
|
+
}).join("\n\n");
|
|
4053
|
+
return `When you need to render a dynamic UI component in your response, use a fenced code block with language \`${language}\` containing a JSON object:
|
|
4054
|
+
|
|
4055
|
+
\`\`\`${language}
|
|
4056
|
+
{ "type": "ComponentName", "props": { ... } }
|
|
4057
|
+
\`\`\`
|
|
4058
|
+
|
|
4059
|
+
For multiple components, use a JSON array:
|
|
4060
|
+
|
|
4061
|
+
\`\`\`${language}
|
|
4062
|
+
[
|
|
4063
|
+
{ "type": "ComponentA", "props": { ... } },
|
|
4064
|
+
{ "type": "ComponentB", "props": { ... } }
|
|
4065
|
+
]
|
|
4066
|
+
\`\`\`
|
|
4067
|
+
|
|
4068
|
+
For nested/composed layouts, use the "children" field:
|
|
4069
|
+
|
|
4070
|
+
\`\`\`${language}
|
|
4071
|
+
{
|
|
4072
|
+
"type": "Parent",
|
|
4073
|
+
"props": { ... },
|
|
4074
|
+
"children": [
|
|
4075
|
+
{ "type": "Child", "props": { ... } }
|
|
4076
|
+
]
|
|
4077
|
+
}
|
|
4078
|
+
\`\`\`
|
|
4079
|
+
|
|
4080
|
+
Available components:
|
|
4081
|
+
|
|
4082
|
+
${componentDocs}`;
|
|
4083
|
+
}
|
|
4084
|
+
function componentCatalog(definitions, options) {
|
|
4085
|
+
const language = (options == null ? void 0 : options.language) ?? "component";
|
|
4086
|
+
const plugin = remarkComponent.bind(void 0, {
|
|
4087
|
+
language
|
|
4088
|
+
});
|
|
4089
|
+
const Pre = createComponentPre(definitions, options);
|
|
4090
|
+
return {
|
|
4091
|
+
remarkPlugin: plugin,
|
|
4092
|
+
components: { pre: Pre },
|
|
4093
|
+
systemPrompt: () => generatePrompt(definitions, language),
|
|
4094
|
+
definitions
|
|
4095
|
+
};
|
|
4096
|
+
}
|
|
4097
|
+
function createChartComponentDef() {
|
|
4098
|
+
const chartPropsSchema = zod.z.object({
|
|
4099
|
+
type: zod.z.enum([
|
|
4100
|
+
"bar",
|
|
4101
|
+
"line",
|
|
4102
|
+
"area",
|
|
4103
|
+
"pie",
|
|
4104
|
+
"radialBar",
|
|
4105
|
+
"radialArea",
|
|
4106
|
+
"sparkline"
|
|
4107
|
+
]).describe("Chart type"),
|
|
4108
|
+
data: zod.z.array(zod.z.object({ key: zod.z.string(), data: zod.z.number() })).describe("Array of { key, data } data points"),
|
|
4109
|
+
width: zod.z.number().describe("Chart width in px").optional(),
|
|
4110
|
+
height: zod.z.number().describe("Chart height in px").optional(),
|
|
4111
|
+
title: zod.z.string().describe("Chart title").optional()
|
|
4112
|
+
});
|
|
4113
|
+
return {
|
|
4114
|
+
description: "Renders a chart. Supported types: bar, line, area, pie, radialBar, radialArea, sparkline",
|
|
4115
|
+
props: chartPropsSchema,
|
|
4116
|
+
component: ({
|
|
4117
|
+
children: _children,
|
|
4118
|
+
sendMessage: _sendMessage,
|
|
4119
|
+
...config
|
|
4120
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(ChartRenderer, { config })
|
|
4121
|
+
};
|
|
4122
|
+
}
|
|
3800
4123
|
exports2.AgUiEventType = AgUiEventType;
|
|
3801
4124
|
exports2.AppBar = AppBar;
|
|
3802
|
-
exports2.ChartError = ChartError;
|
|
3803
|
-
exports2.ChartPre = ChartPre;
|
|
3804
4125
|
exports2.ChartRenderer = ChartRenderer;
|
|
3805
4126
|
exports2.Chat = Chat;
|
|
3806
4127
|
exports2.ChatBubble = ChatBubble;
|
|
@@ -3809,6 +4130,8 @@ ${response}` : ""}`);
|
|
|
3809
4130
|
exports2.ChatSuggestion = ChatSuggestion;
|
|
3810
4131
|
exports2.ChatSuggestions = ChatSuggestions;
|
|
3811
4132
|
exports2.CodeHighlighter = CodeHighlighter;
|
|
4133
|
+
exports2.ComponentError = ComponentError;
|
|
4134
|
+
exports2.ComponentRenderer = ComponentRenderer;
|
|
3812
4135
|
exports2.FileInput = FileInput;
|
|
3813
4136
|
exports2.Markdown = Markdown;
|
|
3814
4137
|
exports2.MentionList = MentionList;
|
|
@@ -3837,21 +4160,21 @@ ${response}` : ""}`);
|
|
|
3837
4160
|
exports2.TableDataCell = TableDataCell;
|
|
3838
4161
|
exports2.TableHeaderCell = TableHeaderCell;
|
|
3839
4162
|
exports2.bitcoinMatcher = bitcoinMatcher;
|
|
3840
|
-
exports2.chartComponents = chartComponents;
|
|
3841
4163
|
exports2.chatTheme = chatTheme;
|
|
3842
4164
|
exports2.commonRedactMatchers = commonRedactMatchers;
|
|
4165
|
+
exports2.componentCatalog = componentCatalog;
|
|
4166
|
+
exports2.createChartComponentDef = createChartComponentDef;
|
|
4167
|
+
exports2.createComponentPre = createComponentPre;
|
|
3843
4168
|
exports2.creditCardMatcher = creditCardMatcher;
|
|
3844
4169
|
exports2.dark = dark;
|
|
3845
|
-
exports2.
|
|
3846
|
-
exports2.isChartClassName = isChartClassName;
|
|
4170
|
+
exports2.generatePrompt = generatePrompt;
|
|
3847
4171
|
exports2.light = light;
|
|
3848
|
-
exports2.
|
|
3849
|
-
exports2.remarkChart = remarkChart;
|
|
4172
|
+
exports2.remarkComponent = remarkComponent;
|
|
3850
4173
|
exports2.remarkCve = remarkCve;
|
|
3851
4174
|
exports2.remarkRedact = remarkRedact;
|
|
3852
4175
|
exports2.ssnMatcher = ssnMatcher;
|
|
3853
4176
|
exports2.useAgUi = useAgUi;
|
|
3854
|
-
exports2.
|
|
4177
|
+
exports2.validateSpec = validateSpec;
|
|
3855
4178
|
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
3856
4179
|
});
|
|
3857
4180
|
//# sourceMappingURL=index.umd.cjs.map
|