@retrivora-ai/rag-engine 2.0.6 → 2.0.8

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/server.js CHANGED
@@ -121,6 +121,609 @@ var init_templateUtils = __esm({
121
121
  }
122
122
  });
123
123
 
124
+ // ../../services/llm-gateway/providers/groq.ts
125
+ async function handleGroqRequest(req, apiKeyOverride) {
126
+ const apiKey = apiKeyOverride || process.env.GROQ_API_KEY;
127
+ if (!apiKey) {
128
+ throw new Error("Groq API Key missing. Please set GROQ_API_KEY in environment variables.");
129
+ }
130
+ const modelName = req.model.replace(/^groq\//i, "");
131
+ const payload = __spreadProps(__spreadValues({}, req), {
132
+ model: modelName
133
+ });
134
+ const response = await fetch("https://api.groq.com/openai/v1/chat/completions", {
135
+ method: "POST",
136
+ headers: {
137
+ "Content-Type": "application/json",
138
+ "Authorization": `Bearer ${apiKey}`
139
+ },
140
+ body: JSON.stringify(payload)
141
+ });
142
+ if (!response.ok) {
143
+ const errorText = await response.text();
144
+ throw new Error(`Groq API Error (${response.status}): ${errorText}`);
145
+ }
146
+ if (req.stream && response.body) {
147
+ return { stream: response.body };
148
+ }
149
+ const json = await response.json();
150
+ return { response: json };
151
+ }
152
+ var init_groq = __esm({
153
+ "../../services/llm-gateway/providers/groq.ts"() {
154
+ "use strict";
155
+ }
156
+ });
157
+
158
+ // ../../services/llm-gateway/providers/openai.ts
159
+ async function handleOpenAIRequest(req, apiKeyOverride) {
160
+ const apiKey = apiKeyOverride || process.env.OPENAI_API_KEY;
161
+ if (!apiKey) {
162
+ throw new Error("OpenAI API Key missing. Please set OPENAI_API_KEY in environment variables.");
163
+ }
164
+ const modelName = req.model.replace(/^(openai|gpt)\//i, "");
165
+ const payload = __spreadProps(__spreadValues({}, req), {
166
+ model: modelName
167
+ });
168
+ const response = await fetch("https://api.openai.com/v1/chat/completions", {
169
+ method: "POST",
170
+ headers: {
171
+ "Content-Type": "application/json",
172
+ "Authorization": `Bearer ${apiKey}`
173
+ },
174
+ body: JSON.stringify(payload)
175
+ });
176
+ if (!response.ok) {
177
+ const errorText = await response.text();
178
+ throw new Error(`OpenAI API Error (${response.status}): ${errorText}`);
179
+ }
180
+ if (req.stream && response.body) {
181
+ return { stream: response.body };
182
+ }
183
+ const json = await response.json();
184
+ return { response: json };
185
+ }
186
+ async function handleOpenAIEmbedding(req, apiKeyOverride) {
187
+ const apiKey = apiKeyOverride || process.env.OPENAI_API_KEY;
188
+ if (!apiKey) {
189
+ throw new Error("OpenAI API Key missing. Please set OPENAI_API_KEY in environment variables.");
190
+ }
191
+ const modelName = req.model.replace(/^(openai)\//i, "");
192
+ const response = await fetch("https://api.openai.com/v1/embeddings", {
193
+ method: "POST",
194
+ headers: {
195
+ "Content-Type": "application/json",
196
+ "Authorization": `Bearer ${apiKey}`
197
+ },
198
+ body: JSON.stringify({
199
+ model: modelName,
200
+ input: req.input
201
+ })
202
+ });
203
+ if (!response.ok) {
204
+ const errorText = await response.text();
205
+ throw new Error(`OpenAI Embedding API Error (${response.status}): ${errorText}`);
206
+ }
207
+ return await response.json();
208
+ }
209
+ var init_openai = __esm({
210
+ "../../services/llm-gateway/providers/openai.ts"() {
211
+ "use strict";
212
+ }
213
+ });
214
+
215
+ // ../../services/llm-gateway/providers/gemini.ts
216
+ async function handleGeminiRequest(req, apiKeyOverride) {
217
+ const apiKey = apiKeyOverride || process.env.GEMINI_API_KEY;
218
+ if (!apiKey) {
219
+ throw new Error("Gemini API Key missing. Please set GEMINI_API_KEY in environment variables.");
220
+ }
221
+ let modelName = req.model.replace(/^(google|gemini)\//i, "");
222
+ if (!modelName.startsWith("gemini-")) {
223
+ modelName = `gemini-${modelName}`;
224
+ }
225
+ const payload = __spreadProps(__spreadValues({}, req), {
226
+ model: modelName
227
+ });
228
+ const response = await fetch("https://generativelanguage.googleapis.com/v1beta/openai/chat/completions", {
229
+ method: "POST",
230
+ headers: {
231
+ "Content-Type": "application/json",
232
+ "Authorization": `Bearer ${apiKey}`
233
+ },
234
+ body: JSON.stringify(payload)
235
+ });
236
+ if (!response.ok) {
237
+ const errorText = await response.text();
238
+ throw new Error(`Google Gemini API Error (${response.status}): ${errorText}`);
239
+ }
240
+ if (req.stream && response.body) {
241
+ return { stream: response.body };
242
+ }
243
+ const json = await response.json();
244
+ return { response: json };
245
+ }
246
+ async function handleGeminiEmbedding(req, apiKeyOverride) {
247
+ const apiKey = apiKeyOverride || process.env.GEMINI_API_KEY;
248
+ if (!apiKey) {
249
+ throw new Error("Gemini API Key missing. Please set GEMINI_API_KEY in environment variables.");
250
+ }
251
+ let modelName = req.model.replace(/^(google|gemini)\//i, "");
252
+ if (!modelName || modelName === "default" || modelName.includes("text-embedding-3") || modelName.includes("ada") || !modelName.startsWith("text-embedding-00") && !modelName.startsWith("embedding-00")) {
253
+ modelName = "text-embedding-004";
254
+ }
255
+ const response = await fetch("https://generativelanguage.googleapis.com/v1beta/openai/embeddings", {
256
+ method: "POST",
257
+ headers: {
258
+ "Content-Type": "application/json",
259
+ "Authorization": `Bearer ${apiKey}`
260
+ },
261
+ body: JSON.stringify({
262
+ model: modelName,
263
+ input: req.input
264
+ })
265
+ });
266
+ if (!response.ok) {
267
+ const errorText = await response.text();
268
+ throw new Error(`Google Gemini Embedding API Error (${response.status}): ${errorText}`);
269
+ }
270
+ return await response.json();
271
+ }
272
+ var init_gemini = __esm({
273
+ "../../services/llm-gateway/providers/gemini.ts"() {
274
+ "use strict";
275
+ }
276
+ });
277
+
278
+ // ../../services/llm-gateway/providers/huggingface.ts
279
+ async function handleHuggingFaceChatRequest(req, apiKeyOverride) {
280
+ var _a2, _b;
281
+ const apiKey = apiKeyOverride || process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN;
282
+ if (!apiKey) {
283
+ throw new Error("HuggingFace API Key missing. Set HUGGINGFACE_API_KEY or HF_TOKEN in environment variables.");
284
+ }
285
+ let modelName = req.model.replace(/^(huggingface|hf)\//i, "");
286
+ if (!modelName || modelName === "default" || modelName.toLowerCase() === "qwen" || modelName.toLowerCase() === "qwen-coder") {
287
+ modelName = "Qwen/Qwen2.5-Coder-32B-Instruct";
288
+ }
289
+ const payload = __spreadProps(__spreadValues({}, req), {
290
+ model: modelName
291
+ });
292
+ try {
293
+ const response = await fetch("https://router.huggingface.co/v1/chat/completions", {
294
+ method: "POST",
295
+ headers: {
296
+ "Content-Type": "application/json",
297
+ "Authorization": `Bearer ${apiKey}`
298
+ },
299
+ body: JSON.stringify(payload)
300
+ });
301
+ if (response.ok) {
302
+ if (req.stream && response.body) {
303
+ return { stream: response.body };
304
+ }
305
+ const json = await response.json();
306
+ return { response: json };
307
+ }
308
+ } catch (e) {
309
+ }
310
+ try {
311
+ const response = await fetch("https://router.huggingface.co/hf-inference/v1/chat/completions", {
312
+ method: "POST",
313
+ headers: {
314
+ "Content-Type": "application/json",
315
+ "Authorization": `Bearer ${apiKey}`
316
+ },
317
+ body: JSON.stringify(payload)
318
+ });
319
+ if (response.ok) {
320
+ if (req.stream && response.body) {
321
+ return { stream: response.body };
322
+ }
323
+ const json = await response.json();
324
+ return { response: json };
325
+ }
326
+ } catch (e) {
327
+ }
328
+ const lastUserMsg = ((_a2 = req.messages.filter((m) => m.role === "user").pop()) == null ? void 0 : _a2.content) || "Hello";
329
+ const pipelineRes = await fetch(`https://router.huggingface.co/hf-inference/models/${modelName}`, {
330
+ method: "POST",
331
+ headers: {
332
+ "Content-Type": "application/json",
333
+ "Authorization": `Bearer ${apiKey}`
334
+ },
335
+ body: JSON.stringify({
336
+ inputs: lastUserMsg,
337
+ parameters: { max_new_tokens: req.max_tokens || 256, temperature: req.temperature || 0.7 },
338
+ options: { wait_for_model: true }
339
+ })
340
+ });
341
+ if (!pipelineRes.ok) {
342
+ const errorText = await pipelineRes.text();
343
+ throw new Error(`HuggingFace API Error (${pipelineRes.status}): ${errorText}`);
344
+ }
345
+ const raw = await pipelineRes.json();
346
+ const textOutput = Array.isArray(raw) ? ((_b = raw[0]) == null ? void 0 : _b.generated_text) || JSON.stringify(raw) : JSON.stringify(raw);
347
+ const formattedResponse = {
348
+ id: `hf-${Date.now()}`,
349
+ object: "chat.completion",
350
+ created: Math.floor(Date.now() / 1e3),
351
+ model: modelName,
352
+ choices: [
353
+ {
354
+ index: 0,
355
+ message: {
356
+ role: "assistant",
357
+ content: textOutput
358
+ },
359
+ finish_reason: "stop"
360
+ }
361
+ ],
362
+ usage: {
363
+ prompt_tokens: lastUserMsg.length,
364
+ completion_tokens: textOutput.length,
365
+ total_tokens: lastUserMsg.length + textOutput.length
366
+ }
367
+ };
368
+ return { response: formattedResponse };
369
+ }
370
+ async function handleHuggingFaceEmbedding(req, apiKeyOverride) {
371
+ const apiKey = apiKeyOverride || process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN;
372
+ if (!apiKey) {
373
+ throw new Error("HuggingFace API Key missing. Set HUGGINGFACE_API_KEY or HF_TOKEN in environment variables.");
374
+ }
375
+ let modelName = req.model.replace(/^(huggingface|hf)\//i, "");
376
+ if (!modelName || modelName === "default" || modelName.includes("text-embedding-3") || modelName.includes("ada") || !modelName.includes("/") && !modelName.includes("bge") && !modelName.includes("sentence-transformers")) {
377
+ modelName = "BAAI/bge-base-en-v1.5";
378
+ }
379
+ const inputs = Array.isArray(req.input) ? req.input : [req.input];
380
+ const fetchEmbeddingFromModel = async (targetModel) => {
381
+ try {
382
+ const routerRes = await fetch("https://router.huggingface.co/hf-inference/v1/embeddings", {
383
+ method: "POST",
384
+ headers: {
385
+ "Content-Type": "application/json",
386
+ "Authorization": `Bearer ${apiKey}`
387
+ },
388
+ body: JSON.stringify({
389
+ model: targetModel,
390
+ input: inputs
391
+ })
392
+ });
393
+ if (routerRes.ok) {
394
+ const json = await routerRes.json();
395
+ if (json && json.data) return json;
396
+ }
397
+ } catch (e) {
398
+ }
399
+ const response = await fetch(`https://router.huggingface.co/hf-inference/models/${targetModel}`, {
400
+ method: "POST",
401
+ headers: {
402
+ "Content-Type": "application/json",
403
+ "Authorization": `Bearer ${apiKey}`
404
+ },
405
+ body: JSON.stringify({
406
+ inputs,
407
+ options: { wait_for_model: true }
408
+ })
409
+ });
410
+ if (!response.ok) {
411
+ const errorText = await response.text();
412
+ throw new Error(`HuggingFace API Error (${response.status}): ${errorText}`);
413
+ }
414
+ const rawData = await response.json();
415
+ const embeddings = Array.isArray(rawData[0]) ? typeof rawData[0][0] === "number" ? rawData : rawData.map((arr) => arr[0]) : [rawData];
416
+ return {
417
+ object: "list",
418
+ data: embeddings.map((vec, idx) => ({
419
+ object: "embedding",
420
+ embedding: vec,
421
+ index: idx
422
+ })),
423
+ model: targetModel,
424
+ usage: {
425
+ prompt_tokens: inputs.reduce((acc, str) => acc + str.length, 0),
426
+ completion_tokens: 0,
427
+ total_tokens: inputs.reduce((acc, str) => acc + str.length, 0)
428
+ }
429
+ };
430
+ };
431
+ try {
432
+ return await fetchEmbeddingFromModel(modelName);
433
+ } catch (err) {
434
+ if (modelName !== "BAAI/bge-base-en-v1.5") {
435
+ console.warn(`[LLM Gateway] HuggingFace model ${modelName} failed. Falling back to BAAI/bge-base-en-v1.5...`, err);
436
+ return await fetchEmbeddingFromModel("BAAI/bge-base-en-v1.5");
437
+ }
438
+ throw err;
439
+ }
440
+ }
441
+ var init_huggingface = __esm({
442
+ "../../services/llm-gateway/providers/huggingface.ts"() {
443
+ "use strict";
444
+ }
445
+ });
446
+
447
+ // ../../services/llm-gateway/providers/anthropic.ts
448
+ async function handleAnthropicRequest(req, apiKeyOverride) {
449
+ var _a2, _b;
450
+ const apiKey = apiKeyOverride || process.env.ANTHROPIC_API_KEY;
451
+ if (!apiKey) {
452
+ throw new Error("Anthropic API Key missing. Please set ANTHROPIC_API_KEY in environment variables.");
453
+ }
454
+ const modelName = req.model.replace(/^(anthropic|claude)\//i, "");
455
+ let systemPrompt = void 0;
456
+ const anthropicMessages = [];
457
+ for (const msg of req.messages) {
458
+ if (msg.role === "system") {
459
+ systemPrompt = systemPrompt ? `${systemPrompt}
460
+ ${msg.content}` : msg.content;
461
+ } else {
462
+ anthropicMessages.push({
463
+ role: msg.role === "assistant" ? "assistant" : "user",
464
+ content: msg.content
465
+ });
466
+ }
467
+ }
468
+ if (anthropicMessages.length === 0) {
469
+ anthropicMessages.push({ role: "user", content: "Hello" });
470
+ }
471
+ const payload = {
472
+ model: modelName,
473
+ messages: anthropicMessages,
474
+ max_tokens: req.max_tokens || req.max_completion_tokens || 1024,
475
+ stream: req.stream || false
476
+ };
477
+ if (systemPrompt) {
478
+ payload.system = systemPrompt;
479
+ }
480
+ if (req.temperature !== void 0) {
481
+ payload.temperature = req.temperature;
482
+ }
483
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
484
+ method: "POST",
485
+ headers: {
486
+ "Content-Type": "application/json",
487
+ "x-api-key": apiKey,
488
+ "anthropic-version": "2023-06-01"
489
+ },
490
+ body: JSON.stringify(payload)
491
+ });
492
+ if (!response.ok) {
493
+ const errorText = await response.text();
494
+ throw new Error(`Anthropic API Error (${response.status}): ${errorText}`);
495
+ }
496
+ if (req.stream && response.body) {
497
+ return { stream: response.body };
498
+ }
499
+ const json = await response.json();
500
+ const textContent = ((_b = (_a2 = json.content) == null ? void 0 : _a2[0]) == null ? void 0 : _b.text) || "";
501
+ const openAIResponse = {
502
+ id: json.id || `chatcmpl-${Date.now()}`,
503
+ object: "chat.completion",
504
+ created: Math.floor(Date.now() / 1e3),
505
+ model: json.model || modelName,
506
+ choices: [
507
+ {
508
+ index: 0,
509
+ message: {
510
+ role: "assistant",
511
+ content: textContent
512
+ },
513
+ finish_reason: json.stop_reason === "end_turn" ? "stop" : json.stop_reason || "stop"
514
+ }
515
+ ],
516
+ usage: json.usage ? {
517
+ prompt_tokens: json.usage.input_tokens,
518
+ completion_tokens: json.usage.output_tokens,
519
+ total_tokens: json.usage.input_tokens + json.usage.output_tokens
520
+ } : void 0
521
+ };
522
+ return { response: openAIResponse };
523
+ }
524
+ var init_anthropic = __esm({
525
+ "../../services/llm-gateway/providers/anthropic.ts"() {
526
+ "use strict";
527
+ }
528
+ });
529
+
530
+ // ../../services/llm-gateway/providers/ollama.ts
531
+ async function handleOllamaRequest(req, baseUrlOverride) {
532
+ const baseUrl = (baseUrlOverride || process.env.OLLAMA_BASE_URL || "http://localhost:11434/v1").replace(/\/+$/, "");
533
+ const modelName = req.model.replace(/^ollama\//i, "");
534
+ const payload = __spreadProps(__spreadValues({}, req), {
535
+ model: modelName
536
+ });
537
+ const response = await fetch(`${baseUrl}/chat/completions`, {
538
+ method: "POST",
539
+ headers: {
540
+ "Content-Type": "application/json"
541
+ },
542
+ body: JSON.stringify(payload)
543
+ });
544
+ if (!response.ok) {
545
+ const errorText = await response.text();
546
+ throw new Error(`Ollama API Error (${response.status}): ${errorText}`);
547
+ }
548
+ if (req.stream && response.body) {
549
+ return { stream: response.body };
550
+ }
551
+ const json = await response.json();
552
+ return { response: json };
553
+ }
554
+ var init_ollama = __esm({
555
+ "../../services/llm-gateway/providers/ollama.ts"() {
556
+ "use strict";
557
+ }
558
+ });
559
+
560
+ // ../../services/llm-gateway/router.ts
561
+ var router_exports = {};
562
+ __export(router_exports, {
563
+ SUPPORTED_MODELS: () => SUPPORTED_MODELS,
564
+ dispatchChatCompletion: () => dispatchChatCompletion,
565
+ dispatchEmbedding: () => dispatchEmbedding,
566
+ resolveProvider: () => resolveProvider
567
+ });
568
+ function resolveProvider(model) {
569
+ const lower = model.toLowerCase();
570
+ if (lower.startsWith("huggingface/") || lower.startsWith("hf/")) {
571
+ return "huggingface";
572
+ }
573
+ if (lower.startsWith("ollama/")) {
574
+ return "ollama";
575
+ }
576
+ if (lower.startsWith("groq/") || lower.includes("llama") || lower.includes("qwen") || lower.includes("mixtral")) {
577
+ return "groq";
578
+ }
579
+ if (process.env.GROQ_API_KEY) return "groq";
580
+ if (process.env.OPENAI_API_KEY) return "openai";
581
+ if (process.env.GEMINI_API_KEY) return "gemini";
582
+ if (process.env.ANTHROPIC_API_KEY) return "anthropic";
583
+ if (process.env.HF_TOKEN || process.env.HUGGINGFACE_API_KEY) return "huggingface";
584
+ return "groq";
585
+ }
586
+ function cleanApiKeyOverride(apiKeyOverride) {
587
+ if (!apiKeyOverride) return void 0;
588
+ const key = apiKeyOverride.trim();
589
+ if (key === process.env.LITELLM_API_KEY || key === process.env.LITELLM_MASTER_KEY || key.startsWith("sk-retrivora") || !key.startsWith("gsk_") && !key.startsWith("AIza") && !key.startsWith("sk-ant-") && !key.startsWith("sk-proj-")) {
590
+ return void 0;
591
+ }
592
+ return key;
593
+ }
594
+ async function dispatchChatCompletion(req, apiKeyOverride) {
595
+ const effectiveKey = cleanApiKeyOverride(apiKeyOverride);
596
+ const provider = resolveProvider(req.model);
597
+ try {
598
+ switch (provider) {
599
+ case "groq":
600
+ return await handleGroqRequest(req, effectiveKey);
601
+ case "openai":
602
+ return await handleOpenAIRequest(req, effectiveKey);
603
+ case "gemini":
604
+ return await handleGeminiRequest(req, effectiveKey);
605
+ case "anthropic":
606
+ return await handleAnthropicRequest(req, effectiveKey);
607
+ case "ollama":
608
+ return await handleOllamaRequest(req);
609
+ case "huggingface":
610
+ return await handleHuggingFaceChatRequest(req, effectiveKey);
611
+ default:
612
+ throw new Error(`Unsupported LLM provider for model: ${req.model}`);
613
+ }
614
+ } catch (error) {
615
+ if (/rate[- ]?limit|429|exhausted/i.test(error.message)) {
616
+ const isGroqKey = process.env.GROQ_API_KEY || effectiveKey && effectiveKey.startsWith("gsk_");
617
+ const reqModelLower = req.model.toLowerCase();
618
+ if (isGroqKey && !reqModelLower.includes("llama-3.3-70b")) {
619
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to secondary Groq model (llama-3.3-70b-versatile)...`);
620
+ try {
621
+ return await handleGroqRequest(__spreadProps(__spreadValues({}, req), { model: "llama-3.3-70b-versatile" }), effectiveKey);
622
+ } catch (e) {
623
+ }
624
+ }
625
+ const geminiKey = process.env.GEMINI_API_KEY || effectiveKey;
626
+ if (provider !== "gemini" && geminiKey && (geminiKey.startsWith("AIza") || !geminiKey.startsWith("AQ."))) {
627
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to Google Gemini (gemini-2.5-flash)...`);
628
+ try {
629
+ return await handleGeminiRequest(__spreadProps(__spreadValues({}, req), { model: "gemini-2.5-flash" }), effectiveKey);
630
+ } catch (e) {
631
+ }
632
+ }
633
+ if (provider !== "huggingface" && (process.env.HF_TOKEN || process.env.HUGGINGFACE_API_KEY)) {
634
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to Hugging Face (Qwen/Qwen2.5-Coder-32B-Instruct)...`);
635
+ try {
636
+ return await handleHuggingFaceChatRequest(__spreadProps(__spreadValues({}, req), { model: "Qwen/Qwen2.5-Coder-32B-Instruct" }), effectiveKey);
637
+ } catch (e) {
638
+ }
639
+ }
640
+ if (provider !== "openai" && process.env.OPENAI_API_KEY) {
641
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to OpenAI (gpt-4o-mini)...`);
642
+ try {
643
+ return await handleOpenAIRequest(__spreadProps(__spreadValues({}, req), { model: "gpt-4o-mini" }), effectiveKey);
644
+ } catch (e) {
645
+ }
646
+ }
647
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to local Ollama (llama3.2)...`);
648
+ return handleOllamaRequest(__spreadProps(__spreadValues({}, req), { model: "llama3.2" }));
649
+ }
650
+ throw error;
651
+ }
652
+ }
653
+ async function dispatchEmbedding(req, apiKeyOverride) {
654
+ const effectiveKey = cleanApiKeyOverride(apiKeyOverride);
655
+ if (req.model.startsWith("hf/") || req.model.startsWith("huggingface/") || req.model.includes("bge-")) {
656
+ try {
657
+ return await handleHuggingFaceEmbedding(req, effectiveKey);
658
+ } catch (err) {
659
+ console.warn("[LLM Gateway] HuggingFace explicit model embedding failed, falling back to default gateway chain:", err);
660
+ }
661
+ }
662
+ const geminiKey = process.env.GEMINI_API_KEY || effectiveKey;
663
+ const isGeminiKeyValid = Boolean(geminiKey && (geminiKey.startsWith("AIza") || !geminiKey.startsWith("AQ.")));
664
+ if (isGeminiKeyValid) {
665
+ try {
666
+ return await handleGeminiEmbedding(req, effectiveKey);
667
+ } catch (err) {
668
+ console.warn("[LLM Gateway] Gemini embedding failed:", err);
669
+ }
670
+ }
671
+ if (process.env.OPENAI_API_KEY) {
672
+ try {
673
+ return await handleOpenAIEmbedding(req, effectiveKey);
674
+ } catch (err) {
675
+ console.warn("[LLM Gateway] OpenAI embedding failed:", err);
676
+ }
677
+ }
678
+ if (process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN) {
679
+ try {
680
+ return await handleHuggingFaceEmbedding(req, effectiveKey);
681
+ } catch (err) {
682
+ console.warn("[LLM Gateway] HuggingFace fallback embedding failed:", err);
683
+ }
684
+ }
685
+ return handleGeminiEmbedding(req, effectiveKey);
686
+ }
687
+ var SUPPORTED_MODELS;
688
+ var init_router = __esm({
689
+ "../../services/llm-gateway/router.ts"() {
690
+ "use strict";
691
+ init_groq();
692
+ init_openai();
693
+ init_gemini();
694
+ init_huggingface();
695
+ init_anthropic();
696
+ init_ollama();
697
+ SUPPORTED_MODELS = [
698
+ { id: "groq/llama-3.1-8b-instant", object: "model", created: 17e8, owned_by: "groq" },
699
+ { id: "llama-3.1-8b-instant", object: "model", created: 17e8, owned_by: "groq" },
700
+ { id: "groq/llama-3.3-70b-versatile", object: "model", created: 17e8, owned_by: "groq" },
701
+ { id: "llama-3.3-70b-versatile", object: "model", created: 17e8, owned_by: "groq" },
702
+ { id: "gpt-4o-mini", object: "model", created: 17e8, owned_by: "openai" },
703
+ { id: "openai/gpt-4o-mini", object: "model", created: 17e8, owned_by: "openai" },
704
+ { id: "gpt-4o", object: "model", created: 17e8, owned_by: "openai" },
705
+ { id: "gemini-2.5-flash", object: "model", created: 17e8, owned_by: "google" },
706
+ { id: "google/gemini-2.5-flash", object: "model", created: 17e8, owned_by: "google" },
707
+ { id: "claude-3-5-haiku-20241022", object: "model", created: 17e8, owned_by: "anthropic" },
708
+ { id: "anthropic/claude-3-5-haiku-20241022", object: "model", created: 17e8, owned_by: "anthropic" },
709
+ { id: "text-embedding-004", object: "model", created: 17e8, owned_by: "google" },
710
+ { id: "google/text-embedding-004", object: "model", created: 17e8, owned_by: "google" },
711
+ { id: "BAAI/bge-base-en-v1.5", object: "model", created: 17e8, owned_by: "huggingface" },
712
+ { id: "huggingface/BAAI/bge-base-en-v1.5", object: "model", created: 17e8, owned_by: "huggingface" },
713
+ { id: "groq/qwen3-32b", object: "model", created: 17e8, owned_by: "groq" },
714
+ { id: "qwen/qwen3-32b", object: "model", created: 17e8, owned_by: "groq" },
715
+ { id: "qwen/qwen3-embedding-8b", object: "model", created: 17e8, owned_by: "qwen" },
716
+ { id: "qwen3-embedding-8b", object: "model", created: 17e8, owned_by: "qwen" },
717
+ { id: "ollama/llama3.2", object: "model", created: 17e8, owned_by: "ollama" }
718
+ ];
719
+ if (typeof globalThis !== "undefined") {
720
+ const _g2 = globalThis;
721
+ _g2.__retrivoraDispatchChat = dispatchChatCompletion;
722
+ _g2.__retrivoraDispatchEmbedding = dispatchEmbedding;
723
+ }
724
+ }
725
+ });
726
+
124
727
  // src/providers/vectordb/BaseVectorProvider.ts
125
728
  var BaseVectorProvider;
126
729
  var init_BaseVectorProvider = __esm({
@@ -3976,6 +4579,17 @@ var VECTOR_PROFILES = {
3976
4579
  };
3977
4580
 
3978
4581
  // src/llm/providers/UniversalLLMAdapter.ts
4582
+ function extractContent(obj) {
4583
+ var _a2, _b, _c;
4584
+ if (!obj || typeof obj !== "object") return void 0;
4585
+ const choice = (_a2 = obj.choices) == null ? void 0 : _a2[0];
4586
+ if (!choice) return void 0;
4587
+ if (typeof ((_b = choice.message) == null ? void 0 : _b.content) === "string") return choice.message.content;
4588
+ if (typeof ((_c = choice.delta) == null ? void 0 : _c.content) === "string") return choice.delta.content;
4589
+ if (typeof choice.text === "string") return choice.text;
4590
+ if (typeof choice.content === "string") return choice.content;
4591
+ return void 0;
4592
+ }
3979
4593
  var UniversalLLMAdapter = class {
3980
4594
  constructor(config) {
3981
4595
  var _a2, _b, _c, _d, _e, _f, _g2, _h;
@@ -4007,7 +4621,7 @@ var UniversalLLMAdapter = class {
4007
4621
  });
4008
4622
  }
4009
4623
  async chat(messages, context) {
4010
- var _a2, _b, _c, _d, _e, _f;
4624
+ var _a2, _b, _c;
4011
4625
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
4012
4626
  const formattedMessages = [
4013
4627
  { role: "system", content: `${this.systemPrompt}
@@ -4034,25 +4648,42 @@ ${context != null ? context : "None"}` },
4034
4648
  }
4035
4649
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4036
4650
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4037
- try {
4038
- const _g2 = globalThis;
4039
- if (typeof _g2.__retrivoraDispatchChat === "function") {
4040
- const res = await _g2.__retrivoraDispatchChat({
4651
+ const _g2 = globalThis;
4652
+ let dispatch = _g2.__retrivoraDispatchChat;
4653
+ if (typeof dispatch !== "function") {
4654
+ try {
4655
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4656
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4657
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4658
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4659
+ dispatch = gateway.dispatchChatCompletion;
4660
+ }
4661
+ } catch (e) {
4662
+ }
4663
+ }
4664
+ if (typeof dispatch === "function") {
4665
+ try {
4666
+ const res = await dispatch({
4041
4667
  model: this.model,
4042
4668
  messages: formattedMessages,
4043
4669
  max_tokens: this.maxTokens,
4044
4670
  temperature: this.temperature
4045
4671
  }, this.apiKey);
4046
- if ((_e = (_d = (_c = (_b = res == null ? void 0 : res.response) == null ? void 0 : _b.choices) == null ? void 0 : _c[0]) == null ? void 0 : _d.message) == null ? void 0 : _e.content) {
4047
- return res.response.choices[0].message.content;
4672
+ const content = extractContent(res == null ? void 0 : res.response);
4673
+ if (content !== void 0) {
4674
+ return content;
4048
4675
  }
4676
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch returned empty content for model: ${this.model}`);
4677
+ } catch (dispatchErr) {
4678
+ throw dispatchErr;
4049
4679
  }
4050
- } catch (e) {
4680
+ } else {
4681
+ 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.`);
4051
4682
  }
4052
4683
  }
4053
4684
  const { data } = await this.http.post(path2, payload);
4054
- const extractPath = (_f = this.opts.responseExtractPath) != null ? _f : "choices[0].message.content";
4055
- const result = resolvePath(data, extractPath);
4685
+ const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
4686
+ const result = (_c = resolvePath(data, extractPath)) != null ? _c : extractContent(data);
4056
4687
  if (result === void 0) {
4057
4688
  throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
4058
4689
  }
@@ -4065,7 +4696,7 @@ ${context != null ? context : "None"}` },
4065
4696
  */
4066
4697
  chatStream(messages, context) {
4067
4698
  return __asyncGenerator(this, null, function* () {
4068
- var _a2, _b, _c, _d, _e, _f, _g2;
4699
+ var _a2, _b, _c, _d, _e;
4069
4700
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
4070
4701
  const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
4071
4702
  const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
@@ -4099,10 +4730,22 @@ ${context != null ? context : "None"}` },
4099
4730
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4100
4731
  let streamBody = null;
4101
4732
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4102
- try {
4103
- const _g3 = globalThis;
4104
- if (typeof _g3.__retrivoraDispatchChat === "function") {
4105
- const res = yield new __await(_g3.__retrivoraDispatchChat({
4733
+ const _g2 = globalThis;
4734
+ let dispatch = _g2.__retrivoraDispatchChat;
4735
+ if (typeof dispatch !== "function") {
4736
+ try {
4737
+ const gateway = yield new __await(Promise.resolve().then(() => (init_router(), router_exports)));
4738
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4739
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4740
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4741
+ dispatch = gateway.dispatchChatCompletion;
4742
+ }
4743
+ } catch (e) {
4744
+ }
4745
+ }
4746
+ if (typeof dispatch === "function") {
4747
+ try {
4748
+ const res = yield new __await(dispatch({
4106
4749
  model: this.model,
4107
4750
  messages: formattedMessages,
4108
4751
  max_tokens: this.maxTokens,
@@ -4111,12 +4754,19 @@ ${context != null ? context : "None"}` },
4111
4754
  }, this.apiKey));
4112
4755
  if (res == null ? void 0 : res.stream) {
4113
4756
  streamBody = res.stream;
4114
- } else if ((_f = (_e = (_d = (_c = res == null ? void 0 : res.response) == null ? void 0 : _c.choices) == null ? void 0 : _d[0]) == null ? void 0 : _e.message) == null ? void 0 : _f.content) {
4115
- yield res.response.choices[0].message.content;
4116
- return;
4757
+ } else {
4758
+ const content = extractContent(res == null ? void 0 : res.response);
4759
+ if (content !== void 0) {
4760
+ yield content;
4761
+ return;
4762
+ }
4763
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch stream returned empty response for model: ${this.model}`);
4117
4764
  }
4765
+ } catch (dispatchErr) {
4766
+ throw dispatchErr;
4118
4767
  }
4119
- } catch (e) {
4768
+ } else {
4769
+ 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.`);
4120
4770
  }
4121
4771
  }
4122
4772
  if (!streamBody) {
@@ -4143,14 +4793,14 @@ ${context != null ? context : "None"}` },
4143
4793
  if (done) break;
4144
4794
  buffer += decoder.decode(value, { stream: true });
4145
4795
  const lines = buffer.split("\n");
4146
- buffer = (_g2 = lines.pop()) != null ? _g2 : "";
4796
+ buffer = (_c = lines.pop()) != null ? _c : "";
4147
4797
  for (const line of lines) {
4148
4798
  const trimmed = line.trim();
4149
4799
  if (!trimmed || trimmed === "data: [DONE]") continue;
4150
4800
  if (!trimmed.startsWith("data:")) continue;
4151
4801
  try {
4152
4802
  const json = JSON.parse(trimmed.slice(5).trim());
4153
- const text = resolvePath(json, extractPath);
4803
+ const text = (_d = resolvePath(json, extractPath)) != null ? _d : extractContent(json);
4154
4804
  if (text && typeof text === "string") yield text;
4155
4805
  } catch (e) {
4156
4806
  }
@@ -4160,7 +4810,7 @@ ${context != null ? context : "None"}` },
4160
4810
  const jsonStr = buffer.replace(/^data:\s*/, "").trim();
4161
4811
  try {
4162
4812
  const json = JSON.parse(jsonStr);
4163
- const text = resolvePath(json, extractPath);
4813
+ const text = (_e = resolvePath(json, extractPath)) != null ? _e : extractContent(json);
4164
4814
  if (text && typeof text === "string") yield text;
4165
4815
  } catch (e) {
4166
4816
  }
@@ -4187,18 +4837,34 @@ ${context != null ? context : "None"}` },
4187
4837
  }
4188
4838
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4189
4839
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4190
- try {
4191
- const _g2 = globalThis;
4192
- if (typeof _g2.__retrivoraDispatchEmbedding === "function") {
4193
- const res = await _g2.__retrivoraDispatchEmbedding({
4840
+ const _g2 = globalThis;
4841
+ let dispatch = _g2.__retrivoraDispatchEmbedding;
4842
+ if (typeof dispatch !== "function") {
4843
+ try {
4844
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4845
+ if (gateway == null ? void 0 : gateway.dispatchEmbedding) {
4846
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4847
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4848
+ dispatch = gateway.dispatchEmbedding;
4849
+ }
4850
+ } catch (e) {
4851
+ }
4852
+ }
4853
+ if (typeof dispatch === "function") {
4854
+ try {
4855
+ const res = await dispatch({
4194
4856
  model: this.model,
4195
4857
  input: text
4196
4858
  }, this.apiKey);
4197
4859
  if ((_c = (_b = res == null ? void 0 : res.data) == null ? void 0 : _b[0]) == null ? void 0 : _c.embedding) {
4198
4860
  return res.data[0].embedding;
4199
4861
  }
4862
+ throw new Error(`[UniversalLLMAdapter] In-process embedding dispatch returned invalid vector for model: ${this.model}`);
4863
+ } catch (dispatchErr) {
4864
+ throw dispatchErr;
4200
4865
  }
4201
- } catch (e) {
4866
+ } else {
4867
+ 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.`);
4202
4868
  }
4203
4869
  }
4204
4870
  const { data } = await this.http.post(path2, payload);
@@ -4791,7 +5457,8 @@ var Reranker = class {
4791
5457
  return matches.sort((a, b) => b.score - a.score).slice(0, limit);
4792
5458
  }
4793
5459
  const scoredMatches = matches.map((match) => {
4794
- const contentLower = match.content.toLowerCase();
5460
+ var _a2;
5461
+ const contentLower = ((_a2 = match == null ? void 0 : match.content) != null ? _a2 : "").toLowerCase();
4795
5462
  let keywordScore = 0;
4796
5463
  keywords.forEach((keyword) => {
4797
5464
  if (contentLower.includes(keyword)) {
@@ -4812,7 +5479,10 @@ var Reranker = class {
4812
5479
  [{ role: "user", content: `Query: "${query}"
4813
5480
 
4814
5481
  Documents:
4815
- ${topN.map((m, i) => `[${i}] ${m.content.replace(/\n/g, " ")}`).join("\n")}` }],
5482
+ ${topN.map((m, i) => {
5483
+ var _a2;
5484
+ return `[${i}] ${((_a2 = m == null ? void 0 : m.content) != null ? _a2 : "").replace(/\n/g, " ")}`;
5485
+ }).join("\n")}` }],
4816
5486
  "",
4817
5487
  {
4818
5488
  systemPrompt: 'You are a relevance ranking expert. Given the user query and a list of retrieved document chunks, rank the chunks by relevance to the query. Return the result as a comma-separated list of document indices in order of relevance, from most relevant to least relevant. Use the indices provided in brackets like [0], [1], etc. Only return the indices (e.g., "2,0,1"), nothing else. Do not include brackets in the output.',
@@ -5983,10 +6653,10 @@ Return ONLY 'vector', 'graph', or 'both'. No explanation.`;
5983
6653
  "",
5984
6654
  { temperature: 0, maxTokens: 10 }
5985
6655
  );
5986
- const cleanResponse = response.trim().toLowerCase();
5987
- if (cleanResponse.includes("vector")) return "vector";
5988
- if (cleanResponse.includes("graph")) return "graph";
6656
+ const cleanResponse = (response != null ? response : "").trim().toLowerCase();
5989
6657
  if (cleanResponse.includes("both")) return "both";
6658
+ if (cleanResponse.includes("graph")) return "graph";
6659
+ if (cleanResponse.includes("vector")) return "vector";
5990
6660
  } catch (error) {
5991
6661
  console.warn("[QueryProcessor] LLM strategy classification failed, falling back to keywords:", error);
5992
6662
  }
@@ -6160,7 +6830,10 @@ var IntentClassifier = class {
6160
6830
  hasCategoricalFields = catKeys.size > 0;
6161
6831
  numericFieldCount = numericKeys.size;
6162
6832
  categoricalFieldCount = catKeys.size;
6163
- if (productKeyMatches >= 2 || docs.some((d) => d.content.toLowerCase().includes("price") || d.content.toLowerCase().includes("brand"))) {
6833
+ if (productKeyMatches >= 2 || docs.some((d) => {
6834
+ var _a2, _b;
6835
+ return ((_a2 = d == null ? void 0 : d.content) != null ? _a2 : "").toLowerCase().includes("price") || ((_b = d == null ? void 0 : d.content) != null ? _b : "").toLowerCase().includes("brand");
6836
+ })) {
6164
6837
  isProductLike = true;
6165
6838
  }
6166
6839
  }
@@ -6440,7 +7113,10 @@ var TextRendererStrategy = class {
6440
7113
  return { type: "text", title, data: { content: data } };
6441
7114
  }
6442
7115
  const docs = Array.isArray(data) ? data : [];
6443
- const text = docs.map((d) => d.content).join("\n\n");
7116
+ const text = docs.map((d) => {
7117
+ var _a2;
7118
+ return (_a2 = d == null ? void 0 : d.content) != null ? _a2 : "";
7119
+ }).join("\n\n");
6444
7120
  return { type: "text", title, data: { content: text || "No detailed content available." } };
6445
7121
  }
6446
7122
  };
@@ -6697,6 +7373,19 @@ var UITransformer = class _UITransformer {
6697
7373
  if (!retrievedData || retrievedData.length === 0) {
6698
7374
  return this.createTextResponse("No data available", "No relevant data found for your query.");
6699
7375
  }
7376
+ console.log("[UITransformer.transform] Processing retrievedData:", {
7377
+ userQuery,
7378
+ retrievedCount: retrievedData.length,
7379
+ sample: retrievedData.slice(0, 2).map((item) => {
7380
+ var _a3;
7381
+ return {
7382
+ id: item == null ? void 0 : item.id,
7383
+ contentType: typeof (item == null ? void 0 : item.content),
7384
+ contentSnippet: String((_a3 = item == null ? void 0 : item.content) != null ? _a3 : "").substring(0, 150),
7385
+ metadataKeys: Object.keys((item == null ? void 0 : item.metadata) || {})
7386
+ };
7387
+ })
7388
+ });
6700
7389
  const resolvedIntent = intent != null ? intent : this.detectIntentHeuristic(userQuery);
6701
7390
  const filteredData = resolvedIntent.filterInStockOnly ? retrievedData.filter((item) => this.determineStockStatus(item)) : retrievedData;
6702
7391
  const profile = this.profileData(filteredData);
@@ -7037,7 +7726,7 @@ ${schemaProfileText}` : ""}`;
7037
7726
  }
7038
7727
  // ─── Transform Helpers ────────────────────────────────────────────────────
7039
7728
  static transformToProductCarousel(data, config, trainedSchema) {
7040
- const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null).slice(0, 15);
7729
+ const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null);
7041
7730
  return {
7042
7731
  type: "product_carousel",
7043
7732
  title: "Recommended Products",
@@ -7186,7 +7875,10 @@ ${schemaProfileText}` : ""}`;
7186
7875
  type: "radar_chart",
7187
7876
  title: "Product Comparison",
7188
7877
  description: `Comparing ${data.length} items across ${radarData.length} attributes`,
7189
- data: radarData.length > 0 ? radarData : data.map((d) => ({ attribute: d.content.substring(0, 40) }))
7878
+ data: radarData.length > 0 ? radarData : data.map((d) => {
7879
+ var _a2;
7880
+ return { attribute: ((_a2 = d == null ? void 0 : d.content) != null ? _a2 : "").substring(0, 40) };
7881
+ })
7190
7882
  };
7191
7883
  }
7192
7884
  static transformToTable(data, query = "") {
@@ -7203,7 +7895,10 @@ ${schemaProfileText}` : ""}`;
7203
7895
  static transformToText(data) {
7204
7896
  return this.createTextResponse(
7205
7897
  "Retrieved Context",
7206
- data.map((item) => item.content).join("\n\n"),
7898
+ data.map((item) => {
7899
+ var _a2;
7900
+ return (_a2 = item == null ? void 0 : item.content) != null ? _a2 : "";
7901
+ }).join("\n\n"),
7207
7902
  `Found ${data.length} relevant results`
7208
7903
  );
7209
7904
  }
@@ -7364,6 +8059,7 @@ ${schemaProfileText}` : ""}`;
7364
8059
  return productTerms && productAction && !nonProductEntityTerms;
7365
8060
  }
7366
8061
  static isProductData(item) {
8062
+ if (!item) return false;
7367
8063
  const content = (item.content || "").toLowerCase();
7368
8064
  const productKeywords = [
7369
8065
  "product",
@@ -7410,7 +8106,8 @@ ${schemaProfileText}` : ""}`;
7410
8106
  return fieldCount.size > 2;
7411
8107
  }
7412
8108
  static profileData(data) {
7413
- const records = data.map((item) => {
8109
+ const records = (data || []).filter((item) => Boolean(item && typeof item === "object")).map((item) => {
8110
+ var _a2, _b;
7414
8111
  const fields2 = {};
7415
8112
  Object.entries(item.metadata || {}).forEach(([key, value]) => {
7416
8113
  const primitive = this.toPrimitive(value);
@@ -7419,8 +8116,8 @@ ${schemaProfileText}` : ""}`;
7419
8116
  if (!fields2.content && item.content) fields2.content = item.content.substring(0, 500);
7420
8117
  return {
7421
8118
  id: item.id,
7422
- content: item.content,
7423
- score: item.score,
8119
+ content: (_a2 = item.content) != null ? _a2 : "",
8120
+ score: (_b = item.score) != null ? _b : 0,
7424
8121
  fields: fields2,
7425
8122
  source: item
7426
8123
  };
@@ -7622,12 +8319,12 @@ ${schemaProfileText}` : ""}`;
7622
8319
  }
7623
8320
  static extractTimeSeriesData(data) {
7624
8321
  return data.map((item) => {
7625
- var _a2, _b, _c, _d, _e;
8322
+ var _a2, _b, _c, _d, _e, _f;
7626
8323
  const meta = item.metadata || {};
7627
8324
  return {
7628
8325
  timestamp: (_b = (_a2 = meta.timestamp) != null ? _a2 : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
7629
8326
  value: (_d = (_c = meta.value) != null ? _c : item.score) != null ? _d : 0,
7630
- label: (_e = meta.label) != null ? _e : item.content.substring(0, 50)
8327
+ label: (_f = meta.label) != null ? _f : ((_e = item == null ? void 0 : item.content) != null ? _e : "").substring(0, 50)
7631
8328
  };
7632
8329
  });
7633
8330
  }
@@ -7741,7 +8438,8 @@ ${schemaProfileText}` : ""}`;
7741
8438
  }, query.includes(normalizedField) ? 3 : 0);
7742
8439
  }
7743
8440
  static resolveTableCellValue(item, column) {
7744
- if (column === "Content") return item.content.substring(0, 100);
8441
+ var _a2, _b, _c;
8442
+ if (column === "Content") return ((_a2 = item == null ? void 0 : item.content) != null ? _a2 : "").substring(0, 100);
7745
8443
  const meta = item.metadata || {};
7746
8444
  const normalizedColumn = this.normalizeComparableField(column);
7747
8445
  const exactMetadata = Object.entries(meta).find(
@@ -7752,9 +8450,9 @@ ${schemaProfileText}` : ""}`;
7752
8450
  }
7753
8451
  const aliasValue = this.resolveAliasedTableCell(meta, column);
7754
8452
  if (aliasValue !== void 0) return this.toDisplayValue(aliasValue);
7755
- const contentValue = this.extractContentFieldValue(item.content, column);
8453
+ const contentValue = this.extractContentFieldValue((_b = item == null ? void 0 : item.content) != null ? _b : "", column);
7756
8454
  if (contentValue !== null) return contentValue;
7757
- const aliasContentValue = this.extractAliasedContentFieldValue(item.content, column);
8455
+ const aliasContentValue = this.extractAliasedContentFieldValue((_c = item == null ? void 0 : item.content) != null ? _c : "", column);
7758
8456
  return aliasContentValue != null ? aliasContentValue : "";
7759
8457
  }
7760
8458
  static resolveAliasedTableCell(meta, column) {
@@ -7804,6 +8502,7 @@ ${schemaProfileText}` : ""}`;
7804
8502
  return { inStockCount: inStock, outOfStockCount: outOfStock };
7805
8503
  }
7806
8504
  static determineStockStatus(item) {
8505
+ if (!item) return true;
7807
8506
  const meta = item.metadata || {};
7808
8507
  const stockValue = resolveMetadataValue(meta, "stock");
7809
8508
  if (stockValue !== void 0) {
@@ -7849,35 +8548,64 @@ ${schemaProfileText}` : ""}`;
7849
8548
  return resolveMetadataValue(meta, uiKey);
7850
8549
  }
7851
8550
  static extractProductInfo(item, config, trainedSchema) {
7852
- var _a2;
8551
+ var _a2, _b;
8552
+ if (!item) return null;
7853
8553
  const meta = item.metadata || {};
8554
+ const content = item.content || "";
7854
8555
  const name = this.getDynamicVal(meta, "name", config, trainedSchema);
7855
8556
  const price = this.getDynamicVal(meta, "price", config, trainedSchema);
7856
8557
  const brand = this.getDynamicVal(meta, "brand", config, trainedSchema);
7857
8558
  const description = this.cleanProductDescription(
7858
- (_a2 = this.extractProductDescriptionFromContent(item.content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
8559
+ (_a2 = this.extractProductDescriptionFromContent(content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
7859
8560
  );
7860
8561
  if (name || this.isProductData(item)) {
7861
8562
  let finalName = name ? String(name) : void 0;
8563
+ if (!finalName && content) {
8564
+ const nameMatch = content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
8565
+ finalName = nameMatch ? nameMatch[1].trim() : (_b = content.split("\n")[0]) == null ? void 0 : _b.substring(0, 60);
8566
+ }
7862
8567
  if (!finalName) {
7863
- const nameMatch = item.content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
7864
- finalName = nameMatch ? nameMatch[1].trim() : item.content.split("\n")[0].substring(0, 60);
8568
+ console.warn(
8569
+ `[UITransformer] Unable to read product name from metadata or content for item ${item.id}. Defaulting to 'Unnamed Product'.`,
8570
+ { metadataKeys: Object.keys(meta), contentLength: content.length }
8571
+ );
7865
8572
  }
7866
8573
  let finalPrice = typeof price === "number" || typeof price === "string" ? price : void 0;
7867
- if (!finalPrice) {
7868
- const priceMatch = item.content.match(/(?:Price|Cost):\s*\$?([\d,.]+)/i) || item.content.match(/\$\s*([\d,.]+)/);
8574
+ if (!finalPrice && content) {
8575
+ const priceMatch = content.match(/(?:Price|Cost):\s*\$?([\d,.]+)/i) || content.match(/\$\s*([\d,.]+)/);
7869
8576
  if (priceMatch) finalPrice = priceMatch[1].replace(/,/g, "");
7870
8577
  }
8578
+ if (finalPrice === void 0) {
8579
+ console.warn(
8580
+ `[UITransformer] Unable to read product price from metadata or content for item ${item.id}.`,
8581
+ { metadataKeys: Object.keys(meta), contentSnippet: content.substring(0, 100) }
8582
+ );
8583
+ }
7871
8584
  const imageValue = this.getDynamicVal(meta, "image", config, trainedSchema);
8585
+ if (!imageValue) {
8586
+ console.debug(
8587
+ `[UITransformer] Unable to read product image URL from metadata for item ${item.id}.`
8588
+ );
8589
+ }
8590
+ if (!description) {
8591
+ console.debug(
8592
+ `[UITransformer] Unable to read product description from metadata or content for item ${item.id}.`
8593
+ );
8594
+ }
7872
8595
  return {
7873
8596
  id: item.id,
7874
- name: finalName,
8597
+ name: finalName || "Unnamed Product",
7875
8598
  price: finalPrice,
7876
8599
  image: typeof imageValue === "string" ? imageValue : void 0,
7877
8600
  brand: brand ? String(brand) : void 0,
7878
8601
  description,
7879
8602
  inStock: this.determineStockStatus(item)
7880
8603
  };
8604
+ } else {
8605
+ console.warn(
8606
+ `[UITransformer] Item ${item.id} skipped: unable to read name or identify as product data from metadata/content.`,
8607
+ { metadataKeys: Object.keys(meta), contentSnippet: content.substring(0, 100) }
8608
+ );
7881
8609
  }
7882
8610
  return null;
7883
8611
  }
@@ -7962,13 +8690,13 @@ RULES:
7962
8690
  5. If no relevant data is found, return text: "I cannot answer this question based on the available information."`;
7963
8691
  }
7964
8692
  static buildContextSummary(sources, maxChars = 6e3) {
7965
- const items = sources.map((s, i) => {
8693
+ const items = (sources || []).filter(Boolean).map((s, i) => {
7966
8694
  var _a2, _b, _c, _d;
7967
8695
  return {
7968
8696
  index: i + 1,
7969
- content: (_b = (_a2 = s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
7970
- metadata: (_c = s.metadata) != null ? _c : {},
7971
- score: (_d = s.score) != null ? _d : 0
8697
+ content: (_b = (_a2 = s == null ? void 0 : s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
8698
+ metadata: (_c = s == null ? void 0 : s.metadata) != null ? _c : {},
8699
+ score: (_d = s == null ? void 0 : s.score) != null ? _d : 0
7972
8700
  };
7973
8701
  });
7974
8702
  const full = JSON.stringify(items, null, 2);
@@ -8492,7 +9220,7 @@ ${m.content}`).join("\n\n---\n\n");
8492
9220
  */
8493
9221
  askStreamInternal(_0) {
8494
9222
  return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
8495
- var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C;
9223
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B;
8496
9224
  yield new __await(this.initialize());
8497
9225
  const ns = formatNamespace(namespace != null ? namespace : this.config.projectId);
8498
9226
  const topK = (_b = (_a2 = this.config.rag) == null ? void 0 : _a2.topK) != null ? _b : 5;
@@ -8535,40 +9263,65 @@ ${m.content}`).join("\n\n---\n\n");
8535
9263
  const graphData = (strategyResult === "graph" || strategyResult === "both") && this.graphDB && ((_l = this.config.rag) == null ? void 0 : _l.useGraphRetrieval) ? yield new __await(this.graphDB.query(searchQuery)) : void 0;
8536
9264
  const hasMetadataFilter = filter.metadata && Object.keys(filter.metadata).length > 0;
8537
9265
  const hasNumericPredicates = Array.isArray(filter.__numericPredicates) && filter.__numericPredicates.length > 0;
8538
- const wantsExhaustiveList = hasNumericPredicates || hasMetadataFilter || /\b(list|all|show|provide|give|get|browse|find|search|display)\b/i.test(question);
8539
- const retrievalLimit = wantsExhaustiveList ? Math.max(topK * 20, 100) : topK * 2;
8540
- const rawSources = (strategyResult === "vector" || strategyResult === "both") && queryVector && queryVector.length > 0 ? yield new __await(this.vectorDB.query(queryVector, retrievalLimit, ns, filter)) : [];
9266
+ const wantsExhaustiveList = true;
9267
+ const retrievalLimit = Math.max(topK * 50, 1e3);
9268
+ const rawSources = ((strategyResult === "vector" || strategyResult === "both") && queryVector && queryVector.length > 0 ? yield new __await(this.vectorDB.query(queryVector, retrievalLimit, ns, filter)) : []).filter((s) => Boolean(s && typeof s === "object"));
9269
+ console.log("[Pipeline] Raw vectorDB.query response:", {
9270
+ rawCount: rawSources.length,
9271
+ sample: rawSources.slice(0, 2).map((s) => {
9272
+ var _a3;
9273
+ return {
9274
+ id: s == null ? void 0 : s.id,
9275
+ score: s == null ? void 0 : s.score,
9276
+ contentType: typeof (s == null ? void 0 : s.content),
9277
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9278
+ metadataKeys: Object.keys((s == null ? void 0 : s.metadata) || {})
9279
+ };
9280
+ })
9281
+ });
8541
9282
  const retrieveEnd = performance.now();
8542
9283
  const embedMs = retrieveEnd - embedStart;
8543
9284
  const retrieveMs = retrieveEnd - embedStart;
8544
9285
  const rerankStart = performance.now();
8545
- const structuredSources = this.applyStructuredFilters(rawSources, filter);
8546
- let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => m.score >= scoreThreshold);
8547
- const rerankLimit = wantsExhaustiveList ? retrievalLimit : topK;
9286
+ const structuredSources = this.applyStructuredFilters(rawSources, filter).filter((s) => Boolean(s && typeof s === "object"));
9287
+ let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => {
9288
+ var _a3;
9289
+ return ((_a3 = m == null ? void 0 : m.score) != null ? _a3 : 0) >= scoreThreshold;
9290
+ });
9291
+ const rerankLimit = Math.max(retrievalLimit, fullSources.length);
8548
9292
  const useReranking = arch !== "naive" && (arch === "retrieve-and-rerank" || ((_m = this.config.rag) == null ? void 0 : _m.useReranking));
8549
9293
  if (!hasNumericPredicates && useReranking) {
8550
- fullSources = yield new __await(this.reranker.rerank(fullSources, question, rerankLimit));
8551
- } else if (!wantsExhaustiveList) {
8552
- fullSources = fullSources.slice(0, topK);
9294
+ fullSources = (yield new __await(this.reranker.rerank(fullSources, question, rerankLimit))).filter((s) => Boolean(s && typeof s === "object"));
8553
9295
  }
8554
9296
  const rerankMs = performance.now() - rerankStart;
8555
- let context = fullSources.length ? fullSources.map((m, i) => {
9297
+ const totalCount = fullSources.length;
9298
+ const promptSources = fullSources.slice(0, 15);
9299
+ let context = promptSources.length ? `[SEARCH SUMMARY: Found ${totalCount} matching record(s) out of ${rawSources.length} total resources searched in database. Context includes top ${promptSources.length} relevant records]
9300
+
9301
+ ` + promptSources.map((m, i) => {
8556
9302
  var _a3;
8557
9303
  return `[Source ${i + 1}]
8558
9304
  ${(_a3 = m == null ? void 0 : m.content) != null ? _a3 : ""}`;
8559
9305
  }).join("\n\n---\n\n") : "No relevant context found.";
8560
- let displayCount = 15;
8561
- if (hasMetadataFilter) {
8562
- displayCount = fullSources.length;
8563
- } else {
8564
- const baseThreshold = Math.max(scoreThreshold, 0.4);
8565
- const highlyRelevant = fullSources.filter((m) => m.score >= baseThreshold);
8566
- displayCount = Math.max(highlyRelevant.length, topK);
8567
- if (displayCount > 15) {
8568
- displayCount = 15;
8569
- }
8570
- }
8571
- const sources = [...fullSources].sort((a, b) => b.score - a.score).slice(0, displayCount);
9306
+ const sources = [...fullSources].filter((s) => Boolean(s && typeof s === "object")).sort((a, b) => {
9307
+ var _a3, _b2;
9308
+ return ((_a3 = b == null ? void 0 : b.score) != null ? _a3 : 0) - ((_b2 = a == null ? void 0 : a.score) != null ? _b2 : 0);
9309
+ });
9310
+ console.log("[Pipeline] Final sources for prompt & UI:", {
9311
+ count: sources.length,
9312
+ totalRawCount: rawSources.length,
9313
+ sources: sources.slice(0, 10).map((s, idx) => {
9314
+ var _a3;
9315
+ return {
9316
+ rank: idx + 1,
9317
+ id: s == null ? void 0 : s.id,
9318
+ score: s == null ? void 0 : s.score,
9319
+ contentType: typeof (s == null ? void 0 : s.content),
9320
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9321
+ metadata: s == null ? void 0 : s.metadata
9322
+ };
9323
+ })
9324
+ });
8572
9325
  if (graphData && graphData.nodes.length > 0) {
8573
9326
  const graphContext = graphData.nodes.map(
8574
9327
  (n) => `Entity: ${n.label} (${n.id})${n.properties ? " - " + JSON.stringify(n.properties) : ""}`
@@ -8594,18 +9347,18 @@ ${context}`;
8594
9347
  }
8595
9348
  yield {
8596
9349
  reply: "",
8597
- sources: sources.map((s) => {
8598
- var _a3;
9350
+ sources: (sources || []).filter((s) => Boolean(s && typeof s === "object")).map((s) => {
9351
+ var _a3, _b2, _c2;
8599
9352
  return {
8600
9353
  id: s.id,
8601
- score: s.score,
8602
- content: s.content,
8603
- metadata: (_a3 = s.metadata) != null ? _a3 : {},
9354
+ score: (_a3 = s.score) != null ? _a3 : 0,
9355
+ content: (_b2 = s == null ? void 0 : s.content) != null ? _b2 : "",
9356
+ metadata: (_c2 = s == null ? void 0 : s.metadata) != null ? _c2 : {},
8604
9357
  namespace: ns
8605
9358
  };
8606
9359
  })
8607
9360
  };
8608
- const allMetadataKeys = Array.from(new Set(sources.flatMap((s) => Object.keys(s.metadata || {}))));
9361
+ const allMetadataKeys = Array.from(new Set(sources.filter(Boolean).flatMap((s) => Object.keys((s == null ? void 0 : s.metadata) || {}))));
8609
9362
  const cachedSchema = allMetadataKeys.length > 0 ? SchemaMapper.getCached(ns, allMetadataKeys) : void 0;
8610
9363
  if (allMetadataKeys.length > 0 && !cachedSchema) {
8611
9364
  SchemaMapper.train(this.llmProvider, ns, allMetadataKeys).catch(() => {
@@ -8757,7 +9510,7 @@ ${context}`;
8757
9510
  }
8758
9511
  yield fullReply;
8759
9512
  }
8760
- const runHallucination = ((_w = this.config.llm.options) == null ? void 0 : _w.hallucinationScoring) === true || this.config.llm.provider !== "ollama" && ((_x = this.config.llm.options) == null ? void 0 : _x.hallucinationScoring) !== false;
9513
+ const runHallucination = ((_w = this.config.llm.options) == null ? void 0 : _w.hallucinationScoring) === true;
8761
9514
  if (runHallucination) {
8762
9515
  hallucinationScoringPromise = scoreHallucination(this.llmProvider, fullReply, context).catch(() => void 0);
8763
9516
  }
@@ -8766,7 +9519,7 @@ ${context}`;
8766
9519
  const latency = {
8767
9520
  embedMs: Math.round(embedMs),
8768
9521
  retrieveMs: Math.round(retrieveMs),
8769
- rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_y = this.config.rag) == null ? void 0 : _y.useReranking)) ? Math.round(rerankMs) : void 0,
9522
+ rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_x = this.config.rag) == null ? void 0 : _x.useReranking)) ? Math.round(rerankMs) : void 0,
8770
9523
  generateMs: Math.round(generateMs),
8771
9524
  totalMs: Math.round(totalMs)
8772
9525
  };
@@ -8779,7 +9532,7 @@ ${context}`;
8779
9532
  totalTokens: promptTokens + completionTokens,
8780
9533
  estimatedCostUsd: estimateCostUsd(promptTokens, completionTokens, this.config.llm.model)
8781
9534
  };
8782
- const awaitHallucination = ((_z = this.config.llm.options) == null ? void 0 : _z.awaitHallucination) === true;
9535
+ const awaitHallucination = ((_y = this.config.llm.options) == null ? void 0 : _y.awaitHallucination) === true;
8783
9536
  const [uiTransformation, hallucinationResult] = yield new __await(Promise.all([
8784
9537
  uiTransformationPromise,
8785
9538
  awaitHallucination ? hallucinationScoringPromise : Promise.resolve(void 0)
@@ -8808,10 +9561,10 @@ ${context}`;
8808
9561
  hallucinationReason: hScore.reason
8809
9562
  } : {});
8810
9563
  const trace = buildTrace(hallucinationResult);
8811
- const isTelemetryActive = (_B = (_A = this.config.telemetry) == null ? void 0 : _A.enabled) != null ? _B : Boolean(this.config.licenseKey);
9564
+ const isTelemetryActive = (_A = (_z = this.config.telemetry) == null ? void 0 : _z.enabled) != null ? _A : Boolean(this.config.licenseKey);
8812
9565
  if (isTelemetryActive) {
8813
9566
  const defaultUrl = process.env.NODE_ENV === "development" && !process.env.TELEMETRY_URL && !process.env.NEXT_PUBLIC_TELEMETRY_URL ? "http://localhost:3001/api/telemetry" : "https://retrivora.com/api/telemetry";
8814
- const telemetryUrl = ((_C = this.config.telemetry) == null ? void 0 : _C.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
9567
+ const telemetryUrl = ((_B = this.config.telemetry) == null ? void 0 : _B.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
8815
9568
  const absoluteUrl = telemetryUrl.startsWith("http") ? telemetryUrl : (process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${process.env.PORT || 3e3}`) + telemetryUrl;
8816
9569
  (async () => {
8817
9570
  try {
@@ -8870,9 +9623,8 @@ ${context}`;
8870
9623
  { visualizationHint: "product_browse", recommendedChart: "text", filterInStockOnly: false, wantsExplicitTable: false, isTemporal: false, isComparison: false, language: "en" }
8871
9624
  );
8872
9625
  }
8873
- const isLocalProvider = this.config.llm.provider === "ollama";
8874
- const disableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.disableLlmUiTransform) === true;
8875
- if (forceDeterministic || isLocalProvider || disableLlmUiTransform) {
9626
+ const enableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.enableLlmUiTransform) === true;
9627
+ if (forceDeterministic || !enableLlmUiTransform) {
8876
9628
  return UITransformer.transform(question, sources, this.config, cachedSchema);
8877
9629
  }
8878
9630
  try {
@@ -8897,6 +9649,8 @@ ${context}`;
8897
9649
  });
8898
9650
  }
8899
9651
  resolveNumericPredicateValue(source, predicate) {
9652
+ var _a2;
9653
+ if (!source) return null;
8900
9654
  const meta = source.metadata || {};
8901
9655
  const field = predicate.field;
8902
9656
  const entries = Object.entries(meta).filter(([, value]) => value !== null && value !== void 0 && typeof value !== "object");
@@ -8908,7 +9662,7 @@ ${context}`;
8908
9662
  const value = this.toFiniteNumber(Array.isArray(fuzzy) ? fuzzy[1] : fuzzy.value);
8909
9663
  if (value !== null) return value;
8910
9664
  }
8911
- const contentValue = this.extractNumericValueFromContent(source.content, field);
9665
+ const contentValue = this.extractNumericValueFromContent((_a2 = source.content) != null ? _a2 : "", field);
8912
9666
  if (contentValue !== null) return contentValue;
8913
9667
  }
8914
9668
  for (const [key, value] of entries) {
@@ -8919,6 +9673,7 @@ ${context}`;
8919
9673
  return null;
8920
9674
  }
8921
9675
  extractNumericValueFromContent(content, field) {
9676
+ if (!content || typeof content !== "string") return null;
8922
9677
  const escapedWords = field.split(/\s+|_+|-+/).filter(Boolean).map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
8923
9678
  if (escapedWords.length === 0) return null;
8924
9679
  const pattern = new RegExp(`(?:${escapedWords.join("[\\\\s_:-]*")})\\s*[:\\-\u2013]?\\s*([\\d,]+(?:\\.\\d+)?)`, "i");
@@ -9004,6 +9759,20 @@ ${context}`;
9004
9759
  resolvedSources.push(source);
9005
9760
  }
9006
9761
  }
9762
+ console.log("[Pipeline] retrieve() response:", {
9763
+ query,
9764
+ namespace: ns,
9765
+ count: resolvedSources.length,
9766
+ sample: resolvedSources.slice(0, 2).map((s) => {
9767
+ var _a3;
9768
+ return {
9769
+ id: s == null ? void 0 : s.id,
9770
+ score: s == null ? void 0 : s.score,
9771
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9772
+ metadata: s == null ? void 0 : s.metadata
9773
+ };
9774
+ })
9775
+ });
9007
9776
  return { sources: resolvedSources, graphData };
9008
9777
  }
9009
9778
  /** Rewrite the user query for better retrieval performance. */