@informedai/react 0.4.14 → 0.4.15

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.js CHANGED
@@ -20,9 +20,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ AdminChatbot: () => AdminChatbot,
23
24
  InformedAIClient: () => InformedAIClient,
24
25
  InformedAIProvider: () => InformedAIProvider,
25
26
  InformedAssistant: () => InformedAssistant,
27
+ WebsiteChatbot: () => WebsiteChatbot,
26
28
  useInformedAI: () => useInformedAI,
27
29
  useSession: () => useSession
28
30
  });
@@ -1301,19 +1303,765 @@ function LoadingSpinner({ size = 20 }) {
1301
1303
  );
1302
1304
  }
1303
1305
 
1304
- // src/hooks/useSession.ts
1306
+ // src/components/AdminChatbot.tsx
1305
1307
  var import_react3 = require("react");
1306
- function useSession(options) {
1307
- const { apiUrl, documentTypeId, sessionId, onSessionChange, onError } = options;
1308
- const [session, setSession] = (0, import_react3.useState)(null);
1309
- const [isLoading, setIsLoading] = (0, import_react3.useState)(true);
1308
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1309
+ var defaultTheme2 = {
1310
+ primaryColor: "#3b82f6",
1311
+ // Blue (different from widget's amber)
1312
+ backgroundColor: "#ffffff",
1313
+ textColor: "#1c1917",
1314
+ borderRadius: "12px",
1315
+ fontFamily: "system-ui, -apple-system, sans-serif"
1316
+ };
1317
+ function AdminChatbot({ className, ...config }) {
1318
+ const theme = { ...defaultTheme2, ...config.theme };
1319
+ const apiUrl = config.apiUrl || "https://api.informedai.app/api/v1";
1320
+ const [messages, setMessages] = (0, import_react3.useState)([]);
1321
+ const [inputValue, setInputValue] = (0, import_react3.useState)("");
1322
+ const [systemPrompt, setSystemPrompt] = (0, import_react3.useState)(config.systemPrompt || "");
1323
+ const [showSystemPromptEditor, setShowSystemPromptEditor] = (0, import_react3.useState)(false);
1324
+ const [isStreaming, setIsStreaming] = (0, import_react3.useState)(false);
1325
+ const [streamingContent, setStreamingContent] = (0, import_react3.useState)("");
1310
1326
  const [error, setError] = (0, import_react3.useState)(null);
1311
- const clientRef = (0, import_react3.useRef)(null);
1312
- const isStreamingRef = (0, import_react3.useRef)(false);
1327
+ const [isCollapsed, setIsCollapsed] = (0, import_react3.useState)(config.defaultCollapsed ?? false);
1328
+ const messagesEndRef = (0, import_react3.useRef)(null);
1329
+ const inputRef = (0, import_react3.useRef)(null);
1313
1330
  (0, import_react3.useEffect)(() => {
1331
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
1332
+ }, [messages, streamingContent]);
1333
+ const sendMessage = async (message) => {
1334
+ if (!message.trim() || isStreaming) return;
1335
+ setError(null);
1336
+ setIsStreaming(true);
1337
+ setStreamingContent("");
1338
+ const newMessages = [...messages, { role: "user", content: message }];
1339
+ setMessages(newMessages);
1340
+ try {
1341
+ const response = await fetch(`${apiUrl}/admin-chatbot/message`, {
1342
+ method: "POST",
1343
+ headers: {
1344
+ "Content-Type": "application/json",
1345
+ Authorization: `Bearer ${config.apiKey}`
1346
+ },
1347
+ body: JSON.stringify({
1348
+ message,
1349
+ history: messages,
1350
+ // Send previous messages (not including current)
1351
+ systemPrompt: systemPrompt || void 0
1352
+ })
1353
+ });
1354
+ if (!response.ok) {
1355
+ const err = await response.json().catch(() => ({ error: "Request failed" }));
1356
+ throw new Error(err.error || `HTTP ${response.status}`);
1357
+ }
1358
+ const reader = response.body?.getReader();
1359
+ if (!reader) throw new Error("No response body");
1360
+ const decoder = new TextDecoder();
1361
+ let buffer = "";
1362
+ let fullContent = "";
1363
+ while (true) {
1364
+ const { done, value } = await reader.read();
1365
+ if (done) break;
1366
+ buffer += decoder.decode(value, { stream: true });
1367
+ const lines = buffer.split("\n");
1368
+ buffer = lines.pop() || "";
1369
+ for (const line of lines) {
1370
+ if (line.startsWith("event:")) continue;
1371
+ if (line.startsWith("data:")) {
1372
+ const data = line.slice(5).trim();
1373
+ try {
1374
+ const parsed = JSON.parse(data);
1375
+ if (parsed.content) {
1376
+ fullContent += parsed.content;
1377
+ setStreamingContent(fullContent);
1378
+ }
1379
+ if (parsed.fullContent) {
1380
+ fullContent = parsed.fullContent;
1381
+ }
1382
+ } catch {
1383
+ }
1384
+ }
1385
+ }
1386
+ }
1387
+ setMessages([...newMessages, { role: "assistant", content: fullContent }]);
1388
+ setStreamingContent("");
1389
+ } catch (err) {
1390
+ setError(err instanceof Error ? err.message : "Failed to send message");
1391
+ } finally {
1392
+ setIsStreaming(false);
1393
+ }
1394
+ };
1395
+ const handleSubmit = (e) => {
1396
+ e.preventDefault();
1397
+ if (!inputValue.trim() || isStreaming) return;
1398
+ const message = inputValue.trim();
1399
+ setInputValue("");
1400
+ sendMessage(message);
1401
+ };
1402
+ const clearConversation = () => {
1403
+ setMessages([]);
1404
+ setStreamingContent("");
1405
+ setError(null);
1406
+ };
1407
+ const cssVars = {
1408
+ "--ac-primary": theme.primaryColor,
1409
+ "--ac-bg": theme.backgroundColor,
1410
+ "--ac-text": theme.textColor,
1411
+ "--ac-radius": theme.borderRadius,
1412
+ "--ac-font": theme.fontFamily
1413
+ };
1414
+ const positionStyles = config.position === "inline" ? {} : {
1415
+ position: "fixed",
1416
+ [config.position === "bottom-left" ? "left" : "right"]: "20px",
1417
+ bottom: "20px",
1418
+ zIndex: 9999
1419
+ };
1420
+ if (isCollapsed && config.position !== "inline") {
1421
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1422
+ "button",
1423
+ {
1424
+ onClick: () => setIsCollapsed(false),
1425
+ className,
1426
+ style: {
1427
+ ...cssVars,
1428
+ ...positionStyles,
1429
+ width: "56px",
1430
+ height: "56px",
1431
+ borderRadius: "50%",
1432
+ backgroundColor: "var(--ac-primary)",
1433
+ color: "white",
1434
+ border: "none",
1435
+ cursor: "pointer",
1436
+ display: "flex",
1437
+ alignItems: "center",
1438
+ justifyContent: "center",
1439
+ boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
1440
+ fontFamily: "var(--ac-font)"
1441
+ },
1442
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) })
1443
+ }
1444
+ );
1445
+ }
1446
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1447
+ "div",
1448
+ {
1449
+ className,
1450
+ style: {
1451
+ ...cssVars,
1452
+ ...positionStyles,
1453
+ width: config.position === "inline" ? "100%" : "400px",
1454
+ maxHeight: config.position === "inline" ? "600px" : "80vh",
1455
+ backgroundColor: "var(--ac-bg)",
1456
+ borderRadius: "var(--ac-radius)",
1457
+ border: "1px solid #e5e5e5",
1458
+ fontFamily: "var(--ac-font)",
1459
+ display: "flex",
1460
+ flexDirection: "column",
1461
+ boxShadow: config.position === "inline" ? "none" : "0 4px 20px rgba(0,0,0,0.15)",
1462
+ overflow: "hidden"
1463
+ },
1464
+ children: [
1465
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1466
+ "div",
1467
+ {
1468
+ style: {
1469
+ padding: "16px",
1470
+ borderBottom: "1px solid #e5e5e5",
1471
+ display: "flex",
1472
+ alignItems: "center",
1473
+ justifyContent: "space-between",
1474
+ backgroundColor: "var(--ac-primary)",
1475
+ color: "white"
1476
+ },
1477
+ children: [
1478
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
1479
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1480
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
1481
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 16v-4M12 8h.01" })
1482
+ ] }),
1483
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontWeight: 600 }, children: config.title || "Knowledge Library" })
1484
+ ] }),
1485
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
1486
+ config.allowEditSystemPrompt && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1487
+ "button",
1488
+ {
1489
+ onClick: () => setShowSystemPromptEditor(!showSystemPromptEditor),
1490
+ style: {
1491
+ background: "rgba(255,255,255,0.2)",
1492
+ border: "none",
1493
+ borderRadius: "4px",
1494
+ padding: "4px 8px",
1495
+ color: "white",
1496
+ cursor: "pointer",
1497
+ fontSize: "12px"
1498
+ },
1499
+ children: showSystemPromptEditor ? "Hide Prompt" : "Edit Prompt"
1500
+ }
1501
+ ),
1502
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1503
+ "button",
1504
+ {
1505
+ onClick: clearConversation,
1506
+ style: {
1507
+ background: "rgba(255,255,255,0.2)",
1508
+ border: "none",
1509
+ borderRadius: "4px",
1510
+ padding: "4px 8px",
1511
+ color: "white",
1512
+ cursor: "pointer",
1513
+ fontSize: "12px"
1514
+ },
1515
+ children: "Clear"
1516
+ }
1517
+ ),
1518
+ config.position !== "inline" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1519
+ "button",
1520
+ {
1521
+ onClick: () => setIsCollapsed(true),
1522
+ style: {
1523
+ background: "none",
1524
+ border: "none",
1525
+ color: "white",
1526
+ cursor: "pointer",
1527
+ padding: "4px"
1528
+ },
1529
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1530
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1531
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1532
+ ] })
1533
+ }
1534
+ )
1535
+ ] })
1536
+ ]
1537
+ }
1538
+ ),
1539
+ showSystemPromptEditor && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: "12px", borderBottom: "1px solid #e5e5e5", backgroundColor: "#f9fafb" }, children: [
1540
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: { display: "block", fontSize: "12px", fontWeight: 500, marginBottom: "4px", color: "#6b7280" }, children: "System Prompt" }),
1541
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1542
+ "textarea",
1543
+ {
1544
+ value: systemPrompt,
1545
+ onChange: (e) => setSystemPrompt(e.target.value),
1546
+ placeholder: "Enter a system prompt to guide the chatbot's behavior...",
1547
+ style: {
1548
+ width: "100%",
1549
+ minHeight: "80px",
1550
+ padding: "8px",
1551
+ borderRadius: "6px",
1552
+ border: "1px solid #d1d5db",
1553
+ fontSize: "13px",
1554
+ fontFamily: "var(--ac-font)",
1555
+ resize: "vertical"
1556
+ }
1557
+ }
1558
+ )
1559
+ ] }),
1560
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1561
+ "div",
1562
+ {
1563
+ style: {
1564
+ flex: 1,
1565
+ overflowY: "auto",
1566
+ padding: "16px",
1567
+ display: "flex",
1568
+ flexDirection: "column",
1569
+ gap: "12px",
1570
+ minHeight: "200px"
1571
+ },
1572
+ children: [
1573
+ messages.length === 0 && !streamingContent && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { textAlign: "center", color: "#9ca3af", padding: "40px 20px" }, children: [
1574
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1575
+ "svg",
1576
+ {
1577
+ width: "48",
1578
+ height: "48",
1579
+ viewBox: "0 0 24 24",
1580
+ fill: "none",
1581
+ stroke: "currentColor",
1582
+ strokeWidth: "1.5",
1583
+ style: { margin: "0 auto 16px" },
1584
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
1585
+ }
1586
+ ),
1587
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: { margin: 0, fontSize: "14px" }, children: "Ask a question about your knowledge library" })
1588
+ ] }),
1589
+ messages.map((msg, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1590
+ "div",
1591
+ {
1592
+ style: {
1593
+ alignSelf: msg.role === "user" ? "flex-end" : "flex-start",
1594
+ maxWidth: "85%"
1595
+ },
1596
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1597
+ "div",
1598
+ {
1599
+ style: {
1600
+ padding: "10px 14px",
1601
+ borderRadius: "12px",
1602
+ backgroundColor: msg.role === "user" ? "var(--ac-primary)" : "#f3f4f6",
1603
+ color: msg.role === "user" ? "white" : "var(--ac-text)",
1604
+ fontSize: "14px",
1605
+ lineHeight: "1.5",
1606
+ whiteSpace: "pre-wrap"
1607
+ },
1608
+ children: msg.content
1609
+ }
1610
+ )
1611
+ },
1612
+ i
1613
+ )),
1614
+ streamingContent && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { alignSelf: "flex-start", maxWidth: "85%" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1615
+ "div",
1616
+ {
1617
+ style: {
1618
+ padding: "10px 14px",
1619
+ borderRadius: "12px",
1620
+ backgroundColor: "#f3f4f6",
1621
+ color: "var(--ac-text)",
1622
+ fontSize: "14px",
1623
+ lineHeight: "1.5",
1624
+ whiteSpace: "pre-wrap"
1625
+ },
1626
+ children: [
1627
+ streamingContent,
1628
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { opacity: 0.5, animation: "blink 1s infinite" }, children: "|" })
1629
+ ]
1630
+ }
1631
+ ) }),
1632
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1633
+ "div",
1634
+ {
1635
+ style: {
1636
+ padding: "10px 14px",
1637
+ borderRadius: "8px",
1638
+ backgroundColor: "#fef2f2",
1639
+ color: "#dc2626",
1640
+ fontSize: "13px"
1641
+ },
1642
+ children: error
1643
+ }
1644
+ ),
1645
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: messagesEndRef })
1646
+ ]
1647
+ }
1648
+ ),
1649
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("form", { onSubmit: handleSubmit, style: { padding: "12px", borderTop: "1px solid #e5e5e5" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
1650
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1651
+ "input",
1652
+ {
1653
+ ref: inputRef,
1654
+ type: "text",
1655
+ value: inputValue,
1656
+ onChange: (e) => setInputValue(e.target.value),
1657
+ placeholder: config.placeholder || "Ask a question...",
1658
+ disabled: isStreaming,
1659
+ style: {
1660
+ flex: 1,
1661
+ padding: "10px 14px",
1662
+ borderRadius: "8px",
1663
+ border: "1px solid #d1d5db",
1664
+ fontSize: "14px",
1665
+ fontFamily: "var(--ac-font)",
1666
+ outline: "none"
1667
+ }
1668
+ }
1669
+ ),
1670
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1671
+ "button",
1672
+ {
1673
+ type: "submit",
1674
+ disabled: isStreaming || !inputValue.trim(),
1675
+ style: {
1676
+ padding: "10px 16px",
1677
+ borderRadius: "8px",
1678
+ backgroundColor: isStreaming || !inputValue.trim() ? "#d1d5db" : "var(--ac-primary)",
1679
+ color: "white",
1680
+ border: "none",
1681
+ cursor: isStreaming || !inputValue.trim() ? "not-allowed" : "pointer",
1682
+ fontWeight: 500,
1683
+ fontSize: "14px"
1684
+ },
1685
+ children: isStreaming ? "..." : "Send"
1686
+ }
1687
+ )
1688
+ ] }) }),
1689
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: `
1690
+ @keyframes blink {
1691
+ 0%, 50% { opacity: 1; }
1692
+ 51%, 100% { opacity: 0; }
1693
+ }
1694
+ ` })
1695
+ ]
1696
+ }
1697
+ );
1698
+ }
1699
+
1700
+ // src/components/WebsiteChatbot.tsx
1701
+ var import_react4 = require("react");
1702
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1703
+ var defaultTheme3 = {
1704
+ primaryColor: "#f59e0b",
1705
+ // Amber
1706
+ backgroundColor: "#ffffff",
1707
+ textColor: "#1c1917",
1708
+ borderRadius: "12px",
1709
+ fontFamily: "system-ui, -apple-system, sans-serif"
1710
+ };
1711
+ function WebsiteChatbot({ className, ...config }) {
1712
+ const theme = { ...defaultTheme3, ...config.theme };
1713
+ const apiUrl = config.apiUrl || "https://api.informedai.app/api/v1";
1714
+ const [messages, setMessages] = (0, import_react4.useState)([]);
1715
+ const [inputValue, setInputValue] = (0, import_react4.useState)("");
1716
+ const [isStreaming, setIsStreaming] = (0, import_react4.useState)(false);
1717
+ const [streamingContent, setStreamingContent] = (0, import_react4.useState)("");
1718
+ const [error, setError] = (0, import_react4.useState)(null);
1719
+ const [isCollapsed, setIsCollapsed] = (0, import_react4.useState)(config.defaultCollapsed ?? false);
1720
+ const messagesEndRef = (0, import_react4.useRef)(null);
1721
+ (0, import_react4.useEffect)(() => {
1722
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
1723
+ }, [messages, streamingContent]);
1724
+ const sendMessage = async (message) => {
1725
+ if (!message.trim() || isStreaming) return;
1726
+ setError(null);
1727
+ setIsStreaming(true);
1728
+ setStreamingContent("");
1729
+ const newMessages = [...messages, { role: "user", content: message }];
1730
+ setMessages(newMessages);
1731
+ try {
1732
+ const response = await fetch(`${apiUrl}/website-agent/message`, {
1733
+ method: "POST",
1734
+ headers: {
1735
+ "Content-Type": "application/json"
1736
+ },
1737
+ body: JSON.stringify({
1738
+ agentId: config.agentId,
1739
+ message,
1740
+ history: messages
1741
+ })
1742
+ });
1743
+ if (!response.ok) {
1744
+ const err = await response.json().catch(() => ({ error: "Request failed" }));
1745
+ throw new Error(err.error || `HTTP ${response.status}`);
1746
+ }
1747
+ const reader = response.body?.getReader();
1748
+ if (!reader) throw new Error("No response body");
1749
+ const decoder = new TextDecoder();
1750
+ let buffer = "";
1751
+ let fullContent = "";
1752
+ while (true) {
1753
+ const { done, value } = await reader.read();
1754
+ if (done) break;
1755
+ buffer += decoder.decode(value, { stream: true });
1756
+ const lines = buffer.split("\n");
1757
+ buffer = lines.pop() || "";
1758
+ for (const line of lines) {
1759
+ if (line.startsWith("event:")) continue;
1760
+ if (line.startsWith("data:")) {
1761
+ const data = line.slice(5).trim();
1762
+ try {
1763
+ const parsed = JSON.parse(data);
1764
+ if (parsed.content) {
1765
+ fullContent += parsed.content;
1766
+ setStreamingContent(fullContent);
1767
+ }
1768
+ if (parsed.fullContent) {
1769
+ fullContent = parsed.fullContent;
1770
+ }
1771
+ } catch {
1772
+ }
1773
+ }
1774
+ }
1775
+ }
1776
+ setMessages([...newMessages, { role: "assistant", content: fullContent }]);
1777
+ setStreamingContent("");
1778
+ } catch (err) {
1779
+ setError(err instanceof Error ? err.message : "Failed to send message");
1780
+ } finally {
1781
+ setIsStreaming(false);
1782
+ }
1783
+ };
1784
+ const handleSubmit = (e) => {
1785
+ e.preventDefault();
1786
+ if (!inputValue.trim() || isStreaming) return;
1787
+ const message = inputValue.trim();
1788
+ setInputValue("");
1789
+ sendMessage(message);
1790
+ };
1791
+ const clearConversation = () => {
1792
+ setMessages([]);
1793
+ setStreamingContent("");
1794
+ setError(null);
1795
+ };
1796
+ const cssVars = {
1797
+ "--wc-primary": theme.primaryColor,
1798
+ "--wc-bg": theme.backgroundColor,
1799
+ "--wc-text": theme.textColor,
1800
+ "--wc-radius": theme.borderRadius,
1801
+ "--wc-font": theme.fontFamily
1802
+ };
1803
+ const positionStyles = config.position === "inline" ? {} : {
1804
+ position: "fixed",
1805
+ [config.position === "bottom-left" ? "left" : "right"]: "20px",
1806
+ bottom: "20px",
1807
+ zIndex: 9999
1808
+ };
1809
+ if (isCollapsed && config.position !== "inline") {
1810
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1811
+ "button",
1812
+ {
1813
+ onClick: () => setIsCollapsed(false),
1814
+ className,
1815
+ style: {
1816
+ ...cssVars,
1817
+ ...positionStyles,
1818
+ width: "56px",
1819
+ height: "56px",
1820
+ borderRadius: "50%",
1821
+ backgroundColor: "var(--wc-primary)",
1822
+ color: "white",
1823
+ border: "none",
1824
+ cursor: "pointer",
1825
+ display: "flex",
1826
+ alignItems: "center",
1827
+ justifyContent: "center",
1828
+ boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
1829
+ fontFamily: "var(--wc-font)"
1830
+ },
1831
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) })
1832
+ }
1833
+ );
1834
+ }
1835
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1836
+ "div",
1837
+ {
1838
+ className,
1839
+ style: {
1840
+ ...cssVars,
1841
+ ...positionStyles,
1842
+ width: config.position === "inline" ? "100%" : "400px",
1843
+ maxHeight: config.position === "inline" ? "600px" : "80vh",
1844
+ backgroundColor: "var(--wc-bg)",
1845
+ borderRadius: "var(--wc-radius)",
1846
+ border: "1px solid #e5e5e5",
1847
+ fontFamily: "var(--wc-font)",
1848
+ display: "flex",
1849
+ flexDirection: "column",
1850
+ boxShadow: config.position === "inline" ? "none" : "0 4px 20px rgba(0,0,0,0.15)",
1851
+ overflow: "hidden"
1852
+ },
1853
+ children: [
1854
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1855
+ "div",
1856
+ {
1857
+ style: {
1858
+ padding: "16px",
1859
+ borderBottom: "1px solid #e5e5e5",
1860
+ display: "flex",
1861
+ alignItems: "center",
1862
+ justifyContent: "space-between",
1863
+ backgroundColor: "var(--wc-primary)",
1864
+ color: "white"
1865
+ },
1866
+ children: [
1867
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
1868
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1869
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
1870
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "2", y1: "12", x2: "22", y2: "12" }),
1871
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" })
1872
+ ] }),
1873
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { fontWeight: 600 }, children: config.title || "Chat" })
1874
+ ] }),
1875
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
1876
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1877
+ "button",
1878
+ {
1879
+ onClick: clearConversation,
1880
+ style: {
1881
+ background: "rgba(255,255,255,0.2)",
1882
+ border: "none",
1883
+ borderRadius: "4px",
1884
+ padding: "4px 8px",
1885
+ color: "white",
1886
+ cursor: "pointer",
1887
+ fontSize: "12px"
1888
+ },
1889
+ children: "Clear"
1890
+ }
1891
+ ),
1892
+ config.position !== "inline" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1893
+ "button",
1894
+ {
1895
+ onClick: () => setIsCollapsed(true),
1896
+ style: {
1897
+ background: "none",
1898
+ border: "none",
1899
+ color: "white",
1900
+ cursor: "pointer",
1901
+ padding: "4px"
1902
+ },
1903
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1904
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1905
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1906
+ ] })
1907
+ }
1908
+ )
1909
+ ] })
1910
+ ]
1911
+ }
1912
+ ),
1913
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1914
+ "div",
1915
+ {
1916
+ style: {
1917
+ flex: 1,
1918
+ overflowY: "auto",
1919
+ padding: "16px",
1920
+ display: "flex",
1921
+ flexDirection: "column",
1922
+ gap: "12px",
1923
+ minHeight: "200px"
1924
+ },
1925
+ children: [
1926
+ messages.length === 0 && !streamingContent && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { textAlign: "center", color: "#9ca3af", padding: "40px 20px" }, children: [
1927
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1928
+ "svg",
1929
+ {
1930
+ width: "48",
1931
+ height: "48",
1932
+ viewBox: "0 0 24 24",
1933
+ fill: "none",
1934
+ stroke: "currentColor",
1935
+ strokeWidth: "1.5",
1936
+ style: { margin: "0 auto 16px" },
1937
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
1938
+ }
1939
+ ),
1940
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { margin: 0, fontSize: "14px" }, children: "How can I help you today?" })
1941
+ ] }),
1942
+ messages.map((msg, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1943
+ "div",
1944
+ {
1945
+ style: {
1946
+ alignSelf: msg.role === "user" ? "flex-end" : "flex-start",
1947
+ maxWidth: "85%"
1948
+ },
1949
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1950
+ "div",
1951
+ {
1952
+ style: {
1953
+ padding: "10px 14px",
1954
+ borderRadius: "12px",
1955
+ backgroundColor: msg.role === "user" ? "var(--wc-primary)" : "#f3f4f6",
1956
+ color: msg.role === "user" ? "white" : "var(--wc-text)",
1957
+ fontSize: "14px",
1958
+ lineHeight: "1.5",
1959
+ whiteSpace: "pre-wrap"
1960
+ },
1961
+ children: msg.content
1962
+ }
1963
+ )
1964
+ },
1965
+ i
1966
+ )),
1967
+ streamingContent && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { alignSelf: "flex-start", maxWidth: "85%" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1968
+ "div",
1969
+ {
1970
+ style: {
1971
+ padding: "10px 14px",
1972
+ borderRadius: "12px",
1973
+ backgroundColor: "#f3f4f6",
1974
+ color: "var(--wc-text)",
1975
+ fontSize: "14px",
1976
+ lineHeight: "1.5",
1977
+ whiteSpace: "pre-wrap"
1978
+ },
1979
+ children: [
1980
+ streamingContent,
1981
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { opacity: 0.5, animation: "blink 1s infinite" }, children: "|" })
1982
+ ]
1983
+ }
1984
+ ) }),
1985
+ error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1986
+ "div",
1987
+ {
1988
+ style: {
1989
+ padding: "10px 14px",
1990
+ borderRadius: "8px",
1991
+ backgroundColor: "#fef2f2",
1992
+ color: "#dc2626",
1993
+ fontSize: "13px"
1994
+ },
1995
+ children: error
1996
+ }
1997
+ ),
1998
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: messagesEndRef })
1999
+ ]
2000
+ }
2001
+ ),
2002
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("form", { onSubmit: handleSubmit, style: { padding: "12px", borderTop: "1px solid #e5e5e5" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
2003
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2004
+ "input",
2005
+ {
2006
+ type: "text",
2007
+ value: inputValue,
2008
+ onChange: (e) => setInputValue(e.target.value),
2009
+ placeholder: config.placeholder || "Type a message...",
2010
+ disabled: isStreaming,
2011
+ style: {
2012
+ flex: 1,
2013
+ padding: "10px 14px",
2014
+ borderRadius: "8px",
2015
+ border: "1px solid #d1d5db",
2016
+ fontSize: "14px",
2017
+ fontFamily: "var(--wc-font)",
2018
+ outline: "none"
2019
+ }
2020
+ }
2021
+ ),
2022
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2023
+ "button",
2024
+ {
2025
+ type: "submit",
2026
+ disabled: isStreaming || !inputValue.trim(),
2027
+ style: {
2028
+ padding: "10px 16px",
2029
+ borderRadius: "8px",
2030
+ backgroundColor: isStreaming || !inputValue.trim() ? "#d1d5db" : "var(--wc-primary)",
2031
+ color: "white",
2032
+ border: "none",
2033
+ cursor: isStreaming || !inputValue.trim() ? "not-allowed" : "pointer",
2034
+ fontWeight: 500,
2035
+ fontSize: "14px"
2036
+ },
2037
+ children: isStreaming ? "..." : "Send"
2038
+ }
2039
+ )
2040
+ ] }) }),
2041
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: `
2042
+ @keyframes blink {
2043
+ 0%, 50% { opacity: 1; }
2044
+ 51%, 100% { opacity: 0; }
2045
+ }
2046
+ ` })
2047
+ ]
2048
+ }
2049
+ );
2050
+ }
2051
+
2052
+ // src/hooks/useSession.ts
2053
+ var import_react5 = require("react");
2054
+ function useSession(options) {
2055
+ const { apiUrl, documentTypeId, sessionId, onSessionChange, onError } = options;
2056
+ const [session, setSession] = (0, import_react5.useState)(null);
2057
+ const [isLoading, setIsLoading] = (0, import_react5.useState)(true);
2058
+ const [error, setError] = (0, import_react5.useState)(null);
2059
+ const clientRef = (0, import_react5.useRef)(null);
2060
+ const isStreamingRef = (0, import_react5.useRef)(false);
2061
+ (0, import_react5.useEffect)(() => {
1314
2062
  clientRef.current = new InformedAIClient(apiUrl);
1315
2063
  }, [apiUrl]);
1316
- (0, import_react3.useEffect)(() => {
2064
+ (0, import_react5.useEffect)(() => {
1317
2065
  async function initialize() {
1318
2066
  if (!clientRef.current) return;
1319
2067
  try {
@@ -1338,7 +2086,7 @@ function useSession(options) {
1338
2086
  }
1339
2087
  initialize();
1340
2088
  }, [documentTypeId, sessionId, onSessionChange, onError]);
1341
- const handleSSEEvent = (0, import_react3.useCallback)((event) => {
2089
+ const handleSSEEvent = (0, import_react5.useCallback)((event) => {
1342
2090
  if (event.type === "done" || event.type === "session_update") {
1343
2091
  if (event.session) {
1344
2092
  setSession(event.session);
@@ -1353,7 +2101,7 @@ function useSession(options) {
1353
2101
  isStreamingRef.current = false;
1354
2102
  }
1355
2103
  }, [onSessionChange, onError]);
1356
- const sendMessage = (0, import_react3.useCallback)(async (message) => {
2104
+ const sendMessage = (0, import_react5.useCallback)(async (message) => {
1357
2105
  if (!clientRef.current || !session || isStreamingRef.current) return;
1358
2106
  try {
1359
2107
  isStreamingRef.current = true;
@@ -1366,7 +2114,7 @@ function useSession(options) {
1366
2114
  isStreamingRef.current = false;
1367
2115
  }
1368
2116
  }, [session, handleSSEEvent, onError]);
1369
- const sendQuickAction = (0, import_react3.useCallback)(async (action) => {
2117
+ const sendQuickAction = (0, import_react5.useCallback)(async (action) => {
1370
2118
  if (!clientRef.current || !session || isStreamingRef.current) return;
1371
2119
  try {
1372
2120
  isStreamingRef.current = true;
@@ -1386,7 +2134,7 @@ function useSession(options) {
1386
2134
  isStreamingRef.current = false;
1387
2135
  }
1388
2136
  }, [session, handleSSEEvent, onSessionChange, onError]);
1389
- const applyPendingValue = (0, import_react3.useCallback)(async () => {
2137
+ const applyPendingValue = (0, import_react5.useCallback)(async () => {
1390
2138
  if (!clientRef.current || !session) return;
1391
2139
  try {
1392
2140
  setError(null);
@@ -1399,7 +2147,7 @@ function useSession(options) {
1399
2147
  onError?.(error2);
1400
2148
  }
1401
2149
  }, [session, onSessionChange, onError]);
1402
- const skipTask = (0, import_react3.useCallback)(async () => {
2150
+ const skipTask = (0, import_react5.useCallback)(async () => {
1403
2151
  if (!clientRef.current || !session) return;
1404
2152
  try {
1405
2153
  setError(null);
@@ -1424,9 +2172,11 @@ function useSession(options) {
1424
2172
  }
1425
2173
  // Annotate the CommonJS export names for ESM import in node:
1426
2174
  0 && (module.exports = {
2175
+ AdminChatbot,
1427
2176
  InformedAIClient,
1428
2177
  InformedAIProvider,
1429
2178
  InformedAssistant,
2179
+ WebsiteChatbot,
1430
2180
  useInformedAI,
1431
2181
  useSession
1432
2182
  });