@retrivora-ai/rag-engine 2.0.6 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.mjs CHANGED
@@ -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({
@@ -3880,6 +4483,17 @@ var VECTOR_PROFILES = {
3880
4483
  };
3881
4484
 
3882
4485
  // src/llm/providers/UniversalLLMAdapter.ts
4486
+ function extractContent(obj) {
4487
+ var _a2, _b, _c;
4488
+ if (!obj || typeof obj !== "object") return void 0;
4489
+ const choice = (_a2 = obj.choices) == null ? void 0 : _a2[0];
4490
+ if (!choice) return void 0;
4491
+ if (typeof ((_b = choice.message) == null ? void 0 : _b.content) === "string") return choice.message.content;
4492
+ if (typeof ((_c = choice.delta) == null ? void 0 : _c.content) === "string") return choice.delta.content;
4493
+ if (typeof choice.text === "string") return choice.text;
4494
+ if (typeof choice.content === "string") return choice.content;
4495
+ return void 0;
4496
+ }
3883
4497
  var UniversalLLMAdapter = class {
3884
4498
  constructor(config) {
3885
4499
  var _a2, _b, _c, _d, _e, _f, _g2, _h;
@@ -3911,7 +4525,7 @@ var UniversalLLMAdapter = class {
3911
4525
  });
3912
4526
  }
3913
4527
  async chat(messages, context) {
3914
- var _a2, _b, _c, _d, _e, _f;
4528
+ var _a2, _b, _c;
3915
4529
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3916
4530
  const formattedMessages = [
3917
4531
  { role: "system", content: `${this.systemPrompt}
@@ -3938,25 +4552,42 @@ ${context != null ? context : "None"}` },
3938
4552
  }
3939
4553
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
3940
4554
  if (isSelfHost || Boolean(process.env.VERCEL)) {
3941
- try {
3942
- const _g2 = globalThis;
3943
- if (typeof _g2.__retrivoraDispatchChat === "function") {
3944
- const res = await _g2.__retrivoraDispatchChat({
4555
+ const _g2 = globalThis;
4556
+ let dispatch = _g2.__retrivoraDispatchChat;
4557
+ if (typeof dispatch !== "function") {
4558
+ try {
4559
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4560
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4561
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4562
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4563
+ dispatch = gateway.dispatchChatCompletion;
4564
+ }
4565
+ } catch (e) {
4566
+ }
4567
+ }
4568
+ if (typeof dispatch === "function") {
4569
+ try {
4570
+ const res = await dispatch({
3945
4571
  model: this.model,
3946
4572
  messages: formattedMessages,
3947
4573
  max_tokens: this.maxTokens,
3948
4574
  temperature: this.temperature
3949
4575
  }, this.apiKey);
3950
- 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) {
3951
- return res.response.choices[0].message.content;
4576
+ const content = extractContent(res == null ? void 0 : res.response);
4577
+ if (content !== void 0) {
4578
+ return content;
3952
4579
  }
4580
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch returned empty content for model: ${this.model}`);
4581
+ } catch (dispatchErr) {
4582
+ throw dispatchErr;
3953
4583
  }
3954
- } catch (e) {
4584
+ } else {
4585
+ 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.`);
3955
4586
  }
3956
4587
  }
3957
4588
  const { data } = await this.http.post(path2, payload);
3958
- const extractPath = (_f = this.opts.responseExtractPath) != null ? _f : "choices[0].message.content";
3959
- const result = resolvePath(data, extractPath);
4589
+ const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
4590
+ const result = (_c = resolvePath(data, extractPath)) != null ? _c : extractContent(data);
3960
4591
  if (result === void 0) {
3961
4592
  throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
3962
4593
  }
@@ -3969,7 +4600,7 @@ ${context != null ? context : "None"}` },
3969
4600
  */
3970
4601
  chatStream(messages, context) {
3971
4602
  return __asyncGenerator(this, null, function* () {
3972
- var _a2, _b, _c, _d, _e, _f, _g2;
4603
+ var _a2, _b, _c, _d, _e;
3973
4604
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3974
4605
  const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
3975
4606
  const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
@@ -4003,10 +4634,22 @@ ${context != null ? context : "None"}` },
4003
4634
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4004
4635
  let streamBody = null;
4005
4636
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4006
- try {
4007
- const _g3 = globalThis;
4008
- if (typeof _g3.__retrivoraDispatchChat === "function") {
4009
- const res = yield new __await(_g3.__retrivoraDispatchChat({
4637
+ const _g2 = globalThis;
4638
+ let dispatch = _g2.__retrivoraDispatchChat;
4639
+ if (typeof dispatch !== "function") {
4640
+ try {
4641
+ const gateway = yield new __await(Promise.resolve().then(() => (init_router(), router_exports)));
4642
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4643
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4644
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4645
+ dispatch = gateway.dispatchChatCompletion;
4646
+ }
4647
+ } catch (e) {
4648
+ }
4649
+ }
4650
+ if (typeof dispatch === "function") {
4651
+ try {
4652
+ const res = yield new __await(dispatch({
4010
4653
  model: this.model,
4011
4654
  messages: formattedMessages,
4012
4655
  max_tokens: this.maxTokens,
@@ -4015,12 +4658,19 @@ ${context != null ? context : "None"}` },
4015
4658
  }, this.apiKey));
4016
4659
  if (res == null ? void 0 : res.stream) {
4017
4660
  streamBody = res.stream;
4018
- } 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) {
4019
- yield res.response.choices[0].message.content;
4020
- return;
4661
+ } else {
4662
+ const content = extractContent(res == null ? void 0 : res.response);
4663
+ if (content !== void 0) {
4664
+ yield content;
4665
+ return;
4666
+ }
4667
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch stream returned empty response for model: ${this.model}`);
4021
4668
  }
4669
+ } catch (dispatchErr) {
4670
+ throw dispatchErr;
4022
4671
  }
4023
- } catch (e) {
4672
+ } else {
4673
+ 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.`);
4024
4674
  }
4025
4675
  }
4026
4676
  if (!streamBody) {
@@ -4047,14 +4697,14 @@ ${context != null ? context : "None"}` },
4047
4697
  if (done) break;
4048
4698
  buffer += decoder.decode(value, { stream: true });
4049
4699
  const lines = buffer.split("\n");
4050
- buffer = (_g2 = lines.pop()) != null ? _g2 : "";
4700
+ buffer = (_c = lines.pop()) != null ? _c : "";
4051
4701
  for (const line of lines) {
4052
4702
  const trimmed = line.trim();
4053
4703
  if (!trimmed || trimmed === "data: [DONE]") continue;
4054
4704
  if (!trimmed.startsWith("data:")) continue;
4055
4705
  try {
4056
4706
  const json = JSON.parse(trimmed.slice(5).trim());
4057
- const text = resolvePath(json, extractPath);
4707
+ const text = (_d = resolvePath(json, extractPath)) != null ? _d : extractContent(json);
4058
4708
  if (text && typeof text === "string") yield text;
4059
4709
  } catch (e) {
4060
4710
  }
@@ -4064,7 +4714,7 @@ ${context != null ? context : "None"}` },
4064
4714
  const jsonStr = buffer.replace(/^data:\s*/, "").trim();
4065
4715
  try {
4066
4716
  const json = JSON.parse(jsonStr);
4067
- const text = resolvePath(json, extractPath);
4717
+ const text = (_e = resolvePath(json, extractPath)) != null ? _e : extractContent(json);
4068
4718
  if (text && typeof text === "string") yield text;
4069
4719
  } catch (e) {
4070
4720
  }
@@ -4091,18 +4741,34 @@ ${context != null ? context : "None"}` },
4091
4741
  }
4092
4742
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4093
4743
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4094
- try {
4095
- const _g2 = globalThis;
4096
- if (typeof _g2.__retrivoraDispatchEmbedding === "function") {
4097
- const res = await _g2.__retrivoraDispatchEmbedding({
4744
+ const _g2 = globalThis;
4745
+ let dispatch = _g2.__retrivoraDispatchEmbedding;
4746
+ if (typeof dispatch !== "function") {
4747
+ try {
4748
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4749
+ if (gateway == null ? void 0 : gateway.dispatchEmbedding) {
4750
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4751
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4752
+ dispatch = gateway.dispatchEmbedding;
4753
+ }
4754
+ } catch (e) {
4755
+ }
4756
+ }
4757
+ if (typeof dispatch === "function") {
4758
+ try {
4759
+ const res = await dispatch({
4098
4760
  model: this.model,
4099
4761
  input: text
4100
4762
  }, this.apiKey);
4101
4763
  if ((_c = (_b = res == null ? void 0 : res.data) == null ? void 0 : _b[0]) == null ? void 0 : _c.embedding) {
4102
4764
  return res.data[0].embedding;
4103
4765
  }
4766
+ throw new Error(`[UniversalLLMAdapter] In-process embedding dispatch returned invalid vector for model: ${this.model}`);
4767
+ } catch (dispatchErr) {
4768
+ throw dispatchErr;
4104
4769
  }
4105
- } catch (e) {
4770
+ } else {
4771
+ 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.`);
4106
4772
  }
4107
4773
  }
4108
4774
  const { data } = await this.http.post(path2, payload);
@@ -4695,7 +5361,8 @@ var Reranker = class {
4695
5361
  return matches.sort((a, b) => b.score - a.score).slice(0, limit);
4696
5362
  }
4697
5363
  const scoredMatches = matches.map((match) => {
4698
- const contentLower = match.content.toLowerCase();
5364
+ var _a2;
5365
+ const contentLower = ((_a2 = match == null ? void 0 : match.content) != null ? _a2 : "").toLowerCase();
4699
5366
  let keywordScore = 0;
4700
5367
  keywords.forEach((keyword) => {
4701
5368
  if (contentLower.includes(keyword)) {
@@ -4716,7 +5383,10 @@ var Reranker = class {
4716
5383
  [{ role: "user", content: `Query: "${query}"
4717
5384
 
4718
5385
  Documents:
4719
- ${topN.map((m, i) => `[${i}] ${m.content.replace(/\n/g, " ")}`).join("\n")}` }],
5386
+ ${topN.map((m, i) => {
5387
+ var _a2;
5388
+ return `[${i}] ${((_a2 = m == null ? void 0 : m.content) != null ? _a2 : "").replace(/\n/g, " ")}`;
5389
+ }).join("\n")}` }],
4720
5390
  "",
4721
5391
  {
4722
5392
  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.',
@@ -5887,10 +6557,10 @@ Return ONLY 'vector', 'graph', or 'both'. No explanation.`;
5887
6557
  "",
5888
6558
  { temperature: 0, maxTokens: 10 }
5889
6559
  );
5890
- const cleanResponse = response.trim().toLowerCase();
5891
- if (cleanResponse.includes("vector")) return "vector";
5892
- if (cleanResponse.includes("graph")) return "graph";
6560
+ const cleanResponse = (response != null ? response : "").trim().toLowerCase();
5893
6561
  if (cleanResponse.includes("both")) return "both";
6562
+ if (cleanResponse.includes("graph")) return "graph";
6563
+ if (cleanResponse.includes("vector")) return "vector";
5894
6564
  } catch (error) {
5895
6565
  console.warn("[QueryProcessor] LLM strategy classification failed, falling back to keywords:", error);
5896
6566
  }
@@ -6064,7 +6734,10 @@ var IntentClassifier = class {
6064
6734
  hasCategoricalFields = catKeys.size > 0;
6065
6735
  numericFieldCount = numericKeys.size;
6066
6736
  categoricalFieldCount = catKeys.size;
6067
- if (productKeyMatches >= 2 || docs.some((d) => d.content.toLowerCase().includes("price") || d.content.toLowerCase().includes("brand"))) {
6737
+ if (productKeyMatches >= 2 || docs.some((d) => {
6738
+ var _a2, _b;
6739
+ 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");
6740
+ })) {
6068
6741
  isProductLike = true;
6069
6742
  }
6070
6743
  }
@@ -6344,7 +7017,10 @@ var TextRendererStrategy = class {
6344
7017
  return { type: "text", title, data: { content: data } };
6345
7018
  }
6346
7019
  const docs = Array.isArray(data) ? data : [];
6347
- const text = docs.map((d) => d.content).join("\n\n");
7020
+ const text = docs.map((d) => {
7021
+ var _a2;
7022
+ return (_a2 = d == null ? void 0 : d.content) != null ? _a2 : "";
7023
+ }).join("\n\n");
6348
7024
  return { type: "text", title, data: { content: text || "No detailed content available." } };
6349
7025
  }
6350
7026
  };
@@ -6601,6 +7277,19 @@ var UITransformer = class _UITransformer {
6601
7277
  if (!retrievedData || retrievedData.length === 0) {
6602
7278
  return this.createTextResponse("No data available", "No relevant data found for your query.");
6603
7279
  }
7280
+ console.log("[UITransformer.transform] Processing retrievedData:", {
7281
+ userQuery,
7282
+ retrievedCount: retrievedData.length,
7283
+ sample: retrievedData.slice(0, 2).map((item) => {
7284
+ var _a3;
7285
+ return {
7286
+ id: item == null ? void 0 : item.id,
7287
+ contentType: typeof (item == null ? void 0 : item.content),
7288
+ contentSnippet: String((_a3 = item == null ? void 0 : item.content) != null ? _a3 : "").substring(0, 150),
7289
+ metadataKeys: Object.keys((item == null ? void 0 : item.metadata) || {})
7290
+ };
7291
+ })
7292
+ });
6604
7293
  const resolvedIntent = intent != null ? intent : this.detectIntentHeuristic(userQuery);
6605
7294
  const filteredData = resolvedIntent.filterInStockOnly ? retrievedData.filter((item) => this.determineStockStatus(item)) : retrievedData;
6606
7295
  const profile = this.profileData(filteredData);
@@ -6941,7 +7630,7 @@ ${schemaProfileText}` : ""}`;
6941
7630
  }
6942
7631
  // ─── Transform Helpers ────────────────────────────────────────────────────
6943
7632
  static transformToProductCarousel(data, config, trainedSchema) {
6944
- const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null).slice(0, 15);
7633
+ const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null);
6945
7634
  return {
6946
7635
  type: "product_carousel",
6947
7636
  title: "Recommended Products",
@@ -7090,7 +7779,10 @@ ${schemaProfileText}` : ""}`;
7090
7779
  type: "radar_chart",
7091
7780
  title: "Product Comparison",
7092
7781
  description: `Comparing ${data.length} items across ${radarData.length} attributes`,
7093
- data: radarData.length > 0 ? radarData : data.map((d) => ({ attribute: d.content.substring(0, 40) }))
7782
+ data: radarData.length > 0 ? radarData : data.map((d) => {
7783
+ var _a2;
7784
+ return { attribute: ((_a2 = d == null ? void 0 : d.content) != null ? _a2 : "").substring(0, 40) };
7785
+ })
7094
7786
  };
7095
7787
  }
7096
7788
  static transformToTable(data, query = "") {
@@ -7107,7 +7799,10 @@ ${schemaProfileText}` : ""}`;
7107
7799
  static transformToText(data) {
7108
7800
  return this.createTextResponse(
7109
7801
  "Retrieved Context",
7110
- data.map((item) => item.content).join("\n\n"),
7802
+ data.map((item) => {
7803
+ var _a2;
7804
+ return (_a2 = item == null ? void 0 : item.content) != null ? _a2 : "";
7805
+ }).join("\n\n"),
7111
7806
  `Found ${data.length} relevant results`
7112
7807
  );
7113
7808
  }
@@ -7268,6 +7963,7 @@ ${schemaProfileText}` : ""}`;
7268
7963
  return productTerms && productAction && !nonProductEntityTerms;
7269
7964
  }
7270
7965
  static isProductData(item) {
7966
+ if (!item) return false;
7271
7967
  const content = (item.content || "").toLowerCase();
7272
7968
  const productKeywords = [
7273
7969
  "product",
@@ -7314,7 +8010,8 @@ ${schemaProfileText}` : ""}`;
7314
8010
  return fieldCount.size > 2;
7315
8011
  }
7316
8012
  static profileData(data) {
7317
- const records = data.map((item) => {
8013
+ const records = (data || []).filter((item) => Boolean(item && typeof item === "object")).map((item) => {
8014
+ var _a2, _b;
7318
8015
  const fields2 = {};
7319
8016
  Object.entries(item.metadata || {}).forEach(([key, value]) => {
7320
8017
  const primitive = this.toPrimitive(value);
@@ -7323,8 +8020,8 @@ ${schemaProfileText}` : ""}`;
7323
8020
  if (!fields2.content && item.content) fields2.content = item.content.substring(0, 500);
7324
8021
  return {
7325
8022
  id: item.id,
7326
- content: item.content,
7327
- score: item.score,
8023
+ content: (_a2 = item.content) != null ? _a2 : "",
8024
+ score: (_b = item.score) != null ? _b : 0,
7328
8025
  fields: fields2,
7329
8026
  source: item
7330
8027
  };
@@ -7526,12 +8223,12 @@ ${schemaProfileText}` : ""}`;
7526
8223
  }
7527
8224
  static extractTimeSeriesData(data) {
7528
8225
  return data.map((item) => {
7529
- var _a2, _b, _c, _d, _e;
8226
+ var _a2, _b, _c, _d, _e, _f;
7530
8227
  const meta = item.metadata || {};
7531
8228
  return {
7532
8229
  timestamp: (_b = (_a2 = meta.timestamp) != null ? _a2 : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
7533
8230
  value: (_d = (_c = meta.value) != null ? _c : item.score) != null ? _d : 0,
7534
- label: (_e = meta.label) != null ? _e : item.content.substring(0, 50)
8231
+ label: (_f = meta.label) != null ? _f : ((_e = item == null ? void 0 : item.content) != null ? _e : "").substring(0, 50)
7535
8232
  };
7536
8233
  });
7537
8234
  }
@@ -7645,7 +8342,8 @@ ${schemaProfileText}` : ""}`;
7645
8342
  }, query.includes(normalizedField) ? 3 : 0);
7646
8343
  }
7647
8344
  static resolveTableCellValue(item, column) {
7648
- if (column === "Content") return item.content.substring(0, 100);
8345
+ var _a2, _b, _c;
8346
+ if (column === "Content") return ((_a2 = item == null ? void 0 : item.content) != null ? _a2 : "").substring(0, 100);
7649
8347
  const meta = item.metadata || {};
7650
8348
  const normalizedColumn = this.normalizeComparableField(column);
7651
8349
  const exactMetadata = Object.entries(meta).find(
@@ -7656,9 +8354,9 @@ ${schemaProfileText}` : ""}`;
7656
8354
  }
7657
8355
  const aliasValue = this.resolveAliasedTableCell(meta, column);
7658
8356
  if (aliasValue !== void 0) return this.toDisplayValue(aliasValue);
7659
- const contentValue = this.extractContentFieldValue(item.content, column);
8357
+ const contentValue = this.extractContentFieldValue((_b = item == null ? void 0 : item.content) != null ? _b : "", column);
7660
8358
  if (contentValue !== null) return contentValue;
7661
- const aliasContentValue = this.extractAliasedContentFieldValue(item.content, column);
8359
+ const aliasContentValue = this.extractAliasedContentFieldValue((_c = item == null ? void 0 : item.content) != null ? _c : "", column);
7662
8360
  return aliasContentValue != null ? aliasContentValue : "";
7663
8361
  }
7664
8362
  static resolveAliasedTableCell(meta, column) {
@@ -7708,6 +8406,7 @@ ${schemaProfileText}` : ""}`;
7708
8406
  return { inStockCount: inStock, outOfStockCount: outOfStock };
7709
8407
  }
7710
8408
  static determineStockStatus(item) {
8409
+ if (!item) return true;
7711
8410
  const meta = item.metadata || {};
7712
8411
  const stockValue = resolveMetadataValue(meta, "stock");
7713
8412
  if (stockValue !== void 0) {
@@ -7753,35 +8452,64 @@ ${schemaProfileText}` : ""}`;
7753
8452
  return resolveMetadataValue(meta, uiKey);
7754
8453
  }
7755
8454
  static extractProductInfo(item, config, trainedSchema) {
7756
- var _a2;
8455
+ var _a2, _b;
8456
+ if (!item) return null;
7757
8457
  const meta = item.metadata || {};
8458
+ const content = item.content || "";
7758
8459
  const name = this.getDynamicVal(meta, "name", config, trainedSchema);
7759
8460
  const price = this.getDynamicVal(meta, "price", config, trainedSchema);
7760
8461
  const brand = this.getDynamicVal(meta, "brand", config, trainedSchema);
7761
8462
  const description = this.cleanProductDescription(
7762
- (_a2 = this.extractProductDescriptionFromContent(item.content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
8463
+ (_a2 = this.extractProductDescriptionFromContent(content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
7763
8464
  );
7764
8465
  if (name || this.isProductData(item)) {
7765
8466
  let finalName = name ? String(name) : void 0;
8467
+ if (!finalName && content) {
8468
+ const nameMatch = content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
8469
+ finalName = nameMatch ? nameMatch[1].trim() : (_b = content.split("\n")[0]) == null ? void 0 : _b.substring(0, 60);
8470
+ }
7766
8471
  if (!finalName) {
7767
- const nameMatch = item.content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
7768
- finalName = nameMatch ? nameMatch[1].trim() : item.content.split("\n")[0].substring(0, 60);
8472
+ console.warn(
8473
+ `[UITransformer] Unable to read product name from metadata or content for item ${item.id}. Defaulting to 'Unnamed Product'.`,
8474
+ { metadataKeys: Object.keys(meta), contentLength: content.length }
8475
+ );
7769
8476
  }
7770
8477
  let finalPrice = typeof price === "number" || typeof price === "string" ? price : void 0;
7771
- if (!finalPrice) {
7772
- const priceMatch = item.content.match(/(?:Price|Cost):\s*\$?([\d,.]+)/i) || item.content.match(/\$\s*([\d,.]+)/);
8478
+ if (!finalPrice && content) {
8479
+ const priceMatch = content.match(/(?:Price|Cost):\s*\$?([\d,.]+)/i) || content.match(/\$\s*([\d,.]+)/);
7773
8480
  if (priceMatch) finalPrice = priceMatch[1].replace(/,/g, "");
7774
8481
  }
8482
+ if (finalPrice === void 0) {
8483
+ console.warn(
8484
+ `[UITransformer] Unable to read product price from metadata or content for item ${item.id}.`,
8485
+ { metadataKeys: Object.keys(meta), contentSnippet: content.substring(0, 100) }
8486
+ );
8487
+ }
7775
8488
  const imageValue = this.getDynamicVal(meta, "image", config, trainedSchema);
8489
+ if (!imageValue) {
8490
+ console.debug(
8491
+ `[UITransformer] Unable to read product image URL from metadata for item ${item.id}.`
8492
+ );
8493
+ }
8494
+ if (!description) {
8495
+ console.debug(
8496
+ `[UITransformer] Unable to read product description from metadata or content for item ${item.id}.`
8497
+ );
8498
+ }
7776
8499
  return {
7777
8500
  id: item.id,
7778
- name: finalName,
8501
+ name: finalName || "Unnamed Product",
7779
8502
  price: finalPrice,
7780
8503
  image: typeof imageValue === "string" ? imageValue : void 0,
7781
8504
  brand: brand ? String(brand) : void 0,
7782
8505
  description,
7783
8506
  inStock: this.determineStockStatus(item)
7784
8507
  };
8508
+ } else {
8509
+ console.warn(
8510
+ `[UITransformer] Item ${item.id} skipped: unable to read name or identify as product data from metadata/content.`,
8511
+ { metadataKeys: Object.keys(meta), contentSnippet: content.substring(0, 100) }
8512
+ );
7785
8513
  }
7786
8514
  return null;
7787
8515
  }
@@ -7866,13 +8594,13 @@ RULES:
7866
8594
  5. If no relevant data is found, return text: "I cannot answer this question based on the available information."`;
7867
8595
  }
7868
8596
  static buildContextSummary(sources, maxChars = 6e3) {
7869
- const items = sources.map((s, i) => {
8597
+ const items = (sources || []).filter(Boolean).map((s, i) => {
7870
8598
  var _a2, _b, _c, _d;
7871
8599
  return {
7872
8600
  index: i + 1,
7873
- content: (_b = (_a2 = s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
7874
- metadata: (_c = s.metadata) != null ? _c : {},
7875
- score: (_d = s.score) != null ? _d : 0
8601
+ content: (_b = (_a2 = s == null ? void 0 : s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
8602
+ metadata: (_c = s == null ? void 0 : s.metadata) != null ? _c : {},
8603
+ score: (_d = s == null ? void 0 : s.score) != null ? _d : 0
7876
8604
  };
7877
8605
  });
7878
8606
  const full = JSON.stringify(items, null, 2);
@@ -8396,7 +9124,7 @@ ${m.content}`).join("\n\n---\n\n");
8396
9124
  */
8397
9125
  askStreamInternal(_0) {
8398
9126
  return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
8399
- 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;
9127
+ 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;
8400
9128
  yield new __await(this.initialize());
8401
9129
  const ns = formatNamespace(namespace != null ? namespace : this.config.projectId);
8402
9130
  const topK = (_b = (_a2 = this.config.rag) == null ? void 0 : _a2.topK) != null ? _b : 5;
@@ -8439,40 +9167,65 @@ ${m.content}`).join("\n\n---\n\n");
8439
9167
  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;
8440
9168
  const hasMetadataFilter = filter.metadata && Object.keys(filter.metadata).length > 0;
8441
9169
  const hasNumericPredicates = Array.isArray(filter.__numericPredicates) && filter.__numericPredicates.length > 0;
8442
- const wantsExhaustiveList = hasNumericPredicates || hasMetadataFilter || /\b(list|all|show|provide|give|get|browse|find|search|display)\b/i.test(question);
8443
- const retrievalLimit = wantsExhaustiveList ? Math.max(topK * 20, 100) : topK * 2;
8444
- const rawSources = (strategyResult === "vector" || strategyResult === "both") && queryVector && queryVector.length > 0 ? yield new __await(this.vectorDB.query(queryVector, retrievalLimit, ns, filter)) : [];
9170
+ const wantsExhaustiveList = true;
9171
+ const retrievalLimit = Math.max(topK * 50, 1e3);
9172
+ 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"));
9173
+ console.log("[Pipeline] Raw vectorDB.query response:", {
9174
+ rawCount: rawSources.length,
9175
+ sample: rawSources.slice(0, 2).map((s) => {
9176
+ var _a3;
9177
+ return {
9178
+ id: s == null ? void 0 : s.id,
9179
+ score: s == null ? void 0 : s.score,
9180
+ contentType: typeof (s == null ? void 0 : s.content),
9181
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9182
+ metadataKeys: Object.keys((s == null ? void 0 : s.metadata) || {})
9183
+ };
9184
+ })
9185
+ });
8445
9186
  const retrieveEnd = performance.now();
8446
9187
  const embedMs = retrieveEnd - embedStart;
8447
9188
  const retrieveMs = retrieveEnd - embedStart;
8448
9189
  const rerankStart = performance.now();
8449
- const structuredSources = this.applyStructuredFilters(rawSources, filter);
8450
- let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => m.score >= scoreThreshold);
8451
- const rerankLimit = wantsExhaustiveList ? retrievalLimit : topK;
9190
+ const structuredSources = this.applyStructuredFilters(rawSources, filter).filter((s) => Boolean(s && typeof s === "object"));
9191
+ let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => {
9192
+ var _a3;
9193
+ return ((_a3 = m == null ? void 0 : m.score) != null ? _a3 : 0) >= scoreThreshold;
9194
+ });
9195
+ const rerankLimit = Math.max(retrievalLimit, fullSources.length);
8452
9196
  const useReranking = arch !== "naive" && (arch === "retrieve-and-rerank" || ((_m = this.config.rag) == null ? void 0 : _m.useReranking));
8453
9197
  if (!hasNumericPredicates && useReranking) {
8454
- fullSources = yield new __await(this.reranker.rerank(fullSources, question, rerankLimit));
8455
- } else if (!wantsExhaustiveList) {
8456
- fullSources = fullSources.slice(0, topK);
9198
+ fullSources = (yield new __await(this.reranker.rerank(fullSources, question, rerankLimit))).filter((s) => Boolean(s && typeof s === "object"));
8457
9199
  }
8458
9200
  const rerankMs = performance.now() - rerankStart;
8459
- let context = fullSources.length ? fullSources.map((m, i) => {
9201
+ const totalCount = fullSources.length;
9202
+ const promptSources = fullSources.slice(0, 15);
9203
+ 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]
9204
+
9205
+ ` + promptSources.map((m, i) => {
8460
9206
  var _a3;
8461
9207
  return `[Source ${i + 1}]
8462
9208
  ${(_a3 = m == null ? void 0 : m.content) != null ? _a3 : ""}`;
8463
9209
  }).join("\n\n---\n\n") : "No relevant context found.";
8464
- let displayCount = 15;
8465
- if (hasMetadataFilter) {
8466
- displayCount = fullSources.length;
8467
- } else {
8468
- const baseThreshold = Math.max(scoreThreshold, 0.4);
8469
- const highlyRelevant = fullSources.filter((m) => m.score >= baseThreshold);
8470
- displayCount = Math.max(highlyRelevant.length, topK);
8471
- if (displayCount > 15) {
8472
- displayCount = 15;
8473
- }
8474
- }
8475
- const sources = [...fullSources].sort((a, b) => b.score - a.score).slice(0, displayCount);
9210
+ const sources = [...fullSources].filter((s) => Boolean(s && typeof s === "object")).sort((a, b) => {
9211
+ var _a3, _b2;
9212
+ return ((_a3 = b == null ? void 0 : b.score) != null ? _a3 : 0) - ((_b2 = a == null ? void 0 : a.score) != null ? _b2 : 0);
9213
+ });
9214
+ console.log("[Pipeline] Final sources for prompt & UI:", {
9215
+ count: sources.length,
9216
+ totalRawCount: rawSources.length,
9217
+ sources: sources.slice(0, 10).map((s, idx) => {
9218
+ var _a3;
9219
+ return {
9220
+ rank: idx + 1,
9221
+ id: s == null ? void 0 : s.id,
9222
+ score: s == null ? void 0 : s.score,
9223
+ contentType: typeof (s == null ? void 0 : s.content),
9224
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9225
+ metadata: s == null ? void 0 : s.metadata
9226
+ };
9227
+ })
9228
+ });
8476
9229
  if (graphData && graphData.nodes.length > 0) {
8477
9230
  const graphContext = graphData.nodes.map(
8478
9231
  (n) => `Entity: ${n.label} (${n.id})${n.properties ? " - " + JSON.stringify(n.properties) : ""}`
@@ -8498,18 +9251,18 @@ ${context}`;
8498
9251
  }
8499
9252
  yield {
8500
9253
  reply: "",
8501
- sources: sources.map((s) => {
8502
- var _a3;
9254
+ sources: (sources || []).filter((s) => Boolean(s && typeof s === "object")).map((s) => {
9255
+ var _a3, _b2, _c2;
8503
9256
  return {
8504
9257
  id: s.id,
8505
- score: s.score,
8506
- content: s.content,
8507
- metadata: (_a3 = s.metadata) != null ? _a3 : {},
9258
+ score: (_a3 = s.score) != null ? _a3 : 0,
9259
+ content: (_b2 = s == null ? void 0 : s.content) != null ? _b2 : "",
9260
+ metadata: (_c2 = s == null ? void 0 : s.metadata) != null ? _c2 : {},
8508
9261
  namespace: ns
8509
9262
  };
8510
9263
  })
8511
9264
  };
8512
- const allMetadataKeys = Array.from(new Set(sources.flatMap((s) => Object.keys(s.metadata || {}))));
9265
+ const allMetadataKeys = Array.from(new Set(sources.filter(Boolean).flatMap((s) => Object.keys((s == null ? void 0 : s.metadata) || {}))));
8513
9266
  const cachedSchema = allMetadataKeys.length > 0 ? SchemaMapper.getCached(ns, allMetadataKeys) : void 0;
8514
9267
  if (allMetadataKeys.length > 0 && !cachedSchema) {
8515
9268
  SchemaMapper.train(this.llmProvider, ns, allMetadataKeys).catch(() => {
@@ -8661,7 +9414,7 @@ ${context}`;
8661
9414
  }
8662
9415
  yield fullReply;
8663
9416
  }
8664
- 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;
9417
+ const runHallucination = ((_w = this.config.llm.options) == null ? void 0 : _w.hallucinationScoring) === true;
8665
9418
  if (runHallucination) {
8666
9419
  hallucinationScoringPromise = scoreHallucination(this.llmProvider, fullReply, context).catch(() => void 0);
8667
9420
  }
@@ -8670,7 +9423,7 @@ ${context}`;
8670
9423
  const latency = {
8671
9424
  embedMs: Math.round(embedMs),
8672
9425
  retrieveMs: Math.round(retrieveMs),
8673
- rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_y = this.config.rag) == null ? void 0 : _y.useReranking)) ? Math.round(rerankMs) : void 0,
9426
+ rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_x = this.config.rag) == null ? void 0 : _x.useReranking)) ? Math.round(rerankMs) : void 0,
8674
9427
  generateMs: Math.round(generateMs),
8675
9428
  totalMs: Math.round(totalMs)
8676
9429
  };
@@ -8683,7 +9436,7 @@ ${context}`;
8683
9436
  totalTokens: promptTokens + completionTokens,
8684
9437
  estimatedCostUsd: estimateCostUsd(promptTokens, completionTokens, this.config.llm.model)
8685
9438
  };
8686
- const awaitHallucination = ((_z = this.config.llm.options) == null ? void 0 : _z.awaitHallucination) === true;
9439
+ const awaitHallucination = ((_y = this.config.llm.options) == null ? void 0 : _y.awaitHallucination) === true;
8687
9440
  const [uiTransformation, hallucinationResult] = yield new __await(Promise.all([
8688
9441
  uiTransformationPromise,
8689
9442
  awaitHallucination ? hallucinationScoringPromise : Promise.resolve(void 0)
@@ -8712,10 +9465,10 @@ ${context}`;
8712
9465
  hallucinationReason: hScore.reason
8713
9466
  } : {});
8714
9467
  const trace = buildTrace(hallucinationResult);
8715
- const isTelemetryActive = (_B = (_A = this.config.telemetry) == null ? void 0 : _A.enabled) != null ? _B : Boolean(this.config.licenseKey);
9468
+ const isTelemetryActive = (_A = (_z = this.config.telemetry) == null ? void 0 : _z.enabled) != null ? _A : Boolean(this.config.licenseKey);
8716
9469
  if (isTelemetryActive) {
8717
9470
  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";
8718
- const telemetryUrl = ((_C = this.config.telemetry) == null ? void 0 : _C.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
9471
+ const telemetryUrl = ((_B = this.config.telemetry) == null ? void 0 : _B.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
8719
9472
  const absoluteUrl = telemetryUrl.startsWith("http") ? telemetryUrl : (process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${process.env.PORT || 3e3}`) + telemetryUrl;
8720
9473
  (async () => {
8721
9474
  try {
@@ -8774,9 +9527,8 @@ ${context}`;
8774
9527
  { visualizationHint: "product_browse", recommendedChart: "text", filterInStockOnly: false, wantsExplicitTable: false, isTemporal: false, isComparison: false, language: "en" }
8775
9528
  );
8776
9529
  }
8777
- const isLocalProvider = this.config.llm.provider === "ollama";
8778
- const disableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.disableLlmUiTransform) === true;
8779
- if (forceDeterministic || isLocalProvider || disableLlmUiTransform) {
9530
+ const enableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.enableLlmUiTransform) === true;
9531
+ if (forceDeterministic || !enableLlmUiTransform) {
8780
9532
  return UITransformer.transform(question, sources, this.config, cachedSchema);
8781
9533
  }
8782
9534
  try {
@@ -8801,6 +9553,8 @@ ${context}`;
8801
9553
  });
8802
9554
  }
8803
9555
  resolveNumericPredicateValue(source, predicate) {
9556
+ var _a2;
9557
+ if (!source) return null;
8804
9558
  const meta = source.metadata || {};
8805
9559
  const field = predicate.field;
8806
9560
  const entries = Object.entries(meta).filter(([, value]) => value !== null && value !== void 0 && typeof value !== "object");
@@ -8812,7 +9566,7 @@ ${context}`;
8812
9566
  const value = this.toFiniteNumber(Array.isArray(fuzzy) ? fuzzy[1] : fuzzy.value);
8813
9567
  if (value !== null) return value;
8814
9568
  }
8815
- const contentValue = this.extractNumericValueFromContent(source.content, field);
9569
+ const contentValue = this.extractNumericValueFromContent((_a2 = source.content) != null ? _a2 : "", field);
8816
9570
  if (contentValue !== null) return contentValue;
8817
9571
  }
8818
9572
  for (const [key, value] of entries) {
@@ -8823,6 +9577,7 @@ ${context}`;
8823
9577
  return null;
8824
9578
  }
8825
9579
  extractNumericValueFromContent(content, field) {
9580
+ if (!content || typeof content !== "string") return null;
8826
9581
  const escapedWords = field.split(/\s+|_+|-+/).filter(Boolean).map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
8827
9582
  if (escapedWords.length === 0) return null;
8828
9583
  const pattern = new RegExp(`(?:${escapedWords.join("[\\\\s_:-]*")})\\s*[:\\-\u2013]?\\s*([\\d,]+(?:\\.\\d+)?)`, "i");
@@ -8908,6 +9663,20 @@ ${context}`;
8908
9663
  resolvedSources.push(source);
8909
9664
  }
8910
9665
  }
9666
+ console.log("[Pipeline] retrieve() response:", {
9667
+ query,
9668
+ namespace: ns,
9669
+ count: resolvedSources.length,
9670
+ sample: resolvedSources.slice(0, 2).map((s) => {
9671
+ var _a3;
9672
+ return {
9673
+ id: s == null ? void 0 : s.id,
9674
+ score: s == null ? void 0 : s.score,
9675
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9676
+ metadata: s == null ? void 0 : s.metadata
9677
+ };
9678
+ })
9679
+ });
8911
9680
  return { sources: resolvedSources, graphData };
8912
9681
  }
8913
9682
  /** Rewrite the user query for better retrieval performance. */