@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.
@@ -106,6 +106,609 @@ var init_templateUtils = __esm({
106
106
  }
107
107
  });
108
108
 
109
+ // ../../services/llm-gateway/providers/groq.ts
110
+ async function handleGroqRequest(req, apiKeyOverride) {
111
+ const apiKey = apiKeyOverride || process.env.GROQ_API_KEY;
112
+ if (!apiKey) {
113
+ throw new Error("Groq API Key missing. Please set GROQ_API_KEY in environment variables.");
114
+ }
115
+ const modelName = req.model.replace(/^groq\//i, "");
116
+ const payload = __spreadProps(__spreadValues({}, req), {
117
+ model: modelName
118
+ });
119
+ const response = await fetch("https://api.groq.com/openai/v1/chat/completions", {
120
+ method: "POST",
121
+ headers: {
122
+ "Content-Type": "application/json",
123
+ "Authorization": `Bearer ${apiKey}`
124
+ },
125
+ body: JSON.stringify(payload)
126
+ });
127
+ if (!response.ok) {
128
+ const errorText = await response.text();
129
+ throw new Error(`Groq API Error (${response.status}): ${errorText}`);
130
+ }
131
+ if (req.stream && response.body) {
132
+ return { stream: response.body };
133
+ }
134
+ const json = await response.json();
135
+ return { response: json };
136
+ }
137
+ var init_groq = __esm({
138
+ "../../services/llm-gateway/providers/groq.ts"() {
139
+ "use strict";
140
+ }
141
+ });
142
+
143
+ // ../../services/llm-gateway/providers/openai.ts
144
+ async function handleOpenAIRequest(req, apiKeyOverride) {
145
+ const apiKey = apiKeyOverride || process.env.OPENAI_API_KEY;
146
+ if (!apiKey) {
147
+ throw new Error("OpenAI API Key missing. Please set OPENAI_API_KEY in environment variables.");
148
+ }
149
+ const modelName = req.model.replace(/^(openai|gpt)\//i, "");
150
+ const payload = __spreadProps(__spreadValues({}, req), {
151
+ model: modelName
152
+ });
153
+ const response = await fetch("https://api.openai.com/v1/chat/completions", {
154
+ method: "POST",
155
+ headers: {
156
+ "Content-Type": "application/json",
157
+ "Authorization": `Bearer ${apiKey}`
158
+ },
159
+ body: JSON.stringify(payload)
160
+ });
161
+ if (!response.ok) {
162
+ const errorText = await response.text();
163
+ throw new Error(`OpenAI API Error (${response.status}): ${errorText}`);
164
+ }
165
+ if (req.stream && response.body) {
166
+ return { stream: response.body };
167
+ }
168
+ const json = await response.json();
169
+ return { response: json };
170
+ }
171
+ async function handleOpenAIEmbedding(req, apiKeyOverride) {
172
+ const apiKey = apiKeyOverride || process.env.OPENAI_API_KEY;
173
+ if (!apiKey) {
174
+ throw new Error("OpenAI API Key missing. Please set OPENAI_API_KEY in environment variables.");
175
+ }
176
+ const modelName = req.model.replace(/^(openai)\//i, "");
177
+ const response = await fetch("https://api.openai.com/v1/embeddings", {
178
+ method: "POST",
179
+ headers: {
180
+ "Content-Type": "application/json",
181
+ "Authorization": `Bearer ${apiKey}`
182
+ },
183
+ body: JSON.stringify({
184
+ model: modelName,
185
+ input: req.input
186
+ })
187
+ });
188
+ if (!response.ok) {
189
+ const errorText = await response.text();
190
+ throw new Error(`OpenAI Embedding API Error (${response.status}): ${errorText}`);
191
+ }
192
+ return await response.json();
193
+ }
194
+ var init_openai = __esm({
195
+ "../../services/llm-gateway/providers/openai.ts"() {
196
+ "use strict";
197
+ }
198
+ });
199
+
200
+ // ../../services/llm-gateway/providers/gemini.ts
201
+ async function handleGeminiRequest(req, apiKeyOverride) {
202
+ const apiKey = apiKeyOverride || process.env.GEMINI_API_KEY;
203
+ if (!apiKey) {
204
+ throw new Error("Gemini API Key missing. Please set GEMINI_API_KEY in environment variables.");
205
+ }
206
+ let modelName = req.model.replace(/^(google|gemini)\//i, "");
207
+ if (!modelName.startsWith("gemini-")) {
208
+ modelName = `gemini-${modelName}`;
209
+ }
210
+ const payload = __spreadProps(__spreadValues({}, req), {
211
+ model: modelName
212
+ });
213
+ const response = await fetch("https://generativelanguage.googleapis.com/v1beta/openai/chat/completions", {
214
+ method: "POST",
215
+ headers: {
216
+ "Content-Type": "application/json",
217
+ "Authorization": `Bearer ${apiKey}`
218
+ },
219
+ body: JSON.stringify(payload)
220
+ });
221
+ if (!response.ok) {
222
+ const errorText = await response.text();
223
+ throw new Error(`Google Gemini API Error (${response.status}): ${errorText}`);
224
+ }
225
+ if (req.stream && response.body) {
226
+ return { stream: response.body };
227
+ }
228
+ const json = await response.json();
229
+ return { response: json };
230
+ }
231
+ async function handleGeminiEmbedding(req, apiKeyOverride) {
232
+ const apiKey = apiKeyOverride || process.env.GEMINI_API_KEY;
233
+ if (!apiKey) {
234
+ throw new Error("Gemini API Key missing. Please set GEMINI_API_KEY in environment variables.");
235
+ }
236
+ let modelName = req.model.replace(/^(google|gemini)\//i, "");
237
+ if (!modelName || modelName === "default" || modelName.includes("text-embedding-3") || modelName.includes("ada") || !modelName.startsWith("text-embedding-00") && !modelName.startsWith("embedding-00")) {
238
+ modelName = "text-embedding-004";
239
+ }
240
+ const response = await fetch("https://generativelanguage.googleapis.com/v1beta/openai/embeddings", {
241
+ method: "POST",
242
+ headers: {
243
+ "Content-Type": "application/json",
244
+ "Authorization": `Bearer ${apiKey}`
245
+ },
246
+ body: JSON.stringify({
247
+ model: modelName,
248
+ input: req.input
249
+ })
250
+ });
251
+ if (!response.ok) {
252
+ const errorText = await response.text();
253
+ throw new Error(`Google Gemini Embedding API Error (${response.status}): ${errorText}`);
254
+ }
255
+ return await response.json();
256
+ }
257
+ var init_gemini = __esm({
258
+ "../../services/llm-gateway/providers/gemini.ts"() {
259
+ "use strict";
260
+ }
261
+ });
262
+
263
+ // ../../services/llm-gateway/providers/huggingface.ts
264
+ async function handleHuggingFaceChatRequest(req, apiKeyOverride) {
265
+ var _a2, _b;
266
+ const apiKey = apiKeyOverride || process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN;
267
+ if (!apiKey) {
268
+ throw new Error("HuggingFace API Key missing. Set HUGGINGFACE_API_KEY or HF_TOKEN in environment variables.");
269
+ }
270
+ let modelName = req.model.replace(/^(huggingface|hf)\//i, "");
271
+ if (!modelName || modelName === "default" || modelName.toLowerCase() === "qwen" || modelName.toLowerCase() === "qwen-coder") {
272
+ modelName = "Qwen/Qwen2.5-Coder-32B-Instruct";
273
+ }
274
+ const payload = __spreadProps(__spreadValues({}, req), {
275
+ model: modelName
276
+ });
277
+ try {
278
+ const response = await fetch("https://router.huggingface.co/v1/chat/completions", {
279
+ method: "POST",
280
+ headers: {
281
+ "Content-Type": "application/json",
282
+ "Authorization": `Bearer ${apiKey}`
283
+ },
284
+ body: JSON.stringify(payload)
285
+ });
286
+ if (response.ok) {
287
+ if (req.stream && response.body) {
288
+ return { stream: response.body };
289
+ }
290
+ const json = await response.json();
291
+ return { response: json };
292
+ }
293
+ } catch (e) {
294
+ }
295
+ try {
296
+ const response = await fetch("https://router.huggingface.co/hf-inference/v1/chat/completions", {
297
+ method: "POST",
298
+ headers: {
299
+ "Content-Type": "application/json",
300
+ "Authorization": `Bearer ${apiKey}`
301
+ },
302
+ body: JSON.stringify(payload)
303
+ });
304
+ if (response.ok) {
305
+ if (req.stream && response.body) {
306
+ return { stream: response.body };
307
+ }
308
+ const json = await response.json();
309
+ return { response: json };
310
+ }
311
+ } catch (e) {
312
+ }
313
+ const lastUserMsg = ((_a2 = req.messages.filter((m) => m.role === "user").pop()) == null ? void 0 : _a2.content) || "Hello";
314
+ const pipelineRes = await fetch(`https://router.huggingface.co/hf-inference/models/${modelName}`, {
315
+ method: "POST",
316
+ headers: {
317
+ "Content-Type": "application/json",
318
+ "Authorization": `Bearer ${apiKey}`
319
+ },
320
+ body: JSON.stringify({
321
+ inputs: lastUserMsg,
322
+ parameters: { max_new_tokens: req.max_tokens || 256, temperature: req.temperature || 0.7 },
323
+ options: { wait_for_model: true }
324
+ })
325
+ });
326
+ if (!pipelineRes.ok) {
327
+ const errorText = await pipelineRes.text();
328
+ throw new Error(`HuggingFace API Error (${pipelineRes.status}): ${errorText}`);
329
+ }
330
+ const raw = await pipelineRes.json();
331
+ const textOutput = Array.isArray(raw) ? ((_b = raw[0]) == null ? void 0 : _b.generated_text) || JSON.stringify(raw) : JSON.stringify(raw);
332
+ const formattedResponse = {
333
+ id: `hf-${Date.now()}`,
334
+ object: "chat.completion",
335
+ created: Math.floor(Date.now() / 1e3),
336
+ model: modelName,
337
+ choices: [
338
+ {
339
+ index: 0,
340
+ message: {
341
+ role: "assistant",
342
+ content: textOutput
343
+ },
344
+ finish_reason: "stop"
345
+ }
346
+ ],
347
+ usage: {
348
+ prompt_tokens: lastUserMsg.length,
349
+ completion_tokens: textOutput.length,
350
+ total_tokens: lastUserMsg.length + textOutput.length
351
+ }
352
+ };
353
+ return { response: formattedResponse };
354
+ }
355
+ async function handleHuggingFaceEmbedding(req, apiKeyOverride) {
356
+ const apiKey = apiKeyOverride || process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN;
357
+ if (!apiKey) {
358
+ throw new Error("HuggingFace API Key missing. Set HUGGINGFACE_API_KEY or HF_TOKEN in environment variables.");
359
+ }
360
+ let modelName = req.model.replace(/^(huggingface|hf)\//i, "");
361
+ if (!modelName || modelName === "default" || modelName.includes("text-embedding-3") || modelName.includes("ada") || !modelName.includes("/") && !modelName.includes("bge") && !modelName.includes("sentence-transformers")) {
362
+ modelName = "BAAI/bge-base-en-v1.5";
363
+ }
364
+ const inputs = Array.isArray(req.input) ? req.input : [req.input];
365
+ const fetchEmbeddingFromModel = async (targetModel) => {
366
+ try {
367
+ const routerRes = await fetch("https://router.huggingface.co/hf-inference/v1/embeddings", {
368
+ method: "POST",
369
+ headers: {
370
+ "Content-Type": "application/json",
371
+ "Authorization": `Bearer ${apiKey}`
372
+ },
373
+ body: JSON.stringify({
374
+ model: targetModel,
375
+ input: inputs
376
+ })
377
+ });
378
+ if (routerRes.ok) {
379
+ const json = await routerRes.json();
380
+ if (json && json.data) return json;
381
+ }
382
+ } catch (e) {
383
+ }
384
+ const response = await fetch(`https://router.huggingface.co/hf-inference/models/${targetModel}`, {
385
+ method: "POST",
386
+ headers: {
387
+ "Content-Type": "application/json",
388
+ "Authorization": `Bearer ${apiKey}`
389
+ },
390
+ body: JSON.stringify({
391
+ inputs,
392
+ options: { wait_for_model: true }
393
+ })
394
+ });
395
+ if (!response.ok) {
396
+ const errorText = await response.text();
397
+ throw new Error(`HuggingFace API Error (${response.status}): ${errorText}`);
398
+ }
399
+ const rawData = await response.json();
400
+ const embeddings = Array.isArray(rawData[0]) ? typeof rawData[0][0] === "number" ? rawData : rawData.map((arr) => arr[0]) : [rawData];
401
+ return {
402
+ object: "list",
403
+ data: embeddings.map((vec, idx) => ({
404
+ object: "embedding",
405
+ embedding: vec,
406
+ index: idx
407
+ })),
408
+ model: targetModel,
409
+ usage: {
410
+ prompt_tokens: inputs.reduce((acc, str) => acc + str.length, 0),
411
+ completion_tokens: 0,
412
+ total_tokens: inputs.reduce((acc, str) => acc + str.length, 0)
413
+ }
414
+ };
415
+ };
416
+ try {
417
+ return await fetchEmbeddingFromModel(modelName);
418
+ } catch (err) {
419
+ if (modelName !== "BAAI/bge-base-en-v1.5") {
420
+ console.warn(`[LLM Gateway] HuggingFace model ${modelName} failed. Falling back to BAAI/bge-base-en-v1.5...`, err);
421
+ return await fetchEmbeddingFromModel("BAAI/bge-base-en-v1.5");
422
+ }
423
+ throw err;
424
+ }
425
+ }
426
+ var init_huggingface = __esm({
427
+ "../../services/llm-gateway/providers/huggingface.ts"() {
428
+ "use strict";
429
+ }
430
+ });
431
+
432
+ // ../../services/llm-gateway/providers/anthropic.ts
433
+ async function handleAnthropicRequest(req, apiKeyOverride) {
434
+ var _a2, _b;
435
+ const apiKey = apiKeyOverride || process.env.ANTHROPIC_API_KEY;
436
+ if (!apiKey) {
437
+ throw new Error("Anthropic API Key missing. Please set ANTHROPIC_API_KEY in environment variables.");
438
+ }
439
+ const modelName = req.model.replace(/^(anthropic|claude)\//i, "");
440
+ let systemPrompt = void 0;
441
+ const anthropicMessages = [];
442
+ for (const msg of req.messages) {
443
+ if (msg.role === "system") {
444
+ systemPrompt = systemPrompt ? `${systemPrompt}
445
+ ${msg.content}` : msg.content;
446
+ } else {
447
+ anthropicMessages.push({
448
+ role: msg.role === "assistant" ? "assistant" : "user",
449
+ content: msg.content
450
+ });
451
+ }
452
+ }
453
+ if (anthropicMessages.length === 0) {
454
+ anthropicMessages.push({ role: "user", content: "Hello" });
455
+ }
456
+ const payload = {
457
+ model: modelName,
458
+ messages: anthropicMessages,
459
+ max_tokens: req.max_tokens || req.max_completion_tokens || 1024,
460
+ stream: req.stream || false
461
+ };
462
+ if (systemPrompt) {
463
+ payload.system = systemPrompt;
464
+ }
465
+ if (req.temperature !== void 0) {
466
+ payload.temperature = req.temperature;
467
+ }
468
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
469
+ method: "POST",
470
+ headers: {
471
+ "Content-Type": "application/json",
472
+ "x-api-key": apiKey,
473
+ "anthropic-version": "2023-06-01"
474
+ },
475
+ body: JSON.stringify(payload)
476
+ });
477
+ if (!response.ok) {
478
+ const errorText = await response.text();
479
+ throw new Error(`Anthropic API Error (${response.status}): ${errorText}`);
480
+ }
481
+ if (req.stream && response.body) {
482
+ return { stream: response.body };
483
+ }
484
+ const json = await response.json();
485
+ const textContent = ((_b = (_a2 = json.content) == null ? void 0 : _a2[0]) == null ? void 0 : _b.text) || "";
486
+ const openAIResponse = {
487
+ id: json.id || `chatcmpl-${Date.now()}`,
488
+ object: "chat.completion",
489
+ created: Math.floor(Date.now() / 1e3),
490
+ model: json.model || modelName,
491
+ choices: [
492
+ {
493
+ index: 0,
494
+ message: {
495
+ role: "assistant",
496
+ content: textContent
497
+ },
498
+ finish_reason: json.stop_reason === "end_turn" ? "stop" : json.stop_reason || "stop"
499
+ }
500
+ ],
501
+ usage: json.usage ? {
502
+ prompt_tokens: json.usage.input_tokens,
503
+ completion_tokens: json.usage.output_tokens,
504
+ total_tokens: json.usage.input_tokens + json.usage.output_tokens
505
+ } : void 0
506
+ };
507
+ return { response: openAIResponse };
508
+ }
509
+ var init_anthropic = __esm({
510
+ "../../services/llm-gateway/providers/anthropic.ts"() {
511
+ "use strict";
512
+ }
513
+ });
514
+
515
+ // ../../services/llm-gateway/providers/ollama.ts
516
+ async function handleOllamaRequest(req, baseUrlOverride) {
517
+ const baseUrl = (baseUrlOverride || process.env.OLLAMA_BASE_URL || "http://localhost:11434/v1").replace(/\/+$/, "");
518
+ const modelName = req.model.replace(/^ollama\//i, "");
519
+ const payload = __spreadProps(__spreadValues({}, req), {
520
+ model: modelName
521
+ });
522
+ const response = await fetch(`${baseUrl}/chat/completions`, {
523
+ method: "POST",
524
+ headers: {
525
+ "Content-Type": "application/json"
526
+ },
527
+ body: JSON.stringify(payload)
528
+ });
529
+ if (!response.ok) {
530
+ const errorText = await response.text();
531
+ throw new Error(`Ollama API Error (${response.status}): ${errorText}`);
532
+ }
533
+ if (req.stream && response.body) {
534
+ return { stream: response.body };
535
+ }
536
+ const json = await response.json();
537
+ return { response: json };
538
+ }
539
+ var init_ollama = __esm({
540
+ "../../services/llm-gateway/providers/ollama.ts"() {
541
+ "use strict";
542
+ }
543
+ });
544
+
545
+ // ../../services/llm-gateway/router.ts
546
+ var router_exports = {};
547
+ __export(router_exports, {
548
+ SUPPORTED_MODELS: () => SUPPORTED_MODELS,
549
+ dispatchChatCompletion: () => dispatchChatCompletion,
550
+ dispatchEmbedding: () => dispatchEmbedding,
551
+ resolveProvider: () => resolveProvider
552
+ });
553
+ function resolveProvider(model) {
554
+ const lower = model.toLowerCase();
555
+ if (lower.startsWith("huggingface/") || lower.startsWith("hf/")) {
556
+ return "huggingface";
557
+ }
558
+ if (lower.startsWith("ollama/")) {
559
+ return "ollama";
560
+ }
561
+ if (lower.startsWith("groq/") || lower.includes("llama") || lower.includes("qwen") || lower.includes("mixtral")) {
562
+ return "groq";
563
+ }
564
+ if (process.env.GROQ_API_KEY) return "groq";
565
+ if (process.env.OPENAI_API_KEY) return "openai";
566
+ if (process.env.GEMINI_API_KEY) return "gemini";
567
+ if (process.env.ANTHROPIC_API_KEY) return "anthropic";
568
+ if (process.env.HF_TOKEN || process.env.HUGGINGFACE_API_KEY) return "huggingface";
569
+ return "groq";
570
+ }
571
+ function cleanApiKeyOverride(apiKeyOverride) {
572
+ if (!apiKeyOverride) return void 0;
573
+ const key = apiKeyOverride.trim();
574
+ 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-")) {
575
+ return void 0;
576
+ }
577
+ return key;
578
+ }
579
+ async function dispatchChatCompletion(req, apiKeyOverride) {
580
+ const effectiveKey = cleanApiKeyOverride(apiKeyOverride);
581
+ const provider = resolveProvider(req.model);
582
+ try {
583
+ switch (provider) {
584
+ case "groq":
585
+ return await handleGroqRequest(req, effectiveKey);
586
+ case "openai":
587
+ return await handleOpenAIRequest(req, effectiveKey);
588
+ case "gemini":
589
+ return await handleGeminiRequest(req, effectiveKey);
590
+ case "anthropic":
591
+ return await handleAnthropicRequest(req, effectiveKey);
592
+ case "ollama":
593
+ return await handleOllamaRequest(req);
594
+ case "huggingface":
595
+ return await handleHuggingFaceChatRequest(req, effectiveKey);
596
+ default:
597
+ throw new Error(`Unsupported LLM provider for model: ${req.model}`);
598
+ }
599
+ } catch (error) {
600
+ if (/rate[- ]?limit|429|exhausted/i.test(error.message)) {
601
+ const isGroqKey = process.env.GROQ_API_KEY || effectiveKey && effectiveKey.startsWith("gsk_");
602
+ const reqModelLower = req.model.toLowerCase();
603
+ if (isGroqKey && !reqModelLower.includes("llama-3.3-70b")) {
604
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to secondary Groq model (llama-3.3-70b-versatile)...`);
605
+ try {
606
+ return await handleGroqRequest(__spreadProps(__spreadValues({}, req), { model: "llama-3.3-70b-versatile" }), effectiveKey);
607
+ } catch (e) {
608
+ }
609
+ }
610
+ const geminiKey = process.env.GEMINI_API_KEY || effectiveKey;
611
+ if (provider !== "gemini" && geminiKey && (geminiKey.startsWith("AIza") || !geminiKey.startsWith("AQ."))) {
612
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to Google Gemini (gemini-2.5-flash)...`);
613
+ try {
614
+ return await handleGeminiRequest(__spreadProps(__spreadValues({}, req), { model: "gemini-2.5-flash" }), effectiveKey);
615
+ } catch (e) {
616
+ }
617
+ }
618
+ if (provider !== "huggingface" && (process.env.HF_TOKEN || process.env.HUGGINGFACE_API_KEY)) {
619
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to Hugging Face (Qwen/Qwen2.5-Coder-32B-Instruct)...`);
620
+ try {
621
+ return await handleHuggingFaceChatRequest(__spreadProps(__spreadValues({}, req), { model: "Qwen/Qwen2.5-Coder-32B-Instruct" }), effectiveKey);
622
+ } catch (e) {
623
+ }
624
+ }
625
+ if (provider !== "openai" && process.env.OPENAI_API_KEY) {
626
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to OpenAI (gpt-4o-mini)...`);
627
+ try {
628
+ return await handleOpenAIRequest(__spreadProps(__spreadValues({}, req), { model: "gpt-4o-mini" }), effectiveKey);
629
+ } catch (e) {
630
+ }
631
+ }
632
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to local Ollama (llama3.2)...`);
633
+ return handleOllamaRequest(__spreadProps(__spreadValues({}, req), { model: "llama3.2" }));
634
+ }
635
+ throw error;
636
+ }
637
+ }
638
+ async function dispatchEmbedding(req, apiKeyOverride) {
639
+ const effectiveKey = cleanApiKeyOverride(apiKeyOverride);
640
+ if (req.model.startsWith("hf/") || req.model.startsWith("huggingface/") || req.model.includes("bge-")) {
641
+ try {
642
+ return await handleHuggingFaceEmbedding(req, effectiveKey);
643
+ } catch (err) {
644
+ console.warn("[LLM Gateway] HuggingFace explicit model embedding failed, falling back to default gateway chain:", err);
645
+ }
646
+ }
647
+ const geminiKey = process.env.GEMINI_API_KEY || effectiveKey;
648
+ const isGeminiKeyValid = Boolean(geminiKey && (geminiKey.startsWith("AIza") || !geminiKey.startsWith("AQ.")));
649
+ if (isGeminiKeyValid) {
650
+ try {
651
+ return await handleGeminiEmbedding(req, effectiveKey);
652
+ } catch (err) {
653
+ console.warn("[LLM Gateway] Gemini embedding failed:", err);
654
+ }
655
+ }
656
+ if (process.env.OPENAI_API_KEY) {
657
+ try {
658
+ return await handleOpenAIEmbedding(req, effectiveKey);
659
+ } catch (err) {
660
+ console.warn("[LLM Gateway] OpenAI embedding failed:", err);
661
+ }
662
+ }
663
+ if (process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN) {
664
+ try {
665
+ return await handleHuggingFaceEmbedding(req, effectiveKey);
666
+ } catch (err) {
667
+ console.warn("[LLM Gateway] HuggingFace fallback embedding failed:", err);
668
+ }
669
+ }
670
+ return handleGeminiEmbedding(req, effectiveKey);
671
+ }
672
+ var SUPPORTED_MODELS;
673
+ var init_router = __esm({
674
+ "../../services/llm-gateway/router.ts"() {
675
+ "use strict";
676
+ init_groq();
677
+ init_openai();
678
+ init_gemini();
679
+ init_huggingface();
680
+ init_anthropic();
681
+ init_ollama();
682
+ SUPPORTED_MODELS = [
683
+ { id: "groq/llama-3.1-8b-instant", object: "model", created: 17e8, owned_by: "groq" },
684
+ { id: "llama-3.1-8b-instant", object: "model", created: 17e8, owned_by: "groq" },
685
+ { id: "groq/llama-3.3-70b-versatile", object: "model", created: 17e8, owned_by: "groq" },
686
+ { id: "llama-3.3-70b-versatile", object: "model", created: 17e8, owned_by: "groq" },
687
+ { id: "gpt-4o-mini", object: "model", created: 17e8, owned_by: "openai" },
688
+ { id: "openai/gpt-4o-mini", object: "model", created: 17e8, owned_by: "openai" },
689
+ { id: "gpt-4o", object: "model", created: 17e8, owned_by: "openai" },
690
+ { id: "gemini-2.5-flash", object: "model", created: 17e8, owned_by: "google" },
691
+ { id: "google/gemini-2.5-flash", object: "model", created: 17e8, owned_by: "google" },
692
+ { id: "claude-3-5-haiku-20241022", object: "model", created: 17e8, owned_by: "anthropic" },
693
+ { id: "anthropic/claude-3-5-haiku-20241022", object: "model", created: 17e8, owned_by: "anthropic" },
694
+ { id: "text-embedding-004", object: "model", created: 17e8, owned_by: "google" },
695
+ { id: "google/text-embedding-004", object: "model", created: 17e8, owned_by: "google" },
696
+ { id: "BAAI/bge-base-en-v1.5", object: "model", created: 17e8, owned_by: "huggingface" },
697
+ { id: "huggingface/BAAI/bge-base-en-v1.5", object: "model", created: 17e8, owned_by: "huggingface" },
698
+ { id: "groq/qwen3-32b", object: "model", created: 17e8, owned_by: "groq" },
699
+ { id: "qwen/qwen3-32b", object: "model", created: 17e8, owned_by: "groq" },
700
+ { id: "qwen/qwen3-embedding-8b", object: "model", created: 17e8, owned_by: "qwen" },
701
+ { id: "qwen3-embedding-8b", object: "model", created: 17e8, owned_by: "qwen" },
702
+ { id: "ollama/llama3.2", object: "model", created: 17e8, owned_by: "ollama" }
703
+ ];
704
+ if (typeof globalThis !== "undefined") {
705
+ const _g2 = globalThis;
706
+ _g2.__retrivoraDispatchChat = dispatchChatCompletion;
707
+ _g2.__retrivoraDispatchEmbedding = dispatchEmbedding;
708
+ }
709
+ }
710
+ });
711
+
109
712
  // src/providers/vectordb/BaseVectorProvider.ts
110
713
  var BaseVectorProvider;
111
714
  var init_BaseVectorProvider = __esm({
@@ -3841,6 +4444,17 @@ var LLM_PROFILES = {
3841
4444
  };
3842
4445
 
3843
4446
  // src/llm/providers/UniversalLLMAdapter.ts
4447
+ function extractContent(obj) {
4448
+ var _a2, _b, _c;
4449
+ if (!obj || typeof obj !== "object") return void 0;
4450
+ const choice = (_a2 = obj.choices) == null ? void 0 : _a2[0];
4451
+ if (!choice) return void 0;
4452
+ if (typeof ((_b = choice.message) == null ? void 0 : _b.content) === "string") return choice.message.content;
4453
+ if (typeof ((_c = choice.delta) == null ? void 0 : _c.content) === "string") return choice.delta.content;
4454
+ if (typeof choice.text === "string") return choice.text;
4455
+ if (typeof choice.content === "string") return choice.content;
4456
+ return void 0;
4457
+ }
3844
4458
  var UniversalLLMAdapter = class {
3845
4459
  constructor(config) {
3846
4460
  var _a2, _b, _c, _d, _e, _f, _g2, _h;
@@ -3872,7 +4486,7 @@ var UniversalLLMAdapter = class {
3872
4486
  });
3873
4487
  }
3874
4488
  async chat(messages, context) {
3875
- var _a2, _b, _c, _d, _e, _f;
4489
+ var _a2, _b, _c;
3876
4490
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3877
4491
  const formattedMessages = [
3878
4492
  { role: "system", content: `${this.systemPrompt}
@@ -3899,25 +4513,42 @@ ${context != null ? context : "None"}` },
3899
4513
  }
3900
4514
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
3901
4515
  if (isSelfHost || Boolean(process.env.VERCEL)) {
3902
- try {
3903
- const _g2 = globalThis;
3904
- if (typeof _g2.__retrivoraDispatchChat === "function") {
3905
- const res = await _g2.__retrivoraDispatchChat({
4516
+ const _g2 = globalThis;
4517
+ let dispatch = _g2.__retrivoraDispatchChat;
4518
+ if (typeof dispatch !== "function") {
4519
+ try {
4520
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4521
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4522
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4523
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4524
+ dispatch = gateway.dispatchChatCompletion;
4525
+ }
4526
+ } catch (e) {
4527
+ }
4528
+ }
4529
+ if (typeof dispatch === "function") {
4530
+ try {
4531
+ const res = await dispatch({
3906
4532
  model: this.model,
3907
4533
  messages: formattedMessages,
3908
4534
  max_tokens: this.maxTokens,
3909
4535
  temperature: this.temperature
3910
4536
  }, this.apiKey);
3911
- 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) {
3912
- return res.response.choices[0].message.content;
4537
+ const content = extractContent(res == null ? void 0 : res.response);
4538
+ if (content !== void 0) {
4539
+ return content;
3913
4540
  }
4541
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch returned empty content for model: ${this.model}`);
4542
+ } catch (dispatchErr) {
4543
+ throw dispatchErr;
3914
4544
  }
3915
- } catch (e) {
4545
+ } else {
4546
+ 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.`);
3916
4547
  }
3917
4548
  }
3918
4549
  const { data } = await this.http.post(path2, payload);
3919
- const extractPath = (_f = this.opts.responseExtractPath) != null ? _f : "choices[0].message.content";
3920
- const result = resolvePath(data, extractPath);
4550
+ const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
4551
+ const result = (_c = resolvePath(data, extractPath)) != null ? _c : extractContent(data);
3921
4552
  if (result === void 0) {
3922
4553
  throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
3923
4554
  }
@@ -3930,7 +4561,7 @@ ${context != null ? context : "None"}` },
3930
4561
  */
3931
4562
  chatStream(messages, context) {
3932
4563
  return __asyncGenerator(this, null, function* () {
3933
- var _a2, _b, _c, _d, _e, _f, _g2;
4564
+ var _a2, _b, _c, _d, _e;
3934
4565
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3935
4566
  const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
3936
4567
  const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
@@ -3964,10 +4595,22 @@ ${context != null ? context : "None"}` },
3964
4595
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
3965
4596
  let streamBody = null;
3966
4597
  if (isSelfHost || Boolean(process.env.VERCEL)) {
3967
- try {
3968
- const _g3 = globalThis;
3969
- if (typeof _g3.__retrivoraDispatchChat === "function") {
3970
- const res = yield new __await(_g3.__retrivoraDispatchChat({
4598
+ const _g2 = globalThis;
4599
+ let dispatch = _g2.__retrivoraDispatchChat;
4600
+ if (typeof dispatch !== "function") {
4601
+ try {
4602
+ const gateway = yield new __await(Promise.resolve().then(() => (init_router(), router_exports)));
4603
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4604
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4605
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4606
+ dispatch = gateway.dispatchChatCompletion;
4607
+ }
4608
+ } catch (e) {
4609
+ }
4610
+ }
4611
+ if (typeof dispatch === "function") {
4612
+ try {
4613
+ const res = yield new __await(dispatch({
3971
4614
  model: this.model,
3972
4615
  messages: formattedMessages,
3973
4616
  max_tokens: this.maxTokens,
@@ -3976,12 +4619,19 @@ ${context != null ? context : "None"}` },
3976
4619
  }, this.apiKey));
3977
4620
  if (res == null ? void 0 : res.stream) {
3978
4621
  streamBody = res.stream;
3979
- } 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) {
3980
- yield res.response.choices[0].message.content;
3981
- return;
4622
+ } else {
4623
+ const content = extractContent(res == null ? void 0 : res.response);
4624
+ if (content !== void 0) {
4625
+ yield content;
4626
+ return;
4627
+ }
4628
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch stream returned empty response for model: ${this.model}`);
3982
4629
  }
4630
+ } catch (dispatchErr) {
4631
+ throw dispatchErr;
3983
4632
  }
3984
- } catch (e) {
4633
+ } else {
4634
+ 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.`);
3985
4635
  }
3986
4636
  }
3987
4637
  if (!streamBody) {
@@ -4008,14 +4658,14 @@ ${context != null ? context : "None"}` },
4008
4658
  if (done) break;
4009
4659
  buffer += decoder.decode(value, { stream: true });
4010
4660
  const lines = buffer.split("\n");
4011
- buffer = (_g2 = lines.pop()) != null ? _g2 : "";
4661
+ buffer = (_c = lines.pop()) != null ? _c : "";
4012
4662
  for (const line of lines) {
4013
4663
  const trimmed = line.trim();
4014
4664
  if (!trimmed || trimmed === "data: [DONE]") continue;
4015
4665
  if (!trimmed.startsWith("data:")) continue;
4016
4666
  try {
4017
4667
  const json = JSON.parse(trimmed.slice(5).trim());
4018
- const text = resolvePath(json, extractPath);
4668
+ const text = (_d = resolvePath(json, extractPath)) != null ? _d : extractContent(json);
4019
4669
  if (text && typeof text === "string") yield text;
4020
4670
  } catch (e) {
4021
4671
  }
@@ -4025,7 +4675,7 @@ ${context != null ? context : "None"}` },
4025
4675
  const jsonStr = buffer.replace(/^data:\s*/, "").trim();
4026
4676
  try {
4027
4677
  const json = JSON.parse(jsonStr);
4028
- const text = resolvePath(json, extractPath);
4678
+ const text = (_e = resolvePath(json, extractPath)) != null ? _e : extractContent(json);
4029
4679
  if (text && typeof text === "string") yield text;
4030
4680
  } catch (e) {
4031
4681
  }
@@ -4052,18 +4702,34 @@ ${context != null ? context : "None"}` },
4052
4702
  }
4053
4703
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4054
4704
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4055
- try {
4056
- const _g2 = globalThis;
4057
- if (typeof _g2.__retrivoraDispatchEmbedding === "function") {
4058
- const res = await _g2.__retrivoraDispatchEmbedding({
4705
+ const _g2 = globalThis;
4706
+ let dispatch = _g2.__retrivoraDispatchEmbedding;
4707
+ if (typeof dispatch !== "function") {
4708
+ try {
4709
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4710
+ if (gateway == null ? void 0 : gateway.dispatchEmbedding) {
4711
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4712
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4713
+ dispatch = gateway.dispatchEmbedding;
4714
+ }
4715
+ } catch (e) {
4716
+ }
4717
+ }
4718
+ if (typeof dispatch === "function") {
4719
+ try {
4720
+ const res = await dispatch({
4059
4721
  model: this.model,
4060
4722
  input: text
4061
4723
  }, this.apiKey);
4062
4724
  if ((_c = (_b = res == null ? void 0 : res.data) == null ? void 0 : _b[0]) == null ? void 0 : _c.embedding) {
4063
4725
  return res.data[0].embedding;
4064
4726
  }
4727
+ throw new Error(`[UniversalLLMAdapter] In-process embedding dispatch returned invalid vector for model: ${this.model}`);
4728
+ } catch (dispatchErr) {
4729
+ throw dispatchErr;
4065
4730
  }
4066
- } catch (e) {
4731
+ } else {
4732
+ 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.`);
4067
4733
  }
4068
4734
  }
4069
4735
  const { data } = await this.http.post(path2, payload);
@@ -4656,7 +5322,8 @@ var Reranker = class {
4656
5322
  return matches.sort((a, b) => b.score - a.score).slice(0, limit);
4657
5323
  }
4658
5324
  const scoredMatches = matches.map((match) => {
4659
- const contentLower = match.content.toLowerCase();
5325
+ var _a2;
5326
+ const contentLower = ((_a2 = match == null ? void 0 : match.content) != null ? _a2 : "").toLowerCase();
4660
5327
  let keywordScore = 0;
4661
5328
  keywords.forEach((keyword) => {
4662
5329
  if (contentLower.includes(keyword)) {
@@ -4677,7 +5344,10 @@ var Reranker = class {
4677
5344
  [{ role: "user", content: `Query: "${query}"
4678
5345
 
4679
5346
  Documents:
4680
- ${topN.map((m, i) => `[${i}] ${m.content.replace(/\n/g, " ")}`).join("\n")}` }],
5347
+ ${topN.map((m, i) => {
5348
+ var _a2;
5349
+ return `[${i}] ${((_a2 = m == null ? void 0 : m.content) != null ? _a2 : "").replace(/\n/g, " ")}`;
5350
+ }).join("\n")}` }],
4681
5351
  "",
4682
5352
  {
4683
5353
  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.',
@@ -5842,10 +6512,10 @@ Return ONLY 'vector', 'graph', or 'both'. No explanation.`;
5842
6512
  "",
5843
6513
  { temperature: 0, maxTokens: 10 }
5844
6514
  );
5845
- const cleanResponse = response.trim().toLowerCase();
5846
- if (cleanResponse.includes("vector")) return "vector";
5847
- if (cleanResponse.includes("graph")) return "graph";
6515
+ const cleanResponse = (response != null ? response : "").trim().toLowerCase();
5848
6516
  if (cleanResponse.includes("both")) return "both";
6517
+ if (cleanResponse.includes("graph")) return "graph";
6518
+ if (cleanResponse.includes("vector")) return "vector";
5849
6519
  } catch (error) {
5850
6520
  console.warn("[QueryProcessor] LLM strategy classification failed, falling back to keywords:", error);
5851
6521
  }
@@ -6019,7 +6689,10 @@ var IntentClassifier = class {
6019
6689
  hasCategoricalFields = catKeys.size > 0;
6020
6690
  numericFieldCount = numericKeys.size;
6021
6691
  categoricalFieldCount = catKeys.size;
6022
- if (productKeyMatches >= 2 || docs.some((d) => d.content.toLowerCase().includes("price") || d.content.toLowerCase().includes("brand"))) {
6692
+ if (productKeyMatches >= 2 || docs.some((d) => {
6693
+ var _a2, _b;
6694
+ 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");
6695
+ })) {
6023
6696
  isProductLike = true;
6024
6697
  }
6025
6698
  }
@@ -6299,7 +6972,10 @@ var TextRendererStrategy = class {
6299
6972
  return { type: "text", title, data: { content: data } };
6300
6973
  }
6301
6974
  const docs = Array.isArray(data) ? data : [];
6302
- const text = docs.map((d) => d.content).join("\n\n");
6975
+ const text = docs.map((d) => {
6976
+ var _a2;
6977
+ return (_a2 = d == null ? void 0 : d.content) != null ? _a2 : "";
6978
+ }).join("\n\n");
6303
6979
  return { type: "text", title, data: { content: text || "No detailed content available." } };
6304
6980
  }
6305
6981
  };
@@ -6548,6 +7224,19 @@ var UITransformer = class _UITransformer {
6548
7224
  if (!retrievedData || retrievedData.length === 0) {
6549
7225
  return this.createTextResponse("No data available", "No relevant data found for your query.");
6550
7226
  }
7227
+ console.log("[UITransformer.transform] Processing retrievedData:", {
7228
+ userQuery,
7229
+ retrievedCount: retrievedData.length,
7230
+ sample: retrievedData.slice(0, 2).map((item) => {
7231
+ var _a3;
7232
+ return {
7233
+ id: item == null ? void 0 : item.id,
7234
+ contentType: typeof (item == null ? void 0 : item.content),
7235
+ contentSnippet: String((_a3 = item == null ? void 0 : item.content) != null ? _a3 : "").substring(0, 150),
7236
+ metadataKeys: Object.keys((item == null ? void 0 : item.metadata) || {})
7237
+ };
7238
+ })
7239
+ });
6551
7240
  const resolvedIntent = intent != null ? intent : this.detectIntentHeuristic(userQuery);
6552
7241
  const filteredData = resolvedIntent.filterInStockOnly ? retrievedData.filter((item) => this.determineStockStatus(item)) : retrievedData;
6553
7242
  const profile = this.profileData(filteredData);
@@ -6888,7 +7577,7 @@ ${schemaProfileText}` : ""}`;
6888
7577
  }
6889
7578
  // ─── Transform Helpers ────────────────────────────────────────────────────
6890
7579
  static transformToProductCarousel(data, config, trainedSchema) {
6891
- const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null).slice(0, 15);
7580
+ const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null);
6892
7581
  return {
6893
7582
  type: "product_carousel",
6894
7583
  title: "Recommended Products",
@@ -7037,7 +7726,10 @@ ${schemaProfileText}` : ""}`;
7037
7726
  type: "radar_chart",
7038
7727
  title: "Product Comparison",
7039
7728
  description: `Comparing ${data.length} items across ${radarData.length} attributes`,
7040
- data: radarData.length > 0 ? radarData : data.map((d) => ({ attribute: d.content.substring(0, 40) }))
7729
+ data: radarData.length > 0 ? radarData : data.map((d) => {
7730
+ var _a2;
7731
+ return { attribute: ((_a2 = d == null ? void 0 : d.content) != null ? _a2 : "").substring(0, 40) };
7732
+ })
7041
7733
  };
7042
7734
  }
7043
7735
  static transformToTable(data, query = "") {
@@ -7054,7 +7746,10 @@ ${schemaProfileText}` : ""}`;
7054
7746
  static transformToText(data) {
7055
7747
  return this.createTextResponse(
7056
7748
  "Retrieved Context",
7057
- data.map((item) => item.content).join("\n\n"),
7749
+ data.map((item) => {
7750
+ var _a2;
7751
+ return (_a2 = item == null ? void 0 : item.content) != null ? _a2 : "";
7752
+ }).join("\n\n"),
7058
7753
  `Found ${data.length} relevant results`
7059
7754
  );
7060
7755
  }
@@ -7215,6 +7910,7 @@ ${schemaProfileText}` : ""}`;
7215
7910
  return productTerms && productAction && !nonProductEntityTerms;
7216
7911
  }
7217
7912
  static isProductData(item) {
7913
+ if (!item) return false;
7218
7914
  const content = (item.content || "").toLowerCase();
7219
7915
  const productKeywords = [
7220
7916
  "product",
@@ -7261,7 +7957,8 @@ ${schemaProfileText}` : ""}`;
7261
7957
  return fieldCount.size > 2;
7262
7958
  }
7263
7959
  static profileData(data) {
7264
- const records = data.map((item) => {
7960
+ const records = (data || []).filter((item) => Boolean(item && typeof item === "object")).map((item) => {
7961
+ var _a2, _b;
7265
7962
  const fields2 = {};
7266
7963
  Object.entries(item.metadata || {}).forEach(([key, value]) => {
7267
7964
  const primitive = this.toPrimitive(value);
@@ -7270,8 +7967,8 @@ ${schemaProfileText}` : ""}`;
7270
7967
  if (!fields2.content && item.content) fields2.content = item.content.substring(0, 500);
7271
7968
  return {
7272
7969
  id: item.id,
7273
- content: item.content,
7274
- score: item.score,
7970
+ content: (_a2 = item.content) != null ? _a2 : "",
7971
+ score: (_b = item.score) != null ? _b : 0,
7275
7972
  fields: fields2,
7276
7973
  source: item
7277
7974
  };
@@ -7473,12 +8170,12 @@ ${schemaProfileText}` : ""}`;
7473
8170
  }
7474
8171
  static extractTimeSeriesData(data) {
7475
8172
  return data.map((item) => {
7476
- var _a2, _b, _c, _d, _e;
8173
+ var _a2, _b, _c, _d, _e, _f;
7477
8174
  const meta = item.metadata || {};
7478
8175
  return {
7479
8176
  timestamp: (_b = (_a2 = meta.timestamp) != null ? _a2 : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
7480
8177
  value: (_d = (_c = meta.value) != null ? _c : item.score) != null ? _d : 0,
7481
- label: (_e = meta.label) != null ? _e : item.content.substring(0, 50)
8178
+ label: (_f = meta.label) != null ? _f : ((_e = item == null ? void 0 : item.content) != null ? _e : "").substring(0, 50)
7482
8179
  };
7483
8180
  });
7484
8181
  }
@@ -7592,7 +8289,8 @@ ${schemaProfileText}` : ""}`;
7592
8289
  }, query.includes(normalizedField) ? 3 : 0);
7593
8290
  }
7594
8291
  static resolveTableCellValue(item, column) {
7595
- if (column === "Content") return item.content.substring(0, 100);
8292
+ var _a2, _b, _c;
8293
+ if (column === "Content") return ((_a2 = item == null ? void 0 : item.content) != null ? _a2 : "").substring(0, 100);
7596
8294
  const meta = item.metadata || {};
7597
8295
  const normalizedColumn = this.normalizeComparableField(column);
7598
8296
  const exactMetadata = Object.entries(meta).find(
@@ -7603,9 +8301,9 @@ ${schemaProfileText}` : ""}`;
7603
8301
  }
7604
8302
  const aliasValue = this.resolveAliasedTableCell(meta, column);
7605
8303
  if (aliasValue !== void 0) return this.toDisplayValue(aliasValue);
7606
- const contentValue = this.extractContentFieldValue(item.content, column);
8304
+ const contentValue = this.extractContentFieldValue((_b = item == null ? void 0 : item.content) != null ? _b : "", column);
7607
8305
  if (contentValue !== null) return contentValue;
7608
- const aliasContentValue = this.extractAliasedContentFieldValue(item.content, column);
8306
+ const aliasContentValue = this.extractAliasedContentFieldValue((_c = item == null ? void 0 : item.content) != null ? _c : "", column);
7609
8307
  return aliasContentValue != null ? aliasContentValue : "";
7610
8308
  }
7611
8309
  static resolveAliasedTableCell(meta, column) {
@@ -7655,6 +8353,7 @@ ${schemaProfileText}` : ""}`;
7655
8353
  return { inStockCount: inStock, outOfStockCount: outOfStock };
7656
8354
  }
7657
8355
  static determineStockStatus(item) {
8356
+ if (!item) return true;
7658
8357
  const meta = item.metadata || {};
7659
8358
  const stockValue = resolveMetadataValue(meta, "stock");
7660
8359
  if (stockValue !== void 0) {
@@ -7700,35 +8399,64 @@ ${schemaProfileText}` : ""}`;
7700
8399
  return resolveMetadataValue(meta, uiKey);
7701
8400
  }
7702
8401
  static extractProductInfo(item, config, trainedSchema) {
7703
- var _a2;
8402
+ var _a2, _b;
8403
+ if (!item) return null;
7704
8404
  const meta = item.metadata || {};
8405
+ const content = item.content || "";
7705
8406
  const name = this.getDynamicVal(meta, "name", config, trainedSchema);
7706
8407
  const price = this.getDynamicVal(meta, "price", config, trainedSchema);
7707
8408
  const brand = this.getDynamicVal(meta, "brand", config, trainedSchema);
7708
8409
  const description = this.cleanProductDescription(
7709
- (_a2 = this.extractProductDescriptionFromContent(item.content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
8410
+ (_a2 = this.extractProductDescriptionFromContent(content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
7710
8411
  );
7711
8412
  if (name || this.isProductData(item)) {
7712
8413
  let finalName = name ? String(name) : void 0;
8414
+ if (!finalName && content) {
8415
+ const nameMatch = content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
8416
+ finalName = nameMatch ? nameMatch[1].trim() : (_b = content.split("\n")[0]) == null ? void 0 : _b.substring(0, 60);
8417
+ }
7713
8418
  if (!finalName) {
7714
- const nameMatch = item.content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
7715
- finalName = nameMatch ? nameMatch[1].trim() : item.content.split("\n")[0].substring(0, 60);
8419
+ console.warn(
8420
+ `[UITransformer] Unable to read product name from metadata or content for item ${item.id}. Defaulting to 'Unnamed Product'.`,
8421
+ { metadataKeys: Object.keys(meta), contentLength: content.length }
8422
+ );
7716
8423
  }
7717
8424
  let finalPrice = typeof price === "number" || typeof price === "string" ? price : void 0;
7718
- if (!finalPrice) {
7719
- const priceMatch = item.content.match(/(?:Price|Cost):\s*\$?([\d,.]+)/i) || item.content.match(/\$\s*([\d,.]+)/);
8425
+ if (!finalPrice && content) {
8426
+ const priceMatch = content.match(/(?:Price|Cost):\s*\$?([\d,.]+)/i) || content.match(/\$\s*([\d,.]+)/);
7720
8427
  if (priceMatch) finalPrice = priceMatch[1].replace(/,/g, "");
7721
8428
  }
8429
+ if (finalPrice === void 0) {
8430
+ console.warn(
8431
+ `[UITransformer] Unable to read product price from metadata or content for item ${item.id}.`,
8432
+ { metadataKeys: Object.keys(meta), contentSnippet: content.substring(0, 100) }
8433
+ );
8434
+ }
7722
8435
  const imageValue = this.getDynamicVal(meta, "image", config, trainedSchema);
8436
+ if (!imageValue) {
8437
+ console.debug(
8438
+ `[UITransformer] Unable to read product image URL from metadata for item ${item.id}.`
8439
+ );
8440
+ }
8441
+ if (!description) {
8442
+ console.debug(
8443
+ `[UITransformer] Unable to read product description from metadata or content for item ${item.id}.`
8444
+ );
8445
+ }
7723
8446
  return {
7724
8447
  id: item.id,
7725
- name: finalName,
8448
+ name: finalName || "Unnamed Product",
7726
8449
  price: finalPrice,
7727
8450
  image: typeof imageValue === "string" ? imageValue : void 0,
7728
8451
  brand: brand ? String(brand) : void 0,
7729
8452
  description,
7730
8453
  inStock: this.determineStockStatus(item)
7731
8454
  };
8455
+ } else {
8456
+ console.warn(
8457
+ `[UITransformer] Item ${item.id} skipped: unable to read name or identify as product data from metadata/content.`,
8458
+ { metadataKeys: Object.keys(meta), contentSnippet: content.substring(0, 100) }
8459
+ );
7732
8460
  }
7733
8461
  return null;
7734
8462
  }
@@ -7813,13 +8541,13 @@ RULES:
7813
8541
  5. If no relevant data is found, return text: "I cannot answer this question based on the available information."`;
7814
8542
  }
7815
8543
  static buildContextSummary(sources, maxChars = 6e3) {
7816
- const items = sources.map((s, i) => {
8544
+ const items = (sources || []).filter(Boolean).map((s, i) => {
7817
8545
  var _a2, _b, _c, _d;
7818
8546
  return {
7819
8547
  index: i + 1,
7820
- content: (_b = (_a2 = s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
7821
- metadata: (_c = s.metadata) != null ? _c : {},
7822
- score: (_d = s.score) != null ? _d : 0
8548
+ content: (_b = (_a2 = s == null ? void 0 : s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
8549
+ metadata: (_c = s == null ? void 0 : s.metadata) != null ? _c : {},
8550
+ score: (_d = s == null ? void 0 : s.score) != null ? _d : 0
7823
8551
  };
7824
8552
  });
7825
8553
  const full = JSON.stringify(items, null, 2);
@@ -8343,7 +9071,7 @@ ${m.content}`).join("\n\n---\n\n");
8343
9071
  */
8344
9072
  askStreamInternal(_0) {
8345
9073
  return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
8346
- 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;
9074
+ 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;
8347
9075
  yield new __await(this.initialize());
8348
9076
  const ns = formatNamespace(namespace != null ? namespace : this.config.projectId);
8349
9077
  const topK = (_b = (_a2 = this.config.rag) == null ? void 0 : _a2.topK) != null ? _b : 5;
@@ -8386,40 +9114,65 @@ ${m.content}`).join("\n\n---\n\n");
8386
9114
  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;
8387
9115
  const hasMetadataFilter = filter.metadata && Object.keys(filter.metadata).length > 0;
8388
9116
  const hasNumericPredicates = Array.isArray(filter.__numericPredicates) && filter.__numericPredicates.length > 0;
8389
- const wantsExhaustiveList = hasNumericPredicates || hasMetadataFilter || /\b(list|all|show|provide|give|get|browse|find|search|display)\b/i.test(question);
8390
- const retrievalLimit = wantsExhaustiveList ? Math.max(topK * 20, 100) : topK * 2;
8391
- const rawSources = (strategyResult === "vector" || strategyResult === "both") && queryVector && queryVector.length > 0 ? yield new __await(this.vectorDB.query(queryVector, retrievalLimit, ns, filter)) : [];
9117
+ const wantsExhaustiveList = true;
9118
+ const retrievalLimit = Math.max(topK * 50, 1e3);
9119
+ 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"));
9120
+ console.log("[Pipeline] Raw vectorDB.query response:", {
9121
+ rawCount: rawSources.length,
9122
+ sample: rawSources.slice(0, 2).map((s) => {
9123
+ var _a3;
9124
+ return {
9125
+ id: s == null ? void 0 : s.id,
9126
+ score: s == null ? void 0 : s.score,
9127
+ contentType: typeof (s == null ? void 0 : s.content),
9128
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9129
+ metadataKeys: Object.keys((s == null ? void 0 : s.metadata) || {})
9130
+ };
9131
+ })
9132
+ });
8392
9133
  const retrieveEnd = performance.now();
8393
9134
  const embedMs = retrieveEnd - embedStart;
8394
9135
  const retrieveMs = retrieveEnd - embedStart;
8395
9136
  const rerankStart = performance.now();
8396
- const structuredSources = this.applyStructuredFilters(rawSources, filter);
8397
- let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => m.score >= scoreThreshold);
8398
- const rerankLimit = wantsExhaustiveList ? retrievalLimit : topK;
9137
+ const structuredSources = this.applyStructuredFilters(rawSources, filter).filter((s) => Boolean(s && typeof s === "object"));
9138
+ let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => {
9139
+ var _a3;
9140
+ return ((_a3 = m == null ? void 0 : m.score) != null ? _a3 : 0) >= scoreThreshold;
9141
+ });
9142
+ const rerankLimit = Math.max(retrievalLimit, fullSources.length);
8399
9143
  const useReranking = arch !== "naive" && (arch === "retrieve-and-rerank" || ((_m = this.config.rag) == null ? void 0 : _m.useReranking));
8400
9144
  if (!hasNumericPredicates && useReranking) {
8401
- fullSources = yield new __await(this.reranker.rerank(fullSources, question, rerankLimit));
8402
- } else if (!wantsExhaustiveList) {
8403
- fullSources = fullSources.slice(0, topK);
9145
+ fullSources = (yield new __await(this.reranker.rerank(fullSources, question, rerankLimit))).filter((s) => Boolean(s && typeof s === "object"));
8404
9146
  }
8405
9147
  const rerankMs = performance.now() - rerankStart;
8406
- let context = fullSources.length ? fullSources.map((m, i) => {
9148
+ const totalCount = fullSources.length;
9149
+ const promptSources = fullSources.slice(0, 15);
9150
+ 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]
9151
+
9152
+ ` + promptSources.map((m, i) => {
8407
9153
  var _a3;
8408
9154
  return `[Source ${i + 1}]
8409
9155
  ${(_a3 = m == null ? void 0 : m.content) != null ? _a3 : ""}`;
8410
9156
  }).join("\n\n---\n\n") : "No relevant context found.";
8411
- let displayCount = 15;
8412
- if (hasMetadataFilter) {
8413
- displayCount = fullSources.length;
8414
- } else {
8415
- const baseThreshold = Math.max(scoreThreshold, 0.4);
8416
- const highlyRelevant = fullSources.filter((m) => m.score >= baseThreshold);
8417
- displayCount = Math.max(highlyRelevant.length, topK);
8418
- if (displayCount > 15) {
8419
- displayCount = 15;
8420
- }
8421
- }
8422
- const sources = [...fullSources].sort((a, b) => b.score - a.score).slice(0, displayCount);
9157
+ const sources = [...fullSources].filter((s) => Boolean(s && typeof s === "object")).sort((a, b) => {
9158
+ var _a3, _b2;
9159
+ return ((_a3 = b == null ? void 0 : b.score) != null ? _a3 : 0) - ((_b2 = a == null ? void 0 : a.score) != null ? _b2 : 0);
9160
+ });
9161
+ console.log("[Pipeline] Final sources for prompt & UI:", {
9162
+ count: sources.length,
9163
+ totalRawCount: rawSources.length,
9164
+ sources: sources.slice(0, 10).map((s, idx) => {
9165
+ var _a3;
9166
+ return {
9167
+ rank: idx + 1,
9168
+ id: s == null ? void 0 : s.id,
9169
+ score: s == null ? void 0 : s.score,
9170
+ contentType: typeof (s == null ? void 0 : s.content),
9171
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9172
+ metadata: s == null ? void 0 : s.metadata
9173
+ };
9174
+ })
9175
+ });
8423
9176
  if (graphData && graphData.nodes.length > 0) {
8424
9177
  const graphContext = graphData.nodes.map(
8425
9178
  (n) => `Entity: ${n.label} (${n.id})${n.properties ? " - " + JSON.stringify(n.properties) : ""}`
@@ -8445,18 +9198,18 @@ ${context}`;
8445
9198
  }
8446
9199
  yield {
8447
9200
  reply: "",
8448
- sources: sources.map((s) => {
8449
- var _a3;
9201
+ sources: (sources || []).filter((s) => Boolean(s && typeof s === "object")).map((s) => {
9202
+ var _a3, _b2, _c2;
8450
9203
  return {
8451
9204
  id: s.id,
8452
- score: s.score,
8453
- content: s.content,
8454
- metadata: (_a3 = s.metadata) != null ? _a3 : {},
9205
+ score: (_a3 = s.score) != null ? _a3 : 0,
9206
+ content: (_b2 = s == null ? void 0 : s.content) != null ? _b2 : "",
9207
+ metadata: (_c2 = s == null ? void 0 : s.metadata) != null ? _c2 : {},
8455
9208
  namespace: ns
8456
9209
  };
8457
9210
  })
8458
9211
  };
8459
- const allMetadataKeys = Array.from(new Set(sources.flatMap((s) => Object.keys(s.metadata || {}))));
9212
+ const allMetadataKeys = Array.from(new Set(sources.filter(Boolean).flatMap((s) => Object.keys((s == null ? void 0 : s.metadata) || {}))));
8460
9213
  const cachedSchema = allMetadataKeys.length > 0 ? SchemaMapper.getCached(ns, allMetadataKeys) : void 0;
8461
9214
  if (allMetadataKeys.length > 0 && !cachedSchema) {
8462
9215
  SchemaMapper.train(this.llmProvider, ns, allMetadataKeys).catch(() => {
@@ -8608,7 +9361,7 @@ ${context}`;
8608
9361
  }
8609
9362
  yield fullReply;
8610
9363
  }
8611
- 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;
9364
+ const runHallucination = ((_w = this.config.llm.options) == null ? void 0 : _w.hallucinationScoring) === true;
8612
9365
  if (runHallucination) {
8613
9366
  hallucinationScoringPromise = scoreHallucination(this.llmProvider, fullReply, context).catch(() => void 0);
8614
9367
  }
@@ -8617,7 +9370,7 @@ ${context}`;
8617
9370
  const latency = {
8618
9371
  embedMs: Math.round(embedMs),
8619
9372
  retrieveMs: Math.round(retrieveMs),
8620
- rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_y = this.config.rag) == null ? void 0 : _y.useReranking)) ? Math.round(rerankMs) : void 0,
9373
+ rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_x = this.config.rag) == null ? void 0 : _x.useReranking)) ? Math.round(rerankMs) : void 0,
8621
9374
  generateMs: Math.round(generateMs),
8622
9375
  totalMs: Math.round(totalMs)
8623
9376
  };
@@ -8630,7 +9383,7 @@ ${context}`;
8630
9383
  totalTokens: promptTokens + completionTokens,
8631
9384
  estimatedCostUsd: estimateCostUsd(promptTokens, completionTokens, this.config.llm.model)
8632
9385
  };
8633
- const awaitHallucination = ((_z = this.config.llm.options) == null ? void 0 : _z.awaitHallucination) === true;
9386
+ const awaitHallucination = ((_y = this.config.llm.options) == null ? void 0 : _y.awaitHallucination) === true;
8634
9387
  const [uiTransformation, hallucinationResult] = yield new __await(Promise.all([
8635
9388
  uiTransformationPromise,
8636
9389
  awaitHallucination ? hallucinationScoringPromise : Promise.resolve(void 0)
@@ -8659,10 +9412,10 @@ ${context}`;
8659
9412
  hallucinationReason: hScore.reason
8660
9413
  } : {});
8661
9414
  const trace = buildTrace(hallucinationResult);
8662
- const isTelemetryActive = (_B = (_A = this.config.telemetry) == null ? void 0 : _A.enabled) != null ? _B : Boolean(this.config.licenseKey);
9415
+ const isTelemetryActive = (_A = (_z = this.config.telemetry) == null ? void 0 : _z.enabled) != null ? _A : Boolean(this.config.licenseKey);
8663
9416
  if (isTelemetryActive) {
8664
9417
  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";
8665
- const telemetryUrl = ((_C = this.config.telemetry) == null ? void 0 : _C.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
9418
+ const telemetryUrl = ((_B = this.config.telemetry) == null ? void 0 : _B.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
8666
9419
  const absoluteUrl = telemetryUrl.startsWith("http") ? telemetryUrl : (process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${process.env.PORT || 3e3}`) + telemetryUrl;
8667
9420
  (async () => {
8668
9421
  try {
@@ -8721,9 +9474,8 @@ ${context}`;
8721
9474
  { visualizationHint: "product_browse", recommendedChart: "text", filterInStockOnly: false, wantsExplicitTable: false, isTemporal: false, isComparison: false, language: "en" }
8722
9475
  );
8723
9476
  }
8724
- const isLocalProvider = this.config.llm.provider === "ollama";
8725
- const disableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.disableLlmUiTransform) === true;
8726
- if (forceDeterministic || isLocalProvider || disableLlmUiTransform) {
9477
+ const enableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.enableLlmUiTransform) === true;
9478
+ if (forceDeterministic || !enableLlmUiTransform) {
8727
9479
  return UITransformer.transform(question, sources, this.config, cachedSchema);
8728
9480
  }
8729
9481
  try {
@@ -8748,6 +9500,8 @@ ${context}`;
8748
9500
  });
8749
9501
  }
8750
9502
  resolveNumericPredicateValue(source, predicate) {
9503
+ var _a2;
9504
+ if (!source) return null;
8751
9505
  const meta = source.metadata || {};
8752
9506
  const field = predicate.field;
8753
9507
  const entries = Object.entries(meta).filter(([, value]) => value !== null && value !== void 0 && typeof value !== "object");
@@ -8759,7 +9513,7 @@ ${context}`;
8759
9513
  const value = this.toFiniteNumber(Array.isArray(fuzzy) ? fuzzy[1] : fuzzy.value);
8760
9514
  if (value !== null) return value;
8761
9515
  }
8762
- const contentValue = this.extractNumericValueFromContent(source.content, field);
9516
+ const contentValue = this.extractNumericValueFromContent((_a2 = source.content) != null ? _a2 : "", field);
8763
9517
  if (contentValue !== null) return contentValue;
8764
9518
  }
8765
9519
  for (const [key, value] of entries) {
@@ -8770,6 +9524,7 @@ ${context}`;
8770
9524
  return null;
8771
9525
  }
8772
9526
  extractNumericValueFromContent(content, field) {
9527
+ if (!content || typeof content !== "string") return null;
8773
9528
  const escapedWords = field.split(/\s+|_+|-+/).filter(Boolean).map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
8774
9529
  if (escapedWords.length === 0) return null;
8775
9530
  const pattern = new RegExp(`(?:${escapedWords.join("[\\\\s_:-]*")})\\s*[:\\-\u2013]?\\s*([\\d,]+(?:\\.\\d+)?)`, "i");
@@ -8855,6 +9610,20 @@ ${context}`;
8855
9610
  resolvedSources.push(source);
8856
9611
  }
8857
9612
  }
9613
+ console.log("[Pipeline] retrieve() response:", {
9614
+ query,
9615
+ namespace: ns,
9616
+ count: resolvedSources.length,
9617
+ sample: resolvedSources.slice(0, 2).map((s) => {
9618
+ var _a3;
9619
+ return {
9620
+ id: s == null ? void 0 : s.id,
9621
+ score: s == null ? void 0 : s.score,
9622
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9623
+ metadata: s == null ? void 0 : s.metadata
9624
+ };
9625
+ })
9626
+ });
8858
9627
  return { sources: resolvedSources, graphData };
8859
9628
  }
8860
9629
  /** Rewrite the user query for better retrieval performance. */