@retrivora-ai/rag-engine 2.2.4 → 2.2.6
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/dist/handlers/index.d.mts +1 -1
- package/dist/handlers/index.d.ts +1 -1
- package/dist/handlers/index.js +147 -843
- package/dist/handlers/index.mjs +147 -843
- package/dist/{index-C6ehmP0b.d.ts → index-B5TTZWkx.d.ts} +6 -6
- package/dist/{index-DFc_Ll9z.d.mts → index-DvbtNz7m.d.mts} +6 -6
- package/dist/index.css +119 -0
- package/dist/index.js +277 -173
- package/dist/index.mjs +279 -174
- package/dist/server.d.mts +3 -4
- package/dist/server.d.ts +3 -4
- package/dist/server.js +147 -843
- package/dist/server.mjs +147 -843
- package/package.json +3 -1
- package/src/components/ChatWidget.tsx +75 -6
- package/src/components/ChatWindow.tsx +91 -13
- package/src/config/UniversalProfiles.ts +1 -2
- package/src/config/serverConfig.ts +5 -3
- package/src/core/ConfigFetcher.ts +1 -1
- package/src/core/Pipeline.ts +24 -27
- package/src/core/VectorPlugin.ts +2 -2
- package/src/handlers/index.ts +11 -14
- package/src/hooks/useRagChat.ts +9 -1
- package/src/index.css +119 -0
- package/src/llm/providers/UniversalLLMAdapter.ts +53 -104
- package/src/utils/SchemaMapper.ts +107 -62
- package/src/utils/UITransformer.ts +22 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retrivora-ai/rag-engine",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.6",
|
|
4
4
|
"description": "Retrivora AI is a plug-and-play AI engine for RAG chat experiences — generic vector DB + LLM provider, embeddable or standalone.",
|
|
5
5
|
"author": "Abhinav Alkuchi",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
"import": "./dist/index.mjs"
|
|
38
38
|
},
|
|
39
39
|
"./style.css": "./dist/index.css",
|
|
40
|
+
"./index.css": "./dist/index.css",
|
|
41
|
+
"./styles.css": "./dist/index.css",
|
|
40
42
|
"./handlers": {
|
|
41
43
|
"types": "./dist/handlers/index.d.ts",
|
|
42
44
|
"require": "./dist/handlers/index.js",
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
1
|
import React, { useState } from 'react';
|
|
4
|
-
import { MessageSquare, X } from 'lucide-react';
|
|
2
|
+
import { MessageSquare, X, AlertTriangle } from 'lucide-react';
|
|
5
3
|
import { ChatWindow } from './ChatWindow';
|
|
6
4
|
import { useConfig } from './ConfigProvider';
|
|
7
5
|
import { ChatWidgetProps } from '../types';
|
|
6
|
+
import { SDK_VERSION } from '../version';
|
|
8
7
|
|
|
9
8
|
const DEFAULT_DIMENSIONS = { width: 380, height: 600 };
|
|
10
9
|
|
|
@@ -54,6 +53,8 @@ export function ChatWidget({ position = 'bottom-right', onAddToCart, apiUrl, ret
|
|
|
54
53
|
const [isResizing, setIsResizing] = useState(false);
|
|
55
54
|
const [isMaximized, setIsMaximized] = useState(false);
|
|
56
55
|
const [prevDimensions, setPrevDimensions] = useState(DEFAULT_DIMENSIONS);
|
|
56
|
+
const [widgetError, setWidgetError] = useState<string | null>(null);
|
|
57
|
+
const [isValidating, setIsValidating] = useState(false);
|
|
57
58
|
|
|
58
59
|
if (ui.showWidget === false) return null;
|
|
59
60
|
|
|
@@ -67,9 +68,50 @@ export function ChatWidget({ position = 'bottom-right', onAddToCart, apiUrl, ret
|
|
|
67
68
|
? 'bottom-20 left-6'
|
|
68
69
|
: 'bottom-20 right-6';
|
|
69
70
|
|
|
70
|
-
const handleOpen = () => {
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
const handleOpen = async () => {
|
|
72
|
+
setIsValidating(true);
|
|
73
|
+
try {
|
|
74
|
+
const base = retrivoraApiBase || '/api/retrivora';
|
|
75
|
+
const configUrl = `${base.replace(/\/$/, '')}/config?sdkVersion=${SDK_VERSION}`;
|
|
76
|
+
const res = await fetch(configUrl, {
|
|
77
|
+
method: 'GET',
|
|
78
|
+
cache: 'no-store',
|
|
79
|
+
headers: {
|
|
80
|
+
'Content-Type': 'application/json',
|
|
81
|
+
'x-sdk-version': SDK_VERSION,
|
|
82
|
+
...(headers || {})
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (!res.ok) {
|
|
87
|
+
const data = await res.json().catch(() => ({}));
|
|
88
|
+
if (res.status === 426 || data.code === 'SDK_VERSION_OUTDATED') {
|
|
89
|
+
const msg = data.error || 'Your Retrivora SDK package version is outdated. Please update your package to the latest version to continue.';
|
|
90
|
+
setWidgetError(msg);
|
|
91
|
+
setIsOpen(false); // DO NOT OPEN CHAT WIDGET
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (
|
|
95
|
+
res.status === 403 ||
|
|
96
|
+
res.status === 401 ||
|
|
97
|
+
(typeof data.error === 'string' && data.error.toLowerCase().includes('license'))
|
|
98
|
+
) {
|
|
99
|
+
const msg = (typeof data.error === 'string' ? data.error : data.error?.message) || 'Your Retrivora license is no longer valid. Please contact your administrator or obtain a valid license key.';
|
|
100
|
+
setWidgetError(msg);
|
|
101
|
+
setIsOpen(false); // DO NOT OPEN CHAT WIDGET
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
setWidgetError(null);
|
|
107
|
+
setIsOpen(true);
|
|
108
|
+
setHasUnread(false);
|
|
109
|
+
} catch {
|
|
110
|
+
// Fallback
|
|
111
|
+
setIsOpen(true);
|
|
112
|
+
} finally {
|
|
113
|
+
setIsValidating(false);
|
|
114
|
+
}
|
|
73
115
|
};
|
|
74
116
|
|
|
75
117
|
const handleResizeStart = (e: React.MouseEvent) => {
|
|
@@ -157,6 +199,33 @@ export function ChatWidget({ position = 'bottom-right', onAddToCart, apiUrl, ret
|
|
|
157
199
|
/>
|
|
158
200
|
</div>
|
|
159
201
|
|
|
202
|
+
{/* ── Widget Error Toast/Pop-over (when opening is blocked) ── */}
|
|
203
|
+
{widgetError && !isOpen && (
|
|
204
|
+
<div
|
|
205
|
+
className={`fixed z-[9999] max-w-sm p-4 rounded-2xl shadow-2xl border border-rose-200 dark:border-rose-900/60 bg-white/95 dark:bg-[#0f0f1a]/95 backdrop-blur-xl transition-all duration-300 animate-in fade-in slide-in-from-bottom-3 ${
|
|
206
|
+
position === 'bottom-left' ? 'bottom-24 left-6' : 'bottom-24 right-6'
|
|
207
|
+
}`}
|
|
208
|
+
>
|
|
209
|
+
<div className="flex items-start gap-3">
|
|
210
|
+
<div className="w-8 h-8 rounded-xl bg-rose-100 dark:bg-rose-900/40 text-rose-600 dark:text-rose-400 flex items-center justify-center shrink-0 mt-0.5">
|
|
211
|
+
<AlertTriangle className="w-4 h-4" />
|
|
212
|
+
</div>
|
|
213
|
+
<div className="flex-1 space-y-1">
|
|
214
|
+
<h5 className="text-xs font-bold text-slate-900 dark:text-white">Access Blocked</h5>
|
|
215
|
+
<p className="text-[11px] text-slate-600 dark:text-slate-300 leading-relaxed font-medium">
|
|
216
|
+
{widgetError}
|
|
217
|
+
</p>
|
|
218
|
+
</div>
|
|
219
|
+
<button
|
|
220
|
+
onClick={() => setWidgetError(null)}
|
|
221
|
+
className="text-slate-400 hover:text-slate-600 dark:hover:text-white transition-colors p-1"
|
|
222
|
+
>
|
|
223
|
+
<X className="w-3.5 h-3.5" />
|
|
224
|
+
</button>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
)}
|
|
228
|
+
|
|
160
229
|
{/* ── Floating Action Button ── */}
|
|
161
230
|
<button
|
|
162
231
|
onClick={isOpen ? () => setIsOpen(false) : handleOpen}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
X,
|
|
8
8
|
Sparkles,
|
|
9
9
|
ArrowUp,
|
|
10
|
+
ArrowUpCircle,
|
|
10
11
|
TriangleAlert,
|
|
11
12
|
RotateCcw,
|
|
12
13
|
Maximize2,
|
|
@@ -21,6 +22,7 @@ import { useConfig } from './ConfigProvider';
|
|
|
21
22
|
import { useRagChat } from '../hooks/useRagChat';
|
|
22
23
|
import { BORDER_RADIUS_MAP, CHAT_SUGGESTIONS } from '../config/uiConstants';
|
|
23
24
|
import { ChatWindowProps } from '../types';
|
|
25
|
+
import { SDK_VERSION } from '../version';
|
|
24
26
|
|
|
25
27
|
interface SpeechRecognitionEvent {
|
|
26
28
|
resultIndex: number;
|
|
@@ -86,8 +88,58 @@ export function ChatWindow({
|
|
|
86
88
|
|
|
87
89
|
const [isListening, setIsListening] = useState(false);
|
|
88
90
|
const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);
|
|
91
|
+
const [licenseError, setLicenseError] = useState<string | null>(null);
|
|
92
|
+
const [versionError, setVersionError] = useState<string | null>(null);
|
|
89
93
|
const recognitionRef = useRef<ISpeechRecognition | null>(null);
|
|
90
94
|
|
|
95
|
+
// Validate server license and SDK version on ChatWindow session initialization
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
let isMounted = true;
|
|
98
|
+
async function validateSessionLicense() {
|
|
99
|
+
try {
|
|
100
|
+
const base = retrivoraApiBase || '/api/retrivora';
|
|
101
|
+
const configUrl = `${base.replace(/\/$/, '')}/config?sdkVersion=${SDK_VERSION}`;
|
|
102
|
+
const res = await fetch(configUrl, {
|
|
103
|
+
method: 'GET',
|
|
104
|
+
cache: 'no-store',
|
|
105
|
+
headers: {
|
|
106
|
+
'Content-Type': 'application/json',
|
|
107
|
+
'x-sdk-version': SDK_VERSION,
|
|
108
|
+
...(headers || {})
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (!res.ok) {
|
|
113
|
+
const data = await res.json().catch(() => ({}));
|
|
114
|
+
if (res.status === 426 || data.code === 'SDK_VERSION_OUTDATED') {
|
|
115
|
+
if (isMounted) {
|
|
116
|
+
setVersionError(data.error || 'Your Retrivora SDK package is outdated. Please update your package to the latest version to continue.');
|
|
117
|
+
}
|
|
118
|
+
} else if (
|
|
119
|
+
res.status === 403 ||
|
|
120
|
+
res.status === 401 ||
|
|
121
|
+
(typeof data.error === 'string' && data.error.toLowerCase().includes('license'))
|
|
122
|
+
) {
|
|
123
|
+
if (isMounted) {
|
|
124
|
+
const errMsg = typeof data.error === 'string' ? data.error : data.error?.message || 'Your Retrivora license is no longer valid. Please contact your administrator or obtain a valid license key.';
|
|
125
|
+
setLicenseError(errMsg);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
if (isMounted) {
|
|
130
|
+
setLicenseError(null);
|
|
131
|
+
setVersionError(null);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
} catch {
|
|
135
|
+
// Non-blocking fallback
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
validateSessionLicense();
|
|
140
|
+
return () => { isMounted = false; };
|
|
141
|
+
}, [retrivoraApiBase, headers]);
|
|
142
|
+
|
|
91
143
|
// Initialize SpeechRecognition
|
|
92
144
|
useEffect(() => {
|
|
93
145
|
if (typeof window !== 'undefined') {
|
|
@@ -345,7 +397,36 @@ export function ChatWindow({
|
|
|
345
397
|
</div>
|
|
346
398
|
|
|
347
399
|
<div className="flex-1 overflow-y-auto px-4 py-4 space-y-5 scrollbar-thin scrollbar-thumb-slate-200 dark:scrollbar-thumb-white/10 scrollbar-track-transparent min-h-0 bg-slate-50 dark:bg-transparent">
|
|
348
|
-
{
|
|
400
|
+
{versionError ? (
|
|
401
|
+
<div className="h-full flex flex-col items-center justify-center text-center p-6 space-y-4 bg-amber-50/70 dark:bg-amber-950/20 rounded-2xl border border-amber-200/80 dark:border-amber-800/40 my-auto">
|
|
402
|
+
<div className="w-14 h-14 rounded-2xl bg-amber-100 dark:bg-amber-900/40 text-amber-600 dark:text-amber-400 flex items-center justify-center shadow-sm shrink-0">
|
|
403
|
+
<ArrowUpCircle className="w-7 h-7 animate-bounce" />
|
|
404
|
+
</div>
|
|
405
|
+
<div className="space-y-2 max-w-xs">
|
|
406
|
+
<h4 className="text-base font-extrabold text-slate-900 dark:text-white tracking-tight">Package Update Required</h4>
|
|
407
|
+
<p className="text-xs text-slate-600 dark:text-slate-300 leading-relaxed font-medium">
|
|
408
|
+
{versionError}
|
|
409
|
+
</p>
|
|
410
|
+
<div className="pt-2">
|
|
411
|
+
<code className="block bg-slate-900 text-amber-300 text-[10px] font-mono py-2 px-3 rounded-xl select-all border border-slate-800">
|
|
412
|
+
npm i @retrivora-ai/rag-engine@latest
|
|
413
|
+
</code>
|
|
414
|
+
</div>
|
|
415
|
+
</div>
|
|
416
|
+
</div>
|
|
417
|
+
) : licenseError ? (
|
|
418
|
+
<div className="h-full flex flex-col items-center justify-center text-center p-6 space-y-4 bg-rose-50/50 dark:bg-rose-950/20 rounded-2xl border border-rose-200/60 dark:border-rose-800/40 my-auto">
|
|
419
|
+
<div className="w-14 h-14 rounded-2xl bg-rose-100 dark:bg-rose-900/40 text-rose-600 dark:text-rose-400 flex items-center justify-center shadow-sm shrink-0">
|
|
420
|
+
<TriangleAlert className="w-7 h-7" />
|
|
421
|
+
</div>
|
|
422
|
+
<div className="space-y-2 max-w-xs">
|
|
423
|
+
<h4 className="text-base font-extrabold text-slate-900 dark:text-white tracking-tight">License Invalid</h4>
|
|
424
|
+
<p className="text-xs text-slate-600 dark:text-slate-300 leading-relaxed font-medium">
|
|
425
|
+
{licenseError}
|
|
426
|
+
</p>
|
|
427
|
+
</div>
|
|
428
|
+
</div>
|
|
429
|
+
) : !mounted || isEmpty ? (
|
|
349
430
|
/* Welcome state */
|
|
350
431
|
<div className="h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-4">
|
|
351
432
|
<div
|
|
@@ -408,7 +489,7 @@ export function ChatWindow({
|
|
|
408
489
|
)}
|
|
409
490
|
|
|
410
491
|
{/* Error */}
|
|
411
|
-
{error && (
|
|
492
|
+
{error && !licenseError && (
|
|
412
493
|
<div className="flex items-center gap-2 text-rose-500 dark:text-rose-400 text-sm bg-rose-50 dark:bg-rose-400/10 border border-rose-200 dark:border-rose-400/20 rounded-xl px-4 py-3">
|
|
413
494
|
<TriangleAlert className="w-4 h-4 flex-shrink-0" />
|
|
414
495
|
<span>{error}</span>
|
|
@@ -479,7 +560,7 @@ export function ChatWindow({
|
|
|
479
560
|
onKeyDown={handleKeyDown}
|
|
480
561
|
placeholder={ui.placeholder}
|
|
481
562
|
rows={1}
|
|
482
|
-
disabled={isLoading}
|
|
563
|
+
disabled={isLoading || !!licenseError || !!versionError}
|
|
483
564
|
className="flex-1 bg-transparent text-slate-900 dark:text-white/90 placeholder-slate-400 dark:placeholder-white/30 text-sm resize-none outline-none py-1.5 px-2 max-h-32 leading-relaxed disabled:opacity-50"
|
|
484
565
|
style={{ scrollbarWidth: 'none' }}
|
|
485
566
|
/>
|
|
@@ -488,7 +569,7 @@ export function ChatWindow({
|
|
|
488
569
|
<button
|
|
489
570
|
type="button"
|
|
490
571
|
onClick={toggleListening}
|
|
491
|
-
disabled={isLoading}
|
|
572
|
+
disabled={isLoading || !!licenseError || !!versionError}
|
|
492
573
|
className={`flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 disabled:active:scale-100 ${isListening
|
|
493
574
|
? 'bg-rose-500 text-white animate-pulse shadow-md shadow-rose-500/20'
|
|
494
575
|
: 'text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10'
|
|
@@ -503,7 +584,8 @@ export function ChatWindow({
|
|
|
503
584
|
<button
|
|
504
585
|
type="button"
|
|
505
586
|
onClick={() => setIsUploadModalOpen(true)}
|
|
506
|
-
|
|
587
|
+
disabled={isLoading || !!licenseError || !!versionError}
|
|
588
|
+
className="flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
507
589
|
title="Upload Document"
|
|
508
590
|
>
|
|
509
591
|
<Paperclip className="w-4 h-4" />
|
|
@@ -521,14 +603,10 @@ export function ChatWindow({
|
|
|
521
603
|
) : (
|
|
522
604
|
<button
|
|
523
605
|
onClick={sendMessage}
|
|
524
|
-
disabled={!input.trim()}
|
|
525
|
-
className=
|
|
526
|
-
style={{
|
|
527
|
-
|
|
528
|
-
input.trim()
|
|
529
|
-
? `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})`
|
|
530
|
-
: 'rgba(148, 163, 184, 0.2)', // slate-400/20 for light mode disabled
|
|
531
|
-
}}
|
|
606
|
+
disabled={!input.trim() || !!licenseError || !!versionError}
|
|
607
|
+
className={`flex-shrink-0 w-9 h-9 flex items-center justify-center transition-all shadow-md active:scale-95 cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed disabled:active:scale-100 ${ui.borderRadius === 'full' ? 'rounded-full' : 'rounded-xl'}`}
|
|
608
|
+
style={{ background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }}
|
|
609
|
+
title="Send message"
|
|
532
610
|
>
|
|
533
611
|
<ArrowUp className="w-4 h-4 text-white" />
|
|
534
612
|
</button>
|
|
@@ -14,8 +14,7 @@ const OPENAI_BASE = {
|
|
|
14
14
|
export const LLM_PROFILES = {
|
|
15
15
|
'openai-compatible': OPENAI_BASE,
|
|
16
16
|
'litellm': {
|
|
17
|
-
...OPENAI_BASE,
|
|
18
|
-
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
|
|
17
|
+
...OPENAI_BASE,
|
|
19
18
|
},
|
|
20
19
|
'anthropic-claude': {
|
|
21
20
|
chatPath: '/v1/messages',
|
|
@@ -187,8 +187,10 @@ export function getEnvConfig(env: Record<string, string | undefined> = process.e
|
|
|
187
187
|
|
|
188
188
|
// Default gateway: retrivora.com/api/v1 acts as a secure proxy that validates the license key
|
|
189
189
|
// and forwards to llm.retrivora.com with LITELLM_MASTER_KEY (which end-users never need to know).
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
const defaultGatewayUrl =
|
|
191
|
+
readString(env, 'LITELLM_BASE_URL') ??
|
|
192
|
+
readString(env, 'LLM_BASE_URL') ??
|
|
193
|
+
'https://www.retrivora.com/api/v1';
|
|
192
194
|
|
|
193
195
|
const defaultLlmProvider = isFreeTier ? 'universal_rest' : 'universal_rest';
|
|
194
196
|
const llmProvider = (readEnum(env, 'LLM_PROVIDER', defaultLlmProvider, LLM_PROVIDERS) ?? base?.llm?.provider ?? defaultLlmProvider) as LLMProvider;
|
|
@@ -277,7 +279,7 @@ export function getEnvConfig(env: Record<string, string | undefined> = process.e
|
|
|
277
279
|
},
|
|
278
280
|
telemetry: {
|
|
279
281
|
enabled: telemetryEnabled,
|
|
280
|
-
url: readString(env, 'TELEMETRY_URL') ?? readString(env, 'NEXT_PUBLIC_TELEMETRY_URL') ?? base?.telemetry?.url ??
|
|
282
|
+
url: readString(env, 'TELEMETRY_URL') ?? readString(env, 'NEXT_PUBLIC_TELEMETRY_URL') ?? base?.telemetry?.url ?? 'https://www.retrivora.com/api/telemetry',
|
|
281
283
|
},
|
|
282
284
|
// Optional graph DB — driven by GRAPH_DB_PROVIDER env var
|
|
283
285
|
...(readString(env, 'GRAPH_DB_PROVIDER') ? {
|
|
@@ -57,8 +57,8 @@ export class ConfigFetcher {
|
|
|
57
57
|
process.env.NEXT_PUBLIC_RETRIVORA_CONTROL_PLANE_URL,
|
|
58
58
|
'https://www.retrivora.com',
|
|
59
59
|
'https://retrivora.com',
|
|
60
|
-
'http://localhost:3001',
|
|
61
60
|
'http://localhost:3000',
|
|
61
|
+
'http://localhost:3001',
|
|
62
62
|
].filter(Boolean) as string[];
|
|
63
63
|
|
|
64
64
|
for (const baseUrl of controlPlaneUrls) {
|
package/src/core/Pipeline.ts
CHANGED
|
@@ -586,16 +586,16 @@ You are a helpful assistant. Use the provided context to answer questions accura
|
|
|
586
586
|
? await this.vectorDB.query(queryVector, retrievalLimit, ns, filter)
|
|
587
587
|
: []).filter((s): s is VectorMatch => Boolean(s && typeof s === 'object'));
|
|
588
588
|
|
|
589
|
-
console.log('[Pipeline] Raw vectorDB.query response:', {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
});
|
|
589
|
+
// console.log('[Pipeline] Raw vectorDB.query response:', {
|
|
590
|
+
// rawCount: rawSources.length,
|
|
591
|
+
// sample: rawSources.slice(0, 2).map((s) => ({
|
|
592
|
+
// id: s?.id,
|
|
593
|
+
// score: s?.score,
|
|
594
|
+
// contentType: typeof s?.content,
|
|
595
|
+
// contentSnippet: String(s?.content ?? '').substring(0, 150),
|
|
596
|
+
// metadataKeys: Object.keys(s?.metadata || {}),
|
|
597
|
+
// })),
|
|
598
|
+
// });
|
|
599
599
|
|
|
600
600
|
const retrieveEnd = performance.now();
|
|
601
601
|
const embedMs = retrieveEnd - embedStart;
|
|
@@ -628,18 +628,18 @@ You are a helpful assistant. Use the provided context to answer questions accura
|
|
|
628
628
|
.filter((s): s is VectorMatch => Boolean(s && typeof s === 'object'))
|
|
629
629
|
.sort((a, b) => (b?.score ?? 0) - (a?.score ?? 0));
|
|
630
630
|
|
|
631
|
-
console.log('[Pipeline] Final sources for prompt & UI:', {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
});
|
|
631
|
+
// console.log('[Pipeline] Final sources for prompt & UI:', {
|
|
632
|
+
// count: sources.length,
|
|
633
|
+
// totalRawCount: rawSources.length,
|
|
634
|
+
// sources: sources.slice(0, 10).map((s, idx) => ({
|
|
635
|
+
// rank: idx + 1,
|
|
636
|
+
// id: s?.id,
|
|
637
|
+
// score: s?.score,
|
|
638
|
+
// contentType: typeof s?.content,
|
|
639
|
+
// contentSnippet: String(s?.content ?? '').substring(0, 150),
|
|
640
|
+
// metadata: s?.metadata,
|
|
641
|
+
// })),
|
|
642
|
+
// });
|
|
643
643
|
|
|
644
644
|
if (graphData && graphData.nodes.length > 0) {
|
|
645
645
|
const graphContext = graphData.nodes.map(n =>
|
|
@@ -912,14 +912,11 @@ You are a helpful assistant. Use the provided context to answer questions accura
|
|
|
912
912
|
// Asynchronously trigger telemetry logging without blocking response yield
|
|
913
913
|
const isTelemetryActive = this.config.telemetry?.enabled ?? Boolean(this.config.licenseKey);
|
|
914
914
|
if (isTelemetryActive) {
|
|
915
|
-
const defaultUrl =
|
|
916
|
-
? 'http://localhost:3001/api/telemetry'
|
|
917
|
-
: 'https://retrivora.com/api/telemetry';
|
|
918
|
-
|
|
915
|
+
const defaultUrl = 'https://www.retrivora.com/api/telemetry';
|
|
919
916
|
const telemetryUrl = this.config.telemetry?.url || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
|
|
920
917
|
const absoluteUrl = telemetryUrl.startsWith('http')
|
|
921
918
|
? telemetryUrl
|
|
922
|
-
:
|
|
919
|
+
: 'https://www.retrivora.com' + (telemetryUrl.startsWith('/') ? telemetryUrl : '/' + telemetryUrl);
|
|
923
920
|
|
|
924
921
|
// Start background process for telemetry, awaiting hallucination scoring if it was backgrounded
|
|
925
922
|
(async () => {
|
package/src/core/VectorPlugin.ts
CHANGED
package/src/handlers/index.ts
CHANGED
|
@@ -166,13 +166,10 @@ function reportTelemetry(
|
|
|
166
166
|
const licenseKey = config.licenseKey || process.env.RAG_LICENSE_KEY || process.env.RETRIVORA_LICENSE_KEY || process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY;
|
|
167
167
|
const telemetryConfig = config.telemetry;
|
|
168
168
|
|
|
169
|
-
const
|
|
170
|
-
const defaultUrl =
|
|
171
|
-
? 'http://localhost:3001/api/telemetry'
|
|
172
|
-
: 'https://www.retrivora.com/api/telemetry';
|
|
169
|
+
const host = req.headers.get('host') || 'localhost';
|
|
170
|
+
const defaultUrl = 'https://www.retrivora.com/api/telemetry';
|
|
173
171
|
|
|
174
172
|
const telemetryUrl = telemetryConfig?.url || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
|
|
175
|
-
const host = req.headers.get('host') || 'localhost';
|
|
176
173
|
const userAgent = req.headers.get('user-agent') || `Retrivora-SDK/${SDK_VERSION}`;
|
|
177
174
|
|
|
178
175
|
let absoluteUrl = telemetryUrl;
|
|
@@ -285,7 +282,7 @@ export function createChatHandler(
|
|
|
285
282
|
const storage = new DatabaseStorage(plugin.getConfig());
|
|
286
283
|
const onAuthorize = options?.onAuthorize;
|
|
287
284
|
|
|
288
|
-
return async function POST(req:
|
|
285
|
+
return async function POST(req: any, context?: any) {
|
|
289
286
|
const authResult = await checkAuth(req, onAuthorize);
|
|
290
287
|
if (authResult) return authResult as any;
|
|
291
288
|
|
|
@@ -361,7 +358,7 @@ export function createStreamHandler(
|
|
|
361
358
|
const storage = new DatabaseStorage(plugin.getConfig());
|
|
362
359
|
const onAuthorize = options?.onAuthorize;
|
|
363
360
|
|
|
364
|
-
return async function POST(req:
|
|
361
|
+
return async function POST(req: any, context?: any) {
|
|
365
362
|
const authResult = await checkAuth(req, onAuthorize);
|
|
366
363
|
if (authResult) return authResult as any;
|
|
367
364
|
|
|
@@ -532,7 +529,7 @@ export function createIngestHandler(
|
|
|
532
529
|
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
533
530
|
const onAuthorize = options?.onAuthorize;
|
|
534
531
|
|
|
535
|
-
return async function POST(req:
|
|
532
|
+
return async function POST(req: any, context?: any) {
|
|
536
533
|
const authResult = await checkAuth(req, onAuthorize);
|
|
537
534
|
if (authResult) return authResult as any;
|
|
538
535
|
|
|
@@ -599,7 +596,7 @@ export function createUploadHandler(
|
|
|
599
596
|
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
600
597
|
const onAuthorize = options?.onAuthorize;
|
|
601
598
|
|
|
602
|
-
return async function POST(req:
|
|
599
|
+
return async function POST(req: any, context?: any) {
|
|
603
600
|
const authResult = await checkAuth(req, onAuthorize);
|
|
604
601
|
if (authResult) return authResult as any;
|
|
605
602
|
|
|
@@ -926,7 +923,7 @@ export function createRagHandler(
|
|
|
926
923
|
const feedbackHandler = createFeedbackHandler(plugin, { onAuthorize });
|
|
927
924
|
const sessionsHandler = createSessionsHandler(plugin, { onAuthorize });
|
|
928
925
|
|
|
929
|
-
async function routePostRequest(req:
|
|
926
|
+
async function routePostRequest(req: any, segment: string) {
|
|
930
927
|
switch (segment) {
|
|
931
928
|
case 'chat':
|
|
932
929
|
return streamHandler(req);
|
|
@@ -948,7 +945,7 @@ export function createRagHandler(
|
|
|
948
945
|
}
|
|
949
946
|
}
|
|
950
947
|
|
|
951
|
-
async function routeGetRequest(req:
|
|
948
|
+
async function routeGetRequest(req: any, segment: string) {
|
|
952
949
|
switch (segment) {
|
|
953
950
|
case 'health':
|
|
954
951
|
return healthHandler(req);
|
|
@@ -965,7 +962,7 @@ export function createRagHandler(
|
|
|
965
962
|
}
|
|
966
963
|
}
|
|
967
964
|
|
|
968
|
-
async function getSegment(req:
|
|
965
|
+
async function getSegment(req: any, context: any): Promise<string> {
|
|
969
966
|
// 1. If content-type is multipart/form-data, it MUST be an upload request!
|
|
970
967
|
const contentType = req.headers.get('content-type') || '';
|
|
971
968
|
if (contentType.includes('multipart/form-data')) {
|
|
@@ -995,7 +992,7 @@ export function createRagHandler(
|
|
|
995
992
|
}
|
|
996
993
|
|
|
997
994
|
return {
|
|
998
|
-
GET: async (req:
|
|
995
|
+
GET: async (req: any, context?: any) => {
|
|
999
996
|
try {
|
|
1000
997
|
const segment = await getSegment(req, context);
|
|
1001
998
|
return await routeGetRequest(req, segment);
|
|
@@ -1004,7 +1001,7 @@ export function createRagHandler(
|
|
|
1004
1001
|
return NextResponse.json({ error: msg }, { status: 500 });
|
|
1005
1002
|
}
|
|
1006
1003
|
},
|
|
1007
|
-
POST: async (req:
|
|
1004
|
+
POST: async (req: any, context?: any) => {
|
|
1008
1005
|
try {
|
|
1009
1006
|
const segment = await getSegment(req, context);
|
|
1010
1007
|
return await routePostRequest(req, segment);
|
package/src/hooks/useRagChat.ts
CHANGED
|
@@ -154,7 +154,15 @@ export function useRagChat(
|
|
|
154
154
|
|
|
155
155
|
if (!response.ok) {
|
|
156
156
|
const errorData = await response.json().catch(() => ({}));
|
|
157
|
-
|
|
157
|
+
if (
|
|
158
|
+
response.status === 403 ||
|
|
159
|
+
response.status === 401 ||
|
|
160
|
+
(typeof errorData.error === 'string' && errorData.error.toLowerCase().includes('license')) ||
|
|
161
|
+
errorData.error?.type === 'license_revoked'
|
|
162
|
+
) {
|
|
163
|
+
throw new Error('Your Retrivora license is no longer valid. Please contact your administrator or obtain a valid license key.');
|
|
164
|
+
}
|
|
165
|
+
throw new Error(errorData.error?.message || errorData.error || `Server returned ${response.status}`);
|
|
158
166
|
}
|
|
159
167
|
|
|
160
168
|
if (!response.body) {
|