reachat 2.1.2 → 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-DXI8PDqR.js → CSVFileRenderer-C2tuexJf.js} +2 -2
- package/dist/{CSVFileRenderer-DXI8PDqR.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-Bi8LNDio.js → DefaultFileRenderer-CJ3jwiQa.js} +3 -3
- package/dist/{DefaultFileRenderer-Bi8LNDio.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 +3 -1
- package/dist/Markdown/plugins/redactMatchers.d.ts +21 -0
- package/dist/Markdown/plugins/remarkComponent.d.ts +27 -0
- package/dist/Markdown/plugins/remarkRedact.d.ts +37 -0
- package/dist/SessionMessages/SessionMessage/MessageActions.d.ts +2 -2
- package/dist/SessionMessages/SessionMessage/MessageFiles.d.ts +2 -2
- package/dist/SessionMessages/SessionMessage/MessageQuestion.d.ts +2 -2
- package/dist/SessionMessages/SessionMessage/MessageResponse.d.ts +2 -2
- package/dist/SessionMessages/SessionMessage/MessageSources.d.ts +2 -2
- package/dist/SessionMessages/SessionMessage/SessionMessage.d.ts +2 -2
- package/dist/SessionsList/SessionListItem.d.ts +2 -2
- package/dist/docs.json +264 -90
- package/dist/{index-CBHNcMyR.js → index-8tlsyFe-.js} +1224 -1576
- package/dist/index-8tlsyFe-.js.map +1 -0
- package/dist/index.css +32 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +53 -46
- package/dist/index.umd.cjs +1220 -1574
- package/dist/index.umd.cjs.map +1 -1
- package/dist/stories/AgUi.stories.tsx +118 -0
- package/dist/stories/Charts.stories.tsx +118 -130
- package/dist/stories/Chat.stories.tsx +6 -1
- package/dist/stories/ChatSuggestions.stories.tsx +9 -81
- package/dist/stories/Companion.stories.tsx +7 -1
- package/dist/stories/ComponentCatalog.stories.tsx +509 -0
- package/dist/stories/{ChartError.stories.tsx → ComponentError.stories.tsx} +14 -11
- package/dist/stories/Console.stories.tsx +66 -21
- package/dist/stories/EnhancedInput.stories.tsx +7 -1
- package/dist/stories/Redact.stories.tsx +175 -0
- package/dist/stories/examples.ts +31 -0
- package/dist/theme.d.ts +3 -0
- package/dist/useAgUi/index.d.ts +4 -0
- package/dist/useAgUi/types.d.ts +157 -0
- package/dist/useAgUi/useAgUi.d.ts +119 -0
- package/dist/useAgUi/useAgUi.spec.d.ts +1 -0
- package/dist/utils/getChildText.d.ts +10 -0
- package/dist/utils/getChildText.spec.d.ts +1 -0
- package/package.json +6 -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-CBHNcMyR.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
|
@@ -2,7 +2,7 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { useState, useRef, useEffect } from "react";
|
|
4
4
|
import { AnimatePresence, motion } from "motion/react";
|
|
5
|
-
import { a as SvgCopy } from "./index-
|
|
5
|
+
import { a as SvgCopy } from "./index-8tlsyFe-.js";
|
|
6
6
|
import { IconButton } from "reablocks";
|
|
7
7
|
const sanitizeSVGCell = (cell) => {
|
|
8
8
|
const trimmed = cell.trim();
|
|
@@ -138,4 +138,4 @@ const CSVFileRenderer = ({ name, url, fileIcon }) => {
|
|
|
138
138
|
export {
|
|
139
139
|
CSVFileRenderer as default
|
|
140
140
|
};
|
|
141
|
-
//# sourceMappingURL=CSVFileRenderer-
|
|
141
|
+
//# sourceMappingURL=CSVFileRenderer-C2tuexJf.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CSVFileRenderer-DXI8PDqR.js","sources":["../src/utils/sanitize.ts","../src/utils/parseCSV.ts","../src/assets/download.svg?react","../src/SessionMessages/SessionMessage/MessageFile/renderers/CSVFileRenderer.tsx"],"sourcesContent":["\n/**\n * Sanitizes cell content to prevent CSV injection and other potential vulnerabilities.\n * Based on the documentation of OWASP for CSV Injection\n * https://owasp.org/www-community/attacks/CSV_Injection\n * @param cell The cell content to sanitize.\n * @returns The sanitized cell content.\n */\nexport const sanitizeSVGCell = (cell: string): string => {\n const trimmed = cell.trim();\n // Escape double quotes by doubling them\n const escaped = trimmed.replace(/\"/g, '\"\"');\n // Add single quote prefix only for potentially dangerous content\n const prefix = /^[=+\\-@]/.test(trimmed) ? '\\'' : '';\n // Only wrap in quotes if the content contains special characters\n const needsQuotes = /[\",\\n\\r]/.test(escaped) || prefix;\n\n return needsQuotes ? `\"${prefix}${escaped}\"` : escaped;\n};\n","import { sanitizeSVGCell } from './sanitize';\n\n/**\n * Parses a CSV string from a local file and returns an array of rows.\n * Sanitizes cell data to prevent injection attacks.\n * @param csvString The raw CSV string content to parse.\n * @returns The parsed CSV data as a 2D array of strings.\n */\nexport const parseCSV = (csvString: string): string[][] => {\n try {\n const rows = csvString.split('\\n');\n return rows.map((row) => row.split(',').map((cell) => sanitizeSVGCell(cell)));\n } catch (error) {\n console.error('Error parsing CSV:', error);\n throw new Error('Failed to parse CSV file.');\n }\n};\n","import * as React from \"react\";\nconst SvgDownload = (props) => /* @__PURE__ */ React.createElement(\"svg\", { xmlns: \"http://www.w3.org/2000/svg\", width: 24, height: 24, viewBox: \"0 0 24 24\", fill: \"none\", stroke: \"currentColor\", strokeWidth: 1, strokeLinecap: \"round\", strokeLinejoin: \"round\", className: \"lucide lucide-cloud-download\", ...props }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242\" }), /* @__PURE__ */ React.createElement(\"path\", { d: \"M12 12v9\" }), /* @__PURE__ */ React.createElement(\"path\", { d: \"m8 17 4 4 4-4\" }));\nexport default SvgDownload;\n","import { FC, useEffect, useState, ReactElement, useRef } from 'react';\nimport { motion, AnimatePresence } from 'motion/react';\nimport { parseCSV } from '@/utils/parseCSV';\nimport DownloadIcon from '@/assets/download.svg?react';\nimport PlaceholderIcon from '@/assets/copy.svg?react';\nimport { IconButton } from 'reablocks';\n\ninterface CSVFileRendererProps {\n /**\n * Name of the file.\n */\n name?: string;\n\n /**\n * URL of the file.\n */\n url: string;\n\n /**\n * Icon to for file type.\n */\n fileIcon?: ReactElement;\n}\n\n/**\n * Renderer for CSV files that fetches and displays a snippet of the file data.\n */\nconst CSVFileRenderer: FC<CSVFileRendererProps> = ({ name, url, fileIcon }) => {\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [csvData, setCsvData] = useState<string[][]>([]);\n const [error, setError] = useState<string | null>(null);\n const [isModalOpen, setIsModalOpen] = useState(false);\n const modalRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const fetchCsvData = async () => {\n try {\n setIsLoading(true);\n const response = await fetch(url);\n const data = parseCSV(await response.text());\n setCsvData(data);\n } catch {\n setError('Failed to load CSV file.');\n } finally {\n setIsLoading(false);\n }\n };\n\n fetchCsvData();\n }, [url]);\n\n const toggleModal = () => {\n setIsModalOpen(prev => !prev);\n };\n\n const handleClickOutside = (event: MouseEvent) => {\n if (modalRef.current && !modalRef.current.contains(event.target as Node)) {\n setIsModalOpen(false);\n }\n };\n\n useEffect(() => {\n if (isModalOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n } else {\n document.removeEventListener('mousedown', handleClickOutside);\n }\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isModalOpen]);\n\n const downloadCSV = () => {\n if (csvData.length === 0) return;\n\n const csvContent = csvData.map(row => row.join(',')).join('\\n');\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.setAttribute('download', `${name || 'data'}`);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n };\n\n const renderTable = (data: string[][], maxRows?: number) => (\n <motion.table\n layout\n className=\"w-full\"\n transition={{ type: 'spring', stiffness: 100, damping: 20 }}\n >\n <thead className=\"sticky top-0 bg-gray-200 dark:bg-gray-800 z-10\">\n <tr>\n <th className=\"py-4 px-6\">#</th>\n {data[0].map((header, index) => (\n <th key={`header-${index}`} className=\"py-4 px-6\">\n {header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.slice(1, maxRows).map((row, rowIndex) => (\n <tr\n key={`row-${rowIndex}`}\n className=\"border-b border-panel-accent light:border-gray-700 hover:bg-panel-accent hover:light:bg-gray-700/40 transition-colors text-base\"\n >\n <td className=\"py-4 px-6\">{rowIndex + 1}</td>\n {row.map((cell, cellIndex) => (\n <td key={`cell-${rowIndex}-${cellIndex}`} className=\"py-4 px-6\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </motion.table>\n );\n\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex justify-between items-center gap-4\">\n <div className=\"csv-icon flex items-center\">\n {fileIcon}\n {name && <figcaption className=\"ml-1\">{name}</figcaption>}\n </div>\n <div className=\"csv-icon flex items-center gap-6\">\n <IconButton size=\"small\" variant=\"text\" onClick={downloadCSV}>\n <DownloadIcon />\n </IconButton>\n <IconButton size=\"small\" variant=\"text\" onClick={toggleModal}>\n <PlaceholderIcon />\n </IconButton>\n </div>\n </div>\n\n {error && <div className=\"error-message\">{error}</div>}\n\n {isLoading && !csvData && (\n <div className=\"text-text-secondary\">Loading...</div>\n )}\n\n <div className=\"flex justify-between\">\n {!error && csvData.length > 0 && renderTable(csvData, 6)}\n </div>\n\n <AnimatePresence>\n {isModalOpen && (\n <motion.div\n className=\"fixed inset-0 bg-black/70 flex justify-center items-center z-50\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.3 }}\n >\n <motion.div\n ref={modalRef}\n className=\"bg-white dark:bg-gray-900 rounded-md w-11/12 h-5/6 overflow-auto\"\n initial={{ scale: 0.8 }}\n animate={{ scale: 1 }}\n exit={{ scale: 0.8 }}\n transition={{ duration: 0.3 }}\n >\n {!error && csvData.length > 0 && renderTable(csvData)}\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n};\n\nexport default CSVFileRenderer;\n"],"names":["url","DownloadIcon","PlaceholderIcon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CSVFileRenderer-C2tuexJf.js","sources":["../src/utils/sanitize.ts","../src/utils/parseCSV.ts","../src/assets/download.svg?react","../src/SessionMessages/SessionMessage/MessageFile/renderers/CSVFileRenderer.tsx"],"sourcesContent":["\n/**\n * Sanitizes cell content to prevent CSV injection and other potential vulnerabilities.\n * Based on the documentation of OWASP for CSV Injection\n * https://owasp.org/www-community/attacks/CSV_Injection\n * @param cell The cell content to sanitize.\n * @returns The sanitized cell content.\n */\nexport const sanitizeSVGCell = (cell: string): string => {\n const trimmed = cell.trim();\n // Escape double quotes by doubling them\n const escaped = trimmed.replace(/\"/g, '\"\"');\n // Add single quote prefix only for potentially dangerous content\n const prefix = /^[=+\\-@]/.test(trimmed) ? '\\'' : '';\n // Only wrap in quotes if the content contains special characters\n const needsQuotes = /[\",\\n\\r]/.test(escaped) || prefix;\n\n return needsQuotes ? `\"${prefix}${escaped}\"` : escaped;\n};\n","import { sanitizeSVGCell } from './sanitize';\n\n/**\n * Parses a CSV string from a local file and returns an array of rows.\n * Sanitizes cell data to prevent injection attacks.\n * @param csvString The raw CSV string content to parse.\n * @returns The parsed CSV data as a 2D array of strings.\n */\nexport const parseCSV = (csvString: string): string[][] => {\n try {\n const rows = csvString.split('\\n');\n return rows.map((row) => row.split(',').map((cell) => sanitizeSVGCell(cell)));\n } catch (error) {\n console.error('Error parsing CSV:', error);\n throw new Error('Failed to parse CSV file.');\n }\n};\n","import * as React from \"react\";\nconst SvgDownload = (props) => /* @__PURE__ */ React.createElement(\"svg\", { xmlns: \"http://www.w3.org/2000/svg\", width: 24, height: 24, viewBox: \"0 0 24 24\", fill: \"none\", stroke: \"currentColor\", strokeWidth: 1, strokeLinecap: \"round\", strokeLinejoin: \"round\", className: \"lucide lucide-cloud-download\", ...props }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242\" }), /* @__PURE__ */ React.createElement(\"path\", { d: \"M12 12v9\" }), /* @__PURE__ */ React.createElement(\"path\", { d: \"m8 17 4 4 4-4\" }));\nexport default SvgDownload;\n","import { FC, useEffect, useState, ReactElement, useRef } from 'react';\nimport { motion, AnimatePresence } from 'motion/react';\nimport { parseCSV } from '@/utils/parseCSV';\nimport DownloadIcon from '@/assets/download.svg?react';\nimport PlaceholderIcon from '@/assets/copy.svg?react';\nimport { IconButton } from 'reablocks';\n\ninterface CSVFileRendererProps {\n /**\n * Name of the file.\n */\n name?: string;\n\n /**\n * URL of the file.\n */\n url: string;\n\n /**\n * Icon to for file type.\n */\n fileIcon?: ReactElement;\n}\n\n/**\n * Renderer for CSV files that fetches and displays a snippet of the file data.\n */\nconst CSVFileRenderer: FC<CSVFileRendererProps> = ({ name, url, fileIcon }) => {\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [csvData, setCsvData] = useState<string[][]>([]);\n const [error, setError] = useState<string | null>(null);\n const [isModalOpen, setIsModalOpen] = useState(false);\n const modalRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const fetchCsvData = async () => {\n try {\n setIsLoading(true);\n const response = await fetch(url);\n const data = parseCSV(await response.text());\n setCsvData(data);\n } catch {\n setError('Failed to load CSV file.');\n } finally {\n setIsLoading(false);\n }\n };\n\n fetchCsvData();\n }, [url]);\n\n const toggleModal = () => {\n setIsModalOpen(prev => !prev);\n };\n\n const handleClickOutside = (event: MouseEvent) => {\n if (modalRef.current && !modalRef.current.contains(event.target as Node)) {\n setIsModalOpen(false);\n }\n };\n\n useEffect(() => {\n if (isModalOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n } else {\n document.removeEventListener('mousedown', handleClickOutside);\n }\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isModalOpen]);\n\n const downloadCSV = () => {\n if (csvData.length === 0) return;\n\n const csvContent = csvData.map(row => row.join(',')).join('\\n');\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.setAttribute('download', `${name || 'data'}`);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n };\n\n const renderTable = (data: string[][], maxRows?: number) => (\n <motion.table\n layout\n className=\"w-full\"\n transition={{ type: 'spring', stiffness: 100, damping: 20 }}\n >\n <thead className=\"sticky top-0 bg-gray-200 dark:bg-gray-800 z-10\">\n <tr>\n <th className=\"py-4 px-6\">#</th>\n {data[0].map((header, index) => (\n <th key={`header-${index}`} className=\"py-4 px-6\">\n {header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.slice(1, maxRows).map((row, rowIndex) => (\n <tr\n key={`row-${rowIndex}`}\n className=\"border-b border-panel-accent light:border-gray-700 hover:bg-panel-accent hover:light:bg-gray-700/40 transition-colors text-base\"\n >\n <td className=\"py-4 px-6\">{rowIndex + 1}</td>\n {row.map((cell, cellIndex) => (\n <td key={`cell-${rowIndex}-${cellIndex}`} className=\"py-4 px-6\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </motion.table>\n );\n\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex justify-between items-center gap-4\">\n <div className=\"csv-icon flex items-center\">\n {fileIcon}\n {name && <figcaption className=\"ml-1\">{name}</figcaption>}\n </div>\n <div className=\"csv-icon flex items-center gap-6\">\n <IconButton size=\"small\" variant=\"text\" onClick={downloadCSV}>\n <DownloadIcon />\n </IconButton>\n <IconButton size=\"small\" variant=\"text\" onClick={toggleModal}>\n <PlaceholderIcon />\n </IconButton>\n </div>\n </div>\n\n {error && <div className=\"error-message\">{error}</div>}\n\n {isLoading && !csvData && (\n <div className=\"text-text-secondary\">Loading...</div>\n )}\n\n <div className=\"flex justify-between\">\n {!error && csvData.length > 0 && renderTable(csvData, 6)}\n </div>\n\n <AnimatePresence>\n {isModalOpen && (\n <motion.div\n className=\"fixed inset-0 bg-black/70 flex justify-center items-center z-50\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.3 }}\n >\n <motion.div\n ref={modalRef}\n className=\"bg-white dark:bg-gray-900 rounded-md w-11/12 h-5/6 overflow-auto\"\n initial={{ scale: 0.8 }}\n animate={{ scale: 1 }}\n exit={{ scale: 0.8 }}\n transition={{ duration: 0.3 }}\n >\n {!error && csvData.length > 0 && renderTable(csvData)}\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n};\n\nexport default CSVFileRenderer;\n"],"names":["url","DownloadIcon","PlaceholderIcon"],"mappings":"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"}
|
package/dist/Chat.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Session } from './types';
|
|
|
4
4
|
import { ChatTheme } from './theme';
|
|
5
5
|
import { ChatViewType } from './ChatContext';
|
|
6
6
|
import { Plugin } from 'unified';
|
|
7
|
+
import { ComponentCatalog } from './ComponentCatalog/types';
|
|
7
8
|
export interface ChatProps extends PropsWithChildren {
|
|
8
9
|
/**
|
|
9
10
|
* The style to apply to the root element.
|
|
@@ -42,6 +43,17 @@ export interface ChatProps extends PropsWithChildren {
|
|
|
42
43
|
* Use this to add support for custom elements like charts.
|
|
43
44
|
*/
|
|
44
45
|
markdownComponents?: Components;
|
|
46
|
+
/**
|
|
47
|
+
* A component catalog created via `componentCatalog()`.
|
|
48
|
+
* Enables dynamic component rendering from LLM responses using
|
|
49
|
+
* fenced code blocks (e.g. ```component).
|
|
50
|
+
*
|
|
51
|
+
* This automatically wires in the necessary remark plugin and
|
|
52
|
+
* markdown component overrides. For advanced control, use the
|
|
53
|
+
* catalog's `remarkPlugin` and `components` properties directly
|
|
54
|
+
* via the `remarkPlugins` and `markdownComponents` props instead.
|
|
55
|
+
*/
|
|
56
|
+
components?: ComponentCatalog;
|
|
45
57
|
/**
|
|
46
58
|
* Whether to display a loading state.
|
|
47
59
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
|
-
export interface
|
|
2
|
+
export interface ComponentErrorProps {
|
|
3
3
|
/**
|
|
4
4
|
* The visual style variant of the error display.
|
|
5
5
|
* Defaults to 'error'.
|
|
@@ -18,4 +18,4 @@ export interface ChartErrorProps {
|
|
|
18
18
|
*/
|
|
19
19
|
code?: string;
|
|
20
20
|
}
|
|
21
|
-
export declare const
|
|
21
|
+
export declare const ComponentError: FC<ComponentErrorProps>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { default as React, FC } from 'react';
|
|
2
|
+
import { ComponentDefinitions, ComponentCatalogOptions } from './types';
|
|
3
|
+
export interface ComponentPreProps {
|
|
4
|
+
children?: React.ReactNode;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Creates a `pre` component override for react-markdown that intercepts
|
|
9
|
+
* fenced code blocks with the configured language tag and renders them
|
|
10
|
+
* via the ComponentRenderer.
|
|
11
|
+
*
|
|
12
|
+
* Checks for a `language-{tag}` className on the nested `<code>` element
|
|
13
|
+
* and, if matched, extracts the text content and hands it off to the
|
|
14
|
+
* renderer.
|
|
15
|
+
*
|
|
16
|
+
* Any non-matching `<pre>` blocks are passed through as-is.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createComponentPre(definitions: ComponentDefinitions, options?: ComponentCatalogOptions): FC<ComponentPreProps>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { ComponentDefinitions, ComponentCatalogOptions } from './types';
|
|
3
|
+
export interface ComponentRendererProps {
|
|
4
|
+
/**
|
|
5
|
+
* The raw JSON string from the ```component code block.
|
|
6
|
+
*/
|
|
7
|
+
raw: string;
|
|
8
|
+
/**
|
|
9
|
+
* The component definitions from the catalog.
|
|
10
|
+
*/
|
|
11
|
+
definitions: ComponentDefinitions;
|
|
12
|
+
/**
|
|
13
|
+
* Optional catalog options (for onError callback).
|
|
14
|
+
*/
|
|
15
|
+
options?: ComponentCatalogOptions;
|
|
16
|
+
}
|
|
17
|
+
export declare const ComponentRenderer: FC<ComponentRendererProps>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ComponentDefinition } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Wraps `ChartRenderer` as a component definition so charts can
|
|
4
|
+
* be registered in a `componentCatalog()`.
|
|
5
|
+
*
|
|
6
|
+
* The adapter renders a `ChartRenderer` internally using the same
|
|
7
|
+
* config-based API, with reaviz as the underlying chart library.
|
|
8
|
+
*
|
|
9
|
+
* Because reaviz is an optional peer dependency, this adapter is
|
|
10
|
+
* fully tree-shakeable — it only loads reaviz code when imported.
|
|
11
|
+
*
|
|
12
|
+
* Both `zod` and `reaviz` are required when this helper is used.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* import { componentCatalog, createChartComponentDef } from 'reachat';
|
|
17
|
+
*
|
|
18
|
+
* const catalog = componentCatalog({
|
|
19
|
+
* Chart: createChartComponentDef(),
|
|
20
|
+
* // ... other components
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* The LLM can then output:
|
|
25
|
+
* ```component
|
|
26
|
+
* {
|
|
27
|
+
* "type": "Chart",
|
|
28
|
+
* "props": {
|
|
29
|
+
* "type": "bar",
|
|
30
|
+
* "data": [{ "key": "A", "data": 10 }, { "key": "B", "data": 20 }],
|
|
31
|
+
* "title": "My Chart"
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function createChartComponentDef(): ComponentDefinition;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ComponentCatalog, ComponentCatalogOptions, ComponentDefinitions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a component catalog — the main entry point for the
|
|
4
|
+
* dynamic component system.
|
|
5
|
+
*
|
|
6
|
+
* Returns an object with a remark plugin, markdown component overrides,
|
|
7
|
+
* and a system-prompt generator, ready to plug into `<Chat>`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { componentCatalog } from 'reachat';
|
|
12
|
+
* import { z } from 'zod';
|
|
13
|
+
*
|
|
14
|
+
* const catalog = componentCatalog({
|
|
15
|
+
* WeatherCard: {
|
|
16
|
+
* description: 'Displays weather for a city',
|
|
17
|
+
* props: z.object({
|
|
18
|
+
* city: z.string(),
|
|
19
|
+
* temperature: z.number()
|
|
20
|
+
* }),
|
|
21
|
+
* component: ({ city, temperature }) => (
|
|
22
|
+
* <div>{city}: {temperature}°F</div>
|
|
23
|
+
* )
|
|
24
|
+
* }
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* // Simple — pass the whole catalog:
|
|
28
|
+
* <Chat components={catalog} sessions={sessions}>
|
|
29
|
+
* ...
|
|
30
|
+
* </Chat>
|
|
31
|
+
*
|
|
32
|
+
* // Advanced — use individual pieces:
|
|
33
|
+
* <Chat
|
|
34
|
+
* remarkPlugins={[catalog.remarkPlugin]}
|
|
35
|
+
* markdownComponents={catalog.components}
|
|
36
|
+
* >
|
|
37
|
+
* ...
|
|
38
|
+
* </Chat>
|
|
39
|
+
*
|
|
40
|
+
* // Generate LLM instructions:
|
|
41
|
+
* const prompt = catalog.systemPrompt();
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function componentCatalog(definitions: ComponentDefinitions, options?: ComponentCatalogOptions): ComponentCatalog;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ComponentDefinitions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Generates an LLM-friendly system prompt describing all available
|
|
4
|
+
* components, their descriptions, and their prop schemas.
|
|
5
|
+
*
|
|
6
|
+
* @param definitions The component definitions from the catalog.
|
|
7
|
+
* @param language The code block language tag (default: 'component').
|
|
8
|
+
*/
|
|
9
|
+
export declare function generatePrompt(definitions: ComponentDefinitions, language?: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { componentCatalog } from './componentCatalog';
|
|
2
|
+
export { ComponentRenderer } from './ComponentRenderer';
|
|
3
|
+
export { ComponentError } from './ComponentError';
|
|
4
|
+
export type { ComponentErrorProps } from './ComponentError';
|
|
5
|
+
export { createComponentPre } from './ComponentPre';
|
|
6
|
+
export { createChartComponentDef } from './chartComponentDef';
|
|
7
|
+
export { validateSpec } from './validateSpec';
|
|
8
|
+
export { generatePrompt } from './generatePrompt';
|
|
9
|
+
export type { ComponentCatalog, ComponentCatalogError, ComponentCatalogOptions, ComponentDefinition, ComponentDefinitions, ComponentSpec } from './types';
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
import { Components } from 'react-markdown';
|
|
3
|
+
import { Plugin } from 'unified';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
/**
|
|
6
|
+
* Definition for a single component in the catalog.
|
|
7
|
+
*/
|
|
8
|
+
export interface ComponentDefinition<TProps extends Record<string, any> = Record<string, any>> {
|
|
9
|
+
/**
|
|
10
|
+
* Human-readable description of what this component renders.
|
|
11
|
+
* Included in the generated LLM system prompt.
|
|
12
|
+
*/
|
|
13
|
+
description: string;
|
|
14
|
+
/**
|
|
15
|
+
* Zod schema that validates the props the LLM provides.
|
|
16
|
+
* Used for runtime validation and system-prompt generation.
|
|
17
|
+
*/
|
|
18
|
+
props: z.ZodType<TProps>;
|
|
19
|
+
/**
|
|
20
|
+
* The React component to render. Receives validated props and optional
|
|
21
|
+
* children (for nested component specs) plus a `sendMessage` callback
|
|
22
|
+
* from ChatContext.
|
|
23
|
+
*/
|
|
24
|
+
component: FC<TProps & {
|
|
25
|
+
children?: ReactNode;
|
|
26
|
+
sendMessage?: (message: string) => void;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Map of component name → definition. This is what the user passes
|
|
31
|
+
* to `componentCatalog()`.
|
|
32
|
+
*/
|
|
33
|
+
export type ComponentDefinitions = Record<string, ComponentDefinition>;
|
|
34
|
+
/**
|
|
35
|
+
* The JSON spec format that the LLM emits inside ```component blocks.
|
|
36
|
+
*
|
|
37
|
+
* Single component:
|
|
38
|
+
* { "type": "WeatherCard", "props": { "city": "SF" } }
|
|
39
|
+
*
|
|
40
|
+
* With nested children:
|
|
41
|
+
* { "type": "Row", "props": {}, "children": [ ... ] }
|
|
42
|
+
*
|
|
43
|
+
* Multiple components (array):
|
|
44
|
+
* [ { "type": "A", "props": {} }, { "type": "B", "props": {} } ]
|
|
45
|
+
*/
|
|
46
|
+
export interface ComponentSpec {
|
|
47
|
+
/** Component name — must match a key in the catalog. */
|
|
48
|
+
type: string;
|
|
49
|
+
/** Props passed to the component after Zod validation. */
|
|
50
|
+
props: Record<string, any>;
|
|
51
|
+
/** Optional nested component specs. */
|
|
52
|
+
children?: ComponentSpec[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Options for `componentCatalog()`.
|
|
56
|
+
*/
|
|
57
|
+
export interface ComponentCatalogOptions {
|
|
58
|
+
/**
|
|
59
|
+
* The fenced-code-block language tag to detect.
|
|
60
|
+
* @default 'component'
|
|
61
|
+
*/
|
|
62
|
+
language?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Called when a component spec fails validation.
|
|
65
|
+
* Return a ReactNode to render, or `undefined` to use the default error UI.
|
|
66
|
+
*/
|
|
67
|
+
onError?: (error: ComponentCatalogError) => ReactNode | undefined;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Error details passed to the `onError` callback.
|
|
71
|
+
*/
|
|
72
|
+
export interface ComponentCatalogError {
|
|
73
|
+
/** What went wrong. */
|
|
74
|
+
type: 'invalid_json' | 'unknown_component' | 'invalid_props' | 'render_error';
|
|
75
|
+
/** Human-readable message. */
|
|
76
|
+
message: string;
|
|
77
|
+
/** The raw code block content. */
|
|
78
|
+
raw: string;
|
|
79
|
+
/** The component type from the spec, if parsed. */
|
|
80
|
+
componentType?: string;
|
|
81
|
+
/** Zod validation issues, if applicable. */
|
|
82
|
+
issues?: {
|
|
83
|
+
message: string;
|
|
84
|
+
path: (string | number)[];
|
|
85
|
+
}[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The object returned by `componentCatalog()`.
|
|
89
|
+
*/
|
|
90
|
+
export interface ComponentCatalog {
|
|
91
|
+
/**
|
|
92
|
+
* Remark plugin that preprocesses ```component code blocks.
|
|
93
|
+
*/
|
|
94
|
+
remarkPlugin: Plugin;
|
|
95
|
+
/**
|
|
96
|
+
* Markdown component overrides (`{ pre: ComponentPre }`).
|
|
97
|
+
* Spread into `markdownComponents` or pass to `Chat`.
|
|
98
|
+
*/
|
|
99
|
+
components: Components;
|
|
100
|
+
/**
|
|
101
|
+
* Generates an LLM system prompt describing available components.
|
|
102
|
+
*/
|
|
103
|
+
systemPrompt: () => string;
|
|
104
|
+
/**
|
|
105
|
+
* The underlying definitions, for advanced use.
|
|
106
|
+
*/
|
|
107
|
+
definitions: ComponentDefinitions;
|
|
108
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ComponentSpec, ComponentDefinitions, ComponentCatalogError } from './types';
|
|
2
|
+
export type ValidateResult = {
|
|
3
|
+
ok: true;
|
|
4
|
+
specs: ComponentSpec[];
|
|
5
|
+
error?: undefined;
|
|
6
|
+
} | {
|
|
7
|
+
ok: false;
|
|
8
|
+
error: ComponentCatalogError;
|
|
9
|
+
specs?: undefined;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Attempts to parse a raw string (from a ```component code block)
|
|
13
|
+
* into one or more ComponentSpec objects.
|
|
14
|
+
*
|
|
15
|
+
* Returns either a validated spec array or an error descriptor.
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateSpec(raw: string, definitions: ComponentDefinitions): ValidateResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import { S as SvgFile } from "./index-
|
|
3
|
-
import {
|
|
2
|
+
import { S as SvgFile } from "./index-8tlsyFe-.js";
|
|
3
|
+
import { Ellipsis, cn } from "reablocks";
|
|
4
4
|
const DefaultFileRenderer = ({
|
|
5
5
|
name,
|
|
6
6
|
limit = 100,
|
|
@@ -12,4 +12,4 @@ const DefaultFileRenderer = ({
|
|
|
12
12
|
export {
|
|
13
13
|
DefaultFileRenderer as default
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=DefaultFileRenderer-
|
|
15
|
+
//# sourceMappingURL=DefaultFileRenderer-CJ3jwiQa.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultFileRenderer-
|
|
1
|
+
{"version":3,"file":"DefaultFileRenderer-CJ3jwiQa.js","sources":["../src/SessionMessages/SessionMessage/MessageFile/renderers/DefaultFileRenderer.tsx"],"sourcesContent":["import { FC, ReactElement } from 'react';\nimport FileIcon from '@/assets/file.svg?react';\nimport { Ellipsis, cn } from 'reablocks';\n\ninterface DefaultFileRendererProps {\n /**\n * Limit for the name.\n */\n limit?: number;\n\n /**\n * Name of the file.\n */\n name?: string;\n\n /**\n * URL of the file.\n */\n url: string;\n\n /**\n * Icon to for file type.\n */\n fileIcon?: ReactElement;\n}\n\n/**\n * Default renderer for unspecified file types.\n */\nconst DefaultFileRenderer: FC<DefaultFileRendererProps> = ({\n name,\n limit = 100,\n fileIcon = <FileIcon />,\n}) => (\n <figure className=\"flex items-center gap-2\">\n {fileIcon}\n {name && (\n <figcaption className={cn('file-name-class')}>\n <Ellipsis value={name} limit={limit} />\n </figcaption>\n )}\n </figure>\n);\n\nexport default DefaultFileRenderer;\n"],"names":["FileIcon"],"mappings":";;;AA6BA,MAAM,sBAAoD,CAAC;AAAA,EACzD;AAAA,EACA,QAAQ;AAAA,EACR,+BAAYA,SAAA,CAAA,CAAS;AACvB,MACE,qBAAC,UAAA,EAAO,WAAU,2BACf,UAAA;AAAA,EAAA;AAAA,EACA,QACC,oBAAC,cAAA,EAAW,WAAW,GAAG,iBAAiB,GACzC,UAAA,oBAAC,UAAA,EAAS,OAAO,MAAM,MAAA,CAAc,EAAA,CACvC;AAAA,EAAA,CAEJ;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ComponentError, type ComponentErrorProps } from '../../ComponentCatalog/ComponentError';
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
+
export * from './types';
|
|
1
2
|
export * from './ChartRenderer';
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './ChartError';
|
|
4
|
-
export * from './chartHelpers';
|
|
5
|
-
export declare const chartComponents: {
|
|
6
|
-
pre: import('react').FC<import('./ChartPre').ChartPreProps>;
|
|
7
|
-
};
|
|
3
|
+
export * from './ComponentError';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported chart types.
|
|
3
|
+
*/
|
|
4
|
+
export type ChartType = 'bar' | 'line' | 'area' | 'pie' | 'radialBar' | 'radialArea' | 'sparkline';
|
|
5
|
+
/**
|
|
6
|
+
* Data point structure for charts.
|
|
7
|
+
*/
|
|
8
|
+
export interface ChartDataPoint {
|
|
9
|
+
key: string;
|
|
10
|
+
data: number | ChartDataPoint[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for chart rendering.
|
|
14
|
+
*/
|
|
15
|
+
export interface ChartConfig {
|
|
16
|
+
type: ChartType;
|
|
17
|
+
data: ChartDataPoint[];
|
|
18
|
+
width?: number;
|
|
19
|
+
height?: number;
|
|
20
|
+
title?: string;
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RedactMatcher } from './remarkRedact';
|
|
2
|
+
/**
|
|
3
|
+
* Matcher for Social Security Numbers (SSN).
|
|
4
|
+
* Matches patterns like: 123-45-6789
|
|
5
|
+
*/
|
|
6
|
+
export declare const ssnMatcher: RedactMatcher;
|
|
7
|
+
/**
|
|
8
|
+
* Matcher for Credit Card numbers.
|
|
9
|
+
* Matches patterns like: 1234-5678-9012-3456 or 1234 5678 9012 3456
|
|
10
|
+
* Supports common formats with spaces, dashes, or no separators.
|
|
11
|
+
*/
|
|
12
|
+
export declare const creditCardMatcher: RedactMatcher;
|
|
13
|
+
/**
|
|
14
|
+
* Matcher for Bitcoin addresses.
|
|
15
|
+
* Matches Bitcoin addresses (starts with 1 or 3, 26-35 alphanumeric characters).
|
|
16
|
+
*/
|
|
17
|
+
export declare const bitcoinMatcher: RedactMatcher;
|
|
18
|
+
/**
|
|
19
|
+
* Common redaction matchers for sensitive data.
|
|
20
|
+
*/
|
|
21
|
+
export declare const commonRedactMatchers: RedactMatcher[];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Plugin } from 'unified';
|
|
2
|
+
import { Root } from 'mdast';
|
|
3
|
+
/**
|
|
4
|
+
* Options for the remarkComponent plugin.
|
|
5
|
+
*/
|
|
6
|
+
export interface RemarkComponentOptions {
|
|
7
|
+
/**
|
|
8
|
+
* The fenced-code-block language tag to detect.
|
|
9
|
+
* @default 'component'
|
|
10
|
+
*/
|
|
11
|
+
language?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A remark plugin that acts as a pass-through for fenced code blocks with
|
|
15
|
+
* the configured language tag (default: `component`).
|
|
16
|
+
*
|
|
17
|
+
* The actual rendering is handled entirely by `ComponentPre` which
|
|
18
|
+
* intercepts `<pre>` elements with a matching `language-{tag}` class.
|
|
19
|
+
* This plugin exists as an integration point so the catalog can expose
|
|
20
|
+
* a standard `remarkPlugin` property; it does not transform the AST.
|
|
21
|
+
*
|
|
22
|
+
* Usage in markdown:
|
|
23
|
+
* ```component
|
|
24
|
+
* { "type": "WeatherCard", "props": { "city": "SF", "temperature": 72 } }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare const remarkComponent: Plugin<[RemarkComponentOptions?], Root>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Plugin } from 'unified';
|
|
2
|
+
import { Root } from 'mdast';
|
|
3
|
+
/**
|
|
4
|
+
* Interface for defining a redaction matcher.
|
|
5
|
+
*/
|
|
6
|
+
export interface RedactMatcher {
|
|
7
|
+
/**
|
|
8
|
+
* Name of the matcher (e.g., "SSN", "Credit Card", "Bitcoin").
|
|
9
|
+
*/
|
|
10
|
+
name: string;
|
|
11
|
+
/**
|
|
12
|
+
* Regular expression pattern to match sensitive data.
|
|
13
|
+
*/
|
|
14
|
+
pattern: RegExp;
|
|
15
|
+
/**
|
|
16
|
+
* Optional validation function that receives the matched value.
|
|
17
|
+
* Return true to redact, false to skip.
|
|
18
|
+
*/
|
|
19
|
+
validate?: (match: string) => boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Creates a remark plugin that redacts sensitive data based on provided matchers.
|
|
23
|
+
* The plugin replaces matched text with HTML elements that can be rendered
|
|
24
|
+
* using the Redact component from reablocks.
|
|
25
|
+
*
|
|
26
|
+
* @param matchers - Array of RedactMatcher objects that define what to redact
|
|
27
|
+
* @returns A remark plugin function
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const matchers = [
|
|
32
|
+
* { name: 'SSN', pattern: /\b\d{3}-\d{2}-\d{4}\b/g }
|
|
33
|
+
* ];
|
|
34
|
+
* remarkPlugins={[remarkRedact(matchers)]}
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function remarkRedact(matchers: RedactMatcher[]): Plugin<[], Root>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PropsWithChildren, ReactElement } from 'react';
|
|
2
2
|
export interface MessageActionsProps extends PropsWithChildren {
|
|
3
3
|
/**
|
|
4
4
|
* Question to be copied
|
|
@@ -41,4 +41,4 @@ export interface MessageActionsProps extends PropsWithChildren {
|
|
|
41
41
|
*/
|
|
42
42
|
onRefresh?: () => void;
|
|
43
43
|
}
|
|
44
|
-
export declare const MessageActions:
|
|
44
|
+
export declare const MessageActions: import('react').NamedExoticComponent<MessageActionsProps>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ConversationFile } from '../../types';
|
|
2
|
-
import {
|
|
2
|
+
import { PropsWithChildren } from 'react';
|
|
3
3
|
interface MessageFilesProps extends PropsWithChildren {
|
|
4
4
|
/**
|
|
5
5
|
* Files to render.
|
|
6
6
|
*/
|
|
7
7
|
files: ConversationFile[];
|
|
8
8
|
}
|
|
9
|
-
export declare const MessageFiles:
|
|
9
|
+
export declare const MessageFiles: import('react').NamedExoticComponent<MessageFilesProps>;
|
|
10
10
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
2
|
import { ConversationFile } from '../../types';
|
|
3
3
|
export interface MessageQuestionProps extends PropsWithChildren {
|
|
4
4
|
/**
|
|
@@ -10,4 +10,4 @@ export interface MessageQuestionProps extends PropsWithChildren {
|
|
|
10
10
|
*/
|
|
11
11
|
files?: ConversationFile[];
|
|
12
12
|
}
|
|
13
|
-
export declare const MessageQuestion:
|
|
13
|
+
export declare const MessageQuestion: import('react').NamedExoticComponent<MessageQuestionProps>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
2
|
export interface MessageResponseProps extends PropsWithChildren {
|
|
3
3
|
/**
|
|
4
4
|
* Response to render.
|
|
@@ -9,4 +9,4 @@ export interface MessageResponseProps extends PropsWithChildren {
|
|
|
9
9
|
*/
|
|
10
10
|
isLoading?: boolean;
|
|
11
11
|
}
|
|
12
|
-
export declare const MessageResponse:
|
|
12
|
+
export declare const MessageResponse: import('react').NamedExoticComponent<MessageResponseProps>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ConversationSource } from '../../types';
|
|
2
|
-
import {
|
|
2
|
+
import { PropsWithChildren } from 'react';
|
|
3
3
|
interface MessageSourcesProps extends PropsWithChildren {
|
|
4
4
|
/**
|
|
5
5
|
* Sources to render.
|
|
6
6
|
*/
|
|
7
7
|
sources: ConversationSource[];
|
|
8
8
|
}
|
|
9
|
-
export declare const MessageSources:
|
|
9
|
+
export declare const MessageSources: import('react').NamedExoticComponent<MessageSourcesProps>;
|
|
10
10
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
2
|
import { Conversation } from '../../types';
|
|
3
3
|
interface SessionMessageProps extends PropsWithChildren {
|
|
4
4
|
/**
|
|
@@ -11,5 +11,5 @@ interface SessionMessageProps extends PropsWithChildren {
|
|
|
11
11
|
*/
|
|
12
12
|
isLast?: boolean;
|
|
13
13
|
}
|
|
14
|
-
export declare const SessionMessage:
|
|
14
|
+
export declare const SessionMessage: import('react').NamedExoticComponent<SessionMessageProps>;
|
|
15
15
|
export {};
|