@alan-ai/alan-sdk-web 1.8.92 → 1.8.94

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/alan_lib.js CHANGED
@@ -98166,10 +98166,14 @@
98166
98166
  }
98167
98167
  },
98168
98168
  textChat: {
98169
+ autocomplete: {
98170
+ enabled: false
98171
+ },
98169
98172
  available: false,
98170
98173
  expanded: false,
98171
98174
  inlined: false,
98172
98175
  options: null,
98176
+ maxCharactersCount: 2e4,
98173
98177
  loaderTimeoutMs: 18e5,
98174
98178
  defaults: {
98175
98179
  minChatWidth: 250,
@@ -98179,7 +98183,8 @@
98179
98183
  textareaLineHeight: 1.6,
98180
98184
  defaultSvgIconSize: 24
98181
98185
  }
98182
- }
98186
+ },
98187
+ socketMessages: []
98183
98188
  };
98184
98189
 
98185
98190
  // alan_btn/src/assets/chatIcons.ts
@@ -98432,7 +98437,8 @@
98432
98437
  let isNew = true;
98433
98438
  let replaceLoader = false;
98434
98439
  let msgInd = null;
98435
- let updateResponse = false;
98440
+ let updateExistingResponse = false;
98441
+ let skipUpdating = false;
98436
98442
  if (msg.type === "connection-separator") {
98437
98443
  messages.push({ ...msg });
98438
98444
  return {
@@ -98446,6 +98452,9 @@
98446
98452
  var loadingMsgReqId = messages.findIndex((m) => {
98447
98453
  return m.type === "response" && m.name === "loading" && msgReqId && (m?.ctx?.reqId || m.reqId) === msgReqId;
98448
98454
  });
98455
+ var existingMsgReqId = messages.findIndex((m) => {
98456
+ return m.type === "response" && msgReqId && (m?.ctx?.reqId || m.reqId) === msgReqId;
98457
+ });
98449
98458
  if (loadingMsgReqId > -1) {
98450
98459
  msgInd = loadingMsgReqId;
98451
98460
  if (msg.queryProgress) {
@@ -98459,7 +98468,16 @@
98459
98468
  } else {
98460
98469
  messages[msgInd] = { ...msg };
98461
98470
  }
98471
+ if (isFinalMessage(messages[msgInd])) {
98472
+ skipUpdating = true;
98473
+ }
98474
+ isNew = false;
98475
+ } else if (existingMsgReqId > -1) {
98462
98476
  isNew = false;
98477
+ msgInd = existingMsgReqId;
98478
+ if (isFinalMessage(messages[msgInd])) {
98479
+ skipUpdating = true;
98480
+ }
98463
98481
  }
98464
98482
  }
98465
98483
  if (msg.type === "response" && msg.name === "text") {
@@ -98478,7 +98496,7 @@
98478
98496
  const hasUnfinalizedResponses = unfinalizeMsgInd !== -1;
98479
98497
  if (hasUnfinalizedResponses) {
98480
98498
  msgInd = unfinalizeMsgInd;
98481
- updateResponse = true;
98499
+ updateExistingResponse = true;
98482
98500
  replaceLoader = false;
98483
98501
  isNew = false;
98484
98502
  mergeProgressiveMessages(messages, msgInd, msg);
@@ -98488,7 +98506,7 @@
98488
98506
  });
98489
98507
  if (lastResponseMsgInd > -1) {
98490
98508
  msgInd = lastResponseMsgInd;
98491
- updateResponse = true;
98509
+ updateExistingResponse = true;
98492
98510
  replaceLoader = false;
98493
98511
  isNew = false;
98494
98512
  mergeProgressiveMessages(messages, msgInd, msg);
@@ -98510,14 +98528,16 @@
98510
98528
  isNew,
98511
98529
  msgInd: messages.length - 1,
98512
98530
  replaceLoader,
98513
- updateResponse
98531
+ updateExistingResponse,
98532
+ skipUpdating
98514
98533
  };
98515
98534
  }
98516
98535
  return {
98517
98536
  isNew,
98518
- updateResponse,
98537
+ updateExistingResponse,
98519
98538
  replaceLoader,
98520
- msgInd
98539
+ msgInd,
98540
+ skipUpdating
98521
98541
  };
98522
98542
  }
98523
98543
 
@@ -98801,6 +98821,9 @@
98801
98821
  userAgent: ${navigator.userAgent}
98802
98822
  `;
98803
98823
  }
98824
+ function getSocketMessages() {
98825
+ return uiState.socketMessages;
98826
+ }
98804
98827
 
98805
98828
  // alan_btn/src/textChat/helpers/adjustIFrameSize.ts
98806
98829
  function adjustIFrameSize(iframeMsgData) {
@@ -98890,7 +98913,7 @@
98890
98913
  function broadcastThemeToIframes() {
98891
98914
  let theme;
98892
98915
  try {
98893
- theme = uiState?.currentTheme;
98916
+ theme = uiState?.currentTheme || window["alanCurrentTheme"];
98894
98917
  } catch (error) {
98895
98918
  theme = window["alanCurrentTheme"];
98896
98919
  }
@@ -99749,9 +99772,22 @@
99749
99772
  background-color: ${textChatOptions?.footer?.backgroundColor || "#DAEBFF"};
99750
99773
  position: relative;
99751
99774
  display: flex;
99775
+ flex-direction: column;
99752
99776
  flex-shrink: 0;
99753
99777
  padding: ${getPaddingProp(footerTopPadding, footerRightPadding, footerBottomPadding, footerLeftPadding)};
99754
99778
  }`;
99779
+ keyFrames += getStyleSheetMarker() + `.alan-btn__chat-footer-info {
99780
+ color: ${textChatOptions?.textarea?.color || `#171717`} ;
99781
+ }`;
99782
+ keyFrames += getStyleSheetMarker() + `.alan-btn__chat-footer-err {
99783
+ color: ${textChatOptions?.textarea?.color || `#171717`} ;
99784
+ position: absolute;
99785
+ top: 4px;
99786
+ left: 0;
99787
+ width: 100%;
99788
+ font-size: 12px;
99789
+ text-align: center;
99790
+ }`;
99755
99791
  keyFrames += getStyleSheetMarker() + `.alan-btn__chat-textarea-holder-outer-content {
99756
99792
  width: 100%;
99757
99793
  height: 100%;
@@ -100136,6 +100172,32 @@
100136
100172
  display: ${withGradientForFooter ? "block" : "none"};
100137
100173
  left:0;
100138
100174
  }`;
100175
+ keyFrames += getStyleSheetMarker() + `.alan-btn__chat-textarea-autocomplete {
100176
+ width: calc(100% - ${calculatedTextareaRightPadding}px);
100177
+ color: ${textChatOptions?.textarea?.color || `#171717`} ;
100178
+ overflow: hidden;
100179
+ outline: none;
100180
+ resize: none;
100181
+ background: transparent;
100182
+ border: none;
100183
+ -webkit-appearance: none;
100184
+ font-size: ${getTextAreaFontSize(isMobile(), textChatOptions?.textarea?.fontSize || defaultChatTextareaFontSize)}px;
100185
+ line-height: ${chatTextareaLineHieght};
100186
+ text-align: left;
100187
+ padding: ${getPaddingProp(textareaTopPadding, 0, textareaBottomPadding, textareaLeftPadding)};
100188
+ margin: 0px!important;
100189
+ -webkit-user-select: text;
100190
+ -khtml-user-select: text;
100191
+ -moz-user-select: text;
100192
+ -ms-user-select: text;
100193
+ user-select: text;
100194
+ transition: opacity 300ms ease-in-out;
100195
+ pointer-events: none;
100196
+ position: absolute;
100197
+ top: 0;
100198
+ left: 0;
100199
+ opacity: 0.5;
100200
+ }`;
100139
100201
  keyFrames += getStyleSheetMarker() + `.alan-btn__chat-textarea {
100140
100202
  width: 100%;
100141
100203
  color: ${textChatOptions?.textarea?.color || `#171717`} ;
@@ -100335,7 +100397,7 @@
100335
100397
  color: ${textChatOptions?.notifications?.color || `#ffffff`};
100336
100398
  border-radius: 50%;
100337
100399
  z-index: ${uiState.btn.zIndex + 1};
100338
- display: flex;
100400
+ display: ${window._alanBtnState?.textChat?.notifications?.enabled ? "flex" : "none"};
100339
100401
  flex-direction: column;
100340
100402
  align-items: center;
100341
100403
  justify-content: center;
@@ -101409,7 +101471,7 @@
101409
101471
  function sanitizeCustomTags(str) {
101410
101472
  let result = str;
101411
101473
  for (const [tag, replacement] of Object.entries(ESCAPE_CUSTOM_TAG_MAP)) {
101412
- const tagRegex = new RegExp(tag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
101474
+ const tagRegex = new RegExp("\b" + tag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "\b", "g");
101413
101475
  result = result.replace(tagRegex, replacement);
101414
101476
  }
101415
101477
  return result;
@@ -102549,9 +102611,49 @@ code.hljs {
102549
102611
 
102550
102612
  // alan_btn/src/autosync.ts
102551
102613
  var html2canvas = require_html2canvas();
102614
+ var SEND_PAGE_STATE_THROTTLE_MS = 2e3;
102552
102615
  var popstateListenerWasAdded = false;
102553
- var prevPageContent = "";
102616
+ var requestCounter = 0;
102617
+ var lastSendPageStateTime = 0;
102618
+ var pendingSync = false;
102619
+ var pendingSyncTimeout = null;
102554
102620
  var ALAN_BTN_PAGE_SYNC_EVENT = "alan-btn__page-sync";
102621
+ var prevPageState = {
102622
+ contentHash: "",
102623
+ scrollX: 0,
102624
+ scrollY: 0,
102625
+ viewportWidth: 0,
102626
+ viewportHeight: 0
102627
+ };
102628
+ function generateContentHash(content) {
102629
+ let hash = 0;
102630
+ for (let i = 0; i < content.length; i++) {
102631
+ const char = content.charCodeAt(i);
102632
+ hash = (hash << 5) - hash + char;
102633
+ hash = hash & hash;
102634
+ }
102635
+ return hash.toString();
102636
+ }
102637
+ function hasPageStateChanged(pageContent, forceUpdate) {
102638
+ if (forceUpdate)
102639
+ return true;
102640
+ const currentScrollX = window.pageXOffset || document.documentElement.scrollLeft;
102641
+ const currentScrollY = window.pageYOffset || document.documentElement.scrollTop;
102642
+ const currentViewportWidth = window.innerWidth || document.documentElement.clientWidth;
102643
+ const currentViewportHeight = window.innerHeight || document.documentElement.clientHeight;
102644
+ const currentContentHash = generateContentHash(pageContent);
102645
+ const hasChanged = prevPageState.contentHash !== currentContentHash || Math.abs(prevPageState.scrollX - currentScrollX) > 10 || Math.abs(prevPageState.scrollY - currentScrollY) > 10 || prevPageState.viewportWidth !== currentViewportWidth || prevPageState.viewportHeight !== currentViewportHeight;
102646
+ if (hasChanged) {
102647
+ prevPageState = {
102648
+ contentHash: currentContentHash,
102649
+ scrollX: currentScrollX,
102650
+ scrollY: currentScrollY,
102651
+ viewportWidth: currentViewportWidth,
102652
+ viewportHeight: currentViewportHeight
102653
+ };
102654
+ }
102655
+ return hasChanged;
102656
+ }
102555
102657
  function manageSyncPageStateListeners(isEnabled) {
102556
102658
  if (isEnabled) {
102557
102659
  if (popstateListenerWasAdded !== true) {
@@ -102563,46 +102665,118 @@ code.hljs {
102563
102665
  window.removeEventListener(ALAN_BTN_PAGE_SYNC_EVENT, listenForPageChanges);
102564
102666
  }
102565
102667
  }
102566
- function syncPageState(onSendCb) {
102567
- sendPageState(onSendCb);
102668
+ async function attemptPageStateSync(onSendCb, forceUpdate = false) {
102669
+ const currentTime = performance.now();
102670
+ const timeSinceLastCall = currentTime - lastSendPageStateTime;
102671
+ if (timeSinceLastCall < SEND_PAGE_STATE_THROTTLE_MS && !forceUpdate) {
102672
+ const delayMs = SEND_PAGE_STATE_THROTTLE_MS - timeSinceLastCall + 50;
102673
+ if (pendingSyncTimeout) {
102674
+ clearTimeout(pendingSyncTimeout);
102675
+ }
102676
+ pendingSync = true;
102677
+ pendingSyncTimeout = setTimeout(() => {
102678
+ pendingSync = false;
102679
+ pendingSyncTimeout = null;
102680
+ sendPageState(onSendCb, true);
102681
+ }, delayMs);
102682
+ return;
102683
+ }
102684
+ if (pendingSyncTimeout) {
102685
+ clearTimeout(pendingSyncTimeout);
102686
+ pendingSyncTimeout = null;
102687
+ pendingSync = false;
102688
+ }
102689
+ await sendPageState(onSendCb, forceUpdate);
102690
+ }
102691
+ function syncPageState(onSendCb, forceUpdate) {
102692
+ attemptPageStateSync(onSendCb, forceUpdate);
102568
102693
  }
102569
102694
  function listenForPageChanges() {
102570
102695
  sendPageState();
102571
102696
  }
102572
- async function captureScreenshot() {
102573
- const canvas = await html2canvas(document.body, {
102574
- logging: false
102575
- });
102576
- return canvas.toDataURL("image/png");
102577
- }
102578
- async function sendPageState(onSendCb) {
102579
- var page = document.createElement("html");
102580
- page.innerHTML = document.getElementsByTagName("html")[0].innerHTML;
102581
- var scripts = page.getElementsByTagName("script");
102582
- var styles = page.getElementsByTagName("style");
102583
- var alanBtnEl = page.getElementsByClassName("alanBtn-root");
102584
- var debugChatEl = page.getElementsByClassName("alanStudio-debug-chat");
102585
- var elementsToRemove = [...scripts, ...styles, ...alanBtnEl, ...debugChatEl];
102586
- for (var i = 0; i < elementsToRemove.length; i++) {
102587
- elementsToRemove[i].remove();
102588
- }
102589
- const pageContent = page.outerHTML;
102590
- if (onSendCb) {
102591
- onSendCb();
102592
- }
102593
- if (prevPageContent === pageContent) {
102594
- return;
102697
+ async function captureScreenshot(requestId) {
102698
+ if (!document.body) {
102699
+ throw new Error("Document body not available");
102700
+ }
102701
+ const bodyRect = document.body.getBoundingClientRect();
102702
+ const maxWidth = 1280;
102703
+ const maxHeight = 1024;
102704
+ const scale = Math.min(maxWidth / bodyRect.width, maxHeight / bodyRect.height, 1);
102705
+ try {
102706
+ const canvas = await html2canvas(document.body, {
102707
+ logging: false,
102708
+ scale,
102709
+ useCORS: false,
102710
+ allowTaint: false,
102711
+ backgroundColor: "#ffffff",
102712
+ removeContainer: true,
102713
+ ignoreElements: (element) => {
102714
+ if (!element || !element.tagName)
102715
+ return false;
102716
+ if (element.classList) {
102717
+ if (element.classList.contains("hidden"))
102718
+ return true;
102719
+ }
102720
+ return false;
102721
+ }
102722
+ });
102723
+ await new Promise((resolve) => setTimeout(resolve, 0));
102724
+ const dataURL = canvas.toDataURL("image/jpeg", 0.8);
102725
+ canvas.width = 0;
102726
+ canvas.height = 0;
102727
+ return dataURL;
102728
+ } catch (error) {
102729
+ throw error;
102595
102730
  }
102596
- prevPageContent = pageContent;
102597
- if (window.tutorProject) {
102598
- let params = {
102731
+ }
102732
+ async function sendPageState(onSendCb, forceUpdate) {
102733
+ lastSendPageStateTime = performance.now();
102734
+ const currentRequestId = ++requestCounter;
102735
+ try {
102736
+ if (!document.getElementsByTagName("html")[0]) {
102737
+ throw new Error("HTML document not available");
102738
+ }
102739
+ const page = document.createElement("html");
102740
+ page.innerHTML = document.getElementsByTagName("html")[0].innerHTML;
102741
+ const scripts = page.getElementsByTagName("script");
102742
+ const styles = page.getElementsByTagName("style");
102743
+ const alanBtnEl = page.getElementsByClassName("alanBtn-root");
102744
+ const debugChatEl = page.getElementsByClassName("alanStudio-debug-chat");
102745
+ const elementsToRemove = [...scripts, ...styles, ...alanBtnEl, ...debugChatEl];
102746
+ for (let i = 0; i < elementsToRemove.length; i++) {
102747
+ if (elementsToRemove[i] && elementsToRemove[i].remove) {
102748
+ elementsToRemove[i].remove();
102749
+ }
102750
+ }
102751
+ const pageContent = page.outerHTML;
102752
+ if (onSendCb) {
102753
+ onSendCb();
102754
+ }
102755
+ const hasChanged = hasPageStateChanged(pageContent, forceUpdate);
102756
+ if (!hasChanged) {
102757
+ return;
102758
+ }
102759
+ if (!window.tutorProject) {
102760
+ return;
102761
+ }
102762
+ const params = {
102599
102763
  html: pageContent,
102600
- url: window.location.href
102764
+ url: window.location.href,
102765
+ scrollPosition: {
102766
+ x: prevPageState.scrollX,
102767
+ y: prevPageState.scrollY
102768
+ },
102769
+ viewport: {
102770
+ width: prevPageState.viewportWidth,
102771
+ height: prevPageState.viewportHeight
102772
+ }
102601
102773
  };
102602
- if (uiState.pageState.screenshot.enabled) {
102603
- params.screenshot = await captureScreenshot();
102774
+ if (window._alanBtnState?.pageState?.screenshot?.enabled) {
102775
+ params.screenshot = await captureScreenshot(currentRequestId);
102604
102776
  }
102605
102777
  window.tutorProject.call("syncPageState", params);
102778
+ } catch (error) {
102779
+ throw error;
102606
102780
  }
102607
102781
  }
102608
102782
 
@@ -109295,6 +109469,31 @@ code.hljs {
109295
109469
  return null;
109296
109470
  return merged;
109297
109471
  }
109472
+ function safelyParseScriptOptions(optionsString) {
109473
+ if (!optionsString || optionsString === "null" || optionsString === "{}") {
109474
+ return null;
109475
+ }
109476
+ try {
109477
+ const cleanOptionsString = optionsString.trim();
109478
+ return Function('"use strict"; return (' + cleanOptionsString + ")")();
109479
+ } catch (error) {
109480
+ console.error("Failed to parse script options:", error);
109481
+ return null;
109482
+ }
109483
+ }
109484
+ function applyThemeToHtmlContent(htmlContent2, theme) {
109485
+ if (!theme || theme !== "light" && theme !== "dark") {
109486
+ return htmlContent2;
109487
+ }
109488
+ const parser2 = new DOMParser();
109489
+ const doc2 = parser2.parseFromString(htmlContent2, "text/html");
109490
+ const htmlElement = doc2.documentElement;
109491
+ if (htmlElement) {
109492
+ const themeClass = theme === "light" ? "light-theme" : "dark-theme";
109493
+ htmlElement.classList.add(themeClass);
109494
+ }
109495
+ return doc2.documentElement.outerHTML;
109496
+ }
109298
109497
  function extractScriptContents(html) {
109299
109498
  const scriptContents = [];
109300
109499
  const parser2 = new DOMParser();
@@ -109330,7 +109529,8 @@ code.hljs {
109330
109529
  projectId,
109331
109530
  environment,
109332
109531
  requestIds,
109333
- headContent
109532
+ headContent,
109533
+ data: data2
109334
109534
  }) {
109335
109535
  const chatConteiner = chatEl.cloneNode(true);
109336
109536
  const images = Array.from(chatConteiner.querySelectorAll("img"));
@@ -109350,6 +109550,7 @@ code.hljs {
109350
109550
  continue;
109351
109551
  }
109352
109552
  let initHtmlContent = await response.text();
109553
+ initHtmlContent = applyThemeToHtmlContent(initHtmlContent, data2?.theme);
109353
109554
  let { htmlContent: htmlContent2 } = await inlineExternalResources(initHtmlContent);
109354
109555
  const initIframeFn2 = extractFunctionWithRegex(htmlContent2, "initIframe");
109355
109556
  if (initIframeFn2) {
@@ -109738,7 +109939,9 @@ code.hljs {
109738
109939
  }
109739
109940
  }
109740
109941
 
109741
- renderDetailsContent(id, 'code');
109942
+ // Set default mode based on data type
109943
+ const defaultMode = detailsData.type === 'markdown' ? 'preview' : 'code';
109944
+ renderDetailsContent(id, defaultMode);
109742
109945
 
109743
109946
  }
109744
109947
 
@@ -109801,18 +110004,29 @@ code.hljs {
109801
110004
  };
109802
110005
  <\/script>
109803
110006
  `;
110007
+ const txtMessages = data2?.textChatMessages ? JSON.stringify(data2?.textChatMessages, null, 2) : '"no-provided"';
110008
+ const socketMessages = data2?.socketMessages ? JSON.stringify(data2?.socketMessages, null, 2) : '"no-provided"';
109804
110009
  const newHtmlContent = `
109805
110010
  <!DOCTYPE html>
109806
110011
  <html lang="en">
109807
110012
  <head>
109808
110013
  <meta charset="UTF-8">
109809
- <title>Alan Text Chat History</title>
110014
+ <title>${chatName} Chat History</title>
109810
110015
  <script src="${LIBS_PREFIX}/d3.v7.min.js" type="text/javascript"><\/script>
109811
110016
  <script src="${LIBS_PREFIX}/viz-standalone.js" type="text/javascript"><\/script>
109812
110017
  <script src="${LIBS_PREFIX}/svg-pan-zoom.min.js" type="text/javascript"><\/script>
109813
110018
  <script src="${LIBS_PREFIX}/alan_markdown.js" type="text/javascript"><\/script>
109814
110019
  <script src="${LIBS_PREFIX}/highlight.min.js?v=2" type="text/javascript"><\/script>
109815
110020
  ${headContent ? headContent : ""}
110021
+
110022
+ <script>
110023
+ console.info('Alan lib v: ${window.alanLib?.version || "-"}, exporter v: 1.0.1');
110024
+ function showAlanDebugInfo() {
110025
+ console.info('Messages in chat:', ${txtMessages});
110026
+ console.info('Messages in socket:', ${socketMessages});
110027
+ }
110028
+ <\/script>
110029
+
109816
110030
  <style>
109817
110031
  * {
109818
110032
  box-sizing: border-box;
@@ -110087,7 +110301,7 @@ code.hljs {
110087
110301
  }
110088
110302
  }
110089
110303
 
110090
- window.alanCurrentTheme = '${uiState.currentTheme}';
110304
+ window.alanCurrentTheme = '${data2?.theme || "null"}';
110091
110305
 
110092
110306
  <\/script>
110093
110307
 
@@ -110098,7 +110312,7 @@ code.hljs {
110098
110312
 
110099
110313
  <div class="alan-history-content ${alanMainClass}">
110100
110314
  <div class="alan-btn__history-chat-header">
110101
- <h1>Alan Text Chat History</h1>
110315
+ <h1>${chatName} Chat History</h1>
110102
110316
  </div>
110103
110317
  <div class="alan-btn__history-chat alan-history-inner-content">
110104
110318
  ${chatConteiner.outerHTML}
@@ -110224,8 +110438,24 @@ code.hljs {
110224
110438
  let allInitIframeResourcesInlined = false;
110225
110439
  if (initIframeFn) {
110226
110440
  let initIframeBody = stripComments(initIframeFn);
110227
- const resourceRegex = /await iframe\.(addScript|addStyleSheet|addFont)\(['"]([^'"]+)['"]\)/g;
110228
- let resourceMatch;
110441
+ const resourceUrls = [];
110442
+ const iframeMethodRegex = /await\s+iframe\.(addScript|addStyleSheet|addFont)\s*\(\s*['"]([^'"]+)['"]\s*(?:,\s*({[^{}]*(?:{[^{}]*}[^{}]*)*}))?\s*\)/g;
110443
+ let iframeMatch;
110444
+ while ((iframeMatch = iframeMethodRegex.exec(initIframeBody)) !== null) {
110445
+ resourceUrls.push({
110446
+ type: iframeMatch[1],
110447
+ url: iframeMatch[2],
110448
+ options: iframeMatch[3] ? iframeMatch[3] : null
110449
+ });
110450
+ }
110451
+ const resourceUrlFnRegex = /(?:window|iframe|document)\.(?:getResourceUrl|getStudioResourceUrl)\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
110452
+ let resourceFnMatch;
110453
+ while ((resourceFnMatch = resourceUrlFnRegex.exec(initIframeBody)) !== null) {
110454
+ resourceUrls.push({
110455
+ type: "getResourceUrl",
110456
+ url: resourceFnMatch[1]
110457
+ });
110458
+ }
110229
110459
  const isValidUrlFn = extractFunction(code, "isValidUrl");
110230
110460
  const getResourceUrlFn = extractFunction(code, "getResourceUrl");
110231
110461
  const getStudioResourceUrlFn = extractFunction(code, "getStudioResourceUrl");
@@ -110291,30 +110521,45 @@ code.hljs {
110291
110521
  console.error("Failed to get or inline basic resources:", error);
110292
110522
  }
110293
110523
  }
110294
- while ((resourceMatch = resourceRegex.exec(initIframeBody)) !== null) {
110295
- const [_, resourceType, rawResourceUrl] = resourceMatch;
110524
+ for (const resource of resourceUrls) {
110296
110525
  try {
110297
- const resourceUrl = getResourceUrl(rawResourceUrl);
110526
+ const resourceUrl = getResourceUrl(resource.url);
110298
110527
  const response = await fetch(resourceUrl);
110299
110528
  if (!response.ok) {
110300
- console.error(`Failed to fetch ${resourceType} from ${resourceUrl}: ${response.statusText}`);
110529
+ console.error(`Failed to fetch resource from ${resourceUrl}: ${response.statusText}`);
110301
110530
  allInitIframeResourcesInlined = false;
110302
110531
  continue;
110303
110532
  }
110304
110533
  const resourceContent = await response.text();
110305
- if (resourceType === "addScript") {
110534
+ if (resource.type === "addScript" || resource.url.endsWith(".js")) {
110306
110535
  const inlineScript = doc.createElement("script");
110307
110536
  inlineScript.textContent = resourceContent;
110537
+ if (resource.options) {
110538
+ const optionsObj = safelyParseScriptOptions(resource.options);
110539
+ if (optionsObj && typeof optionsObj === "object") {
110540
+ if (optionsObj.type) {
110541
+ inlineScript.setAttribute("type", optionsObj.type);
110542
+ }
110543
+ if (optionsObj.defer)
110544
+ inlineScript.setAttribute("defer", "");
110545
+ if (optionsObj.async)
110546
+ inlineScript.setAttribute("async", "");
110547
+ if (optionsObj.nomodule)
110548
+ inlineScript.setAttribute("nomodule", "");
110549
+ if (optionsObj.crossOrigin)
110550
+ inlineScript.setAttribute("crossorigin", optionsObj.crossOrigin);
110551
+ }
110552
+ }
110308
110553
  doc.head.appendChild(inlineScript);
110309
- console.log(`Inlined script from initIframe fn: ${resourceUrl}`);
110310
- } else if (resourceType === "addStyleSheet") {
110554
+ console.log(`Inlined script: ${resourceUrl}${inlineScript.type ? " (type=" + inlineScript.type + ")" : ""}`);
110555
+ } else if (resource.type === "addStyleSheet" || resource.url.endsWith(".css")) {
110311
110556
  const inlineStyle = doc.createElement("style");
110312
110557
  inlineStyle.textContent = resourceContent;
110313
110558
  doc.head.appendChild(inlineStyle);
110314
- console.log(`Inlined stylesheet from initIframe fn: ${resourceUrl}`);
110559
+ console.log(`Inlined stylesheet: ${resourceUrl}`);
110315
110560
  }
110316
110561
  } catch (error) {
110317
- console.error(`Failed to inline ${resourceType} from ${rawResourceUrl}:`, error);
110562
+ console.error(`Failed to inline resource from ${resource.url}:`, error);
110318
110563
  allInitIframeResourcesInlined = false;
110319
110564
  }
110320
110565
  }
@@ -110343,6 +110588,9 @@ code.hljs {
110343
110588
  return msg.reqId || msg?.ctx?.reqId;
110344
110589
  ;
110345
110590
  }
110591
+ function getMsgResponseId(msg) {
110592
+ return msg.responseId || msg?.ctx?.responseId || msg?.ctx?.resId;
110593
+ }
110346
110594
 
110347
110595
  // alan_btn/src/textChat/helpers/shouldTextBeSavedInChatHistory.ts
110348
110596
  function shouldTextBeSavedInChatHistory(text, sentMessages) {
@@ -110500,7 +110748,8 @@ code.hljs {
110500
110748
 
110501
110749
  // alan_btn/alan_btn.ts
110502
110750
  (function(ns) {
110503
- uiState.lib.version = "alan-version.1.8.92".replace("alan-version.", "");
110751
+ uiState.lib.version = "alan-version.1.8.94".replace("alan-version.", "");
110752
+ window.alanLib = { version: "alan-version.1.8.93".replace("alan-version.", "") };
110504
110753
  if (window.alanBtn) {
110505
110754
  console.warn("Alan: the Alan Button source code has already added (v." + uiState.lib.version + ")");
110506
110755
  }
@@ -110743,6 +110992,8 @@ code.hljs {
110743
110992
  alanAudio.off("command", onCommandCbInMicBtn);
110744
110993
  alanAudio.off("afterText", onAfterTextCbInMicBtn);
110745
110994
  document.removeEventListener("click", alanBtnClickEventListener);
110995
+ document.removeEventListener("click", performLikeOrDislike);
110996
+ document.removeEventListener("click", onCopyClick);
110746
110997
  rootEl.innerHTML = "";
110747
110998
  btnInstance = null;
110748
110999
  if (!isTutorMode()) {
@@ -110830,6 +111081,11 @@ code.hljs {
110830
111081
  var playReadyToListenSound = true;
110831
111082
  var turnOffTimeout = 3e4;
110832
111083
  var turnOffVoiceFn;
111084
+ var completionText = "";
111085
+ var completionToInsert = "";
111086
+ var completions = [];
111087
+ var selectedCompletionIndex = -1;
111088
+ var complitionWasApplied = false;
110833
111089
  var dndInitMousePos2 = [0, 0];
110834
111090
  var dndIsDown = false;
110835
111091
  var btnWasMoved = false;
@@ -110857,6 +111113,21 @@ code.hljs {
110857
111113
  function getUserIdLsPrefix() {
110858
111114
  return uiState.userInfo?.userId ? `-${uiState.userInfo?.userId}` : "";
110859
111115
  }
111116
+ window._alanBtnState = {
111117
+ pageState: {
111118
+ screenshot: {
111119
+ enabled: false
111120
+ }
111121
+ },
111122
+ textChat: {
111123
+ notifications: {
111124
+ enabled: false
111125
+ }
111126
+ }
111127
+ };
111128
+ if (isTutorMode()) {
111129
+ window._alanBtnState.pageState.screenshot.enabled = options?.pageState?.screenshot?.enabled;
111130
+ }
110860
111131
  var pulsatingAnimation = "";
110861
111132
  var pulsatingMicAnimation = "";
110862
111133
  var pulsatingTriangleMicAnimation = "";
@@ -111806,6 +112077,10 @@ code.hljs {
111806
112077
  param.ctx = {
111807
112078
  url: window.location.href
111808
112079
  };
112080
+ storeSocketHistory({
112081
+ type: "request",
112082
+ ...param
112083
+ });
111809
112084
  window.tutorProject.call("text", param, function(e, res) {
111810
112085
  if (e) {
111811
112086
  reject({ error: e });
@@ -112071,7 +112346,6 @@ code.hljs {
112071
112346
  }
112072
112347
  }
112073
112348
  if (isTutorMode()) {
112074
- uiState.pageState.screenshot.enabled = true;
112075
112349
  manageSyncPageStateListeners(true);
112076
112350
  }
112077
112351
  function changeOptions(options2) {
@@ -112172,7 +112446,10 @@ code.hljs {
112172
112446
  console.log("Alan: options received");
112173
112447
  console.timeEnd("Alan: receiving options time");
112174
112448
  saveOptions(data2);
112175
- uiState.pageState.screenshot.enabled = data2?.web?.pageState?.screenshot?.enabled;
112449
+ window._alanBtnState.textChat.notifications.enabled = data2?.web?.chatOptions?.textChat?.notifications?.enabled;
112450
+ window._alanBtnState.pageState.screenshot.enabled = data2?.web?.pageState?.screenshot?.enabled;
112451
+ uiState.textChat.autocomplete.enabled = data2?.web?.chatOptions?.textChat?.textarea?.autocomplete?.enabled;
112452
+ uiState.textChat.maxCharactersCount = data2?.web?.chatOptions?.textChat?.textarea?.maxCharactersCount ? +data2?.web?.chatOptions?.textChat?.textarea?.maxCharactersCount : 2e4;
112176
112453
  changeOptions(getOptionsByTheme(data2?.web, uiState.currentTheme || options.theme));
112177
112454
  }
112178
112455
  function setUserId(userId) {
@@ -112254,6 +112531,8 @@ ${curDialogId}`);
112254
112531
  if (options.onConnectionStatus) {
112255
112532
  options.onConnectionStatus(res);
112256
112533
  }
112534
+ isMsgTypingInProcess = false;
112535
+ sendSyncPageState(true);
112257
112536
  }
112258
112537
  function onMicAllowed() {
112259
112538
  sendClientEvent({ micAllowed: true });
@@ -112391,6 +112670,7 @@ ${curDialogId}`);
112391
112670
  function _onTextCb(e) {
112392
112671
  clearMessageProgressStatusInterval();
112393
112672
  const event = Object.assign(e, { name: "text", type: "response" /* Response */ });
112673
+ storeSocketHistory(event);
112394
112674
  if (event.images?.length > 0) {
112395
112675
  event.images = filterImagesForTextChat(event.images);
112396
112676
  }
@@ -112409,6 +112689,9 @@ ${curDialogId}`);
112409
112689
  _onTextCb(e);
112410
112690
  }
112411
112691
  }
112692
+ function storeSocketHistory(event) {
112693
+ uiState.socketMessages.push({ ...event, socketTs: Date.now() });
112694
+ }
112412
112695
  function onQueryProgressCb(e) {
112413
112696
  if (uiState?.textChat?.options?.bubbles?.waitingResponse?.queryProgress?.enabled === false)
112414
112697
  return;
@@ -112420,6 +112703,7 @@ ${curDialogId}`);
112420
112703
  queryProgress: []
112421
112704
  }
112422
112705
  );
112706
+ storeSocketHistory(event);
112423
112707
  if (e.progress?.name) {
112424
112708
  event.queryProgress = [{
112425
112709
  text: e.progress?.name,
@@ -112438,6 +112722,7 @@ ${curDialogId}`);
112438
112722
  }
112439
112723
  function onParsedCbInMicBtn(e) {
112440
112724
  const event = Object.assign(e, { name: "parsed" });
112725
+ storeSocketHistory(event);
112441
112726
  if (options.onEvent) {
112442
112727
  options.onEvent(event);
112443
112728
  }
@@ -112446,6 +112731,7 @@ ${curDialogId}`);
112446
112731
  }
112447
112732
  function onRecognizedCbInMicBtn(e) {
112448
112733
  const event = Object.assign(e, { name: "recognized" });
112734
+ storeSocketHistory(event);
112449
112735
  if (options.onEvent) {
112450
112736
  options.onEvent(event);
112451
112737
  }
@@ -112820,7 +113106,7 @@ ${curDialogId}`);
112820
113106
  return `${buildImagesContent(msg)}${buildMsgTextContent(msg)}${buildLinksContent(msg)}${buildCommandsBlock(msg, uiState?.textChat?.options)}${buildMsgIncommingLoader(msg)}${addGraphIcon(msg)}`;
112821
113107
  }
112822
113108
  initMathJax(textChatMessages.length, (i2) => getMsgElForMathJax(i2));
112823
- document.addEventListener("click", (e) => {
113109
+ function onCopyClick(e) {
112824
113110
  let clickedEl = e.target;
112825
113111
  clickedEl = clickedEl.closest(".alan-btn__chat-response__copy-btn");
112826
113112
  if (clickedEl) {
@@ -112860,7 +113146,8 @@ ${LEARN_MORE_LABEL}
112860
113146
  }
112861
113147
  enableTextareaInTheChat();
112862
113148
  }
112863
- }, false);
113149
+ }
113150
+ document.addEventListener("click", onCopyClick, false);
112864
113151
  window.addEventListener("click", (0, import_lodash2.debounce)((e) => {
112865
113152
  if (isTutorMode())
112866
113153
  return;
@@ -112894,6 +113181,7 @@ ${LEARN_MORE_LABEL}
112894
113181
  div.classList.add("alan-hide-msg-immidiatelly");
112895
113182
  });
112896
113183
  }
113184
+ let emptyMessages = {};
112897
113185
  function renderMessageInTextChat(msg, noAnimation, immidiateScroll) {
112898
113186
  if (!uiState.textChat.available)
112899
113187
  return;
@@ -112960,11 +113248,31 @@ ${LEARN_MORE_LABEL}
112960
113248
  }
112961
113249
  }
112962
113250
  msg = { ...msg, ...getMsgReadProp(msg, textChatIsHidden) };
112963
- const { isNew, msgInd, replaceLoader, updateResponse } = processMessageForChat(msg, textChatMessages);
113251
+ if (msg.type === "response" && msg.name === "text") {
113252
+ const msgResponseId = getMsgResponseId(msg);
113253
+ if (isFinalMessage(msg)) {
113254
+ if (emptyMessages[msgResponseId]) {
113255
+ return;
113256
+ }
113257
+ } else {
113258
+ if (isMsgEmpty(msg)) {
113259
+ emptyMessages[msgResponseId] = msg;
113260
+ return;
113261
+ }
113262
+ }
113263
+ delete emptyMessages[msgResponseId];
113264
+ }
113265
+ const { isNew, msgInd, replaceLoader, updateExistingResponse, skipUpdating } = processMessageForChat(msg, textChatMessages);
113266
+ if (skipUpdating) {
113267
+ return;
113268
+ }
112964
113269
  if (isNew) {
112965
113270
  var div = document.createElement("div");
112966
113271
  div.id = "msg-" + msgInd;
112967
113272
  div.setAttribute("data-request-id", getMsgReqId(msg));
113273
+ if (msg.type === "response") {
113274
+ div.setAttribute("data-response-id", getMsgResponseId(msg));
113275
+ }
112968
113276
  div.classList.add("alan-btn__chat-msg-holder");
112969
113277
  div.setAttribute("data-msg-index", msgInd);
112970
113278
  if (msg.type === "chat") {
@@ -113021,7 +113329,7 @@ ${LEARN_MORE_LABEL}
113021
113329
  }
113022
113330
  scrollTextChat(msgsScrollableContainer, "smooth");
113023
113331
  }
113024
- } else if (updateResponse && msg.type !== "chat") {
113332
+ } else if (updateExistingResponse && msg.type !== "chat") {
113025
113333
  let innerEl = msgEl.querySelector(".alan-btn__chat-inner-msg");
113026
113334
  if (innerEl) {
113027
113335
  if (innerEl.classList.contains("alan-hidden-loader")) {
@@ -113049,7 +113357,7 @@ ${LEARN_MORE_LABEL}
113049
113357
  innerEl.insertAdjacentHTML("beforeend", buildCommandsBlock(msg, uiState?.textChat?.options));
113050
113358
  innerEl.insertAdjacentHTML("beforeend", buildMsgIncommingLoader(updatedMsg));
113051
113359
  innerEl.insertAdjacentHTML("beforeend", addGraphIcon(updatedMsg));
113052
- const newSuggestions = msg?.suggestions;
113360
+ const newSuggestions = updatedMsg?.suggestions;
113053
113361
  if (newSuggestions?.length > 0) {
113054
113362
  if (innerEl.nextElementSibling?.classList.contains("alan-btn__chat-suggestions")) {
113055
113363
  innerEl.nextElementSibling.remove();
@@ -113166,6 +113474,7 @@ ${LEARN_MORE_LABEL}
113166
113474
  window.alanIframes = {};
113167
113475
  connectToNewDialog();
113168
113476
  clearDOMChat();
113477
+ uiState.socketMessages = [];
113169
113478
  clearChatHistoryStorage();
113170
113479
  manageSaveChatHistoryBtn();
113171
113480
  }
@@ -113259,6 +113568,7 @@ ${LEARN_MORE_LABEL}
113259
113568
  }
113260
113569
  }
113261
113570
  async function _sendText(text) {
113571
+ manageAutocompeteInChat();
113262
113572
  var msg = { text, type: "request", name: "text" };
113263
113573
  sentMessageInd = null;
113264
113574
  clearMessageProgressStatusInterval();
@@ -113279,6 +113589,16 @@ ${LEARN_MORE_LABEL}
113279
113589
  const regId = getMsgReqId(msg);
113280
113590
  return canceledRequests.indexOf(regId) > -1;
113281
113591
  }
113592
+ function isMsgEmpty(msg) {
113593
+ let isEmpty2 = false;
113594
+ if (msg.type === "response" /* Response */ && msg.name === "text") {
113595
+ isEmpty2 = true;
113596
+ if (msg.images?.length > 0 || msg.links?.length > 0 || msg.suggestions?.length > 0 || msg.text !== "") {
113597
+ isEmpty2 = false;
113598
+ }
113599
+ }
113600
+ return isEmpty2;
113601
+ }
113282
113602
  function enableTextareaInTheChat() {
113283
113603
  var textareaHolderEl = document.getElementById("textarea-holder");
113284
113604
  textareaHolderEl.classList.remove("alan-btn__inactive");
@@ -113290,7 +113610,8 @@ ${LEARN_MORE_LABEL}
113290
113610
  var textareaEl = getChatTextareaEl();
113291
113611
  var textareaHolderEl = document.getElementById("textarea-holder");
113292
113612
  var text = textareaEl.value;
113293
- if (lastSendMsgTs) {
113613
+ var maxChars = uiState.textChat.maxCharactersCount || 2e4;
113614
+ if (lastSendMsgTs || text?.length > maxChars) {
113294
113615
  return;
113295
113616
  }
113296
113617
  lastSendMsgTs = setTimeout(() => {
@@ -113349,14 +113670,114 @@ ${LEARN_MORE_LABEL}
113349
113670
  }
113350
113671
  resizeTextArea();
113351
113672
  }
113352
- function onChatTextAreaChange(e) {
113673
+ let latestAutocompleteRequestId = 0;
113674
+ const fillChatAutocompleteDebounced = (0, import_lodash2.debounce)(() => {
113675
+ const requestId = ++latestAutocompleteRequestId;
113676
+ fillChatAutocomplete(requestId);
113677
+ }, 200);
113678
+ function onChatTextAreaChange(event) {
113353
113679
  resizeTextArea();
113680
+ manageAutocompeteInChat();
113681
+ manageSendButtonAvailability();
113682
+ }
113683
+ function manageAutocompeteInChat() {
113684
+ if (uiState.textChat?.autocomplete?.enabled === true) {
113685
+ checkIfNewComplitionNeeded();
113686
+ fillChatAutocompleteDebounced();
113687
+ }
113688
+ }
113689
+ function updateAutocompleteInChat(completion) {
113690
+ const chatAutocompleteEl = getAutocompleteChatTextareaEl();
113691
+ if (chatAutocompleteEl) {
113692
+ completionToInsert = completion || "";
113693
+ completionText = `${completionToInsert}`;
113694
+ chatAutocompleteEl.value = completionText;
113695
+ resizeTextArea();
113696
+ }
113697
+ }
113698
+ function checkIfNewComplitionNeeded() {
113699
+ const chatEl = getChatTextareaEl();
113700
+ const chatAutocompletEl = getAutocompleteChatTextareaEl();
113701
+ if (!chatEl || !chatAutocompletEl)
113702
+ return;
113703
+ const prefix = chatEl.value;
113704
+ const curComplitionText = completionText;
113705
+ if (!curComplitionText.startsWith(prefix) || prefix.trim() === "") {
113706
+ clearChatAutocomplete(true);
113707
+ }
113708
+ }
113709
+ function clearChatAutocomplete(fullClear) {
113710
+ const chatAutocompleteEl = getAutocompleteChatTextareaEl();
113711
+ if (chatAutocompleteEl && completionText?.length > 0) {
113712
+ chatAutocompleteEl.value = "";
113713
+ complitionWasApplied = false;
113714
+ if (fullClear) {
113715
+ completionToInsert = "";
113716
+ completionText = "";
113717
+ }
113718
+ }
113719
+ }
113720
+ function fillChatAutocomplete(requestId) {
113721
+ const maxChars = uiState.textChat.maxCharactersCount || 2e4;
113722
+ const chatEl = getChatTextareaEl();
113723
+ const chatAutocompletEl = getAutocompleteChatTextareaEl();
113724
+ if (!chatEl || !chatAutocompletEl)
113725
+ return;
113726
+ let prefix = chatEl.value;
113727
+ const curComplitionText = completionText;
113728
+ ;
113729
+ if (prefix.trim() === "" || curComplitionText.startsWith(prefix))
113730
+ return;
113731
+ if (prefix.length > maxChars)
113732
+ return;
113733
+ prefix = prefix.replace(/\n+$/, "");
113734
+ if (complitionWasApplied) {
113735
+ complitionWasApplied = false;
113736
+ return;
113737
+ }
113738
+ clearChatAutocomplete(true);
113739
+ if (window.tutorProject) {
113740
+ window.tutorProject.call("chatMessageCompletions", {
113741
+ prefix,
113742
+ candidates: 1
113743
+ }, (err, res) => {
113744
+ if (requestId !== latestAutocompleteRequestId)
113745
+ return;
113746
+ if (err) {
113747
+ console.error("Error getting chat autocompete:", err);
113748
+ updateAutocompleteInChat("");
113749
+ completions = [];
113750
+ } else {
113751
+ completions = res?.completions?.map((el) => `${prefix}${el}`) || [];
113752
+ updateAutocompleteInChat(`${prefix}${res?.completions[0]}`);
113753
+ }
113754
+ });
113755
+ }
113756
+ }
113757
+ function manageSendButtonAvailability() {
113758
+ const maxChars = uiState.textChat.maxCharactersCount || 2e4;
113759
+ const textareaEl = getChatTextareaEl();
113760
+ const sendBtn = document.getElementById("chat-send-btn");
113761
+ const errEl = document.getElementById("alan-btn__chat-footer-err");
113762
+ if (textareaEl && sendBtn && errEl) {
113763
+ if (textareaEl.value.length > 0 && textareaEl.value.length <= maxChars) {
113764
+ sendBtn.classList.remove("alan-btn__disabled");
113765
+ } else {
113766
+ sendBtn.classList.add("alan-btn__disabled");
113767
+ }
113768
+ if (textareaEl.value.length <= maxChars) {
113769
+ errEl.style.display = "none";
113770
+ } else {
113771
+ errEl.style.display = "block";
113772
+ }
113773
+ }
113354
113774
  }
113355
113775
  const resizeTextAreaDebounced = throttle(function() {
113356
113776
  resizeTextArea();
113357
113777
  }, 300);
113358
113778
  function resizeTextArea() {
113359
113779
  var el = getChatTextareaEl();
113780
+ var elAutocomplete = getAutocompleteChatTextareaEl();
113360
113781
  if (!el)
113361
113782
  return;
113362
113783
  const isMultiline = uiState.textChat.options?.textarea?.fieldType === "multi-line";
@@ -113371,7 +113792,13 @@ ${LEARN_MORE_LABEL}
113371
113792
  const lineHeight = fontSize * defaultLineHeight;
113372
113793
  const maxHeight = lineHeight * maxLinesCount + paddingsAndBorder;
113373
113794
  const defaultOneLineHeight = lineHeight + paddingsAndBorder;
113374
- el.style.height = `${getDynamicInputHeight(el, maxHeight)}px`;
113795
+ const inputHeight = getDynamicInputHeight(el, maxHeight);
113796
+ const autocompleteHeight = getDynamicInputHeight(elAutocomplete, maxHeight);
113797
+ const finalHeight = Math.max(inputHeight, autocompleteHeight);
113798
+ el.style.height = `${finalHeight}px`;
113799
+ if (elAutocomplete) {
113800
+ elAutocomplete.style.height = `${finalHeight}px`;
113801
+ }
113375
113802
  if (el.offsetHeight > defaultOneLineHeight) {
113376
113803
  el.closest("#textarea-holder")?.classList?.add("multi-line");
113377
113804
  } else {
@@ -113380,6 +113807,9 @@ ${LEARN_MORE_LABEL}
113380
113807
  } else {
113381
113808
  el.closest("#textarea-holder")?.classList?.remove("multi-line");
113382
113809
  el.style.height = `100%`;
113810
+ if (elAutocomplete) {
113811
+ elAutocomplete.style.height = `100%`;
113812
+ }
113383
113813
  }
113384
113814
  }
113385
113815
  function getDynamicInputHeight(el, maxHeight) {
@@ -113484,12 +113914,19 @@ ${LEARN_MORE_LABEL}
113484
113914
  range.select();
113485
113915
  }
113486
113916
  }
113917
+ function scrollCursorToEnd(el) {
113918
+ if (!el)
113919
+ return;
113920
+ if (el.tagName === "INPUT") {
113921
+ el.scrollLeft = el.scrollWidth;
113922
+ }
113923
+ }
113487
113924
  let isMsgTypingInProcess = false;
113488
- function sendSyncPageState() {
113925
+ function sendSyncPageState(forceUpdate = false) {
113489
113926
  if (!isMsgTypingInProcess) {
113490
113927
  syncPageState(function() {
113491
113928
  isMsgTypingInProcess = true;
113492
- });
113929
+ }, forceUpdate);
113493
113930
  }
113494
113931
  }
113495
113932
  function onChatTextAreaFocus() {
@@ -113498,6 +113935,7 @@ ${LEARN_MORE_LABEL}
113498
113935
  function onChatTextAreaBlur() {
113499
113936
  isMsgTypingInProcess = false;
113500
113937
  }
113938
+ let delPressed = 0;
113501
113939
  function onChatTextAreaKeyDown(e) {
113502
113940
  const keyCode = e.keyCode || e.which;
113503
113941
  sendSyncPageState();
@@ -113508,15 +113946,43 @@ ${LEARN_MORE_LABEL}
113508
113946
  addNewLine(e.target);
113509
113947
  return;
113510
113948
  }
113949
+ if (keyCode === 8) {
113950
+ delPressed++;
113951
+ if (delPressed > 6) {
113952
+ delPressed = 0;
113953
+ latestAutocompleteRequestId++;
113954
+ clearChatAutocomplete(true);
113955
+ }
113956
+ }
113511
113957
  if (keyCode === 13) {
113512
113958
  sendMessageToTextChat();
113513
113959
  e.stopPropagation();
113514
113960
  e.preventDefault();
113515
113961
  }
113962
+ if (keyCode === 9) {
113963
+ const chatAutocompleteEl = getAutocompleteChatTextareaEl();
113964
+ const newTextVal = chatAutocompleteEl?.value || "";
113965
+ if (newTextVal) {
113966
+ delPressed = 0;
113967
+ clearChatAutocomplete(false);
113968
+ moveCursorToEnd(e.target);
113969
+ setTimeout(() => {
113970
+ scrollCursorToEnd(e.target);
113971
+ });
113972
+ e.stopPropagation();
113973
+ e.preventDefault();
113974
+ complitionWasApplied = true;
113975
+ latestAutocompleteRequestId++;
113976
+ e.target.value = "";
113977
+ document.execCommand("insertText", false, completionToInsert || "");
113978
+ return;
113979
+ }
113980
+ }
113516
113981
  const goToPrev = keyCode === 38;
113517
113982
  const goToNext = keyCode === 40;
113518
113983
  const isMultiline = uiState.textChat.options?.textarea?.fieldType === "multi-line";
113519
113984
  if (!isMultiline && (goToPrev || goToNext)) {
113985
+ clearChatAutocomplete(true);
113520
113986
  switchMessages(keyCode);
113521
113987
  e.stopPropagation();
113522
113988
  e.preventDefault();
@@ -113587,6 +114053,9 @@ ${LEARN_MORE_LABEL}
113587
114053
  function getChatTextareaEl() {
113588
114054
  return document.getElementById("chatTextarea");
113589
114055
  }
114056
+ function getAutocompleteChatTextareaEl() {
114057
+ return document.getElementById("chatTextareaAutocomplete");
114058
+ }
113590
114059
  function addNeedClassesToExpandCollapseBtn(parentEl) {
113591
114060
  parentEl.children[0].classList.add("alan-btn__chat-enter-full-screen-mode");
113592
114061
  parentEl.children[1].classList.add("alan-btn__chat-exit-full-screen-mode");
@@ -113601,6 +114070,14 @@ ${LEARN_MORE_LABEL}
113601
114070
  el.addEventListener("keydown", onChatTextAreaKeyDown);
113602
114071
  el.addEventListener("keyup", onChatTextAreaKeyUp);
113603
114072
  el.addEventListener("input", onChatTextAreaChange);
114073
+ el.addEventListener("change", onChatTextAreaChange);
114074
+ return el;
114075
+ }
114076
+ function createAutocompleteInputNode(fieldType) {
114077
+ const el = document.createElement(fieldType);
114078
+ el.id = "chatTextareaAutocomplete";
114079
+ el.setAttribute("autocomplete", "off");
114080
+ el.classList.add("alan-btn__chat-textarea-autocomplete");
113604
114081
  return el;
113605
114082
  }
113606
114083
  function manageSaveChatHistoryBtn() {
@@ -113618,6 +114095,7 @@ ${LEARN_MORE_LABEL}
113618
114095
  var textareaInnerDiv = document.getElementById("textarea-inner-holder");
113619
114096
  var textareaHolderDiv = document.getElementById("textarea-holder-content");
113620
114097
  var chatTextarea = getChatTextareaEl();
114098
+ var chatTextareaAutocomplete = getAutocompleteChatTextareaEl();
113621
114099
  var chatMicBtn = document.getElementById("chat-mic-btn");
113622
114100
  var unmuteAlanBtn = document.getElementById("chat-unmute-btn");
113623
114101
  var chatSendBtn = document.getElementById("chat-send-btn");
@@ -113704,11 +114182,13 @@ ${LEARN_MORE_LABEL}
113704
114182
  var textareaDivGr = document.createElement("div");
113705
114183
  textareaDivGr.classList.add("alan-btn__chat-textarea-holder-gradient");
113706
114184
  chatTextarea = createTextInputNode(isMultiline ? "textarea" : "input");
114185
+ chatTextareaAutocomplete = createAutocompleteInputNode(isMultiline ? "textarea" : "input");
113707
114186
  chatSendBtn = document.createElement("div");
113708
114187
  chatSendBtn.id = "chat-send-btn";
113709
114188
  chatSendBtn.classList.add("alan-btn__chat-send-btn");
113710
114189
  chatSendBtn.addEventListener("click", sendMessageToTextChat);
113711
114190
  textareaInnerDiv.appendChild(chatTextarea);
114191
+ textareaInnerDiv.appendChild(chatTextareaAutocomplete);
113712
114192
  textareaHolderDiv.appendChild(clearChatBtn);
113713
114193
  textareaHolderDiv.appendChild(textareaInnerDiv);
113714
114194
  textareaDiv.appendChild(textareaHolderDiv);
@@ -113716,18 +114196,37 @@ ${LEARN_MORE_LABEL}
113716
114196
  chatDiv.appendChild(headerDiv);
113717
114197
  chatDiv.appendChild(messagesWrapperDiv);
113718
114198
  chatDiv.appendChild(textareaDiv);
114199
+ if (options.textChat?.footerInfoElement) {
114200
+ const footerDiv = createDiv({ class: "alan-btn__chat-footer-info" });
114201
+ footerDiv.appendChild(options.textChat.footerInfoElement);
114202
+ textareaDiv.appendChild(footerDiv);
114203
+ }
114204
+ const footerErrDiv = createDiv({ id: "alan-btn__chat-footer-err", class: "alan-btn__chat-footer-err" });
114205
+ footerErrDiv.innerHTML = "Message too long. Please shorten it.";
114206
+ footerErrDiv.style.display = "none";
114207
+ textareaDiv.prepend(footerErrDiv);
113719
114208
  chatDiv.appendChild(headerDivGr);
113720
114209
  chatHolderDiv.classList.add("alan-btn__chat-holder");
113721
114210
  }
113722
114211
  const tagName = chatTextarea?.tagName?.toLowerCase();
114212
+ const chatParentNode = document.getElementById("textarea-inner-holder");
114213
+ ++latestAutocompleteRequestId;
113723
114214
  if (tagName === "input" && isMultiline) {
113724
114215
  const newTextareaEl = createTextInputNode("textarea");
114216
+ const newAutocompleteTextareaEl = createAutocompleteInputNode("textarea");
113725
114217
  newTextareaEl.placeholder = chatTextarea.placeholder;
113726
- chatTextarea.parentNode.replaceChild(newTextareaEl, chatTextarea);
114218
+ chatParentNode.replaceChild(newTextareaEl, chatTextarea);
114219
+ if (chatTextareaAutocomplete.parentNode) {
114220
+ chatParentNode.replaceChild(newAutocompleteTextareaEl, chatTextareaAutocomplete);
114221
+ }
113727
114222
  } else if (tagName === "textarea" && !isMultiline) {
113728
114223
  const newTextareaEl = createTextInputNode("input");
114224
+ const newAutocompleteTextareaEl = createAutocompleteInputNode("input");
113729
114225
  newTextareaEl.placeholder = chatTextarea.placeholder;
113730
- chatTextarea.parentNode.replaceChild(newTextareaEl, chatTextarea);
114226
+ chatParentNode.replaceChild(newTextareaEl, chatTextarea);
114227
+ if (chatTextareaAutocomplete.parentNode) {
114228
+ chatParentNode.replaceChild(newAutocompleteTextareaEl, chatTextareaAutocomplete);
114229
+ }
113731
114230
  }
113732
114231
  setTimeout(() => {
113733
114232
  resizeTextArea();
@@ -113958,13 +114457,8 @@ ${LEARN_MORE_LABEL}
113958
114457
  ];
113959
114458
  const styles = head.querySelectorAll(styleSelectors.join(", "));
113960
114459
  const combinedStylesHTML = Array.from(styles).map((style) => style.outerHTML).join("\n");
113961
- const txtMessages = JSON.stringify(textChatMessages, null, 2);
113962
114460
  const customHeadContent = `
113963
114461
  ${combinedStylesHTML}
113964
-
113965
- <script>
113966
- console.info('Messages in chat:', ${txtMessages});
113967
- <\/script>
113968
114462
  `;
113969
114463
  const initChat = document.querySelector("#chatMessagesWrapper");
113970
114464
  if (!initChat)
@@ -113986,7 +114480,12 @@ ${LEARN_MORE_LABEL}
113986
114480
  projectId,
113987
114481
  environment: getEnvironment(),
113988
114482
  requestIds: textChatMessages?.length > 0 ? textChatMessages.filter((m) => m.type === "response" /* Response */).map((m) => getMsgReqId(m)) : [],
113989
- headContent: customHeadContent
114483
+ headContent: customHeadContent,
114484
+ data: {
114485
+ textChatMessages,
114486
+ socketMessages: uiState.socketMessages,
114487
+ theme: uiState.currentTheme
114488
+ }
113990
114489
  });
113991
114490
  if (saveChatStateBtnImg) {
113992
114491
  saveChatStateBtnImg.classList.remove("saving");
@@ -114029,7 +114528,7 @@ ${LEARN_MORE_LABEL}
114029
114528
  function showChatNotifications() {
114030
114529
  if (unreadChatMsgCount > 0) {
114031
114530
  chatNotificationsBubble.innerHTML = unreadChatMsgCount > 99 ? `99+` : `${unreadChatMsgCount}`;
114032
- chatNotificationsBubble.style.display = "flex";
114531
+ chatNotificationsBubble.classList.remove("super-hidden");
114033
114532
  }
114034
114533
  }
114035
114534
  function manageUnmuteAlanIcon(iconEl, unmuted) {
@@ -114088,7 +114587,7 @@ ${LEARN_MORE_LABEL}
114088
114587
  }
114089
114588
  function hideChatNotifications() {
114090
114589
  unreadChatMsgCount = 0;
114091
- chatNotificationsBubble.style.display = "none";
114590
+ chatNotificationsBubble.classList.add("super-hidden");
114092
114591
  for (let i2 = 0; i2 < textChatMessages.length; i2++) {
114093
114592
  textChatMessages[i2].read = true;
114094
114593
  }
@@ -114814,7 +115313,8 @@ ${LEARN_MORE_LABEL}
114814
115313
  }
114815
115314
  });
114816
115315
  }
114817
- }
115316
+ },
115317
+ getSocketMessages
114818
115318
  },
114819
115319
  writable: false,
114820
115320
  configurable: false