@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/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
- // Try direct HTTP POST request to llm.retrivora.com first
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
- // Direct POST fallback attempt
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
- let dispatch = _g.__retrivoraDispatchChat;
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
- if (isSelfHost || Boolean(process.env.VERCEL)) {
217
- const _g = globalThis as any;
218
- let dispatch = _g.__retrivoraDispatchChat;
219
- if (typeof dispatch !== 'function') {
220
- try {
221
- const gateway = await import('../../../../../services/llm-gateway/router');
222
- if (gateway?.dispatchChatCompletion) {
223
- _g.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
224
- _g.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
225
- dispatch = gateway.dispatchChatCompletion;
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
- } catch { /* proceed */ }
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
- throw dispatchErr;
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
- const response = await fetch(url, {
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
- // Malformed SSE line — skip
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
- return vector as number[];
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
- let dispatch = _g.__retrivoraDispatchEmbedding;
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] Expected a number array at '${extractPath}' for embeddings.`);
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 vectors: number[][] = [];
336
+ const results: number[][] = [];
385
337
  for (const text of texts) {
386
- vectors.push(await this.embed(text));
338
+ results.push(await this.embed(text));
387
339
  }
388
- return vectors;
340
+ return results;
389
341
  }
390
342
 
391
343
  async ping(): Promise<boolean> {
392
344
  try {
393
- if (this.opts.pingPath) {
394
- await this.http.get(this.opts.pingPath);
395
- }
345
+ await this.embed('ping');
396
346
  return true;
397
- } catch (err) {
398
- console.error('[UniversalLLMAdapter] Ping failed:', err);
347
+ } catch {
399
348
  return false;
400
349
  }
401
350
  }