@eeacms/volto-eea-chatbot 1.0.9
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/.coverage.babel.config.js +9 -0
- package/.eslintrc.js +68 -0
- package/.husky/pre-commit +2 -0
- package/.release-it.json +17 -0
- package/AGENTS.md +89 -0
- package/CHANGELOG.md +770 -0
- package/DEVELOP.md +124 -0
- package/LICENSE.md +9 -0
- package/README.md +170 -0
- package/RELEASE.md +74 -0
- package/TESTING.md +5 -0
- package/babel.config.js +17 -0
- package/bootstrap +41 -0
- package/cypress.config.js +27 -0
- package/docker-compose.yml +32 -0
- package/jest-addon.config.js +465 -0
- package/jest.setup.js +65 -0
- package/locales/de/LC_MESSAGES/volto.po +14 -0
- package/locales/en/LC_MESSAGES/volto.po +14 -0
- package/locales/it/LC_MESSAGES/volto.po +14 -0
- package/locales/ro/LC_MESSAGES/volto.po +14 -0
- package/locales/volto.pot +16 -0
- package/package.json +98 -0
- package/razzle.extend.js +40 -0
- package/src/ChatBlock/ChatBlockEdit.jsx +46 -0
- package/src/ChatBlock/ChatBlockView.jsx +21 -0
- package/src/ChatBlock/chat/AIMessage.tsx +566 -0
- package/src/ChatBlock/chat/ChatMessage.tsx +35 -0
- package/src/ChatBlock/chat/ChatWindow.tsx +288 -0
- package/src/ChatBlock/chat/UserMessage.tsx +27 -0
- package/src/ChatBlock/chat/index.ts +4 -0
- package/src/ChatBlock/components/AutoResizeTextarea.jsx +67 -0
- package/src/ChatBlock/components/BlinkingDot.tsx +3 -0
- package/src/ChatBlock/components/ChatMessageFeedback.jsx +77 -0
- package/src/ChatBlock/components/EmptyState.jsx +70 -0
- package/src/ChatBlock/components/FeedbackModal.jsx +125 -0
- package/src/ChatBlock/components/HalloumiFeedback.jsx +126 -0
- package/src/ChatBlock/components/Icon.tsx +35 -0
- package/src/ChatBlock/components/QualityCheckToggle.jsx +26 -0
- package/src/ChatBlock/components/RelatedQuestions.jsx +59 -0
- package/src/ChatBlock/components/Source.jsx +93 -0
- package/src/ChatBlock/components/SourceChip.tsx +55 -0
- package/src/ChatBlock/components/Spinner.jsx +3 -0
- package/src/ChatBlock/components/UserActionsToolbar.jsx +44 -0
- package/src/ChatBlock/components/WebResultIcon.tsx +42 -0
- package/src/ChatBlock/components/markdown/Citation.jsx +70 -0
- package/src/ChatBlock/components/markdown/ClaimModal.jsx +98 -0
- package/src/ChatBlock/components/markdown/ClaimSegments.jsx +172 -0
- package/src/ChatBlock/components/markdown/RenderClaimView.jsx +96 -0
- package/src/ChatBlock/components/markdown/colors.js +29 -0
- package/src/ChatBlock/components/markdown/colors.less +52 -0
- package/src/ChatBlock/components/markdown/colors.test.js +69 -0
- package/src/ChatBlock/components/markdown/index.js +115 -0
- package/src/ChatBlock/fonts/DejaVuSans.ttf +0 -0
- package/src/ChatBlock/hocs/withOnyxData.jsx +46 -0
- package/src/ChatBlock/hooks/index.ts +7 -0
- package/src/ChatBlock/hooks/useChatController.ts +333 -0
- package/src/ChatBlock/hooks/useChatStreaming.ts +82 -0
- package/src/ChatBlock/hooks/useDeepCompareMemoize.js +17 -0
- package/src/ChatBlock/hooks/useMarked.js +44 -0
- package/src/ChatBlock/hooks/useQualityMarkers.js +119 -0
- package/src/ChatBlock/hooks/useScrollonStream.ts +131 -0
- package/src/ChatBlock/hooks/useToolDisplayTiming.ts +80 -0
- package/src/ChatBlock/index.js +32 -0
- package/src/ChatBlock/packets/MultiToolRenderer.tsx +235 -0
- package/src/ChatBlock/packets/RendererComponent.tsx +115 -0
- package/src/ChatBlock/packets/index.ts +4 -0
- package/src/ChatBlock/packets/renderers/CustomToolRenderer.tsx +63 -0
- package/src/ChatBlock/packets/renderers/FetchToolRenderer.tsx +59 -0
- package/src/ChatBlock/packets/renderers/ImageToolRenderer.tsx +62 -0
- package/src/ChatBlock/packets/renderers/MessageTextRenderer.tsx +172 -0
- package/src/ChatBlock/packets/renderers/ReasoningRenderer.tsx +122 -0
- package/src/ChatBlock/packets/renderers/SearchToolRenderer.tsx +323 -0
- package/src/ChatBlock/packets/renderers/index.ts +6 -0
- package/src/ChatBlock/schema.js +403 -0
- package/src/ChatBlock/services/index.ts +3 -0
- package/src/ChatBlock/services/messageProcessor.ts +348 -0
- package/src/ChatBlock/services/packetUtils.ts +48 -0
- package/src/ChatBlock/services/streamingService.ts +342 -0
- package/src/ChatBlock/style.less +1881 -0
- package/src/ChatBlock/tests/AIMessage.test.jsx +95 -0
- package/src/ChatBlock/tests/AutoResizeTextarea.test.jsx +49 -0
- package/src/ChatBlock/tests/BlinkingDot.test.jsx +71 -0
- package/src/ChatBlock/tests/ChatMessageFeedback.test.jsx +73 -0
- package/src/ChatBlock/tests/Citation.test.jsx +107 -0
- package/src/ChatBlock/tests/EmptyState.test.jsx +137 -0
- package/src/ChatBlock/tests/FeedbackModal.test.jsx +138 -0
- package/src/ChatBlock/tests/HalloumiFeedback.test.jsx +94 -0
- package/src/ChatBlock/tests/QualityCheckToggle.test.jsx +105 -0
- package/src/ChatBlock/tests/RelatedQuestions.test.jsx +215 -0
- package/src/ChatBlock/tests/Source.test.jsx +79 -0
- package/src/ChatBlock/tests/Spinner.test.jsx +18 -0
- package/src/ChatBlock/tests/index.test.js +51 -0
- package/src/ChatBlock/tests/messageProcessor.test.jsx +154 -0
- package/src/ChatBlock/tests/schema.test.js +166 -0
- package/src/ChatBlock/tests/useDeepCompareMemoize.test.js +107 -0
- package/src/ChatBlock/tests/useToolDisplayTiming.test.jsx +151 -0
- package/src/ChatBlock/types/cssmodules.d.ts +7 -0
- package/src/ChatBlock/types/interfaces.ts +154 -0
- package/src/ChatBlock/types/slate.d.ts +3 -0
- package/src/ChatBlock/types/streamingModels.ts +267 -0
- package/src/ChatBlock/types/volto.d.ts +3 -0
- package/src/ChatBlock/utils/citations.ts +25 -0
- package/src/ChatBlock/utils/index.tsx +114 -0
- package/src/halloumi/README.md +1 -0
- package/src/halloumi/generative.js +219 -0
- package/src/halloumi/generative.test.js +88 -0
- package/src/halloumi/middleware.js +70 -0
- package/src/halloumi/postprocessing.js +273 -0
- package/src/halloumi/postprocessing.test.js +441 -0
- package/src/halloumi/preprocessing.js +115 -0
- package/src/halloumi/preprocessing.test.js +245 -0
- package/src/icons/bot.svg +1 -0
- package/src/icons/check.svg +1 -0
- package/src/icons/chevron.svg +3 -0
- package/src/icons/clear.svg +1 -0
- package/src/icons/copy.svg +1 -0
- package/src/icons/done.svg +5 -0
- package/src/icons/external-link.svg +1 -0
- package/src/icons/file.svg +1 -0
- package/src/icons/glasses.svg +1 -0
- package/src/icons/globe.svg +1 -0
- package/src/icons/rotate.svg +1 -0
- package/src/icons/search.svg +5 -0
- package/src/icons/send.svg +1 -0
- package/src/icons/square-pen.svg +1 -0
- package/src/icons/stop.svg +9 -0
- package/src/icons/thumbs-down.svg +1 -0
- package/src/icons/thumbs-up.svg +1 -0
- package/src/icons/user.svg +1 -0
- package/src/index.js +58 -0
- package/src/middleware.js +250 -0
- package/tsconfig.json +40 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CitationDelta,
|
|
3
|
+
MessageDelta,
|
|
4
|
+
MessageStart,
|
|
5
|
+
OnyxDocument,
|
|
6
|
+
Packet,
|
|
7
|
+
StreamingCitation,
|
|
8
|
+
} from '../types/streamingModels';
|
|
9
|
+
import type { Message, ToolCallMetadata } from '../types/interfaces';
|
|
10
|
+
import {
|
|
11
|
+
getSynteticPacket,
|
|
12
|
+
isToolPacket,
|
|
13
|
+
isDisplayPacket,
|
|
14
|
+
} from './packetUtils';
|
|
15
|
+
import { PacketType } from '../types/streamingModels';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Process streaming packets into a message object
|
|
19
|
+
*/
|
|
20
|
+
export class MessageProcessor {
|
|
21
|
+
private packets: Packet[] = [];
|
|
22
|
+
private groupedPackets = new Map<number, Packet[]>();
|
|
23
|
+
private toolPackets: number[] = [];
|
|
24
|
+
private displayPackets: number[] = [];
|
|
25
|
+
private userMessageId: number | null = null;
|
|
26
|
+
private assistantMessageId: number | null = null;
|
|
27
|
+
private documentMap = new Map<string, OnyxDocument>();
|
|
28
|
+
private indicesStarted: number[] = [];
|
|
29
|
+
private _textContent: string = '';
|
|
30
|
+
private _errorContent: string = '';
|
|
31
|
+
private _documents: OnyxDocument[] = [];
|
|
32
|
+
private _citations = new Map<number, string>();
|
|
33
|
+
private _isComplete: boolean = false;
|
|
34
|
+
private _isFinalMessageComing: boolean = false;
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
private nodeId: number,
|
|
38
|
+
private parentNodeId: number | null,
|
|
39
|
+
) {}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Add new packets to the processor
|
|
43
|
+
*/
|
|
44
|
+
addPackets(newPackets: Packet[]): void {
|
|
45
|
+
for (const packet of newPackets) {
|
|
46
|
+
this.processPacket(packet);
|
|
47
|
+
this.processMessageIdsInfo(packet);
|
|
48
|
+
this.processTextContent(packet);
|
|
49
|
+
this.processDocuments(packet);
|
|
50
|
+
this.processCitations(packet);
|
|
51
|
+
this.processFinalMessageComming(packet);
|
|
52
|
+
this.processError(packet);
|
|
53
|
+
this.processStreamEnd(packet);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Getters
|
|
58
|
+
/**
|
|
59
|
+
* Indicates if the streaming has completed
|
|
60
|
+
*/
|
|
61
|
+
get isComplete(): boolean {
|
|
62
|
+
return this._isComplete;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Indicates if the final message is about to come
|
|
67
|
+
*/
|
|
68
|
+
get isFinalMessageComing(): boolean {
|
|
69
|
+
return this._isFinalMessageComing;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get the real database message IDs from backend
|
|
74
|
+
*/
|
|
75
|
+
get messageIds(): {
|
|
76
|
+
userMessageId: number | null;
|
|
77
|
+
assistantMessageId: number | null;
|
|
78
|
+
} {
|
|
79
|
+
return {
|
|
80
|
+
userMessageId: this.userMessageId,
|
|
81
|
+
assistantMessageId: this.assistantMessageId,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Packet processing
|
|
86
|
+
/**
|
|
87
|
+
* Process a single packet and track its lifecycle
|
|
88
|
+
*/
|
|
89
|
+
private processPacket(packet: Packet) {
|
|
90
|
+
let processedPacket: Packet = packet;
|
|
91
|
+
|
|
92
|
+
// Store tool packets indices
|
|
93
|
+
if (isToolPacket(packet) && !this.toolPackets.includes(packet.ind)) {
|
|
94
|
+
this.toolPackets.push(packet.ind);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Store display packets indices
|
|
98
|
+
if (isDisplayPacket(packet) && !this.displayPackets.includes(packet.ind)) {
|
|
99
|
+
this.displayPackets.push(packet.ind);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Keep track of all started indices to know when to send SECTION_END
|
|
103
|
+
if (
|
|
104
|
+
packet.ind > -1 &&
|
|
105
|
+
packet.obj.type !== PacketType.SECTION_END &&
|
|
106
|
+
!this.indicesStarted.includes(packet.ind)
|
|
107
|
+
) {
|
|
108
|
+
this.indicesStarted.push(packet.ind);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Send synthetic SECTION_END when needed
|
|
112
|
+
if (
|
|
113
|
+
packet.obj.type === PacketType.SECTION_END &&
|
|
114
|
+
this.indicesStarted.length > 0
|
|
115
|
+
) {
|
|
116
|
+
processedPacket = getSynteticPacket(
|
|
117
|
+
this.indicesStarted.shift()!,
|
|
118
|
+
PacketType.SECTION_END,
|
|
119
|
+
);
|
|
120
|
+
} else if (packet.obj.type === PacketType.SECTION_END) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const { ind } = processedPacket;
|
|
125
|
+
|
|
126
|
+
// Store processed packet for later aggregation
|
|
127
|
+
this.packets.push(processedPacket);
|
|
128
|
+
|
|
129
|
+
// Group packets by index for later processing
|
|
130
|
+
if (!this.groupedPackets.has(ind)) {
|
|
131
|
+
this.groupedPackets.set(ind, []);
|
|
132
|
+
}
|
|
133
|
+
this.groupedPackets.get(ind)!.push(processedPacket);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Process MESSAGE_END_ID_INFO packets to extract message IDs
|
|
138
|
+
* These packets contain the actual database message IDs assigned by the backend
|
|
139
|
+
*/
|
|
140
|
+
private processMessageIdsInfo(packet: Packet) {
|
|
141
|
+
if (packet.obj.type !== PacketType.MESSAGE_END_ID_INFO) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const idInfo = packet.obj;
|
|
145
|
+
this.userMessageId = idInfo.user_message_id;
|
|
146
|
+
this.assistantMessageId = idInfo.reserved_assistant_message_id;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Process text content from MESSAGE_START and MESSAGE_DELTA packets
|
|
151
|
+
* Accumulates text content across multiple packets
|
|
152
|
+
*/
|
|
153
|
+
private processTextContent(packet: Packet) {
|
|
154
|
+
if (
|
|
155
|
+
[PacketType.MESSAGE_START, PacketType.MESSAGE_DELTA].includes(
|
|
156
|
+
packet.obj.type,
|
|
157
|
+
)
|
|
158
|
+
) {
|
|
159
|
+
const content = (packet.obj as MessageStart | MessageDelta).content || '';
|
|
160
|
+
this._textContent += content;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Process document information from various tool packets
|
|
166
|
+
* Updates the internal document collection and notifies when new documents are added
|
|
167
|
+
*/
|
|
168
|
+
private processDocuments(packet: Packet) {
|
|
169
|
+
if (
|
|
170
|
+
![
|
|
171
|
+
PacketType.MESSAGE_START,
|
|
172
|
+
PacketType.SEARCH_TOOL_DELTA,
|
|
173
|
+
PacketType.FETCH_TOOL_START,
|
|
174
|
+
].includes(packet.obj.type)
|
|
175
|
+
) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
let newDocuments = false;
|
|
179
|
+
const data = packet.obj as any;
|
|
180
|
+
const documents = data.final_documents || data.documents;
|
|
181
|
+
if (documents) {
|
|
182
|
+
documents.forEach((doc: OnyxDocument) => {
|
|
183
|
+
const docId = doc.document_id;
|
|
184
|
+
if (docId && !this.documentMap.has(docId)) {
|
|
185
|
+
this.documentMap.set(docId, doc);
|
|
186
|
+
newDocuments = true;
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
if (newDocuments) {
|
|
191
|
+
this._documents = Array.from(this.documentMap.values());
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Process citation information from CITATION_DELTA packets
|
|
197
|
+
* Updates the internal citation collection and notifies when new citations are added
|
|
198
|
+
*/
|
|
199
|
+
private processCitations(packet: Packet) {
|
|
200
|
+
if (packet.obj.type !== PacketType.CITATION_DELTA) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const citationDelta = packet.obj as CitationDelta;
|
|
204
|
+
citationDelta.citations?.forEach((citation: StreamingCitation) => {
|
|
205
|
+
if (!this._citations.has(citation.citation_num)) {
|
|
206
|
+
this._citations.set(citation.citation_num, citation.document_id);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Check if a packet indicates the final message is about to be sent
|
|
213
|
+
* Sets the _isFinalMessageComing flag when appropriate
|
|
214
|
+
*/
|
|
215
|
+
private processFinalMessageComming(packet: Packet) {
|
|
216
|
+
if (
|
|
217
|
+
[
|
|
218
|
+
PacketType.MESSAGE_START,
|
|
219
|
+
PacketType.IMAGE_GENERATION_TOOL_START,
|
|
220
|
+
].includes(packet.obj.type)
|
|
221
|
+
) {
|
|
222
|
+
this._isFinalMessageComing = true;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private processError(packet: Packet) {
|
|
227
|
+
if (packet.obj.type === PacketType.ERROR) {
|
|
228
|
+
this._errorContent = packet.obj.error;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Handle STOP packets to mark streaming as complete
|
|
234
|
+
*/
|
|
235
|
+
private processStreamEnd(packet: Packet) {
|
|
236
|
+
if ([PacketType.STOP, PacketType.ERROR].includes(packet.obj.type)) {
|
|
237
|
+
this._isComplete = true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Utility methods
|
|
242
|
+
/**
|
|
243
|
+
* Extract tool call information from packets
|
|
244
|
+
*/
|
|
245
|
+
private extractToolCall(packets: Packet[]): ToolCallMetadata | null {
|
|
246
|
+
// Look for search tool packets
|
|
247
|
+
const searchToolStart = packets.find(
|
|
248
|
+
(p) => p.obj.type === PacketType.SEARCH_TOOL_START,
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
if (!searchToolStart) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Collect all documents from SEARCH_TOOL_DELTA packets
|
|
256
|
+
const toolDocuments: any[] = [];
|
|
257
|
+
const processedDocs: Record<string, any> = {};
|
|
258
|
+
|
|
259
|
+
for (const packet of packets) {
|
|
260
|
+
if (packet.obj.type === PacketType.SEARCH_TOOL_DELTA) {
|
|
261
|
+
const delta = packet.obj as any;
|
|
262
|
+
if (delta.documents && Array.isArray(delta.documents)) {
|
|
263
|
+
delta.documents.forEach((doc: any) => {
|
|
264
|
+
if (!processedDocs[doc.document_id]) {
|
|
265
|
+
processedDocs[doc.document_id] = doc;
|
|
266
|
+
toolDocuments.push(doc);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// If we have documents, create the tool call metadata
|
|
274
|
+
if (toolDocuments.length > 0) {
|
|
275
|
+
return {
|
|
276
|
+
tool_name: 'run_search',
|
|
277
|
+
tool_args: {
|
|
278
|
+
query: '', // Query info might be in SEARCH_TOOL_DELTA.queries
|
|
279
|
+
},
|
|
280
|
+
tool_result: toolDocuments.map((doc) => ({
|
|
281
|
+
...doc,
|
|
282
|
+
content: doc.content || doc.blurb,
|
|
283
|
+
})),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Get the current message state
|
|
292
|
+
*/
|
|
293
|
+
getMessage(): Message {
|
|
294
|
+
let toolCall = null;
|
|
295
|
+
|
|
296
|
+
if (this._isComplete) {
|
|
297
|
+
// Extract tool call information
|
|
298
|
+
toolCall = this._isComplete ? this.extractToolCall(this.packets) : null;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
messageId: this.assistantMessageId,
|
|
303
|
+
nodeId: this.nodeId,
|
|
304
|
+
message: this._textContent,
|
|
305
|
+
error: this._errorContent,
|
|
306
|
+
type: 'assistant',
|
|
307
|
+
parentNodeId: this.parentNodeId,
|
|
308
|
+
packets: [...this.packets],
|
|
309
|
+
groupedPackets: Array.from(this.groupedPackets.entries())
|
|
310
|
+
.map(([ind, packets]) => ({
|
|
311
|
+
ind,
|
|
312
|
+
packets: [...packets],
|
|
313
|
+
}))
|
|
314
|
+
.sort((a, b) => a.ind - b.ind),
|
|
315
|
+
toolPackets: [...this.toolPackets],
|
|
316
|
+
displayPackets: [...this.displayPackets],
|
|
317
|
+
documents: this._documents.length > 0 ? [...this._documents] : null,
|
|
318
|
+
citations:
|
|
319
|
+
this._citations.size > 0
|
|
320
|
+
? Object.fromEntries(this._citations)
|
|
321
|
+
: undefined,
|
|
322
|
+
files: [],
|
|
323
|
+
isComplete: this._isComplete,
|
|
324
|
+
isFinalMessageComing: this._isFinalMessageComing,
|
|
325
|
+
toolCall,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Reset the processor
|
|
331
|
+
*/
|
|
332
|
+
reset(): void {
|
|
333
|
+
this.packets = [];
|
|
334
|
+
this.groupedPackets.clear();
|
|
335
|
+
this.toolPackets = [];
|
|
336
|
+
this.displayPackets = [];
|
|
337
|
+
this.userMessageId = null;
|
|
338
|
+
this.assistantMessageId = null;
|
|
339
|
+
this.documentMap.clear();
|
|
340
|
+
this.indicesStarted = [];
|
|
341
|
+
this._textContent = '';
|
|
342
|
+
this._errorContent = '';
|
|
343
|
+
this._documents = [];
|
|
344
|
+
this._citations.clear();
|
|
345
|
+
this._isComplete = false;
|
|
346
|
+
this._isFinalMessageComing = false;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Packet } from '../types/streamingModels';
|
|
2
|
+
import { PacketType } from '../types/streamingModels';
|
|
3
|
+
|
|
4
|
+
export function getSynteticPacket(ind: number, type: PacketType): Packet {
|
|
5
|
+
return {
|
|
6
|
+
ind,
|
|
7
|
+
obj: { type } as any,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function isToolPacket(packet: Packet): boolean {
|
|
12
|
+
const toolPacketTypes = [
|
|
13
|
+
PacketType.SEARCH_TOOL_START,
|
|
14
|
+
PacketType.SEARCH_TOOL_DELTA,
|
|
15
|
+
PacketType.CUSTOM_TOOL_START,
|
|
16
|
+
PacketType.CUSTOM_TOOL_DELTA,
|
|
17
|
+
PacketType.REASONING_START,
|
|
18
|
+
PacketType.REASONING_DELTA,
|
|
19
|
+
PacketType.FETCH_TOOL_START,
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
return toolPacketTypes.includes(packet.obj.type as PacketType);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function isDisplayPacket(packet: Packet): boolean {
|
|
26
|
+
return [
|
|
27
|
+
PacketType.MESSAGE_START,
|
|
28
|
+
PacketType.IMAGE_GENERATION_TOOL_START,
|
|
29
|
+
].includes(packet.obj.type as PacketType);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function isFinalAnswerComplete(packets: Packet[]): boolean {
|
|
33
|
+
const messageStartPacket = packets.find(
|
|
34
|
+
(packet) =>
|
|
35
|
+
packet.obj.type === PacketType.MESSAGE_START ||
|
|
36
|
+
packet.obj.type === PacketType.IMAGE_GENERATION_TOOL_START,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (!messageStartPacket) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return packets.some(
|
|
44
|
+
(packet) =>
|
|
45
|
+
packet.obj.type === PacketType.SECTION_END &&
|
|
46
|
+
packet.ind === messageStartPacket.ind,
|
|
47
|
+
);
|
|
48
|
+
}
|