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

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
+ }
98462
98474
  isNew = false;
98475
+ } else if (existingMsgReqId > -1) {
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) {
@@ -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`} ;
@@ -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;
@@ -102563,19 +102625,20 @@ code.hljs {
102563
102625
  window.removeEventListener(ALAN_BTN_PAGE_SYNC_EVENT, listenForPageChanges);
102564
102626
  }
102565
102627
  }
102566
- function syncPageState(onSendCb) {
102567
- sendPageState(onSendCb);
102628
+ function syncPageState(onSendCb, forceUpdate) {
102629
+ sendPageState(onSendCb, forceUpdate);
102568
102630
  }
102569
102631
  function listenForPageChanges() {
102570
102632
  sendPageState();
102571
102633
  }
102572
102634
  async function captureScreenshot() {
102573
102635
  const canvas = await html2canvas(document.body, {
102574
- logging: false
102636
+ logging: false,
102637
+ scale: 1
102575
102638
  });
102576
102639
  return canvas.toDataURL("image/png");
102577
102640
  }
102578
- async function sendPageState(onSendCb) {
102641
+ async function sendPageState(onSendCb, forceUpdate) {
102579
102642
  var page = document.createElement("html");
102580
102643
  page.innerHTML = document.getElementsByTagName("html")[0].innerHTML;
102581
102644
  var scripts = page.getElementsByTagName("script");
@@ -102590,7 +102653,7 @@ code.hljs {
102590
102653
  if (onSendCb) {
102591
102654
  onSendCb();
102592
102655
  }
102593
- if (prevPageContent === pageContent) {
102656
+ if (prevPageContent === pageContent && !forceUpdate) {
102594
102657
  return;
102595
102658
  }
102596
102659
  prevPageContent = pageContent;
@@ -102599,7 +102662,7 @@ code.hljs {
102599
102662
  html: pageContent,
102600
102663
  url: window.location.href
102601
102664
  };
102602
- if (uiState.pageState.screenshot.enabled) {
102665
+ if (window._alanBtnState?.pageState?.screenshot?.enabled) {
102603
102666
  params.screenshot = await captureScreenshot();
102604
102667
  }
102605
102668
  window.tutorProject.call("syncPageState", params);
@@ -109295,6 +109358,18 @@ code.hljs {
109295
109358
  return null;
109296
109359
  return merged;
109297
109360
  }
109361
+ function safelyParseScriptOptions(optionsString) {
109362
+ if (!optionsString || optionsString === "null" || optionsString === "{}") {
109363
+ return null;
109364
+ }
109365
+ try {
109366
+ const cleanOptionsString = optionsString.trim();
109367
+ return Function('"use strict"; return (' + cleanOptionsString + ")")();
109368
+ } catch (error) {
109369
+ console.error("Failed to parse script options:", error);
109370
+ return null;
109371
+ }
109372
+ }
109298
109373
  function extractScriptContents(html) {
109299
109374
  const scriptContents = [];
109300
109375
  const parser2 = new DOMParser();
@@ -109738,7 +109813,9 @@ code.hljs {
109738
109813
  }
109739
109814
  }
109740
109815
 
109741
- renderDetailsContent(id, 'code');
109816
+ // Set default mode based on data type
109817
+ const defaultMode = detailsData.type === 'markdown' ? 'preview' : 'code';
109818
+ renderDetailsContent(id, defaultMode);
109742
109819
 
109743
109820
  }
109744
109821
 
@@ -109806,7 +109883,7 @@ code.hljs {
109806
109883
  <html lang="en">
109807
109884
  <head>
109808
109885
  <meta charset="UTF-8">
109809
- <title>Alan Text Chat History</title>
109886
+ <title>${chatName} Chat History</title>
109810
109887
  <script src="${LIBS_PREFIX}/d3.v7.min.js" type="text/javascript"><\/script>
109811
109888
  <script src="${LIBS_PREFIX}/viz-standalone.js" type="text/javascript"><\/script>
109812
109889
  <script src="${LIBS_PREFIX}/svg-pan-zoom.min.js" type="text/javascript"><\/script>
@@ -110098,7 +110175,7 @@ code.hljs {
110098
110175
 
110099
110176
  <div class="alan-history-content ${alanMainClass}">
110100
110177
  <div class="alan-btn__history-chat-header">
110101
- <h1>Alan Text Chat History</h1>
110178
+ <h1>${chatName} Chat History</h1>
110102
110179
  </div>
110103
110180
  <div class="alan-btn__history-chat alan-history-inner-content">
110104
110181
  ${chatConteiner.outerHTML}
@@ -110224,8 +110301,24 @@ code.hljs {
110224
110301
  let allInitIframeResourcesInlined = false;
110225
110302
  if (initIframeFn) {
110226
110303
  let initIframeBody = stripComments(initIframeFn);
110227
- const resourceRegex = /await iframe\.(addScript|addStyleSheet|addFont)\(['"]([^'"]+)['"]\)/g;
110228
- let resourceMatch;
110304
+ const resourceUrls = [];
110305
+ const iframeMethodRegex = /await\s+iframe\.(addScript|addStyleSheet|addFont)\s*\(\s*['"]([^'"]+)['"]\s*(?:,\s*({[^{}]*(?:{[^{}]*}[^{}]*)*}))?\s*\)/g;
110306
+ let iframeMatch;
110307
+ while ((iframeMatch = iframeMethodRegex.exec(initIframeBody)) !== null) {
110308
+ resourceUrls.push({
110309
+ type: iframeMatch[1],
110310
+ url: iframeMatch[2],
110311
+ options: iframeMatch[3] ? iframeMatch[3] : null
110312
+ });
110313
+ }
110314
+ const resourceUrlFnRegex = /(?:window|iframe|document)\.(?:getResourceUrl|getStudioResourceUrl)\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
110315
+ let resourceFnMatch;
110316
+ while ((resourceFnMatch = resourceUrlFnRegex.exec(initIframeBody)) !== null) {
110317
+ resourceUrls.push({
110318
+ type: "getResourceUrl",
110319
+ url: resourceFnMatch[1]
110320
+ });
110321
+ }
110229
110322
  const isValidUrlFn = extractFunction(code, "isValidUrl");
110230
110323
  const getResourceUrlFn = extractFunction(code, "getResourceUrl");
110231
110324
  const getStudioResourceUrlFn = extractFunction(code, "getStudioResourceUrl");
@@ -110291,30 +110384,45 @@ code.hljs {
110291
110384
  console.error("Failed to get or inline basic resources:", error);
110292
110385
  }
110293
110386
  }
110294
- while ((resourceMatch = resourceRegex.exec(initIframeBody)) !== null) {
110295
- const [_, resourceType, rawResourceUrl] = resourceMatch;
110387
+ for (const resource of resourceUrls) {
110296
110388
  try {
110297
- const resourceUrl = getResourceUrl(rawResourceUrl);
110389
+ const resourceUrl = getResourceUrl(resource.url);
110298
110390
  const response = await fetch(resourceUrl);
110299
110391
  if (!response.ok) {
110300
- console.error(`Failed to fetch ${resourceType} from ${resourceUrl}: ${response.statusText}`);
110392
+ console.error(`Failed to fetch resource from ${resourceUrl}: ${response.statusText}`);
110301
110393
  allInitIframeResourcesInlined = false;
110302
110394
  continue;
110303
110395
  }
110304
110396
  const resourceContent = await response.text();
110305
- if (resourceType === "addScript") {
110397
+ if (resource.type === "addScript" || resource.url.endsWith(".js")) {
110306
110398
  const inlineScript = doc.createElement("script");
110307
110399
  inlineScript.textContent = resourceContent;
110400
+ if (resource.options) {
110401
+ const optionsObj = safelyParseScriptOptions(resource.options);
110402
+ if (optionsObj && typeof optionsObj === "object") {
110403
+ if (optionsObj.type) {
110404
+ inlineScript.setAttribute("type", optionsObj.type);
110405
+ }
110406
+ if (optionsObj.defer)
110407
+ inlineScript.setAttribute("defer", "");
110408
+ if (optionsObj.async)
110409
+ inlineScript.setAttribute("async", "");
110410
+ if (optionsObj.nomodule)
110411
+ inlineScript.setAttribute("nomodule", "");
110412
+ if (optionsObj.crossOrigin)
110413
+ inlineScript.setAttribute("crossorigin", optionsObj.crossOrigin);
110414
+ }
110415
+ }
110308
110416
  doc.head.appendChild(inlineScript);
110309
- console.log(`Inlined script from initIframe fn: ${resourceUrl}`);
110310
- } else if (resourceType === "addStyleSheet") {
110417
+ console.log(`Inlined script: ${resourceUrl}${inlineScript.type ? " (type=" + inlineScript.type + ")" : ""}`);
110418
+ } else if (resource.type === "addStyleSheet" || resource.url.endsWith(".css")) {
110311
110419
  const inlineStyle = doc.createElement("style");
110312
110420
  inlineStyle.textContent = resourceContent;
110313
110421
  doc.head.appendChild(inlineStyle);
110314
- console.log(`Inlined stylesheet from initIframe fn: ${resourceUrl}`);
110422
+ console.log(`Inlined stylesheet: ${resourceUrl}`);
110315
110423
  }
110316
110424
  } catch (error) {
110317
- console.error(`Failed to inline ${resourceType} from ${rawResourceUrl}:`, error);
110425
+ console.error(`Failed to inline resource from ${resource.url}:`, error);
110318
110426
  allInitIframeResourcesInlined = false;
110319
110427
  }
110320
110428
  }
@@ -110343,6 +110451,9 @@ code.hljs {
110343
110451
  return msg.reqId || msg?.ctx?.reqId;
110344
110452
  ;
110345
110453
  }
110454
+ function getMsgResponseId(msg) {
110455
+ return msg.responseId || msg?.ctx?.responseId || msg?.ctx?.resId;
110456
+ }
110346
110457
 
110347
110458
  // alan_btn/src/textChat/helpers/shouldTextBeSavedInChatHistory.ts
110348
110459
  function shouldTextBeSavedInChatHistory(text, sentMessages) {
@@ -110500,7 +110611,7 @@ code.hljs {
110500
110611
 
110501
110612
  // alan_btn/alan_btn.ts
110502
110613
  (function(ns) {
110503
- uiState.lib.version = "alan-version.1.8.92".replace("alan-version.", "");
110614
+ uiState.lib.version = "alan-version.1.8.93".replace("alan-version.", "");
110504
110615
  if (window.alanBtn) {
110505
110616
  console.warn("Alan: the Alan Button source code has already added (v." + uiState.lib.version + ")");
110506
110617
  }
@@ -110830,6 +110941,11 @@ code.hljs {
110830
110941
  var playReadyToListenSound = true;
110831
110942
  var turnOffTimeout = 3e4;
110832
110943
  var turnOffVoiceFn;
110944
+ var completionText = "";
110945
+ var completionToInsert = "";
110946
+ var completions = [];
110947
+ var selectedCompletionIndex = -1;
110948
+ var complitionWasApplied = false;
110833
110949
  var dndInitMousePos2 = [0, 0];
110834
110950
  var dndIsDown = false;
110835
110951
  var btnWasMoved = false;
@@ -110857,6 +110973,16 @@ code.hljs {
110857
110973
  function getUserIdLsPrefix() {
110858
110974
  return uiState.userInfo?.userId ? `-${uiState.userInfo?.userId}` : "";
110859
110975
  }
110976
+ window._alanBtnState = {
110977
+ pageState: {
110978
+ screenshot: {
110979
+ enabled: false
110980
+ }
110981
+ }
110982
+ };
110983
+ if (isTutorMode()) {
110984
+ window._alanBtnState.pageState.screenshot.enabled = options?.pageState?.screenshot?.enabled;
110985
+ }
110860
110986
  var pulsatingAnimation = "";
110861
110987
  var pulsatingMicAnimation = "";
110862
110988
  var pulsatingTriangleMicAnimation = "";
@@ -111806,6 +111932,10 @@ code.hljs {
111806
111932
  param.ctx = {
111807
111933
  url: window.location.href
111808
111934
  };
111935
+ storeSocketHistory({
111936
+ type: "request",
111937
+ ...param
111938
+ });
111809
111939
  window.tutorProject.call("text", param, function(e, res) {
111810
111940
  if (e) {
111811
111941
  reject({ error: e });
@@ -112071,7 +112201,6 @@ code.hljs {
112071
112201
  }
112072
112202
  }
112073
112203
  if (isTutorMode()) {
112074
- uiState.pageState.screenshot.enabled = true;
112075
112204
  manageSyncPageStateListeners(true);
112076
112205
  }
112077
112206
  function changeOptions(options2) {
@@ -112172,7 +112301,9 @@ code.hljs {
112172
112301
  console.log("Alan: options received");
112173
112302
  console.timeEnd("Alan: receiving options time");
112174
112303
  saveOptions(data2);
112175
- uiState.pageState.screenshot.enabled = data2?.web?.pageState?.screenshot?.enabled;
112304
+ window._alanBtnState.pageState.screenshot.enabled = data2?.web?.pageState?.screenshot?.enabled;
112305
+ uiState.textChat.autocomplete.enabled = data2?.web?.chatOptions?.textChat?.textarea?.autocomplete?.enabled;
112306
+ uiState.textChat.maxCharactersCount = data2?.web?.chatOptions?.textChat?.textarea?.maxCharactersCount ? +data2?.web?.chatOptions?.textChat?.textarea?.maxCharactersCount : 2e4;
112176
112307
  changeOptions(getOptionsByTheme(data2?.web, uiState.currentTheme || options.theme));
112177
112308
  }
112178
112309
  function setUserId(userId) {
@@ -112254,6 +112385,8 @@ ${curDialogId}`);
112254
112385
  if (options.onConnectionStatus) {
112255
112386
  options.onConnectionStatus(res);
112256
112387
  }
112388
+ isMsgTypingInProcess = false;
112389
+ sendSyncPageState(true);
112257
112390
  }
112258
112391
  function onMicAllowed() {
112259
112392
  sendClientEvent({ micAllowed: true });
@@ -112391,6 +112524,7 @@ ${curDialogId}`);
112391
112524
  function _onTextCb(e) {
112392
112525
  clearMessageProgressStatusInterval();
112393
112526
  const event = Object.assign(e, { name: "text", type: "response" /* Response */ });
112527
+ storeSocketHistory(event);
112394
112528
  if (event.images?.length > 0) {
112395
112529
  event.images = filterImagesForTextChat(event.images);
112396
112530
  }
@@ -112409,6 +112543,9 @@ ${curDialogId}`);
112409
112543
  _onTextCb(e);
112410
112544
  }
112411
112545
  }
112546
+ function storeSocketHistory(event) {
112547
+ uiState.socketMessages.push({ ...event, socketTs: Date.now() });
112548
+ }
112412
112549
  function onQueryProgressCb(e) {
112413
112550
  if (uiState?.textChat?.options?.bubbles?.waitingResponse?.queryProgress?.enabled === false)
112414
112551
  return;
@@ -112420,6 +112557,7 @@ ${curDialogId}`);
112420
112557
  queryProgress: []
112421
112558
  }
112422
112559
  );
112560
+ storeSocketHistory(event);
112423
112561
  if (e.progress?.name) {
112424
112562
  event.queryProgress = [{
112425
112563
  text: e.progress?.name,
@@ -112438,6 +112576,7 @@ ${curDialogId}`);
112438
112576
  }
112439
112577
  function onParsedCbInMicBtn(e) {
112440
112578
  const event = Object.assign(e, { name: "parsed" });
112579
+ storeSocketHistory(event);
112441
112580
  if (options.onEvent) {
112442
112581
  options.onEvent(event);
112443
112582
  }
@@ -112446,6 +112585,7 @@ ${curDialogId}`);
112446
112585
  }
112447
112586
  function onRecognizedCbInMicBtn(e) {
112448
112587
  const event = Object.assign(e, { name: "recognized" });
112588
+ storeSocketHistory(event);
112449
112589
  if (options.onEvent) {
112450
112590
  options.onEvent(event);
112451
112591
  }
@@ -112894,6 +113034,7 @@ ${LEARN_MORE_LABEL}
112894
113034
  div.classList.add("alan-hide-msg-immidiatelly");
112895
113035
  });
112896
113036
  }
113037
+ let emptyMessages = {};
112897
113038
  function renderMessageInTextChat(msg, noAnimation, immidiateScroll) {
112898
113039
  if (!uiState.textChat.available)
112899
113040
  return;
@@ -112960,11 +113101,31 @@ ${LEARN_MORE_LABEL}
112960
113101
  }
112961
113102
  }
112962
113103
  msg = { ...msg, ...getMsgReadProp(msg, textChatIsHidden) };
112963
- const { isNew, msgInd, replaceLoader, updateResponse } = processMessageForChat(msg, textChatMessages);
113104
+ if (msg.type === "response" && msg.name === "text") {
113105
+ const msgResponseId = getMsgResponseId(msg);
113106
+ if (isFinalMessage(msg)) {
113107
+ if (emptyMessages[msgResponseId]) {
113108
+ return;
113109
+ }
113110
+ } else {
113111
+ if (isMsgEmpty(msg)) {
113112
+ emptyMessages[msgResponseId] = msg;
113113
+ return;
113114
+ }
113115
+ }
113116
+ delete emptyMessages[msgResponseId];
113117
+ }
113118
+ const { isNew, msgInd, replaceLoader, updateExistingResponse, skipUpdating } = processMessageForChat(msg, textChatMessages);
113119
+ if (skipUpdating) {
113120
+ return;
113121
+ }
112964
113122
  if (isNew) {
112965
113123
  var div = document.createElement("div");
112966
113124
  div.id = "msg-" + msgInd;
112967
113125
  div.setAttribute("data-request-id", getMsgReqId(msg));
113126
+ if (msg.type === "response") {
113127
+ div.setAttribute("data-response-id", getMsgResponseId(msg));
113128
+ }
112968
113129
  div.classList.add("alan-btn__chat-msg-holder");
112969
113130
  div.setAttribute("data-msg-index", msgInd);
112970
113131
  if (msg.type === "chat") {
@@ -113021,7 +113182,7 @@ ${LEARN_MORE_LABEL}
113021
113182
  }
113022
113183
  scrollTextChat(msgsScrollableContainer, "smooth");
113023
113184
  }
113024
- } else if (updateResponse && msg.type !== "chat") {
113185
+ } else if (updateExistingResponse && msg.type !== "chat") {
113025
113186
  let innerEl = msgEl.querySelector(".alan-btn__chat-inner-msg");
113026
113187
  if (innerEl) {
113027
113188
  if (innerEl.classList.contains("alan-hidden-loader")) {
@@ -113166,6 +113327,7 @@ ${LEARN_MORE_LABEL}
113166
113327
  window.alanIframes = {};
113167
113328
  connectToNewDialog();
113168
113329
  clearDOMChat();
113330
+ uiState.socketMessages = [];
113169
113331
  clearChatHistoryStorage();
113170
113332
  manageSaveChatHistoryBtn();
113171
113333
  }
@@ -113259,6 +113421,7 @@ ${LEARN_MORE_LABEL}
113259
113421
  }
113260
113422
  }
113261
113423
  async function _sendText(text) {
113424
+ manageAutocompeteInChat();
113262
113425
  var msg = { text, type: "request", name: "text" };
113263
113426
  sentMessageInd = null;
113264
113427
  clearMessageProgressStatusInterval();
@@ -113279,6 +113442,16 @@ ${LEARN_MORE_LABEL}
113279
113442
  const regId = getMsgReqId(msg);
113280
113443
  return canceledRequests.indexOf(regId) > -1;
113281
113444
  }
113445
+ function isMsgEmpty(msg) {
113446
+ let isEmpty2 = false;
113447
+ if (msg.type === "response" /* Response */ && msg.name === "text") {
113448
+ isEmpty2 = true;
113449
+ if (msg.images?.length > 0 || msg.links?.length > 0 || msg.suggestions?.length > 0 || msg.text !== "") {
113450
+ isEmpty2 = false;
113451
+ }
113452
+ }
113453
+ return isEmpty2;
113454
+ }
113282
113455
  function enableTextareaInTheChat() {
113283
113456
  var textareaHolderEl = document.getElementById("textarea-holder");
113284
113457
  textareaHolderEl.classList.remove("alan-btn__inactive");
@@ -113290,7 +113463,8 @@ ${LEARN_MORE_LABEL}
113290
113463
  var textareaEl = getChatTextareaEl();
113291
113464
  var textareaHolderEl = document.getElementById("textarea-holder");
113292
113465
  var text = textareaEl.value;
113293
- if (lastSendMsgTs) {
113466
+ var maxChars = uiState.textChat.maxCharactersCount || 2e4;
113467
+ if (lastSendMsgTs || text?.length > maxChars) {
113294
113468
  return;
113295
113469
  }
113296
113470
  lastSendMsgTs = setTimeout(() => {
@@ -113349,14 +113523,114 @@ ${LEARN_MORE_LABEL}
113349
113523
  }
113350
113524
  resizeTextArea();
113351
113525
  }
113352
- function onChatTextAreaChange(e) {
113526
+ let latestAutocompleteRequestId = 0;
113527
+ const fillChatAutocompleteDebounced = (0, import_lodash2.debounce)(() => {
113528
+ const requestId = ++latestAutocompleteRequestId;
113529
+ fillChatAutocomplete(requestId);
113530
+ }, 200);
113531
+ function onChatTextAreaChange(event) {
113353
113532
  resizeTextArea();
113533
+ manageAutocompeteInChat();
113534
+ manageSendButtonAvailability();
113535
+ }
113536
+ function manageAutocompeteInChat() {
113537
+ if (uiState.textChat?.autocomplete?.enabled === true) {
113538
+ checkIfNewComplitionNeeded();
113539
+ fillChatAutocompleteDebounced();
113540
+ }
113541
+ }
113542
+ function updateAutocompleteInChat(completion) {
113543
+ const chatAutocompleteEl = getAutocompleteChatTextareaEl();
113544
+ if (chatAutocompleteEl) {
113545
+ completionToInsert = completion || "";
113546
+ completionText = `${completionToInsert}`;
113547
+ chatAutocompleteEl.value = completionText;
113548
+ resizeTextArea();
113549
+ }
113550
+ }
113551
+ function checkIfNewComplitionNeeded() {
113552
+ const chatEl = getChatTextareaEl();
113553
+ const chatAutocompletEl = getAutocompleteChatTextareaEl();
113554
+ if (!chatEl || !chatAutocompletEl)
113555
+ return;
113556
+ const prefix = chatEl.value;
113557
+ const curComplitionText = completionText;
113558
+ if (!curComplitionText.startsWith(prefix) || prefix.trim() === "") {
113559
+ clearChatAutocomplete(true);
113560
+ }
113561
+ }
113562
+ function clearChatAutocomplete(fullClear) {
113563
+ const chatAutocompleteEl = getAutocompleteChatTextareaEl();
113564
+ if (chatAutocompleteEl && completionText?.length > 0) {
113565
+ chatAutocompleteEl.value = "";
113566
+ complitionWasApplied = false;
113567
+ if (fullClear) {
113568
+ completionToInsert = "";
113569
+ completionText = "";
113570
+ }
113571
+ }
113572
+ }
113573
+ function fillChatAutocomplete(requestId) {
113574
+ const maxChars = uiState.textChat.maxCharactersCount || 2e4;
113575
+ const chatEl = getChatTextareaEl();
113576
+ const chatAutocompletEl = getAutocompleteChatTextareaEl();
113577
+ if (!chatEl || !chatAutocompletEl)
113578
+ return;
113579
+ let prefix = chatEl.value;
113580
+ const curComplitionText = completionText;
113581
+ ;
113582
+ if (prefix.trim() === "" || curComplitionText.startsWith(prefix))
113583
+ return;
113584
+ if (prefix.length > maxChars)
113585
+ return;
113586
+ prefix = prefix.replace(/\n+$/, "");
113587
+ if (complitionWasApplied) {
113588
+ complitionWasApplied = false;
113589
+ return;
113590
+ }
113591
+ clearChatAutocomplete(true);
113592
+ if (window.tutorProject) {
113593
+ window.tutorProject.call("chatMessageCompletions", {
113594
+ prefix,
113595
+ candidates: 1
113596
+ }, (err, res) => {
113597
+ if (requestId !== latestAutocompleteRequestId)
113598
+ return;
113599
+ if (err) {
113600
+ console.error("Error getting chat autocompete:", err);
113601
+ updateAutocompleteInChat("");
113602
+ completions = [];
113603
+ } else {
113604
+ completions = res?.completions?.map((el) => `${prefix}${el}`) || [];
113605
+ updateAutocompleteInChat(`${prefix}${res?.completions[0]}`);
113606
+ }
113607
+ });
113608
+ }
113609
+ }
113610
+ function manageSendButtonAvailability() {
113611
+ const maxChars = uiState.textChat.maxCharactersCount || 2e4;
113612
+ const textareaEl = getChatTextareaEl();
113613
+ const sendBtn = document.getElementById("chat-send-btn");
113614
+ const errEl = document.getElementById("alan-btn__chat-footer-err");
113615
+ if (textareaEl && sendBtn && errEl) {
113616
+ if (textareaEl.value.length > 0 && textareaEl.value.length <= maxChars) {
113617
+ sendBtn.classList.remove("alan-btn__disabled");
113618
+ } else {
113619
+ sendBtn.classList.add("alan-btn__disabled");
113620
+ }
113621
+ if (textareaEl.value.length <= maxChars) {
113622
+ errEl.style.display = "none";
113623
+ } else {
113624
+ errEl.style.display = "block";
113625
+ }
113626
+ }
113354
113627
  }
113355
113628
  const resizeTextAreaDebounced = throttle(function() {
113356
113629
  resizeTextArea();
113357
113630
  }, 300);
113358
113631
  function resizeTextArea() {
113359
113632
  var el = getChatTextareaEl();
113633
+ var elAutocomplete = getAutocompleteChatTextareaEl();
113360
113634
  if (!el)
113361
113635
  return;
113362
113636
  const isMultiline = uiState.textChat.options?.textarea?.fieldType === "multi-line";
@@ -113371,7 +113645,13 @@ ${LEARN_MORE_LABEL}
113371
113645
  const lineHeight = fontSize * defaultLineHeight;
113372
113646
  const maxHeight = lineHeight * maxLinesCount + paddingsAndBorder;
113373
113647
  const defaultOneLineHeight = lineHeight + paddingsAndBorder;
113374
- el.style.height = `${getDynamicInputHeight(el, maxHeight)}px`;
113648
+ const inputHeight = getDynamicInputHeight(el, maxHeight);
113649
+ const autocompleteHeight = getDynamicInputHeight(elAutocomplete, maxHeight);
113650
+ const finalHeight = Math.max(inputHeight, autocompleteHeight);
113651
+ el.style.height = `${finalHeight}px`;
113652
+ if (elAutocomplete) {
113653
+ elAutocomplete.style.height = `${finalHeight}px`;
113654
+ }
113375
113655
  if (el.offsetHeight > defaultOneLineHeight) {
113376
113656
  el.closest("#textarea-holder")?.classList?.add("multi-line");
113377
113657
  } else {
@@ -113380,6 +113660,9 @@ ${LEARN_MORE_LABEL}
113380
113660
  } else {
113381
113661
  el.closest("#textarea-holder")?.classList?.remove("multi-line");
113382
113662
  el.style.height = `100%`;
113663
+ if (elAutocomplete) {
113664
+ elAutocomplete.style.height = `100%`;
113665
+ }
113383
113666
  }
113384
113667
  }
113385
113668
  function getDynamicInputHeight(el, maxHeight) {
@@ -113484,12 +113767,19 @@ ${LEARN_MORE_LABEL}
113484
113767
  range.select();
113485
113768
  }
113486
113769
  }
113770
+ function scrollCursorToEnd(el) {
113771
+ if (!el)
113772
+ return;
113773
+ if (el.tagName === "INPUT") {
113774
+ el.scrollLeft = el.scrollWidth;
113775
+ }
113776
+ }
113487
113777
  let isMsgTypingInProcess = false;
113488
- function sendSyncPageState() {
113778
+ function sendSyncPageState(forceUpdate = false) {
113489
113779
  if (!isMsgTypingInProcess) {
113490
113780
  syncPageState(function() {
113491
113781
  isMsgTypingInProcess = true;
113492
- });
113782
+ }, forceUpdate);
113493
113783
  }
113494
113784
  }
113495
113785
  function onChatTextAreaFocus() {
@@ -113498,6 +113788,7 @@ ${LEARN_MORE_LABEL}
113498
113788
  function onChatTextAreaBlur() {
113499
113789
  isMsgTypingInProcess = false;
113500
113790
  }
113791
+ let delPressed = 0;
113501
113792
  function onChatTextAreaKeyDown(e) {
113502
113793
  const keyCode = e.keyCode || e.which;
113503
113794
  sendSyncPageState();
@@ -113508,15 +113799,43 @@ ${LEARN_MORE_LABEL}
113508
113799
  addNewLine(e.target);
113509
113800
  return;
113510
113801
  }
113802
+ if (keyCode === 8) {
113803
+ delPressed++;
113804
+ if (delPressed > 6) {
113805
+ delPressed = 0;
113806
+ latestAutocompleteRequestId++;
113807
+ clearChatAutocomplete(true);
113808
+ }
113809
+ }
113511
113810
  if (keyCode === 13) {
113512
113811
  sendMessageToTextChat();
113513
113812
  e.stopPropagation();
113514
113813
  e.preventDefault();
113515
113814
  }
113815
+ if (keyCode === 9) {
113816
+ const chatAutocompleteEl = getAutocompleteChatTextareaEl();
113817
+ const newTextVal = chatAutocompleteEl?.value || "";
113818
+ if (newTextVal) {
113819
+ delPressed = 0;
113820
+ clearChatAutocomplete(false);
113821
+ moveCursorToEnd(e.target);
113822
+ setTimeout(() => {
113823
+ scrollCursorToEnd(e.target);
113824
+ });
113825
+ e.stopPropagation();
113826
+ e.preventDefault();
113827
+ complitionWasApplied = true;
113828
+ latestAutocompleteRequestId++;
113829
+ e.target.value = "";
113830
+ document.execCommand("insertText", false, completionToInsert || "");
113831
+ return;
113832
+ }
113833
+ }
113516
113834
  const goToPrev = keyCode === 38;
113517
113835
  const goToNext = keyCode === 40;
113518
113836
  const isMultiline = uiState.textChat.options?.textarea?.fieldType === "multi-line";
113519
113837
  if (!isMultiline && (goToPrev || goToNext)) {
113838
+ clearChatAutocomplete(true);
113520
113839
  switchMessages(keyCode);
113521
113840
  e.stopPropagation();
113522
113841
  e.preventDefault();
@@ -113587,6 +113906,9 @@ ${LEARN_MORE_LABEL}
113587
113906
  function getChatTextareaEl() {
113588
113907
  return document.getElementById("chatTextarea");
113589
113908
  }
113909
+ function getAutocompleteChatTextareaEl() {
113910
+ return document.getElementById("chatTextareaAutocomplete");
113911
+ }
113590
113912
  function addNeedClassesToExpandCollapseBtn(parentEl) {
113591
113913
  parentEl.children[0].classList.add("alan-btn__chat-enter-full-screen-mode");
113592
113914
  parentEl.children[1].classList.add("alan-btn__chat-exit-full-screen-mode");
@@ -113601,6 +113923,14 @@ ${LEARN_MORE_LABEL}
113601
113923
  el.addEventListener("keydown", onChatTextAreaKeyDown);
113602
113924
  el.addEventListener("keyup", onChatTextAreaKeyUp);
113603
113925
  el.addEventListener("input", onChatTextAreaChange);
113926
+ el.addEventListener("change", onChatTextAreaChange);
113927
+ return el;
113928
+ }
113929
+ function createAutocompleteInputNode(fieldType) {
113930
+ const el = document.createElement(fieldType);
113931
+ el.id = "chatTextareaAutocomplete";
113932
+ el.setAttribute("autocomplete", "off");
113933
+ el.classList.add("alan-btn__chat-textarea-autocomplete");
113604
113934
  return el;
113605
113935
  }
113606
113936
  function manageSaveChatHistoryBtn() {
@@ -113618,6 +113948,7 @@ ${LEARN_MORE_LABEL}
113618
113948
  var textareaInnerDiv = document.getElementById("textarea-inner-holder");
113619
113949
  var textareaHolderDiv = document.getElementById("textarea-holder-content");
113620
113950
  var chatTextarea = getChatTextareaEl();
113951
+ var chatTextareaAutocomplete = getAutocompleteChatTextareaEl();
113621
113952
  var chatMicBtn = document.getElementById("chat-mic-btn");
113622
113953
  var unmuteAlanBtn = document.getElementById("chat-unmute-btn");
113623
113954
  var chatSendBtn = document.getElementById("chat-send-btn");
@@ -113704,11 +114035,13 @@ ${LEARN_MORE_LABEL}
113704
114035
  var textareaDivGr = document.createElement("div");
113705
114036
  textareaDivGr.classList.add("alan-btn__chat-textarea-holder-gradient");
113706
114037
  chatTextarea = createTextInputNode(isMultiline ? "textarea" : "input");
114038
+ chatTextareaAutocomplete = createAutocompleteInputNode(isMultiline ? "textarea" : "input");
113707
114039
  chatSendBtn = document.createElement("div");
113708
114040
  chatSendBtn.id = "chat-send-btn";
113709
114041
  chatSendBtn.classList.add("alan-btn__chat-send-btn");
113710
114042
  chatSendBtn.addEventListener("click", sendMessageToTextChat);
113711
114043
  textareaInnerDiv.appendChild(chatTextarea);
114044
+ textareaInnerDiv.appendChild(chatTextareaAutocomplete);
113712
114045
  textareaHolderDiv.appendChild(clearChatBtn);
113713
114046
  textareaHolderDiv.appendChild(textareaInnerDiv);
113714
114047
  textareaDiv.appendChild(textareaHolderDiv);
@@ -113716,18 +114049,37 @@ ${LEARN_MORE_LABEL}
113716
114049
  chatDiv.appendChild(headerDiv);
113717
114050
  chatDiv.appendChild(messagesWrapperDiv);
113718
114051
  chatDiv.appendChild(textareaDiv);
114052
+ if (options.textChat?.footerInfoElement) {
114053
+ const footerDiv = createDiv({ class: "alan-btn__chat-footer-info" });
114054
+ footerDiv.appendChild(options.textChat.footerInfoElement);
114055
+ textareaDiv.appendChild(footerDiv);
114056
+ }
114057
+ const footerErrDiv = createDiv({ id: "alan-btn__chat-footer-err", class: "alan-btn__chat-footer-err" });
114058
+ footerErrDiv.innerHTML = "Message too long. Please shorten it.";
114059
+ footerErrDiv.style.display = "none";
114060
+ textareaDiv.prepend(footerErrDiv);
113719
114061
  chatDiv.appendChild(headerDivGr);
113720
114062
  chatHolderDiv.classList.add("alan-btn__chat-holder");
113721
114063
  }
113722
114064
  const tagName = chatTextarea?.tagName?.toLowerCase();
114065
+ const chatParentNode = document.getElementById("textarea-inner-holder");
114066
+ ++latestAutocompleteRequestId;
113723
114067
  if (tagName === "input" && isMultiline) {
113724
114068
  const newTextareaEl = createTextInputNode("textarea");
114069
+ const newAutocompleteTextareaEl = createAutocompleteInputNode("textarea");
113725
114070
  newTextareaEl.placeholder = chatTextarea.placeholder;
113726
- chatTextarea.parentNode.replaceChild(newTextareaEl, chatTextarea);
114071
+ chatParentNode.replaceChild(newTextareaEl, chatTextarea);
114072
+ if (chatTextareaAutocomplete.parentNode) {
114073
+ chatParentNode.replaceChild(newAutocompleteTextareaEl, chatTextareaAutocomplete);
114074
+ }
113727
114075
  } else if (tagName === "textarea" && !isMultiline) {
113728
114076
  const newTextareaEl = createTextInputNode("input");
114077
+ const newAutocompleteTextareaEl = createAutocompleteInputNode("input");
113729
114078
  newTextareaEl.placeholder = chatTextarea.placeholder;
113730
- chatTextarea.parentNode.replaceChild(newTextareaEl, chatTextarea);
114079
+ chatParentNode.replaceChild(newTextareaEl, chatTextarea);
114080
+ if (chatTextareaAutocomplete.parentNode) {
114081
+ chatParentNode.replaceChild(newAutocompleteTextareaEl, chatTextareaAutocomplete);
114082
+ }
113731
114083
  }
113732
114084
  setTimeout(() => {
113733
114085
  resizeTextArea();
@@ -113959,11 +114311,16 @@ ${LEARN_MORE_LABEL}
113959
114311
  const styles = head.querySelectorAll(styleSelectors.join(", "));
113960
114312
  const combinedStylesHTML = Array.from(styles).map((style) => style.outerHTML).join("\n");
113961
114313
  const txtMessages = JSON.stringify(textChatMessages, null, 2);
114314
+ const socketMessages = JSON.stringify(uiState.socketMessages, null, 2);
113962
114315
  const customHeadContent = `
113963
114316
  ${combinedStylesHTML}
113964
114317
 
113965
114318
  <script>
113966
- console.info('Messages in chat:', ${txtMessages});
114319
+ function showAlanDebugLogs() {
114320
+ console.info('Alan lib v: ${uiState.lib.version}');
114321
+ console.info('Messages in chat:', ${txtMessages});
114322
+ console.info('Messages in socket:', ${socketMessages});
114323
+ }
113967
114324
  <\/script>
113968
114325
  `;
113969
114326
  const initChat = document.querySelector("#chatMessagesWrapper");
@@ -114814,7 +115171,8 @@ ${LEARN_MORE_LABEL}
114814
115171
  }
114815
115172
  });
114816
115173
  }
114817
- }
115174
+ },
115175
+ getSocketMessages
114818
115176
  },
114819
115177
  writable: false,
114820
115178
  configurable: false