advaisor-chatbot 1.7.0 → 1.7.1-beta.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/testchatbot.js +344 -216
- package/package.json +1 -1
package/dist/testchatbot.js
CHANGED
|
@@ -1390,6 +1390,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1390
1390
|
this.attachShadow({ mode: "open" });
|
|
1391
1391
|
this.isOpen = false;
|
|
1392
1392
|
this.activeSessionId = null;
|
|
1393
|
+
this.abortController = null;
|
|
1393
1394
|
}
|
|
1394
1395
|
connectedCallback() {
|
|
1395
1396
|
this.apiEndpoint = this.getAttribute("api_endpoint") || "https://silicore.ai:2002/cds_bookshelves/ask_all_bookshelves";
|
|
@@ -1399,216 +1400,238 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1399
1400
|
}
|
|
1400
1401
|
render() {
|
|
1401
1402
|
this.shadowRoot.innerHTML = `
|
|
1402
|
-
<
|
|
1403
|
-
|
|
1404
|
-
:
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
.chat-trigger {
|
|
1412
|
-
position: fixed;
|
|
1413
|
-
bottom: 20px;
|
|
1414
|
-
right: 20px;
|
|
1415
|
-
z-index: 9999;
|
|
1416
|
-
height: 56px;
|
|
1417
|
-
width: 56px;
|
|
1418
|
-
border-radius: 50%;
|
|
1419
|
-
background: var(--primary-color);
|
|
1420
|
-
color: white;
|
|
1421
|
-
display: flex;
|
|
1422
|
-
align-items: center;
|
|
1423
|
-
justify-content: center;
|
|
1424
|
-
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
1425
|
-
font-size: 24px;
|
|
1426
|
-
cursor: pointer;
|
|
1427
|
-
transition: transform 0.2s;
|
|
1428
|
-
border: none;
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
.chat-trigger:hover { transform: scale(1.05); }
|
|
1432
|
-
|
|
1433
|
-
.chat-window {
|
|
1434
|
-
position: fixed;
|
|
1435
|
-
bottom: 20px;
|
|
1436
|
-
right: 20px;
|
|
1437
|
-
z-index: 10000;
|
|
1438
|
-
|
|
1439
|
-
display: none;
|
|
1440
|
-
flex-direction: column;
|
|
1441
|
-
|
|
1442
|
-
background: #ffffff;
|
|
1443
|
-
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
|
1403
|
+
<style>
|
|
1404
|
+
:host {
|
|
1405
|
+
--primary-color: #EC9588;
|
|
1406
|
+
--user-bubble: #f29b8c;
|
|
1407
|
+
--bot-bubble: #e5e7eb;
|
|
1408
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
1409
|
+
}
|
|
1444
1410
|
|
|
1445
|
-
|
|
1446
|
-
|
|
1411
|
+
.chat-trigger {
|
|
1412
|
+
position: fixed;
|
|
1413
|
+
bottom: 20px;
|
|
1414
|
+
right: 20px;
|
|
1415
|
+
z-index: 9999;
|
|
1416
|
+
height: 56px;
|
|
1417
|
+
width: 56px;
|
|
1418
|
+
border-radius: 50%;
|
|
1419
|
+
background: var(--primary-color);
|
|
1420
|
+
color: white;
|
|
1421
|
+
display: flex;
|
|
1422
|
+
align-items: center;
|
|
1423
|
+
justify-content: center;
|
|
1424
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
1425
|
+
font-size: 24px;
|
|
1426
|
+
cursor: pointer;
|
|
1427
|
+
transition: transform 0.2s;
|
|
1428
|
+
border: none;
|
|
1429
|
+
}
|
|
1447
1430
|
|
|
1448
|
-
|
|
1449
|
-
overflow: hidden;
|
|
1431
|
+
.chat-trigger:hover { transform: scale(1.05); }
|
|
1450
1432
|
|
|
1451
|
-
|
|
1433
|
+
.chat-window {
|
|
1434
|
+
position: fixed;
|
|
1435
|
+
bottom: 20px;
|
|
1436
|
+
right: 20px;
|
|
1437
|
+
z-index: 10000;
|
|
1438
|
+
display: none;
|
|
1439
|
+
flex-direction: column;
|
|
1440
|
+
background: #ffffff;
|
|
1441
|
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
|
1442
|
+
width: min(30vw, 420px);
|
|
1443
|
+
height: 90vh;
|
|
1444
|
+
border-radius: 16px;
|
|
1445
|
+
overflow: hidden;
|
|
1446
|
+
transition: all 0.25s ease;
|
|
1447
|
+
resize: both;
|
|
1448
|
+
min-width: 300px;
|
|
1449
|
+
min-height: 450px;
|
|
1450
|
+
}
|
|
1452
1451
|
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1452
|
+
.chat-window.expanded {
|
|
1453
|
+
width: min(700px, 95vw);
|
|
1454
|
+
height: 90vh;
|
|
1455
|
+
}
|
|
1457
1456
|
|
|
1458
|
-
|
|
1457
|
+
@media (max-width: 768px) {
|
|
1458
|
+
.chat-window,
|
|
1459
1459
|
.chat-window.expanded {
|
|
1460
|
-
width:
|
|
1461
|
-
|
|
1462
|
-
|
|
1460
|
+
width: 100vw !important;
|
|
1461
|
+
max-width: 100vw !important;
|
|
1462
|
+
height: 85vh !important;
|
|
1463
|
+
bottom: 0;
|
|
1464
|
+
right: 0;
|
|
1465
|
+
border-radius: 16px 16px 0 0;
|
|
1463
1466
|
}
|
|
1467
|
+
}
|
|
1464
1468
|
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
|
|
1479
|
-
.typing {
|
|
1480
|
-
display: flex;
|
|
1481
|
-
gap: 4px;
|
|
1482
|
-
align-items: center;
|
|
1483
|
-
}
|
|
1469
|
+
.header {
|
|
1470
|
+
background: var(--primary-color);
|
|
1471
|
+
padding: 12px 16px;
|
|
1472
|
+
color: white;
|
|
1473
|
+
display: flex;
|
|
1474
|
+
justify-content: space-between;
|
|
1475
|
+
align-items: center;
|
|
1476
|
+
cursor: move;
|
|
1477
|
+
user-select: none;
|
|
1478
|
+
touch-action: none;
|
|
1479
|
+
}
|
|
1484
1480
|
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1481
|
+
.close-btn, .resize-btn, .history-btn {
|
|
1482
|
+
background: none;
|
|
1483
|
+
border: none;
|
|
1484
|
+
color: white;
|
|
1485
|
+
cursor: pointer;
|
|
1486
|
+
font-size: 16px;
|
|
1487
|
+
}
|
|
1490
1488
|
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1489
|
+
.history-btn {
|
|
1490
|
+
height: 32px;
|
|
1491
|
+
width: 32px;
|
|
1492
|
+
border-radius: 50%;
|
|
1493
|
+
font-size: 14px;
|
|
1494
|
+
display: flex;
|
|
1495
|
+
align-items: center;
|
|
1496
|
+
justify-content: center;
|
|
1497
|
+
margin-top: 4px;
|
|
1498
|
+
}
|
|
1495
1499
|
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1500
|
+
.chat-body {
|
|
1501
|
+
flex: 1;
|
|
1502
|
+
padding: 16px;
|
|
1503
|
+
overflow-y: auto;
|
|
1504
|
+
background: #f9fafb;
|
|
1505
|
+
display: flex;
|
|
1506
|
+
flex-direction: column;
|
|
1507
|
+
gap: 12px;
|
|
1508
|
+
}
|
|
1501
1509
|
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
+
/* Base message styles */
|
|
1511
|
+
.message {
|
|
1512
|
+
max-width: 75%;
|
|
1513
|
+
font-size: 15px;
|
|
1514
|
+
line-height: 1.5;
|
|
1515
|
+
word-wrap: break-word;
|
|
1516
|
+
overflow-wrap: break-word;
|
|
1517
|
+
}
|
|
1510
1518
|
|
|
1511
|
-
|
|
1519
|
+
.message.bot {
|
|
1520
|
+
align-self: flex-start;
|
|
1521
|
+
display: flex;
|
|
1522
|
+
flex-direction: column;
|
|
1523
|
+
align-items: flex-start;
|
|
1524
|
+
gap: 4px;
|
|
1525
|
+
}
|
|
1512
1526
|
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
}
|
|
1527
|
+
.message.user {
|
|
1528
|
+
align-self: flex-end;
|
|
1529
|
+
background: var(--user-bubble);
|
|
1530
|
+
color: white;
|
|
1531
|
+
padding: 8px 16px;
|
|
1532
|
+
border-radius: 18px 18px 4px 18px;
|
|
1533
|
+
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
|
|
1534
|
+
}
|
|
1522
1535
|
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1536
|
+
/* Bot message content bubble */
|
|
1537
|
+
.message.bot .content {
|
|
1538
|
+
background: var(--bot-bubble);
|
|
1539
|
+
color: #1f2937;
|
|
1540
|
+
padding: 8px 16px;
|
|
1541
|
+
border-radius: 18px 18px 18px 4px;
|
|
1542
|
+
word-wrap: break-word;
|
|
1543
|
+
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
|
|
1544
|
+
}
|
|
1530
1545
|
|
|
1531
|
-
|
|
1532
|
-
|
|
1546
|
+
.message.bot .content p {
|
|
1547
|
+
margin: 4px 0;
|
|
1548
|
+
}
|
|
1533
1549
|
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
padding: 12px;
|
|
1537
|
-
display: flex;
|
|
1538
|
-
gap: 8px;
|
|
1539
|
-
}
|
|
1550
|
+
.message.bot .content p:first-child { margin-top: 0; }
|
|
1551
|
+
.message.bot .content p:last-child { margin-bottom: 0; }
|
|
1540
1552
|
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
padding: 8px 12px;
|
|
1546
|
-
outline: none;
|
|
1547
|
-
}
|
|
1553
|
+
.message pre, .message code {
|
|
1554
|
+
white-space: pre-wrap;
|
|
1555
|
+
word-break: break-word;
|
|
1556
|
+
}
|
|
1548
1557
|
|
|
1549
|
-
|
|
1558
|
+
/* Status message (outside bubble) */
|
|
1559
|
+
.status-message {
|
|
1560
|
+
font-style: italic;
|
|
1561
|
+
color: #888;
|
|
1562
|
+
font-size: 0.85em;
|
|
1563
|
+
padding: 4px 12px;
|
|
1564
|
+
margin: 2px 0;
|
|
1565
|
+
background: transparent;
|
|
1566
|
+
border-radius: 12px;
|
|
1567
|
+
display: inline-block;
|
|
1568
|
+
max-width: 80%;
|
|
1569
|
+
}
|
|
1550
1570
|
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1571
|
+
/* Typing indicator as message bubble */
|
|
1572
|
+
.typing-indicator {
|
|
1573
|
+
display: inline-flex;
|
|
1574
|
+
align-items: center;
|
|
1575
|
+
gap: 4px;
|
|
1576
|
+
padding: 8px 16px;
|
|
1577
|
+
background: var(--bot-bubble);
|
|
1578
|
+
border-radius: 18px 18px 18px 4px;
|
|
1579
|
+
margin: 4px 0;
|
|
1580
|
+
max-width: fit-content;
|
|
1581
|
+
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
|
|
1582
|
+
}
|
|
1560
1583
|
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1584
|
+
.typing-indicator span {
|
|
1585
|
+
width: 8px;
|
|
1586
|
+
height: 8px;
|
|
1587
|
+
background: #666;
|
|
1588
|
+
border-radius: 50%;
|
|
1589
|
+
display: inline-block;
|
|
1590
|
+
animation: typingBounce 1.4s infinite ease-in-out both;
|
|
1591
|
+
}
|
|
1568
1592
|
|
|
1593
|
+
.typing-indicator span:nth-child(1) { animation-delay: -0.32s; }
|
|
1594
|
+
.typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
|
|
1595
|
+
.typing-indicator span:nth-child(3) { animation-delay: 0; }
|
|
1569
1596
|
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
border-radius: 50%;
|
|
1575
|
-
animation: blink 1.4s infinite;
|
|
1576
|
-
}
|
|
1597
|
+
@keyframes typingBounce {
|
|
1598
|
+
0%, 80%, 100% { transform: scale(0.6); opacity: 0.6; }
|
|
1599
|
+
40% { transform: scale(1); opacity: 1; }
|
|
1600
|
+
}
|
|
1577
1601
|
|
|
1578
|
-
|
|
1579
|
-
|
|
1602
|
+
.input-area {
|
|
1603
|
+
border-top: 1px solid #e5e7eb;
|
|
1604
|
+
padding: 12px;
|
|
1605
|
+
display: flex;
|
|
1606
|
+
gap: 8px;
|
|
1607
|
+
}
|
|
1580
1608
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1609
|
+
input {
|
|
1610
|
+
flex: 1;
|
|
1611
|
+
border: 1px solid #e5e7eb;
|
|
1612
|
+
border-radius: 6px;
|
|
1613
|
+
padding: 8px 12px;
|
|
1614
|
+
outline: none;
|
|
1615
|
+
}
|
|
1585
1616
|
|
|
1586
|
-
|
|
1587
|
-
opacity: 0.6;
|
|
1588
|
-
cursor: not-allowed;
|
|
1589
|
-
}
|
|
1617
|
+
input:focus { border-color: var(--primary-color); }
|
|
1590
1618
|
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1619
|
+
.send-btn {
|
|
1620
|
+
background: var(--user-bubble);
|
|
1621
|
+
color: white;
|
|
1622
|
+
border: none;
|
|
1623
|
+
padding: 0 16px;
|
|
1624
|
+
border-radius: 6px;
|
|
1625
|
+
cursor: pointer;
|
|
1626
|
+
}
|
|
1596
1627
|
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
color: white;
|
|
1605
|
-
font-size: 14px;
|
|
1606
|
-
display: flex;
|
|
1607
|
-
align-items: center;
|
|
1608
|
-
justify-content: center;
|
|
1609
|
-
margin-top: 4px;
|
|
1610
|
-
}
|
|
1611
|
-
</style>
|
|
1628
|
+
.send-btn:disabled {
|
|
1629
|
+
opacity: 0.6;
|
|
1630
|
+
cursor: not-allowed;
|
|
1631
|
+
}
|
|
1632
|
+
</style>
|
|
1633
|
+
|
|
1634
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
|
|
1612
1635
|
|
|
1613
1636
|
<button class="chat-trigger" id="trigger">\u{1F4AC}</button>
|
|
1614
1637
|
|
|
@@ -1652,6 +1675,10 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1652
1675
|
const historyBtn = this.shadowRoot.getElementById("history");
|
|
1653
1676
|
const sidebar = this.shadowRoot.getElementById("sidebar");
|
|
1654
1677
|
sidebar.addEventListener("new-chat", () => {
|
|
1678
|
+
if (this.abortController) {
|
|
1679
|
+
this.abortController.abort();
|
|
1680
|
+
this.abortController = null;
|
|
1681
|
+
}
|
|
1655
1682
|
this.activeSessionId = null;
|
|
1656
1683
|
const body2 = this.shadowRoot.getElementById("body");
|
|
1657
1684
|
body2.innerHTML = `<div class="message bot">Hi ${this.userName}! How can I help?</div>`;
|
|
@@ -1680,6 +1707,10 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1680
1707
|
body.scrollTop = body.scrollHeight;
|
|
1681
1708
|
};
|
|
1682
1709
|
closeBtn.onclick = () => {
|
|
1710
|
+
if (this.abortController) {
|
|
1711
|
+
this.abortController.abort();
|
|
1712
|
+
this.abortController = null;
|
|
1713
|
+
}
|
|
1683
1714
|
windowEl.style.display = "none";
|
|
1684
1715
|
trigger.style.display = "flex";
|
|
1685
1716
|
};
|
|
@@ -1693,6 +1724,10 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1693
1724
|
const sendMessage = async () => {
|
|
1694
1725
|
const text = input.value.trim();
|
|
1695
1726
|
if (!text) return;
|
|
1727
|
+
if (this.abortController) {
|
|
1728
|
+
this.abortController.abort();
|
|
1729
|
+
this.abortController = null;
|
|
1730
|
+
}
|
|
1696
1731
|
input.disabled = true;
|
|
1697
1732
|
sendBtn.disabled = true;
|
|
1698
1733
|
const userMsg = document.createElement("div");
|
|
@@ -1701,21 +1736,39 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1701
1736
|
body.appendChild(userMsg);
|
|
1702
1737
|
input.value = "";
|
|
1703
1738
|
body.scrollTop = body.scrollHeight;
|
|
1739
|
+
const botMessageContainer = document.createElement("div");
|
|
1740
|
+
botMessageContainer.className = "message bot";
|
|
1741
|
+
const contentDiv = document.createElement("div");
|
|
1742
|
+
contentDiv.className = "content";
|
|
1743
|
+
contentDiv.id = "answer-content";
|
|
1704
1744
|
const typingDiv = document.createElement("div");
|
|
1705
|
-
typingDiv.className = "
|
|
1745
|
+
typingDiv.className = "typing-indicator";
|
|
1706
1746
|
typingDiv.id = "typing-indicator";
|
|
1707
1747
|
typingDiv.innerHTML = `
|
|
1708
|
-
<
|
|
1709
|
-
<span></span><span></span><span></span>
|
|
1710
|
-
</div>
|
|
1748
|
+
<span></span><span></span><span></span>
|
|
1711
1749
|
`;
|
|
1712
|
-
|
|
1750
|
+
const statusDiv = document.createElement("div");
|
|
1751
|
+
statusDiv.className = "status-message";
|
|
1752
|
+
statusDiv.id = "status-message";
|
|
1753
|
+
botMessageContainer.appendChild(contentDiv);
|
|
1754
|
+
botMessageContainer.appendChild(typingDiv);
|
|
1755
|
+
botMessageContainer.appendChild(statusDiv);
|
|
1756
|
+
body.appendChild(botMessageContainer);
|
|
1713
1757
|
body.scrollTop = body.scrollHeight;
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1758
|
+
const timeoutId = setTimeout(() => {
|
|
1759
|
+
if (this.abortController) {
|
|
1760
|
+
this.abortController.abort();
|
|
1761
|
+
this.abortController = null;
|
|
1762
|
+
this.showErrorMessage(body, "Request timed out after 30 seconds. Please try again.");
|
|
1763
|
+
botMessageContainer.remove();
|
|
1764
|
+
input.disabled = false;
|
|
1765
|
+
sendBtn.disabled = false;
|
|
1766
|
+
input.focus();
|
|
1767
|
+
}
|
|
1768
|
+
}, 3e4);
|
|
1717
1769
|
try {
|
|
1718
|
-
|
|
1770
|
+
this.abortController = new AbortController();
|
|
1771
|
+
const response = await fetch(this.apiEndpoint, {
|
|
1719
1772
|
method: "POST",
|
|
1720
1773
|
headers: {
|
|
1721
1774
|
"Content-Type": "application/json",
|
|
@@ -1728,36 +1781,90 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1728
1781
|
bookshelf_name: "All Bookshelves",
|
|
1729
1782
|
package_id: 30,
|
|
1730
1783
|
user_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
1731
|
-
})
|
|
1784
|
+
}),
|
|
1785
|
+
signal: this.abortController.signal
|
|
1732
1786
|
});
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1787
|
+
clearTimeout(timeoutId);
|
|
1788
|
+
if (!response.ok) {
|
|
1789
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
1790
|
+
}
|
|
1791
|
+
const reader = response.body.getReader();
|
|
1792
|
+
const decoder = new TextDecoder("utf-8");
|
|
1793
|
+
let buffer = "";
|
|
1794
|
+
let accumulatedAnswer = "";
|
|
1795
|
+
let lastStatusMessage = "";
|
|
1796
|
+
while (true) {
|
|
1797
|
+
const { value, done } = await reader.read();
|
|
1798
|
+
if (done) break;
|
|
1799
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1800
|
+
const events = buffer.split("\n\n");
|
|
1801
|
+
buffer = events.pop();
|
|
1802
|
+
for (const event of events) {
|
|
1803
|
+
const match = event.match(/^data: (.+)$/m);
|
|
1804
|
+
if (!match) continue;
|
|
1805
|
+
const jsonStr = match[1].trim();
|
|
1806
|
+
try {
|
|
1807
|
+
const data = JSON.parse(jsonStr);
|
|
1808
|
+
if (data.type === "message") {
|
|
1809
|
+
lastStatusMessage = data.text;
|
|
1810
|
+
statusDiv.textContent = data.text;
|
|
1811
|
+
typingDiv.style.display = "none";
|
|
1812
|
+
}
|
|
1813
|
+
if (data.type === "answer") {
|
|
1814
|
+
typingDiv.style.display = "none";
|
|
1815
|
+
if (data.session_id) {
|
|
1816
|
+
this.activeSessionId = data.session_id;
|
|
1817
|
+
}
|
|
1818
|
+
if (accumulatedAnswer && !accumulatedAnswer.endsWith("\n\n")) {
|
|
1819
|
+
accumulatedAnswer += "\n\n";
|
|
1820
|
+
}
|
|
1821
|
+
const newText = data.text;
|
|
1822
|
+
accumulatedAnswer += newText;
|
|
1823
|
+
const words = newText.split(" ");
|
|
1824
|
+
let currentDisplayText = accumulatedAnswer.substring(0, accumulatedAnswer.length - newText.length);
|
|
1825
|
+
if (currentDisplayText) {
|
|
1826
|
+
const cleanExisting = this.fixMarkdown(currentDisplayText);
|
|
1827
|
+
const htmlExisting = d.parse(cleanExisting);
|
|
1828
|
+
contentDiv.innerHTML = htmlExisting;
|
|
1829
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1830
|
+
}
|
|
1831
|
+
for (let i = 0; i < words.length; i++) {
|
|
1832
|
+
currentDisplayText += (i > 0 || currentDisplayText ? " " : "") + words[i];
|
|
1833
|
+
const cleanReply = this.fixMarkdown(currentDisplayText + (i < words.length - 1 ? " ..." : ""));
|
|
1834
|
+
const htmlReply = d.parse(cleanReply);
|
|
1835
|
+
contentDiv.innerHTML = htmlReply;
|
|
1836
|
+
if (i < words.length - 1) {
|
|
1837
|
+
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
if (data.is_last) {
|
|
1842
|
+
statusDiv.remove();
|
|
1843
|
+
typingDiv.style.display = "none";
|
|
1844
|
+
const cleanReply = this.fixMarkdown(accumulatedAnswer);
|
|
1845
|
+
const htmlReply = d.parse(cleanReply);
|
|
1846
|
+
contentDiv.innerHTML = htmlReply;
|
|
1847
|
+
break;
|
|
1848
|
+
}
|
|
1849
|
+
} catch (parseError) {
|
|
1850
|
+
console.error("Error parsing JSON:", jsonStr, parseError);
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1737
1853
|
}
|
|
1738
|
-
const botReply = response?.answer || "No response received.";
|
|
1739
|
-
d.setOptions({
|
|
1740
|
-
breaks: true,
|
|
1741
|
-
gfm: true
|
|
1742
|
-
});
|
|
1743
|
-
const cleanReply = fixMarkdown(botReply);
|
|
1744
|
-
const htmlReply = d.parse(cleanReply);
|
|
1745
|
-
const wrapper = document.createElement("div");
|
|
1746
|
-
wrapper.className = "message bot";
|
|
1747
|
-
wrapper.innerHTML = htmlReply;
|
|
1748
|
-
body.appendChild(wrapper);
|
|
1749
|
-
body.scrollTop = body.scrollHeight;
|
|
1750
1854
|
} catch (error) {
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1855
|
+
clearTimeout(timeoutId);
|
|
1856
|
+
botMessageContainer.remove();
|
|
1857
|
+
if (error.name === "AbortError") {
|
|
1858
|
+
console.log("Stream aborted");
|
|
1859
|
+
} else {
|
|
1860
|
+
this.showErrorMessage(body, "Sorry, something went wrong. Please try again.");
|
|
1861
|
+
console.error("Stream error:", error);
|
|
1862
|
+
}
|
|
1757
1863
|
} finally {
|
|
1758
1864
|
input.disabled = false;
|
|
1759
1865
|
sendBtn.disabled = false;
|
|
1760
1866
|
input.focus();
|
|
1867
|
+
this.abortController = null;
|
|
1761
1868
|
}
|
|
1762
1869
|
};
|
|
1763
1870
|
sendBtn.onclick = sendMessage;
|
|
@@ -1824,7 +1931,21 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1824
1931
|
}
|
|
1825
1932
|
});
|
|
1826
1933
|
}
|
|
1934
|
+
fixMarkdown(text) {
|
|
1935
|
+
return text.replace(/}```/g, "}\n```").replace(/```(\S)/g, "```\n$1");
|
|
1936
|
+
}
|
|
1937
|
+
showErrorMessage(body, message) {
|
|
1938
|
+
const errorMsg = document.createElement("div");
|
|
1939
|
+
errorMsg.className = "message bot error-message";
|
|
1940
|
+
errorMsg.textContent = message;
|
|
1941
|
+
body.appendChild(errorMsg);
|
|
1942
|
+
body.scrollTop = body.scrollHeight;
|
|
1943
|
+
}
|
|
1827
1944
|
async loadSession(sessionId) {
|
|
1945
|
+
if (this.abortController) {
|
|
1946
|
+
this.abortController.abort();
|
|
1947
|
+
this.abortController = null;
|
|
1948
|
+
}
|
|
1828
1949
|
this.activeSessionId = sessionId;
|
|
1829
1950
|
const body = this.shadowRoot.getElementById("body");
|
|
1830
1951
|
body.innerHTML = `<div class="message bot">Loading conversation...</div>`;
|
|
@@ -1842,6 +1963,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1842
1963
|
})
|
|
1843
1964
|
}
|
|
1844
1965
|
);
|
|
1966
|
+
if (!res.ok) {
|
|
1967
|
+
throw new Error(`HTTP error! status: ${res.status}`);
|
|
1968
|
+
}
|
|
1845
1969
|
const data = await res.json();
|
|
1846
1970
|
const history = data?.body?.chat_history || [];
|
|
1847
1971
|
body.innerHTML = "";
|
|
@@ -1851,6 +1975,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1851
1975
|
});
|
|
1852
1976
|
} catch (err) {
|
|
1853
1977
|
console.error("Failed to load session", err);
|
|
1978
|
+
body.innerHTML = `<div class="message bot error-message">Failed to load conversation. Please try again.</div>`;
|
|
1854
1979
|
}
|
|
1855
1980
|
}
|
|
1856
1981
|
renderMessage(content, type, isMarkdown = false) {
|
|
@@ -1858,8 +1983,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
1858
1983
|
const wrapper = document.createElement("div");
|
|
1859
1984
|
wrapper.className = `message ${type}`;
|
|
1860
1985
|
if (isMarkdown) {
|
|
1861
|
-
const cleanReply =
|
|
1862
|
-
|
|
1986
|
+
const cleanReply = this.fixMarkdown(content);
|
|
1987
|
+
const contentDiv = document.createElement("div");
|
|
1988
|
+
contentDiv.className = "content";
|
|
1989
|
+
contentDiv.innerHTML = d.parse(cleanReply);
|
|
1990
|
+
wrapper.appendChild(contentDiv);
|
|
1863
1991
|
} else {
|
|
1864
1992
|
wrapper.textContent = content;
|
|
1865
1993
|
}
|