@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.
@@ -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({
@@ -3876,6 +4479,17 @@ var LLM_PROFILES = {
3876
4479
  };
3877
4480
 
3878
4481
  // src/llm/providers/UniversalLLMAdapter.ts
4482
+ function extractContent(obj) {
4483
+ var _a2, _b, _c;
4484
+ if (!obj || typeof obj !== "object") return void 0;
4485
+ const choice = (_a2 = obj.choices) == null ? void 0 : _a2[0];
4486
+ if (!choice) return void 0;
4487
+ if (typeof ((_b = choice.message) == null ? void 0 : _b.content) === "string") return choice.message.content;
4488
+ if (typeof ((_c = choice.delta) == null ? void 0 : _c.content) === "string") return choice.delta.content;
4489
+ if (typeof choice.text === "string") return choice.text;
4490
+ if (typeof choice.content === "string") return choice.content;
4491
+ return void 0;
4492
+ }
3879
4493
  var UniversalLLMAdapter = class {
3880
4494
  constructor(config) {
3881
4495
  var _a2, _b, _c, _d, _e, _f, _g2, _h;
@@ -3907,7 +4521,7 @@ var UniversalLLMAdapter = class {
3907
4521
  });
3908
4522
  }
3909
4523
  async chat(messages, context) {
3910
- var _a2, _b, _c, _d, _e, _f;
4524
+ var _a2, _b, _c;
3911
4525
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3912
4526
  const formattedMessages = [
3913
4527
  { role: "system", content: `${this.systemPrompt}
@@ -3934,25 +4548,42 @@ ${context != null ? context : "None"}` },
3934
4548
  }
3935
4549
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
3936
4550
  if (isSelfHost || Boolean(process.env.VERCEL)) {
3937
- try {
3938
- const _g2 = globalThis;
3939
- if (typeof _g2.__retrivoraDispatchChat === "function") {
3940
- const res = await _g2.__retrivoraDispatchChat({
4551
+ const _g2 = globalThis;
4552
+ let dispatch = _g2.__retrivoraDispatchChat;
4553
+ if (typeof dispatch !== "function") {
4554
+ try {
4555
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4556
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4557
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4558
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4559
+ dispatch = gateway.dispatchChatCompletion;
4560
+ }
4561
+ } catch (e) {
4562
+ }
4563
+ }
4564
+ if (typeof dispatch === "function") {
4565
+ try {
4566
+ const res = await dispatch({
3941
4567
  model: this.model,
3942
4568
  messages: formattedMessages,
3943
4569
  max_tokens: this.maxTokens,
3944
4570
  temperature: this.temperature
3945
4571
  }, this.apiKey);
3946
- 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) {
3947
- return res.response.choices[0].message.content;
4572
+ const content = extractContent(res == null ? void 0 : res.response);
4573
+ if (content !== void 0) {
4574
+ return content;
3948
4575
  }
4576
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch returned empty content for model: ${this.model}`);
4577
+ } catch (dispatchErr) {
4578
+ throw dispatchErr;
3949
4579
  }
3950
- } catch (e) {
4580
+ } else {
4581
+ 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.`);
3951
4582
  }
3952
4583
  }
3953
4584
  const { data } = await this.http.post(path2, payload);
3954
- const extractPath = (_f = this.opts.responseExtractPath) != null ? _f : "choices[0].message.content";
3955
- const result = resolvePath(data, extractPath);
4585
+ const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
4586
+ const result = (_c = resolvePath(data, extractPath)) != null ? _c : extractContent(data);
3956
4587
  if (result === void 0) {
3957
4588
  throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
3958
4589
  }
@@ -3965,7 +4596,7 @@ ${context != null ? context : "None"}` },
3965
4596
  */
3966
4597
  chatStream(messages, context) {
3967
4598
  return __asyncGenerator(this, null, function* () {
3968
- var _a2, _b, _c, _d, _e, _f, _g2;
4599
+ var _a2, _b, _c, _d, _e;
3969
4600
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3970
4601
  const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
3971
4602
  const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
@@ -3999,10 +4630,22 @@ ${context != null ? context : "None"}` },
3999
4630
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4000
4631
  let streamBody = null;
4001
4632
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4002
- try {
4003
- const _g3 = globalThis;
4004
- if (typeof _g3.__retrivoraDispatchChat === "function") {
4005
- const res = yield new __await(_g3.__retrivoraDispatchChat({
4633
+ const _g2 = globalThis;
4634
+ let dispatch = _g2.__retrivoraDispatchChat;
4635
+ if (typeof dispatch !== "function") {
4636
+ try {
4637
+ const gateway = yield new __await(Promise.resolve().then(() => (init_router(), router_exports)));
4638
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4639
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4640
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4641
+ dispatch = gateway.dispatchChatCompletion;
4642
+ }
4643
+ } catch (e) {
4644
+ }
4645
+ }
4646
+ if (typeof dispatch === "function") {
4647
+ try {
4648
+ const res = yield new __await(dispatch({
4006
4649
  model: this.model,
4007
4650
  messages: formattedMessages,
4008
4651
  max_tokens: this.maxTokens,
@@ -4011,12 +4654,19 @@ ${context != null ? context : "None"}` },
4011
4654
  }, this.apiKey));
4012
4655
  if (res == null ? void 0 : res.stream) {
4013
4656
  streamBody = res.stream;
4014
- } 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) {
4015
- yield res.response.choices[0].message.content;
4016
- return;
4657
+ } else {
4658
+ const content = extractContent(res == null ? void 0 : res.response);
4659
+ if (content !== void 0) {
4660
+ yield content;
4661
+ return;
4662
+ }
4663
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch stream returned empty response for model: ${this.model}`);
4017
4664
  }
4665
+ } catch (dispatchErr) {
4666
+ throw dispatchErr;
4018
4667
  }
4019
- } catch (e) {
4668
+ } else {
4669
+ 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.`);
4020
4670
  }
4021
4671
  }
4022
4672
  if (!streamBody) {
@@ -4043,14 +4693,14 @@ ${context != null ? context : "None"}` },
4043
4693
  if (done) break;
4044
4694
  buffer += decoder.decode(value, { stream: true });
4045
4695
  const lines = buffer.split("\n");
4046
- buffer = (_g2 = lines.pop()) != null ? _g2 : "";
4696
+ buffer = (_c = lines.pop()) != null ? _c : "";
4047
4697
  for (const line of lines) {
4048
4698
  const trimmed = line.trim();
4049
4699
  if (!trimmed || trimmed === "data: [DONE]") continue;
4050
4700
  if (!trimmed.startsWith("data:")) continue;
4051
4701
  try {
4052
4702
  const json = JSON.parse(trimmed.slice(5).trim());
4053
- const text = resolvePath(json, extractPath);
4703
+ const text = (_d = resolvePath(json, extractPath)) != null ? _d : extractContent(json);
4054
4704
  if (text && typeof text === "string") yield text;
4055
4705
  } catch (e) {
4056
4706
  }
@@ -4060,7 +4710,7 @@ ${context != null ? context : "None"}` },
4060
4710
  const jsonStr = buffer.replace(/^data:\s*/, "").trim();
4061
4711
  try {
4062
4712
  const json = JSON.parse(jsonStr);
4063
- const text = resolvePath(json, extractPath);
4713
+ const text = (_e = resolvePath(json, extractPath)) != null ? _e : extractContent(json);
4064
4714
  if (text && typeof text === "string") yield text;
4065
4715
  } catch (e) {
4066
4716
  }
@@ -4087,18 +4737,34 @@ ${context != null ? context : "None"}` },
4087
4737
  }
4088
4738
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4089
4739
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4090
- try {
4091
- const _g2 = globalThis;
4092
- if (typeof _g2.__retrivoraDispatchEmbedding === "function") {
4093
- const res = await _g2.__retrivoraDispatchEmbedding({
4740
+ const _g2 = globalThis;
4741
+ let dispatch = _g2.__retrivoraDispatchEmbedding;
4742
+ if (typeof dispatch !== "function") {
4743
+ try {
4744
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4745
+ if (gateway == null ? void 0 : gateway.dispatchEmbedding) {
4746
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4747
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4748
+ dispatch = gateway.dispatchEmbedding;
4749
+ }
4750
+ } catch (e) {
4751
+ }
4752
+ }
4753
+ if (typeof dispatch === "function") {
4754
+ try {
4755
+ const res = await dispatch({
4094
4756
  model: this.model,
4095
4757
  input: text
4096
4758
  }, this.apiKey);
4097
4759
  if ((_c = (_b = res == null ? void 0 : res.data) == null ? void 0 : _b[0]) == null ? void 0 : _c.embedding) {
4098
4760
  return res.data[0].embedding;
4099
4761
  }
4762
+ throw new Error(`[UniversalLLMAdapter] In-process embedding dispatch returned invalid vector for model: ${this.model}`);
4763
+ } catch (dispatchErr) {
4764
+ throw dispatchErr;
4100
4765
  }
4101
- } catch (e) {
4766
+ } else {
4767
+ 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.`);
4102
4768
  }
4103
4769
  }
4104
4770
  const { data } = await this.http.post(path2, payload);
@@ -4691,7 +5357,8 @@ var Reranker = class {
4691
5357
  return matches.sort((a, b) => b.score - a.score).slice(0, limit);
4692
5358
  }
4693
5359
  const scoredMatches = matches.map((match) => {
4694
- const contentLower = match.content.toLowerCase();
5360
+ var _a2;
5361
+ const contentLower = ((_a2 = match == null ? void 0 : match.content) != null ? _a2 : "").toLowerCase();
4695
5362
  let keywordScore = 0;
4696
5363
  keywords.forEach((keyword) => {
4697
5364
  if (contentLower.includes(keyword)) {
@@ -4712,7 +5379,10 @@ var Reranker = class {
4712
5379
  [{ role: "user", content: `Query: "${query}"
4713
5380
 
4714
5381
  Documents:
4715
- ${topN.map((m, i) => `[${i}] ${m.content.replace(/\n/g, " ")}`).join("\n")}` }],
5382
+ ${topN.map((m, i) => {
5383
+ var _a2;
5384
+ return `[${i}] ${((_a2 = m == null ? void 0 : m.content) != null ? _a2 : "").replace(/\n/g, " ")}`;
5385
+ }).join("\n")}` }],
4716
5386
  "",
4717
5387
  {
4718
5388
  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.',
@@ -5877,10 +6547,10 @@ Return ONLY 'vector', 'graph', or 'both'. No explanation.`;
5877
6547
  "",
5878
6548
  { temperature: 0, maxTokens: 10 }
5879
6549
  );
5880
- const cleanResponse = response.trim().toLowerCase();
5881
- if (cleanResponse.includes("vector")) return "vector";
5882
- if (cleanResponse.includes("graph")) return "graph";
6550
+ const cleanResponse = (response != null ? response : "").trim().toLowerCase();
5883
6551
  if (cleanResponse.includes("both")) return "both";
6552
+ if (cleanResponse.includes("graph")) return "graph";
6553
+ if (cleanResponse.includes("vector")) return "vector";
5884
6554
  } catch (error) {
5885
6555
  console.warn("[QueryProcessor] LLM strategy classification failed, falling back to keywords:", error);
5886
6556
  }
@@ -6054,7 +6724,10 @@ var IntentClassifier = class {
6054
6724
  hasCategoricalFields = catKeys.size > 0;
6055
6725
  numericFieldCount = numericKeys.size;
6056
6726
  categoricalFieldCount = catKeys.size;
6057
- if (productKeyMatches >= 2 || docs.some((d) => d.content.toLowerCase().includes("price") || d.content.toLowerCase().includes("brand"))) {
6727
+ if (productKeyMatches >= 2 || docs.some((d) => {
6728
+ var _a2, _b;
6729
+ 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");
6730
+ })) {
6058
6731
  isProductLike = true;
6059
6732
  }
6060
6733
  }
@@ -6334,7 +7007,10 @@ var TextRendererStrategy = class {
6334
7007
  return { type: "text", title, data: { content: data } };
6335
7008
  }
6336
7009
  const docs = Array.isArray(data) ? data : [];
6337
- const text = docs.map((d) => d.content).join("\n\n");
7010
+ const text = docs.map((d) => {
7011
+ var _a2;
7012
+ return (_a2 = d == null ? void 0 : d.content) != null ? _a2 : "";
7013
+ }).join("\n\n");
6338
7014
  return { type: "text", title, data: { content: text || "No detailed content available." } };
6339
7015
  }
6340
7016
  };
@@ -6583,6 +7259,19 @@ var UITransformer = class _UITransformer {
6583
7259
  if (!retrievedData || retrievedData.length === 0) {
6584
7260
  return this.createTextResponse("No data available", "No relevant data found for your query.");
6585
7261
  }
7262
+ console.log("[UITransformer.transform] Processing retrievedData:", {
7263
+ userQuery,
7264
+ retrievedCount: retrievedData.length,
7265
+ sample: retrievedData.slice(0, 2).map((item) => {
7266
+ var _a3;
7267
+ return {
7268
+ id: item == null ? void 0 : item.id,
7269
+ contentType: typeof (item == null ? void 0 : item.content),
7270
+ contentSnippet: String((_a3 = item == null ? void 0 : item.content) != null ? _a3 : "").substring(0, 150),
7271
+ metadataKeys: Object.keys((item == null ? void 0 : item.metadata) || {})
7272
+ };
7273
+ })
7274
+ });
6586
7275
  const resolvedIntent = intent != null ? intent : this.detectIntentHeuristic(userQuery);
6587
7276
  const filteredData = resolvedIntent.filterInStockOnly ? retrievedData.filter((item) => this.determineStockStatus(item)) : retrievedData;
6588
7277
  const profile = this.profileData(filteredData);
@@ -6923,7 +7612,7 @@ ${schemaProfileText}` : ""}`;
6923
7612
  }
6924
7613
  // ─── Transform Helpers ────────────────────────────────────────────────────
6925
7614
  static transformToProductCarousel(data, config, trainedSchema) {
6926
- const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null).slice(0, 15);
7615
+ const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null);
6927
7616
  return {
6928
7617
  type: "product_carousel",
6929
7618
  title: "Recommended Products",
@@ -7072,7 +7761,10 @@ ${schemaProfileText}` : ""}`;
7072
7761
  type: "radar_chart",
7073
7762
  title: "Product Comparison",
7074
7763
  description: `Comparing ${data.length} items across ${radarData.length} attributes`,
7075
- data: radarData.length > 0 ? radarData : data.map((d) => ({ attribute: d.content.substring(0, 40) }))
7764
+ data: radarData.length > 0 ? radarData : data.map((d) => {
7765
+ var _a2;
7766
+ return { attribute: ((_a2 = d == null ? void 0 : d.content) != null ? _a2 : "").substring(0, 40) };
7767
+ })
7076
7768
  };
7077
7769
  }
7078
7770
  static transformToTable(data, query = "") {
@@ -7089,7 +7781,10 @@ ${schemaProfileText}` : ""}`;
7089
7781
  static transformToText(data) {
7090
7782
  return this.createTextResponse(
7091
7783
  "Retrieved Context",
7092
- data.map((item) => item.content).join("\n\n"),
7784
+ data.map((item) => {
7785
+ var _a2;
7786
+ return (_a2 = item == null ? void 0 : item.content) != null ? _a2 : "";
7787
+ }).join("\n\n"),
7093
7788
  `Found ${data.length} relevant results`
7094
7789
  );
7095
7790
  }
@@ -7250,6 +7945,7 @@ ${schemaProfileText}` : ""}`;
7250
7945
  return productTerms && productAction && !nonProductEntityTerms;
7251
7946
  }
7252
7947
  static isProductData(item) {
7948
+ if (!item) return false;
7253
7949
  const content = (item.content || "").toLowerCase();
7254
7950
  const productKeywords = [
7255
7951
  "product",
@@ -7296,7 +7992,8 @@ ${schemaProfileText}` : ""}`;
7296
7992
  return fieldCount.size > 2;
7297
7993
  }
7298
7994
  static profileData(data) {
7299
- const records = data.map((item) => {
7995
+ const records = (data || []).filter((item) => Boolean(item && typeof item === "object")).map((item) => {
7996
+ var _a2, _b;
7300
7997
  const fields2 = {};
7301
7998
  Object.entries(item.metadata || {}).forEach(([key, value]) => {
7302
7999
  const primitive = this.toPrimitive(value);
@@ -7305,8 +8002,8 @@ ${schemaProfileText}` : ""}`;
7305
8002
  if (!fields2.content && item.content) fields2.content = item.content.substring(0, 500);
7306
8003
  return {
7307
8004
  id: item.id,
7308
- content: item.content,
7309
- score: item.score,
8005
+ content: (_a2 = item.content) != null ? _a2 : "",
8006
+ score: (_b = item.score) != null ? _b : 0,
7310
8007
  fields: fields2,
7311
8008
  source: item
7312
8009
  };
@@ -7508,12 +8205,12 @@ ${schemaProfileText}` : ""}`;
7508
8205
  }
7509
8206
  static extractTimeSeriesData(data) {
7510
8207
  return data.map((item) => {
7511
- var _a2, _b, _c, _d, _e;
8208
+ var _a2, _b, _c, _d, _e, _f;
7512
8209
  const meta = item.metadata || {};
7513
8210
  return {
7514
8211
  timestamp: (_b = (_a2 = meta.timestamp) != null ? _a2 : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
7515
8212
  value: (_d = (_c = meta.value) != null ? _c : item.score) != null ? _d : 0,
7516
- label: (_e = meta.label) != null ? _e : item.content.substring(0, 50)
8213
+ label: (_f = meta.label) != null ? _f : ((_e = item == null ? void 0 : item.content) != null ? _e : "").substring(0, 50)
7517
8214
  };
7518
8215
  });
7519
8216
  }
@@ -7627,7 +8324,8 @@ ${schemaProfileText}` : ""}`;
7627
8324
  }, query.includes(normalizedField) ? 3 : 0);
7628
8325
  }
7629
8326
  static resolveTableCellValue(item, column) {
7630
- if (column === "Content") return item.content.substring(0, 100);
8327
+ var _a2, _b, _c;
8328
+ if (column === "Content") return ((_a2 = item == null ? void 0 : item.content) != null ? _a2 : "").substring(0, 100);
7631
8329
  const meta = item.metadata || {};
7632
8330
  const normalizedColumn = this.normalizeComparableField(column);
7633
8331
  const exactMetadata = Object.entries(meta).find(
@@ -7638,9 +8336,9 @@ ${schemaProfileText}` : ""}`;
7638
8336
  }
7639
8337
  const aliasValue = this.resolveAliasedTableCell(meta, column);
7640
8338
  if (aliasValue !== void 0) return this.toDisplayValue(aliasValue);
7641
- const contentValue = this.extractContentFieldValue(item.content, column);
8339
+ const contentValue = this.extractContentFieldValue((_b = item == null ? void 0 : item.content) != null ? _b : "", column);
7642
8340
  if (contentValue !== null) return contentValue;
7643
- const aliasContentValue = this.extractAliasedContentFieldValue(item.content, column);
8341
+ const aliasContentValue = this.extractAliasedContentFieldValue((_c = item == null ? void 0 : item.content) != null ? _c : "", column);
7644
8342
  return aliasContentValue != null ? aliasContentValue : "";
7645
8343
  }
7646
8344
  static resolveAliasedTableCell(meta, column) {
@@ -7690,6 +8388,7 @@ ${schemaProfileText}` : ""}`;
7690
8388
  return { inStockCount: inStock, outOfStockCount: outOfStock };
7691
8389
  }
7692
8390
  static determineStockStatus(item) {
8391
+ if (!item) return true;
7693
8392
  const meta = item.metadata || {};
7694
8393
  const stockValue = resolveMetadataValue(meta, "stock");
7695
8394
  if (stockValue !== void 0) {
@@ -7735,35 +8434,64 @@ ${schemaProfileText}` : ""}`;
7735
8434
  return resolveMetadataValue(meta, uiKey);
7736
8435
  }
7737
8436
  static extractProductInfo(item, config, trainedSchema) {
7738
- var _a2;
8437
+ var _a2, _b;
8438
+ if (!item) return null;
7739
8439
  const meta = item.metadata || {};
8440
+ const content = item.content || "";
7740
8441
  const name = this.getDynamicVal(meta, "name", config, trainedSchema);
7741
8442
  const price = this.getDynamicVal(meta, "price", config, trainedSchema);
7742
8443
  const brand = this.getDynamicVal(meta, "brand", config, trainedSchema);
7743
8444
  const description = this.cleanProductDescription(
7744
- (_a2 = this.extractProductDescriptionFromContent(item.content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
8445
+ (_a2 = this.extractProductDescriptionFromContent(content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
7745
8446
  );
7746
8447
  if (name || this.isProductData(item)) {
7747
8448
  let finalName = name ? String(name) : void 0;
8449
+ if (!finalName && content) {
8450
+ const nameMatch = content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
8451
+ finalName = nameMatch ? nameMatch[1].trim() : (_b = content.split("\n")[0]) == null ? void 0 : _b.substring(0, 60);
8452
+ }
7748
8453
  if (!finalName) {
7749
- const nameMatch = item.content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
7750
- finalName = nameMatch ? nameMatch[1].trim() : item.content.split("\n")[0].substring(0, 60);
8454
+ console.warn(
8455
+ `[UITransformer] Unable to read product name from metadata or content for item ${item.id}. Defaulting to 'Unnamed Product'.`,
8456
+ { metadataKeys: Object.keys(meta), contentLength: content.length }
8457
+ );
7751
8458
  }
7752
8459
  let finalPrice = typeof price === "number" || typeof price === "string" ? price : void 0;
7753
- if (!finalPrice) {
7754
- const priceMatch = item.content.match(/(?:Price|Cost):\s*\$?([\d,.]+)/i) || item.content.match(/\$\s*([\d,.]+)/);
8460
+ if (!finalPrice && content) {
8461
+ const priceMatch = content.match(/(?:Price|Cost):\s*\$?([\d,.]+)/i) || content.match(/\$\s*([\d,.]+)/);
7755
8462
  if (priceMatch) finalPrice = priceMatch[1].replace(/,/g, "");
7756
8463
  }
8464
+ if (finalPrice === void 0) {
8465
+ console.warn(
8466
+ `[UITransformer] Unable to read product price from metadata or content for item ${item.id}.`,
8467
+ { metadataKeys: Object.keys(meta), contentSnippet: content.substring(0, 100) }
8468
+ );
8469
+ }
7757
8470
  const imageValue = this.getDynamicVal(meta, "image", config, trainedSchema);
8471
+ if (!imageValue) {
8472
+ console.debug(
8473
+ `[UITransformer] Unable to read product image URL from metadata for item ${item.id}.`
8474
+ );
8475
+ }
8476
+ if (!description) {
8477
+ console.debug(
8478
+ `[UITransformer] Unable to read product description from metadata or content for item ${item.id}.`
8479
+ );
8480
+ }
7758
8481
  return {
7759
8482
  id: item.id,
7760
- name: finalName,
8483
+ name: finalName || "Unnamed Product",
7761
8484
  price: finalPrice,
7762
8485
  image: typeof imageValue === "string" ? imageValue : void 0,
7763
8486
  brand: brand ? String(brand) : void 0,
7764
8487
  description,
7765
8488
  inStock: this.determineStockStatus(item)
7766
8489
  };
8490
+ } else {
8491
+ console.warn(
8492
+ `[UITransformer] Item ${item.id} skipped: unable to read name or identify as product data from metadata/content.`,
8493
+ { metadataKeys: Object.keys(meta), contentSnippet: content.substring(0, 100) }
8494
+ );
7767
8495
  }
7768
8496
  return null;
7769
8497
  }
@@ -7848,13 +8576,13 @@ RULES:
7848
8576
  5. If no relevant data is found, return text: "I cannot answer this question based on the available information."`;
7849
8577
  }
7850
8578
  static buildContextSummary(sources, maxChars = 6e3) {
7851
- const items = sources.map((s, i) => {
8579
+ const items = (sources || []).filter(Boolean).map((s, i) => {
7852
8580
  var _a2, _b, _c, _d;
7853
8581
  return {
7854
8582
  index: i + 1,
7855
- content: (_b = (_a2 = s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
7856
- metadata: (_c = s.metadata) != null ? _c : {},
7857
- score: (_d = s.score) != null ? _d : 0
8583
+ content: (_b = (_a2 = s == null ? void 0 : s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
8584
+ metadata: (_c = s == null ? void 0 : s.metadata) != null ? _c : {},
8585
+ score: (_d = s == null ? void 0 : s.score) != null ? _d : 0
7858
8586
  };
7859
8587
  });
7860
8588
  const full = JSON.stringify(items, null, 2);
@@ -8378,7 +9106,7 @@ ${m.content}`).join("\n\n---\n\n");
8378
9106
  */
8379
9107
  askStreamInternal(_0) {
8380
9108
  return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
8381
- 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;
9109
+ 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;
8382
9110
  yield new __await(this.initialize());
8383
9111
  const ns = formatNamespace(namespace != null ? namespace : this.config.projectId);
8384
9112
  const topK = (_b = (_a2 = this.config.rag) == null ? void 0 : _a2.topK) != null ? _b : 5;
@@ -8421,40 +9149,65 @@ ${m.content}`).join("\n\n---\n\n");
8421
9149
  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;
8422
9150
  const hasMetadataFilter = filter.metadata && Object.keys(filter.metadata).length > 0;
8423
9151
  const hasNumericPredicates = Array.isArray(filter.__numericPredicates) && filter.__numericPredicates.length > 0;
8424
- const wantsExhaustiveList = hasNumericPredicates || hasMetadataFilter || /\b(list|all|show|provide|give|get|browse|find|search|display)\b/i.test(question);
8425
- const retrievalLimit = wantsExhaustiveList ? Math.max(topK * 20, 100) : topK * 2;
8426
- const rawSources = (strategyResult === "vector" || strategyResult === "both") && queryVector && queryVector.length > 0 ? yield new __await(this.vectorDB.query(queryVector, retrievalLimit, ns, filter)) : [];
9152
+ const wantsExhaustiveList = true;
9153
+ const retrievalLimit = Math.max(topK * 50, 1e3);
9154
+ 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"));
9155
+ console.log("[Pipeline] Raw vectorDB.query response:", {
9156
+ rawCount: rawSources.length,
9157
+ sample: rawSources.slice(0, 2).map((s) => {
9158
+ var _a3;
9159
+ return {
9160
+ id: s == null ? void 0 : s.id,
9161
+ score: s == null ? void 0 : s.score,
9162
+ contentType: typeof (s == null ? void 0 : s.content),
9163
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9164
+ metadataKeys: Object.keys((s == null ? void 0 : s.metadata) || {})
9165
+ };
9166
+ })
9167
+ });
8427
9168
  const retrieveEnd = performance.now();
8428
9169
  const embedMs = retrieveEnd - embedStart;
8429
9170
  const retrieveMs = retrieveEnd - embedStart;
8430
9171
  const rerankStart = performance.now();
8431
- const structuredSources = this.applyStructuredFilters(rawSources, filter);
8432
- let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => m.score >= scoreThreshold);
8433
- const rerankLimit = wantsExhaustiveList ? retrievalLimit : topK;
9172
+ const structuredSources = this.applyStructuredFilters(rawSources, filter).filter((s) => Boolean(s && typeof s === "object"));
9173
+ let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => {
9174
+ var _a3;
9175
+ return ((_a3 = m == null ? void 0 : m.score) != null ? _a3 : 0) >= scoreThreshold;
9176
+ });
9177
+ const rerankLimit = Math.max(retrievalLimit, fullSources.length);
8434
9178
  const useReranking = arch !== "naive" && (arch === "retrieve-and-rerank" || ((_m = this.config.rag) == null ? void 0 : _m.useReranking));
8435
9179
  if (!hasNumericPredicates && useReranking) {
8436
- fullSources = yield new __await(this.reranker.rerank(fullSources, question, rerankLimit));
8437
- } else if (!wantsExhaustiveList) {
8438
- fullSources = fullSources.slice(0, topK);
9180
+ fullSources = (yield new __await(this.reranker.rerank(fullSources, question, rerankLimit))).filter((s) => Boolean(s && typeof s === "object"));
8439
9181
  }
8440
9182
  const rerankMs = performance.now() - rerankStart;
8441
- let context = fullSources.length ? fullSources.map((m, i) => {
9183
+ const totalCount = fullSources.length;
9184
+ const promptSources = fullSources.slice(0, 15);
9185
+ 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]
9186
+
9187
+ ` + promptSources.map((m, i) => {
8442
9188
  var _a3;
8443
9189
  return `[Source ${i + 1}]
8444
9190
  ${(_a3 = m == null ? void 0 : m.content) != null ? _a3 : ""}`;
8445
9191
  }).join("\n\n---\n\n") : "No relevant context found.";
8446
- let displayCount = 15;
8447
- if (hasMetadataFilter) {
8448
- displayCount = fullSources.length;
8449
- } else {
8450
- const baseThreshold = Math.max(scoreThreshold, 0.4);
8451
- const highlyRelevant = fullSources.filter((m) => m.score >= baseThreshold);
8452
- displayCount = Math.max(highlyRelevant.length, topK);
8453
- if (displayCount > 15) {
8454
- displayCount = 15;
8455
- }
8456
- }
8457
- const sources = [...fullSources].sort((a, b) => b.score - a.score).slice(0, displayCount);
9192
+ const sources = [...fullSources].filter((s) => Boolean(s && typeof s === "object")).sort((a, b) => {
9193
+ var _a3, _b2;
9194
+ return ((_a3 = b == null ? void 0 : b.score) != null ? _a3 : 0) - ((_b2 = a == null ? void 0 : a.score) != null ? _b2 : 0);
9195
+ });
9196
+ console.log("[Pipeline] Final sources for prompt & UI:", {
9197
+ count: sources.length,
9198
+ totalRawCount: rawSources.length,
9199
+ sources: sources.slice(0, 10).map((s, idx) => {
9200
+ var _a3;
9201
+ return {
9202
+ rank: idx + 1,
9203
+ id: s == null ? void 0 : s.id,
9204
+ score: s == null ? void 0 : s.score,
9205
+ contentType: typeof (s == null ? void 0 : s.content),
9206
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9207
+ metadata: s == null ? void 0 : s.metadata
9208
+ };
9209
+ })
9210
+ });
8458
9211
  if (graphData && graphData.nodes.length > 0) {
8459
9212
  const graphContext = graphData.nodes.map(
8460
9213
  (n) => `Entity: ${n.label} (${n.id})${n.properties ? " - " + JSON.stringify(n.properties) : ""}`
@@ -8480,18 +9233,18 @@ ${context}`;
8480
9233
  }
8481
9234
  yield {
8482
9235
  reply: "",
8483
- sources: sources.map((s) => {
8484
- var _a3;
9236
+ sources: (sources || []).filter((s) => Boolean(s && typeof s === "object")).map((s) => {
9237
+ var _a3, _b2, _c2;
8485
9238
  return {
8486
9239
  id: s.id,
8487
- score: s.score,
8488
- content: s.content,
8489
- metadata: (_a3 = s.metadata) != null ? _a3 : {},
9240
+ score: (_a3 = s.score) != null ? _a3 : 0,
9241
+ content: (_b2 = s == null ? void 0 : s.content) != null ? _b2 : "",
9242
+ metadata: (_c2 = s == null ? void 0 : s.metadata) != null ? _c2 : {},
8490
9243
  namespace: ns
8491
9244
  };
8492
9245
  })
8493
9246
  };
8494
- const allMetadataKeys = Array.from(new Set(sources.flatMap((s) => Object.keys(s.metadata || {}))));
9247
+ const allMetadataKeys = Array.from(new Set(sources.filter(Boolean).flatMap((s) => Object.keys((s == null ? void 0 : s.metadata) || {}))));
8495
9248
  const cachedSchema = allMetadataKeys.length > 0 ? SchemaMapper.getCached(ns, allMetadataKeys) : void 0;
8496
9249
  if (allMetadataKeys.length > 0 && !cachedSchema) {
8497
9250
  SchemaMapper.train(this.llmProvider, ns, allMetadataKeys).catch(() => {
@@ -8643,7 +9396,7 @@ ${context}`;
8643
9396
  }
8644
9397
  yield fullReply;
8645
9398
  }
8646
- 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;
9399
+ const runHallucination = ((_w = this.config.llm.options) == null ? void 0 : _w.hallucinationScoring) === true;
8647
9400
  if (runHallucination) {
8648
9401
  hallucinationScoringPromise = scoreHallucination(this.llmProvider, fullReply, context).catch(() => void 0);
8649
9402
  }
@@ -8652,7 +9405,7 @@ ${context}`;
8652
9405
  const latency = {
8653
9406
  embedMs: Math.round(embedMs),
8654
9407
  retrieveMs: Math.round(retrieveMs),
8655
- rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_y = this.config.rag) == null ? void 0 : _y.useReranking)) ? Math.round(rerankMs) : void 0,
9408
+ rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_x = this.config.rag) == null ? void 0 : _x.useReranking)) ? Math.round(rerankMs) : void 0,
8656
9409
  generateMs: Math.round(generateMs),
8657
9410
  totalMs: Math.round(totalMs)
8658
9411
  };
@@ -8665,7 +9418,7 @@ ${context}`;
8665
9418
  totalTokens: promptTokens + completionTokens,
8666
9419
  estimatedCostUsd: estimateCostUsd(promptTokens, completionTokens, this.config.llm.model)
8667
9420
  };
8668
- const awaitHallucination = ((_z = this.config.llm.options) == null ? void 0 : _z.awaitHallucination) === true;
9421
+ const awaitHallucination = ((_y = this.config.llm.options) == null ? void 0 : _y.awaitHallucination) === true;
8669
9422
  const [uiTransformation, hallucinationResult] = yield new __await(Promise.all([
8670
9423
  uiTransformationPromise,
8671
9424
  awaitHallucination ? hallucinationScoringPromise : Promise.resolve(void 0)
@@ -8694,10 +9447,10 @@ ${context}`;
8694
9447
  hallucinationReason: hScore.reason
8695
9448
  } : {});
8696
9449
  const trace = buildTrace(hallucinationResult);
8697
- const isTelemetryActive = (_B = (_A = this.config.telemetry) == null ? void 0 : _A.enabled) != null ? _B : Boolean(this.config.licenseKey);
9450
+ const isTelemetryActive = (_A = (_z = this.config.telemetry) == null ? void 0 : _z.enabled) != null ? _A : Boolean(this.config.licenseKey);
8698
9451
  if (isTelemetryActive) {
8699
9452
  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";
8700
- const telemetryUrl = ((_C = this.config.telemetry) == null ? void 0 : _C.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
9453
+ const telemetryUrl = ((_B = this.config.telemetry) == null ? void 0 : _B.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
8701
9454
  const absoluteUrl = telemetryUrl.startsWith("http") ? telemetryUrl : (process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${process.env.PORT || 3e3}`) + telemetryUrl;
8702
9455
  (async () => {
8703
9456
  try {
@@ -8756,9 +9509,8 @@ ${context}`;
8756
9509
  { visualizationHint: "product_browse", recommendedChart: "text", filterInStockOnly: false, wantsExplicitTable: false, isTemporal: false, isComparison: false, language: "en" }
8757
9510
  );
8758
9511
  }
8759
- const isLocalProvider = this.config.llm.provider === "ollama";
8760
- const disableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.disableLlmUiTransform) === true;
8761
- if (forceDeterministic || isLocalProvider || disableLlmUiTransform) {
9512
+ const enableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.enableLlmUiTransform) === true;
9513
+ if (forceDeterministic || !enableLlmUiTransform) {
8762
9514
  return UITransformer.transform(question, sources, this.config, cachedSchema);
8763
9515
  }
8764
9516
  try {
@@ -8783,6 +9535,8 @@ ${context}`;
8783
9535
  });
8784
9536
  }
8785
9537
  resolveNumericPredicateValue(source, predicate) {
9538
+ var _a2;
9539
+ if (!source) return null;
8786
9540
  const meta = source.metadata || {};
8787
9541
  const field = predicate.field;
8788
9542
  const entries = Object.entries(meta).filter(([, value]) => value !== null && value !== void 0 && typeof value !== "object");
@@ -8794,7 +9548,7 @@ ${context}`;
8794
9548
  const value = this.toFiniteNumber(Array.isArray(fuzzy) ? fuzzy[1] : fuzzy.value);
8795
9549
  if (value !== null) return value;
8796
9550
  }
8797
- const contentValue = this.extractNumericValueFromContent(source.content, field);
9551
+ const contentValue = this.extractNumericValueFromContent((_a2 = source.content) != null ? _a2 : "", field);
8798
9552
  if (contentValue !== null) return contentValue;
8799
9553
  }
8800
9554
  for (const [key, value] of entries) {
@@ -8805,6 +9559,7 @@ ${context}`;
8805
9559
  return null;
8806
9560
  }
8807
9561
  extractNumericValueFromContent(content, field) {
9562
+ if (!content || typeof content !== "string") return null;
8808
9563
  const escapedWords = field.split(/\s+|_+|-+/).filter(Boolean).map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
8809
9564
  if (escapedWords.length === 0) return null;
8810
9565
  const pattern = new RegExp(`(?:${escapedWords.join("[\\\\s_:-]*")})\\s*[:\\-\u2013]?\\s*([\\d,]+(?:\\.\\d+)?)`, "i");
@@ -8890,6 +9645,20 @@ ${context}`;
8890
9645
  resolvedSources.push(source);
8891
9646
  }
8892
9647
  }
9648
+ console.log("[Pipeline] retrieve() response:", {
9649
+ query,
9650
+ namespace: ns,
9651
+ count: resolvedSources.length,
9652
+ sample: resolvedSources.slice(0, 2).map((s) => {
9653
+ var _a3;
9654
+ return {
9655
+ id: s == null ? void 0 : s.id,
9656
+ score: s == null ? void 0 : s.score,
9657
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9658
+ metadata: s == null ? void 0 : s.metadata
9659
+ };
9660
+ })
9661
+ });
8893
9662
  return { sources: resolvedSources, graphData };
8894
9663
  }
8895
9664
  /** Rewrite the user query for better retrieval performance. */