@coveo/quantic 3.42.0 → 3.43.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 (27) hide show
  1. package/force-app/main/default/labels/CustomLabels.labels-meta.xml +21 -0
  2. package/force-app/main/default/lwc/quanticGeneratedAnswer/e2e/agentData.ts +248 -0
  3. package/force-app/main/default/lwc/quanticGeneratedAnswer/e2e/fixture-agent.ts +77 -0
  4. package/force-app/main/default/lwc/quanticGeneratedAnswer/e2e/fixture.ts +65 -59
  5. package/force-app/main/default/lwc/quanticGeneratedAnswer/e2e/pageObject.ts +158 -13
  6. package/force-app/main/default/lwc/quanticGeneratedAnswer/e2e/quanticGeneratedAnswer.e2e.ts +1 -5
  7. package/force-app/main/default/lwc/quanticGeneratedAnswer/e2e/quanticGeneratedAnswerAgent.e2e.ts +233 -0
  8. package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/conversation.html +1 -1
  9. package/force-app/main/default/lwc/quanticGeneratedAnswerFollowUpInput/__tests__/quanticGeneratedAnswerFollowUpInput.test.js +242 -10
  10. package/force-app/main/default/lwc/quanticGeneratedAnswerFollowUpInput/quanticGeneratedAnswerFollowUpInput.css +2 -2
  11. package/force-app/main/default/lwc/quanticGeneratedAnswerFollowUpInput/quanticGeneratedAnswerFollowUpInput.html +16 -1
  12. package/force-app/main/default/lwc/quanticGeneratedAnswerFollowUpInput/quanticGeneratedAnswerFollowUpInput.js +47 -4
  13. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/__tests__/quanticGeneratedAnswerStreamOfThought.test.js +95 -41
  14. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/__tests__/stepsUtils.test.js +118 -0
  15. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/quanticGeneratedAnswerStreamOfThought.js +21 -35
  16. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/stepsUtils.js +66 -0
  17. package/force-app/main/default/staticresources/coveoheadless/case-assist/headless.js +15 -15
  18. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/commerce/product-listing/facets/headless-product-listing-facet-options.d.ts +4 -39
  19. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/commerce/search/facets/headless-search-facet-options.d.ts +4 -39
  20. package/force-app/main/default/staticresources/coveoheadless/definitions/features/commerce/facets/facet-set/facet-set-selector.d.ts +3 -9
  21. package/force-app/main/default/staticresources/coveoheadless/definitions/features/facets/facet-search-set/category/category-facet-search-state-selector.d.ts +1 -27
  22. package/force-app/main/default/staticresources/coveoheadless/definitions/features/facets/facet-search-set/specific/specific-facet-search-state-selector.d.ts +1 -27
  23. package/force-app/main/default/staticresources/coveoheadless/headless.js +17 -17
  24. package/force-app/main/default/staticresources/coveoheadless/insight/headless.js +17 -17
  25. package/force-app/main/default/staticresources/coveoheadless/recommendation/headless.js +15 -15
  26. package/force-app/main/default/staticresources/dompurify/purify.min.js +2 -2
  27. package/package.json +5 -5
@@ -1652,6 +1652,13 @@
1652
1652
  <protected>false</protected>
1653
1653
  <shortDescription>Submit follow-up</shortDescription>
1654
1654
  </labels>
1655
+ <labels>
1656
+ <fullName>quantic_FollowUpInputTooLong</fullName>
1657
+ <value>Your question is too long. Please use {{0}} characters or fewer.</value>
1658
+ <language>en_US</language>
1659
+ <protected>false</protected>
1660
+ <shortDescription>Follow-up question character limit exceeded</shortDescription>
1661
+ </labels>
1655
1662
  <labels>
1656
1663
  <fullName>quantic_ShowPreviousQuestions_plural</fullName>
1657
1664
  <value>Show {{0}} previous questions</value>
@@ -1687,6 +1694,20 @@
1687
1694
  <protected>false</protected>
1688
1695
  <shortDescription>Knowledge base searched</shortDescription>
1689
1696
  </labels>
1697
+ <labels>
1698
+ <fullName>quantic_AgentGenerationStepSearchQuery</fullName>
1699
+ <value>Searching for {{0}}…</value>
1700
+ <language>en_US</language>
1701
+ <protected>false</protected>
1702
+ <shortDescription>Searching for query</shortDescription>
1703
+ </labels>
1704
+ <labels>
1705
+ <fullName>quantic_AgentGenerationStepSearchQueryCompleted</fullName>
1706
+ <value>Searched for {{0}}</value>
1707
+ <language>en_US</language>
1708
+ <protected>false</protected>
1709
+ <shortDescription>Searched for query</shortDescription>
1710
+ </labels>
1690
1711
  <labels>
1691
1712
  <fullName>quantic_AgentGenerationStepAnalyzingResults</fullName>
1692
1713
  <value>Analyzing results…</value>
@@ -0,0 +1,248 @@
1
+ type AgentRunType = {
2
+ type: 'RUN_STARTED' | 'RUN_FINISHED';
3
+ timestamp: number;
4
+ threadId: string;
5
+ runId: string;
6
+ result?: {
7
+ completionReason: string;
8
+ };
9
+ };
10
+
11
+ type AgentCustomType = {
12
+ type: 'CUSTOM';
13
+ timestamp: number;
14
+ name: string;
15
+ value: any;
16
+ };
17
+
18
+ type AgentStepType = {
19
+ type: 'STEP_STARTED' | 'STEP_FINISHED';
20
+ timestamp: number;
21
+ stepName: string;
22
+ };
23
+
24
+ type AgentToolCallType = {
25
+ type: 'TOOL_CALL_START' | 'TOOL_CALL_END';
26
+ timestamp: number;
27
+ toolCallId: string;
28
+ toolCallName: string;
29
+ parentMessageId: string;
30
+ };
31
+
32
+ type AgentToolCallArgsType = {
33
+ type: 'TOOL_CALL_ARGS';
34
+ timestamp: number;
35
+ toolCallId: string;
36
+ delta: any;
37
+ };
38
+
39
+ type AgentTextMessageType = {
40
+ type: 'TEXT_MESSAGE_CHUNK';
41
+ timestamp: number;
42
+ messageId: string;
43
+ parentMessageId: string;
44
+ delta: string;
45
+ };
46
+
47
+ export type AgentCitation = {
48
+ id: string;
49
+ title: string;
50
+ uri: string;
51
+ permanentid: string;
52
+ primaryId: string;
53
+ clickUri: string;
54
+ text: string;
55
+ source: string;
56
+ filetype: string;
57
+ fields: Record<string, any>;
58
+ };
59
+
60
+ type AgentCitationType = {
61
+ type: 'CUSTOM';
62
+ timestamp: number;
63
+ name: 'citations';
64
+ value: {
65
+ citations: Array<AgentCitation>;
66
+ };
67
+ };
68
+
69
+ const STREAM_ID = 'conv_1';
70
+ const ANSWER_ID_1 = 'conv_1_0001';
71
+ const ANSWER_ID_2 = 'conv_1_0002';
72
+ const ANSWER_ID_3 = 'conv_1_0003';
73
+ const CONVERSATION_TOKEN = 'conv_1_token';
74
+
75
+ const runStartStream = (answerId: string): AgentRunType => ({
76
+ type: 'RUN_STARTED',
77
+ timestamp: new Date().valueOf(),
78
+ threadId: STREAM_ID,
79
+ runId: answerId,
80
+ });
81
+
82
+ const customInitialHeadersStream = (followUpEnabled: boolean): AgentCustomType => ({
83
+ type: 'CUSTOM',
84
+ timestamp: new Date().valueOf(),
85
+ name: 'header',
86
+ value: {
87
+ contentFormat: 'text/markdown',
88
+ conversationId: STREAM_ID,
89
+ followUpEnabled,
90
+ conversationToken: CONVERSATION_TOKEN,
91
+ },
92
+ });
93
+
94
+ const stepStartedStream = (stepName: string): AgentStepType => ({
95
+ type: 'STEP_STARTED',
96
+ timestamp: new Date().valueOf(),
97
+ stepName,
98
+ });
99
+
100
+ const stepFinishedStream = (stepName: string): AgentStepType => ({
101
+ type: 'STEP_FINISHED',
102
+ timestamp: new Date().valueOf(),
103
+ stepName,
104
+ });
105
+
106
+ const toolCallStartStream = (toolCallName: string): AgentToolCallType => ({
107
+ type: 'TOOL_CALL_START',
108
+ timestamp: new Date().valueOf(),
109
+ toolCallId: 'tool_call_1',
110
+ toolCallName,
111
+ parentMessageId: 'message_1',
112
+ });
113
+
114
+ const searchQueryToolCallArgsStream = (q: string): AgentToolCallArgsType => ({
115
+ type: 'TOOL_CALL_ARGS',
116
+ timestamp: new Date().valueOf(),
117
+ toolCallId: 'tool_call_1',
118
+ delta: JSON.stringify({
119
+ q,
120
+ }),
121
+ });
122
+
123
+ const toolCallEndStream = (toolCallName: string): AgentToolCallType => ({
124
+ type: 'TOOL_CALL_END',
125
+ timestamp: new Date().valueOf(),
126
+ toolCallId: 'tool_call_1',
127
+ toolCallName,
128
+ parentMessageId: 'message_1',
129
+ });
130
+
131
+ const textMessageStream = (delta: string): AgentTextMessageType => ({
132
+ type: 'TEXT_MESSAGE_CHUNK',
133
+ timestamp: new Date().valueOf(),
134
+ messageId: 'message_2',
135
+ parentMessageId: 'message_1',
136
+ delta,
137
+ });
138
+
139
+ const exampleCitation: AgentCitation = {
140
+ id: 'some-id-1',
141
+ title: 'Some Title 1',
142
+ uri: 'https://www.coveo.com',
143
+ permanentid: 'some-permanent-id-1',
144
+ clickUri: 'https://www.coveo.com',
145
+ text: 'example text 1',
146
+ source: 'Some source 1',
147
+ filetype: 'pdf',
148
+ fields: {},
149
+ primaryId: 'primary-id-1',
150
+ };
151
+
152
+ const citationStream: AgentCitationType = {
153
+ type: 'CUSTOM',
154
+ timestamp: new Date().valueOf(),
155
+ name: 'citations',
156
+ value: {
157
+ citations: [exampleCitation],
158
+ },
159
+ };
160
+
161
+ const runFinishedStream = (answerId: string): AgentRunType => ({
162
+ type: 'RUN_FINISHED',
163
+ timestamp: new Date().valueOf(),
164
+ threadId: STREAM_ID,
165
+ runId: answerId,
166
+ result: {
167
+ completionReason: 'ANSWERED',
168
+ },
169
+ });
170
+
171
+ export type AgentMessage =
172
+ | AgentRunType
173
+ | AgentCustomType
174
+ | AgentStepType
175
+ | AgentToolCallType
176
+ | AgentToolCallArgsType
177
+ | AgentTextMessageType
178
+ | AgentCitationType;
179
+
180
+ export type AgentData = {
181
+ answerStreams: Array<AgentMessage>;
182
+ followUpStreams: Array<Array<AgentMessage>>;
183
+ conversationId: string;
184
+ answerId1: string;
185
+ answerId2: string;
186
+ answerId3: string;
187
+ conversationToken: string;
188
+ citations: Array<AgentCitation>;
189
+ };
190
+
191
+ const agentData: AgentData = {
192
+ answerStreams: [
193
+ runStartStream(ANSWER_ID_1),
194
+ customInitialHeadersStream(true),
195
+ stepStartedStream('Searching'),
196
+ toolCallStartStream('search'),
197
+ searchQueryToolCallArgsStream('test'),
198
+ toolCallEndStream('search'),
199
+ stepFinishedStream('Searching'),
200
+ stepStartedStream('Answering'),
201
+ textMessageStream('### Testing in Coveo\n\nclick **Edit components**.\n - On the **A/B test** tab, click **Configure A/B test**.\n - Set the traffic ratio and configure the **Test scenario**.\n - Click **Start** to activate the A/B test.\n\n2. **Edit an A/B Test**\n - Follow the same steps as creating an A/B test.\n - Click **Edit A/B test** and adjust the traffic ratio.'),
202
+ citationStream,
203
+ stepFinishedStream('Answering'),
204
+ runFinishedStream(ANSWER_ID_1),
205
+ ],
206
+ followUpStreams: [
207
+ [
208
+ runStartStream(ANSWER_ID_2),
209
+ customInitialHeadersStream(true),
210
+ stepStartedStream('Thinking'),
211
+ stepFinishedStream('Thinking'),
212
+ stepStartedStream('Searching'),
213
+ toolCallStartStream('search'),
214
+ searchQueryToolCallArgsStream('follow-up question'),
215
+ toolCallEndStream('search'),
216
+ stepFinishedStream('Searching'),
217
+ stepStartedStream('Answering'),
218
+ textMessageStream('This is a follow-up answer.'),
219
+ citationStream,
220
+ stepFinishedStream('Answering'),
221
+ runFinishedStream(ANSWER_ID_2),
222
+ ],
223
+ [
224
+ runStartStream(ANSWER_ID_3),
225
+ customInitialHeadersStream(true),
226
+ stepStartedStream('Thinking'),
227
+ stepFinishedStream('Thinking'),
228
+ stepStartedStream('Searching'),
229
+ toolCallStartStream('search'),
230
+ searchQueryToolCallArgsStream('third question'),
231
+ toolCallEndStream('search'),
232
+ stepFinishedStream('Searching'),
233
+ stepStartedStream('Answering'),
234
+ textMessageStream('This is the third answer.'),
235
+ citationStream,
236
+ stepFinishedStream('Answering'),
237
+ runFinishedStream(ANSWER_ID_3),
238
+ ],
239
+ ],
240
+ conversationId: STREAM_ID,
241
+ answerId1: ANSWER_ID_1,
242
+ answerId2: ANSWER_ID_2,
243
+ answerId3: ANSWER_ID_3,
244
+ conversationToken: CONVERSATION_TOKEN,
245
+ citations: [exampleCitation],
246
+ };
247
+
248
+ export default agentData;
@@ -0,0 +1,77 @@
1
+ import {quanticBase} from '../../../../../../playwright/fixtures/baseFixture';
2
+ import {SearchObject} from '../../../../../../playwright/page-object/searchObject';
3
+ import {
4
+ searchRequestRegex,
5
+ agentAnswerRequestRegex,
6
+ agentFollowUpRequestRegex,
7
+ } from '../../../../../../playwright/utils/requests';
8
+ import {GeneratedAnswerObject} from './pageObject';
9
+ import agentData from './agentData';
10
+ import type {AgentData} from './agentData';
11
+ import {AnalyticsModeEnum} from '../../../../../../playwright/utils/analyticsMode';
12
+
13
+ const pageUrl = 's/quantic-generated-answer';
14
+
15
+ interface AgentOptions {
16
+ agentId: string;
17
+ withToggle: boolean;
18
+ }
19
+
20
+ type QuanticGeneratedAnswerAgentE2EFixtures = {
21
+ agentData: AgentData;
22
+ generatedAnswer: GeneratedAnswerObject;
23
+ search: SearchObject;
24
+ options: Partial<AgentOptions>;
25
+ };
26
+
27
+ export const exampleQuery = 'test';
28
+
29
+ export const testAgent =
30
+ quanticBase.extend<QuanticGeneratedAnswerAgentE2EFixtures>({
31
+ pageUrl,
32
+ agentData,
33
+ options: {},
34
+ analyticsMode: AnalyticsModeEnum.legacy,
35
+ search: async ({page}, use) => {
36
+ await use(new SearchObject(page, searchRequestRegex));
37
+ },
38
+ generatedAnswer: async (
39
+ {page, options, configuration, search, agentData: data, analytics},
40
+ use
41
+ ) => {
42
+ const generatedAnswerObject = new GeneratedAnswerObject(
43
+ page,
44
+ data.answerId1,
45
+ analytics,
46
+ {
47
+ headAnswerRequestRegex: agentAnswerRequestRegex,
48
+ agentFollowUpRequestRegex,
49
+ isAgent: true,
50
+ }
51
+ );
52
+
53
+ await generatedAnswerObject.mockAgentAnswerResponse(
54
+ data.answerStreams
55
+ );
56
+ await generatedAnswerObject.mockAgentFollowUpResponse(
57
+ data.followUpStreams
58
+ );
59
+
60
+ await page.goto(pageUrl);
61
+ await configuration.configure(options);
62
+ await search.waitForSearchResponse();
63
+
64
+ generatedAnswerObject.streamEndAnalyticRequestPromise =
65
+ generatedAnswerObject.waitForStreamEndAnalytics();
66
+ generatedAnswerObject.generateRequestPromise =
67
+ generatedAnswerObject.waitForHeadAnswerRequest();
68
+
69
+ await search.fillSearchInput(exampleQuery);
70
+ await search.performSearch();
71
+ await search.waitForSearchResponse();
72
+
73
+ await use(generatedAnswerObject);
74
+ },
75
+ });
76
+
77
+ export {expect} from '@playwright/test';
@@ -44,70 +44,74 @@ type QuanticGeneratedAnswerE2EInsightFixtures =
44
44
 
45
45
  export const exampleQuery = 'test';
46
46
 
47
- export const testSearch = quanticBase.extend<QuanticGeneratedAnswerE2ESearchFixtures>({
48
- pageUrl,
49
- genQaData,
50
- options: {},
51
- analyticsMode: AnalyticsModeEnum.legacy,
52
- withFacets: false,
53
- search: async ({page}, use) => {
54
- await use(new SearchObject(page, searchRequestRegex));
55
- },
56
- baseFacet: async ({page}, use) => {
57
- await use(new BaseFacetObject(page, searchRequestRegex));
58
- },
59
- generatedAnswer: async (
60
- {
61
- page,
62
- options,
63
- configuration,
64
- search,
65
- genQaData: data,
66
- analytics,
67
- withFacets,
47
+ export const testSearch =
48
+ quanticBase.extend<QuanticGeneratedAnswerE2ESearchFixtures>({
49
+ pageUrl,
50
+ genQaData,
51
+ options: {},
52
+ analyticsMode: AnalyticsModeEnum.legacy,
53
+ withFacets: false,
54
+ search: async ({page}, use) => {
55
+ await use(new SearchObject(page, searchRequestRegex));
68
56
  },
69
- use
70
- ) => {
71
- const generatedAnswerObject = new GeneratedAnswerObject(
72
- page,
73
- data.streamId,
74
- analytics,
75
- !!options.answerConfigurationId,
76
- rgaGenerateRequestRegex,
77
- withFacets,
78
- );
79
-
80
- const streamingUrl = options.answerConfigurationId
81
- ? ANSWER_API_URL
82
- : `${MACHINE_LEARNING_API_URL}/${data.streamId}`;
83
- await generatedAnswerObject.mockStreamResponse(
84
- streamingUrl,
85
- data.streams,
86
- data.streamId
87
- );
88
-
89
- await page.goto(pageUrl);
90
- if (withFacets) {
91
- await generatedAnswerObject.clickAddFacetsButton();
92
- }
93
- await configuration.configure(options);
94
- await search.waitForSearchResponse();
57
+ baseFacet: async ({page}, use) => {
58
+ await use(new BaseFacetObject(page, searchRequestRegex));
59
+ },
60
+ generatedAnswer: async (
61
+ {
62
+ page,
63
+ options,
64
+ configuration,
65
+ search,
66
+ genQaData: data,
67
+ analytics,
68
+ withFacets,
69
+ },
70
+ use
71
+ ) => {
72
+ const generatedAnswerObject = new GeneratedAnswerObject(
73
+ page,
74
+ data.streamId,
75
+ analytics,
76
+ {
77
+ answerApiEnabled: !!options.answerConfigurationId,
78
+ headAnswerRequestRegex: rgaGenerateRequestRegex,
79
+ withFacets,
80
+ }
81
+ );
82
+
83
+ const streamingUrl = options.answerConfigurationId
84
+ ? ANSWER_API_URL
85
+ : `${MACHINE_LEARNING_API_URL}/${data.streamId}`;
86
+ await generatedAnswerObject.mockStreamResponse(
87
+ streamingUrl,
88
+ data.streams,
89
+ data.streamId
90
+ );
91
+
92
+ await page.goto(pageUrl);
93
+ if (withFacets) {
94
+ await generatedAnswerObject.clickAddFacetsButton();
95
+ }
96
+ await configuration.configure(options);
97
+ await search.waitForSearchResponse();
95
98
 
96
99
  generatedAnswerObject.streamEndAnalyticRequestPromise =
97
100
  generatedAnswerObject.waitForStreamEndAnalytics();
101
+
98
102
  if (options.answerConfigurationId) {
99
103
  generatedAnswerObject.generateRequestPromise =
100
- generatedAnswerObject.waitForGenerateRequest();
104
+ generatedAnswerObject.waitForHeadAnswerRequest();
101
105
  }
102
106
 
103
- await search.fillSearchInput(exampleQuery);
104
- await search.mockSearchWithGenerativeQuestionAnsweringId(data.streamId);
105
- await search.performSearch();
106
- await search.waitForSearchResponse();
107
+ await search.fillSearchInput(exampleQuery);
108
+ await search.mockSearchWithGenerativeQuestionAnsweringId(data.streamId);
109
+ await search.performSearch();
110
+ await search.waitForSearchResponse();
107
111
 
108
- await use(generatedAnswerObject);
109
- },
110
- });
112
+ await use(generatedAnswerObject);
113
+ },
114
+ });
111
115
 
112
116
  export const testInsight =
113
117
  quanticBase.extend<QuanticGeneratedAnswerE2EInsightFixtures>({
@@ -142,9 +146,11 @@ export const testInsight =
142
146
  page,
143
147
  data.streamId,
144
148
  analytics,
145
- !!options.answerConfigurationId,
146
- insightRgaGenerateRequestRegex,
147
- withFacets
149
+ {
150
+ answerApiEnabled: !!options.answerConfigurationId,
151
+ headAnswerRequestRegex: insightRgaGenerateRequestRegex,
152
+ withFacets,
153
+ }
148
154
  );
149
155
 
150
156
  const streamingUrl = options.answerConfigurationId
@@ -171,7 +177,7 @@ export const testInsight =
171
177
  generatedAnswerObject.waitForStreamEndAnalytics();
172
178
  if (options.answerConfigurationId) {
173
179
  generatedAnswerObject.generateRequestPromise =
174
- generatedAnswerObject.waitForGenerateRequest();
180
+ generatedAnswerObject.waitForHeadAnswerRequest();
175
181
  }
176
182
 
177
183
  await search.fillSearchInput(exampleQuery);