@vezlo/assistant-chat 1.7.0 → 1.8.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.
- package/lib/api/message.d.ts +10 -1
- package/lib/api/message.js +1 -1
- package/lib/components/Widget.js +42 -5
- package/lib/types/index.d.ts +20 -0
- package/package.json +1 -1
package/lib/api/message.d.ts
CHANGED
|
@@ -29,6 +29,11 @@ export interface StreamChunkEvent {
|
|
|
29
29
|
document_title: string;
|
|
30
30
|
chunk_indices: number[];
|
|
31
31
|
}>;
|
|
32
|
+
validation?: {
|
|
33
|
+
confidence: number;
|
|
34
|
+
valid: boolean;
|
|
35
|
+
status: string;
|
|
36
|
+
};
|
|
32
37
|
}
|
|
33
38
|
export interface StreamCompletionEvent {
|
|
34
39
|
type: 'completion';
|
|
@@ -48,7 +53,11 @@ export interface StreamCallbacks {
|
|
|
48
53
|
document_uuid: string;
|
|
49
54
|
document_title: string;
|
|
50
55
|
chunk_indices: number[];
|
|
51
|
-
}
|
|
56
|
+
}>, validation?: {
|
|
57
|
+
confidence: number;
|
|
58
|
+
valid: boolean;
|
|
59
|
+
status: string;
|
|
60
|
+
}) => void;
|
|
52
61
|
onCompletion?: (data: StreamCompletionEvent) => void;
|
|
53
62
|
onError?: (error: StreamErrorEvent) => void;
|
|
54
63
|
onDone?: () => void;
|
package/lib/api/message.js
CHANGED
|
@@ -121,7 +121,7 @@ export async function streamAIResponse(userMessageUuid, callbacks, apiUrl) {
|
|
|
121
121
|
const event = JSON.parse(data);
|
|
122
122
|
switch (event.type) {
|
|
123
123
|
case 'chunk':
|
|
124
|
-
callbacks.onChunk?.(event.content, event.done, event.sources);
|
|
124
|
+
callbacks.onChunk?.(event.content, event.done, event.sources, event.validation);
|
|
125
125
|
break;
|
|
126
126
|
case 'completion':
|
|
127
127
|
callbacks.onCompletion?.(event);
|
package/lib/components/Widget.js
CHANGED
|
@@ -189,7 +189,7 @@ export function Widget({ config, isPlayground = false, onOpen, onClose, onMessag
|
|
|
189
189
|
const tempMessageId = `streaming-${userMessageResponse.uuid}`;
|
|
190
190
|
// Stream AI response using SSE
|
|
191
191
|
await streamAIResponse(userMessageResponse.uuid, {
|
|
192
|
-
onChunk: (chunk, isDone, sources) => {
|
|
192
|
+
onChunk: (chunk, isDone, sources, validation) => {
|
|
193
193
|
// Hide loading indicator on first chunk (streaming started)
|
|
194
194
|
if (!hasReceivedChunks) {
|
|
195
195
|
hasReceivedChunks = true;
|
|
@@ -203,8 +203,8 @@ export function Widget({ config, isPlayground = false, onOpen, onClose, onMessag
|
|
|
203
203
|
// If this is the final chunk (done=true), convert to message immediately
|
|
204
204
|
if (isDone && !streamingComplete) {
|
|
205
205
|
streamingComplete = true;
|
|
206
|
-
console.log('Stream complete, sources:', sources);
|
|
207
|
-
// Add message to array with temp ID and
|
|
206
|
+
console.log('Stream complete, sources:', sources, 'validation:', validation);
|
|
207
|
+
// Add message to array with temp ID, sources, and validation
|
|
208
208
|
const tempMessage = {
|
|
209
209
|
id: tempMessageId,
|
|
210
210
|
content: accumulatedContent,
|
|
@@ -215,7 +215,8 @@ export function Widget({ config, isPlayground = false, onOpen, onClose, onMessag
|
|
|
215
215
|
document_uuid: s.document_uuid,
|
|
216
216
|
document_title: s.document_title,
|
|
217
217
|
chunk_indices: s.chunk_indices
|
|
218
|
-
})) : undefined
|
|
218
|
+
})) : undefined,
|
|
219
|
+
validation: validation
|
|
219
220
|
};
|
|
220
221
|
setStreamingMessage('');
|
|
221
222
|
setMessages((prev) => [...prev, tempMessage]);
|
|
@@ -498,7 +499,43 @@ export function Widget({ config, isPlayground = false, onOpen, onClose, onMessag
|
|
|
498
499
|
const isTempId = message.id?.startsWith('streaming-') || false;
|
|
499
500
|
const hasRealUuid = !!message._realUuid;
|
|
500
501
|
const isDisabled = isTempId && !hasRealUuid;
|
|
501
|
-
return (_jsxs("div", { className: "flex items-center gap-1 ml-2", children: [_jsx("
|
|
502
|
+
return (_jsxs("div", { className: "flex items-center gap-1 ml-2", children: [message.validation && (_jsx("div", { className: "relative w-5 h-5 cursor-pointer", title: `AI Validation\nConfidence: ${(message.validation.confidence * 100).toFixed(1)}%\nStatus: ${message.validation.status}${message.validation.accuracy ? `\n\nAccuracy:\n Verified: ${message.validation.accuracy.verified ? 'Yes' : 'No'}\n Rate: ${(message.validation.accuracy.verification_rate * 100).toFixed(1)}%` : ''}${message.validation.hallucination ? `\n\nHallucination:\n Detected: ${message.validation.hallucination.detected ? 'Yes' : 'No'}\n Risk: ${(message.validation.hallucination.risk * 100).toFixed(1)}%` : ''}${message.validation.context ? `\n\nContext:\n Relevance: ${(message.validation.context.source_relevance * 100).toFixed(1)}%\n Usage: ${(message.validation.context.source_usage_rate * 100).toFixed(1)}%` : ''}`, children: _jsxs("svg", { className: "w-5 h-5", viewBox: "0 0 24 24", fill: "none", children: [_jsx("circle", { cx: "12", cy: "12", r: "9.5", className: message.validation.confidence > 0.7
|
|
503
|
+
? 'fill-green-500'
|
|
504
|
+
: message.validation.confidence > 0.5
|
|
505
|
+
? 'fill-amber-500'
|
|
506
|
+
: 'fill-red-500' }), _jsx("path", { d: "M12 0.5 L13.5 3 L10.5 3 Z", className: message.validation.confidence > 0.7
|
|
507
|
+
? 'fill-green-500'
|
|
508
|
+
: message.validation.confidence > 0.5
|
|
509
|
+
? 'fill-amber-500'
|
|
510
|
+
: 'fill-red-500' }), _jsx("path", { d: "M20.5 4.5 L19 7 L18 5 Z", className: message.validation.confidence > 0.7
|
|
511
|
+
? 'fill-green-500'
|
|
512
|
+
: message.validation.confidence > 0.5
|
|
513
|
+
? 'fill-amber-500'
|
|
514
|
+
: 'fill-red-500' }), _jsx("path", { d: "M23.5 12 L21 13.5 L21 10.5 Z", className: message.validation.confidence > 0.7
|
|
515
|
+
? 'fill-green-500'
|
|
516
|
+
: message.validation.confidence > 0.5
|
|
517
|
+
? 'fill-amber-500'
|
|
518
|
+
: 'fill-red-500' }), _jsx("path", { d: "M20.5 19.5 L18 19 L19 17 Z", className: message.validation.confidence > 0.7
|
|
519
|
+
? 'fill-green-500'
|
|
520
|
+
: message.validation.confidence > 0.5
|
|
521
|
+
? 'fill-amber-500'
|
|
522
|
+
: 'fill-red-500' }), _jsx("path", { d: "M12 23.5 L10.5 21 L13.5 21 Z", className: message.validation.confidence > 0.7
|
|
523
|
+
? 'fill-green-500'
|
|
524
|
+
: message.validation.confidence > 0.5
|
|
525
|
+
? 'fill-amber-500'
|
|
526
|
+
: 'fill-red-500' }), _jsx("path", { d: "M3.5 19.5 L5 17 L6 19 Z", className: message.validation.confidence > 0.7
|
|
527
|
+
? 'fill-green-500'
|
|
528
|
+
: message.validation.confidence > 0.5
|
|
529
|
+
? 'fill-amber-500'
|
|
530
|
+
: 'fill-red-500' }), _jsx("path", { d: "M0.5 12 L3 10.5 L3 13.5 Z", className: message.validation.confidence > 0.7
|
|
531
|
+
? 'fill-green-500'
|
|
532
|
+
: message.validation.confidence > 0.5
|
|
533
|
+
? 'fill-amber-500'
|
|
534
|
+
: 'fill-red-500' }), _jsx("path", { d: "M3.5 4.5 L6 5 L5 7 Z", className: message.validation.confidence > 0.7
|
|
535
|
+
? 'fill-green-500'
|
|
536
|
+
: message.validation.confidence > 0.5
|
|
537
|
+
? 'fill-amber-500'
|
|
538
|
+
: 'fill-red-500' }), _jsx("path", { d: "M8.5 12L10.5 14L15.5 9", stroke: "white", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" })] }) })), _jsx("button", { onClick: () => handleCopyMessage(message.id), className: "p-1 rounded transition-all duration-200 hover:scale-110 cursor-pointer text-gray-400 hover:text-gray-600", title: "Copy response", children: copiedMessageId === message.id ? (_jsx(Check, { className: "w-4 h-4 text-green-600" })) : (_jsx(Copy, { className: "w-4 h-4" })) }), _jsx("button", { onClick: () => !isDisabled && handleFeedback(message.id, 'like'), disabled: isDisabled, className: `p-1 rounded transition-all duration-200 ${isDisabled
|
|
502
539
|
? 'opacity-40 cursor-not-allowed'
|
|
503
540
|
: 'hover:scale-110 cursor-pointer'} ${messageFeedback[message.id] === 'like'
|
|
504
541
|
? 'text-green-600'
|
package/lib/types/index.d.ts
CHANGED
|
@@ -24,6 +24,26 @@ export interface ChatMessage {
|
|
|
24
24
|
type?: 'user' | 'assistant' | 'agent' | 'system';
|
|
25
25
|
timestamp: Date;
|
|
26
26
|
sources?: ChatSource[];
|
|
27
|
+
validation?: {
|
|
28
|
+
confidence: number;
|
|
29
|
+
valid: boolean;
|
|
30
|
+
status: string;
|
|
31
|
+
accuracy?: {
|
|
32
|
+
verified: boolean;
|
|
33
|
+
verification_rate: number;
|
|
34
|
+
reason?: string;
|
|
35
|
+
};
|
|
36
|
+
hallucination?: {
|
|
37
|
+
detected: boolean;
|
|
38
|
+
risk: number;
|
|
39
|
+
reason?: string;
|
|
40
|
+
};
|
|
41
|
+
context?: {
|
|
42
|
+
source_relevance: number;
|
|
43
|
+
source_usage_rate: number;
|
|
44
|
+
valid: boolean;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
27
47
|
_realUuid?: string;
|
|
28
48
|
}
|
|
29
49
|
export interface ChatSource {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vezlo/assistant-chat",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "React component library for AI-powered chat widgets with RAG knowledge base integration, realtime updates, and human agent support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|