@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/src/index.css
CHANGED
|
@@ -96,6 +96,9 @@
|
|
|
96
96
|
--color-rose-400: oklch(71.2% 0.194 13.428);
|
|
97
97
|
--color-rose-500: oklch(64.5% 0.246 16.439);
|
|
98
98
|
--color-rose-600: oklch(58.6% 0.253 17.585);
|
|
99
|
+
--color-rose-800: oklch(45.5% 0.188 13.697);
|
|
100
|
+
--color-rose-900: oklch(41% 0.159 10.272);
|
|
101
|
+
--color-rose-950: oklch(27.1% 0.105 12.094);
|
|
99
102
|
--color-slate-50: oklch(98.4% 0.003 247.858);
|
|
100
103
|
--color-slate-100: oklch(96.8% 0.007 247.896);
|
|
101
104
|
--color-slate-200: oklch(92.9% 0.013 255.508);
|
|
@@ -370,6 +373,9 @@
|
|
|
370
373
|
.bottom-20 {
|
|
371
374
|
bottom: calc(var(--spacing) * 20);
|
|
372
375
|
}
|
|
376
|
+
.bottom-24 {
|
|
377
|
+
bottom: calc(var(--spacing) * 24);
|
|
378
|
+
}
|
|
373
379
|
.-left-4 {
|
|
374
380
|
left: calc(var(--spacing) * -4);
|
|
375
381
|
}
|
|
@@ -451,6 +457,9 @@
|
|
|
451
457
|
.my-6 {
|
|
452
458
|
margin-block: calc(var(--spacing) * 6);
|
|
453
459
|
}
|
|
460
|
+
.my-auto {
|
|
461
|
+
margin-block: auto;
|
|
462
|
+
}
|
|
454
463
|
.mt-0\.5 {
|
|
455
464
|
margin-top: calc(var(--spacing) * 0.5);
|
|
456
465
|
}
|
|
@@ -1121,6 +1130,12 @@
|
|
|
1121
1130
|
.border-amber-200 {
|
|
1122
1131
|
border-color: var(--color-amber-200);
|
|
1123
1132
|
}
|
|
1133
|
+
.border-amber-200\/80 {
|
|
1134
|
+
border-color: color-mix(in srgb, oklch(92.4% 0.12 95.746) 80%, transparent);
|
|
1135
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1136
|
+
border-color: color-mix(in oklab, var(--color-amber-200) 80%, transparent);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1124
1139
|
.border-emerald-100 {
|
|
1125
1140
|
border-color: var(--color-emerald-100);
|
|
1126
1141
|
}
|
|
@@ -1157,6 +1172,12 @@
|
|
|
1157
1172
|
.border-rose-200 {
|
|
1158
1173
|
border-color: var(--color-rose-200);
|
|
1159
1174
|
}
|
|
1175
|
+
.border-rose-200\/60 {
|
|
1176
|
+
border-color: color-mix(in srgb, oklch(89.2% 0.058 10.001) 60%, transparent);
|
|
1177
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1178
|
+
border-color: color-mix(in oklab, var(--color-rose-200) 60%, transparent);
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1160
1181
|
.border-slate-100 {
|
|
1161
1182
|
border-color: var(--color-slate-100);
|
|
1162
1183
|
}
|
|
@@ -1217,6 +1238,12 @@
|
|
|
1217
1238
|
.bg-amber-50 {
|
|
1218
1239
|
background-color: var(--color-amber-50);
|
|
1219
1240
|
}
|
|
1241
|
+
.bg-amber-50\/70 {
|
|
1242
|
+
background-color: color-mix(in srgb, oklch(98.7% 0.022 95.277) 70%, transparent);
|
|
1243
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1244
|
+
background-color: color-mix(in oklab, var(--color-amber-50) 70%, transparent);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1220
1247
|
.bg-amber-100 {
|
|
1221
1248
|
background-color: var(--color-amber-100);
|
|
1222
1249
|
}
|
|
@@ -1322,6 +1349,15 @@
|
|
|
1322
1349
|
.bg-rose-50 {
|
|
1323
1350
|
background-color: var(--color-rose-50);
|
|
1324
1351
|
}
|
|
1352
|
+
.bg-rose-50\/50 {
|
|
1353
|
+
background-color: color-mix(in srgb, oklch(96.9% 0.015 12.422) 50%, transparent);
|
|
1354
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1355
|
+
background-color: color-mix(in oklab, var(--color-rose-50) 50%, transparent);
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
.bg-rose-100 {
|
|
1359
|
+
background-color: var(--color-rose-100);
|
|
1360
|
+
}
|
|
1325
1361
|
.bg-rose-500 {
|
|
1326
1362
|
background-color: var(--color-rose-500);
|
|
1327
1363
|
}
|
|
@@ -1409,6 +1445,12 @@
|
|
|
1409
1445
|
background-color: color-mix(in oklab, var(--color-white) 90%, transparent);
|
|
1410
1446
|
}
|
|
1411
1447
|
}
|
|
1448
|
+
.bg-white\/95 {
|
|
1449
|
+
background-color: color-mix(in srgb, #fff 95%, transparent);
|
|
1450
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1451
|
+
background-color: color-mix(in oklab, var(--color-white) 95%, transparent);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1412
1454
|
.bg-gradient-to-br {
|
|
1413
1455
|
--tw-gradient-position: to bottom right in oklab;
|
|
1414
1456
|
background-image: linear-gradient(var(--tw-gradient-stops));
|
|
@@ -1619,6 +1661,9 @@
|
|
|
1619
1661
|
.whitespace-pre-wrap {
|
|
1620
1662
|
white-space: pre-wrap;
|
|
1621
1663
|
}
|
|
1664
|
+
.text-amber-300 {
|
|
1665
|
+
color: var(--color-amber-300);
|
|
1666
|
+
}
|
|
1622
1667
|
.text-amber-400 {
|
|
1623
1668
|
color: var(--color-amber-400);
|
|
1624
1669
|
}
|
|
@@ -1950,6 +1995,10 @@
|
|
|
1950
1995
|
--tw-outline-style: none;
|
|
1951
1996
|
outline-style: none;
|
|
1952
1997
|
}
|
|
1998
|
+
.select-all {
|
|
1999
|
+
-webkit-user-select: all;
|
|
2000
|
+
user-select: all;
|
|
2001
|
+
}
|
|
1953
2002
|
.select-none {
|
|
1954
2003
|
-webkit-user-select: none;
|
|
1955
2004
|
user-select: none;
|
|
@@ -2391,6 +2440,14 @@
|
|
|
2391
2440
|
}
|
|
2392
2441
|
}
|
|
2393
2442
|
}
|
|
2443
|
+
.dark\:border-amber-800\/40 {
|
|
2444
|
+
@media (prefers-color-scheme: dark) {
|
|
2445
|
+
border-color: color-mix(in srgb, oklch(47.3% 0.137 46.201) 40%, transparent);
|
|
2446
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2447
|
+
border-color: color-mix(in oklab, var(--color-amber-800) 40%, transparent);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2394
2451
|
.dark\:border-emerald-400\/20 {
|
|
2395
2452
|
@media (prefers-color-scheme: dark) {
|
|
2396
2453
|
border-color: color-mix(in srgb, oklch(76.5% 0.177 163.223) 20%, transparent);
|
|
@@ -2463,6 +2520,22 @@
|
|
|
2463
2520
|
}
|
|
2464
2521
|
}
|
|
2465
2522
|
}
|
|
2523
|
+
.dark\:border-rose-800\/40 {
|
|
2524
|
+
@media (prefers-color-scheme: dark) {
|
|
2525
|
+
border-color: color-mix(in srgb, oklch(45.5% 0.188 13.697) 40%, transparent);
|
|
2526
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2527
|
+
border-color: color-mix(in oklab, var(--color-rose-800) 40%, transparent);
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
.dark\:border-rose-900\/60 {
|
|
2532
|
+
@media (prefers-color-scheme: dark) {
|
|
2533
|
+
border-color: color-mix(in srgb, oklch(41% 0.159 10.272) 60%, transparent);
|
|
2534
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2535
|
+
border-color: color-mix(in oklab, var(--color-rose-900) 60%, transparent);
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2466
2539
|
.dark\:border-slate-700 {
|
|
2467
2540
|
@media (prefers-color-scheme: dark) {
|
|
2468
2541
|
border-color: var(--color-slate-700);
|
|
@@ -2515,6 +2588,11 @@
|
|
|
2515
2588
|
background-color: color-mix(in oklab, #0f0f1a 90%, transparent);
|
|
2516
2589
|
}
|
|
2517
2590
|
}
|
|
2591
|
+
.dark\:bg-\[\#0f0f1a\]\/95 {
|
|
2592
|
+
@media (prefers-color-scheme: dark) {
|
|
2593
|
+
background-color: color-mix(in oklab, #0f0f1a 95%, transparent);
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2518
2596
|
.dark\:bg-\[\#080811\] {
|
|
2519
2597
|
@media (prefers-color-scheme: dark) {
|
|
2520
2598
|
background-color: #080811;
|
|
@@ -2560,6 +2638,22 @@
|
|
|
2560
2638
|
}
|
|
2561
2639
|
}
|
|
2562
2640
|
}
|
|
2641
|
+
.dark\:bg-amber-900\/40 {
|
|
2642
|
+
@media (prefers-color-scheme: dark) {
|
|
2643
|
+
background-color: color-mix(in srgb, oklch(41.4% 0.112 45.904) 40%, transparent);
|
|
2644
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2645
|
+
background-color: color-mix(in oklab, var(--color-amber-900) 40%, transparent);
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
.dark\:bg-amber-950\/20 {
|
|
2650
|
+
@media (prefers-color-scheme: dark) {
|
|
2651
|
+
background-color: color-mix(in srgb, oklch(27.9% 0.077 45.635) 20%, transparent);
|
|
2652
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2653
|
+
background-color: color-mix(in oklab, var(--color-amber-950) 20%, transparent);
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2563
2657
|
.dark\:bg-amber-950\/40 {
|
|
2564
2658
|
@media (prefers-color-scheme: dark) {
|
|
2565
2659
|
background-color: color-mix(in srgb, oklch(27.9% 0.077 45.635) 40%, transparent);
|
|
@@ -2826,6 +2920,22 @@
|
|
|
2826
2920
|
}
|
|
2827
2921
|
}
|
|
2828
2922
|
}
|
|
2923
|
+
.dark\:bg-rose-900\/40 {
|
|
2924
|
+
@media (prefers-color-scheme: dark) {
|
|
2925
|
+
background-color: color-mix(in srgb, oklch(41% 0.159 10.272) 40%, transparent);
|
|
2926
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2927
|
+
background-color: color-mix(in oklab, var(--color-rose-900) 40%, transparent);
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
.dark\:bg-rose-950\/20 {
|
|
2932
|
+
@media (prefers-color-scheme: dark) {
|
|
2933
|
+
background-color: color-mix(in srgb, oklch(27.1% 0.105 12.094) 20%, transparent);
|
|
2934
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2935
|
+
background-color: color-mix(in oklab, var(--color-rose-950) 20%, transparent);
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2829
2939
|
.dark\:bg-slate-700 {
|
|
2830
2940
|
@media (prefers-color-scheme: dark) {
|
|
2831
2941
|
background-color: var(--color-slate-700);
|
|
@@ -3372,6 +3482,15 @@
|
|
|
3372
3482
|
}
|
|
3373
3483
|
}
|
|
3374
3484
|
}
|
|
3485
|
+
.dark\:hover\:text-white {
|
|
3486
|
+
@media (prefers-color-scheme: dark) {
|
|
3487
|
+
&:hover {
|
|
3488
|
+
@media (hover: hover) {
|
|
3489
|
+
color: var(--color-white);
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3375
3494
|
.dark\:hover\:text-white\/60 {
|
|
3376
3495
|
@media (prefers-color-scheme: dark) {
|
|
3377
3496
|
&:hover {
|
|
@@ -43,10 +43,7 @@ export class UniversalLLMAdapter implements ILLMProvider {
|
|
|
43
43
|
constructor(config: LLMConfig | EmbeddingConfig) {
|
|
44
44
|
this.model = config.model;
|
|
45
45
|
|
|
46
|
-
// Type narrow to extract LLM-specific fields safely
|
|
47
46
|
const llmConfig = config as LLMConfig;
|
|
48
|
-
|
|
49
|
-
// Merge profile defaults if specified in options
|
|
50
47
|
const options = (llmConfig.options as Record<string, unknown>) ?? {};
|
|
51
48
|
let profile: Record<string, unknown> = {};
|
|
52
49
|
|
|
@@ -112,7 +109,7 @@ export class UniversalLLMAdapter implements ILLMProvider {
|
|
|
112
109
|
};
|
|
113
110
|
}
|
|
114
111
|
|
|
115
|
-
//
|
|
112
|
+
// Tier 1: Remote HTTP POST to Retrivora Cloud Proxy (e.g. https://www.retrivora.com/api/v1/chat/completions)
|
|
116
113
|
try {
|
|
117
114
|
const { data } = await this.http.post(path, payload);
|
|
118
115
|
const extractPath = this.opts.responseExtractPath ?? 'choices[0].message.content';
|
|
@@ -121,20 +118,9 @@ export class UniversalLLMAdapter implements ILLMProvider {
|
|
|
121
118
|
return String(result);
|
|
122
119
|
}
|
|
123
120
|
} catch (httpErr: any) {
|
|
124
|
-
//
|
|
125
|
-
|
|
121
|
+
// Tier 2: In-process fallback (only if HTTP call fails and server registered dispatch on globalThis)
|
|
126
122
|
const _g = globalThis as any;
|
|
127
|
-
|
|
128
|
-
if (typeof dispatch !== 'function') {
|
|
129
|
-
try {
|
|
130
|
-
const gateway = await import('../../../../../services/llm-gateway/router');
|
|
131
|
-
if (gateway?.dispatchChatCompletion) {
|
|
132
|
-
_g.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
|
|
133
|
-
_g.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
|
|
134
|
-
dispatch = gateway.dispatchChatCompletion;
|
|
135
|
-
}
|
|
136
|
-
} catch { /* proceed */ }
|
|
137
|
-
}
|
|
123
|
+
const dispatch = _g.__retrivoraDispatchChat;
|
|
138
124
|
|
|
139
125
|
if (typeof dispatch === 'function') {
|
|
140
126
|
const res = await dispatch({
|
|
@@ -153,7 +139,6 @@ export class UniversalLLMAdapter implements ILLMProvider {
|
|
|
153
139
|
}
|
|
154
140
|
|
|
155
141
|
const { data } = await this.http.post(path, payload);
|
|
156
|
-
|
|
157
142
|
const extractPath = this.opts.responseExtractPath ?? 'choices[0].message.content';
|
|
158
143
|
const result = resolvePath(data, extractPath) ?? extractContent(data);
|
|
159
144
|
|
|
@@ -167,12 +152,10 @@ export class UniversalLLMAdapter implements ILLMProvider {
|
|
|
167
152
|
/**
|
|
168
153
|
* Streaming chat using native fetch + ReadableStream.
|
|
169
154
|
* Parses OpenAI-compatible SSE frames: `data: {...}\n\n`
|
|
170
|
-
* Works with vLLM, LMStudio, Together AI, Fireworks, and any OpenAI-compatible API.
|
|
171
155
|
*/
|
|
172
156
|
async *chatStream(messages: ChatMessage[], context?: string): AsyncIterable<string> {
|
|
173
157
|
const path = this.opts.chatPath ?? '/chat/completions';
|
|
174
158
|
const url = `${this.baseUrl.replace(/\/$/, '')}${path}`;
|
|
175
|
-
// Delta extract path — same root as chat but with delta instead of message
|
|
176
159
|
const extractPath = (this.opts.responseExtractPath ?? 'choices[0].message.content')
|
|
177
160
|
.replace('message.content', 'delta.content');
|
|
178
161
|
|
|
@@ -196,7 +179,6 @@ export class UniversalLLMAdapter implements ILLMProvider {
|
|
|
196
179
|
maxTokens: this.maxTokens,
|
|
197
180
|
temperature: this.temperature,
|
|
198
181
|
});
|
|
199
|
-
// Inject stream: true into the payload if it's an object
|
|
200
182
|
if (typeof payload === 'object' && payload !== null) {
|
|
201
183
|
(payload as Record<string, unknown>).stream = true;
|
|
202
184
|
}
|
|
@@ -210,22 +192,40 @@ export class UniversalLLMAdapter implements ILLMProvider {
|
|
|
210
192
|
};
|
|
211
193
|
}
|
|
212
194
|
|
|
213
|
-
const isSelfHost = this.baseUrl.includes('retrivora.com') || this.baseUrl.includes('localhost');
|
|
214
195
|
let streamBody: ReadableStream<Uint8Array> | null = null;
|
|
215
196
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
197
|
+
// ── Tier 1: HTTP Stream Request to Retrivora Gateway Proxy ─────────────────
|
|
198
|
+
try {
|
|
199
|
+
const response = await fetch(url, {
|
|
200
|
+
method: 'POST',
|
|
201
|
+
headers: this.resolvedHeaders,
|
|
202
|
+
body: typeof payload === 'string' ? payload : JSON.stringify(payload),
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
if (response.ok) {
|
|
206
|
+
const contentType = response.headers.get('content-type') || '';
|
|
207
|
+
if (contentType.includes('application/json')) {
|
|
208
|
+
const json = await response.json();
|
|
209
|
+
const text = (resolvePath(json, extractPath) as string | undefined) ?? extractContent(json);
|
|
210
|
+
if (text && typeof text === 'string') {
|
|
211
|
+
yield text;
|
|
212
|
+
return;
|
|
226
213
|
}
|
|
227
|
-
}
|
|
214
|
+
} else if (response.body) {
|
|
215
|
+
streamBody = response.body;
|
|
216
|
+
}
|
|
217
|
+
} else {
|
|
218
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
219
|
+
console.warn(`[UniversalLLMAdapter] Remote HTTP stream returned ${response.status}: ${errorText}. Attempting in-process fallback...`);
|
|
228
220
|
}
|
|
221
|
+
} catch (fetchErr: any) {
|
|
222
|
+
console.warn(`[UniversalLLMAdapter] Remote HTTP stream fetch warning: ${fetchErr?.message}. Attempting in-process fallback...`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ── Tier 2: In-process Dispatch Fallback (if remote HTTP fails) ────────────
|
|
226
|
+
if (!streamBody) {
|
|
227
|
+
const _g = globalThis as any;
|
|
228
|
+
const dispatch = _g.__retrivoraDispatchChat;
|
|
229
229
|
|
|
230
230
|
if (typeof dispatch === 'function') {
|
|
231
231
|
try {
|
|
@@ -245,32 +245,15 @@ export class UniversalLLMAdapter implements ILLMProvider {
|
|
|
245
245
|
yield content;
|
|
246
246
|
return;
|
|
247
247
|
}
|
|
248
|
-
throw new Error(`[UniversalLLMAdapter] In-process dispatch stream returned empty response for model: ${this.model}`);
|
|
249
248
|
}
|
|
250
249
|
} catch (dispatchErr) {
|
|
251
|
-
|
|
250
|
+
console.warn('[UniversalLLMAdapter] In-process dispatch error:', dispatchErr);
|
|
252
251
|
}
|
|
253
|
-
} else {
|
|
254
|
-
throw new Error(`[UniversalLLMAdapter] In-process gateway dispatch not registered. Direct self-referential HTTP calls to ${this.baseUrl} are disabled on Vercel to prevent HTTP 508 Loop Detected.`);
|
|
255
252
|
}
|
|
256
253
|
}
|
|
257
254
|
|
|
258
255
|
if (!streamBody) {
|
|
259
|
-
|
|
260
|
-
method: 'POST',
|
|
261
|
-
headers: this.resolvedHeaders,
|
|
262
|
-
body: JSON.stringify(payload),
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
if (!response.ok) {
|
|
266
|
-
const errorText = await response.text().catch(() => response.statusText);
|
|
267
|
-
throw new Error(`[UniversalLLMAdapter] Streaming request failed (${response.status}): ${errorText}`);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (!response.body) {
|
|
271
|
-
throw new Error('[UniversalLLMAdapter] Response body is null — server did not send a streaming response.');
|
|
272
|
-
}
|
|
273
|
-
streamBody = response.body;
|
|
256
|
+
throw new Error(`[UniversalLLMAdapter] Streaming request failed. Ensure RETRIVORA_LICENSE_KEY is valid or LLM service is available.`);
|
|
274
257
|
}
|
|
275
258
|
|
|
276
259
|
const reader = streamBody.getReader();
|
|
@@ -296,12 +279,11 @@ export class UniversalLLMAdapter implements ILLMProvider {
|
|
|
296
279
|
const text = (resolvePath(json, extractPath) as string | undefined) ?? extractContent(json);
|
|
297
280
|
if (text && typeof text === 'string') yield text;
|
|
298
281
|
} catch {
|
|
299
|
-
//
|
|
282
|
+
// Skip malformed SSE lines
|
|
300
283
|
}
|
|
301
284
|
}
|
|
302
285
|
}
|
|
303
286
|
|
|
304
|
-
// Flush remaining buffer
|
|
305
287
|
if (buffer.trim() && buffer.trim() !== 'data: [DONE]') {
|
|
306
288
|
const jsonStr = buffer.replace(/^data:\s*/, '').trim();
|
|
307
289
|
try {
|
|
@@ -317,85 +299,52 @@ export class UniversalLLMAdapter implements ILLMProvider {
|
|
|
317
299
|
|
|
318
300
|
async embed(text: string): Promise<number[]> {
|
|
319
301
|
const path = this.opts.embedPath ?? '/embeddings';
|
|
302
|
+
const payload = this.opts.embedPayloadTemplate
|
|
303
|
+
? buildPayload(this.opts.embedPayloadTemplate, { input: text, model: this.model })
|
|
304
|
+
: { input: text, model: this.model };
|
|
320
305
|
|
|
321
|
-
let payload: unknown;
|
|
322
|
-
if (this.opts.embedPayloadTemplate) {
|
|
323
|
-
payload = buildPayload(this.opts.embedPayloadTemplate, {
|
|
324
|
-
model: this.model,
|
|
325
|
-
input: text,
|
|
326
|
-
});
|
|
327
|
-
} else {
|
|
328
|
-
payload = {
|
|
329
|
-
model: this.model,
|
|
330
|
-
input: text,
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// Try direct HTTP POST request to llm.retrivora.com first
|
|
335
306
|
try {
|
|
336
307
|
const { data } = await this.http.post(path, payload);
|
|
337
308
|
const extractPath = this.opts.embedExtractPath ?? 'data[0].embedding';
|
|
338
|
-
const vector = resolvePath(data, extractPath);
|
|
339
|
-
if (Array.isArray(vector))
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
} catch (httpErr: any) {
|
|
343
|
-
console.warn(`[UniversalLLMAdapter] Direct HTTP embedding POST to ${this.baseUrl}${path} failed (${httpErr.message}). Attempting in-process gateway dispatch fallback...`);
|
|
344
|
-
|
|
309
|
+
const vector = resolvePath(data, extractPath) as number[] | undefined;
|
|
310
|
+
if (Array.isArray(vector)) return vector;
|
|
311
|
+
} catch {
|
|
312
|
+
// In-process fallback for embeddings
|
|
345
313
|
const _g = globalThis as any;
|
|
346
|
-
|
|
347
|
-
if (typeof dispatch !== 'function') {
|
|
348
|
-
try {
|
|
349
|
-
const gateway = await import('../../../../../services/llm-gateway/router');
|
|
350
|
-
if (gateway?.dispatchEmbedding) {
|
|
351
|
-
_g.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
|
|
352
|
-
_g.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
|
|
353
|
-
dispatch = gateway.dispatchEmbedding;
|
|
354
|
-
}
|
|
355
|
-
} catch { /* proceed */ }
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
if (typeof dispatch === 'function') {
|
|
359
|
-
const res = await dispatch({
|
|
360
|
-
model: this.model,
|
|
361
|
-
input: text,
|
|
362
|
-
}, this.apiKey);
|
|
314
|
+
const dispatchEmbed = _g.__retrivoraDispatchEmbedding;
|
|
363
315
|
|
|
316
|
+
if (typeof dispatchEmbed === 'function') {
|
|
317
|
+
const res = await dispatchEmbed({ input: text, model: this.model }, this.apiKey);
|
|
364
318
|
if (res?.data?.[0]?.embedding) {
|
|
365
319
|
return res.data[0].embedding;
|
|
366
320
|
}
|
|
367
321
|
}
|
|
368
|
-
throw httpErr;
|
|
369
322
|
}
|
|
370
323
|
|
|
371
324
|
const { data } = await this.http.post(path, payload);
|
|
372
|
-
|
|
373
325
|
const extractPath = this.opts.embedExtractPath ?? 'data[0].embedding';
|
|
374
|
-
const vector = resolvePath(data, extractPath);
|
|
326
|
+
const vector = resolvePath(data, extractPath) as number[] | undefined;
|
|
375
327
|
|
|
376
328
|
if (!Array.isArray(vector)) {
|
|
377
|
-
throw new Error(`[UniversalLLMAdapter]
|
|
329
|
+
throw new Error(`[UniversalLLMAdapter] Could not extract embedding vector from path '${extractPath}' in response.`);
|
|
378
330
|
}
|
|
379
331
|
|
|
380
332
|
return vector;
|
|
381
333
|
}
|
|
382
334
|
|
|
383
335
|
async batchEmbed(texts: string[]): Promise<number[][]> {
|
|
384
|
-
const
|
|
336
|
+
const results: number[][] = [];
|
|
385
337
|
for (const text of texts) {
|
|
386
|
-
|
|
338
|
+
results.push(await this.embed(text));
|
|
387
339
|
}
|
|
388
|
-
return
|
|
340
|
+
return results;
|
|
389
341
|
}
|
|
390
342
|
|
|
391
343
|
async ping(): Promise<boolean> {
|
|
392
344
|
try {
|
|
393
|
-
|
|
394
|
-
await this.http.get(this.opts.pingPath);
|
|
395
|
-
}
|
|
345
|
+
await this.embed('ping');
|
|
396
346
|
return true;
|
|
397
|
-
} catch
|
|
398
|
-
console.error('[UniversalLLMAdapter] Ping failed:', err);
|
|
347
|
+
} catch {
|
|
399
348
|
return false;
|
|
400
349
|
}
|
|
401
350
|
}
|