advaisor-chatbot 1.0.0 → 1.2.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.
Binary file
@@ -1176,12 +1176,220 @@ Please report this to https://github.com/markedjs/marked.`, e) {
1176
1176
  var Ft = b.parse;
1177
1177
  var jt = x.lex;
1178
1178
 
1179
+ // src/sidebar.js
1180
+ var ChatSidebar = class extends HTMLElement {
1181
+ constructor() {
1182
+ super();
1183
+ this.attachShadow({ mode: "open" });
1184
+ this.isOpen = false;
1185
+ this.token = null;
1186
+ this.packageId = null;
1187
+ }
1188
+ setConfig(config) {
1189
+ this.token = config.token;
1190
+ this.packageId = config.packageId;
1191
+ }
1192
+ connectedCallback() {
1193
+ this.render();
1194
+ }
1195
+ async toggle() {
1196
+ this.isOpen = !this.isOpen;
1197
+ this.shadowRoot.querySelector(".sidebar").classList.toggle("open");
1198
+ if (this.isOpen) {
1199
+ await this.loadRecentChats();
1200
+ }
1201
+ }
1202
+ async loadRecentChats() {
1203
+ if (!this.token || !this.packageId) return;
1204
+ try {
1205
+ const res = await fetch("https://silicore.ai:2002/customer/recent_chats", {
1206
+ method: "POST",
1207
+ headers: {
1208
+ "Content-Type": "application/json",
1209
+ "Authorization": `Bearer ${this.token}`
1210
+ },
1211
+ body: JSON.stringify({
1212
+ package_id: this.packageId
1213
+ })
1214
+ });
1215
+ const data = await res.json();
1216
+ this.renderChats(data?.body);
1217
+ } catch (err) {
1218
+ console.error("Failed to load recent chats", err);
1219
+ }
1220
+ }
1221
+ renderChats(chats) {
1222
+ const container = this.shadowRoot.getElementById("recent-container");
1223
+ const newChatBtn = this.shadowRoot.getElementById("newChatBtn");
1224
+ newChatBtn.onclick = () => {
1225
+ this.selectedSessionId = null;
1226
+ container.querySelectorAll(".chat-item").forEach((item) => {
1227
+ item.classList.remove("active");
1228
+ });
1229
+ this.dispatchEvent(new CustomEvent("new-chat", {
1230
+ bubbles: true,
1231
+ composed: true
1232
+ }));
1233
+ };
1234
+ if (!chats || chats.length === 0) {
1235
+ container.innerHTML = `<div>No recent chats</div>`;
1236
+ return;
1237
+ }
1238
+ container.innerHTML = chats.map((chat) => {
1239
+ const title = chat?.chat_title || "No title";
1240
+ const shortTitle = title.length > 25 ? title.substring(0, 25) + "..." : title;
1241
+ const activeClass = String(chat.session_id) === String(this.selectedSessionId) ? "active" : "";
1242
+ return `
1243
+ <div class="chat-item ${activeClass}"
1244
+ data-id="${chat.session_id}"
1245
+ title="${title}">
1246
+
1247
+ <div class="chat-title">${shortTitle}</div>
1248
+
1249
+ <div class="chat-date">
1250
+ ${chat?.created_at || ""}
1251
+ </div>
1252
+
1253
+ </div>
1254
+ `;
1255
+ }).join("");
1256
+ container.querySelectorAll(".chat-item").forEach((el) => {
1257
+ el.onclick = () => {
1258
+ const sessionId = el.dataset.id;
1259
+ this.selectedSessionId = String(sessionId);
1260
+ this.dispatchEvent(new CustomEvent("chat-selected", {
1261
+ detail: { sessionId },
1262
+ bubbles: true,
1263
+ composed: true
1264
+ }));
1265
+ this.renderChats(chats);
1266
+ };
1267
+ });
1268
+ }
1269
+ render() {
1270
+ this.shadowRoot.innerHTML = `
1271
+ <style>
1272
+ .sidebar {
1273
+ position: absolute;
1274
+ left: -280px;
1275
+ top: 64.5px;
1276
+ width: 280px;
1277
+ height: calc(100% - 64.5px);
1278
+ background: white;
1279
+ border-right: 1px solid #eee;
1280
+ box-shadow: 2px 0 10px rgba(0,0,0,0.05);
1281
+ transition: left 0.3s ease;
1282
+ padding: 16px;
1283
+ box-sizing: border-box;
1284
+ border-radius: 0 12px 12px 0;
1285
+
1286
+ display: flex;
1287
+ flex-direction: column;
1288
+ }
1289
+
1290
+ .recent-wrapper {
1291
+ flex: 1;
1292
+ overflow-y: auto;
1293
+ margin-top: 10px;
1294
+ }
1295
+
1296
+ #recent-container {
1297
+ display: flex;
1298
+ flex-direction: column;
1299
+ gap: 6px;
1300
+ }
1301
+
1302
+ .sidebar.open {
1303
+ left: 0;
1304
+ }
1305
+
1306
+ h3 {
1307
+ margin-top: 0;
1308
+ font-size: 16px;
1309
+ margin-bottom: 0px;
1310
+ }
1311
+
1312
+ .chat-item {
1313
+ padding: 8px;
1314
+ border-radius: 6px;
1315
+ cursor: pointer;
1316
+ }
1317
+
1318
+ .chat-item:hover {
1319
+ background: #f3f4f6;
1320
+ }
1321
+
1322
+ .chat-title {
1323
+ font-size: 14px;
1324
+ }
1325
+
1326
+ .chat-date {
1327
+ font-size: 12px;
1328
+ color: rgba(0,0,0,0.38);
1329
+ white-space: nowrap;
1330
+ margin-top: 2px;
1331
+ }
1332
+
1333
+ .recent-wrapper::-webkit-scrollbar {
1334
+ width: 6px;
1335
+ }
1336
+
1337
+ .recent-wrapper::-webkit-scrollbar-thumb {
1338
+ background: #ddd;
1339
+ border-radius: 6px;
1340
+ }
1341
+
1342
+ .recent-wrapper::-webkit-scrollbar-thumb:hover {
1343
+ background: #ccc;
1344
+ }
1345
+
1346
+ .new-chat-btn {
1347
+ width: 100%;
1348
+ padding: 8px;
1349
+ border: none;
1350
+ background: var(--primary-color);
1351
+ color: white;
1352
+ border-radius: 6px;
1353
+ cursor: pointer;
1354
+ font-size: 14px;
1355
+ margin-bottom: 8px;
1356
+ }
1357
+
1358
+ .chat-item.active {
1359
+ background: rgba(0,0,0,0.08);
1360
+ font-weight: 500;
1361
+ }
1362
+ </style>
1363
+
1364
+ <div class="sidebar">
1365
+
1366
+ <div class="sidebar-header">
1367
+ <button id="newChatBtn" class="new-chat-btn">+ Start New Chat</button>
1368
+ </div>
1369
+
1370
+ <h3>Recent Chats</h3>
1371
+ <div class="recent-wrapper">
1372
+ <div id="recent-container">
1373
+ <div>Loading...</div>
1374
+ </div>
1375
+ </div>
1376
+ </div>
1377
+
1378
+ `;
1379
+ }
1380
+ };
1381
+ customElements.define("chat-sidebar", ChatSidebar);
1382
+
1383
+ // src/assets/chats.png
1384
+ var chats_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAdElEQVR4nO2UQQqAMAwE8zzrhzzqW9uHjCAKHhrolkYQnXO6A9lQs59WgBkotFOApAiU8IusCA6i5u27gubyBwrq5Y9aEV7OYwKRHCnIwNQjWCNWZ7Xw0YJNeuCgzlvnJygJ0llojEABWEIFd4lFgnMw72QHf/xl9mYG+AwAAAAASUVORK5CYII=";
1385
+
1179
1386
  // src/chatbot.js
1180
1387
  var AdvaisorChatBot = class extends HTMLElement {
1181
1388
  constructor() {
1182
1389
  super();
1183
1390
  this.attachShadow({ mode: "open" });
1184
1391
  this.isOpen = false;
1392
+ this.activeSessionId = null;
1185
1393
  }
1186
1394
  connectedCallback() {
1187
1395
  this.apiEndpoint = this.getAttribute("api_endpoint") || "https://silicore.ai:2002/cds_bookshelves/ask_all_bookshelves";
@@ -1191,6 +1399,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
1191
1399
  }
1192
1400
  render() {
1193
1401
  this.shadowRoot.innerHTML = `
1402
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
1194
1403
  <style>
1195
1404
  :host {
1196
1405
  --primary-color: #EC9588;
@@ -1267,7 +1476,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
1267
1476
  align-items: center;
1268
1477
  }
1269
1478
 
1270
- .close-btn { background: none; border: none; color: white; cursor: pointer; font-size: 18px; }
1479
+ .close-btn { background: none; border: none; color: white; cursor: pointer; font-size: 16px; }
1271
1480
 
1272
1481
  .chat-body {
1273
1482
  flex: 1;
@@ -1362,11 +1571,27 @@ Please report this to https://github.com/markedjs/marked.`, e) {
1362
1571
  cursor: move;
1363
1572
  user-select: none;
1364
1573
  }
1574
+
1575
+ .history-btn {
1576
+ height: 32px;
1577
+ width: 32px;
1578
+ border-radius: 50%;
1579
+ border: none;
1580
+ cursor: pointer;
1581
+ background: rgba(255,255,255,0.0);
1582
+ color: white;
1583
+ font-size: 14px;
1584
+ display: flex;
1585
+ align-items: center;
1586
+ justify-content: center;
1587
+ margin-top: 4px;
1588
+ }
1365
1589
  </style>
1366
1590
 
1367
1591
  <button class="chat-trigger" id="trigger">\u{1F4AC}</button>
1368
1592
 
1369
1593
  <div class="chat-window" id="window">
1594
+ <chat-sidebar id="sidebar"></chat-sidebar>
1370
1595
  <div class="header">
1371
1596
  <div>
1372
1597
  <div style="font-weight: 600;">advAIsor</div>
@@ -1374,8 +1599,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
1374
1599
  </div>
1375
1600
 
1376
1601
  <div style="display:flex; gap:8px;">
1377
- <button class="resize-btn" id="resize">\u26F6</button>
1378
- <button class="close-btn" id="close">\u2715</button>
1602
+ <button title="Chat History" class="history-btn" id="history">
1603
+ <img src="${chats_default}" alt="History"
1604
+ style="width:18px; height:16px;">
1605
+ </button>
1606
+ <button title="Resize" class="resize-btn" id="resize">\u26F6</button>
1607
+ <button title="Close" class="close-btn" id="close">\u2715</button>
1379
1608
  </div>
1380
1609
  </div>
1381
1610
 
@@ -1398,6 +1627,31 @@ Please report this to https://github.com/markedjs/marked.`, e) {
1398
1627
  const sendBtn = this.shadowRoot.getElementById("send");
1399
1628
  const input = this.shadowRoot.getElementById("input");
1400
1629
  const body = this.shadowRoot.getElementById("body");
1630
+ const historyBtn = this.shadowRoot.getElementById("history");
1631
+ const sidebar = this.shadowRoot.getElementById("sidebar");
1632
+ sidebar.addEventListener("new-chat", () => {
1633
+ this.activeSessionId = null;
1634
+ const body2 = this.shadowRoot.getElementById("body");
1635
+ body2.innerHTML = `<div class="message bot">Hi ${this.userName}! How can I help?</div>`;
1636
+ if (sidebar.isOpen) {
1637
+ sidebar.toggle();
1638
+ }
1639
+ });
1640
+ sidebar.setConfig({
1641
+ token: this.token,
1642
+ packageId: 30
1643
+ // or this.packageId if dynamic
1644
+ });
1645
+ historyBtn.onclick = () => {
1646
+ sidebar.toggle();
1647
+ };
1648
+ sidebar.addEventListener("chat-selected", (e) => {
1649
+ const sessionId = e.detail.sessionId;
1650
+ this.loadSession(sessionId);
1651
+ if (sidebar.isOpen) {
1652
+ sidebar.toggle();
1653
+ }
1654
+ });
1401
1655
  trigger.onclick = () => {
1402
1656
  windowEl.style.display = "flex";
1403
1657
  trigger.style.display = "none";
@@ -1448,7 +1702,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
1448
1702
  body: JSON.stringify({
1449
1703
  question: text,
1450
1704
  pdf_name: "All Bookshelves",
1451
- session_id: null,
1705
+ session_id: this.activeSessionId,
1452
1706
  bookshelf_name: "All Bookshelves",
1453
1707
  package_id: 30,
1454
1708
  user_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
@@ -1456,6 +1710,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
1456
1710
  });
1457
1711
  const response = await res.json();
1458
1712
  typingDiv.remove();
1713
+ if (response?.session_id) {
1714
+ this.activeSessionId = response.session_id;
1715
+ }
1459
1716
  const botReply = response?.answer || "No response received.";
1460
1717
  d.setOptions({
1461
1718
  breaks: true,
@@ -1513,6 +1770,59 @@ Please report this to https://github.com/markedjs/marked.`, e) {
1513
1770
  document.addEventListener("mouseup", () => {
1514
1771
  isDragging = false;
1515
1772
  });
1773
+ windowEl.addEventListener("click", (e) => {
1774
+ const sidebar2 = this.shadowRoot.getElementById("sidebar");
1775
+ const historyBtn2 = this.shadowRoot.getElementById("history");
1776
+ if (!sidebar2.isOpen) return;
1777
+ const path = e.composedPath();
1778
+ const clickedInsideSidebar = path.includes(sidebar2);
1779
+ const clickedHistoryBtn = path.includes(historyBtn2);
1780
+ if (!clickedInsideSidebar && !clickedHistoryBtn) {
1781
+ sidebar2.toggle();
1782
+ }
1783
+ });
1784
+ }
1785
+ async loadSession(sessionId) {
1786
+ this.activeSessionId = sessionId;
1787
+ const body = this.shadowRoot.getElementById("body");
1788
+ body.innerHTML = `<div class="message bot">Loading conversation...</div>`;
1789
+ try {
1790
+ const res = await fetch(
1791
+ "https://silicore.ai:2002/customer/user_session_chats",
1792
+ {
1793
+ method: "POST",
1794
+ headers: {
1795
+ "Content-Type": "application/json",
1796
+ "Authorization": `Bearer ${this.token}`
1797
+ },
1798
+ body: JSON.stringify({
1799
+ session_id: sessionId
1800
+ })
1801
+ }
1802
+ );
1803
+ const data = await res.json();
1804
+ const history = data?.body?.chat_history || [];
1805
+ body.innerHTML = "";
1806
+ history.forEach((chat) => {
1807
+ this.renderMessage(chat.question, "user");
1808
+ this.renderMessage(chat.answer, "bot", true);
1809
+ });
1810
+ } catch (err) {
1811
+ console.error("Failed to load session", err);
1812
+ }
1813
+ }
1814
+ renderMessage(content, type, isMarkdown = false) {
1815
+ const body = this.shadowRoot.getElementById("body");
1816
+ const wrapper = document.createElement("div");
1817
+ wrapper.className = `message ${type}`;
1818
+ if (isMarkdown) {
1819
+ const cleanReply = content.replace(/}```/g, "}\n```").replace(/```(\S)/g, "```\n$1");
1820
+ wrapper.innerHTML = d.parse(cleanReply);
1821
+ } else {
1822
+ wrapper.textContent = content;
1823
+ }
1824
+ body.appendChild(wrapper);
1825
+ body.scrollTop = body.scrollHeight;
1516
1826
  }
1517
1827
  };
1518
1828
  customElements.define("advaisor-chatbot", AdvaisorChatBot);
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "advaisor-chatbot",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Embeddable chatbot component",
5
5
  "main": "dist/testchatbot.js",
6
6
  "scripts": {
7
7
  "build": "node build.js"
8
8
  },
9
- "keywords": ["chatbot", "web-component", "ai"],
9
+ "keywords": [
10
+ "chatbot",
11
+ "web-component",
12
+ "ai"
13
+ ],
10
14
  "author": "Echno Technologies",
11
15
  "license": "ISC",
12
16
  "files": [