@retrivora-ai/rag-engine 2.0.7 → 2.1.1

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,617 @@ 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
+ console.log(`[LLM Gateway Router] Dispatching chat request: model=${req.model}, provider=${provider}, hasGroqKey=${Boolean(process.env.GROQ_API_KEY)}, hasGeminiKey=${Boolean(process.env.GROQ_API_KEY || process.env.GEMINI_API_KEY)}, hasHFToken=${Boolean(process.env.HF_TOKEN)}`);
583
+ try {
584
+ switch (provider) {
585
+ case "groq":
586
+ return await handleGroqRequest(req, effectiveKey);
587
+ case "openai":
588
+ return await handleOpenAIRequest(req, effectiveKey);
589
+ case "gemini":
590
+ return await handleGeminiRequest(req, effectiveKey);
591
+ case "anthropic":
592
+ return await handleAnthropicRequest(req, effectiveKey);
593
+ case "ollama":
594
+ return await handleOllamaRequest(req);
595
+ case "huggingface":
596
+ return await handleHuggingFaceChatRequest(req, effectiveKey);
597
+ default:
598
+ throw new Error(`Unsupported LLM provider for model: ${req.model}`);
599
+ }
600
+ } catch (error) {
601
+ console.error(`[LLM Gateway Router] Provider '${provider}' failed for model '${req.model}':`, {
602
+ message: error.message,
603
+ stack: error.stack
604
+ });
605
+ if (/rate[- ]?limit|429|exhausted/i.test(error.message)) {
606
+ const isGroqKey = process.env.GROQ_API_KEY || effectiveKey && effectiveKey.startsWith("gsk_");
607
+ const reqModelLower = req.model.toLowerCase();
608
+ if (isGroqKey && !reqModelLower.includes("llama-3.3-70b")) {
609
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to secondary Groq model (llama-3.3-70b-versatile)...`);
610
+ try {
611
+ return await handleGroqRequest(__spreadProps(__spreadValues({}, req), { model: "llama-3.3-70b-versatile" }), effectiveKey);
612
+ } catch (fErr) {
613
+ console.error("[LLM Gateway] Fallback groq/llama-3.3-70b-versatile failed:", fErr.message);
614
+ }
615
+ }
616
+ const geminiKey = process.env.GEMINI_API_KEY || effectiveKey;
617
+ if (provider !== "gemini" && geminiKey && (geminiKey.startsWith("AIza") || !geminiKey.startsWith("AQ."))) {
618
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to Google Gemini (gemini-2.5-flash)...`);
619
+ try {
620
+ return await handleGeminiRequest(__spreadProps(__spreadValues({}, req), { model: "gemini-2.5-flash" }), effectiveKey);
621
+ } catch (fErr) {
622
+ console.error("[LLM Gateway] Fallback gemini-2.5-flash failed:", fErr.message);
623
+ }
624
+ }
625
+ if (provider !== "huggingface" && (process.env.HF_TOKEN || process.env.HUGGINGFACE_API_KEY)) {
626
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to Hugging Face (Qwen/Qwen2.5-Coder-32B-Instruct)...`);
627
+ try {
628
+ return await handleHuggingFaceChatRequest(__spreadProps(__spreadValues({}, req), { model: "Qwen/Qwen2.5-Coder-32B-Instruct" }), effectiveKey);
629
+ } catch (fErr) {
630
+ console.error("[LLM Gateway] Fallback HuggingFace Qwen failed:", fErr.message);
631
+ }
632
+ }
633
+ if (provider !== "openai" && process.env.OPENAI_API_KEY) {
634
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to OpenAI (gpt-4o-mini)...`);
635
+ try {
636
+ return await handleOpenAIRequest(__spreadProps(__spreadValues({}, req), { model: "gpt-4o-mini" }), effectiveKey);
637
+ } catch (e) {
638
+ }
639
+ }
640
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to local Ollama (llama3.2)...`);
641
+ return handleOllamaRequest(__spreadProps(__spreadValues({}, req), { model: "llama3.2" }));
642
+ }
643
+ throw error;
644
+ }
645
+ }
646
+ async function dispatchEmbedding(req, apiKeyOverride) {
647
+ const effectiveKey = cleanApiKeyOverride(apiKeyOverride);
648
+ if (req.model.startsWith("hf/") || req.model.startsWith("huggingface/") || req.model.includes("bge-")) {
649
+ try {
650
+ return await handleHuggingFaceEmbedding(req, effectiveKey);
651
+ } catch (err) {
652
+ console.warn("[LLM Gateway] HuggingFace explicit model embedding failed, falling back to default gateway chain:", err);
653
+ }
654
+ }
655
+ const geminiKey = process.env.GEMINI_API_KEY || effectiveKey;
656
+ const isGeminiKeyValid = Boolean(geminiKey && (geminiKey.startsWith("AIza") || !geminiKey.startsWith("AQ.")));
657
+ if (isGeminiKeyValid) {
658
+ try {
659
+ return await handleGeminiEmbedding(req, effectiveKey);
660
+ } catch (err) {
661
+ console.warn("[LLM Gateway] Gemini embedding failed:", err);
662
+ }
663
+ }
664
+ if (process.env.OPENAI_API_KEY) {
665
+ try {
666
+ return await handleOpenAIEmbedding(req, effectiveKey);
667
+ } catch (err) {
668
+ console.warn("[LLM Gateway] OpenAI embedding failed:", err);
669
+ }
670
+ }
671
+ if (process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN) {
672
+ try {
673
+ return await handleHuggingFaceEmbedding(req, effectiveKey);
674
+ } catch (err) {
675
+ console.warn("[LLM Gateway] HuggingFace fallback embedding failed:", err);
676
+ }
677
+ }
678
+ return handleGeminiEmbedding(req, effectiveKey);
679
+ }
680
+ var SUPPORTED_MODELS;
681
+ var init_router = __esm({
682
+ "../../services/llm-gateway/router.ts"() {
683
+ "use strict";
684
+ init_groq();
685
+ init_openai();
686
+ init_gemini();
687
+ init_huggingface();
688
+ init_anthropic();
689
+ init_ollama();
690
+ SUPPORTED_MODELS = [
691
+ { id: "groq/llama-3.1-8b-instant", object: "model", created: 17e8, owned_by: "groq" },
692
+ { id: "llama-3.1-8b-instant", object: "model", created: 17e8, owned_by: "groq" },
693
+ { id: "groq/llama-3.3-70b-versatile", object: "model", created: 17e8, owned_by: "groq" },
694
+ { id: "llama-3.3-70b-versatile", object: "model", created: 17e8, owned_by: "groq" },
695
+ { id: "gpt-4o-mini", object: "model", created: 17e8, owned_by: "openai" },
696
+ { id: "openai/gpt-4o-mini", object: "model", created: 17e8, owned_by: "openai" },
697
+ { id: "gpt-4o", object: "model", created: 17e8, owned_by: "openai" },
698
+ { id: "gemini-2.5-flash", object: "model", created: 17e8, owned_by: "google" },
699
+ { id: "google/gemini-2.5-flash", object: "model", created: 17e8, owned_by: "google" },
700
+ { id: "claude-3-5-haiku-20241022", object: "model", created: 17e8, owned_by: "anthropic" },
701
+ { id: "anthropic/claude-3-5-haiku-20241022", object: "model", created: 17e8, owned_by: "anthropic" },
702
+ { id: "text-embedding-004", object: "model", created: 17e8, owned_by: "google" },
703
+ { id: "google/text-embedding-004", object: "model", created: 17e8, owned_by: "google" },
704
+ { id: "BAAI/bge-base-en-v1.5", object: "model", created: 17e8, owned_by: "huggingface" },
705
+ { id: "huggingface/BAAI/bge-base-en-v1.5", object: "model", created: 17e8, owned_by: "huggingface" },
706
+ { id: "groq/qwen3-32b", object: "model", created: 17e8, owned_by: "groq" },
707
+ { id: "qwen/qwen3-32b", object: "model", created: 17e8, owned_by: "groq" },
708
+ { id: "qwen/qwen3-embedding-8b", object: "model", created: 17e8, owned_by: "qwen" },
709
+ { id: "qwen3-embedding-8b", object: "model", created: 17e8, owned_by: "qwen" },
710
+ { id: "ollama/llama3.2", object: "model", created: 17e8, owned_by: "ollama" }
711
+ ];
712
+ if (typeof globalThis !== "undefined") {
713
+ const _g2 = globalThis;
714
+ _g2.__retrivoraDispatchChat = dispatchChatCompletion;
715
+ _g2.__retrivoraDispatchEmbedding = dispatchEmbedding;
716
+ }
717
+ }
718
+ });
719
+
109
720
  // src/providers/vectordb/BaseVectorProvider.ts
110
721
  var BaseVectorProvider;
111
722
  var init_BaseVectorProvider = __esm({
@@ -2790,12 +3401,13 @@ var OpenAIProvider = class {
2790
3401
  role: "system",
2791
3402
  content: buildSystemContent(basePrompt, context)
2792
3403
  };
3404
+ const safeMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
3405
+ role: m.role || "user",
3406
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
3407
+ }));
2793
3408
  const formattedMessages = [
2794
3409
  systemMessage,
2795
- ...messages.map((m) => ({
2796
- role: m.role,
2797
- content: m.content
2798
- }))
3410
+ ...safeMessages
2799
3411
  ];
2800
3412
  const completion = await this.client.chat.completions.create({
2801
3413
  model: this.llmConfig.model,
@@ -2814,12 +3426,13 @@ var OpenAIProvider = class {
2814
3426
  role: "system",
2815
3427
  content: buildSystemContent(basePrompt, context)
2816
3428
  };
3429
+ const safeStreamMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
3430
+ role: m.role || "user",
3431
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
3432
+ }));
2817
3433
  const formattedMessages = [
2818
3434
  systemMessage,
2819
- ...messages.map((m) => ({
2820
- role: m.role,
2821
- content: m.content
2822
- }))
3435
+ ...safeStreamMessages
2823
3436
  ];
2824
3437
  const stream = yield new __await(this.client.chat.completions.create({
2825
3438
  model: this.llmConfig.model,
@@ -3350,9 +3963,9 @@ var GeminiProvider = class {
3350
3963
  * - Messages must strictly alternate between `user` and `model`.
3351
3964
  */
3352
3965
  buildGeminiContents(messages) {
3353
- return messages.filter((m) => m.role !== "system").map((m) => ({
3966
+ return (messages || []).filter((m) => Boolean(m && typeof m === "object" && m.role !== "system")).map((m) => ({
3354
3967
  role: m.role === "assistant" ? "model" : "user",
3355
- parts: [{ text: m.content }]
3968
+ parts: [{ text: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : "" }]
3356
3969
  }));
3357
3970
  }
3358
3971
  // -------------------------------------------------------------------------
@@ -3555,12 +4168,13 @@ var GroqProvider = class {
3555
4168
  role: "system",
3556
4169
  content: buildSystemContent(basePrompt, context)
3557
4170
  };
4171
+ const safeMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4172
+ role: m.role || "user",
4173
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4174
+ }));
3558
4175
  const formattedMessages = [
3559
4176
  systemMessage,
3560
- ...messages.map((m) => ({
3561
- role: m.role,
3562
- content: m.content
3563
- }))
4177
+ ...safeMessages
3564
4178
  ];
3565
4179
  const completion = await this.client.chat.completions.create({
3566
4180
  model: this.llmConfig.model,
@@ -3579,12 +4193,13 @@ var GroqProvider = class {
3579
4193
  role: "system",
3580
4194
  content: buildSystemContent(basePrompt, context)
3581
4195
  };
4196
+ const safeStreamMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4197
+ role: m.role || "user",
4198
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4199
+ }));
3582
4200
  const formattedMessages = [
3583
4201
  systemMessage,
3584
- ...messages.map((m) => ({
3585
- role: m.role,
3586
- content: m.content
3587
- }))
4202
+ ...safeStreamMessages
3588
4203
  ];
3589
4204
  const stream = yield new __await(this.client.chat.completions.create({
3590
4205
  model: this.llmConfig.model,
@@ -3713,12 +4328,13 @@ var QwenProvider = class {
3713
4328
  role: "system",
3714
4329
  content: buildSystemContent(basePrompt, context)
3715
4330
  };
4331
+ const safeMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4332
+ role: m.role || "user",
4333
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4334
+ }));
3716
4335
  const formattedMessages = [
3717
4336
  systemMessage,
3718
- ...messages.map((m) => ({
3719
- role: m.role,
3720
- content: m.content
3721
- }))
4337
+ ...safeMessages
3722
4338
  ];
3723
4339
  const completion = await this.client.chat.completions.create({
3724
4340
  model: this.llmConfig.model,
@@ -3737,12 +4353,13 @@ var QwenProvider = class {
3737
4353
  role: "system",
3738
4354
  content: buildSystemContent(basePrompt, context)
3739
4355
  };
4356
+ const safeStreamMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4357
+ role: m.role || "user",
4358
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4359
+ }));
3740
4360
  const formattedMessages = [
3741
4361
  systemMessage,
3742
- ...messages.map((m) => ({
3743
- role: m.role,
3744
- content: m.content
3745
- }))
4362
+ ...safeStreamMessages
3746
4363
  ];
3747
4364
  const stream = yield new __await(this.client.chat.completions.create({
3748
4365
  model: this.llmConfig.model,
@@ -3841,6 +4458,17 @@ var LLM_PROFILES = {
3841
4458
  };
3842
4459
 
3843
4460
  // src/llm/providers/UniversalLLMAdapter.ts
4461
+ function extractContent(obj) {
4462
+ var _a2, _b, _c;
4463
+ if (!obj || typeof obj !== "object") return void 0;
4464
+ const choice = (_a2 = obj.choices) == null ? void 0 : _a2[0];
4465
+ if (!choice) return void 0;
4466
+ if (typeof ((_b = choice.message) == null ? void 0 : _b.content) === "string") return choice.message.content;
4467
+ if (typeof ((_c = choice.delta) == null ? void 0 : _c.content) === "string") return choice.delta.content;
4468
+ if (typeof choice.text === "string") return choice.text;
4469
+ if (typeof choice.content === "string") return choice.content;
4470
+ return void 0;
4471
+ }
3844
4472
  var UniversalLLMAdapter = class {
3845
4473
  constructor(config) {
3846
4474
  var _a2, _b, _c, _d, _e, _f, _g2, _h;
@@ -3872,14 +4500,18 @@ var UniversalLLMAdapter = class {
3872
4500
  });
3873
4501
  }
3874
4502
  async chat(messages, context) {
3875
- var _a2, _b, _c, _d, _e, _f;
4503
+ var _a2, _b, _c;
3876
4504
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
4505
+ const safeMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4506
+ role: m.role || "user",
4507
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4508
+ }));
3877
4509
  const formattedMessages = [
3878
4510
  { role: "system", content: `${this.systemPrompt}
3879
4511
 
3880
4512
  Context:
3881
4513
  ${context != null ? context : "None"}` },
3882
- ...messages
4514
+ ...safeMessages
3883
4515
  ];
3884
4516
  let payload;
3885
4517
  if (this.opts.chatPayloadTemplate) {
@@ -3900,25 +4532,41 @@ ${context != null ? context : "None"}` },
3900
4532
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
3901
4533
  if (isSelfHost || Boolean(process.env.VERCEL)) {
3902
4534
  const _g2 = globalThis;
3903
- if (typeof _g2.__retrivoraDispatchChat === "function") {
4535
+ let dispatch = _g2.__retrivoraDispatchChat;
4536
+ if (typeof dispatch !== "function") {
3904
4537
  try {
3905
- const res = await _g2.__retrivoraDispatchChat({
4538
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4539
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4540
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4541
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4542
+ dispatch = gateway.dispatchChatCompletion;
4543
+ }
4544
+ } catch (e) {
4545
+ }
4546
+ }
4547
+ if (typeof dispatch === "function") {
4548
+ try {
4549
+ const res = await dispatch({
3906
4550
  model: this.model,
3907
4551
  messages: formattedMessages,
3908
4552
  max_tokens: this.maxTokens,
3909
4553
  temperature: this.temperature
3910
4554
  }, 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;
4555
+ const content = extractContent(res == null ? void 0 : res.response);
4556
+ if (content !== void 0) {
4557
+ return content;
3913
4558
  }
4559
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch returned empty content for model: ${this.model}`);
3914
4560
  } catch (dispatchErr) {
3915
4561
  throw dispatchErr;
3916
4562
  }
4563
+ } else {
4564
+ 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.`);
3917
4565
  }
3918
4566
  }
3919
4567
  const { data } = await this.http.post(path2, payload);
3920
- const extractPath = (_f = this.opts.responseExtractPath) != null ? _f : "choices[0].message.content";
3921
- const result = resolvePath(data, extractPath);
4568
+ const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
4569
+ const result = (_c = resolvePath(data, extractPath)) != null ? _c : extractContent(data);
3922
4570
  if (result === void 0) {
3923
4571
  throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
3924
4572
  }
@@ -3931,16 +4579,20 @@ ${context != null ? context : "None"}` },
3931
4579
  */
3932
4580
  chatStream(messages, context) {
3933
4581
  return __asyncGenerator(this, null, function* () {
3934
- var _a2, _b, _c, _d, _e, _f, _g2;
4582
+ var _a2, _b, _c, _d, _e;
3935
4583
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3936
4584
  const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
3937
4585
  const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
4586
+ const safeMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4587
+ role: m.role || "user",
4588
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4589
+ }));
3938
4590
  const formattedMessages = [
3939
4591
  { role: "system", content: `${this.systemPrompt}
3940
4592
 
3941
4593
  Context:
3942
4594
  ${context != null ? context : "None"}` },
3943
- ...messages
4595
+ ...safeMessages
3944
4596
  ];
3945
4597
  let payload;
3946
4598
  if (this.opts.chatPayloadTemplate) {
@@ -3965,10 +4617,22 @@ ${context != null ? context : "None"}` },
3965
4617
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
3966
4618
  let streamBody = null;
3967
4619
  if (isSelfHost || Boolean(process.env.VERCEL)) {
3968
- const _g3 = globalThis;
3969
- if (typeof _g3.__retrivoraDispatchChat === "function") {
4620
+ const _g2 = globalThis;
4621
+ let dispatch = _g2.__retrivoraDispatchChat;
4622
+ if (typeof dispatch !== "function") {
3970
4623
  try {
3971
- const res = yield new __await(_g3.__retrivoraDispatchChat({
4624
+ const gateway = yield new __await(Promise.resolve().then(() => (init_router(), router_exports)));
4625
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4626
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4627
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4628
+ dispatch = gateway.dispatchChatCompletion;
4629
+ }
4630
+ } catch (e) {
4631
+ }
4632
+ }
4633
+ if (typeof dispatch === "function") {
4634
+ try {
4635
+ const res = yield new __await(dispatch({
3972
4636
  model: this.model,
3973
4637
  messages: formattedMessages,
3974
4638
  max_tokens: this.maxTokens,
@@ -3977,13 +4641,19 @@ ${context != null ? context : "None"}` },
3977
4641
  }, this.apiKey));
3978
4642
  if (res == null ? void 0 : res.stream) {
3979
4643
  streamBody = res.stream;
3980
- } 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) {
3981
- yield res.response.choices[0].message.content;
3982
- return;
4644
+ } else {
4645
+ const content = extractContent(res == null ? void 0 : res.response);
4646
+ if (content !== void 0) {
4647
+ yield content;
4648
+ return;
4649
+ }
4650
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch stream returned empty response for model: ${this.model}`);
3983
4651
  }
3984
4652
  } catch (dispatchErr) {
3985
4653
  throw dispatchErr;
3986
4654
  }
4655
+ } else {
4656
+ 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.`);
3987
4657
  }
3988
4658
  }
3989
4659
  if (!streamBody) {
@@ -4010,14 +4680,14 @@ ${context != null ? context : "None"}` },
4010
4680
  if (done) break;
4011
4681
  buffer += decoder.decode(value, { stream: true });
4012
4682
  const lines = buffer.split("\n");
4013
- buffer = (_g2 = lines.pop()) != null ? _g2 : "";
4683
+ buffer = (_c = lines.pop()) != null ? _c : "";
4014
4684
  for (const line of lines) {
4015
4685
  const trimmed = line.trim();
4016
4686
  if (!trimmed || trimmed === "data: [DONE]") continue;
4017
4687
  if (!trimmed.startsWith("data:")) continue;
4018
4688
  try {
4019
4689
  const json = JSON.parse(trimmed.slice(5).trim());
4020
- const text = resolvePath(json, extractPath);
4690
+ const text = (_d = resolvePath(json, extractPath)) != null ? _d : extractContent(json);
4021
4691
  if (text && typeof text === "string") yield text;
4022
4692
  } catch (e) {
4023
4693
  }
@@ -4027,7 +4697,7 @@ ${context != null ? context : "None"}` },
4027
4697
  const jsonStr = buffer.replace(/^data:\s*/, "").trim();
4028
4698
  try {
4029
4699
  const json = JSON.parse(jsonStr);
4030
- const text = resolvePath(json, extractPath);
4700
+ const text = (_e = resolvePath(json, extractPath)) != null ? _e : extractContent(json);
4031
4701
  if (text && typeof text === "string") yield text;
4032
4702
  } catch (e) {
4033
4703
  }
@@ -4055,18 +4725,33 @@ ${context != null ? context : "None"}` },
4055
4725
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4056
4726
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4057
4727
  const _g2 = globalThis;
4058
- if (typeof _g2.__retrivoraDispatchEmbedding === "function") {
4728
+ let dispatch = _g2.__retrivoraDispatchEmbedding;
4729
+ if (typeof dispatch !== "function") {
4059
4730
  try {
4060
- const res = await _g2.__retrivoraDispatchEmbedding({
4731
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4732
+ if (gateway == null ? void 0 : gateway.dispatchEmbedding) {
4733
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4734
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4735
+ dispatch = gateway.dispatchEmbedding;
4736
+ }
4737
+ } catch (e) {
4738
+ }
4739
+ }
4740
+ if (typeof dispatch === "function") {
4741
+ try {
4742
+ const res = await dispatch({
4061
4743
  model: this.model,
4062
4744
  input: text
4063
4745
  }, this.apiKey);
4064
4746
  if ((_c = (_b = res == null ? void 0 : res.data) == null ? void 0 : _b[0]) == null ? void 0 : _c.embedding) {
4065
4747
  return res.data[0].embedding;
4066
4748
  }
4749
+ throw new Error(`[UniversalLLMAdapter] In-process embedding dispatch returned invalid vector for model: ${this.model}`);
4067
4750
  } catch (dispatchErr) {
4068
4751
  throw dispatchErr;
4069
4752
  }
4753
+ } else {
4754
+ 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.`);
4070
4755
  }
4071
4756
  }
4072
4757
  const { data } = await this.http.post(path2, payload);
@@ -6045,8 +6730,8 @@ var IntentClassifier = class {
6045
6730
  }
6046
6731
  // ─── Intent Heuristic Checkers ─────────────────────────────────────────────
6047
6732
  static isInformationLookup(query) {
6048
- if (/^(what|who|explain|define|where|when|why|how|how does|can|could|does|do|is|are|has|have|will|should|would|meaning of)\s+/i.test(query)) {
6049
- if (!/\b(compare|versus|vs\.?|trend|monthly|revenue|top selling|best)\b/i.test(query)) {
6733
+ if (/^(what|who|explain|explore|define|where|when|why|how|how does|can|could|does|do|is|are|has|have|will|should|would|meaning of|tell me about|show details of|overview of|summarize)\s+/i.test(query)) {
6734
+ if (!/\b(compare|versus|vs\.?|trend|monthly|revenue|top 10|top selling|best|chart|graph|plot|breakdown|analytics)\b/i.test(query)) {
6050
6735
  return true;
6051
6736
  }
6052
6737
  }
@@ -6083,7 +6768,7 @@ var Rule1SpecificInfoRule = class {
6083
6768
  }
6084
6769
  evaluate(context, intent) {
6085
6770
  const q = (context.userQuery || "").toLowerCase().trim();
6086
- const isFactQuery = intent === "information_lookup" || /^(what|who|explain|define|where|when|why|meaning of)\s+/i.test(q) || /^(what is the price of|price of|cost of)\b/i.test(q);
6771
+ const isFactQuery = intent === "information_lookup" || /^(what|who|explain|explore|define|where|when|why|meaning of|tell me about|show details of|overview of|summarize)\s+/i.test(q) || /^(what is the price of|price of|cost of)\b/i.test(q);
6087
6772
  const isNonVisual = !/\b(compare|versus|vs\.?|trend|monthly|revenue|best|top 10|chart|table|list|grid)\b/i.test(q);
6088
6773
  if (isFactQuery && isNonVisual) {
6089
6774
  return {
@@ -6914,7 +7599,7 @@ ${schemaProfileText}` : ""}`;
6914
7599
  }
6915
7600
  // ─── Transform Helpers ────────────────────────────────────────────────────
6916
7601
  static transformToProductCarousel(data, config, trainedSchema) {
6917
- const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null).slice(0, 15);
7602
+ const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null);
6918
7603
  return {
6919
7604
  type: "product_carousel",
6920
7605
  title: "Recommended Products",
@@ -7294,7 +7979,8 @@ ${schemaProfileText}` : ""}`;
7294
7979
  return fieldCount.size > 2;
7295
7980
  }
7296
7981
  static profileData(data) {
7297
- const records = data.map((item) => {
7982
+ const records = (data || []).filter((item) => Boolean(item && typeof item === "object")).map((item) => {
7983
+ var _a2, _b;
7298
7984
  const fields2 = {};
7299
7985
  Object.entries(item.metadata || {}).forEach(([key, value]) => {
7300
7986
  const primitive = this.toPrimitive(value);
@@ -7303,8 +7989,8 @@ ${schemaProfileText}` : ""}`;
7303
7989
  if (!fields2.content && item.content) fields2.content = item.content.substring(0, 500);
7304
7990
  return {
7305
7991
  id: item.id,
7306
- content: item.content,
7307
- score: item.score,
7992
+ content: (_a2 = item.content) != null ? _a2 : "",
7993
+ score: (_b = item.score) != null ? _b : 0,
7308
7994
  fields: fields2,
7309
7995
  source: item
7310
7996
  };
@@ -7361,6 +8047,11 @@ ${schemaProfileText}` : ""}`;
7361
8047
  }
7362
8048
  static chooseAutomaticVisualization(data, profile, query) {
7363
8049
  if (profile.records.length === 0) return null;
8050
+ const q = query.toLowerCase().trim();
8051
+ const isExplicitVisualOrAnalytic = /\b(chart|graph|plot|visualize|trend|monthly|revenue|top\s*\d+|breakdown|analytics|compare|versus|vs\.?|histogram|pie|bar|line|distribution|percentage|share|summary of metrics)\b/i.test(q);
8052
+ if (!isExplicitVisualOrAnalytic) {
8053
+ return null;
8054
+ }
7364
8055
  if (profile.dateFields.length > 0 && profile.numericFields.length > 0) {
7365
8056
  return this.transformToLineChart(profile);
7366
8057
  }
@@ -7476,6 +8167,7 @@ ${schemaProfileText}` : ""}`;
7476
8167
  return Array.from(categories);
7477
8168
  }
7478
8169
  static getProductCategory(item) {
8170
+ if (!item) return null;
7479
8171
  const meta = item.metadata || {};
7480
8172
  const metadataCategory = resolveMetadataValue(meta, "category");
7481
8173
  if (this.isUsableCategory(metadataCategory)) return String(metadataCategory).trim();
@@ -7592,6 +8284,7 @@ ${schemaProfileText}` : ""}`;
7592
8284
  if (!fields.has(normalized)) fields.set(normalized, clean);
7593
8285
  };
7594
8286
  data.forEach((item) => {
8287
+ if (!item) return;
7595
8288
  Object.keys(item.metadata || {}).forEach(addField);
7596
8289
  for (const match of (item.content || "").matchAll(/(?:^|\n)\s*([A-Za-z][A-Za-z0-9_ /-]{1,50})\s*[:\-–]\s*([^\n]+)/g)) {
7597
8290
  addField(match[1]);
@@ -7708,6 +8401,7 @@ ${schemaProfileText}` : ""}`;
7708
8401
  return true;
7709
8402
  }
7710
8403
  static extractStockQuantity(item) {
8404
+ if (!item) return null;
7711
8405
  const meta = item.metadata || {};
7712
8406
  const stockValue = resolveMetadataValue(meta, "stock");
7713
8407
  const numericStock = this.toFiniteNumber(stockValue);
@@ -8407,7 +9101,7 @@ ${m.content}`).join("\n\n---\n\n");
8407
9101
  */
8408
9102
  askStreamInternal(_0) {
8409
9103
  return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
8410
- 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;
9104
+ 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;
8411
9105
  yield new __await(this.initialize());
8412
9106
  const ns = formatNamespace(namespace != null ? namespace : this.config.projectId);
8413
9107
  const topK = (_b = (_a2 = this.config.rag) == null ? void 0 : _a2.topK) != null ? _b : 5;
@@ -8450,8 +9144,8 @@ ${m.content}`).join("\n\n---\n\n");
8450
9144
  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;
8451
9145
  const hasMetadataFilter = filter.metadata && Object.keys(filter.metadata).length > 0;
8452
9146
  const hasNumericPredicates = Array.isArray(filter.__numericPredicates) && filter.__numericPredicates.length > 0;
8453
- const wantsExhaustiveList = hasNumericPredicates || hasMetadataFilter || /\b(list|all|show|provide|give|get|browse|find|search|display)\b/i.test(question);
8454
- const retrievalLimit = wantsExhaustiveList ? Math.max(topK * 20, 100) : topK * 2;
9147
+ const wantsExhaustiveList = true;
9148
+ const retrievalLimit = Math.max(topK * 50, 1e3);
8455
9149
  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"));
8456
9150
  console.log("[Pipeline] Raw vectorDB.query response:", {
8457
9151
  rawCount: rawSources.length,
@@ -8475,40 +9169,29 @@ ${m.content}`).join("\n\n---\n\n");
8475
9169
  var _a3;
8476
9170
  return ((_a3 = m == null ? void 0 : m.score) != null ? _a3 : 0) >= scoreThreshold;
8477
9171
  });
8478
- const rerankLimit = wantsExhaustiveList ? retrievalLimit : topK;
9172
+ const rerankLimit = Math.max(retrievalLimit, fullSources.length);
8479
9173
  const useReranking = arch !== "naive" && (arch === "retrieve-and-rerank" || ((_m = this.config.rag) == null ? void 0 : _m.useReranking));
8480
9174
  if (!hasNumericPredicates && useReranking) {
8481
9175
  fullSources = (yield new __await(this.reranker.rerank(fullSources, question, rerankLimit))).filter((s) => Boolean(s && typeof s === "object"));
8482
- } else if (!wantsExhaustiveList) {
8483
- fullSources = fullSources.slice(0, topK);
8484
9176
  }
8485
9177
  const rerankMs = performance.now() - rerankStart;
8486
- let context = fullSources.length ? fullSources.map((m, i) => {
9178
+ const totalCount = fullSources.length;
9179
+ const promptSources = fullSources.slice(0, 15);
9180
+ 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]
9181
+
9182
+ ` + promptSources.map((m, i) => {
8487
9183
  var _a3;
8488
9184
  return `[Source ${i + 1}]
8489
9185
  ${(_a3 = m == null ? void 0 : m.content) != null ? _a3 : ""}`;
8490
9186
  }).join("\n\n---\n\n") : "No relevant context found.";
8491
- let displayCount = 15;
8492
- if (hasMetadataFilter) {
8493
- displayCount = fullSources.length;
8494
- } else {
8495
- const baseThreshold = Math.max(scoreThreshold, 0.4);
8496
- const highlyRelevant = fullSources.filter((m) => {
8497
- var _a3;
8498
- return ((_a3 = m == null ? void 0 : m.score) != null ? _a3 : 0) >= baseThreshold;
8499
- });
8500
- displayCount = Math.max(highlyRelevant.length, topK);
8501
- if (displayCount > 15) {
8502
- displayCount = 15;
8503
- }
8504
- }
8505
9187
  const sources = [...fullSources].filter((s) => Boolean(s && typeof s === "object")).sort((a, b) => {
8506
9188
  var _a3, _b2;
8507
9189
  return ((_a3 = b == null ? void 0 : b.score) != null ? _a3 : 0) - ((_b2 = a == null ? void 0 : a.score) != null ? _b2 : 0);
8508
- }).slice(0, displayCount);
9190
+ });
8509
9191
  console.log("[Pipeline] Final sources for prompt & UI:", {
8510
9192
  count: sources.length,
8511
- sources: sources.map((s, idx) => {
9193
+ totalRawCount: rawSources.length,
9194
+ sources: sources.slice(0, 10).map((s, idx) => {
8512
9195
  var _a3;
8513
9196
  return {
8514
9197
  rank: idx + 1,
@@ -8708,7 +9391,7 @@ ${context}`;
8708
9391
  }
8709
9392
  yield fullReply;
8710
9393
  }
8711
- 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;
9394
+ const runHallucination = ((_w = this.config.llm.options) == null ? void 0 : _w.hallucinationScoring) === true;
8712
9395
  if (runHallucination) {
8713
9396
  hallucinationScoringPromise = scoreHallucination(this.llmProvider, fullReply, context).catch(() => void 0);
8714
9397
  }
@@ -8717,7 +9400,7 @@ ${context}`;
8717
9400
  const latency = {
8718
9401
  embedMs: Math.round(embedMs),
8719
9402
  retrieveMs: Math.round(retrieveMs),
8720
- rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_y = this.config.rag) == null ? void 0 : _y.useReranking)) ? Math.round(rerankMs) : void 0,
9403
+ rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_x = this.config.rag) == null ? void 0 : _x.useReranking)) ? Math.round(rerankMs) : void 0,
8721
9404
  generateMs: Math.round(generateMs),
8722
9405
  totalMs: Math.round(totalMs)
8723
9406
  };
@@ -8730,7 +9413,7 @@ ${context}`;
8730
9413
  totalTokens: promptTokens + completionTokens,
8731
9414
  estimatedCostUsd: estimateCostUsd(promptTokens, completionTokens, this.config.llm.model)
8732
9415
  };
8733
- const awaitHallucination = ((_z = this.config.llm.options) == null ? void 0 : _z.awaitHallucination) === true;
9416
+ const awaitHallucination = ((_y = this.config.llm.options) == null ? void 0 : _y.awaitHallucination) === true;
8734
9417
  const [uiTransformation, hallucinationResult] = yield new __await(Promise.all([
8735
9418
  uiTransformationPromise,
8736
9419
  awaitHallucination ? hallucinationScoringPromise : Promise.resolve(void 0)
@@ -8759,10 +9442,10 @@ ${context}`;
8759
9442
  hallucinationReason: hScore.reason
8760
9443
  } : {});
8761
9444
  const trace = buildTrace(hallucinationResult);
8762
- const isTelemetryActive = (_B = (_A = this.config.telemetry) == null ? void 0 : _A.enabled) != null ? _B : Boolean(this.config.licenseKey);
9445
+ const isTelemetryActive = (_A = (_z = this.config.telemetry) == null ? void 0 : _z.enabled) != null ? _A : Boolean(this.config.licenseKey);
8763
9446
  if (isTelemetryActive) {
8764
9447
  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";
8765
- const telemetryUrl = ((_C = this.config.telemetry) == null ? void 0 : _C.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
9448
+ const telemetryUrl = ((_B = this.config.telemetry) == null ? void 0 : _B.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
8766
9449
  const absoluteUrl = telemetryUrl.startsWith("http") ? telemetryUrl : (process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${process.env.PORT || 3e3}`) + telemetryUrl;
8767
9450
  (async () => {
8768
9451
  try {
@@ -8821,9 +9504,8 @@ ${context}`;
8821
9504
  { visualizationHint: "product_browse", recommendedChart: "text", filterInStockOnly: false, wantsExplicitTable: false, isTemporal: false, isComparison: false, language: "en" }
8822
9505
  );
8823
9506
  }
8824
- const isLocalProvider = this.config.llm.provider === "ollama";
8825
- const disableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.disableLlmUiTransform) === true;
8826
- if (forceDeterministic || isLocalProvider || disableLlmUiTransform) {
9507
+ const enableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.enableLlmUiTransform) === true;
9508
+ if (forceDeterministic || !enableLlmUiTransform) {
8827
9509
  return UITransformer.transform(question, sources, this.config, cachedSchema);
8828
9510
  }
8829
9511
  try {
@@ -8980,7 +9662,10 @@ ${context}`;
8980
9662
  Focus on extracting the core intent and entities. Do not answer the question, just rewrite it.
8981
9663
 
8982
9664
  History:
8983
- ${history.map((m) => `${m.role}: ${m.content}`).join("\n")}
9665
+ ${(history || []).map((m) => {
9666
+ var _a2;
9667
+ return `${(m == null ? void 0 : m.role) || "user"}: ${(_a2 = m == null ? void 0 : m.content) != null ? _a2 : ""}`;
9668
+ }).join("\n")}
8984
9669
 
8985
9670
  New Question: ${question}
8986
9671
 
@@ -9004,8 +9689,11 @@ Optimized Search Query:`;
9004
9689
  const ns = formatNamespace(namespace != null ? namespace : this.config.projectId);
9005
9690
  try {
9006
9691
  const { sources } = await this.retrieve(query, { namespace: ns, topK: 5 });
9007
- if (sources.length === 0) return [];
9008
- const context = sources.map((s) => s.content).join("\n\n---\n\n");
9692
+ if (!sources || sources.length === 0) return [];
9693
+ const context = sources.map((s) => {
9694
+ var _a2;
9695
+ return (_a2 = s == null ? void 0 : s.content) != null ? _a2 : "";
9696
+ }).join("\n\n---\n\n");
9009
9697
  const prompt = `Based on the following snippets from a document, what are at least 5 short, relevant questions a user might ask?
9010
9698
  Focus on questions that can be answered by the context.
9011
9699
  Keep each question under 10 words and make them very specific to the content.