@informedai/react 0.4.15 → 0.4.17
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/index.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +260 -12
- package/dist/index.mjs +261 -13
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -82,6 +82,8 @@ interface InformedAssistantConfig {
|
|
|
82
82
|
documentTypeId: string;
|
|
83
83
|
/** API base URL (defaults to https://api.informedassistant.ai/api/v1) */
|
|
84
84
|
apiUrl?: string;
|
|
85
|
+
/** Pool access key (pak_*) for authentication */
|
|
86
|
+
accessKey?: string;
|
|
85
87
|
/**
|
|
86
88
|
* External ID for idempotency - your object's ID in your system.
|
|
87
89
|
* If provided, the widget will find or create a document linked to this ID.
|
|
@@ -240,6 +242,7 @@ declare function AdminChatbot({ className, ...config }: AdminChatbotProps): reac
|
|
|
240
242
|
* WebsiteChatbot
|
|
241
243
|
* An embeddable chatbot widget for website agents.
|
|
242
244
|
* Uses domain-based authentication - no API key required.
|
|
245
|
+
* Supports rendering rich cards from AI responses.
|
|
243
246
|
*/
|
|
244
247
|
interface WebsiteChatbotTheme {
|
|
245
248
|
primaryColor?: string;
|
|
@@ -346,7 +349,8 @@ interface ApplyResponse {
|
|
|
346
349
|
}
|
|
347
350
|
declare class InformedAIClient {
|
|
348
351
|
private apiUrl;
|
|
349
|
-
|
|
352
|
+
private accessKey?;
|
|
353
|
+
constructor(apiUrl?: string, accessKey?: string);
|
|
350
354
|
private getHeaders;
|
|
351
355
|
private request;
|
|
352
356
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -82,6 +82,8 @@ interface InformedAssistantConfig {
|
|
|
82
82
|
documentTypeId: string;
|
|
83
83
|
/** API base URL (defaults to https://api.informedassistant.ai/api/v1) */
|
|
84
84
|
apiUrl?: string;
|
|
85
|
+
/** Pool access key (pak_*) for authentication */
|
|
86
|
+
accessKey?: string;
|
|
85
87
|
/**
|
|
86
88
|
* External ID for idempotency - your object's ID in your system.
|
|
87
89
|
* If provided, the widget will find or create a document linked to this ID.
|
|
@@ -240,6 +242,7 @@ declare function AdminChatbot({ className, ...config }: AdminChatbotProps): reac
|
|
|
240
242
|
* WebsiteChatbot
|
|
241
243
|
* An embeddable chatbot widget for website agents.
|
|
242
244
|
* Uses domain-based authentication - no API key required.
|
|
245
|
+
* Supports rendering rich cards from AI responses.
|
|
243
246
|
*/
|
|
244
247
|
interface WebsiteChatbotTheme {
|
|
245
248
|
primaryColor?: string;
|
|
@@ -346,7 +349,8 @@ interface ApplyResponse {
|
|
|
346
349
|
}
|
|
347
350
|
declare class InformedAIClient {
|
|
348
351
|
private apiUrl;
|
|
349
|
-
|
|
352
|
+
private accessKey?;
|
|
353
|
+
constructor(apiUrl?: string, accessKey?: string);
|
|
350
354
|
private getHeaders;
|
|
351
355
|
private request;
|
|
352
356
|
/**
|
package/dist/index.js
CHANGED
|
@@ -40,13 +40,18 @@ var import_react_dom = require("react-dom");
|
|
|
40
40
|
// src/utils/api-client.ts
|
|
41
41
|
var DEFAULT_API_URL = "https://api.informedassistant.ai/api/v1";
|
|
42
42
|
var InformedAIClient = class {
|
|
43
|
-
constructor(apiUrl) {
|
|
43
|
+
constructor(apiUrl, accessKey) {
|
|
44
44
|
this.apiUrl = apiUrl || DEFAULT_API_URL;
|
|
45
|
+
this.accessKey = accessKey;
|
|
45
46
|
}
|
|
46
47
|
getHeaders() {
|
|
47
|
-
|
|
48
|
+
const headers = {
|
|
48
49
|
"Content-Type": "application/json"
|
|
49
50
|
};
|
|
51
|
+
if (this.accessKey) {
|
|
52
|
+
headers["Authorization"] = `Bearer ${this.accessKey}`;
|
|
53
|
+
}
|
|
54
|
+
return headers;
|
|
50
55
|
}
|
|
51
56
|
async request(endpoint, options = {}) {
|
|
52
57
|
const response = await fetch(`${this.apiUrl}${endpoint}`, {
|
|
@@ -304,8 +309,8 @@ function InformedAIProvider({ config, children }) {
|
|
|
304
309
|
const shouldPersist = config.persistSession ?? true;
|
|
305
310
|
const storageKey = getStorageKey(config.documentTypeId, config.externalId);
|
|
306
311
|
(0, import_react.useEffect)(() => {
|
|
307
|
-
clientRef.current = new InformedAIClient(config.apiUrl);
|
|
308
|
-
}, [config.apiUrl]);
|
|
312
|
+
clientRef.current = new InformedAIClient(config.apiUrl, config.accessKey);
|
|
313
|
+
}, [config.apiUrl, config.accessKey]);
|
|
309
314
|
const createNewSession = (0, import_react.useCallback)(async () => {
|
|
310
315
|
if (!clientRef.current) return null;
|
|
311
316
|
const result = await clientRef.current.createSession(
|
|
@@ -1699,6 +1704,91 @@ function AdminChatbot({ className, ...config }) {
|
|
|
1699
1704
|
|
|
1700
1705
|
// src/components/WebsiteChatbot.tsx
|
|
1701
1706
|
var import_react4 = require("react");
|
|
1707
|
+
|
|
1708
|
+
// src/utils/card-parser.ts
|
|
1709
|
+
var CARD_MARKER_REGEX = /\[([A-Z][A-Z0-9_]*):([^\]]+)\]/g;
|
|
1710
|
+
function parseCardMarker(marker) {
|
|
1711
|
+
const match = marker.match(/^\[([A-Z][A-Z0-9_]*):([^\]]+)\]$/);
|
|
1712
|
+
if (!match) return null;
|
|
1713
|
+
const [, type, valuesStr] = match;
|
|
1714
|
+
const values = valuesStr.split("|").map((v) => v.trim());
|
|
1715
|
+
return {
|
|
1716
|
+
type,
|
|
1717
|
+
values,
|
|
1718
|
+
originalMarker: marker
|
|
1719
|
+
};
|
|
1720
|
+
}
|
|
1721
|
+
function parseMessageContent(content) {
|
|
1722
|
+
const segments = [];
|
|
1723
|
+
let lastIndex = 0;
|
|
1724
|
+
const matches = [...content.matchAll(CARD_MARKER_REGEX)];
|
|
1725
|
+
for (const match of matches) {
|
|
1726
|
+
const marker = match[0];
|
|
1727
|
+
const startIndex = match.index;
|
|
1728
|
+
if (startIndex > lastIndex) {
|
|
1729
|
+
const text = content.slice(lastIndex, startIndex).trim();
|
|
1730
|
+
if (text) {
|
|
1731
|
+
segments.push({ type: "text", content: text });
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
const card = parseCardMarker(marker);
|
|
1735
|
+
if (card) {
|
|
1736
|
+
segments.push({ type: "card", card });
|
|
1737
|
+
}
|
|
1738
|
+
lastIndex = startIndex + marker.length;
|
|
1739
|
+
}
|
|
1740
|
+
if (lastIndex < content.length) {
|
|
1741
|
+
const text = content.slice(lastIndex).trim();
|
|
1742
|
+
if (text) {
|
|
1743
|
+
segments.push({ type: "text", content: text });
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
if (segments.length === 0 && content.trim()) {
|
|
1747
|
+
segments.push({ type: "text", content: content.trim() });
|
|
1748
|
+
}
|
|
1749
|
+
return segments;
|
|
1750
|
+
}
|
|
1751
|
+
function isUrl(str) {
|
|
1752
|
+
return /^https?:\/\//i.test(str);
|
|
1753
|
+
}
|
|
1754
|
+
function isImageUrl(url) {
|
|
1755
|
+
if (!isUrl(url)) return false;
|
|
1756
|
+
return /\.(jpg|jpeg|png|gif|webp|svg)(\?|$)/i.test(url);
|
|
1757
|
+
}
|
|
1758
|
+
function extractCardDisplayData(card) {
|
|
1759
|
+
const values = [...card.values];
|
|
1760
|
+
const result = {
|
|
1761
|
+
title: values[0] || card.type,
|
|
1762
|
+
extraValues: []
|
|
1763
|
+
};
|
|
1764
|
+
if (values.length <= 1) return result;
|
|
1765
|
+
const imageIndex = values.findIndex((v, i) => i > 0 && isImageUrl(v));
|
|
1766
|
+
if (imageIndex > 0) {
|
|
1767
|
+
result.imageUrl = values[imageIndex];
|
|
1768
|
+
values.splice(imageIndex, 1);
|
|
1769
|
+
}
|
|
1770
|
+
const actionIndex = values.findIndex((v, i) => i > 0 && isUrl(v) && !isImageUrl(v));
|
|
1771
|
+
if (actionIndex > 0) {
|
|
1772
|
+
result.actionUrl = values[actionIndex];
|
|
1773
|
+
result.actionLabel = "View";
|
|
1774
|
+
values.splice(actionIndex, 1);
|
|
1775
|
+
}
|
|
1776
|
+
const remaining = values.slice(1);
|
|
1777
|
+
if (remaining.length > 0) {
|
|
1778
|
+
if (remaining[0].length <= 50) {
|
|
1779
|
+
result.subtitle = remaining[0];
|
|
1780
|
+
remaining.shift();
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
if (remaining.length > 0) {
|
|
1784
|
+
result.description = remaining[0];
|
|
1785
|
+
remaining.shift();
|
|
1786
|
+
}
|
|
1787
|
+
result.extraValues = remaining;
|
|
1788
|
+
return result;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
// src/components/WebsiteChatbot.tsx
|
|
1702
1792
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1703
1793
|
var defaultTheme3 = {
|
|
1704
1794
|
primaryColor: "#f59e0b",
|
|
@@ -1708,6 +1798,167 @@ var defaultTheme3 = {
|
|
|
1708
1798
|
borderRadius: "12px",
|
|
1709
1799
|
fontFamily: "system-ui, -apple-system, sans-serif"
|
|
1710
1800
|
};
|
|
1801
|
+
function ChatCard({ card, theme }) {
|
|
1802
|
+
const data = extractCardDisplayData(card);
|
|
1803
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1804
|
+
"div",
|
|
1805
|
+
{
|
|
1806
|
+
style: {
|
|
1807
|
+
border: "1px solid #e5e7eb",
|
|
1808
|
+
borderRadius: "8px",
|
|
1809
|
+
overflow: "hidden",
|
|
1810
|
+
backgroundColor: "#fff",
|
|
1811
|
+
marginTop: "8px",
|
|
1812
|
+
marginBottom: "8px"
|
|
1813
|
+
},
|
|
1814
|
+
children: [
|
|
1815
|
+
data.imageUrl && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1816
|
+
"div",
|
|
1817
|
+
{
|
|
1818
|
+
style: {
|
|
1819
|
+
width: "100%",
|
|
1820
|
+
height: "140px",
|
|
1821
|
+
backgroundColor: "#f3f4f6",
|
|
1822
|
+
overflow: "hidden"
|
|
1823
|
+
},
|
|
1824
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1825
|
+
"img",
|
|
1826
|
+
{
|
|
1827
|
+
src: data.imageUrl,
|
|
1828
|
+
alt: data.title,
|
|
1829
|
+
style: {
|
|
1830
|
+
width: "100%",
|
|
1831
|
+
height: "100%",
|
|
1832
|
+
objectFit: "cover"
|
|
1833
|
+
},
|
|
1834
|
+
onError: (e) => {
|
|
1835
|
+
e.target.style.display = "none";
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
)
|
|
1839
|
+
}
|
|
1840
|
+
),
|
|
1841
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { padding: "12px" }, children: [
|
|
1842
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1843
|
+
"div",
|
|
1844
|
+
{
|
|
1845
|
+
style: {
|
|
1846
|
+
display: "inline-block",
|
|
1847
|
+
fontSize: "10px",
|
|
1848
|
+
fontWeight: 600,
|
|
1849
|
+
textTransform: "uppercase",
|
|
1850
|
+
letterSpacing: "0.5px",
|
|
1851
|
+
color: theme.primaryColor,
|
|
1852
|
+
backgroundColor: `${theme.primaryColor}15`,
|
|
1853
|
+
padding: "2px 6px",
|
|
1854
|
+
borderRadius: "4px",
|
|
1855
|
+
marginBottom: "6px"
|
|
1856
|
+
},
|
|
1857
|
+
children: card.type
|
|
1858
|
+
}
|
|
1859
|
+
),
|
|
1860
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1861
|
+
"div",
|
|
1862
|
+
{
|
|
1863
|
+
style: {
|
|
1864
|
+
fontSize: "15px",
|
|
1865
|
+
fontWeight: 600,
|
|
1866
|
+
color: "#1f2937",
|
|
1867
|
+
marginBottom: "4px",
|
|
1868
|
+
lineHeight: "1.3"
|
|
1869
|
+
},
|
|
1870
|
+
children: data.title
|
|
1871
|
+
}
|
|
1872
|
+
),
|
|
1873
|
+
data.subtitle && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1874
|
+
"div",
|
|
1875
|
+
{
|
|
1876
|
+
style: {
|
|
1877
|
+
fontSize: "13px",
|
|
1878
|
+
color: "#6b7280",
|
|
1879
|
+
marginBottom: "6px"
|
|
1880
|
+
},
|
|
1881
|
+
children: data.subtitle
|
|
1882
|
+
}
|
|
1883
|
+
),
|
|
1884
|
+
data.description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1885
|
+
"div",
|
|
1886
|
+
{
|
|
1887
|
+
style: {
|
|
1888
|
+
fontSize: "13px",
|
|
1889
|
+
color: "#4b5563",
|
|
1890
|
+
lineHeight: "1.4",
|
|
1891
|
+
marginBottom: "8px"
|
|
1892
|
+
},
|
|
1893
|
+
children: data.description
|
|
1894
|
+
}
|
|
1895
|
+
),
|
|
1896
|
+
data.extraValues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1897
|
+
"div",
|
|
1898
|
+
{
|
|
1899
|
+
style: {
|
|
1900
|
+
fontSize: "12px",
|
|
1901
|
+
color: "#6b7280",
|
|
1902
|
+
marginBottom: "8px"
|
|
1903
|
+
},
|
|
1904
|
+
children: data.extraValues.join(" \u2022 ")
|
|
1905
|
+
}
|
|
1906
|
+
),
|
|
1907
|
+
data.actionUrl && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1908
|
+
"a",
|
|
1909
|
+
{
|
|
1910
|
+
href: data.actionUrl,
|
|
1911
|
+
target: "_blank",
|
|
1912
|
+
rel: "noopener noreferrer",
|
|
1913
|
+
style: {
|
|
1914
|
+
display: "inline-flex",
|
|
1915
|
+
alignItems: "center",
|
|
1916
|
+
gap: "4px",
|
|
1917
|
+
fontSize: "13px",
|
|
1918
|
+
fontWeight: 500,
|
|
1919
|
+
color: theme.primaryColor,
|
|
1920
|
+
textDecoration: "none",
|
|
1921
|
+
padding: "6px 12px",
|
|
1922
|
+
borderRadius: "6px",
|
|
1923
|
+
backgroundColor: `${theme.primaryColor}10`,
|
|
1924
|
+
transition: "background-color 0.2s"
|
|
1925
|
+
},
|
|
1926
|
+
onMouseEnter: (e) => {
|
|
1927
|
+
e.currentTarget.style.backgroundColor = `${theme.primaryColor}20`;
|
|
1928
|
+
},
|
|
1929
|
+
onMouseLeave: (e) => {
|
|
1930
|
+
e.currentTarget.style.backgroundColor = `${theme.primaryColor}10`;
|
|
1931
|
+
},
|
|
1932
|
+
children: [
|
|
1933
|
+
data.actionLabel || "View",
|
|
1934
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1935
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
|
|
1936
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: "15 3 21 3 21 9" }),
|
|
1937
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
|
|
1938
|
+
] })
|
|
1939
|
+
]
|
|
1940
|
+
}
|
|
1941
|
+
)
|
|
1942
|
+
] })
|
|
1943
|
+
]
|
|
1944
|
+
}
|
|
1945
|
+
);
|
|
1946
|
+
}
|
|
1947
|
+
function MessageContent({ content, theme }) {
|
|
1948
|
+
const segments = parseMessageContent(content);
|
|
1949
|
+
if (segments.length === 1 && segments[0].type === "text") {
|
|
1950
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: segments[0].content });
|
|
1951
|
+
}
|
|
1952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: segments.map((segment, index) => {
|
|
1953
|
+
if (segment.type === "text") {
|
|
1954
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { whiteSpace: "pre-wrap" }, children: segment.content }, index);
|
|
1955
|
+
}
|
|
1956
|
+
if (segment.type === "card" && segment.card) {
|
|
1957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatCard, { card: segment.card, theme }, index);
|
|
1958
|
+
}
|
|
1959
|
+
return null;
|
|
1960
|
+
}) });
|
|
1961
|
+
}
|
|
1711
1962
|
function WebsiteChatbot({ className, ...config }) {
|
|
1712
1963
|
const theme = { ...defaultTheme3, ...config.theme };
|
|
1713
1964
|
const apiUrl = config.apiUrl || "https://api.informedai.app/api/v1";
|
|
@@ -1729,13 +1980,12 @@ function WebsiteChatbot({ className, ...config }) {
|
|
|
1729
1980
|
const newMessages = [...messages, { role: "user", content: message }];
|
|
1730
1981
|
setMessages(newMessages);
|
|
1731
1982
|
try {
|
|
1732
|
-
const response = await fetch(`${apiUrl}/website-agent/message`, {
|
|
1983
|
+
const response = await fetch(`${apiUrl}/website-agent/${config.agentId}/message`, {
|
|
1733
1984
|
method: "POST",
|
|
1734
1985
|
headers: {
|
|
1735
1986
|
"Content-Type": "application/json"
|
|
1736
1987
|
},
|
|
1737
1988
|
body: JSON.stringify({
|
|
1738
|
-
agentId: config.agentId,
|
|
1739
1989
|
message,
|
|
1740
1990
|
history: messages
|
|
1741
1991
|
})
|
|
@@ -1955,10 +2205,9 @@ function WebsiteChatbot({ className, ...config }) {
|
|
|
1955
2205
|
backgroundColor: msg.role === "user" ? "var(--wc-primary)" : "#f3f4f6",
|
|
1956
2206
|
color: msg.role === "user" ? "white" : "var(--wc-text)",
|
|
1957
2207
|
fontSize: "14px",
|
|
1958
|
-
lineHeight: "1.5"
|
|
1959
|
-
whiteSpace: "pre-wrap"
|
|
2208
|
+
lineHeight: "1.5"
|
|
1960
2209
|
},
|
|
1961
|
-
children: msg.content
|
|
2210
|
+
children: msg.role === "user" ? msg.content : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageContent, { content: msg.content, theme })
|
|
1962
2211
|
}
|
|
1963
2212
|
)
|
|
1964
2213
|
},
|
|
@@ -1973,11 +2222,10 @@ function WebsiteChatbot({ className, ...config }) {
|
|
|
1973
2222
|
backgroundColor: "#f3f4f6",
|
|
1974
2223
|
color: "var(--wc-text)",
|
|
1975
2224
|
fontSize: "14px",
|
|
1976
|
-
lineHeight: "1.5"
|
|
1977
|
-
whiteSpace: "pre-wrap"
|
|
2225
|
+
lineHeight: "1.5"
|
|
1978
2226
|
},
|
|
1979
2227
|
children: [
|
|
1980
|
-
streamingContent,
|
|
2228
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageContent, { content: streamingContent, theme }),
|
|
1981
2229
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { opacity: 0.5, animation: "blink 1s infinite" }, children: "|" })
|
|
1982
2230
|
]
|
|
1983
2231
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -8,13 +8,18 @@ import { flushSync } from "react-dom";
|
|
|
8
8
|
// src/utils/api-client.ts
|
|
9
9
|
var DEFAULT_API_URL = "https://api.informedassistant.ai/api/v1";
|
|
10
10
|
var InformedAIClient = class {
|
|
11
|
-
constructor(apiUrl) {
|
|
11
|
+
constructor(apiUrl, accessKey) {
|
|
12
12
|
this.apiUrl = apiUrl || DEFAULT_API_URL;
|
|
13
|
+
this.accessKey = accessKey;
|
|
13
14
|
}
|
|
14
15
|
getHeaders() {
|
|
15
|
-
|
|
16
|
+
const headers = {
|
|
16
17
|
"Content-Type": "application/json"
|
|
17
18
|
};
|
|
19
|
+
if (this.accessKey) {
|
|
20
|
+
headers["Authorization"] = `Bearer ${this.accessKey}`;
|
|
21
|
+
}
|
|
22
|
+
return headers;
|
|
18
23
|
}
|
|
19
24
|
async request(endpoint, options = {}) {
|
|
20
25
|
const response = await fetch(`${this.apiUrl}${endpoint}`, {
|
|
@@ -272,8 +277,8 @@ function InformedAIProvider({ config, children }) {
|
|
|
272
277
|
const shouldPersist = config.persistSession ?? true;
|
|
273
278
|
const storageKey = getStorageKey(config.documentTypeId, config.externalId);
|
|
274
279
|
useEffect(() => {
|
|
275
|
-
clientRef.current = new InformedAIClient(config.apiUrl);
|
|
276
|
-
}, [config.apiUrl]);
|
|
280
|
+
clientRef.current = new InformedAIClient(config.apiUrl, config.accessKey);
|
|
281
|
+
}, [config.apiUrl, config.accessKey]);
|
|
277
282
|
const createNewSession = useCallback(async () => {
|
|
278
283
|
if (!clientRef.current) return null;
|
|
279
284
|
const result = await clientRef.current.createSession(
|
|
@@ -1667,7 +1672,92 @@ function AdminChatbot({ className, ...config }) {
|
|
|
1667
1672
|
|
|
1668
1673
|
// src/components/WebsiteChatbot.tsx
|
|
1669
1674
|
import { useState as useState4, useRef as useRef4, useEffect as useEffect4 } from "react";
|
|
1670
|
-
|
|
1675
|
+
|
|
1676
|
+
// src/utils/card-parser.ts
|
|
1677
|
+
var CARD_MARKER_REGEX = /\[([A-Z][A-Z0-9_]*):([^\]]+)\]/g;
|
|
1678
|
+
function parseCardMarker(marker) {
|
|
1679
|
+
const match = marker.match(/^\[([A-Z][A-Z0-9_]*):([^\]]+)\]$/);
|
|
1680
|
+
if (!match) return null;
|
|
1681
|
+
const [, type, valuesStr] = match;
|
|
1682
|
+
const values = valuesStr.split("|").map((v) => v.trim());
|
|
1683
|
+
return {
|
|
1684
|
+
type,
|
|
1685
|
+
values,
|
|
1686
|
+
originalMarker: marker
|
|
1687
|
+
};
|
|
1688
|
+
}
|
|
1689
|
+
function parseMessageContent(content) {
|
|
1690
|
+
const segments = [];
|
|
1691
|
+
let lastIndex = 0;
|
|
1692
|
+
const matches = [...content.matchAll(CARD_MARKER_REGEX)];
|
|
1693
|
+
for (const match of matches) {
|
|
1694
|
+
const marker = match[0];
|
|
1695
|
+
const startIndex = match.index;
|
|
1696
|
+
if (startIndex > lastIndex) {
|
|
1697
|
+
const text = content.slice(lastIndex, startIndex).trim();
|
|
1698
|
+
if (text) {
|
|
1699
|
+
segments.push({ type: "text", content: text });
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
const card = parseCardMarker(marker);
|
|
1703
|
+
if (card) {
|
|
1704
|
+
segments.push({ type: "card", card });
|
|
1705
|
+
}
|
|
1706
|
+
lastIndex = startIndex + marker.length;
|
|
1707
|
+
}
|
|
1708
|
+
if (lastIndex < content.length) {
|
|
1709
|
+
const text = content.slice(lastIndex).trim();
|
|
1710
|
+
if (text) {
|
|
1711
|
+
segments.push({ type: "text", content: text });
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
if (segments.length === 0 && content.trim()) {
|
|
1715
|
+
segments.push({ type: "text", content: content.trim() });
|
|
1716
|
+
}
|
|
1717
|
+
return segments;
|
|
1718
|
+
}
|
|
1719
|
+
function isUrl(str) {
|
|
1720
|
+
return /^https?:\/\//i.test(str);
|
|
1721
|
+
}
|
|
1722
|
+
function isImageUrl(url) {
|
|
1723
|
+
if (!isUrl(url)) return false;
|
|
1724
|
+
return /\.(jpg|jpeg|png|gif|webp|svg)(\?|$)/i.test(url);
|
|
1725
|
+
}
|
|
1726
|
+
function extractCardDisplayData(card) {
|
|
1727
|
+
const values = [...card.values];
|
|
1728
|
+
const result = {
|
|
1729
|
+
title: values[0] || card.type,
|
|
1730
|
+
extraValues: []
|
|
1731
|
+
};
|
|
1732
|
+
if (values.length <= 1) return result;
|
|
1733
|
+
const imageIndex = values.findIndex((v, i) => i > 0 && isImageUrl(v));
|
|
1734
|
+
if (imageIndex > 0) {
|
|
1735
|
+
result.imageUrl = values[imageIndex];
|
|
1736
|
+
values.splice(imageIndex, 1);
|
|
1737
|
+
}
|
|
1738
|
+
const actionIndex = values.findIndex((v, i) => i > 0 && isUrl(v) && !isImageUrl(v));
|
|
1739
|
+
if (actionIndex > 0) {
|
|
1740
|
+
result.actionUrl = values[actionIndex];
|
|
1741
|
+
result.actionLabel = "View";
|
|
1742
|
+
values.splice(actionIndex, 1);
|
|
1743
|
+
}
|
|
1744
|
+
const remaining = values.slice(1);
|
|
1745
|
+
if (remaining.length > 0) {
|
|
1746
|
+
if (remaining[0].length <= 50) {
|
|
1747
|
+
result.subtitle = remaining[0];
|
|
1748
|
+
remaining.shift();
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
if (remaining.length > 0) {
|
|
1752
|
+
result.description = remaining[0];
|
|
1753
|
+
remaining.shift();
|
|
1754
|
+
}
|
|
1755
|
+
result.extraValues = remaining;
|
|
1756
|
+
return result;
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
// src/components/WebsiteChatbot.tsx
|
|
1760
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1671
1761
|
var defaultTheme3 = {
|
|
1672
1762
|
primaryColor: "#f59e0b",
|
|
1673
1763
|
// Amber
|
|
@@ -1676,6 +1766,167 @@ var defaultTheme3 = {
|
|
|
1676
1766
|
borderRadius: "12px",
|
|
1677
1767
|
fontFamily: "system-ui, -apple-system, sans-serif"
|
|
1678
1768
|
};
|
|
1769
|
+
function ChatCard({ card, theme }) {
|
|
1770
|
+
const data = extractCardDisplayData(card);
|
|
1771
|
+
return /* @__PURE__ */ jsxs3(
|
|
1772
|
+
"div",
|
|
1773
|
+
{
|
|
1774
|
+
style: {
|
|
1775
|
+
border: "1px solid #e5e7eb",
|
|
1776
|
+
borderRadius: "8px",
|
|
1777
|
+
overflow: "hidden",
|
|
1778
|
+
backgroundColor: "#fff",
|
|
1779
|
+
marginTop: "8px",
|
|
1780
|
+
marginBottom: "8px"
|
|
1781
|
+
},
|
|
1782
|
+
children: [
|
|
1783
|
+
data.imageUrl && /* @__PURE__ */ jsx4(
|
|
1784
|
+
"div",
|
|
1785
|
+
{
|
|
1786
|
+
style: {
|
|
1787
|
+
width: "100%",
|
|
1788
|
+
height: "140px",
|
|
1789
|
+
backgroundColor: "#f3f4f6",
|
|
1790
|
+
overflow: "hidden"
|
|
1791
|
+
},
|
|
1792
|
+
children: /* @__PURE__ */ jsx4(
|
|
1793
|
+
"img",
|
|
1794
|
+
{
|
|
1795
|
+
src: data.imageUrl,
|
|
1796
|
+
alt: data.title,
|
|
1797
|
+
style: {
|
|
1798
|
+
width: "100%",
|
|
1799
|
+
height: "100%",
|
|
1800
|
+
objectFit: "cover"
|
|
1801
|
+
},
|
|
1802
|
+
onError: (e) => {
|
|
1803
|
+
e.target.style.display = "none";
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
)
|
|
1807
|
+
}
|
|
1808
|
+
),
|
|
1809
|
+
/* @__PURE__ */ jsxs3("div", { style: { padding: "12px" }, children: [
|
|
1810
|
+
/* @__PURE__ */ jsx4(
|
|
1811
|
+
"div",
|
|
1812
|
+
{
|
|
1813
|
+
style: {
|
|
1814
|
+
display: "inline-block",
|
|
1815
|
+
fontSize: "10px",
|
|
1816
|
+
fontWeight: 600,
|
|
1817
|
+
textTransform: "uppercase",
|
|
1818
|
+
letterSpacing: "0.5px",
|
|
1819
|
+
color: theme.primaryColor,
|
|
1820
|
+
backgroundColor: `${theme.primaryColor}15`,
|
|
1821
|
+
padding: "2px 6px",
|
|
1822
|
+
borderRadius: "4px",
|
|
1823
|
+
marginBottom: "6px"
|
|
1824
|
+
},
|
|
1825
|
+
children: card.type
|
|
1826
|
+
}
|
|
1827
|
+
),
|
|
1828
|
+
/* @__PURE__ */ jsx4(
|
|
1829
|
+
"div",
|
|
1830
|
+
{
|
|
1831
|
+
style: {
|
|
1832
|
+
fontSize: "15px",
|
|
1833
|
+
fontWeight: 600,
|
|
1834
|
+
color: "#1f2937",
|
|
1835
|
+
marginBottom: "4px",
|
|
1836
|
+
lineHeight: "1.3"
|
|
1837
|
+
},
|
|
1838
|
+
children: data.title
|
|
1839
|
+
}
|
|
1840
|
+
),
|
|
1841
|
+
data.subtitle && /* @__PURE__ */ jsx4(
|
|
1842
|
+
"div",
|
|
1843
|
+
{
|
|
1844
|
+
style: {
|
|
1845
|
+
fontSize: "13px",
|
|
1846
|
+
color: "#6b7280",
|
|
1847
|
+
marginBottom: "6px"
|
|
1848
|
+
},
|
|
1849
|
+
children: data.subtitle
|
|
1850
|
+
}
|
|
1851
|
+
),
|
|
1852
|
+
data.description && /* @__PURE__ */ jsx4(
|
|
1853
|
+
"div",
|
|
1854
|
+
{
|
|
1855
|
+
style: {
|
|
1856
|
+
fontSize: "13px",
|
|
1857
|
+
color: "#4b5563",
|
|
1858
|
+
lineHeight: "1.4",
|
|
1859
|
+
marginBottom: "8px"
|
|
1860
|
+
},
|
|
1861
|
+
children: data.description
|
|
1862
|
+
}
|
|
1863
|
+
),
|
|
1864
|
+
data.extraValues.length > 0 && /* @__PURE__ */ jsx4(
|
|
1865
|
+
"div",
|
|
1866
|
+
{
|
|
1867
|
+
style: {
|
|
1868
|
+
fontSize: "12px",
|
|
1869
|
+
color: "#6b7280",
|
|
1870
|
+
marginBottom: "8px"
|
|
1871
|
+
},
|
|
1872
|
+
children: data.extraValues.join(" \u2022 ")
|
|
1873
|
+
}
|
|
1874
|
+
),
|
|
1875
|
+
data.actionUrl && /* @__PURE__ */ jsxs3(
|
|
1876
|
+
"a",
|
|
1877
|
+
{
|
|
1878
|
+
href: data.actionUrl,
|
|
1879
|
+
target: "_blank",
|
|
1880
|
+
rel: "noopener noreferrer",
|
|
1881
|
+
style: {
|
|
1882
|
+
display: "inline-flex",
|
|
1883
|
+
alignItems: "center",
|
|
1884
|
+
gap: "4px",
|
|
1885
|
+
fontSize: "13px",
|
|
1886
|
+
fontWeight: 500,
|
|
1887
|
+
color: theme.primaryColor,
|
|
1888
|
+
textDecoration: "none",
|
|
1889
|
+
padding: "6px 12px",
|
|
1890
|
+
borderRadius: "6px",
|
|
1891
|
+
backgroundColor: `${theme.primaryColor}10`,
|
|
1892
|
+
transition: "background-color 0.2s"
|
|
1893
|
+
},
|
|
1894
|
+
onMouseEnter: (e) => {
|
|
1895
|
+
e.currentTarget.style.backgroundColor = `${theme.primaryColor}20`;
|
|
1896
|
+
},
|
|
1897
|
+
onMouseLeave: (e) => {
|
|
1898
|
+
e.currentTarget.style.backgroundColor = `${theme.primaryColor}10`;
|
|
1899
|
+
},
|
|
1900
|
+
children: [
|
|
1901
|
+
data.actionLabel || "View",
|
|
1902
|
+
/* @__PURE__ */ jsxs3("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1903
|
+
/* @__PURE__ */ jsx4("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
|
|
1904
|
+
/* @__PURE__ */ jsx4("polyline", { points: "15 3 21 3 21 9" }),
|
|
1905
|
+
/* @__PURE__ */ jsx4("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
|
|
1906
|
+
] })
|
|
1907
|
+
]
|
|
1908
|
+
}
|
|
1909
|
+
)
|
|
1910
|
+
] })
|
|
1911
|
+
]
|
|
1912
|
+
}
|
|
1913
|
+
);
|
|
1914
|
+
}
|
|
1915
|
+
function MessageContent({ content, theme }) {
|
|
1916
|
+
const segments = parseMessageContent(content);
|
|
1917
|
+
if (segments.length === 1 && segments[0].type === "text") {
|
|
1918
|
+
return /* @__PURE__ */ jsx4(Fragment2, { children: segments[0].content });
|
|
1919
|
+
}
|
|
1920
|
+
return /* @__PURE__ */ jsx4(Fragment2, { children: segments.map((segment, index) => {
|
|
1921
|
+
if (segment.type === "text") {
|
|
1922
|
+
return /* @__PURE__ */ jsx4("span", { style: { whiteSpace: "pre-wrap" }, children: segment.content }, index);
|
|
1923
|
+
}
|
|
1924
|
+
if (segment.type === "card" && segment.card) {
|
|
1925
|
+
return /* @__PURE__ */ jsx4(ChatCard, { card: segment.card, theme }, index);
|
|
1926
|
+
}
|
|
1927
|
+
return null;
|
|
1928
|
+
}) });
|
|
1929
|
+
}
|
|
1679
1930
|
function WebsiteChatbot({ className, ...config }) {
|
|
1680
1931
|
const theme = { ...defaultTheme3, ...config.theme };
|
|
1681
1932
|
const apiUrl = config.apiUrl || "https://api.informedai.app/api/v1";
|
|
@@ -1697,13 +1948,12 @@ function WebsiteChatbot({ className, ...config }) {
|
|
|
1697
1948
|
const newMessages = [...messages, { role: "user", content: message }];
|
|
1698
1949
|
setMessages(newMessages);
|
|
1699
1950
|
try {
|
|
1700
|
-
const response = await fetch(`${apiUrl}/website-agent/message`, {
|
|
1951
|
+
const response = await fetch(`${apiUrl}/website-agent/${config.agentId}/message`, {
|
|
1701
1952
|
method: "POST",
|
|
1702
1953
|
headers: {
|
|
1703
1954
|
"Content-Type": "application/json"
|
|
1704
1955
|
},
|
|
1705
1956
|
body: JSON.stringify({
|
|
1706
|
-
agentId: config.agentId,
|
|
1707
1957
|
message,
|
|
1708
1958
|
history: messages
|
|
1709
1959
|
})
|
|
@@ -1923,10 +2173,9 @@ function WebsiteChatbot({ className, ...config }) {
|
|
|
1923
2173
|
backgroundColor: msg.role === "user" ? "var(--wc-primary)" : "#f3f4f6",
|
|
1924
2174
|
color: msg.role === "user" ? "white" : "var(--wc-text)",
|
|
1925
2175
|
fontSize: "14px",
|
|
1926
|
-
lineHeight: "1.5"
|
|
1927
|
-
whiteSpace: "pre-wrap"
|
|
2176
|
+
lineHeight: "1.5"
|
|
1928
2177
|
},
|
|
1929
|
-
children: msg.content
|
|
2178
|
+
children: msg.role === "user" ? msg.content : /* @__PURE__ */ jsx4(MessageContent, { content: msg.content, theme })
|
|
1930
2179
|
}
|
|
1931
2180
|
)
|
|
1932
2181
|
},
|
|
@@ -1941,11 +2190,10 @@ function WebsiteChatbot({ className, ...config }) {
|
|
|
1941
2190
|
backgroundColor: "#f3f4f6",
|
|
1942
2191
|
color: "var(--wc-text)",
|
|
1943
2192
|
fontSize: "14px",
|
|
1944
|
-
lineHeight: "1.5"
|
|
1945
|
-
whiteSpace: "pre-wrap"
|
|
2193
|
+
lineHeight: "1.5"
|
|
1946
2194
|
},
|
|
1947
2195
|
children: [
|
|
1948
|
-
streamingContent,
|
|
2196
|
+
/* @__PURE__ */ jsx4(MessageContent, { content: streamingContent, theme }),
|
|
1949
2197
|
/* @__PURE__ */ jsx4("span", { style: { opacity: 0.5, animation: "blink 1s infinite" }, children: "|" })
|
|
1950
2198
|
]
|
|
1951
2199
|
}
|