@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.
@@ -121,6 +121,617 @@ var init_templateUtils = __esm({
121
121
  }
122
122
  });
123
123
 
124
+ // ../../services/llm-gateway/providers/groq.ts
125
+ async function handleGroqRequest(req, apiKeyOverride) {
126
+ const apiKey = apiKeyOverride || process.env.GROQ_API_KEY;
127
+ if (!apiKey) {
128
+ throw new Error("Groq API Key missing. Please set GROQ_API_KEY in environment variables.");
129
+ }
130
+ const modelName = req.model.replace(/^groq\//i, "");
131
+ const payload = __spreadProps(__spreadValues({}, req), {
132
+ model: modelName
133
+ });
134
+ const response = await fetch("https://api.groq.com/openai/v1/chat/completions", {
135
+ method: "POST",
136
+ headers: {
137
+ "Content-Type": "application/json",
138
+ "Authorization": `Bearer ${apiKey}`
139
+ },
140
+ body: JSON.stringify(payload)
141
+ });
142
+ if (!response.ok) {
143
+ const errorText = await response.text();
144
+ throw new Error(`Groq API Error (${response.status}): ${errorText}`);
145
+ }
146
+ if (req.stream && response.body) {
147
+ return { stream: response.body };
148
+ }
149
+ const json = await response.json();
150
+ return { response: json };
151
+ }
152
+ var init_groq = __esm({
153
+ "../../services/llm-gateway/providers/groq.ts"() {
154
+ "use strict";
155
+ }
156
+ });
157
+
158
+ // ../../services/llm-gateway/providers/openai.ts
159
+ async function handleOpenAIRequest(req, apiKeyOverride) {
160
+ const apiKey = apiKeyOverride || process.env.OPENAI_API_KEY;
161
+ if (!apiKey) {
162
+ throw new Error("OpenAI API Key missing. Please set OPENAI_API_KEY in environment variables.");
163
+ }
164
+ const modelName = req.model.replace(/^(openai|gpt)\//i, "");
165
+ const payload = __spreadProps(__spreadValues({}, req), {
166
+ model: modelName
167
+ });
168
+ const response = await fetch("https://api.openai.com/v1/chat/completions", {
169
+ method: "POST",
170
+ headers: {
171
+ "Content-Type": "application/json",
172
+ "Authorization": `Bearer ${apiKey}`
173
+ },
174
+ body: JSON.stringify(payload)
175
+ });
176
+ if (!response.ok) {
177
+ const errorText = await response.text();
178
+ throw new Error(`OpenAI API Error (${response.status}): ${errorText}`);
179
+ }
180
+ if (req.stream && response.body) {
181
+ return { stream: response.body };
182
+ }
183
+ const json = await response.json();
184
+ return { response: json };
185
+ }
186
+ async function handleOpenAIEmbedding(req, apiKeyOverride) {
187
+ const apiKey = apiKeyOverride || process.env.OPENAI_API_KEY;
188
+ if (!apiKey) {
189
+ throw new Error("OpenAI API Key missing. Please set OPENAI_API_KEY in environment variables.");
190
+ }
191
+ const modelName = req.model.replace(/^(openai)\//i, "");
192
+ const response = await fetch("https://api.openai.com/v1/embeddings", {
193
+ method: "POST",
194
+ headers: {
195
+ "Content-Type": "application/json",
196
+ "Authorization": `Bearer ${apiKey}`
197
+ },
198
+ body: JSON.stringify({
199
+ model: modelName,
200
+ input: req.input
201
+ })
202
+ });
203
+ if (!response.ok) {
204
+ const errorText = await response.text();
205
+ throw new Error(`OpenAI Embedding API Error (${response.status}): ${errorText}`);
206
+ }
207
+ return await response.json();
208
+ }
209
+ var init_openai = __esm({
210
+ "../../services/llm-gateway/providers/openai.ts"() {
211
+ "use strict";
212
+ }
213
+ });
214
+
215
+ // ../../services/llm-gateway/providers/gemini.ts
216
+ async function handleGeminiRequest(req, apiKeyOverride) {
217
+ const apiKey = apiKeyOverride || process.env.GEMINI_API_KEY;
218
+ if (!apiKey) {
219
+ throw new Error("Gemini API Key missing. Please set GEMINI_API_KEY in environment variables.");
220
+ }
221
+ let modelName = req.model.replace(/^(google|gemini)\//i, "");
222
+ if (!modelName.startsWith("gemini-")) {
223
+ modelName = `gemini-${modelName}`;
224
+ }
225
+ const payload = __spreadProps(__spreadValues({}, req), {
226
+ model: modelName
227
+ });
228
+ const response = await fetch("https://generativelanguage.googleapis.com/v1beta/openai/chat/completions", {
229
+ method: "POST",
230
+ headers: {
231
+ "Content-Type": "application/json",
232
+ "Authorization": `Bearer ${apiKey}`
233
+ },
234
+ body: JSON.stringify(payload)
235
+ });
236
+ if (!response.ok) {
237
+ const errorText = await response.text();
238
+ throw new Error(`Google Gemini API Error (${response.status}): ${errorText}`);
239
+ }
240
+ if (req.stream && response.body) {
241
+ return { stream: response.body };
242
+ }
243
+ const json = await response.json();
244
+ return { response: json };
245
+ }
246
+ async function handleGeminiEmbedding(req, apiKeyOverride) {
247
+ const apiKey = apiKeyOverride || process.env.GEMINI_API_KEY;
248
+ if (!apiKey) {
249
+ throw new Error("Gemini API Key missing. Please set GEMINI_API_KEY in environment variables.");
250
+ }
251
+ let modelName = req.model.replace(/^(google|gemini)\//i, "");
252
+ if (!modelName || modelName === "default" || modelName.includes("text-embedding-3") || modelName.includes("ada") || !modelName.startsWith("text-embedding-00") && !modelName.startsWith("embedding-00")) {
253
+ modelName = "text-embedding-004";
254
+ }
255
+ const response = await fetch("https://generativelanguage.googleapis.com/v1beta/openai/embeddings", {
256
+ method: "POST",
257
+ headers: {
258
+ "Content-Type": "application/json",
259
+ "Authorization": `Bearer ${apiKey}`
260
+ },
261
+ body: JSON.stringify({
262
+ model: modelName,
263
+ input: req.input
264
+ })
265
+ });
266
+ if (!response.ok) {
267
+ const errorText = await response.text();
268
+ throw new Error(`Google Gemini Embedding API Error (${response.status}): ${errorText}`);
269
+ }
270
+ return await response.json();
271
+ }
272
+ var init_gemini = __esm({
273
+ "../../services/llm-gateway/providers/gemini.ts"() {
274
+ "use strict";
275
+ }
276
+ });
277
+
278
+ // ../../services/llm-gateway/providers/huggingface.ts
279
+ async function handleHuggingFaceChatRequest(req, apiKeyOverride) {
280
+ var _a2, _b;
281
+ const apiKey = apiKeyOverride || process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN;
282
+ if (!apiKey) {
283
+ throw new Error("HuggingFace API Key missing. Set HUGGINGFACE_API_KEY or HF_TOKEN in environment variables.");
284
+ }
285
+ let modelName = req.model.replace(/^(huggingface|hf)\//i, "");
286
+ if (!modelName || modelName === "default" || modelName.toLowerCase() === "qwen" || modelName.toLowerCase() === "qwen-coder") {
287
+ modelName = "Qwen/Qwen2.5-Coder-32B-Instruct";
288
+ }
289
+ const payload = __spreadProps(__spreadValues({}, req), {
290
+ model: modelName
291
+ });
292
+ try {
293
+ const response = await fetch("https://router.huggingface.co/v1/chat/completions", {
294
+ method: "POST",
295
+ headers: {
296
+ "Content-Type": "application/json",
297
+ "Authorization": `Bearer ${apiKey}`
298
+ },
299
+ body: JSON.stringify(payload)
300
+ });
301
+ if (response.ok) {
302
+ if (req.stream && response.body) {
303
+ return { stream: response.body };
304
+ }
305
+ const json = await response.json();
306
+ return { response: json };
307
+ }
308
+ } catch (e) {
309
+ }
310
+ try {
311
+ const response = await fetch("https://router.huggingface.co/hf-inference/v1/chat/completions", {
312
+ method: "POST",
313
+ headers: {
314
+ "Content-Type": "application/json",
315
+ "Authorization": `Bearer ${apiKey}`
316
+ },
317
+ body: JSON.stringify(payload)
318
+ });
319
+ if (response.ok) {
320
+ if (req.stream && response.body) {
321
+ return { stream: response.body };
322
+ }
323
+ const json = await response.json();
324
+ return { response: json };
325
+ }
326
+ } catch (e) {
327
+ }
328
+ const lastUserMsg = ((_a2 = req.messages.filter((m) => m.role === "user").pop()) == null ? void 0 : _a2.content) || "Hello";
329
+ const pipelineRes = await fetch(`https://router.huggingface.co/hf-inference/models/${modelName}`, {
330
+ method: "POST",
331
+ headers: {
332
+ "Content-Type": "application/json",
333
+ "Authorization": `Bearer ${apiKey}`
334
+ },
335
+ body: JSON.stringify({
336
+ inputs: lastUserMsg,
337
+ parameters: { max_new_tokens: req.max_tokens || 256, temperature: req.temperature || 0.7 },
338
+ options: { wait_for_model: true }
339
+ })
340
+ });
341
+ if (!pipelineRes.ok) {
342
+ const errorText = await pipelineRes.text();
343
+ throw new Error(`HuggingFace API Error (${pipelineRes.status}): ${errorText}`);
344
+ }
345
+ const raw = await pipelineRes.json();
346
+ const textOutput = Array.isArray(raw) ? ((_b = raw[0]) == null ? void 0 : _b.generated_text) || JSON.stringify(raw) : JSON.stringify(raw);
347
+ const formattedResponse = {
348
+ id: `hf-${Date.now()}`,
349
+ object: "chat.completion",
350
+ created: Math.floor(Date.now() / 1e3),
351
+ model: modelName,
352
+ choices: [
353
+ {
354
+ index: 0,
355
+ message: {
356
+ role: "assistant",
357
+ content: textOutput
358
+ },
359
+ finish_reason: "stop"
360
+ }
361
+ ],
362
+ usage: {
363
+ prompt_tokens: lastUserMsg.length,
364
+ completion_tokens: textOutput.length,
365
+ total_tokens: lastUserMsg.length + textOutput.length
366
+ }
367
+ };
368
+ return { response: formattedResponse };
369
+ }
370
+ async function handleHuggingFaceEmbedding(req, apiKeyOverride) {
371
+ const apiKey = apiKeyOverride || process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN;
372
+ if (!apiKey) {
373
+ throw new Error("HuggingFace API Key missing. Set HUGGINGFACE_API_KEY or HF_TOKEN in environment variables.");
374
+ }
375
+ let modelName = req.model.replace(/^(huggingface|hf)\//i, "");
376
+ if (!modelName || modelName === "default" || modelName.includes("text-embedding-3") || modelName.includes("ada") || !modelName.includes("/") && !modelName.includes("bge") && !modelName.includes("sentence-transformers")) {
377
+ modelName = "BAAI/bge-base-en-v1.5";
378
+ }
379
+ const inputs = Array.isArray(req.input) ? req.input : [req.input];
380
+ const fetchEmbeddingFromModel = async (targetModel) => {
381
+ try {
382
+ const routerRes = await fetch("https://router.huggingface.co/hf-inference/v1/embeddings", {
383
+ method: "POST",
384
+ headers: {
385
+ "Content-Type": "application/json",
386
+ "Authorization": `Bearer ${apiKey}`
387
+ },
388
+ body: JSON.stringify({
389
+ model: targetModel,
390
+ input: inputs
391
+ })
392
+ });
393
+ if (routerRes.ok) {
394
+ const json = await routerRes.json();
395
+ if (json && json.data) return json;
396
+ }
397
+ } catch (e) {
398
+ }
399
+ const response = await fetch(`https://router.huggingface.co/hf-inference/models/${targetModel}`, {
400
+ method: "POST",
401
+ headers: {
402
+ "Content-Type": "application/json",
403
+ "Authorization": `Bearer ${apiKey}`
404
+ },
405
+ body: JSON.stringify({
406
+ inputs,
407
+ options: { wait_for_model: true }
408
+ })
409
+ });
410
+ if (!response.ok) {
411
+ const errorText = await response.text();
412
+ throw new Error(`HuggingFace API Error (${response.status}): ${errorText}`);
413
+ }
414
+ const rawData = await response.json();
415
+ const embeddings = Array.isArray(rawData[0]) ? typeof rawData[0][0] === "number" ? rawData : rawData.map((arr) => arr[0]) : [rawData];
416
+ return {
417
+ object: "list",
418
+ data: embeddings.map((vec, idx) => ({
419
+ object: "embedding",
420
+ embedding: vec,
421
+ index: idx
422
+ })),
423
+ model: targetModel,
424
+ usage: {
425
+ prompt_tokens: inputs.reduce((acc, str) => acc + str.length, 0),
426
+ completion_tokens: 0,
427
+ total_tokens: inputs.reduce((acc, str) => acc + str.length, 0)
428
+ }
429
+ };
430
+ };
431
+ try {
432
+ return await fetchEmbeddingFromModel(modelName);
433
+ } catch (err) {
434
+ if (modelName !== "BAAI/bge-base-en-v1.5") {
435
+ console.warn(`[LLM Gateway] HuggingFace model ${modelName} failed. Falling back to BAAI/bge-base-en-v1.5...`, err);
436
+ return await fetchEmbeddingFromModel("BAAI/bge-base-en-v1.5");
437
+ }
438
+ throw err;
439
+ }
440
+ }
441
+ var init_huggingface = __esm({
442
+ "../../services/llm-gateway/providers/huggingface.ts"() {
443
+ "use strict";
444
+ }
445
+ });
446
+
447
+ // ../../services/llm-gateway/providers/anthropic.ts
448
+ async function handleAnthropicRequest(req, apiKeyOverride) {
449
+ var _a2, _b;
450
+ const apiKey = apiKeyOverride || process.env.ANTHROPIC_API_KEY;
451
+ if (!apiKey) {
452
+ throw new Error("Anthropic API Key missing. Please set ANTHROPIC_API_KEY in environment variables.");
453
+ }
454
+ const modelName = req.model.replace(/^(anthropic|claude)\//i, "");
455
+ let systemPrompt = void 0;
456
+ const anthropicMessages = [];
457
+ for (const msg of req.messages) {
458
+ if (msg.role === "system") {
459
+ systemPrompt = systemPrompt ? `${systemPrompt}
460
+ ${msg.content}` : msg.content;
461
+ } else {
462
+ anthropicMessages.push({
463
+ role: msg.role === "assistant" ? "assistant" : "user",
464
+ content: msg.content
465
+ });
466
+ }
467
+ }
468
+ if (anthropicMessages.length === 0) {
469
+ anthropicMessages.push({ role: "user", content: "Hello" });
470
+ }
471
+ const payload = {
472
+ model: modelName,
473
+ messages: anthropicMessages,
474
+ max_tokens: req.max_tokens || req.max_completion_tokens || 1024,
475
+ stream: req.stream || false
476
+ };
477
+ if (systemPrompt) {
478
+ payload.system = systemPrompt;
479
+ }
480
+ if (req.temperature !== void 0) {
481
+ payload.temperature = req.temperature;
482
+ }
483
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
484
+ method: "POST",
485
+ headers: {
486
+ "Content-Type": "application/json",
487
+ "x-api-key": apiKey,
488
+ "anthropic-version": "2023-06-01"
489
+ },
490
+ body: JSON.stringify(payload)
491
+ });
492
+ if (!response.ok) {
493
+ const errorText = await response.text();
494
+ throw new Error(`Anthropic API Error (${response.status}): ${errorText}`);
495
+ }
496
+ if (req.stream && response.body) {
497
+ return { stream: response.body };
498
+ }
499
+ const json = await response.json();
500
+ const textContent = ((_b = (_a2 = json.content) == null ? void 0 : _a2[0]) == null ? void 0 : _b.text) || "";
501
+ const openAIResponse = {
502
+ id: json.id || `chatcmpl-${Date.now()}`,
503
+ object: "chat.completion",
504
+ created: Math.floor(Date.now() / 1e3),
505
+ model: json.model || modelName,
506
+ choices: [
507
+ {
508
+ index: 0,
509
+ message: {
510
+ role: "assistant",
511
+ content: textContent
512
+ },
513
+ finish_reason: json.stop_reason === "end_turn" ? "stop" : json.stop_reason || "stop"
514
+ }
515
+ ],
516
+ usage: json.usage ? {
517
+ prompt_tokens: json.usage.input_tokens,
518
+ completion_tokens: json.usage.output_tokens,
519
+ total_tokens: json.usage.input_tokens + json.usage.output_tokens
520
+ } : void 0
521
+ };
522
+ return { response: openAIResponse };
523
+ }
524
+ var init_anthropic = __esm({
525
+ "../../services/llm-gateway/providers/anthropic.ts"() {
526
+ "use strict";
527
+ }
528
+ });
529
+
530
+ // ../../services/llm-gateway/providers/ollama.ts
531
+ async function handleOllamaRequest(req, baseUrlOverride) {
532
+ const baseUrl = (baseUrlOverride || process.env.OLLAMA_BASE_URL || "http://localhost:11434/v1").replace(/\/+$/, "");
533
+ const modelName = req.model.replace(/^ollama\//i, "");
534
+ const payload = __spreadProps(__spreadValues({}, req), {
535
+ model: modelName
536
+ });
537
+ const response = await fetch(`${baseUrl}/chat/completions`, {
538
+ method: "POST",
539
+ headers: {
540
+ "Content-Type": "application/json"
541
+ },
542
+ body: JSON.stringify(payload)
543
+ });
544
+ if (!response.ok) {
545
+ const errorText = await response.text();
546
+ throw new Error(`Ollama API Error (${response.status}): ${errorText}`);
547
+ }
548
+ if (req.stream && response.body) {
549
+ return { stream: response.body };
550
+ }
551
+ const json = await response.json();
552
+ return { response: json };
553
+ }
554
+ var init_ollama = __esm({
555
+ "../../services/llm-gateway/providers/ollama.ts"() {
556
+ "use strict";
557
+ }
558
+ });
559
+
560
+ // ../../services/llm-gateway/router.ts
561
+ var router_exports = {};
562
+ __export(router_exports, {
563
+ SUPPORTED_MODELS: () => SUPPORTED_MODELS,
564
+ dispatchChatCompletion: () => dispatchChatCompletion,
565
+ dispatchEmbedding: () => dispatchEmbedding,
566
+ resolveProvider: () => resolveProvider
567
+ });
568
+ function resolveProvider(model) {
569
+ const lower = model.toLowerCase();
570
+ if (lower.startsWith("huggingface/") || lower.startsWith("hf/")) {
571
+ return "huggingface";
572
+ }
573
+ if (lower.startsWith("ollama/")) {
574
+ return "ollama";
575
+ }
576
+ if (lower.startsWith("groq/") || lower.includes("llama") || lower.includes("qwen") || lower.includes("mixtral")) {
577
+ return "groq";
578
+ }
579
+ if (process.env.GROQ_API_KEY) return "groq";
580
+ if (process.env.OPENAI_API_KEY) return "openai";
581
+ if (process.env.GEMINI_API_KEY) return "gemini";
582
+ if (process.env.ANTHROPIC_API_KEY) return "anthropic";
583
+ if (process.env.HF_TOKEN || process.env.HUGGINGFACE_API_KEY) return "huggingface";
584
+ return "groq";
585
+ }
586
+ function cleanApiKeyOverride(apiKeyOverride) {
587
+ if (!apiKeyOverride) return void 0;
588
+ const key = apiKeyOverride.trim();
589
+ if (key === process.env.LITELLM_API_KEY || key === process.env.LITELLM_MASTER_KEY || key.startsWith("sk-retrivora") || !key.startsWith("gsk_") && !key.startsWith("AIza") && !key.startsWith("sk-ant-") && !key.startsWith("sk-proj-")) {
590
+ return void 0;
591
+ }
592
+ return key;
593
+ }
594
+ async function dispatchChatCompletion(req, apiKeyOverride) {
595
+ const effectiveKey = cleanApiKeyOverride(apiKeyOverride);
596
+ const provider = resolveProvider(req.model);
597
+ 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)}`);
598
+ try {
599
+ switch (provider) {
600
+ case "groq":
601
+ return await handleGroqRequest(req, effectiveKey);
602
+ case "openai":
603
+ return await handleOpenAIRequest(req, effectiveKey);
604
+ case "gemini":
605
+ return await handleGeminiRequest(req, effectiveKey);
606
+ case "anthropic":
607
+ return await handleAnthropicRequest(req, effectiveKey);
608
+ case "ollama":
609
+ return await handleOllamaRequest(req);
610
+ case "huggingface":
611
+ return await handleHuggingFaceChatRequest(req, effectiveKey);
612
+ default:
613
+ throw new Error(`Unsupported LLM provider for model: ${req.model}`);
614
+ }
615
+ } catch (error) {
616
+ console.error(`[LLM Gateway Router] Provider '${provider}' failed for model '${req.model}':`, {
617
+ message: error.message,
618
+ stack: error.stack
619
+ });
620
+ if (/rate[- ]?limit|429|exhausted/i.test(error.message)) {
621
+ const isGroqKey = process.env.GROQ_API_KEY || effectiveKey && effectiveKey.startsWith("gsk_");
622
+ const reqModelLower = req.model.toLowerCase();
623
+ if (isGroqKey && !reqModelLower.includes("llama-3.3-70b")) {
624
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to secondary Groq model (llama-3.3-70b-versatile)...`);
625
+ try {
626
+ return await handleGroqRequest(__spreadProps(__spreadValues({}, req), { model: "llama-3.3-70b-versatile" }), effectiveKey);
627
+ } catch (fErr) {
628
+ console.error("[LLM Gateway] Fallback groq/llama-3.3-70b-versatile failed:", fErr.message);
629
+ }
630
+ }
631
+ const geminiKey = process.env.GEMINI_API_KEY || effectiveKey;
632
+ if (provider !== "gemini" && geminiKey && (geminiKey.startsWith("AIza") || !geminiKey.startsWith("AQ."))) {
633
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to Google Gemini (gemini-2.5-flash)...`);
634
+ try {
635
+ return await handleGeminiRequest(__spreadProps(__spreadValues({}, req), { model: "gemini-2.5-flash" }), effectiveKey);
636
+ } catch (fErr) {
637
+ console.error("[LLM Gateway] Fallback gemini-2.5-flash failed:", fErr.message);
638
+ }
639
+ }
640
+ if (provider !== "huggingface" && (process.env.HF_TOKEN || process.env.HUGGINGFACE_API_KEY)) {
641
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to Hugging Face (Qwen/Qwen2.5-Coder-32B-Instruct)...`);
642
+ try {
643
+ return await handleHuggingFaceChatRequest(__spreadProps(__spreadValues({}, req), { model: "Qwen/Qwen2.5-Coder-32B-Instruct" }), effectiveKey);
644
+ } catch (fErr) {
645
+ console.error("[LLM Gateway] Fallback HuggingFace Qwen failed:", fErr.message);
646
+ }
647
+ }
648
+ if (provider !== "openai" && process.env.OPENAI_API_KEY) {
649
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to OpenAI (gpt-4o-mini)...`);
650
+ try {
651
+ return await handleOpenAIRequest(__spreadProps(__spreadValues({}, req), { model: "gpt-4o-mini" }), effectiveKey);
652
+ } catch (e) {
653
+ }
654
+ }
655
+ console.warn(`[LLM Gateway] Provider ${provider} rate limited (${error.message}). Falling back to local Ollama (llama3.2)...`);
656
+ return handleOllamaRequest(__spreadProps(__spreadValues({}, req), { model: "llama3.2" }));
657
+ }
658
+ throw error;
659
+ }
660
+ }
661
+ async function dispatchEmbedding(req, apiKeyOverride) {
662
+ const effectiveKey = cleanApiKeyOverride(apiKeyOverride);
663
+ if (req.model.startsWith("hf/") || req.model.startsWith("huggingface/") || req.model.includes("bge-")) {
664
+ try {
665
+ return await handleHuggingFaceEmbedding(req, effectiveKey);
666
+ } catch (err) {
667
+ console.warn("[LLM Gateway] HuggingFace explicit model embedding failed, falling back to default gateway chain:", err);
668
+ }
669
+ }
670
+ const geminiKey = process.env.GEMINI_API_KEY || effectiveKey;
671
+ const isGeminiKeyValid = Boolean(geminiKey && (geminiKey.startsWith("AIza") || !geminiKey.startsWith("AQ.")));
672
+ if (isGeminiKeyValid) {
673
+ try {
674
+ return await handleGeminiEmbedding(req, effectiveKey);
675
+ } catch (err) {
676
+ console.warn("[LLM Gateway] Gemini embedding failed:", err);
677
+ }
678
+ }
679
+ if (process.env.OPENAI_API_KEY) {
680
+ try {
681
+ return await handleOpenAIEmbedding(req, effectiveKey);
682
+ } catch (err) {
683
+ console.warn("[LLM Gateway] OpenAI embedding failed:", err);
684
+ }
685
+ }
686
+ if (process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN) {
687
+ try {
688
+ return await handleHuggingFaceEmbedding(req, effectiveKey);
689
+ } catch (err) {
690
+ console.warn("[LLM Gateway] HuggingFace fallback embedding failed:", err);
691
+ }
692
+ }
693
+ return handleGeminiEmbedding(req, effectiveKey);
694
+ }
695
+ var SUPPORTED_MODELS;
696
+ var init_router = __esm({
697
+ "../../services/llm-gateway/router.ts"() {
698
+ "use strict";
699
+ init_groq();
700
+ init_openai();
701
+ init_gemini();
702
+ init_huggingface();
703
+ init_anthropic();
704
+ init_ollama();
705
+ SUPPORTED_MODELS = [
706
+ { id: "groq/llama-3.1-8b-instant", object: "model", created: 17e8, owned_by: "groq" },
707
+ { id: "llama-3.1-8b-instant", object: "model", created: 17e8, owned_by: "groq" },
708
+ { id: "groq/llama-3.3-70b-versatile", object: "model", created: 17e8, owned_by: "groq" },
709
+ { id: "llama-3.3-70b-versatile", object: "model", created: 17e8, owned_by: "groq" },
710
+ { id: "gpt-4o-mini", object: "model", created: 17e8, owned_by: "openai" },
711
+ { id: "openai/gpt-4o-mini", object: "model", created: 17e8, owned_by: "openai" },
712
+ { id: "gpt-4o", object: "model", created: 17e8, owned_by: "openai" },
713
+ { id: "gemini-2.5-flash", object: "model", created: 17e8, owned_by: "google" },
714
+ { id: "google/gemini-2.5-flash", object: "model", created: 17e8, owned_by: "google" },
715
+ { id: "claude-3-5-haiku-20241022", object: "model", created: 17e8, owned_by: "anthropic" },
716
+ { id: "anthropic/claude-3-5-haiku-20241022", object: "model", created: 17e8, owned_by: "anthropic" },
717
+ { id: "text-embedding-004", object: "model", created: 17e8, owned_by: "google" },
718
+ { id: "google/text-embedding-004", object: "model", created: 17e8, owned_by: "google" },
719
+ { id: "BAAI/bge-base-en-v1.5", object: "model", created: 17e8, owned_by: "huggingface" },
720
+ { id: "huggingface/BAAI/bge-base-en-v1.5", object: "model", created: 17e8, owned_by: "huggingface" },
721
+ { id: "groq/qwen3-32b", object: "model", created: 17e8, owned_by: "groq" },
722
+ { id: "qwen/qwen3-32b", object: "model", created: 17e8, owned_by: "groq" },
723
+ { id: "qwen/qwen3-embedding-8b", object: "model", created: 17e8, owned_by: "qwen" },
724
+ { id: "qwen3-embedding-8b", object: "model", created: 17e8, owned_by: "qwen" },
725
+ { id: "ollama/llama3.2", object: "model", created: 17e8, owned_by: "ollama" }
726
+ ];
727
+ if (typeof globalThis !== "undefined") {
728
+ const _g2 = globalThis;
729
+ _g2.__retrivoraDispatchChat = dispatchChatCompletion;
730
+ _g2.__retrivoraDispatchEmbedding = dispatchEmbedding;
731
+ }
732
+ }
733
+ });
734
+
124
735
  // src/providers/vectordb/BaseVectorProvider.ts
125
736
  var BaseVectorProvider;
126
737
  var init_BaseVectorProvider = __esm({
@@ -2825,12 +3436,13 @@ var OpenAIProvider = class {
2825
3436
  role: "system",
2826
3437
  content: buildSystemContent(basePrompt, context)
2827
3438
  };
3439
+ const safeMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
3440
+ role: m.role || "user",
3441
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
3442
+ }));
2828
3443
  const formattedMessages = [
2829
3444
  systemMessage,
2830
- ...messages.map((m) => ({
2831
- role: m.role,
2832
- content: m.content
2833
- }))
3445
+ ...safeMessages
2834
3446
  ];
2835
3447
  const completion = await this.client.chat.completions.create({
2836
3448
  model: this.llmConfig.model,
@@ -2849,12 +3461,13 @@ var OpenAIProvider = class {
2849
3461
  role: "system",
2850
3462
  content: buildSystemContent(basePrompt, context)
2851
3463
  };
3464
+ const safeStreamMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
3465
+ role: m.role || "user",
3466
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
3467
+ }));
2852
3468
  const formattedMessages = [
2853
3469
  systemMessage,
2854
- ...messages.map((m) => ({
2855
- role: m.role,
2856
- content: m.content
2857
- }))
3470
+ ...safeStreamMessages
2858
3471
  ];
2859
3472
  const stream = yield new __await(this.client.chat.completions.create({
2860
3473
  model: this.llmConfig.model,
@@ -3385,9 +3998,9 @@ var GeminiProvider = class {
3385
3998
  * - Messages must strictly alternate between `user` and `model`.
3386
3999
  */
3387
4000
  buildGeminiContents(messages) {
3388
- return messages.filter((m) => m.role !== "system").map((m) => ({
4001
+ return (messages || []).filter((m) => Boolean(m && typeof m === "object" && m.role !== "system")).map((m) => ({
3389
4002
  role: m.role === "assistant" ? "model" : "user",
3390
- parts: [{ text: m.content }]
4003
+ parts: [{ text: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : "" }]
3391
4004
  }));
3392
4005
  }
3393
4006
  // -------------------------------------------------------------------------
@@ -3590,12 +4203,13 @@ var GroqProvider = class {
3590
4203
  role: "system",
3591
4204
  content: buildSystemContent(basePrompt, context)
3592
4205
  };
4206
+ const safeMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4207
+ role: m.role || "user",
4208
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4209
+ }));
3593
4210
  const formattedMessages = [
3594
4211
  systemMessage,
3595
- ...messages.map((m) => ({
3596
- role: m.role,
3597
- content: m.content
3598
- }))
4212
+ ...safeMessages
3599
4213
  ];
3600
4214
  const completion = await this.client.chat.completions.create({
3601
4215
  model: this.llmConfig.model,
@@ -3614,12 +4228,13 @@ var GroqProvider = class {
3614
4228
  role: "system",
3615
4229
  content: buildSystemContent(basePrompt, context)
3616
4230
  };
4231
+ const safeStreamMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4232
+ role: m.role || "user",
4233
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4234
+ }));
3617
4235
  const formattedMessages = [
3618
4236
  systemMessage,
3619
- ...messages.map((m) => ({
3620
- role: m.role,
3621
- content: m.content
3622
- }))
4237
+ ...safeStreamMessages
3623
4238
  ];
3624
4239
  const stream = yield new __await(this.client.chat.completions.create({
3625
4240
  model: this.llmConfig.model,
@@ -3748,12 +4363,13 @@ var QwenProvider = class {
3748
4363
  role: "system",
3749
4364
  content: buildSystemContent(basePrompt, context)
3750
4365
  };
4366
+ const safeMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4367
+ role: m.role || "user",
4368
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4369
+ }));
3751
4370
  const formattedMessages = [
3752
4371
  systemMessage,
3753
- ...messages.map((m) => ({
3754
- role: m.role,
3755
- content: m.content
3756
- }))
4372
+ ...safeMessages
3757
4373
  ];
3758
4374
  const completion = await this.client.chat.completions.create({
3759
4375
  model: this.llmConfig.model,
@@ -3772,12 +4388,13 @@ var QwenProvider = class {
3772
4388
  role: "system",
3773
4389
  content: buildSystemContent(basePrompt, context)
3774
4390
  };
4391
+ const safeStreamMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4392
+ role: m.role || "user",
4393
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4394
+ }));
3775
4395
  const formattedMessages = [
3776
4396
  systemMessage,
3777
- ...messages.map((m) => ({
3778
- role: m.role,
3779
- content: m.content
3780
- }))
4397
+ ...safeStreamMessages
3781
4398
  ];
3782
4399
  const stream = yield new __await(this.client.chat.completions.create({
3783
4400
  model: this.llmConfig.model,
@@ -3876,6 +4493,17 @@ var LLM_PROFILES = {
3876
4493
  };
3877
4494
 
3878
4495
  // src/llm/providers/UniversalLLMAdapter.ts
4496
+ function extractContent(obj) {
4497
+ var _a2, _b, _c;
4498
+ if (!obj || typeof obj !== "object") return void 0;
4499
+ const choice = (_a2 = obj.choices) == null ? void 0 : _a2[0];
4500
+ if (!choice) return void 0;
4501
+ if (typeof ((_b = choice.message) == null ? void 0 : _b.content) === "string") return choice.message.content;
4502
+ if (typeof ((_c = choice.delta) == null ? void 0 : _c.content) === "string") return choice.delta.content;
4503
+ if (typeof choice.text === "string") return choice.text;
4504
+ if (typeof choice.content === "string") return choice.content;
4505
+ return void 0;
4506
+ }
3879
4507
  var UniversalLLMAdapter = class {
3880
4508
  constructor(config) {
3881
4509
  var _a2, _b, _c, _d, _e, _f, _g2, _h;
@@ -3907,14 +4535,18 @@ var UniversalLLMAdapter = class {
3907
4535
  });
3908
4536
  }
3909
4537
  async chat(messages, context) {
3910
- var _a2, _b, _c, _d, _e, _f;
4538
+ var _a2, _b, _c;
3911
4539
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
4540
+ const safeMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4541
+ role: m.role || "user",
4542
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4543
+ }));
3912
4544
  const formattedMessages = [
3913
4545
  { role: "system", content: `${this.systemPrompt}
3914
4546
 
3915
4547
  Context:
3916
4548
  ${context != null ? context : "None"}` },
3917
- ...messages
4549
+ ...safeMessages
3918
4550
  ];
3919
4551
  let payload;
3920
4552
  if (this.opts.chatPayloadTemplate) {
@@ -3935,25 +4567,41 @@ ${context != null ? context : "None"}` },
3935
4567
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
3936
4568
  if (isSelfHost || Boolean(process.env.VERCEL)) {
3937
4569
  const _g2 = globalThis;
3938
- if (typeof _g2.__retrivoraDispatchChat === "function") {
4570
+ let dispatch = _g2.__retrivoraDispatchChat;
4571
+ if (typeof dispatch !== "function") {
3939
4572
  try {
3940
- const res = await _g2.__retrivoraDispatchChat({
4573
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4574
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4575
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4576
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4577
+ dispatch = gateway.dispatchChatCompletion;
4578
+ }
4579
+ } catch (e) {
4580
+ }
4581
+ }
4582
+ if (typeof dispatch === "function") {
4583
+ try {
4584
+ const res = await dispatch({
3941
4585
  model: this.model,
3942
4586
  messages: formattedMessages,
3943
4587
  max_tokens: this.maxTokens,
3944
4588
  temperature: this.temperature
3945
4589
  }, this.apiKey);
3946
- if ((_e = (_d = (_c = (_b = res == null ? void 0 : res.response) == null ? void 0 : _b.choices) == null ? void 0 : _c[0]) == null ? void 0 : _d.message) == null ? void 0 : _e.content) {
3947
- return res.response.choices[0].message.content;
4590
+ const content = extractContent(res == null ? void 0 : res.response);
4591
+ if (content !== void 0) {
4592
+ return content;
3948
4593
  }
4594
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch returned empty content for model: ${this.model}`);
3949
4595
  } catch (dispatchErr) {
3950
4596
  throw dispatchErr;
3951
4597
  }
4598
+ } else {
4599
+ 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.`);
3952
4600
  }
3953
4601
  }
3954
4602
  const { data } = await this.http.post(path2, payload);
3955
- const extractPath = (_f = this.opts.responseExtractPath) != null ? _f : "choices[0].message.content";
3956
- const result = resolvePath(data, extractPath);
4603
+ const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
4604
+ const result = (_c = resolvePath(data, extractPath)) != null ? _c : extractContent(data);
3957
4605
  if (result === void 0) {
3958
4606
  throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
3959
4607
  }
@@ -3966,16 +4614,20 @@ ${context != null ? context : "None"}` },
3966
4614
  */
3967
4615
  chatStream(messages, context) {
3968
4616
  return __asyncGenerator(this, null, function* () {
3969
- var _a2, _b, _c, _d, _e, _f, _g2;
4617
+ var _a2, _b, _c, _d, _e;
3970
4618
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3971
4619
  const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
3972
4620
  const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
4621
+ const safeMessages = (Array.isArray(messages) ? messages : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
4622
+ role: m.role || "user",
4623
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
4624
+ }));
3973
4625
  const formattedMessages = [
3974
4626
  { role: "system", content: `${this.systemPrompt}
3975
4627
 
3976
4628
  Context:
3977
4629
  ${context != null ? context : "None"}` },
3978
- ...messages
4630
+ ...safeMessages
3979
4631
  ];
3980
4632
  let payload;
3981
4633
  if (this.opts.chatPayloadTemplate) {
@@ -4000,10 +4652,22 @@ ${context != null ? context : "None"}` },
4000
4652
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4001
4653
  let streamBody = null;
4002
4654
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4003
- const _g3 = globalThis;
4004
- if (typeof _g3.__retrivoraDispatchChat === "function") {
4655
+ const _g2 = globalThis;
4656
+ let dispatch = _g2.__retrivoraDispatchChat;
4657
+ if (typeof dispatch !== "function") {
4005
4658
  try {
4006
- const res = yield new __await(_g3.__retrivoraDispatchChat({
4659
+ const gateway = yield new __await(Promise.resolve().then(() => (init_router(), router_exports)));
4660
+ if (gateway == null ? void 0 : gateway.dispatchChatCompletion) {
4661
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4662
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4663
+ dispatch = gateway.dispatchChatCompletion;
4664
+ }
4665
+ } catch (e) {
4666
+ }
4667
+ }
4668
+ if (typeof dispatch === "function") {
4669
+ try {
4670
+ const res = yield new __await(dispatch({
4007
4671
  model: this.model,
4008
4672
  messages: formattedMessages,
4009
4673
  max_tokens: this.maxTokens,
@@ -4012,13 +4676,19 @@ ${context != null ? context : "None"}` },
4012
4676
  }, this.apiKey));
4013
4677
  if (res == null ? void 0 : res.stream) {
4014
4678
  streamBody = res.stream;
4015
- } 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) {
4016
- yield res.response.choices[0].message.content;
4017
- return;
4679
+ } else {
4680
+ const content = extractContent(res == null ? void 0 : res.response);
4681
+ if (content !== void 0) {
4682
+ yield content;
4683
+ return;
4684
+ }
4685
+ throw new Error(`[UniversalLLMAdapter] In-process dispatch stream returned empty response for model: ${this.model}`);
4018
4686
  }
4019
4687
  } catch (dispatchErr) {
4020
4688
  throw dispatchErr;
4021
4689
  }
4690
+ } else {
4691
+ 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.`);
4022
4692
  }
4023
4693
  }
4024
4694
  if (!streamBody) {
@@ -4045,14 +4715,14 @@ ${context != null ? context : "None"}` },
4045
4715
  if (done) break;
4046
4716
  buffer += decoder.decode(value, { stream: true });
4047
4717
  const lines = buffer.split("\n");
4048
- buffer = (_g2 = lines.pop()) != null ? _g2 : "";
4718
+ buffer = (_c = lines.pop()) != null ? _c : "";
4049
4719
  for (const line of lines) {
4050
4720
  const trimmed = line.trim();
4051
4721
  if (!trimmed || trimmed === "data: [DONE]") continue;
4052
4722
  if (!trimmed.startsWith("data:")) continue;
4053
4723
  try {
4054
4724
  const json = JSON.parse(trimmed.slice(5).trim());
4055
- const text = resolvePath(json, extractPath);
4725
+ const text = (_d = resolvePath(json, extractPath)) != null ? _d : extractContent(json);
4056
4726
  if (text && typeof text === "string") yield text;
4057
4727
  } catch (e) {
4058
4728
  }
@@ -4062,7 +4732,7 @@ ${context != null ? context : "None"}` },
4062
4732
  const jsonStr = buffer.replace(/^data:\s*/, "").trim();
4063
4733
  try {
4064
4734
  const json = JSON.parse(jsonStr);
4065
- const text = resolvePath(json, extractPath);
4735
+ const text = (_e = resolvePath(json, extractPath)) != null ? _e : extractContent(json);
4066
4736
  if (text && typeof text === "string") yield text;
4067
4737
  } catch (e) {
4068
4738
  }
@@ -4090,18 +4760,33 @@ ${context != null ? context : "None"}` },
4090
4760
  const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4091
4761
  if (isSelfHost || Boolean(process.env.VERCEL)) {
4092
4762
  const _g2 = globalThis;
4093
- if (typeof _g2.__retrivoraDispatchEmbedding === "function") {
4763
+ let dispatch = _g2.__retrivoraDispatchEmbedding;
4764
+ if (typeof dispatch !== "function") {
4094
4765
  try {
4095
- const res = await _g2.__retrivoraDispatchEmbedding({
4766
+ const gateway = await Promise.resolve().then(() => (init_router(), router_exports));
4767
+ if (gateway == null ? void 0 : gateway.dispatchEmbedding) {
4768
+ _g2.__retrivoraDispatchChat = gateway.dispatchChatCompletion;
4769
+ _g2.__retrivoraDispatchEmbedding = gateway.dispatchEmbedding;
4770
+ dispatch = gateway.dispatchEmbedding;
4771
+ }
4772
+ } catch (e) {
4773
+ }
4774
+ }
4775
+ if (typeof dispatch === "function") {
4776
+ try {
4777
+ const res = await dispatch({
4096
4778
  model: this.model,
4097
4779
  input: text
4098
4780
  }, this.apiKey);
4099
4781
  if ((_c = (_b = res == null ? void 0 : res.data) == null ? void 0 : _b[0]) == null ? void 0 : _c.embedding) {
4100
4782
  return res.data[0].embedding;
4101
4783
  }
4784
+ throw new Error(`[UniversalLLMAdapter] In-process embedding dispatch returned invalid vector for model: ${this.model}`);
4102
4785
  } catch (dispatchErr) {
4103
4786
  throw dispatchErr;
4104
4787
  }
4788
+ } else {
4789
+ 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.`);
4105
4790
  }
4106
4791
  }
4107
4792
  const { data } = await this.http.post(path2, payload);
@@ -6080,8 +6765,8 @@ var IntentClassifier = class {
6080
6765
  }
6081
6766
  // ─── Intent Heuristic Checkers ─────────────────────────────────────────────
6082
6767
  static isInformationLookup(query) {
6083
- 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)) {
6084
- if (!/\b(compare|versus|vs\.?|trend|monthly|revenue|top selling|best)\b/i.test(query)) {
6768
+ 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)) {
6769
+ if (!/\b(compare|versus|vs\.?|trend|monthly|revenue|top 10|top selling|best|chart|graph|plot|breakdown|analytics)\b/i.test(query)) {
6085
6770
  return true;
6086
6771
  }
6087
6772
  }
@@ -6118,7 +6803,7 @@ var Rule1SpecificInfoRule = class {
6118
6803
  }
6119
6804
  evaluate(context, intent) {
6120
6805
  const q = (context.userQuery || "").toLowerCase().trim();
6121
- 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);
6806
+ 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);
6122
6807
  const isNonVisual = !/\b(compare|versus|vs\.?|trend|monthly|revenue|best|top 10|chart|table|list|grid)\b/i.test(q);
6123
6808
  if (isFactQuery && isNonVisual) {
6124
6809
  return {
@@ -6949,7 +7634,7 @@ ${schemaProfileText}` : ""}`;
6949
7634
  }
6950
7635
  // ─── Transform Helpers ────────────────────────────────────────────────────
6951
7636
  static transformToProductCarousel(data, config, trainedSchema) {
6952
- const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null).slice(0, 15);
7637
+ const products = data.map((item) => this.extractProductInfo(item, config, trainedSchema)).filter((p) => p !== null);
6953
7638
  return {
6954
7639
  type: "product_carousel",
6955
7640
  title: "Recommended Products",
@@ -7329,7 +8014,8 @@ ${schemaProfileText}` : ""}`;
7329
8014
  return fieldCount.size > 2;
7330
8015
  }
7331
8016
  static profileData(data) {
7332
- const records = data.map((item) => {
8017
+ const records = (data || []).filter((item) => Boolean(item && typeof item === "object")).map((item) => {
8018
+ var _a2, _b;
7333
8019
  const fields2 = {};
7334
8020
  Object.entries(item.metadata || {}).forEach(([key, value]) => {
7335
8021
  const primitive = this.toPrimitive(value);
@@ -7338,8 +8024,8 @@ ${schemaProfileText}` : ""}`;
7338
8024
  if (!fields2.content && item.content) fields2.content = item.content.substring(0, 500);
7339
8025
  return {
7340
8026
  id: item.id,
7341
- content: item.content,
7342
- score: item.score,
8027
+ content: (_a2 = item.content) != null ? _a2 : "",
8028
+ score: (_b = item.score) != null ? _b : 0,
7343
8029
  fields: fields2,
7344
8030
  source: item
7345
8031
  };
@@ -7396,6 +8082,11 @@ ${schemaProfileText}` : ""}`;
7396
8082
  }
7397
8083
  static chooseAutomaticVisualization(data, profile, query) {
7398
8084
  if (profile.records.length === 0) return null;
8085
+ const q = query.toLowerCase().trim();
8086
+ 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);
8087
+ if (!isExplicitVisualOrAnalytic) {
8088
+ return null;
8089
+ }
7399
8090
  if (profile.dateFields.length > 0 && profile.numericFields.length > 0) {
7400
8091
  return this.transformToLineChart(profile);
7401
8092
  }
@@ -7511,6 +8202,7 @@ ${schemaProfileText}` : ""}`;
7511
8202
  return Array.from(categories);
7512
8203
  }
7513
8204
  static getProductCategory(item) {
8205
+ if (!item) return null;
7514
8206
  const meta = item.metadata || {};
7515
8207
  const metadataCategory = resolveMetadataValue(meta, "category");
7516
8208
  if (this.isUsableCategory(metadataCategory)) return String(metadataCategory).trim();
@@ -7627,6 +8319,7 @@ ${schemaProfileText}` : ""}`;
7627
8319
  if (!fields.has(normalized)) fields.set(normalized, clean);
7628
8320
  };
7629
8321
  data.forEach((item) => {
8322
+ if (!item) return;
7630
8323
  Object.keys(item.metadata || {}).forEach(addField);
7631
8324
  for (const match of (item.content || "").matchAll(/(?:^|\n)\s*([A-Za-z][A-Za-z0-9_ /-]{1,50})\s*[:\-–]\s*([^\n]+)/g)) {
7632
8325
  addField(match[1]);
@@ -7743,6 +8436,7 @@ ${schemaProfileText}` : ""}`;
7743
8436
  return true;
7744
8437
  }
7745
8438
  static extractStockQuantity(item) {
8439
+ if (!item) return null;
7746
8440
  const meta = item.metadata || {};
7747
8441
  const stockValue = resolveMetadataValue(meta, "stock");
7748
8442
  const numericStock = this.toFiniteNumber(stockValue);
@@ -8442,7 +9136,7 @@ ${m.content}`).join("\n\n---\n\n");
8442
9136
  */
8443
9137
  askStreamInternal(_0) {
8444
9138
  return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
8445
- 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;
9139
+ 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;
8446
9140
  yield new __await(this.initialize());
8447
9141
  const ns = formatNamespace(namespace != null ? namespace : this.config.projectId);
8448
9142
  const topK = (_b = (_a2 = this.config.rag) == null ? void 0 : _a2.topK) != null ? _b : 5;
@@ -8485,8 +9179,8 @@ ${m.content}`).join("\n\n---\n\n");
8485
9179
  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;
8486
9180
  const hasMetadataFilter = filter.metadata && Object.keys(filter.metadata).length > 0;
8487
9181
  const hasNumericPredicates = Array.isArray(filter.__numericPredicates) && filter.__numericPredicates.length > 0;
8488
- const wantsExhaustiveList = hasNumericPredicates || hasMetadataFilter || /\b(list|all|show|provide|give|get|browse|find|search|display)\b/i.test(question);
8489
- const retrievalLimit = wantsExhaustiveList ? Math.max(topK * 20, 100) : topK * 2;
9182
+ const wantsExhaustiveList = true;
9183
+ const retrievalLimit = Math.max(topK * 50, 1e3);
8490
9184
  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"));
8491
9185
  console.log("[Pipeline] Raw vectorDB.query response:", {
8492
9186
  rawCount: rawSources.length,
@@ -8510,40 +9204,29 @@ ${m.content}`).join("\n\n---\n\n");
8510
9204
  var _a3;
8511
9205
  return ((_a3 = m == null ? void 0 : m.score) != null ? _a3 : 0) >= scoreThreshold;
8512
9206
  });
8513
- const rerankLimit = wantsExhaustiveList ? retrievalLimit : topK;
9207
+ const rerankLimit = Math.max(retrievalLimit, fullSources.length);
8514
9208
  const useReranking = arch !== "naive" && (arch === "retrieve-and-rerank" || ((_m = this.config.rag) == null ? void 0 : _m.useReranking));
8515
9209
  if (!hasNumericPredicates && useReranking) {
8516
9210
  fullSources = (yield new __await(this.reranker.rerank(fullSources, question, rerankLimit))).filter((s) => Boolean(s && typeof s === "object"));
8517
- } else if (!wantsExhaustiveList) {
8518
- fullSources = fullSources.slice(0, topK);
8519
9211
  }
8520
9212
  const rerankMs = performance.now() - rerankStart;
8521
- let context = fullSources.length ? fullSources.map((m, i) => {
9213
+ const totalCount = fullSources.length;
9214
+ const promptSources = fullSources.slice(0, 15);
9215
+ 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]
9216
+
9217
+ ` + promptSources.map((m, i) => {
8522
9218
  var _a3;
8523
9219
  return `[Source ${i + 1}]
8524
9220
  ${(_a3 = m == null ? void 0 : m.content) != null ? _a3 : ""}`;
8525
9221
  }).join("\n\n---\n\n") : "No relevant context found.";
8526
- let displayCount = 15;
8527
- if (hasMetadataFilter) {
8528
- displayCount = fullSources.length;
8529
- } else {
8530
- const baseThreshold = Math.max(scoreThreshold, 0.4);
8531
- const highlyRelevant = fullSources.filter((m) => {
8532
- var _a3;
8533
- return ((_a3 = m == null ? void 0 : m.score) != null ? _a3 : 0) >= baseThreshold;
8534
- });
8535
- displayCount = Math.max(highlyRelevant.length, topK);
8536
- if (displayCount > 15) {
8537
- displayCount = 15;
8538
- }
8539
- }
8540
9222
  const sources = [...fullSources].filter((s) => Boolean(s && typeof s === "object")).sort((a, b) => {
8541
9223
  var _a3, _b2;
8542
9224
  return ((_a3 = b == null ? void 0 : b.score) != null ? _a3 : 0) - ((_b2 = a == null ? void 0 : a.score) != null ? _b2 : 0);
8543
- }).slice(0, displayCount);
9225
+ });
8544
9226
  console.log("[Pipeline] Final sources for prompt & UI:", {
8545
9227
  count: sources.length,
8546
- sources: sources.map((s, idx) => {
9228
+ totalRawCount: rawSources.length,
9229
+ sources: sources.slice(0, 10).map((s, idx) => {
8547
9230
  var _a3;
8548
9231
  return {
8549
9232
  rank: idx + 1,
@@ -8743,7 +9426,7 @@ ${context}`;
8743
9426
  }
8744
9427
  yield fullReply;
8745
9428
  }
8746
- 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;
9429
+ const runHallucination = ((_w = this.config.llm.options) == null ? void 0 : _w.hallucinationScoring) === true;
8747
9430
  if (runHallucination) {
8748
9431
  hallucinationScoringPromise = scoreHallucination(this.llmProvider, fullReply, context).catch(() => void 0);
8749
9432
  }
@@ -8752,7 +9435,7 @@ ${context}`;
8752
9435
  const latency = {
8753
9436
  embedMs: Math.round(embedMs),
8754
9437
  retrieveMs: Math.round(retrieveMs),
8755
- rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_y = this.config.rag) == null ? void 0 : _y.useReranking)) ? Math.round(rerankMs) : void 0,
9438
+ rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_x = this.config.rag) == null ? void 0 : _x.useReranking)) ? Math.round(rerankMs) : void 0,
8756
9439
  generateMs: Math.round(generateMs),
8757
9440
  totalMs: Math.round(totalMs)
8758
9441
  };
@@ -8765,7 +9448,7 @@ ${context}`;
8765
9448
  totalTokens: promptTokens + completionTokens,
8766
9449
  estimatedCostUsd: estimateCostUsd(promptTokens, completionTokens, this.config.llm.model)
8767
9450
  };
8768
- const awaitHallucination = ((_z = this.config.llm.options) == null ? void 0 : _z.awaitHallucination) === true;
9451
+ const awaitHallucination = ((_y = this.config.llm.options) == null ? void 0 : _y.awaitHallucination) === true;
8769
9452
  const [uiTransformation, hallucinationResult] = yield new __await(Promise.all([
8770
9453
  uiTransformationPromise,
8771
9454
  awaitHallucination ? hallucinationScoringPromise : Promise.resolve(void 0)
@@ -8794,10 +9477,10 @@ ${context}`;
8794
9477
  hallucinationReason: hScore.reason
8795
9478
  } : {});
8796
9479
  const trace = buildTrace(hallucinationResult);
8797
- const isTelemetryActive = (_B = (_A = this.config.telemetry) == null ? void 0 : _A.enabled) != null ? _B : Boolean(this.config.licenseKey);
9480
+ const isTelemetryActive = (_A = (_z = this.config.telemetry) == null ? void 0 : _z.enabled) != null ? _A : Boolean(this.config.licenseKey);
8798
9481
  if (isTelemetryActive) {
8799
9482
  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";
8800
- const telemetryUrl = ((_C = this.config.telemetry) == null ? void 0 : _C.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
9483
+ const telemetryUrl = ((_B = this.config.telemetry) == null ? void 0 : _B.url) || process.env.TELEMETRY_URL || process.env.NEXT_PUBLIC_TELEMETRY_URL || defaultUrl;
8801
9484
  const absoluteUrl = telemetryUrl.startsWith("http") ? telemetryUrl : (process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${process.env.PORT || 3e3}`) + telemetryUrl;
8802
9485
  (async () => {
8803
9486
  try {
@@ -8856,9 +9539,8 @@ ${context}`;
8856
9539
  { visualizationHint: "product_browse", recommendedChart: "text", filterInStockOnly: false, wantsExplicitTable: false, isTemporal: false, isComparison: false, language: "en" }
8857
9540
  );
8858
9541
  }
8859
- const isLocalProvider = this.config.llm.provider === "ollama";
8860
- const disableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.disableLlmUiTransform) === true;
8861
- if (forceDeterministic || isLocalProvider || disableLlmUiTransform) {
9542
+ const enableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.enableLlmUiTransform) === true;
9543
+ if (forceDeterministic || !enableLlmUiTransform) {
8862
9544
  return UITransformer.transform(question, sources, this.config, cachedSchema);
8863
9545
  }
8864
9546
  try {
@@ -9015,7 +9697,10 @@ ${context}`;
9015
9697
  Focus on extracting the core intent and entities. Do not answer the question, just rewrite it.
9016
9698
 
9017
9699
  History:
9018
- ${history.map((m) => `${m.role}: ${m.content}`).join("\n")}
9700
+ ${(history || []).map((m) => {
9701
+ var _a2;
9702
+ return `${(m == null ? void 0 : m.role) || "user"}: ${(_a2 = m == null ? void 0 : m.content) != null ? _a2 : ""}`;
9703
+ }).join("\n")}
9019
9704
 
9020
9705
  New Question: ${question}
9021
9706
 
@@ -9039,8 +9724,11 @@ Optimized Search Query:`;
9039
9724
  const ns = formatNamespace(namespace != null ? namespace : this.config.projectId);
9040
9725
  try {
9041
9726
  const { sources } = await this.retrieve(query, { namespace: ns, topK: 5 });
9042
- if (sources.length === 0) return [];
9043
- const context = sources.map((s) => s.content).join("\n\n---\n\n");
9727
+ if (!sources || sources.length === 0) return [];
9728
+ const context = sources.map((s) => {
9729
+ var _a2;
9730
+ return (_a2 = s == null ? void 0 : s.content) != null ? _a2 : "";
9731
+ }).join("\n\n---\n\n");
9044
9732
  const prompt = `Based on the following snippets from a document, what are at least 5 short, relevant questions a user might ask?
9045
9733
  Focus on questions that can be answered by the context.
9046
9734
  Keep each question under 10 words and make them very specific to the content.