@blotoutio/providers-shop-gpt-sdk 1.7.1 → 1.9.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.
Files changed (4) hide show
  1. package/index.cjs.js +400 -101
  2. package/index.js +400 -101
  3. package/index.mjs +400 -101
  4. package/package.json +1 -1
package/index.js CHANGED
@@ -365,6 +365,50 @@ var ProvidersShopGptSdk = (function () {
365
365
  ]);
366
366
  new Set([...isoCountries.keys(), ...usStates.keys()]);
367
367
 
368
+ const createEnabled = () => ({
369
+ name: 'enabled',
370
+ groupNames: new Set(),
371
+ groupName: '',
372
+ isEnabled: true,
373
+ });
374
+ const createDisabled = () => ({
375
+ name: 'disabled',
376
+ groupNames: new Set(),
377
+ groupName: '',
378
+ isEnabled: false,
379
+ });
380
+ const createABTest = ({ userId }) => {
381
+ const [sample] = userId.split('-');
382
+ const segment = parseInt(sample, 16) % 2;
383
+ return {
384
+ name: 'ab-test',
385
+ groupNames: new Set(['enabled', 'control']),
386
+ groupName: segment == 1 ? 'enabled' : 'control',
387
+ isEnabled: segment == 1,
388
+ };
389
+ };
390
+ const createPreview = ({ preview }) => {
391
+ return {
392
+ name: 'preview',
393
+ groupNames: new Set(['preview']),
394
+ groupName: preview ? 'preview' : '',
395
+ isEnabled: preview !== null && preview !== void 0 ? preview : false,
396
+ };
397
+ };
398
+ const getExperimentName = (mode) => (mode !== null && mode !== void 0 ? mode : 'disabled');
399
+ const createExperiment = (props) => {
400
+ switch (props.name) {
401
+ case 'enabled':
402
+ return createEnabled();
403
+ case 'disabled':
404
+ return createDisabled();
405
+ case 'ab-test':
406
+ return createABTest(props);
407
+ case 'preview':
408
+ return createPreview(props);
409
+ }
410
+ };
411
+
368
412
  const packageName = 'shopGPT';
369
413
  const DEFAULT_MAX_THREAD_AGE = 14;
370
414
  const previewKeyName = 'previewShopGPT';
@@ -429,7 +473,6 @@ var ProvidersShopGptSdk = (function () {
429
473
  return url;
430
474
  };
431
475
  const processQuery = async (query, threadId, productHandle) => {
432
- var _a;
433
476
  const response = await fetchImpl(getURL('/query'), {
434
477
  method: 'POST',
435
478
  headers: getHeaders(),
@@ -444,14 +487,7 @@ var ProvidersShopGptSdk = (function () {
444
487
  if (!response.ok) {
445
488
  throw new Error(`Failed to process the query - ${response.status}: ${await response.text()}`);
446
489
  }
447
- const data = (await response.json());
448
- return {
449
- messageId: data.messageId,
450
- message: data.message,
451
- products: (_a = data.products) === null || _a === void 0 ? void 0 : _a.filter((item) => !!item).map((item) => ({ ...item, quantity: 1 })),
452
- chatTitle: data.chatTitle,
453
- welcomePrompts: data.welcomePrompts,
454
- };
490
+ return response;
455
491
  };
456
492
  const fetchChatHistory = async (threadId) => {
457
493
  if (!threadId) {
@@ -531,6 +567,18 @@ var ProvidersShopGptSdk = (function () {
531
567
  throw new Error(`Failed to save feedback - ${response.status}: ${await response.text()}`);
532
568
  }
533
569
  };
570
+ const fetchCustomPrompts = async (threadId) => {
571
+ const response = await fetchImpl(getURL(`/custom-prompts?threadId=${threadId}`), {
572
+ method: 'GET',
573
+ headers: getHeaders(),
574
+ credentials: 'include',
575
+ });
576
+ if (!response.ok) {
577
+ throw new Error(`Could not fetch custom prompts - ${response.status}: ${await response.text()}`);
578
+ }
579
+ const data = (await response.json());
580
+ return data.customPrompts;
581
+ };
534
582
  return {
535
583
  processQuery,
536
584
  fetchChatHistory,
@@ -539,6 +587,7 @@ var ProvidersShopGptSdk = (function () {
539
587
  deleteSingleThread,
540
588
  deleteAllThreads,
541
589
  saveFeedback,
590
+ fetchCustomPrompts,
542
591
  };
543
592
  };
544
593
 
@@ -572,11 +621,15 @@ var ProvidersShopGptSdk = (function () {
572
621
  // exit if not in top window
573
622
  return;
574
623
  }
575
- const { enabled, devMode, merchantUrl, profiles, productHandles, targetPath, uiMode, brandName, quickPrompts, merchantImage, latestThreadLoad, } = (_c = params.manifest.variables) !== null && _c !== void 0 ? _c : {};
576
- let shouldShowUI = enabled;
577
- if (!enabled && hasPreviewKey()) {
624
+ const { enabled, mode, devMode, merchantUrl, profiles, productHandles, targetPath, view, brandName, quickPrompts, merchantImage, latestThreadLoad, botIconUrl, css, } = (_c = params.manifest.variables) !== null && _c !== void 0 ? _c : {};
625
+ const experiment = createExperiment({
626
+ name: getExperimentName(mode),
627
+ userId: params.userId,
628
+ preview: hasPreviewKey(),
629
+ });
630
+ const shouldShowUI = enabled || experiment.isEnabled;
631
+ if (experiment.name === 'preview' && shouldShowUI) {
578
632
  logger.log('Enabling UI in preview mode');
579
- shouldShowUI = true;
580
633
  }
581
634
  if (shouldShowUI) {
582
635
  const uiImplementation = window[registryKey].ui;
@@ -593,7 +646,7 @@ var ProvidersShopGptSdk = (function () {
593
646
  storeAPI,
594
647
  shopGPTAPI,
595
648
  devMode,
596
- uiMode,
649
+ view,
597
650
  merchantUrl,
598
651
  profiles,
599
652
  productHandles,
@@ -602,6 +655,8 @@ var ProvidersShopGptSdk = (function () {
602
655
  quickPrompts,
603
656
  merchantImage,
604
657
  latestThreadLoad: latestThreadLoad !== null && latestThreadLoad !== void 0 ? latestThreadLoad : DEFAULT_MAX_THREAD_AGE,
658
+ botIconUrl,
659
+ css,
605
660
  });
606
661
  }
607
662
  };
@@ -728,6 +783,14 @@ var ProvidersShopGptSdk = (function () {
728
783
  const shopGPTStyles = i$4 `
729
784
  ${scrollBarStyles}
730
785
 
786
+ :host {
787
+ --shopgpt-primary: #001531;
788
+ --shopgpt-secondary: #172a41;
789
+ --shopgpt-white: #ffffff;
790
+ --shopgpt-border: #dbe2eb;
791
+ --shopgpt-warning: #ffcc81;
792
+ }
793
+
731
794
  * {
732
795
  box-sizing: border-box;
733
796
  }
@@ -760,6 +823,7 @@ var ProvidersShopGptSdk = (function () {
760
823
  0px 20px 20px 0px rgba(0, 0, 0, 0.08);
761
824
  position: fixed;
762
825
  z-index: 2000;
826
+ background: var(--shopgpt-white);
763
827
 
764
828
  @media screen and (max-width: 768px) {
765
829
  min-height: unset;
@@ -778,21 +842,21 @@ var ProvidersShopGptSdk = (function () {
778
842
  z-index: 1000;
779
843
 
780
844
  button {
781
- color: #ffffff;
845
+ color: var(--shopgpt-white);
782
846
  border: none;
783
847
  cursor: pointer;
784
848
  width: 56px;
785
849
  height: 56px;
786
- background-color: #001531;
850
+ background-color: var(--shopgpt-primary);
787
851
  border-radius: 50%;
788
852
  justify-content: center;
789
853
  align-items: center;
790
- box-shadow: 0 0 4px 1px #ffffff;
854
+ box-shadow: 0 0 4px 1px var(--shopgpt-white);
791
855
  }
792
856
 
793
857
  .chatbot-hover-text {
794
858
  position: absolute;
795
- color: #172a41;
859
+ color: var(--shopgpt-secondary);
796
860
  padding: 8px;
797
861
  white-space: nowrap;
798
862
  font-size: 16px;
@@ -805,7 +869,7 @@ var ProvidersShopGptSdk = (function () {
805
869
  right: calc(100% + 5px);
806
870
 
807
871
  border-radius: 5px 5px 0px;
808
- background: #ffcc81;
872
+ background: var(--shopgpt-warning);
809
873
  box-shadow: 0px 4px 6px -1px rgba(0, 0, 0, 0.1),
810
874
  0px 2px 4px -1px rgba(0, 0, 0, 0.06);
811
875
 
@@ -827,7 +891,7 @@ var ProvidersShopGptSdk = (function () {
827
891
  display: flex;
828
892
  overflow: hidden;
829
893
  height: 100%;
830
- background: #ffffff;
894
+ background: var(--shopgpt-white);
831
895
  justify-content: center;
832
896
  align-items: center;
833
897
  padding: 25px;
@@ -838,7 +902,7 @@ var ProvidersShopGptSdk = (function () {
838
902
  .shopgpt-container {
839
903
  display: flex;
840
904
  gap: 1px;
841
- background: #dbe2eb;
905
+ background: var(--shopgpt-border);
842
906
  height: 100%;
843
907
  width: 100%;
844
908
 
@@ -1013,6 +1077,10 @@ var ProvidersShopGptSdk = (function () {
1013
1077
  &:hover {
1014
1078
  background: #091627;
1015
1079
  }
1080
+
1081
+ &:disabled {
1082
+ cursor: not-allowed;
1083
+ }
1016
1084
  }
1017
1085
 
1018
1086
  .history {
@@ -1161,6 +1229,16 @@ var ProvidersShopGptSdk = (function () {
1161
1229
  constructor() {
1162
1230
  super(...arguments);
1163
1231
  this.deleteAllThreads = false;
1232
+ this.isStylesheetInjected = false;
1233
+ }
1234
+ connectedCallback() {
1235
+ super.connectedCallback();
1236
+ if (!this.isStylesheetInjected && this.css) {
1237
+ const sheet = new CSSStyleSheet();
1238
+ sheet.replaceSync(this.css);
1239
+ this.shadowRoot.adoptedStyleSheets.push(sheet);
1240
+ this.isStylesheetInjected = true;
1241
+ }
1164
1242
  }
1165
1243
  getDomain() {
1166
1244
  var _a;
@@ -1258,6 +1336,7 @@ var ProvidersShopGptSdk = (function () {
1258
1336
  <span class="line"></span>
1259
1337
  <button
1260
1338
  class="btn-new-search"
1339
+ ?disabled=${this.isLoading || this.isTyping}
1261
1340
  @click=${() => this.setSelectedThreadId('')}
1262
1341
  >
1263
1342
  New Search
@@ -1266,7 +1345,7 @@ var ProvidersShopGptSdk = (function () {
1266
1345
  ${this.merchantUrl
1267
1346
  ? x `<div class="footer">
1268
1347
  Catalog:
1269
- <a href="${this.getDomain()}" target="_blank">
1348
+ <a href="${this.getDomain()}" target="_blank" rel="noopener">
1270
1349
  ${this.getDomain().replace('https://', '')}
1271
1350
  </a>
1272
1351
  </div>`
@@ -1328,6 +1407,10 @@ var ProvidersShopGptSdk = (function () {
1328
1407
  r(),
1329
1408
  __metadata("design:type", Object)
1330
1409
  ], ChatThreads.prototype, "deleteAllThreads", void 0);
1410
+ __decorate([
1411
+ n({ type: String }),
1412
+ __metadata("design:type", String)
1413
+ ], ChatThreads.prototype, "css", void 0);
1331
1414
  if (!customElements.get('chat-threads')) {
1332
1415
  customElements.define('chat-threads', ChatThreads);
1333
1416
  }
@@ -1766,8 +1849,18 @@ var ProvidersShopGptSdk = (function () {
1766
1849
  }
1767
1850
 
1768
1851
  class ProductsSection extends r$2 {
1852
+ constructor() {
1853
+ super(...arguments);
1854
+ this.isStylesheetInjected = false;
1855
+ }
1769
1856
  connectedCallback() {
1770
1857
  super.connectedCallback();
1858
+ if (!this.isStylesheetInjected && this.css) {
1859
+ const sheet = new CSSStyleSheet();
1860
+ sheet.replaceSync(this.css);
1861
+ this.shadowRoot.adoptedStyleSheets.push(sheet);
1862
+ this.isStylesheetInjected = true;
1863
+ }
1771
1864
  }
1772
1865
  renderMerchantImage() {
1773
1866
  if (this.merchantImage) {
@@ -1844,6 +1937,10 @@ var ProvidersShopGptSdk = (function () {
1844
1937
  e$3('.products'),
1845
1938
  __metadata("design:type", Object)
1846
1939
  ], ProductsSection.prototype, "productsEle", void 0);
1940
+ __decorate([
1941
+ n({ type: String }),
1942
+ __metadata("design:type", String)
1943
+ ], ProductsSection.prototype, "css", void 0);
1847
1944
  if (!customElements.get('products-section')) {
1848
1945
  customElements.define('products-section', ProductsSection);
1849
1946
  }
@@ -1960,8 +2057,8 @@ var ProvidersShopGptSdk = (function () {
1960
2057
  }
1961
2058
 
1962
2059
  .chatbot-section.modal-view {
1963
- height: calc(100% - 121px);
1964
- padding: 0px 16px 44px;
2060
+ height: calc(100% - 93px);
2061
+ padding: 0px 16px 16px;
1965
2062
  gap: 16px;
1966
2063
  }
1967
2064
 
@@ -2110,6 +2207,9 @@ var ProvidersShopGptSdk = (function () {
2110
2207
  border-radius: 5px;
2111
2208
  border: 1px solid #dbe2eb;
2112
2209
  background: #fff;
2210
+ width: 36px;
2211
+ height: 36px;
2212
+ box-sizing: border-box;
2113
2213
  }
2114
2214
 
2115
2215
  .line {
@@ -2237,6 +2337,7 @@ var ProvidersShopGptSdk = (function () {
2237
2337
  padding: 10px;
2238
2338
  border-radius: 10px;
2239
2339
  border: 1px solid #a3b2c6;
2340
+ text-decoration: none;
2240
2341
 
2241
2342
  color: #4e647f;
2242
2343
  line-height: 21px;
@@ -2345,6 +2446,17 @@ var ProvidersShopGptSdk = (function () {
2345
2446
  }
2346
2447
  }
2347
2448
 
2449
+ footer {
2450
+ text-align: center;
2451
+ font-size: 10px;
2452
+ color: #4e647f;
2453
+ font-weight: 500;
2454
+
2455
+ a {
2456
+ text-decoration: none;
2457
+ }
2458
+ }
2459
+
2348
2460
  ${scrollBarStyles}
2349
2461
  `;
2350
2462
 
@@ -2988,7 +3100,7 @@ var ProvidersShopGptSdk = (function () {
2988
3100
  stash[--si] = p4
2989
3101
  ? p2
2990
3102
  ? `<img src="${p4}" alt="${p3}"/>`
2991
- : `<a href="${p4}">${highlight(p3)}</a>`
3103
+ : `<a href="${p4}" rel="noopener">${highlight(p3)}</a>`
2992
3104
  : p6;
2993
3105
  return `${si}\uf8ff`;
2994
3106
  });
@@ -3014,12 +3126,12 @@ var ProvidersShopGptSdk = (function () {
3014
3126
  };
3015
3127
 
3016
3128
  class MarkdownRenderer extends r$2 {
3129
+ constructor() {
3130
+ super(...arguments);
3131
+ this.content = '';
3132
+ }
3017
3133
  render() {
3018
- // Remove lit markers from slot content
3019
- const slotContent = this.innerHTML
3020
- .trim()
3021
- .replace(/<!--\?lit\$[\d$]+-->/g, '');
3022
- return o(markdown(slotContent));
3134
+ return o(markdown(this.content));
3023
3135
  }
3024
3136
  }
3025
3137
  MarkdownRenderer.styles = i$4 `
@@ -3033,6 +3145,10 @@ var ProvidersShopGptSdk = (function () {
3033
3145
  }
3034
3146
  }
3035
3147
  `;
3148
+ __decorate([
3149
+ n({ type: String }),
3150
+ __metadata("design:type", Object)
3151
+ ], MarkdownRenderer.prototype, "content", void 0);
3036
3152
  if (!customElements.get('markdown-renderer')) {
3037
3153
  customElements.define('markdown-renderer', MarkdownRenderer);
3038
3154
  }
@@ -3488,6 +3604,16 @@ ${this.comment ? this.comment : E}</textarea
3488
3604
  this.showChatThreads = false;
3489
3605
  this.deleteAllThreads = false;
3490
3606
  this.userQuery = '';
3607
+ this.isStylesheetInjected = false;
3608
+ }
3609
+ connectedCallback() {
3610
+ super.connectedCallback();
3611
+ if (!this.isStylesheetInjected && this.css) {
3612
+ const sheet = new CSSStyleSheet();
3613
+ sheet.replaceSync(this.css);
3614
+ this.shadowRoot.adoptedStyleSheets.push(sheet);
3615
+ this.isStylesheetInjected = true;
3616
+ }
3491
3617
  }
3492
3618
  scrollToBottom() {
3493
3619
  var _a;
@@ -3558,12 +3684,12 @@ ${this.comment ? this.comment : E}</textarea
3558
3684
  return x `
3559
3685
  <div class="message-wrapper">
3560
3686
  <div class="message bot">
3561
- <div>
3562
- <div class="bot-icon">${botIcon}</div>
3563
- </div>
3687
+ <div>${this.renderBotIcon()}</div>
3564
3688
  <div>
3565
3689
  ${message.message
3566
- ? x ` <markdown-renderer>${message.message}</markdown-renderer>`
3690
+ ? x ` <markdown-renderer
3691
+ .content=${message.message}
3692
+ ></markdown-renderer>`
3567
3693
  : E}
3568
3694
  ${this.viewType !== 'modal' && ((_a = message.products) === null || _a === void 0 ? void 0 : _a[0])
3569
3695
  ? x `
@@ -3608,6 +3734,14 @@ ${this.comment ? this.comment : E}</textarea
3608
3734
  </div>
3609
3735
  `;
3610
3736
  }
3737
+ renderBotIcon() {
3738
+ if (this.botIconUrl) {
3739
+ return x `<div class="bot-icon">
3740
+ <img src=${this.botIconUrl} width="30" height="30" />
3741
+ </div>`;
3742
+ }
3743
+ return x ` <div class="bot-icon">${botIcon}</div> `;
3744
+ }
3611
3745
  chatWindow() {
3612
3746
  if (this.isLoadingHistory || this.isLoadingThreads) {
3613
3747
  return x `<div class="messages loading">
@@ -3618,17 +3752,13 @@ ${this.comment ? this.comment : E}</textarea
3618
3752
  <div class="messages">
3619
3753
  ${this.isTyping
3620
3754
  ? x ` <div class="message bot">
3621
- <div>
3622
- <div class="bot-icon">${botIcon}</div>
3623
- </div>
3755
+ <div>${this.renderBotIcon()}</div>
3624
3756
  ${this.typingIndicator()}
3625
3757
  </div>`
3626
3758
  : ''}
3627
3759
  ${this.isFailed
3628
3760
  ? x `<div class="message bot">
3629
- <div>
3630
- <div class="bot-icon">${botIcon}</div>
3631
- </div>
3761
+ <div>${this.renderBotIcon()}</div>
3632
3762
  <div>
3633
3763
  <p>
3634
3764
  Uh-oh! Looks like I tripped over some alpha-stage wires.
@@ -3639,16 +3769,14 @@ ${this.comment ? this.comment : E}</textarea
3639
3769
  </div>
3640
3770
  </div>`
3641
3771
  : E}
3642
- ${this.messages.map((message) => {
3772
+ ${o$1(this.messages, (message) => {
3643
3773
  if (message.sender === 'bot') {
3644
3774
  return this.botMessage(message);
3645
3775
  }
3646
3776
  return x ` <div class="message user">${message.message}</div> `;
3647
3777
  })}
3648
3778
  <div class="message bot">
3649
- <div>
3650
- <div class="bot-icon">${botIcon}</div>
3651
- </div>
3779
+ <div>${this.renderBotIcon()}</div>
3652
3780
  <div>
3653
3781
  <p>
3654
3782
  Hi,
@@ -3661,28 +3789,39 @@ ${this.comment ? this.comment : E}</textarea
3661
3789
  </div>
3662
3790
  `;
3663
3791
  }
3664
- quickPrompts() {
3792
+ renderPrompts() {
3665
3793
  if (this.isLoadingHistory || this.isTyping || this.isLoadingThreads) {
3666
3794
  return E;
3667
3795
  }
3796
+ const isWelcomeMessage = this.messages.length === 1 && this.messages[0].sender === 'bot';
3668
3797
  const prompts = this.messages.length
3669
3798
  ? this.messages[0].welcomePrompts
3670
3799
  : this.prompts
3671
3800
  ? this.prompts.split(',').map((prompt) => prompt.trim())
3672
3801
  : ['Best Sellers'];
3673
- if (!prompts) {
3802
+ const customPrompts = !this.messages.length || isWelcomeMessage ? this.customPrompts : undefined;
3803
+ if (!prompts && !customPrompts) {
3674
3804
  return E;
3675
3805
  }
3676
3806
  return x `
3677
3807
  <div class="prompts btn">
3678
- ${prompts.map((prompt) => x `
3679
- <div
3680
- class="prompt"
3681
- @click=${(e) => this.processMessage(e, prompt)}
3682
- >
3683
- ${prompt}
3684
- </div>
3685
- `)}
3808
+ ${o$1(prompts, (prompt) => {
3809
+ return x `
3810
+ <div
3811
+ class="prompt"
3812
+ @click=${(e) => this.processMessage(e, prompt)}
3813
+ >
3814
+ ${prompt}
3815
+ </div>
3816
+ `;
3817
+ })}
3818
+ ${o$1(customPrompts, ({ prompt, link }) => {
3819
+ return x `
3820
+ <a class="prompt" href=${link} target="_blank" rel="noopener">
3821
+ ${prompt}
3822
+ </a>
3823
+ `;
3824
+ })}
3686
3825
  </div>
3687
3826
  `;
3688
3827
  }
@@ -3762,7 +3901,11 @@ ${this.comment ? this.comment : E}</textarea
3762
3901
  modalViewHeader() {
3763
3902
  var _a;
3764
3903
  return x `
3765
- <div>${botIcon}</div>
3904
+ <div>
3905
+ ${this.botIconUrl
3906
+ ? x `<img src=${this.botIconUrl} width="30" height="30" />`
3907
+ : botIcon}
3908
+ </div>
3766
3909
  <h2>${((_a = this.thread) === null || _a === void 0 ? void 0 : _a.title) || 'New Search'}</h2>
3767
3910
  <div class="btns-wrapper">
3768
3911
  <tooltip-component .position=${'bottom-right'} .text=${'New Chat'}>
@@ -3929,7 +4072,7 @@ ${this.comment ? this.comment : E}</textarea
3929
4072
  'modal-view': this.viewType === 'modal',
3930
4073
  })}
3931
4074
  >
3932
- ${this.chatWindow()} ${this.quickPrompts()}
4075
+ ${this.chatWindow()} ${this.renderPrompts()}
3933
4076
  <form class="chat-form" @submit=${this.onSubmit}>
3934
4077
  <input
3935
4078
  type="text"
@@ -3948,6 +4091,11 @@ ${this.comment ? this.comment : E}</textarea
3948
4091
  ${sendFilledIcon}
3949
4092
  </button>
3950
4093
  </form>
4094
+ ${this.viewType === 'modal'
4095
+ ? x ` <footer>
4096
+ Powered by <a href="https://blotout.io">Blotout</a>
4097
+ </footer>`
4098
+ : E}
3951
4099
  </div>
3952
4100
  <personalize-dialog
3953
4101
  .createChatThread=${this.createChatThread.bind(this)}
@@ -4004,6 +4152,10 @@ ${this.comment ? this.comment : E}</textarea
4004
4152
  n({ type: String }),
4005
4153
  __metadata("design:type", Object)
4006
4154
  ], ChatSection.prototype, "merchantImage", void 0);
4155
+ __decorate([
4156
+ n({ type: String }),
4157
+ __metadata("design:type", Object)
4158
+ ], ChatSection.prototype, "botIconUrl", void 0);
4007
4159
  __decorate([
4008
4160
  n({ type: String }),
4009
4161
  __metadata("design:type", Object)
@@ -4012,6 +4164,10 @@ ${this.comment ? this.comment : E}</textarea
4012
4164
  n({ type: String }),
4013
4165
  __metadata("design:type", Object)
4014
4166
  ], ChatSection.prototype, "prompts", void 0);
4167
+ __decorate([
4168
+ n({ type: Array }),
4169
+ __metadata("design:type", Object)
4170
+ ], ChatSection.prototype, "customPrompts", void 0);
4015
4171
  __decorate([
4016
4172
  n({ type: Boolean }),
4017
4173
  __metadata("design:type", Boolean)
@@ -4088,15 +4244,69 @@ ${this.comment ? this.comment : E}</textarea
4088
4244
  n({ type: String }),
4089
4245
  __metadata("design:type", Object)
4090
4246
  ], ChatSection.prototype, "userQuery", void 0);
4247
+ __decorate([
4248
+ n({ type: String }),
4249
+ __metadata("design:type", String)
4250
+ ], ChatSection.prototype, "css", void 0);
4091
4251
  if (!customElements.get('chat-section')) {
4092
4252
  customElements.define('chat-section', ChatSection);
4093
4253
  }
4094
4254
 
4255
+ const handleEventSource = async (response, onEvent) => {
4256
+ var _a, _b;
4257
+ if (!response.body) {
4258
+ throw new Error('No body found in response');
4259
+ }
4260
+ let buffer = '';
4261
+ for await (const chunk of response.body.pipeThrough(new TextDecoderStream())) {
4262
+ buffer += chunk;
4263
+ const sections = buffer.split('\n\n');
4264
+ buffer = sections.pop() || '';
4265
+ for (const section of sections) {
4266
+ const event = parseMessage(section, true);
4267
+ onEvent((_a = event.event) !== null && _a !== void 0 ? _a : '', event.data);
4268
+ }
4269
+ }
4270
+ if (buffer) {
4271
+ const event = parseMessage(buffer, true);
4272
+ onEvent((_b = event.event) !== null && _b !== void 0 ? _b : '', event.data);
4273
+ }
4274
+ };
4275
+ const parseMessage = (message, parseDataAsJSON) => {
4276
+ const fields = message.split('\n');
4277
+ const result = {};
4278
+ for (const field of fields) {
4279
+ if (field.startsWith(':')) {
4280
+ continue;
4281
+ }
4282
+ if (field.startsWith('event: ')) {
4283
+ result.event = field.slice(7);
4284
+ }
4285
+ else if (field.startsWith('data: ')) {
4286
+ if (result.data) {
4287
+ result.data += '\n';
4288
+ }
4289
+ else {
4290
+ result.data = '';
4291
+ }
4292
+ result.data += field.slice(6);
4293
+ }
4294
+ else if (field.startsWith('retry: ')) {
4295
+ result.retry = field.slice(7);
4296
+ }
4297
+ }
4298
+ if (result.data && parseDataAsJSON) {
4299
+ result.data = JSON.parse(result.data);
4300
+ }
4301
+ return result;
4302
+ };
4303
+
4095
4304
  const DIALOG_DELAY = 1000;
4096
4305
  const normalizePath = (path) => path.replace(/\/$/, '');
4097
4306
  class ShopGPT extends r$2 {
4098
4307
  constructor() {
4099
4308
  super(...arguments);
4309
+ this.isStylesheetInjected = false;
4100
4310
  this.latestThreadLoad = DEFAULT_MAX_THREAD_AGE;
4101
4311
  this.modalState = 'close';
4102
4312
  this.isLoadingHistory = false;
@@ -4107,6 +4317,7 @@ ${this.comment ? this.comment : E}</textarea
4107
4317
  this.products = [];
4108
4318
  this.messages = [];
4109
4319
  this.chatThreads = new Map();
4320
+ this.customPrompts = [];
4110
4321
  this.loadData = async () => {
4111
4322
  if (!this.shopGPTAPI) {
4112
4323
  return;
@@ -4129,7 +4340,13 @@ ${this.comment ? this.comment : E}</textarea
4129
4340
  }
4130
4341
  connectedCallback() {
4131
4342
  super.connectedCallback();
4132
- if (!this.uiMode || this.uiMode === 'overlay') {
4343
+ if (!this.isStylesheetInjected && this.css) {
4344
+ const sheet = new CSSStyleSheet();
4345
+ sheet.replaceSync(this.css);
4346
+ this.shadowRoot.adoptedStyleSheets.push(sheet);
4347
+ this.isStylesheetInjected = true;
4348
+ }
4349
+ if (!this.view || this.view === 'overlay') {
4133
4350
  if (!this.path) {
4134
4351
  return;
4135
4352
  }
@@ -4150,7 +4367,7 @@ ${this.comment ? this.comment : E}</textarea
4150
4367
  init() {
4151
4368
  window.addEventListener('edgetag-initialized', this.loadData);
4152
4369
  window.addEventListener('popstate', this.onPopState);
4153
- if (!this.uiMode || this.uiMode === 'overlay') {
4370
+ if (!this.view || this.view === 'overlay') {
4154
4371
  delay(DIALOG_DELAY).then(() => {
4155
4372
  var _a;
4156
4373
  if (document.hidden) {
@@ -4198,27 +4415,12 @@ ${this.comment ? this.comment : E}</textarea
4198
4415
  : undefined;
4199
4416
  try {
4200
4417
  this.isTyping = true;
4201
- const reply = await this.shopGPTAPI.processQuery('', thread.threadId, productHandle);
4202
- if (reply.chatTitle) {
4203
- this.setChatTitle(this.selectedThreadId, reply.chatTitle);
4204
- }
4205
- this.messages = [
4206
- {
4207
- messageId: reply.messageId,
4208
- sender: 'bot',
4209
- message: reply.message,
4210
- products: reply.products,
4211
- welcomePrompts: reply.welcomePrompts,
4212
- },
4213
- ...this.messages,
4214
- ];
4215
- this.products = reply.products || [];
4418
+ const response = await this.shopGPTAPI.processQuery('', thread.threadId, productHandle);
4419
+ this.processMessageResponse(response);
4216
4420
  }
4217
4421
  catch (error) {
4218
4422
  logger.error(error);
4219
4423
  this.isFailed = true;
4220
- }
4221
- finally {
4222
4424
  this.isTyping = false;
4223
4425
  }
4224
4426
  }
@@ -4289,10 +4491,25 @@ ${this.comment ? this.comment : E}</textarea
4289
4491
  this.isLoadingHistory = false;
4290
4492
  }
4291
4493
  }
4494
+ async loadCustomPrompts(threadId) {
4495
+ try {
4496
+ if (!threadId) {
4497
+ this.customPrompts = [];
4498
+ return;
4499
+ }
4500
+ this.customPrompts = await this.shopGPTAPI.fetchCustomPrompts(threadId);
4501
+ }
4502
+ catch (e) {
4503
+ logger.error(e);
4504
+ }
4505
+ }
4292
4506
  async setSelectedThreadId(threadId) {
4293
4507
  this.isFailed = false;
4294
4508
  this.selectedThreadId = threadId;
4295
- await this.loadHistory(threadId);
4509
+ await Promise.all([
4510
+ this.loadHistory(threadId),
4511
+ this.loadCustomPrompts(threadId),
4512
+ ]);
4296
4513
  }
4297
4514
  async createChatThread(payload, loadInitialQuery) {
4298
4515
  try {
@@ -4303,7 +4520,9 @@ ${this.comment ? this.comment : E}</textarea
4303
4520
  ]);
4304
4521
  this.selectedThreadId = thread.threadId;
4305
4522
  if (loadInitialQuery) {
4306
- await this.loadInitialQuery();
4523
+ await Promise.all([
4524
+ (this.loadInitialQuery(), this.loadCustomPrompts(thread.threadId)),
4525
+ ]);
4307
4526
  }
4308
4527
  }
4309
4528
  catch (e) {
@@ -4339,6 +4558,92 @@ ${this.comment ? this.comment : E}</textarea
4339
4558
  .catch(logger.error)
4340
4559
  .finally(() => (this.isLoadingThreads = false));
4341
4560
  }
4561
+ handleMessageChunks(messageData) {
4562
+ if (!messageData.message) {
4563
+ return;
4564
+ }
4565
+ const latestMessage = this.messages[0];
4566
+ this.isTyping = false;
4567
+ if (latestMessage === null || latestMessage === void 0 ? void 0 : latestMessage.isChunk) {
4568
+ this.messages = [
4569
+ {
4570
+ ...latestMessage,
4571
+ message: latestMessage.message + messageData.message,
4572
+ isChunk: messageData.isChunk,
4573
+ sender: 'bot',
4574
+ },
4575
+ ...this.messages.slice(1),
4576
+ ];
4577
+ }
4578
+ else {
4579
+ this.messages = [
4580
+ {
4581
+ sender: 'bot',
4582
+ message: messageData.message || '',
4583
+ isChunk: messageData.isChunk,
4584
+ },
4585
+ ...this.messages,
4586
+ ];
4587
+ }
4588
+ }
4589
+ handleCompleteMessage(messageData) {
4590
+ const latestMessage = this.messages[0];
4591
+ this.messages = [
4592
+ {
4593
+ ...latestMessage,
4594
+ message: messageData.message || '',
4595
+ messageId: messageData.messageId,
4596
+ welcomePrompts: messageData.welcomePrompts,
4597
+ sender: 'bot',
4598
+ isChunk: false,
4599
+ },
4600
+ ...this.messages.slice(1),
4601
+ ];
4602
+ }
4603
+ handleProductsComplete(products, isMessageCompleted) {
4604
+ if (!products || !isMessageCompleted) {
4605
+ return;
4606
+ }
4607
+ const latestMessage = this.messages[0];
4608
+ this.messages = [
4609
+ {
4610
+ ...latestMessage,
4611
+ products,
4612
+ },
4613
+ ...this.messages.slice(1),
4614
+ ];
4615
+ if (products.length) {
4616
+ this.products = products;
4617
+ }
4618
+ }
4619
+ processMessageResponse(response) {
4620
+ let isMessageCompleted = false;
4621
+ let products;
4622
+ handleEventSource(response, (eventName, data) => {
4623
+ if (eventName === 'ChatTitle') {
4624
+ this.setChatTitle(this.selectedThreadId, data.chatTitle || '');
4625
+ }
4626
+ else if (eventName === 'Message') {
4627
+ this.handleMessageChunks(data);
4628
+ }
4629
+ else if (eventName === 'MessageComplete') {
4630
+ isMessageCompleted = true;
4631
+ this.handleProductsComplete(products, isMessageCompleted);
4632
+ this.handleCompleteMessage(data);
4633
+ }
4634
+ else if (eventName === 'ProductsComplete') {
4635
+ this.handleProductsComplete(data.products, isMessageCompleted);
4636
+ products = data.products;
4637
+ }
4638
+ else if (eventName === 'error') {
4639
+ if (this.messages[0].isChunk) {
4640
+ this.messages = this.messages.slice(1);
4641
+ }
4642
+ this.isFailed = true;
4643
+ throw new Error(data);
4644
+ }
4645
+ });
4646
+ }
4342
4647
  async sendMessageToServer(e, message) {
4343
4648
  e.preventDefault();
4344
4649
  e.stopPropagation();
@@ -4349,32 +4654,12 @@ ${this.comment ? this.comment : E}</textarea
4349
4654
  try {
4350
4655
  this.messages = [{ sender: 'user', message }, ...this.messages];
4351
4656
  this.isTyping = true;
4352
- const reply = await this.submitQuery(message);
4353
- if (!reply) {
4354
- return;
4355
- }
4356
- if (reply.chatTitle) {
4357
- this.setChatTitle(this.selectedThreadId, reply.chatTitle);
4358
- }
4359
- this.messages = [
4360
- {
4361
- messageId: reply.messageId,
4362
- sender: 'bot',
4363
- message: reply.message,
4364
- products: reply.products,
4365
- welcomePrompts: reply.welcomePrompts,
4366
- },
4367
- ...this.messages,
4368
- ];
4369
- if (reply.products && reply.products.length > 0) {
4370
- this.products = reply.products;
4371
- }
4657
+ const response = await this.submitQuery(message);
4658
+ this.processMessageResponse(response);
4372
4659
  }
4373
4660
  catch (err) {
4374
4661
  logger.error(err);
4375
4662
  this.isFailed = true;
4376
- }
4377
- finally {
4378
4663
  this.isTyping = false;
4379
4664
  }
4380
4665
  }
@@ -4396,7 +4681,7 @@ ${this.comment ? this.comment : E}</textarea
4396
4681
  return this.storeAPI.getSiteCurrency();
4397
4682
  }
4398
4683
  render() {
4399
- if (this.uiMode === 'modal') {
4684
+ if (this.view === 'modal') {
4400
4685
  return this.modalMode();
4401
4686
  }
4402
4687
  return this.overlayMode();
@@ -4421,6 +4706,7 @@ ${this.comment ? this.comment : E}</textarea
4421
4706
  .isLoading=${this.isLoadingThreads}
4422
4707
  .isTyping=${this.isTyping}
4423
4708
  .merchantUrl=${this.merchantUrl}
4709
+ .css=${this.css}
4424
4710
  ></chat-threads>
4425
4711
  <products-section
4426
4712
  .merchantImage=${this.merchantImage}
@@ -4428,6 +4714,7 @@ ${this.comment ? this.comment : E}</textarea
4428
4714
  .isLoadingHistory=${this.isLoadingHistory}
4429
4715
  .siteCurrency=${this.getSiteCurrency()}
4430
4716
  .isLoadingThreads=${this.isLoadingThreads}
4717
+ .css=${this.css}
4431
4718
  ></products-section>
4432
4719
  <chat-section
4433
4720
  .prompts=${this.quickPrompts}
@@ -4445,6 +4732,9 @@ ${this.comment ? this.comment : E}</textarea
4445
4732
  .profiles=${this.profiles}
4446
4733
  .viewType=${'overlay'}
4447
4734
  .isLoadingThreads=${this.isLoadingThreads}
4735
+ .customPrompts=${this.customPrompts}
4736
+ .botIconUrl=${this.botIconUrl}
4737
+ .css=${this.css}
4448
4738
  ></chat-section>
4449
4739
  </div>
4450
4740
  </dialog>
@@ -4495,6 +4785,9 @@ ${this.comment ? this.comment : E}</textarea
4495
4785
  .chatThreads=${this.chatThreads}
4496
4786
  .isLoadingThreads=${this.isLoadingThreads}
4497
4787
  .merchantImage=${this.merchantImage}
4788
+ .customPrompts=${this.customPrompts}
4789
+ .botIconUrl=${this.botIconUrl}
4790
+ .css=${this.css}
4498
4791
  ></chat-section>
4499
4792
  </div>
4500
4793
  `;
@@ -4545,6 +4838,10 @@ ${this.comment ? this.comment : E}</textarea
4545
4838
  n({ type: Object }),
4546
4839
  __metadata("design:type", Map)
4547
4840
  ], ShopGPT.prototype, "chatThreads", void 0);
4841
+ __decorate([
4842
+ n({ type: Array }),
4843
+ __metadata("design:type", Array)
4844
+ ], ShopGPT.prototype, "customPrompts", void 0);
4548
4845
  if (!customElements.get('shop-gpt')) {
4549
4846
  customElements.define('shop-gpt', ShopGPT);
4550
4847
  }
@@ -4566,12 +4863,14 @@ ${this.comment ? this.comment : E}</textarea
4566
4863
  shopGPT.merchantUrl = params.merchantUrl;
4567
4864
  shopGPT.profiles = params.profiles;
4568
4865
  shopGPT.productHandles = params.productHandles;
4569
- shopGPT.uiMode = params.uiMode;
4866
+ shopGPT.view = params.view;
4570
4867
  shopGPT.path = params.path;
4571
4868
  shopGPT.brandName = params.brandName;
4572
4869
  shopGPT.quickPrompts = params.quickPrompts;
4573
4870
  shopGPT.merchantImage = params.merchantImage;
4574
4871
  shopGPT.latestThreadLoad = params.latestThreadLoad;
4872
+ shopGPT.botIconUrl = params.botIconUrl;
4873
+ shopGPT.css = params.css;
4575
4874
  document.body.append(shopGPT);
4576
4875
  },
4577
4876
  destroy() {