@coveo/quantic 3.40.0 → 3.42.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 (62) hide show
  1. package/docs/out/quantic-docs.json +9 -0
  2. package/force-app/main/default/labels/CustomLabels.labels-meta.xml +91 -0
  3. package/force-app/main/default/lwc/quanticGeneratedAnswer/__tests__/quanticGeneratedAnswer.test.js +271 -22
  4. package/force-app/main/default/lwc/quanticGeneratedAnswer/quanticGeneratedAnswer.js +92 -31
  5. package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/conversation.css +7 -0
  6. package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/conversation.html +63 -0
  7. package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/generatedAnswer.css +0 -11
  8. package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/generatedAnswer.html +2 -2
  9. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/__tests__/quanticGeneratedAnswerBody.test.js +379 -0
  10. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/quanticGeneratedAnswerBody.js +152 -0
  11. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/quanticGeneratedAnswerBody.js-meta.xml +5 -0
  12. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/templates/answer.css +3 -0
  13. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/templates/answer.html +59 -0
  14. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/templates/cannotAnswer.html +7 -0
  15. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/templates/error.html +7 -0
  16. package/force-app/main/default/lwc/quanticGeneratedAnswerCopyToClipboard/__tests__/quanticGeneratedAnswerCopyToClipboard.test.js +5 -1
  17. package/force-app/main/default/lwc/quanticGeneratedAnswerCopyToClipboard/quanticGeneratedAnswerCopyToClipboard.js +9 -2
  18. package/force-app/main/default/lwc/quanticGeneratedAnswerFollowUpInput/__tests__/quanticGeneratedAnswerFollowUpInput.test.js +109 -55
  19. package/force-app/main/default/lwc/quanticGeneratedAnswerFollowUpInput/quanticGeneratedAnswerFollowUpInput.css +59 -11
  20. package/force-app/main/default/lwc/quanticGeneratedAnswerFollowUpInput/quanticGeneratedAnswerFollowUpInput.html +14 -13
  21. package/force-app/main/default/lwc/quanticGeneratedAnswerFollowUpInput/quanticGeneratedAnswerFollowUpInput.js +40 -2
  22. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/__tests__/quanticGeneratedAnswerStreamOfThought.test.js +348 -0
  23. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/quanticGeneratedAnswerStreamOfThought.css +17 -0
  24. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/quanticGeneratedAnswerStreamOfThought.js +163 -0
  25. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/quanticGeneratedAnswerStreamOfThought.js-meta.xml +5 -0
  26. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/templates/collapsedSummary.css +1 -0
  27. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/templates/collapsedSummary.html +32 -0
  28. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/templates/streamOfThought.css +1 -0
  29. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/templates/streamOfThought.html +65 -0
  30. package/force-app/main/default/lwc/quanticGeneratedAnswerThread/__tests__/quanticGeneratedAnswerThread.test.js +285 -0
  31. package/force-app/main/default/lwc/quanticGeneratedAnswerThread/quanticGeneratedAnswerThread.css +47 -0
  32. package/force-app/main/default/lwc/quanticGeneratedAnswerThread/quanticGeneratedAnswerThread.html +67 -0
  33. package/force-app/main/default/lwc/quanticGeneratedAnswerThread/quanticGeneratedAnswerThread.js +93 -0
  34. package/force-app/main/default/lwc/quanticGeneratedAnswerThread/quanticGeneratedAnswerThread.js-meta.xml +5 -0
  35. package/force-app/main/default/lwc/quanticSourceCitations/__tests__/quanticSourceCitations.test.js +22 -2
  36. package/force-app/main/default/lwc/quanticSourceCitations/quanticSourceCitations.js +7 -0
  37. package/force-app/main/default/lwc/quanticThreadItem/quanticThreadItem.css +0 -4
  38. package/force-app/main/default/lwc/quanticThreadItem/quanticThreadItem.html +1 -1
  39. package/force-app/main/default/staticresources/coveoheadless/case-assist/headless.js +15 -15
  40. package/force-app/main/default/staticresources/coveoheadless/definitions/api/commerce/common/pagination.d.ts +1 -1
  41. package/force-app/main/default/staticresources/coveoheadless/definitions/commerce.index.d.ts +1 -1
  42. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/commerce/core/sub-controller/headless-sub-controller.d.ts +3 -1
  43. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/commerce/recent-queries-list/headless-recent-queries-list.d.ts +13 -2
  44. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/commerce/search/did-you-mean/headless-did-you-mean.d.ts +10 -1
  45. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/core/generated-answer/headless-core-generated-answer.d.ts +1 -0
  46. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/core/generated-answer/headless-core-interactive-citation.d.ts +3 -3
  47. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/generated-answer/headless-generated-answer.d.ts +2 -2
  48. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/generated-answer/interactive-citation-analytics-client.d.ts +3 -0
  49. package/force-app/main/default/staticresources/coveoheadless/definitions/features/analytics/analytics-utils.d.ts +3 -2
  50. package/force-app/main/default/staticresources/coveoheadless/definitions/features/follow-up-answers/follow-up-answers-actions.d.ts +32 -1
  51. package/force-app/main/default/staticresources/coveoheadless/definitions/features/generated-answer/generated-answer-actions.d.ts +26 -1
  52. package/force-app/main/default/staticresources/coveoheadless/definitions/features/generated-answer/generated-answer-analytics-actions.d.ts +2 -0
  53. package/force-app/main/default/staticresources/coveoheadless/definitions/features/generated-answer/generated-answer-state.d.ts +19 -0
  54. package/force-app/main/default/staticresources/coveoheadless/definitions/index.d.ts +1 -1
  55. package/force-app/main/default/staticresources/coveoheadless/definitions/ssr/commerce/controllers/did-you-mean/headless-did-you-mean.ssr.d.ts +4 -3
  56. package/force-app/main/default/staticresources/coveoheadless/definitions/ssr-commerce-next.index.d.ts +1 -1
  57. package/force-app/main/default/staticresources/coveoheadless/definitions/ssr-commerce.index.d.ts +1 -1
  58. package/force-app/main/default/staticresources/coveoheadless/definitions/ssr-next/commerce/controllers/did-you-mean/headless-did-you-mean.ssr.d.ts +4 -3
  59. package/force-app/main/default/staticresources/coveoheadless/headless.js +18 -18
  60. package/force-app/main/default/staticresources/coveoheadless/insight/headless.js +16 -16
  61. package/force-app/main/default/staticresources/coveoheadless/recommendation/headless.js +14 -14
  62. package/package.json +2 -2
@@ -35,9 +35,12 @@ import generatedAnswerTemplate from './templates/generatedAnswer.html';
35
35
  import loadingTemplate from './templates/loading.html';
36
36
  // @ts-ignore
37
37
  import retryPromptTemplate from './templates/retryPrompt.html';
38
+ // @ts-ignore
39
+ import conversationTemplate from './templates/conversation.html';
38
40
 
39
41
  /** @typedef {import("coveo").SearchEngine} SearchEngine */
40
42
  /** @typedef {import("coveo").GeneratedAnswer} GeneratedAnswer */
43
+ /** @typedef {import("coveo").GeneratedAnswerWithFollowUps} GeneratedAnswerWithFollowUps */
41
44
  /** @typedef {import("coveo").GeneratedAnswerState} GeneratedAnswerState */
42
45
  /** @typedef {import("coveo").GeneratedAnswerCitation} GeneratedAnswerCitation */
43
46
  /** @typedef { 'neutral' | 'liked' | 'disliked'} FeedbackState */
@@ -100,6 +103,13 @@ export default class QuanticGeneratedAnswer extends LightningElement {
100
103
  * @default {undefined}
101
104
  */
102
105
  @api answerConfigurationId;
106
+ /**
107
+ * The unique identifier of the agent to use to generate the answer.
108
+ * @api
109
+ * @type {string}
110
+ * @default {undefined}
111
+ */
112
+ @api agentId;
103
113
  /**
104
114
  * The maximum height (in px units) of the generated answer when it is collapsed.
105
115
  * @api
@@ -155,7 +165,7 @@ export default class QuanticGeneratedAnswer extends LightningElement {
155
165
  noGeneratedAnswer,
156
166
  };
157
167
 
158
- /** @type {GeneratedAnswer} */
168
+ /** @type { GeneratedAnswer | GeneratedAnswerWithFollowUps} */
159
169
  generatedAnswer;
160
170
  /** @type {GeneratedAnswerState} */
161
171
  state;
@@ -172,13 +182,7 @@ export default class QuanticGeneratedAnswer extends LightningElement {
172
182
  /** @type {boolean} */
173
183
  hasInitializationError = false;
174
184
  /** @type {boolean} */
175
- _areFollowUpsEnabled = false;
176
- /** @type {boolean} */
177
185
  _exceedsMaximumHeight = false;
178
- /** @type {boolean} */
179
- _liked = false;
180
- /** @type {boolean} */
181
- _disliked = false;
182
186
  /** @type {number} */
183
187
  _maxCollapsedHeight = DEFAULT_COLLAPSED_HEIGHT;
184
188
 
@@ -207,6 +211,7 @@ export default class QuanticGeneratedAnswer extends LightningElement {
207
211
  * @param {SearchEngine} engine
208
212
  */
209
213
  initialize = (engine) => {
214
+ this.engine = engine;
210
215
  this.ariaLiveMessage = AriaLiveRegion('GeneratedAnswer', this);
211
216
  this.headless = getHeadlessBundle(this.engineId);
212
217
  this.generatedAnswer = this.buildHeadlessGeneratedAnswerController(engine);
@@ -238,6 +243,9 @@ export default class QuanticGeneratedAnswer extends LightningElement {
238
243
  ...(this.answerConfigurationId && {
239
244
  answerConfigurationId: this.answerConfigurationId,
240
245
  }),
246
+ ...(this.agentId?.trim() && {
247
+ agentId: this.agentId.trim(),
248
+ }),
241
249
  fieldsToIncludeInCitations: this.citationFields,
242
250
  });
243
251
  }
@@ -316,7 +324,7 @@ export default class QuanticGeneratedAnswer extends LightningElement {
316
324
  * @param {string} id
317
325
  * @param {number} citationHoverTimeMs
318
326
  */
319
- handleCitationHover = (id, citationHoverTimeMs) => {
327
+ logCitationHover = (id, citationHoverTimeMs) => {
320
328
  this.generatedAnswer.logCitationHover(id, citationHoverTimeMs);
321
329
  };
322
330
 
@@ -326,12 +334,8 @@ export default class QuanticGeneratedAnswer extends LightningElement {
326
334
  */
327
335
  async handleLike(event) {
328
336
  event.stopPropagation();
329
- if (!this._liked) {
330
- this._liked = true;
331
- this._disliked = false;
332
- this.generatedAnswer.like?.();
333
- }
334
- if (!this.feedbackSubmitted) {
337
+ this.generatedAnswer.like?.(event.detail?.answerId);
338
+ if (!this.feedbackSubmitted && !this.areFollowUpsEnabled) {
335
339
  // @ts-ignore
336
340
  await FeedbackModalQna.open({
337
341
  size: 'small',
@@ -344,18 +348,28 @@ export default class QuanticGeneratedAnswer extends LightningElement {
344
348
  }
345
349
  }
346
350
 
351
+ /**
352
+ * handles hovering over a citation.
353
+ * @param {CustomEvent} event
354
+ */
355
+ handleCitationHover(event) {
356
+ event.stopPropagation();
357
+ const {citationId, citationHoverTimeMs, answerId} = event.detail;
358
+ this.generatedAnswer.logCitationHover(
359
+ citationId,
360
+ citationHoverTimeMs,
361
+ answerId
362
+ );
363
+ }
364
+
347
365
  /**
348
366
  * handles disliking the generated answer.
349
367
  * @param {CustomEvent} event
350
368
  */
351
369
  async handleDislike(event) {
352
370
  event.stopPropagation();
353
- if (!this._disliked) {
354
- this._disliked = true;
355
- this._liked = false;
356
- this.generatedAnswer.dislike?.();
357
- }
358
- if (!this.feedbackSubmitted) {
371
+ this.generatedAnswer.dislike?.(event.detail?.answerId);
372
+ if (!this.feedbackSubmitted && !this.areFollowUpsEnabled) {
359
373
  // @ts-ignore
360
374
  await FeedbackModalQna.open({
361
375
  size: 'small',
@@ -381,9 +395,13 @@ export default class QuanticGeneratedAnswer extends LightningElement {
381
395
  this.generatedAnswer.retry();
382
396
  }
383
397
 
398
+ /**
399
+ * handles copying the generated answer to the clipboard.
400
+ * @param {CustomEvent} event
401
+ */
384
402
  handleGeneratedAnswerCopyToClipboard = (event) => {
385
403
  event.stopPropagation();
386
- this.generatedAnswer.logCopyToClipboard();
404
+ this.generatedAnswer.logCopyToClipboard(event.detail?.answerId);
387
405
  };
388
406
 
389
407
  handleGeneratedAnswerToggle = (event) => {
@@ -487,9 +505,37 @@ export default class QuanticGeneratedAnswer extends LightningElement {
487
505
  return this.state.isVisible;
488
506
  }
489
507
 
508
+ /**
509
+ * Returns the generated answer controller narrowed to `GeneratedAnswerWithFollowUps`, or `null` if follow-ups are not available.
510
+ * @returns {GeneratedAnswerWithFollowUps | null}
511
+ */
512
+ get generateAnswerWithFollowUps() {
513
+ if (
514
+ !this.agentId ||
515
+ !this.generatedAnswer ||
516
+ !('askFollowUp' in this.generatedAnswer)
517
+ ) {
518
+ return null;
519
+ }
520
+ return /** @type {GeneratedAnswerWithFollowUps} */ (this.generatedAnswer);
521
+ }
522
+
490
523
  get areFollowUpsEnabled() {
491
- // TODO SFINT-6786: Modify this getter to return the actual value from the state for follow-up enabled/agentId.
492
- return this._areFollowUpsEnabled;
524
+ return (
525
+ this.generateAnswerWithFollowUps?.state.followUpAnswers?.isEnabled ===
526
+ true
527
+ );
528
+ }
529
+
530
+ get allGeneratedAnswers() {
531
+ const initialAnswer = {
532
+ ...this.state,
533
+ question: this.engine?.state.query?.q ?? '',
534
+ };
535
+ const followUpAnswers =
536
+ this.generateAnswerWithFollowUps?.state.followUpAnswers
537
+ ?.followUpAnswers ?? [];
538
+ return [initialAnswer, ...followUpAnswers];
493
539
  }
494
540
 
495
541
  get isCollapsibleEnabled() {
@@ -516,14 +562,6 @@ export default class QuanticGeneratedAnswer extends LightningElement {
516
562
  return `generated-answer__answer ${collapsedStateClass}`;
517
563
  }
518
564
 
519
- get contentSectionClass() {
520
- const baseClass =
521
- 'generated-answer__content slds-p-top_medium slds-p-horizontal_large';
522
- return this.areFollowUpsEnabled
523
- ? `${baseClass} generated-answer__content--scrollable`
524
- : baseClass;
525
- }
526
-
527
565
  get hasRetryableError() {
528
566
  return !this?.searchStatusState?.hasError && this.state?.error?.isRetryable;
529
567
  }
@@ -618,6 +656,17 @@ export default class QuanticGeneratedAnswer extends LightningElement {
618
656
  return this.state?.isLoading;
619
657
  }
620
658
 
659
+ get isAnswerGenerationOngoing() {
660
+ const initialAnswerPending = this.isStreaming || this.isLoading;
661
+ const followUpAnswers =
662
+ this.generateAnswerWithFollowUps?.state?.followUpAnswers
663
+ ?.followUpAnswers ?? [];
664
+ return (
665
+ initialAnswerPending ||
666
+ followUpAnswers.some((answer) => answer.isStreaming || answer.isLoading)
667
+ );
668
+ }
669
+
621
670
  get isManualAnswerGeneration() {
622
671
  return this.state?.answerGenerationMode === 'manual';
623
672
  }
@@ -629,6 +678,15 @@ export default class QuanticGeneratedAnswer extends LightningElement {
629
678
  this.hasInitializationError = true;
630
679
  }
631
680
 
681
+ /**
682
+ * Handles the submission of a follow-up question from the `QuanticGeneratedAnswerFollowUpInput` component.
683
+ * @param {CustomEvent} event - The custom event containing the follow-up question details.
684
+ * @returns {void}
685
+ */
686
+ handleFollowUpSubmit = (event) => {
687
+ this.generateAnswerWithFollowUps?.askFollowUp(event.detail.value);
688
+ };
689
+
632
690
  render() {
633
691
  if (this.hasInitializationError) {
634
692
  return errorTemplate;
@@ -643,6 +701,9 @@ export default class QuanticGeneratedAnswer extends LightningElement {
643
701
  if (this.hasRetryableError) {
644
702
  return retryPromptTemplate;
645
703
  }
704
+ if (this.areFollowUpsEnabled) {
705
+ return conversationTemplate;
706
+ }
646
707
  return generatedAnswerTemplate;
647
708
  }
648
709
  }
@@ -0,0 +1,7 @@
1
+ @import '../quanticGeneratedAnswer.css';
2
+
3
+ .generated-answer__content--scrollable {
4
+ overflow-y: auto;
5
+ height: var(--quantic-generated-answer-content-fixed-height, 50vh);
6
+ overflow-x: hidden;
7
+ }
@@ -0,0 +1,63 @@
1
+ <template>
2
+ <template lwc:if={shouldDisplayGeneratedAnswer}>
3
+ <div
4
+ data-testid="generated-answer__card"
5
+ class="slds-box slds-p-around_none"
6
+ >
7
+ <header
8
+ data-testid="generated-answer__header"
9
+ class={generatedAnswerHeaderClass}
10
+ >
11
+ <div
12
+ class="generated-answer__header-title slds-grid slds-grid_vertical-align-center"
13
+ >
14
+ <lightning-icon
15
+ icon-name="utility:sparkles"
16
+ size="x-small"
17
+ alternative-text={labels.generatedAnswerForYou}
18
+ class="slds-current-color slds-var-m-right_x-small"
19
+ ></lightning-icon>
20
+ <span
21
+ data-testid="generated-answer__header-title"
22
+ class="slds-text-title_bold slds-p-vertical_x-small"
23
+ >{labels.generatedAnswerForYou}
24
+ </span>
25
+ </div>
26
+ <template lwc:if={withToggle}>
27
+ <c-quantic-generated-answer-toggle
28
+ is-generated-answer-visible={isVisible}
29
+ ></c-quantic-generated-answer-toggle>
30
+ </template>
31
+ </header>
32
+ <template lwc:if={isVisible}>
33
+ <div
34
+ class="slds-p-horizontal_large slds-p-top_medium generated-answer__content--scrollable"
35
+ >
36
+ <c-quantic-generated-answer-thread
37
+ engine-id={engineId}
38
+ onquantic__generatedanswerlike={handleLike}
39
+ onquantic__generatedanswerdislike={handleDislike}
40
+ onquantic__citationhover={handleCitationHover}
41
+ generated-answers={allGeneratedAnswers}
42
+ disable-citation-anchoring={disableCitationAnchoring}
43
+ >
44
+ </c-quantic-generated-answer-thread>
45
+ </div>
46
+ <div class="slds-p-horizontal_large slds-p-vertical_medium">
47
+ <c-quantic-generated-answer-follow-up-input
48
+ onquantic__submitfollowup={handleFollowUpSubmit}
49
+ submit-button-disabled={isAnswerGenerationOngoing}
50
+ ></c-quantic-generated-answer-follow-up-input>
51
+ <footer
52
+ data-testid="generated-answer__footer"
53
+ class="generated-answer__disclaimer slds-grid slds-grid_vertical-align-center slds-grid_align-end slds-text-color_weak slds-text-body_small slds-var-m-top_xx-small"
54
+ >
55
+ <div data-testid="generated-answer__disclaimer">
56
+ <slot name="disclaimer">{labels.rgaDisclaimer}</slot>
57
+ </div>
58
+ </footer>
59
+ </div>
60
+ </template>
61
+ </div>
62
+ </template>
63
+ </template>
@@ -9,11 +9,6 @@
9
9
  word-wrap: break-word;
10
10
  }
11
11
 
12
- .generated-answer__content--scrollable {
13
- overflow-y: auto;
14
- height: var(--quantic-generated-answer-content-fixed-height, 50vh);
15
- }
16
-
17
12
  .generated-answer__footer {
18
13
  gap: 1rem;
19
14
  }
@@ -59,9 +54,3 @@
59
54
  opacity: 0.2;
60
55
  visibility: hidden;
61
56
  }
62
-
63
- @keyframes cursor-blink {
64
- 100% {
65
- visibility: hidden;
66
- }
67
- }
@@ -27,7 +27,7 @@
27
27
  <template lwc:if={isVisible}>
28
28
  <section
29
29
  data-testid="generated-answer__body"
30
- class={contentSectionClass}
30
+ class="generated-answer__content slds-p-top_medium slds-p-horizontal_large"
31
31
  >
32
32
  <div
33
33
  data-testid="generated-answer__answer"
@@ -50,7 +50,7 @@
50
50
  engine-id={engineId}
51
51
  data-testid="generated-answer__citations"
52
52
  citations={citations}
53
- citation-hover-handler={handleCitationHover}
53
+ citation-hover-handler={logCitationHover}
54
54
  disable-citation-anchoring={disableCitationAnchoring}
55
55
  ></c-quantic-source-citations>
56
56
  </div>