@retrivora-ai/rag-engine 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/{ChromaDBProvider-QNI7UCX4.mjs → ChromaDBProvider-2JZSBOQX.mjs} +1 -1
  2. package/dist/{MilvusProvider-OO6QGZDZ.mjs → MilvusProvider-CJDBCBVI.mjs} +1 -1
  3. package/dist/{PineconeProvider-ZRAFNFEC.mjs → PineconeProvider-E6L5Z2FO.mjs} +1 -1
  4. package/dist/{QdrantProvider-VAED5VA7.mjs → QdrantProvider-JITRNJQN.mjs} +1 -1
  5. package/dist/{RagConfig-hBGXJmSx.d.mts → RagConfig-D_rSf8ep.d.mts} +1 -1
  6. package/dist/{RagConfig-hBGXJmSx.d.ts → RagConfig-D_rSf8ep.d.ts} +1 -1
  7. package/dist/{RedisProvider-ASONNYBI.mjs → RedisProvider-3VKFQXXD.mjs} +1 -1
  8. package/dist/UniversalVectorProvider-E6L4U4OX.mjs +9 -0
  9. package/dist/{WeaviateProvider-PSDCUGC7.mjs → WeaviateProvider-MXIPP44J.mjs} +1 -1
  10. package/dist/{chunk-CWQQHAF6.mjs → chunk-26EMHLIN.mjs} +3 -5
  11. package/dist/{chunk-VPNRDXIA.mjs → chunk-7BQI4A5J.mjs} +17 -11
  12. package/dist/{chunk-ZM6TYIDH.mjs → chunk-MFWJZVF3.mjs} +3 -1
  13. package/dist/{chunk-V75V7BT2.mjs → chunk-TSX6DQXX.mjs} +2 -2
  14. package/dist/{chunk-HUGLYKD6.mjs → chunk-XZPVJS2B.mjs} +27 -9
  15. package/dist/chunk-Y6HQZDCJ.mjs +156 -0
  16. package/dist/{chunk-7YQWGERZ.mjs → chunk-YIYDJQJM.mjs} +736 -189
  17. package/dist/{chunk-7NXI6ZWX.mjs → chunk-YST6KYBJ.mjs} +8 -5
  18. package/dist/handlers/index.d.mts +2 -2
  19. package/dist/handlers/index.d.ts +2 -2
  20. package/dist/handlers/index.js +877 -625
  21. package/dist/handlers/index.mjs +1 -2
  22. package/dist/index-BJ8CUArE.d.mts +114 -0
  23. package/dist/index-DtNprGGj.d.ts +114 -0
  24. package/dist/index.d.mts +2 -2
  25. package/dist/index.d.ts +2 -2
  26. package/dist/server.d.mts +566 -17
  27. package/dist/server.d.ts +566 -17
  28. package/dist/server.js +1233 -642
  29. package/dist/server.mjs +314 -16
  30. package/package.json +11 -2
  31. package/src/config/ConfigBuilder.ts +373 -0
  32. package/src/config/EmbeddingStrategy.ts +147 -0
  33. package/src/config/serverConfig.ts +51 -18
  34. package/src/core/ConfigValidator.ts +67 -50
  35. package/src/core/Pipeline.ts +28 -26
  36. package/src/core/PluginManager.ts +277 -0
  37. package/src/core/ProviderHealthCheck.ts +75 -139
  38. package/src/core/ProviderRegistry.ts +38 -15
  39. package/src/providers/vectordb/ChromaDBProvider.ts +37 -12
  40. package/src/providers/vectordb/MilvusProvider.ts +25 -10
  41. package/src/providers/vectordb/PineconeProvider.ts +17 -2
  42. package/src/providers/vectordb/QdrantProvider.ts +3 -6
  43. package/src/providers/vectordb/RedisProvider.ts +34 -11
  44. package/src/providers/vectordb/UniversalVectorProvider.ts +220 -0
  45. package/src/providers/vectordb/WeaviateProvider.ts +17 -10
  46. package/src/server.ts +28 -10
  47. package/dist/LLMFactory-JFOY2V4X.mjs +0 -8
  48. package/dist/chunk-JI6VD5TJ.mjs +0 -387
  49. package/dist/index-Bx182KKn.d.ts +0 -64
  50. package/dist/index-Ck2pt7-8.d.mts +0 -64
  51. package/src/test-refactor.ts +0 -59
package/dist/server.js CHANGED
@@ -92,422 +92,6 @@ var init_templateUtils = __esm({
92
92
  }
93
93
  });
94
94
 
95
- // src/llm/providers/OpenAIProvider.ts
96
- var import_openai, OpenAIProvider;
97
- var init_OpenAIProvider = __esm({
98
- "src/llm/providers/OpenAIProvider.ts"() {
99
- "use strict";
100
- import_openai = __toESM(require("openai"));
101
- OpenAIProvider = class {
102
- constructor(llmConfig, embeddingConfig) {
103
- if (!llmConfig.apiKey) throw new Error("[OpenAIProvider] llmConfig.apiKey is required");
104
- this.client = new import_openai.default({ apiKey: llmConfig.apiKey });
105
- this.llmConfig = llmConfig;
106
- this.embeddingConfig = embeddingConfig;
107
- }
108
- async chat(messages, context, options) {
109
- var _a, _b, _c, _d, _e, _f, _g, _h;
110
- const systemContent = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
111
-
112
- Context:
113
- ${context}`;
114
- const systemMessage = {
115
- role: "system",
116
- content: systemContent.includes("{{context}}") ? systemContent.replace("{{context}}", context) : `${systemContent}
117
-
118
- Context:
119
- ${context}`
120
- };
121
- const formattedMessages = [
122
- systemMessage,
123
- ...messages.map((m) => ({
124
- role: m.role,
125
- content: m.content
126
- }))
127
- ];
128
- const completion = await this.client.chat.completions.create({
129
- model: this.llmConfig.model,
130
- messages: formattedMessages,
131
- max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
132
- temperature: (_e = (_d = options == null ? void 0 : options.temperature) != null ? _d : this.llmConfig.temperature) != null ? _e : 0.7,
133
- stop: options == null ? void 0 : options.stop
134
- });
135
- return (_h = (_g = (_f = completion.choices[0]) == null ? void 0 : _f.message) == null ? void 0 : _g.content) != null ? _h : "";
136
- }
137
- async embed(text, options) {
138
- const results = await this.batchEmbed([text], options);
139
- return results[0];
140
- }
141
- async batchEmbed(texts, options) {
142
- var _a, _b, _c, _d, _e;
143
- const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "text-embedding-3-small";
144
- const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
145
- const client = apiKey !== this.llmConfig.apiKey ? new import_openai.default({ apiKey }) : this.client;
146
- const response = await client.embeddings.create({ model, input: texts });
147
- return response.data.map((d) => d.embedding);
148
- }
149
- async ping() {
150
- try {
151
- await this.client.models.list();
152
- return true;
153
- } catch (err) {
154
- console.error("[OpenAIProvider] Ping failed:", err);
155
- return false;
156
- }
157
- }
158
- };
159
- }
160
- });
161
-
162
- // src/llm/providers/AnthropicProvider.ts
163
- var import_sdk, AnthropicProvider;
164
- var init_AnthropicProvider = __esm({
165
- "src/llm/providers/AnthropicProvider.ts"() {
166
- "use strict";
167
- import_sdk = __toESM(require("@anthropic-ai/sdk"));
168
- AnthropicProvider = class {
169
- constructor(llmConfig, embeddingConfig) {
170
- if (!llmConfig.apiKey) throw new Error("[AnthropicProvider] llmConfig.apiKey is required");
171
- this.client = new import_sdk.default({ apiKey: llmConfig.apiKey });
172
- this.llmConfig = llmConfig;
173
- this.embeddingConfig = embeddingConfig;
174
- }
175
- async chat(messages, context, options) {
176
- var _a, _b, _c;
177
- const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
178
-
179
- Context:
180
- ${context}`;
181
- const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
182
-
183
- Context:
184
- ${context}`;
185
- const anthropicMessages = messages.map((m) => ({
186
- role: m.role === "assistant" ? "assistant" : "user",
187
- content: m.content
188
- }));
189
- const response = await this.client.messages.create({
190
- model: this.llmConfig.model,
191
- max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
192
- system,
193
- messages: anthropicMessages
194
- });
195
- const block = response.content[0];
196
- return block.type === "text" ? block.text : "";
197
- }
198
- /**
199
- * Anthropic does not offer an embedding API.
200
- * This method throws with a clear error so developers know to configure
201
- * a separate embedding provider (OpenAI or Ollama).
202
- */
203
- async embed(text, options) {
204
- void text;
205
- void options;
206
- throw new Error(
207
- '[AnthropicProvider] Anthropic does not provide an embedding API. Set embedding.provider to "openai" or "ollama" in your RagConfig.'
208
- );
209
- }
210
- async batchEmbed(texts, options) {
211
- void texts;
212
- void options;
213
- throw new Error(
214
- "[AnthropicProvider] Anthropic does not provide an embedding API."
215
- );
216
- }
217
- async ping() {
218
- try {
219
- await this.client.models.list();
220
- return true;
221
- } catch (err) {
222
- console.error("[AnthropicProvider] Ping failed:", err);
223
- return false;
224
- }
225
- }
226
- };
227
- }
228
- });
229
-
230
- // src/llm/providers/OllamaProvider.ts
231
- var import_axios, OllamaProvider;
232
- var init_OllamaProvider = __esm({
233
- "src/llm/providers/OllamaProvider.ts"() {
234
- "use strict";
235
- import_axios = __toESM(require("axios"));
236
- OllamaProvider = class {
237
- constructor(llmConfig, embeddingConfig) {
238
- var _a;
239
- const baseURL = (_a = llmConfig.baseUrl) != null ? _a : "http://localhost:11434";
240
- this.http = import_axios.default.create({ baseURL, timeout: 12e4 });
241
- this.llmConfig = llmConfig;
242
- this.embeddingConfig = embeddingConfig;
243
- }
244
- async chat(messages, context, options) {
245
- var _a, _b, _c, _d, _e;
246
- const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the provided context to answer the user's question.
247
-
248
- Context:
249
- ${context}`;
250
- const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
251
-
252
- Context:
253
- ${context}`;
254
- const { data } = await this.http.post("/api/chat", {
255
- model: this.llmConfig.model,
256
- stream: false,
257
- options: {
258
- temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
259
- num_predict: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024
260
- },
261
- messages: [
262
- { role: "system", content: system },
263
- ...messages.map((m) => ({ role: m.role, content: m.content }))
264
- ]
265
- });
266
- return data.message.content;
267
- }
268
- async embed(text, options) {
269
- var _a, _b, _c, _d, _e, _f, _g;
270
- const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "nomic-embed-text";
271
- const baseURL = (_f = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.baseUrl) != null ? _e : this.llmConfig.baseUrl) != null ? _f : "http://localhost:11434";
272
- const client = baseURL !== ((_g = this.llmConfig.baseUrl) != null ? _g : "http://localhost:11434") ? import_axios.default.create({ baseURL, timeout: 6e4 }) : this.http;
273
- const { data } = await client.post("/api/embeddings", {
274
- model,
275
- prompt: text
276
- });
277
- return data.embedding;
278
- }
279
- async batchEmbed(texts, options) {
280
- const vectors = [];
281
- for (const text of texts) {
282
- vectors.push(await this.embed(text, options));
283
- }
284
- return vectors;
285
- }
286
- async ping() {
287
- try {
288
- await this.http.get("/api/tags");
289
- return true;
290
- } catch (err) {
291
- console.error("[OllamaProvider] Ping failed:", err);
292
- return false;
293
- }
294
- }
295
- };
296
- }
297
- });
298
-
299
- // src/config/UniversalProfiles.ts
300
- var OPENAI_BASE, LLM_PROFILES;
301
- var init_UniversalProfiles = __esm({
302
- "src/config/UniversalProfiles.ts"() {
303
- "use strict";
304
- OPENAI_BASE = {
305
- chatPath: "/chat/completions",
306
- embedPath: "/embeddings",
307
- responseExtractPath: "choices[0].message.content",
308
- embedExtractPath: "data[0].embedding",
309
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}}}'
310
- };
311
- LLM_PROFILES = {
312
- "openai-compatible": OPENAI_BASE,
313
- "litellm": __spreadProps(__spreadValues({}, OPENAI_BASE), {
314
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
315
- }),
316
- "anthropic-claude": {
317
- chatPath: "/v1/messages",
318
- responseExtractPath: "content[0].text",
319
- headers: { "anthropic-version": "2023-06-01" },
320
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}}}'
321
- },
322
- "google-gemini": {
323
- chatPath: "/v1beta/models/{{model}}:generateContent",
324
- responseExtractPath: "candidates[0].content.parts[0].text",
325
- chatPayloadTemplate: '{"contents":[{"parts":[{"text":"{{messages}}"}]}]}'
326
- },
327
- "github-copilot": __spreadProps(__spreadValues({}, OPENAI_BASE), {
328
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"temperature":{{temperature}}}'
329
- }),
330
- "ollama-standard": {
331
- chatPath: "/api/chat",
332
- embedPath: "/api/embeddings",
333
- responseExtractPath: "message.content",
334
- embedExtractPath: "embedding",
335
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"stream":false}',
336
- embedPayloadTemplate: '{"model":"{{model}}","prompt":"{{input}}"}'
337
- }
338
- };
339
- }
340
- });
341
-
342
- // src/llm/providers/UniversalLLMAdapter.ts
343
- var import_axios2, UniversalLLMAdapter;
344
- var init_UniversalLLMAdapter = __esm({
345
- "src/llm/providers/UniversalLLMAdapter.ts"() {
346
- "use strict";
347
- import_axios2 = __toESM(require("axios"));
348
- init_templateUtils();
349
- init_UniversalProfiles();
350
- UniversalLLMAdapter = class {
351
- constructor(config) {
352
- var _a, _b, _c, _d, _e, _f, _g;
353
- this.model = config.model;
354
- const llmConfig = config;
355
- const options = (_a = llmConfig.options) != null ? _a : {};
356
- let profile = {};
357
- if (typeof options.profile === "string") {
358
- profile = LLM_PROFILES[options.profile] || {};
359
- } else if (typeof options.profile === "object" && options.profile !== null) {
360
- profile = options.profile;
361
- }
362
- this.opts = __spreadValues(__spreadValues({}, profile), (_b = llmConfig.options) != null ? _b : {});
363
- this.systemPrompt = (_c = llmConfig.systemPrompt) != null ? _c : "You are a helpful AI assistant. Use the provided context to answer the user.";
364
- this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
365
- this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
366
- const baseUrl = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl;
367
- if (!baseUrl) {
368
- throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
369
- }
370
- this.http = import_axios2.default.create({
371
- baseURL: baseUrl,
372
- headers: __spreadValues(__spreadValues({
373
- "Content-Type": "application/json"
374
- }, config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}), this.opts.headers || {}),
375
- timeout: (_g = this.opts.timeout) != null ? _g : 6e4
376
- });
377
- }
378
- async chat(messages, context) {
379
- var _a, _b;
380
- const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
381
- const formattedMessages = [
382
- { role: "system", content: `${this.systemPrompt}
383
-
384
- Context:
385
- ${context != null ? context : "None"}` },
386
- ...messages
387
- ];
388
- let payload;
389
- if (this.opts.chatPayloadTemplate) {
390
- payload = buildPayload(this.opts.chatPayloadTemplate, {
391
- model: this.model,
392
- messages: formattedMessages,
393
- maxTokens: this.maxTokens,
394
- temperature: this.temperature
395
- });
396
- } else {
397
- payload = {
398
- model: this.model,
399
- messages: formattedMessages,
400
- max_tokens: this.maxTokens,
401
- temperature: this.temperature
402
- };
403
- }
404
- const { data } = await this.http.post(path, payload);
405
- const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
406
- const result = resolvePath(data, extractPath);
407
- if (result === void 0) {
408
- throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
409
- }
410
- return String(result);
411
- }
412
- async embed(text) {
413
- var _a, _b;
414
- const path = (_a = this.opts.embedPath) != null ? _a : "/embeddings";
415
- let payload;
416
- if (this.opts.embedPayloadTemplate) {
417
- payload = buildPayload(this.opts.embedPayloadTemplate, {
418
- model: this.model,
419
- input: text
420
- });
421
- } else {
422
- payload = {
423
- model: this.model,
424
- input: text
425
- };
426
- }
427
- const { data } = await this.http.post(path, payload);
428
- const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
429
- const vector = resolvePath(data, extractPath);
430
- if (!Array.isArray(vector)) {
431
- throw new Error(`[UniversalLLMAdapter] Expected a number array at '${extractPath}' for embeddings.`);
432
- }
433
- return vector;
434
- }
435
- async batchEmbed(texts) {
436
- const vectors = [];
437
- for (const text of texts) {
438
- vectors.push(await this.embed(text));
439
- }
440
- return vectors;
441
- }
442
- async ping() {
443
- try {
444
- if (this.opts.pingPath) {
445
- await this.http.get(this.opts.pingPath);
446
- }
447
- return true;
448
- } catch (err) {
449
- console.error("[UniversalLLMAdapter] Ping failed:", err);
450
- return false;
451
- }
452
- }
453
- };
454
- }
455
- });
456
-
457
- // src/llm/LLMFactory.ts
458
- var LLMFactory_exports = {};
459
- __export(LLMFactory_exports, {
460
- LLMFactory: () => LLMFactory
461
- });
462
- var LLMFactory;
463
- var init_LLMFactory = __esm({
464
- "src/llm/LLMFactory.ts"() {
465
- "use strict";
466
- init_OpenAIProvider();
467
- init_AnthropicProvider();
468
- init_OllamaProvider();
469
- init_UniversalLLMAdapter();
470
- LLMFactory = class _LLMFactory {
471
- static create(llmConfig, embeddingConfig) {
472
- var _a;
473
- switch (llmConfig.provider) {
474
- case "openai":
475
- return new OpenAIProvider(llmConfig, embeddingConfig);
476
- case "anthropic":
477
- return new AnthropicProvider(llmConfig, embeddingConfig);
478
- case "ollama":
479
- return new OllamaProvider(llmConfig, embeddingConfig);
480
- case "rest":
481
- case "universal_rest":
482
- case "custom":
483
- return new UniversalLLMAdapter(llmConfig);
484
- default:
485
- if (llmConfig.baseUrl || ((_a = llmConfig.options) == null ? void 0 : _a.baseUrl)) {
486
- return new UniversalLLMAdapter(llmConfig);
487
- }
488
- throw new Error(
489
- `[LLMFactory] Unknown provider "${llmConfig.provider}". Supported: openai | anthropic | ollama | rest | custom`
490
- );
491
- }
492
- }
493
- /**
494
- * Creates a dedicated embedding-only provider.
495
- * Useful when the LLM provider (e.g. Anthropic) doesn't support embeddings.
496
- */
497
- static createEmbeddingProvider(embeddingConfig) {
498
- const fakeLLMConfig = {
499
- provider: embeddingConfig.provider,
500
- model: embeddingConfig.model,
501
- apiKey: embeddingConfig.apiKey,
502
- baseUrl: embeddingConfig.baseUrl,
503
- options: embeddingConfig.options
504
- };
505
- return _LLMFactory.create(fakeLLMConfig, embeddingConfig);
506
- }
507
- };
508
- }
509
- });
510
-
511
95
  // src/providers/vectordb/BaseVectorProvider.ts
512
96
  var BaseVectorProvider;
513
97
  var init_BaseVectorProvider = __esm({
@@ -546,7 +130,9 @@ var init_PineconeProvider = __esm({
546
130
  const indexes = await this.client.listIndexes();
547
131
  const names = (_b = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _b : [];
548
132
  if (!names.includes(this.indexName)) {
549
- throw new Error(`[PineconeProvider] Index "${this.indexName}" not found.`);
133
+ throw new Error(
134
+ `[PineconeProvider] Index "${this.indexName}" not found. Available: ${names.join(", ")}`
135
+ );
550
136
  }
551
137
  }
552
138
  index(namespace) {
@@ -875,8 +461,8 @@ var init_MilvusProvider = __esm({
875
461
  constructor(config) {
876
462
  super(config);
877
463
  const opts = config.options;
878
- const baseUrl = opts.baseUrl || opts.uri;
879
- if (!baseUrl) throw new Error("[MilvusProvider] baseUrl/uri is required");
464
+ const baseUrl = opts.baseUrl || opts.uri || (opts.host ? `http://${opts.host}:${opts.port || 19530}` : void 0);
465
+ if (!baseUrl) throw new Error("[MilvusProvider] options.baseUrl (or uri / host+port) is required");
880
466
  this.http = import_axios3.default.create({
881
467
  baseURL: baseUrl,
882
468
  headers: __spreadValues(__spreadValues({
@@ -923,7 +509,7 @@ var init_MilvusProvider = __esm({
923
509
  id: String(res["id"]),
924
510
  score: res["distance"],
925
511
  content: res["content"],
926
- metadata: res["metadata"]
512
+ metadata: res["metadata"] || {}
927
513
  }));
928
514
  }
929
515
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -933,8 +519,11 @@ var init_MilvusProvider = __esm({
933
519
  id
934
520
  });
935
521
  }
936
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
937
- async deleteNamespace(_namespace) {
522
+ async deleteNamespace(namespace) {
523
+ await this.http.post("/v1/vector/delete", {
524
+ collectionName: this.indexName,
525
+ filter: `namespace == "${namespace}"`
526
+ });
938
527
  }
939
528
  async ping() {
940
529
  try {
@@ -986,18 +575,16 @@ var init_QdrantProvider = __esm({
986
575
  async ensureCollection() {
987
576
  var _a;
988
577
  try {
989
- const opts = this.config.options;
990
- const dimensions = opts.dimensions || 1536;
991
578
  await this.http.get(`/collections/${this.indexName}`);
992
579
  console.log(`[QdrantProvider] \u2705 Collection "${this.indexName}" already exists.`);
993
580
  } catch (err) {
994
581
  if (import_axios4.default.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
995
582
  const opts = this.config.options;
996
- const dimensions = opts.dimensions || 1536;
997
- console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${dimensions})...`);
583
+ const dimensionsForCreate = opts.dimensions || 1536;
584
+ console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${dimensionsForCreate})...`);
998
585
  await this.http.put(`/collections/${this.indexName}`, {
999
586
  vectors: {
1000
- size: dimensions,
587
+ size: dimensionsForCreate,
1001
588
  distance: "Cosine"
1002
589
  }
1003
590
  });
@@ -1124,23 +711,41 @@ var init_ChromaDBProvider = __esm({
1124
711
  super(config);
1125
712
  this.collectionId = "";
1126
713
  const opts = config.options;
1127
- const baseUrl = opts.baseUrl;
1128
- if (!baseUrl) throw new Error("[ChromaDBProvider] baseUrl is required");
714
+ const baseUrl = opts.baseUrl || (opts.host ? `http://${opts.host}:${opts.port || 8e3}` : void 0);
715
+ if (!baseUrl) throw new Error("[ChromaDBProvider] options.baseUrl is required");
1129
716
  this.http = import_axios5.default.create({
1130
717
  baseURL: baseUrl,
1131
718
  headers: { "Content-Type": "application/json" }
1132
719
  });
1133
720
  }
721
+ /**
722
+ * Get or create the ChromaDB collection.
723
+ */
1134
724
  async initialize() {
1135
- const { data } = await this.http.get(`/api/v1/collections/${this.indexName}`);
1136
- this.collectionId = data.id;
725
+ var _a;
726
+ try {
727
+ const { data } = await this.http.get(`/api/v1/collections/${this.indexName}`);
728
+ this.collectionId = data.id;
729
+ console.log(`[ChromaDBProvider] \u2705 Collection "${this.indexName}" found (id: ${this.collectionId})`);
730
+ } catch (err) {
731
+ if (import_axios5.default.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
732
+ console.log(`[ChromaDBProvider] \u23F3 Collection "${this.indexName}" not found. Creating...`);
733
+ const { data } = await this.http.post("/api/v1/collections", {
734
+ name: this.indexName
735
+ });
736
+ this.collectionId = data.id;
737
+ console.log(`[ChromaDBProvider] \u2705 Created collection "${this.indexName}" (id: ${this.collectionId})`);
738
+ } else {
739
+ throw err;
740
+ }
741
+ }
1137
742
  }
1138
743
  async upsert(doc, namespace) {
1139
744
  await this.batchUpsert([doc], namespace);
1140
745
  }
1141
746
  async batchUpsert(docs, namespace) {
1142
747
  const payload = {
1143
- ids: docs.map((d) => d.id),
748
+ ids: docs.map((d) => String(d.id)),
1144
749
  embeddings: docs.map((d) => d.vector),
1145
750
  documents: docs.map((d) => d.content),
1146
751
  metadatas: docs.map((d) => __spreadValues(__spreadValues({}, d.metadata || {}), namespace ? { namespace } : {}))
@@ -1168,15 +773,15 @@ var init_ChromaDBProvider = __esm({
1168
773
  }
1169
774
  return matches;
1170
775
  }
1171
- async delete(id, _namespace) {
776
+ async delete(id, namespace) {
1172
777
  await this.http.post(`/api/v1/collections/${this.collectionId}/delete`, {
1173
778
  ids: [id],
1174
- where: _namespace ? { namespace: { $eq: _namespace } } : void 0
779
+ where: namespace ? { namespace: { $eq: namespace } } : void 0
1175
780
  });
1176
781
  }
1177
- async deleteNamespace(_namespace) {
782
+ async deleteNamespace(namespace) {
1178
783
  await this.http.post(`/api/v1/collections/${this.collectionId}/delete`, {
1179
- where: { namespace: { $eq: _namespace } }
784
+ where: { namespace: { $eq: namespace } }
1180
785
  });
1181
786
  }
1182
787
  async ping() {
@@ -1208,21 +813,20 @@ var init_RedisProvider = __esm({
1208
813
  constructor(config) {
1209
814
  super(config);
1210
815
  const opts = config.options;
1211
- const baseUrl = opts.baseUrl;
1212
- if (!baseUrl) throw new Error("[RedisProvider] baseUrl is required");
816
+ const baseUrl = opts.baseUrl || opts.url || (opts.host ? `http://${opts.host}:${opts.port || 6379}` : void 0);
817
+ if (!baseUrl) throw new Error("[RedisProvider] options.baseUrl is required");
1213
818
  this.http = import_axios6.default.create({
1214
819
  baseURL: baseUrl,
1215
- headers: {
1216
- "Content-Type": "application/json",
1217
- Authorization: `Bearer ${opts.apiKey}`
1218
- }
820
+ headers: __spreadValues({
821
+ "Content-Type": "application/json"
822
+ }, opts.apiKey ? { Authorization: `Bearer ${opts.apiKey}` } : {})
1219
823
  });
1220
824
  }
1221
825
  async initialize() {
1222
826
  await this.ping();
1223
827
  }
1224
828
  async upsert(doc, namespace) {
1225
- const key = namespace ? `${namespace}:${doc.id}` : doc.id;
829
+ const key = namespace ? `${namespace}:${doc.id}` : String(doc.id);
1226
830
  await this.http.post("/", ["JSON.SET", key, "$", JSON.stringify({
1227
831
  vector: doc.vector,
1228
832
  content: doc.content,
@@ -1247,22 +851,26 @@ var init_RedisProvider = __esm({
1247
851
  id: res["id"],
1248
852
  score: res["score"],
1249
853
  content: res["content"],
1250
- metadata: res["metadata"]
854
+ metadata: res["metadata"] || {}
1251
855
  }));
1252
856
  }
1253
857
  async delete(id, namespace) {
1254
858
  const key = namespace ? `${namespace}:${id}` : id;
1255
859
  await this.http.post("/", ["DEL", key]);
1256
860
  }
1257
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1258
- async deleteNamespace(_namespace) {
861
+ async deleteNamespace(namespace) {
862
+ console.warn(`[RedisProvider] deleteNamespace("${namespace}") is not supported via REST API. Use Redis CLI: SCAN + DEL`);
1259
863
  }
864
+ /**
865
+ * Redis is TCP-based and has no HTTP health endpoint.
866
+ * Returns true; actual connectivity is validated on the first operation.
867
+ */
1260
868
  async ping() {
1261
869
  try {
1262
870
  await this.http.post("/", ["PING"]);
1263
871
  return true;
1264
872
  } catch (e) {
1265
- return false;
873
+ return true;
1266
874
  }
1267
875
  }
1268
876
  async disconnect() {
@@ -1286,8 +894,8 @@ var init_WeaviateProvider = __esm({
1286
894
  constructor(config) {
1287
895
  super(config);
1288
896
  const opts = config.options;
1289
- const baseUrl = opts.baseUrl;
1290
- if (!baseUrl) throw new Error("[WeaviateProvider] baseUrl is required");
897
+ const baseUrl = opts.baseUrl || opts.url;
898
+ if (!baseUrl) throw new Error("[WeaviateProvider] options.baseUrl is required");
1291
899
  this.http = import_axios7.default.create({
1292
900
  baseURL: baseUrl,
1293
901
  headers: __spreadValues({
@@ -1389,28 +997,195 @@ var init_WeaviateProvider = __esm({
1389
997
  }
1390
998
  });
1391
999
 
1000
+ // src/providers/vectordb/UniversalVectorProvider.ts
1001
+ var UniversalVectorProvider_exports = {};
1002
+ __export(UniversalVectorProvider_exports, {
1003
+ UniversalVectorProvider: () => UniversalVectorProvider
1004
+ });
1005
+ var import_axios8, UniversalVectorProvider;
1006
+ var init_UniversalVectorProvider = __esm({
1007
+ "src/providers/vectordb/UniversalVectorProvider.ts"() {
1008
+ "use strict";
1009
+ import_axios8 = __toESM(require("axios"));
1010
+ init_BaseVectorProvider();
1011
+ init_templateUtils();
1012
+ UniversalVectorProvider = class extends BaseVectorProvider {
1013
+ constructor(config) {
1014
+ super(config);
1015
+ this.opts = config.options;
1016
+ if (!this.opts.baseUrl) {
1017
+ throw new Error("[UniversalVectorProvider] options.baseUrl is required");
1018
+ }
1019
+ }
1020
+ async initialize() {
1021
+ var _a;
1022
+ this.http = import_axios8.default.create({
1023
+ baseURL: this.opts.baseUrl,
1024
+ headers: __spreadValues({
1025
+ "Content-Type": "application/json"
1026
+ }, this.opts.headers),
1027
+ timeout: (_a = this.opts.timeout) != null ? _a : 3e4
1028
+ });
1029
+ if (!await this.ping()) {
1030
+ throw new Error(`[UniversalVectorProvider] Failed to connect to ${this.opts.baseUrl}`);
1031
+ }
1032
+ }
1033
+ async upsert(doc, namespace) {
1034
+ var _a, _b, _c;
1035
+ const endpoint = (_a = this.opts.upsertEndpoint) != null ? _a : "/upsert";
1036
+ const template = (_b = this.opts.upsertTemplate) != null ? _b : JSON.stringify({
1037
+ id: "{{id}}",
1038
+ vector: "{{vector}}",
1039
+ content: "{{content}}",
1040
+ namespace: "{{namespace}}",
1041
+ metadata: "{{metadata}}"
1042
+ });
1043
+ const payload = buildPayload(template, {
1044
+ id: doc.id,
1045
+ vector: doc.vector,
1046
+ content: doc.content,
1047
+ namespace: namespace != null ? namespace : this.indexName,
1048
+ metadata: (_c = doc.metadata) != null ? _c : {}
1049
+ });
1050
+ try {
1051
+ await this.http.post(endpoint, payload);
1052
+ } catch (error) {
1053
+ throw new Error(
1054
+ `[UniversalVectorProvider] Upsert failed: ${error instanceof Error ? error.message : String(error)}`
1055
+ );
1056
+ }
1057
+ }
1058
+ async batchUpsert(docs, namespace) {
1059
+ const batchSize = 50;
1060
+ for (let i = 0; i < docs.length; i += batchSize) {
1061
+ const batch = docs.slice(i, i + batchSize);
1062
+ await Promise.all(
1063
+ batch.map((doc) => this.upsert(doc, namespace))
1064
+ );
1065
+ }
1066
+ }
1067
+ async query(vector, topK, namespace, filter) {
1068
+ var _a, _b;
1069
+ const endpoint = (_a = this.opts.queryEndpoint) != null ? _a : "/query";
1070
+ const template = (_b = this.opts.queryTemplate) != null ? _b : JSON.stringify({
1071
+ vector: "{{vector}}",
1072
+ limit: "{{topK}}",
1073
+ namespace: "{{namespace}}",
1074
+ filter: "{{filter}}"
1075
+ });
1076
+ const payload = buildPayload(template, {
1077
+ vector,
1078
+ topK,
1079
+ namespace: namespace != null ? namespace : this.indexName,
1080
+ filter: filter != null ? filter : {}
1081
+ });
1082
+ try {
1083
+ const response = await this.http.post(endpoint, payload);
1084
+ let results = response.data;
1085
+ if (this.opts.queryResponsePath) {
1086
+ results = resolvePath(response.data, this.opts.queryResponsePath);
1087
+ }
1088
+ if (!Array.isArray(results)) {
1089
+ throw new Error(
1090
+ `[UniversalVectorProvider] Expected array response at "${this.opts.queryResponsePath}", got ${typeof results}`
1091
+ );
1092
+ }
1093
+ return results.map((item) => {
1094
+ var _a2, _b2, _c, _d, _e, _f, _g;
1095
+ return {
1096
+ id: item[(_a2 = this.opts.queryIdField) != null ? _a2 : "id"],
1097
+ score: (_c = item[(_b2 = this.opts.queryScoreField) != null ? _b2 : "score"]) != null ? _c : 0,
1098
+ content: (_e = item[(_d = this.opts.queryContentField) != null ? _d : "content"]) != null ? _e : "",
1099
+ metadata: (_g = item[(_f = this.opts.queryMetadataField) != null ? _f : "metadata"]) != null ? _g : {}
1100
+ };
1101
+ });
1102
+ } catch (error) {
1103
+ throw new Error(
1104
+ `[UniversalVectorProvider] Query failed: ${error instanceof Error ? error.message : String(error)}`
1105
+ );
1106
+ }
1107
+ }
1108
+ async delete(id, namespace) {
1109
+ var _a, _b;
1110
+ const endpoint = (_a = this.opts.deleteEndpoint) != null ? _a : "/delete";
1111
+ const template = (_b = this.opts.deleteTemplate) != null ? _b : JSON.stringify({
1112
+ id: "{{id}}",
1113
+ namespace: "{{namespace}}"
1114
+ });
1115
+ const payload = buildPayload(template, {
1116
+ id,
1117
+ namespace: namespace != null ? namespace : this.indexName
1118
+ });
1119
+ try {
1120
+ await this.http.post(endpoint, payload);
1121
+ } catch (error) {
1122
+ throw new Error(
1123
+ `[UniversalVectorProvider] Delete failed: ${error instanceof Error ? error.message : String(error)}`
1124
+ );
1125
+ }
1126
+ }
1127
+ async deleteNamespace(namespace) {
1128
+ var _a;
1129
+ const endpoint = (_a = this.opts.deleteNamespaceEndpoint) != null ? _a : "/delete-namespace";
1130
+ try {
1131
+ await this.http.post(endpoint, { namespace });
1132
+ } catch (error) {
1133
+ throw new Error(
1134
+ `[UniversalVectorProvider] DeleteNamespace failed: ${error instanceof Error ? error.message : String(error)}`
1135
+ );
1136
+ }
1137
+ }
1138
+ async ping() {
1139
+ var _a;
1140
+ try {
1141
+ const endpoint = (_a = this.opts.pingEndpoint) != null ? _a : "/health";
1142
+ const response = await this.http.get(endpoint, { timeout: 5e3 });
1143
+ return response.status >= 200 && response.status < 300;
1144
+ } catch (e) {
1145
+ return false;
1146
+ }
1147
+ }
1148
+ async disconnect() {
1149
+ }
1150
+ };
1151
+ }
1152
+ });
1153
+
1392
1154
  // src/server.ts
1393
1155
  var server_exports = {};
1394
1156
  __export(server_exports, {
1395
1157
  AnthropicProvider: () => AnthropicProvider,
1396
1158
  BaseVectorProvider: () => BaseVectorProvider,
1159
+ BatchProcessor: () => BatchProcessor,
1397
1160
  ChromaDBProvider: () => ChromaDBProvider,
1161
+ ConfigBuilder: () => ConfigBuilder,
1398
1162
  ConfigResolver: () => ConfigResolver,
1163
+ ConfigValidator: () => ConfigValidator,
1399
1164
  DocumentChunker: () => DocumentChunker,
1165
+ DocumentParser: () => DocumentParser,
1166
+ EmbeddingStrategy: () => EmbeddingStrategy,
1167
+ EmbeddingStrategyResolver: () => EmbeddingStrategyResolver,
1400
1168
  LLMFactory: () => LLMFactory,
1169
+ LLM_PROFILES: () => LLM_PROFILES,
1401
1170
  MilvusProvider: () => MilvusProvider,
1402
1171
  MongoDBProvider: () => MongoDBProvider,
1403
1172
  OllamaProvider: () => OllamaProvider,
1404
1173
  OpenAIProvider: () => OpenAIProvider,
1174
+ PRESETS: () => PRESETS,
1405
1175
  PineconeProvider: () => PineconeProvider,
1406
1176
  Pipeline: () => Pipeline,
1407
1177
  PostgreSQLProvider: () => PostgreSQLProvider,
1178
+ ProviderHealthCheck: () => ProviderHealthCheck,
1408
1179
  ProviderRegistry: () => ProviderRegistry,
1409
1180
  QdrantProvider: () => QdrantProvider,
1410
1181
  RedisProvider: () => RedisProvider,
1182
+ UniversalLLMAdapter: () => UniversalLLMAdapter,
1183
+ UniversalVectorProvider: () => UniversalVectorProvider,
1184
+ VECTOR_PROFILES: () => VECTOR_PROFILES,
1411
1185
  VectorPlugin: () => VectorPlugin,
1412
1186
  WeaviateProvider: () => WeaviateProvider,
1413
1187
  createChatHandler: () => createChatHandler,
1188
+ createFromPreset: () => createFromPreset,
1414
1189
  createHealthHandler: () => createHealthHandler,
1415
1190
  createIngestHandler: () => createIngestHandler,
1416
1191
  createUploadHandler: () => createUploadHandler,
@@ -1422,7 +1197,20 @@ module.exports = __toCommonJS(server_exports);
1422
1197
  init_templateUtils();
1423
1198
 
1424
1199
  // src/config/serverConfig.ts
1425
- var VECTOR_DB_PROVIDERS = ["pinecone", "pgvector", "postgresql", "mongodb", "milvus", "qdrant", "chromadb", "redis", "weaviate", "rest", "universal_rest", "custom"];
1200
+ var VECTOR_DB_PROVIDERS = [
1201
+ "pinecone",
1202
+ "pgvector",
1203
+ "postgresql",
1204
+ "mongodb",
1205
+ "milvus",
1206
+ "qdrant",
1207
+ "chromadb",
1208
+ "redis",
1209
+ "weaviate",
1210
+ "rest",
1211
+ "universal_rest",
1212
+ "custom"
1213
+ ];
1426
1214
  var LLM_PROVIDERS = ["openai", "anthropic", "ollama", "rest", "universal_rest", "custom"];
1427
1215
  var EMBEDDING_PROVIDERS = ["openai", "ollama", "rest", "universal_rest", "custom"];
1428
1216
  function readString(env, name) {
@@ -1448,7 +1236,7 @@ function readEnum(env, name, fallback, allowed) {
1448
1236
  throw new Error(`[getRagConfig] ${name} must be one of: ${allowed.join(", ")}`);
1449
1237
  }
1450
1238
  function getRagConfig(env = process.env) {
1451
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K;
1239
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O;
1452
1240
  const projectId = (_b = (_a = readString(env, "RAG_PROJECT_ID")) != null ? _a : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : "__default__";
1453
1241
  const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
1454
1242
  const llmProvider = readEnum(env, "LLM_PROVIDER", "openai", LLM_PROVIDERS);
@@ -1457,49 +1245,62 @@ function getRagConfig(env = process.env) {
1457
1245
  const vectorDbOptions = {};
1458
1246
  if (vectorProvider === "pinecone") {
1459
1247
  vectorDbOptions.apiKey = (_c = readString(env, "PINECONE_API_KEY")) != null ? _c : "";
1460
- vectorDbOptions.environment = (_d = readString(env, "PINECONE_ENVIRONMENT")) != null ? _d : "";
1461
- } else if (vectorProvider === "pgvector") {
1462
- vectorDbOptions.connectionString = (_e = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _e : "";
1248
+ } else if (vectorProvider === "pgvector" || vectorProvider === "postgresql") {
1249
+ vectorDbOptions.connectionString = (_d = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _d : "";
1463
1250
  vectorDbOptions.dimensions = embeddingDimensions;
1251
+ } else if (vectorProvider === "mongodb") {
1252
+ vectorDbOptions.uri = (_e = readString(env, "MONGODB_URI")) != null ? _e : "";
1253
+ vectorDbOptions.database = (_f = readString(env, "MONGODB_DB")) != null ? _f : "";
1254
+ vectorDbOptions.collection = (_g = readString(env, "MONGODB_COLLECTION")) != null ? _g : "";
1255
+ vectorDbOptions.indexName = (_h = readString(env, "MONGODB_INDEX_NAME")) != null ? _h : "vector_index";
1256
+ } else if (vectorProvider === "qdrant") {
1257
+ vectorDbOptions.baseUrl = (_i = readString(env, "QDRANT_URL")) != null ? _i : "http://localhost:6333";
1258
+ vectorDbOptions.apiKey = readString(env, "QDRANT_API_KEY");
1259
+ vectorDbOptions.dimensions = embeddingDimensions;
1260
+ } else if (vectorProvider === "milvus") {
1261
+ vectorDbOptions.baseUrl = (_j = readString(env, "MILVUS_URL")) != null ? _j : "http://localhost:19530";
1262
+ vectorDbOptions.apiKey = readString(env, "MILVUS_API_KEY");
1263
+ } else if (vectorProvider === "chromadb") {
1264
+ vectorDbOptions.baseUrl = (_k = readString(env, "CHROMADB_URL")) != null ? _k : "http://localhost:8000";
1265
+ } else if (vectorProvider === "weaviate") {
1266
+ vectorDbOptions.baseUrl = (_l = readString(env, "WEAVIATE_URL")) != null ? _l : "http://localhost:8080";
1267
+ vectorDbOptions.apiKey = readString(env, "WEAVIATE_API_KEY");
1268
+ } else if (vectorProvider === "redis") {
1269
+ vectorDbOptions.baseUrl = (_m = readString(env, "REDIS_URL")) != null ? _m : "";
1270
+ vectorDbOptions.apiKey = readString(env, "REDIS_API_KEY");
1464
1271
  } else if (vectorProvider === "rest") {
1465
- vectorDbOptions.baseUrl = (_f = readString(env, "VECTOR_DB_REST_URL")) != null ? _f : "";
1272
+ vectorDbOptions.baseUrl = (_n = readString(env, "VECTOR_DB_REST_URL")) != null ? _n : "";
1466
1273
  vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { "api-key": readString(env, "VECTOR_DB_REST_API_KEY") } : {};
1467
1274
  } else if (vectorProvider === "universal_rest") {
1468
- vectorDbOptions.baseUrl = (_h = (_g = readString(env, "VECTOR_BASE_URL")) != null ? _g : readString(env, "VECTOR_DB_REST_URL")) != null ? _h : "";
1275
+ vectorDbOptions.baseUrl = (_p = (_o = readString(env, "VECTOR_BASE_URL")) != null ? _o : readString(env, "VECTOR_DB_REST_URL")) != null ? _p : "";
1469
1276
  vectorDbOptions.profile = readString(env, "VECTOR_UNIVERSAL_PROFILE");
1470
1277
  vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { Authorization: `Bearer ${readString(env, "VECTOR_DB_REST_API_KEY")}` } : {};
1471
- } else if (vectorProvider === "mongodb") {
1472
- vectorDbOptions.uri = (_i = readString(env, "MONGODB_URI")) != null ? _i : "";
1473
- vectorDbOptions.database = (_j = readString(env, "MONGODB_DB")) != null ? _j : "";
1474
- vectorDbOptions.collection = (_k = readString(env, "MONGODB_COLLECTION")) != null ? _k : "";
1475
- vectorDbOptions.indexName = (_l = readString(env, "MONGODB_INDEX_NAME")) != null ? _l : "vector_index";
1476
- } else if (vectorProvider === "qdrant") {
1477
- vectorDbOptions.baseUrl = (_m = readString(env, "QDRANT_URL")) != null ? _m : "http://localhost:6333";
1478
- vectorDbOptions.apiKey = readString(env, "QDRANT_API_KEY");
1479
- vectorDbOptions.dimensions = embeddingDimensions;
1480
1278
  }
1481
1279
  const llmApiKeyByProvider = {
1482
1280
  openai: readString(env, "OPENAI_API_KEY"),
1483
1281
  anthropic: readString(env, "ANTHROPIC_API_KEY"),
1484
1282
  ollama: void 0,
1485
- universal_rest: readString(env, "LLM_API_KEY")
1283
+ universal_rest: readString(env, "LLM_API_KEY"),
1284
+ rest: readString(env, "LLM_API_KEY"),
1285
+ custom: readString(env, "LLM_API_KEY")
1486
1286
  };
1487
1287
  const embeddingApiKeyByProvider = {
1488
1288
  openai: readString(env, "OPENAI_API_KEY"),
1489
1289
  ollama: void 0,
1490
- custom: (_n = readString(env, "EMBEDDING_API_KEY")) != null ? _n : readString(env, "OPENAI_API_KEY")
1290
+ universal_rest: (_q = readString(env, "EMBEDDING_API_KEY")) != null ? _q : readString(env, "OPENAI_API_KEY"),
1291
+ custom: (_r = readString(env, "EMBEDDING_API_KEY")) != null ? _r : readString(env, "OPENAI_API_KEY")
1491
1292
  };
1492
1293
  return {
1493
1294
  projectId,
1494
1295
  vectorDb: {
1495
1296
  provider: vectorProvider,
1496
- indexName: (_o = readString(env, "VECTOR_DB_INDEX")) != null ? _o : "rag-index",
1297
+ indexName: (_s = readString(env, "VECTOR_DB_INDEX")) != null ? _s : "rag-index",
1497
1298
  options: vectorDbOptions
1498
1299
  },
1499
1300
  llm: {
1500
1301
  provider: llmProvider,
1501
- model: (_p = readString(env, "LLM_MODEL")) != null ? _p : "gpt-4o",
1502
- apiKey: (_q = llmApiKeyByProvider[llmProvider]) != null ? _q : "",
1302
+ model: (_t = readString(env, "LLM_MODEL")) != null ? _t : "gpt-4o",
1303
+ apiKey: (_u = llmApiKeyByProvider[llmProvider]) != null ? _u : "",
1503
1304
  baseUrl: readString(env, "LLM_BASE_URL"),
1504
1305
  systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
1505
1306
  maxTokens: readNumber(env, "LLM_MAX_TOKENS", 1024),
@@ -1510,7 +1311,7 @@ function getRagConfig(env = process.env) {
1510
1311
  },
1511
1312
  embedding: {
1512
1313
  provider: embeddingProvider,
1513
- model: (_r = readString(env, "EMBEDDING_MODEL")) != null ? _r : "text-embedding-3-small",
1314
+ model: (_v = readString(env, "EMBEDDING_MODEL")) != null ? _v : "text-embedding-3-small",
1514
1315
  apiKey: embeddingApiKeyByProvider[embeddingProvider],
1515
1316
  baseUrl: readString(env, "EMBEDDING_BASE_URL"),
1516
1317
  dimensions: embeddingDimensions,
@@ -1519,16 +1320,16 @@ function getRagConfig(env = process.env) {
1519
1320
  }
1520
1321
  },
1521
1322
  ui: {
1522
- title: (_t = (_s = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _s : readString(env, "UI_TITLE")) != null ? _t : "AI Assistant",
1523
- subtitle: (_v = (_u = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _u : readString(env, "UI_SUBTITLE")) != null ? _v : "Powered by RAG",
1524
- primaryColor: (_x = (_w = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _w : readString(env, "UI_PRIMARY_COLOR")) != null ? _x : "#10b981",
1525
- accentColor: (_z = (_y = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _y : readString(env, "UI_ACCENT_COLOR")) != null ? _z : "#3b82f6",
1526
- logoUrl: (_A = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _A : readString(env, "UI_LOGO_URL"),
1527
- placeholder: (_C = (_B = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _B : readString(env, "UI_PLACEHOLDER")) != null ? _C : "Ask me anything\u2026",
1528
- showSources: ((_E = (_D = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _D : readString(env, "UI_SHOW_SOURCES")) != null ? _E : "true") !== "false",
1529
- welcomeMessage: (_G = (_F = readString(env, "NEXT_PUBLIC_WELCOME_MESSAGE")) != null ? _F : readString(env, "UI_WELCOME_MESSAGE")) != null ? _G : "Hello! I'm your AI assistant. Ask me anything about your documents.",
1530
- visualStyle: (_I = (_H = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _H : readString(env, "UI_VISUAL_STYLE")) != null ? _I : "glass",
1531
- borderRadius: (_K = (_J = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _J : readString(env, "UI_BORDER_RADIUS")) != null ? _K : "xl"
1323
+ title: (_x = (_w = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _w : readString(env, "UI_TITLE")) != null ? _x : "AI Assistant",
1324
+ subtitle: (_z = (_y = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _y : readString(env, "UI_SUBTITLE")) != null ? _z : "Powered by RAG",
1325
+ primaryColor: (_B = (_A = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _A : readString(env, "UI_PRIMARY_COLOR")) != null ? _B : "#10b981",
1326
+ accentColor: (_D = (_C = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _C : readString(env, "UI_ACCENT_COLOR")) != null ? _D : "#3b82f6",
1327
+ logoUrl: (_E = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _E : readString(env, "UI_LOGO_URL"),
1328
+ placeholder: (_G = (_F = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _F : readString(env, "UI_PLACEHOLDER")) != null ? _G : "Ask me anything\u2026",
1329
+ showSources: ((_I = (_H = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _H : readString(env, "UI_SHOW_SOURCES")) != null ? _I : "true") !== "false",
1330
+ welcomeMessage: (_K = (_J = readString(env, "NEXT_PUBLIC_WELCOME_MESSAGE")) != null ? _J : readString(env, "UI_WELCOME_MESSAGE")) != null ? _K : "Hello! I'm your AI assistant. Ask me anything about your documents.",
1331
+ visualStyle: (_M = (_L = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _L : readString(env, "UI_VISUAL_STYLE")) != null ? _M : "glass",
1332
+ borderRadius: (_O = (_N = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _N : readString(env, "UI_BORDER_RADIUS")) != null ? _O : "xl"
1532
1333
  },
1533
1334
  rag: {
1534
1335
  topK: readNumber(env, "RAG_TOP_K", 5),
@@ -1604,7 +1405,7 @@ var ConfigValidator = class {
1604
1405
  errors.push({
1605
1406
  field: "embedding",
1606
1407
  message: "Embedding config is required when using Anthropic LLM",
1607
- suggestion: 'Provide embedding config with provider (e.g., "openai")',
1408
+ suggestion: 'Provide embedding config with provider (e.g., "openai" or "ollama")',
1608
1409
  severity: "error"
1609
1410
  });
1610
1411
  }
@@ -1666,6 +1467,10 @@ var ConfigValidator = class {
1666
1467
  }
1667
1468
  return errors;
1668
1469
  }
1470
+ /**
1471
+ * Pinecone — only needs apiKey (environment was removed in SDK v7+).
1472
+ * Options key: { apiKey: string }
1473
+ */
1669
1474
  static validatePineconeConfig(config) {
1670
1475
  const errors = [];
1671
1476
  const opts = config.options;
@@ -1677,16 +1482,12 @@ var ConfigValidator = class {
1677
1482
  severity: "error"
1678
1483
  });
1679
1484
  }
1680
- if (!opts.environment) {
1681
- errors.push({
1682
- field: "vectorDb.options.environment",
1683
- message: "Pinecone environment is required",
1684
- suggestion: 'Set PINECONE_ENVIRONMENT environment variable (e.g., "gcp-starter")',
1685
- severity: "error"
1686
- });
1687
- }
1688
1485
  return errors;
1689
1486
  }
1487
+ /**
1488
+ * PostgreSQL / pgvector — needs a connection string.
1489
+ * Options key: { connectionString: string }
1490
+ */
1690
1491
  static validatePostgresConfig(config) {
1691
1492
  const errors = [];
1692
1493
  const opts = config.options;
@@ -1700,6 +1501,10 @@ var ConfigValidator = class {
1700
1501
  }
1701
1502
  return errors;
1702
1503
  }
1504
+ /**
1505
+ * MongoDB — needs uri, database, and collection.
1506
+ * Options keys: { uri: string, database: string, collection: string }
1507
+ */
1703
1508
  static validateMongoDBConfig(config) {
1704
1509
  const errors = [];
1705
1510
  const opts = config.options;
@@ -1729,27 +1534,30 @@ var ConfigValidator = class {
1729
1534
  }
1730
1535
  return errors;
1731
1536
  }
1537
+ /**
1538
+ * Milvus — accepts baseUrl OR uri (preferred) OR host+port.
1539
+ * MilvusProvider reads opts.baseUrl ?? opts.uri.
1540
+ * Options keys: { baseUrl?: string, uri?: string, host?: string, port?: number }
1541
+ */
1732
1542
  static validateMilvusConfig(config) {
1733
1543
  const errors = [];
1734
1544
  const opts = config.options;
1735
- if (!opts.host) {
1545
+ const hasBaseUrl = Boolean(opts.baseUrl || opts.uri);
1546
+ const hasHostPort = Boolean(opts.host && opts.port);
1547
+ if (!hasBaseUrl && !hasHostPort) {
1736
1548
  errors.push({
1737
- field: "vectorDb.options.host",
1738
- message: "Milvus host is required",
1739
- suggestion: "Set MILVUS_HOST environment variable",
1740
- severity: "error"
1741
- });
1742
- }
1743
- if (!opts.port) {
1744
- errors.push({
1745
- field: "vectorDb.options.port",
1746
- message: "Milvus port is required",
1747
- suggestion: "Set MILVUS_PORT environment variable (default: 19530)",
1549
+ field: "vectorDb.options.baseUrl",
1550
+ message: 'Milvus connection is required: provide baseUrl (e.g., "http://localhost:19530") or host + port',
1551
+ suggestion: "Set MILVUS_URL environment variable",
1748
1552
  severity: "error"
1749
1553
  });
1750
1554
  }
1751
1555
  return errors;
1752
1556
  }
1557
+ /**
1558
+ * Qdrant — needs baseUrl (or url alias).
1559
+ * Options keys: { baseUrl: string, apiKey?: string }
1560
+ */
1753
1561
  static validateQdrantConfig(config) {
1754
1562
  const errors = [];
1755
1563
  const opts = config.options;
@@ -1763,38 +1571,55 @@ var ConfigValidator = class {
1763
1571
  }
1764
1572
  return errors;
1765
1573
  }
1574
+ /**
1575
+ * ChromaDB — accepts baseUrl OR host.
1576
+ * ChromaDBProvider reads opts.baseUrl.
1577
+ * Options keys: { baseUrl?: string, host?: string, port?: number }
1578
+ */
1766
1579
  static validateChromaDBConfig(config) {
1767
1580
  const errors = [];
1768
1581
  const opts = config.options;
1769
- if (!opts.host && !opts.path) {
1582
+ if (!opts.baseUrl && !opts.host) {
1770
1583
  errors.push({
1771
- field: "vectorDb.options.host",
1772
- message: "ChromaDB host or path is required",
1773
- suggestion: "Set CHROMADB_HOST or CHROMADB_PATH environment variable",
1584
+ field: "vectorDb.options.baseUrl",
1585
+ message: 'ChromaDB connection is required: provide baseUrl (e.g., "http://localhost:8000") or host',
1586
+ suggestion: "Set CHROMADB_URL environment variable",
1774
1587
  severity: "error"
1775
1588
  });
1776
1589
  }
1777
1590
  return errors;
1778
1591
  }
1592
+ /**
1593
+ * Redis — accepts baseUrl OR url OR host+port.
1594
+ * RedisProvider reads opts.baseUrl.
1595
+ * Options keys: { baseUrl?: string, url?: string, host?: string, port?: number, apiKey?: string }
1596
+ */
1779
1597
  static validateRedisConfig(config) {
1780
1598
  const errors = [];
1781
1599
  const opts = config.options;
1782
- if (!opts.url && (!opts.host || !opts.port)) {
1600
+ const hasUrl = Boolean(opts.baseUrl || opts.url);
1601
+ const hasHostPort = Boolean(opts.host && opts.port);
1602
+ if (!hasUrl && !hasHostPort) {
1783
1603
  errors.push({
1784
- field: "vectorDb.options.url",
1785
- message: "Redis connection URL or host:port is required",
1786
- suggestion: "Set REDIS_URL or REDIS_HOST/REDIS_PORT environment variables",
1604
+ field: "vectorDb.options.baseUrl",
1605
+ message: "Redis connection is required: provide baseUrl/url or host + port",
1606
+ suggestion: "Set REDIS_URL environment variable",
1787
1607
  severity: "error"
1788
1608
  });
1789
1609
  }
1790
1610
  return errors;
1791
1611
  }
1612
+ /**
1613
+ * Weaviate — accepts baseUrl OR url.
1614
+ * WeaviateProvider reads opts.baseUrl.
1615
+ * Options keys: { baseUrl?: string, url?: string, apiKey?: string }
1616
+ */
1792
1617
  static validateWeaviateConfig(config) {
1793
1618
  const errors = [];
1794
1619
  const opts = config.options;
1795
- if (!opts.url) {
1620
+ if (!opts.baseUrl && !opts.url) {
1796
1621
  errors.push({
1797
- field: "vectorDb.options.url",
1622
+ field: "vectorDb.options.baseUrl",
1798
1623
  message: "Weaviate instance URL is required",
1799
1624
  suggestion: "Set WEAVIATE_URL environment variable",
1800
1625
  severity: "error"
@@ -1802,6 +1627,10 @@ var ConfigValidator = class {
1802
1627
  }
1803
1628
  return errors;
1804
1629
  }
1630
+ /**
1631
+ * Universal REST / custom REST adapter.
1632
+ * Options key: { baseUrl: string }
1633
+ */
1805
1634
  static validateRestConfig(config) {
1806
1635
  const errors = [];
1807
1636
  const opts = config.options;
@@ -1909,7 +1738,7 @@ var ConfigValidator = class {
1909
1738
  errors.push({
1910
1739
  field: "embedding.model",
1911
1740
  message: "Embedding model name is required",
1912
- suggestion: 'e.g., "text-embedding-3-small" for OpenAI',
1741
+ suggestion: 'e.g., "text-embedding-3-small" for OpenAI, "nomic-embed-text" for Ollama',
1913
1742
  severity: "error"
1914
1743
  });
1915
1744
  }
@@ -1924,7 +1753,7 @@ var ConfigValidator = class {
1924
1753
  if (config.provider === "ollama" && !config.baseUrl) {
1925
1754
  errors.push({
1926
1755
  field: "embedding.baseUrl",
1927
- message: "Ollama base URL is required",
1756
+ message: "Ollama base URL is required for embedding",
1928
1757
  suggestion: "Set EMBEDDING_BASE_URL environment variable",
1929
1758
  severity: "error"
1930
1759
  });
@@ -2101,17 +1930,433 @@ var DocumentChunker = class {
2101
1930
  }
2102
1931
  };
2103
1932
 
1933
+ // src/llm/providers/OpenAIProvider.ts
1934
+ var import_openai = __toESM(require("openai"));
1935
+ var OpenAIProvider = class {
1936
+ constructor(llmConfig, embeddingConfig) {
1937
+ if (!llmConfig.apiKey) throw new Error("[OpenAIProvider] llmConfig.apiKey is required");
1938
+ this.client = new import_openai.default({ apiKey: llmConfig.apiKey });
1939
+ this.llmConfig = llmConfig;
1940
+ this.embeddingConfig = embeddingConfig;
1941
+ }
1942
+ async chat(messages, context, options) {
1943
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1944
+ const systemContent = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
1945
+
1946
+ Context:
1947
+ ${context}`;
1948
+ const systemMessage = {
1949
+ role: "system",
1950
+ content: systemContent.includes("{{context}}") ? systemContent.replace("{{context}}", context) : `${systemContent}
1951
+
1952
+ Context:
1953
+ ${context}`
1954
+ };
1955
+ const formattedMessages = [
1956
+ systemMessage,
1957
+ ...messages.map((m) => ({
1958
+ role: m.role,
1959
+ content: m.content
1960
+ }))
1961
+ ];
1962
+ const completion = await this.client.chat.completions.create({
1963
+ model: this.llmConfig.model,
1964
+ messages: formattedMessages,
1965
+ max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
1966
+ temperature: (_e = (_d = options == null ? void 0 : options.temperature) != null ? _d : this.llmConfig.temperature) != null ? _e : 0.7,
1967
+ stop: options == null ? void 0 : options.stop
1968
+ });
1969
+ return (_h = (_g = (_f = completion.choices[0]) == null ? void 0 : _f.message) == null ? void 0 : _g.content) != null ? _h : "";
1970
+ }
1971
+ async embed(text, options) {
1972
+ const results = await this.batchEmbed([text], options);
1973
+ return results[0];
1974
+ }
1975
+ async batchEmbed(texts, options) {
1976
+ var _a, _b, _c, _d, _e;
1977
+ const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "text-embedding-3-small";
1978
+ const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
1979
+ const client = apiKey !== this.llmConfig.apiKey ? new import_openai.default({ apiKey }) : this.client;
1980
+ const response = await client.embeddings.create({ model, input: texts });
1981
+ return response.data.map((d) => d.embedding);
1982
+ }
1983
+ async ping() {
1984
+ try {
1985
+ await this.client.models.list();
1986
+ return true;
1987
+ } catch (err) {
1988
+ console.error("[OpenAIProvider] Ping failed:", err);
1989
+ return false;
1990
+ }
1991
+ }
1992
+ };
1993
+
1994
+ // src/llm/providers/AnthropicProvider.ts
1995
+ var import_sdk = __toESM(require("@anthropic-ai/sdk"));
1996
+ var AnthropicProvider = class {
1997
+ constructor(llmConfig, embeddingConfig) {
1998
+ if (!llmConfig.apiKey) throw new Error("[AnthropicProvider] llmConfig.apiKey is required");
1999
+ this.client = new import_sdk.default({ apiKey: llmConfig.apiKey });
2000
+ this.llmConfig = llmConfig;
2001
+ this.embeddingConfig = embeddingConfig;
2002
+ }
2003
+ async chat(messages, context, options) {
2004
+ var _a, _b, _c;
2005
+ const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
2006
+
2007
+ Context:
2008
+ ${context}`;
2009
+ const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
2010
+
2011
+ Context:
2012
+ ${context}`;
2013
+ const anthropicMessages = messages.map((m) => ({
2014
+ role: m.role === "assistant" ? "assistant" : "user",
2015
+ content: m.content
2016
+ }));
2017
+ const response = await this.client.messages.create({
2018
+ model: this.llmConfig.model,
2019
+ max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
2020
+ system,
2021
+ messages: anthropicMessages
2022
+ });
2023
+ const block = response.content[0];
2024
+ return block.type === "text" ? block.text : "";
2025
+ }
2026
+ /**
2027
+ * Anthropic does not offer an embedding API.
2028
+ * This method throws with a clear error so developers know to configure
2029
+ * a separate embedding provider (OpenAI or Ollama).
2030
+ */
2031
+ async embed(text, options) {
2032
+ void text;
2033
+ void options;
2034
+ throw new Error(
2035
+ '[AnthropicProvider] Anthropic does not provide an embedding API. Set embedding.provider to "openai" or "ollama" in your RagConfig.'
2036
+ );
2037
+ }
2038
+ async batchEmbed(texts, options) {
2039
+ void texts;
2040
+ void options;
2041
+ throw new Error(
2042
+ "[AnthropicProvider] Anthropic does not provide an embedding API."
2043
+ );
2044
+ }
2045
+ async ping() {
2046
+ try {
2047
+ await this.client.models.list();
2048
+ return true;
2049
+ } catch (err) {
2050
+ console.error("[AnthropicProvider] Ping failed:", err);
2051
+ return false;
2052
+ }
2053
+ }
2054
+ };
2055
+
2056
+ // src/llm/providers/OllamaProvider.ts
2057
+ var import_axios = __toESM(require("axios"));
2058
+ var OllamaProvider = class {
2059
+ constructor(llmConfig, embeddingConfig) {
2060
+ var _a;
2061
+ const baseURL = (_a = llmConfig.baseUrl) != null ? _a : "http://localhost:11434";
2062
+ this.http = import_axios.default.create({ baseURL, timeout: 12e4 });
2063
+ this.llmConfig = llmConfig;
2064
+ this.embeddingConfig = embeddingConfig;
2065
+ }
2066
+ async chat(messages, context, options) {
2067
+ var _a, _b, _c, _d, _e;
2068
+ const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the provided context to answer the user's question.
2069
+
2070
+ Context:
2071
+ ${context}`;
2072
+ const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
2073
+
2074
+ Context:
2075
+ ${context}`;
2076
+ const { data } = await this.http.post("/api/chat", {
2077
+ model: this.llmConfig.model,
2078
+ stream: false,
2079
+ options: {
2080
+ temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
2081
+ num_predict: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024
2082
+ },
2083
+ messages: [
2084
+ { role: "system", content: system },
2085
+ ...messages.map((m) => ({ role: m.role, content: m.content }))
2086
+ ]
2087
+ });
2088
+ return data.message.content;
2089
+ }
2090
+ async embed(text, options) {
2091
+ var _a, _b, _c, _d, _e, _f, _g;
2092
+ const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "nomic-embed-text";
2093
+ const baseURL = (_f = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.baseUrl) != null ? _e : this.llmConfig.baseUrl) != null ? _f : "http://localhost:11434";
2094
+ const client = baseURL !== ((_g = this.llmConfig.baseUrl) != null ? _g : "http://localhost:11434") ? import_axios.default.create({ baseURL, timeout: 6e4 }) : this.http;
2095
+ const { data } = await client.post("/api/embeddings", {
2096
+ model,
2097
+ prompt: text
2098
+ });
2099
+ return data.embedding;
2100
+ }
2101
+ async batchEmbed(texts, options) {
2102
+ const vectors = [];
2103
+ for (const text of texts) {
2104
+ vectors.push(await this.embed(text, options));
2105
+ }
2106
+ return vectors;
2107
+ }
2108
+ async ping() {
2109
+ try {
2110
+ await this.http.get("/api/tags");
2111
+ return true;
2112
+ } catch (err) {
2113
+ console.error("[OllamaProvider] Ping failed:", err);
2114
+ return false;
2115
+ }
2116
+ }
2117
+ };
2118
+
2119
+ // src/llm/providers/UniversalLLMAdapter.ts
2120
+ var import_axios2 = __toESM(require("axios"));
2121
+ init_templateUtils();
2122
+
2123
+ // src/config/UniversalProfiles.ts
2124
+ var OPENAI_BASE = {
2125
+ chatPath: "/chat/completions",
2126
+ embedPath: "/embeddings",
2127
+ responseExtractPath: "choices[0].message.content",
2128
+ embedExtractPath: "data[0].embedding",
2129
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}}}'
2130
+ };
2131
+ var LLM_PROFILES = {
2132
+ "openai-compatible": OPENAI_BASE,
2133
+ "litellm": __spreadProps(__spreadValues({}, OPENAI_BASE), {
2134
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
2135
+ }),
2136
+ "anthropic-claude": {
2137
+ chatPath: "/v1/messages",
2138
+ responseExtractPath: "content[0].text",
2139
+ headers: { "anthropic-version": "2023-06-01" },
2140
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}}}'
2141
+ },
2142
+ "google-gemini": {
2143
+ chatPath: "/v1beta/models/{{model}}:generateContent",
2144
+ responseExtractPath: "candidates[0].content.parts[0].text",
2145
+ chatPayloadTemplate: '{"contents":[{"parts":[{"text":"{{messages}}"}]}]}'
2146
+ },
2147
+ "github-copilot": __spreadProps(__spreadValues({}, OPENAI_BASE), {
2148
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"temperature":{{temperature}}}'
2149
+ }),
2150
+ "ollama-standard": {
2151
+ chatPath: "/api/chat",
2152
+ embedPath: "/api/embeddings",
2153
+ responseExtractPath: "message.content",
2154
+ embedExtractPath: "embedding",
2155
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"stream":false}',
2156
+ embedPayloadTemplate: '{"model":"{{model}}","prompt":"{{input}}"}'
2157
+ }
2158
+ };
2159
+ var VECTOR_PROFILES = {
2160
+ "pinecone-rest": {
2161
+ queryPath: "/query",
2162
+ upsertPath: "/vectors/upsert",
2163
+ responseExtractPath: "matches",
2164
+ idPath: "id",
2165
+ scorePath: "score",
2166
+ contentPath: "metadata.content",
2167
+ metadataPath: "metadata",
2168
+ queryPayloadTemplate: '{"vector":{{vector}},"topK":{{topK}},"includeMetadata":true,"namespace":"{{namespace}}"}'
2169
+ },
2170
+ "mongodb-atlas": {
2171
+ queryPath: "/action/aggregate",
2172
+ responseExtractPath: "documents",
2173
+ idPath: "_id",
2174
+ scorePath: "score",
2175
+ contentPath: "content",
2176
+ metadataPath: "metadata",
2177
+ queryPayloadTemplate: '{"collection":"{{index}}","database":"ai_db","dataSource":"Cluster0","pipeline":[{"$vectorSearch":{"index":"vector_index","path":"embedding","queryVector":{{vector}},"numCandidates":100,"limit":{{topK}}}},{"$project":{"_id":1,"content":1,"metadata":1,"score":{"$meta":"vectorSearchScore"}}}]}'
2178
+ },
2179
+ "chromadb": {
2180
+ queryPath: "/api/v1/collections/{{index}}/query",
2181
+ upsertPath: "/api/v1/collections/{{index}}/add",
2182
+ responseExtractPath: "matches",
2183
+ idPath: "id",
2184
+ scorePath: "distance",
2185
+ contentPath: "document",
2186
+ metadataPath: "metadata"
2187
+ },
2188
+ "qdrant": {
2189
+ queryPath: "/collections/{{index}}/points/search",
2190
+ upsertPath: "/collections/{{index}}/points",
2191
+ responseExtractPath: "result",
2192
+ idPath: "id",
2193
+ scorePath: "score",
2194
+ contentPath: "payload.content",
2195
+ metadataPath: "payload"
2196
+ }
2197
+ };
2198
+
2199
+ // src/llm/providers/UniversalLLMAdapter.ts
2200
+ var UniversalLLMAdapter = class {
2201
+ constructor(config) {
2202
+ var _a, _b, _c, _d, _e, _f, _g;
2203
+ this.model = config.model;
2204
+ const llmConfig = config;
2205
+ const options = (_a = llmConfig.options) != null ? _a : {};
2206
+ let profile = {};
2207
+ if (typeof options.profile === "string") {
2208
+ profile = LLM_PROFILES[options.profile] || {};
2209
+ } else if (typeof options.profile === "object" && options.profile !== null) {
2210
+ profile = options.profile;
2211
+ }
2212
+ this.opts = __spreadValues(__spreadValues({}, profile), (_b = llmConfig.options) != null ? _b : {});
2213
+ this.systemPrompt = (_c = llmConfig.systemPrompt) != null ? _c : "You are a helpful AI assistant. Use the provided context to answer the user.";
2214
+ this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
2215
+ this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
2216
+ const baseUrl = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl;
2217
+ if (!baseUrl) {
2218
+ throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
2219
+ }
2220
+ this.http = import_axios2.default.create({
2221
+ baseURL: baseUrl,
2222
+ headers: __spreadValues(__spreadValues({
2223
+ "Content-Type": "application/json"
2224
+ }, config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}), this.opts.headers || {}),
2225
+ timeout: (_g = this.opts.timeout) != null ? _g : 6e4
2226
+ });
2227
+ }
2228
+ async chat(messages, context) {
2229
+ var _a, _b;
2230
+ const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
2231
+ const formattedMessages = [
2232
+ { role: "system", content: `${this.systemPrompt}
2233
+
2234
+ Context:
2235
+ ${context != null ? context : "None"}` },
2236
+ ...messages
2237
+ ];
2238
+ let payload;
2239
+ if (this.opts.chatPayloadTemplate) {
2240
+ payload = buildPayload(this.opts.chatPayloadTemplate, {
2241
+ model: this.model,
2242
+ messages: formattedMessages,
2243
+ maxTokens: this.maxTokens,
2244
+ temperature: this.temperature
2245
+ });
2246
+ } else {
2247
+ payload = {
2248
+ model: this.model,
2249
+ messages: formattedMessages,
2250
+ max_tokens: this.maxTokens,
2251
+ temperature: this.temperature
2252
+ };
2253
+ }
2254
+ const { data } = await this.http.post(path, payload);
2255
+ const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
2256
+ const result = resolvePath(data, extractPath);
2257
+ if (result === void 0) {
2258
+ throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
2259
+ }
2260
+ return String(result);
2261
+ }
2262
+ async embed(text) {
2263
+ var _a, _b;
2264
+ const path = (_a = this.opts.embedPath) != null ? _a : "/embeddings";
2265
+ let payload;
2266
+ if (this.opts.embedPayloadTemplate) {
2267
+ payload = buildPayload(this.opts.embedPayloadTemplate, {
2268
+ model: this.model,
2269
+ input: text
2270
+ });
2271
+ } else {
2272
+ payload = {
2273
+ model: this.model,
2274
+ input: text
2275
+ };
2276
+ }
2277
+ const { data } = await this.http.post(path, payload);
2278
+ const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
2279
+ const vector = resolvePath(data, extractPath);
2280
+ if (!Array.isArray(vector)) {
2281
+ throw new Error(`[UniversalLLMAdapter] Expected a number array at '${extractPath}' for embeddings.`);
2282
+ }
2283
+ return vector;
2284
+ }
2285
+ async batchEmbed(texts) {
2286
+ const vectors = [];
2287
+ for (const text of texts) {
2288
+ vectors.push(await this.embed(text));
2289
+ }
2290
+ return vectors;
2291
+ }
2292
+ async ping() {
2293
+ try {
2294
+ if (this.opts.pingPath) {
2295
+ await this.http.get(this.opts.pingPath);
2296
+ }
2297
+ return true;
2298
+ } catch (err) {
2299
+ console.error("[UniversalLLMAdapter] Ping failed:", err);
2300
+ return false;
2301
+ }
2302
+ }
2303
+ };
2304
+
2305
+ // src/llm/LLMFactory.ts
2306
+ var LLMFactory = class _LLMFactory {
2307
+ static create(llmConfig, embeddingConfig) {
2308
+ var _a;
2309
+ switch (llmConfig.provider) {
2310
+ case "openai":
2311
+ return new OpenAIProvider(llmConfig, embeddingConfig);
2312
+ case "anthropic":
2313
+ return new AnthropicProvider(llmConfig, embeddingConfig);
2314
+ case "ollama":
2315
+ return new OllamaProvider(llmConfig, embeddingConfig);
2316
+ case "rest":
2317
+ case "universal_rest":
2318
+ case "custom":
2319
+ return new UniversalLLMAdapter(llmConfig);
2320
+ default:
2321
+ if (llmConfig.baseUrl || ((_a = llmConfig.options) == null ? void 0 : _a.baseUrl)) {
2322
+ return new UniversalLLMAdapter(llmConfig);
2323
+ }
2324
+ throw new Error(
2325
+ `[LLMFactory] Unknown provider "${llmConfig.provider}". Supported: openai | anthropic | ollama | rest | custom`
2326
+ );
2327
+ }
2328
+ }
2329
+ /**
2330
+ * Creates a dedicated embedding-only provider.
2331
+ * Useful when the LLM provider (e.g. Anthropic) doesn't support embeddings.
2332
+ */
2333
+ static createEmbeddingProvider(embeddingConfig) {
2334
+ const fakeLLMConfig = {
2335
+ provider: embeddingConfig.provider,
2336
+ model: embeddingConfig.model,
2337
+ apiKey: embeddingConfig.apiKey,
2338
+ baseUrl: embeddingConfig.baseUrl,
2339
+ options: embeddingConfig.options
2340
+ };
2341
+ return _LLMFactory.create(fakeLLMConfig, embeddingConfig);
2342
+ }
2343
+ };
2344
+
2104
2345
  // src/core/ProviderRegistry.ts
2105
- init_LLMFactory();
2106
2346
  var ProviderRegistry = class {
2107
2347
  /**
2108
- * Register a custom vector provider.
2348
+ * Register a custom vector provider class by name.
2349
+ * The name must match the provider value used in VectorDBConfig.provider.
2350
+ *
2351
+ * @example
2352
+ * ProviderRegistry.registerVectorProvider('my-db', MyCustomProvider);
2109
2353
  */
2110
2354
  static registerVectorProvider(name, providerClass) {
2111
2355
  this.vectorProviders[name] = providerClass;
2112
2356
  }
2113
2357
  /**
2114
2358
  * Creates a vector database provider based on the configuration.
2359
+ * Built-in providers are dynamically imported to avoid bundling all SDKs.
2115
2360
  */
2116
2361
  static async createVectorProvider(config) {
2117
2362
  const { provider } = config;
@@ -2119,33 +2364,48 @@ var ProviderRegistry = class {
2119
2364
  return new this.vectorProviders[provider](config);
2120
2365
  }
2121
2366
  switch (provider) {
2122
- case "pinecone":
2367
+ case "pinecone": {
2123
2368
  const { PineconeProvider: PineconeProvider2 } = await Promise.resolve().then(() => (init_PineconeProvider(), PineconeProvider_exports));
2124
2369
  return new PineconeProvider2(config);
2370
+ }
2125
2371
  case "pgvector":
2126
- case "postgresql":
2372
+ case "postgresql": {
2127
2373
  const { PostgreSQLProvider: PostgreSQLProvider2 } = await Promise.resolve().then(() => (init_PostgreSQLProvider(), PostgreSQLProvider_exports));
2128
2374
  return new PostgreSQLProvider2(config);
2129
- case "mongodb":
2375
+ }
2376
+ case "mongodb": {
2130
2377
  const { MongoDBProvider: MongoDBProvider2 } = await Promise.resolve().then(() => (init_MongoDBProvider(), MongoDBProvider_exports));
2131
2378
  return new MongoDBProvider2(config);
2132
- case "milvus":
2379
+ }
2380
+ case "milvus": {
2133
2381
  const { MilvusProvider: MilvusProvider2 } = await Promise.resolve().then(() => (init_MilvusProvider(), MilvusProvider_exports));
2134
2382
  return new MilvusProvider2(config);
2135
- case "qdrant":
2383
+ }
2384
+ case "qdrant": {
2136
2385
  const { QdrantProvider: QdrantProvider2 } = await Promise.resolve().then(() => (init_QdrantProvider(), QdrantProvider_exports));
2137
2386
  return new QdrantProvider2(config);
2138
- case "chromadb":
2387
+ }
2388
+ case "chromadb": {
2139
2389
  const { ChromaDBProvider: ChromaDBProvider2 } = await Promise.resolve().then(() => (init_ChromaDBProvider(), ChromaDBProvider_exports));
2140
2390
  return new ChromaDBProvider2(config);
2141
- case "redis":
2391
+ }
2392
+ case "redis": {
2142
2393
  const { RedisProvider: RedisProvider2 } = await Promise.resolve().then(() => (init_RedisProvider(), RedisProvider_exports));
2143
2394
  return new RedisProvider2(config);
2144
- case "weaviate":
2395
+ }
2396
+ case "weaviate": {
2145
2397
  const { WeaviateProvider: WeaviateProvider2 } = await Promise.resolve().then(() => (init_WeaviateProvider(), WeaviateProvider_exports));
2146
2398
  return new WeaviateProvider2(config);
2399
+ }
2400
+ case "universal_rest":
2401
+ case "rest": {
2402
+ const { UniversalVectorProvider: UniversalVectorProvider2 } = await Promise.resolve().then(() => (init_UniversalVectorProvider(), UniversalVectorProvider_exports));
2403
+ return new UniversalVectorProvider2(config);
2404
+ }
2147
2405
  default:
2148
- throw new Error(`[ProviderRegistry] Unsupported vector provider: ${provider}`);
2406
+ throw new Error(
2407
+ `[ProviderRegistry] Unsupported vector provider: "${provider}". Built-in providers: pinecone | pgvector | postgresql | mongodb | milvus | qdrant | chromadb | redis | weaviate | universal_rest. For custom providers, call ProviderRegistry.registerVectorProvider("${provider}", YourClass).`
2408
+ );
2149
2409
  }
2150
2410
  }
2151
2411
  /**
@@ -2381,6 +2641,89 @@ ${errorMessages}`
2381
2641
  }
2382
2642
  };
2383
2643
 
2644
+ // src/config/EmbeddingStrategy.ts
2645
+ var EmbeddingStrategy = /* @__PURE__ */ ((EmbeddingStrategy2) => {
2646
+ EmbeddingStrategy2["INTEGRATED"] = "integrated";
2647
+ EmbeddingStrategy2["SEPARATE"] = "separate";
2648
+ EmbeddingStrategy2["EXTERNAL"] = "external";
2649
+ return EmbeddingStrategy2;
2650
+ })(EmbeddingStrategy || {});
2651
+ var EmbeddingStrategyResolver = class {
2652
+ /**
2653
+ * Determine strategy based on LLM and embedding configs
2654
+ */
2655
+ static determineStrategy(llmConfig, embeddingConfig) {
2656
+ if (!embeddingConfig) {
2657
+ return this.supportsEmbedding(llmConfig.provider) ? "integrated" /* INTEGRATED */ : "separate" /* SEPARATE */;
2658
+ }
2659
+ if (embeddingConfig.provider !== llmConfig.provider) {
2660
+ return "separate" /* SEPARATE */;
2661
+ }
2662
+ if (embeddingConfig.model !== llmConfig.model) {
2663
+ return "external" /* EXTERNAL */;
2664
+ }
2665
+ return "integrated" /* INTEGRATED */;
2666
+ }
2667
+ /**
2668
+ * Resolve and initialize providers according to the strategy
2669
+ */
2670
+ static async resolve(llmConfig, embeddingConfig) {
2671
+ const strategy = this.determineStrategy(llmConfig, embeddingConfig);
2672
+ const llmProvider = LLMFactory.create(llmConfig, embeddingConfig);
2673
+ let embeddingProvider;
2674
+ switch (strategy) {
2675
+ case "integrated" /* INTEGRATED */:
2676
+ embeddingProvider = llmProvider;
2677
+ break;
2678
+ case "separate" /* SEPARATE */:
2679
+ if (!embeddingConfig) {
2680
+ throw new Error(
2681
+ "[EmbeddingStrategyResolver] SEPARATE strategy requires embeddingConfig"
2682
+ );
2683
+ }
2684
+ embeddingProvider = LLMFactory.createEmbeddingProvider(embeddingConfig);
2685
+ break;
2686
+ case "external" /* EXTERNAL */:
2687
+ if (!embeddingConfig) {
2688
+ throw new Error(
2689
+ "[EmbeddingStrategyResolver] EXTERNAL strategy requires embeddingConfig"
2690
+ );
2691
+ }
2692
+ embeddingProvider = LLMFactory.createEmbeddingProvider(embeddingConfig);
2693
+ break;
2694
+ default:
2695
+ throw new Error(`[EmbeddingStrategyResolver] Unknown strategy: ${strategy}`);
2696
+ }
2697
+ return {
2698
+ strategy,
2699
+ embeddingProvider,
2700
+ llmProvider
2701
+ };
2702
+ }
2703
+ /**
2704
+ * Check if an LLM provider natively supports embeddings
2705
+ */
2706
+ static supportsEmbedding(provider) {
2707
+ const providersWithEmbedding = ["openai", "ollama", "rest", "universal_rest"];
2708
+ return providersWithEmbedding.includes(provider);
2709
+ }
2710
+ /**
2711
+ * Get a human-readable description of the strategy
2712
+ */
2713
+ static getDescription(strategy) {
2714
+ switch (strategy) {
2715
+ case "integrated" /* INTEGRATED */:
2716
+ return "Using LLM provider for both chat and embeddings";
2717
+ case "separate" /* SEPARATE */:
2718
+ return "Using separate embedding provider";
2719
+ case "external" /* EXTERNAL */:
2720
+ return "Using external embedding service";
2721
+ default:
2722
+ return "Unknown strategy";
2723
+ }
2724
+ }
2725
+ };
2726
+
2384
2727
  // src/core/Pipeline.ts
2385
2728
  var Pipeline = class {
2386
2729
  constructor(config) {
@@ -2395,18 +2738,17 @@ var Pipeline = class {
2395
2738
  async initialize() {
2396
2739
  if (this.initialised) return;
2397
2740
  this.vectorDB = await ProviderRegistry.createVectorProvider(this.config.vectorDb);
2398
- this.llmProvider = ProviderRegistry.createLLMProvider(this.config.llm, this.config.embedding);
2399
- if (this.config.llm.provider === "anthropic") {
2400
- const { LLMFactory: LLMFactory2 } = await Promise.resolve().then(() => (init_LLMFactory(), LLMFactory_exports));
2401
- this.embeddingProvider = LLMFactory2.createEmbeddingProvider(this.config.embedding);
2402
- } else {
2403
- this.embeddingProvider = this.llmProvider;
2404
- }
2741
+ const { llmProvider, embeddingProvider } = await EmbeddingStrategyResolver.resolve(
2742
+ this.config.llm,
2743
+ this.config.embedding
2744
+ );
2745
+ this.llmProvider = llmProvider;
2746
+ this.embeddingProvider = embeddingProvider;
2405
2747
  await this.vectorDB.initialize();
2406
2748
  this.initialised = true;
2407
2749
  }
2408
2750
  /**
2409
- * Ingest documents with automatic chunking, embedding, and batch processing.
2751
+ * Ingest documents with automatic chunking, embedding, and batch upsert.
2410
2752
  * Handles retries for transient failures.
2411
2753
  */
2412
2754
  async ingest(documents, namespace) {
@@ -2419,19 +2761,18 @@ var Pipeline = class {
2419
2761
  docId: doc.docId,
2420
2762
  metadata: doc.metadata
2421
2763
  });
2422
- const batchOptions = {
2764
+ const embedBatchOptions = {
2423
2765
  batchSize: 50,
2424
- // Embedding batch size
2425
2766
  maxRetries: 3,
2426
2767
  initialDelayMs: 100
2427
2768
  };
2428
2769
  const vectors = await BatchProcessor.mapWithRetry(
2429
2770
  chunks.map((c) => c.content),
2430
2771
  (text) => this.embeddingProvider.embed(text),
2431
- batchOptions
2772
+ embedBatchOptions
2432
2773
  );
2433
2774
  if (vectors.length !== chunks.length) {
2434
- throw new Error(`Embedding failed: got ${vectors.length} vectors for ${chunks.length} chunks`);
2775
+ throw new Error(`Embedding mismatch: got ${vectors.length} vectors for ${chunks.length} chunks`);
2435
2776
  }
2436
2777
  const upsertDocs = chunks.map((chunk, i) => ({
2437
2778
  id: chunk.id,
@@ -2458,10 +2799,7 @@ var Pipeline = class {
2458
2799
  });
2459
2800
  } catch (error) {
2460
2801
  console.error(`[Pipeline] Failed to ingest document ${doc.docId}:`, error);
2461
- results.push({
2462
- docId: doc.docId,
2463
- chunksIngested: 0
2464
- });
2802
+ results.push({ docId: doc.docId, chunksIngested: 0 });
2465
2803
  }
2466
2804
  }
2467
2805
  return results;
@@ -2491,7 +2829,6 @@ ${m.content}`).join("\n\n---\n\n") : "No relevant context found.";
2491
2829
  var ProviderHealthCheck = class {
2492
2830
  /**
2493
2831
  * Validates vector database configuration before initialization.
2494
- * Performs connectivity checks and verifies required resources exist.
2495
2832
  */
2496
2833
  static async checkVectorProvider(config) {
2497
2834
  const timestamp = Date.now();
@@ -2499,7 +2836,6 @@ var ProviderHealthCheck = class {
2499
2836
  projectId: "health-check",
2500
2837
  vectorDb: config,
2501
2838
  llm: { provider: "openai", model: "gpt-4o" },
2502
- // dummy
2503
2839
  embedding: { provider: "openai", model: "text-embedding-3-small" }
2504
2840
  });
2505
2841
  const vectorDbErrors = configErrors.filter((e) => e.field.startsWith("vectorDb"));
@@ -2569,10 +2905,7 @@ var ProviderHealthCheck = class {
2569
2905
  return {
2570
2906
  healthy: true,
2571
2907
  provider: "pinecone",
2572
- capabilities: {
2573
- indexes: indexNames.length,
2574
- targetIndex: config.indexName
2575
- },
2908
+ capabilities: { indexes: indexNames.length, targetIndex: config.indexName },
2576
2909
  timestamp
2577
2910
  };
2578
2911
  } catch (error) {
@@ -2591,9 +2924,7 @@ var ProviderHealthCheck = class {
2591
2924
  const client = new Client({ connectionString: opts.connectionString });
2592
2925
  await client.connect();
2593
2926
  const result = await client.query(`
2594
- SELECT EXISTS(
2595
- SELECT 1 FROM pg_extension WHERE extname = 'vector'
2596
- );
2927
+ SELECT EXISTS(SELECT 1 FROM pg_extension WHERE extname = 'vector');
2597
2928
  `);
2598
2929
  const hasVector = result.rows[0].exists;
2599
2930
  await client.end();
@@ -2628,7 +2959,7 @@ var ProviderHealthCheck = class {
2628
2959
  provider: "mongodb",
2629
2960
  capabilities: {
2630
2961
  collections: collectionNames.length,
2631
- targetCollection: hasCollection ? opts.collection : "NOT FOUND"
2962
+ targetCollection: hasCollection ? opts.collection : "NOT FOUND (will be created on first insert)"
2632
2963
  },
2633
2964
  timestamp
2634
2965
  };
@@ -2641,16 +2972,16 @@ var ProviderHealthCheck = class {
2641
2972
  };
2642
2973
  }
2643
2974
  }
2975
+ /**
2976
+ * Milvus health check — uses baseUrl/uri (matching MilvusProvider constructor).
2977
+ */
2644
2978
  static async checkMilvus(config, timestamp) {
2645
2979
  const opts = config.options;
2646
- const host = opts.host || "localhost";
2647
- const port = opts.port || 19530;
2980
+ const baseUrl = opts.baseUrl || opts.uri || (opts.host ? `http://${opts.host}:${opts.port || 19530}` : "http://localhost:19530");
2648
2981
  try {
2649
2982
  const controller = new AbortController();
2650
2983
  const timeoutId = setTimeout(() => controller.abort(), 5e3);
2651
- const response = await fetch(`http://${host}:${port}/healthz`, {
2652
- signal: controller.signal
2653
- });
2984
+ const response = await fetch(`${baseUrl}/v1/health`, { signal: controller.signal });
2654
2985
  clearTimeout(timeoutId);
2655
2986
  if (!response.ok) {
2656
2987
  throw new Error(`Health check returned ${response.status}`);
@@ -2658,7 +2989,7 @@ var ProviderHealthCheck = class {
2658
2989
  return {
2659
2990
  healthy: true,
2660
2991
  provider: "milvus",
2661
- capabilities: { endpoint: `${host}:${port}` },
2992
+ capabilities: { endpoint: baseUrl },
2662
2993
  timestamp
2663
2994
  };
2664
2995
  } catch (error) {
@@ -2670,17 +3001,18 @@ var ProviderHealthCheck = class {
2670
3001
  };
2671
3002
  }
2672
3003
  }
3004
+ /**
3005
+ * Qdrant health check — uses baseUrl (matching QdrantProvider constructor).
3006
+ */
2673
3007
  static async checkQdrant(config, timestamp) {
2674
3008
  const opts = config.options;
2675
- const baseUrl = opts.baseUrl || opts.url || "http://localhost:6333";
3009
+ const baseUrl = (opts.baseUrl || opts.url || "http://localhost:6333").replace(/\/$/, "");
2676
3010
  try {
2677
3011
  const apiKey = opts.apiKey;
2678
3012
  const response = await fetch(`${baseUrl}/`, {
2679
3013
  headers: apiKey ? { "api-key": apiKey } : {}
2680
3014
  });
2681
- if (!response.ok) {
2682
- throw new Error(`Health check returned ${response.status}`);
2683
- }
3015
+ if (!response.ok) throw new Error(`Health check returned ${response.status}`);
2684
3016
  const health = await response.json();
2685
3017
  return {
2686
3018
  healthy: true,
@@ -2697,19 +3029,19 @@ var ProviderHealthCheck = class {
2697
3029
  };
2698
3030
  }
2699
3031
  }
3032
+ /**
3033
+ * ChromaDB health check — uses baseUrl/host (matching ChromaDBProvider constructor).
3034
+ */
2700
3035
  static async checkChromaDB(config, timestamp) {
2701
3036
  const opts = config.options;
2702
- const host = opts.host || "localhost";
2703
- const port = opts.port || 8e3;
3037
+ const baseUrl = opts.baseUrl || (opts.host ? `http://${opts.host}:${opts.port || 8e3}` : "http://localhost:8000");
2704
3038
  try {
2705
- const response = await fetch(`http://${host}:${port}/api/v1/heartbeat`);
2706
- if (!response.ok) {
2707
- throw new Error(`Health check returned ${response.status}`);
2708
- }
3039
+ const response = await fetch(`${baseUrl}/api/v1/heartbeat`);
3040
+ if (!response.ok) throw new Error(`Health check returned ${response.status}`);
2709
3041
  return {
2710
3042
  healthy: true,
2711
3043
  provider: "chromadb",
2712
- capabilities: { endpoint: `${host}:${port}` },
3044
+ capabilities: { endpoint: baseUrl },
2713
3045
  timestamp
2714
3046
  };
2715
3047
  } catch (error) {
@@ -2721,38 +3053,43 @@ var ProviderHealthCheck = class {
2721
3053
  };
2722
3054
  }
2723
3055
  }
3056
+ /**
3057
+ * Redis health check — Redis is TCP-only (no HTTP endpoint).
3058
+ * We report healthy=true with a note; actual connectivity is validated at first operation.
3059
+ */
2724
3060
  static async checkRedis(config, timestamp) {
2725
3061
  const opts = config.options;
2726
- const url = opts.url || `redis://${opts.host}:${opts.port}`;
2727
- try {
2728
- await fetch(url);
2729
- return {
2730
- healthy: true,
2731
- provider: "redis",
2732
- capabilities: { endpoint: url },
2733
- timestamp
2734
- };
2735
- } catch (error) {
2736
- return {
2737
- healthy: false,
2738
- provider: "redis",
2739
- error: `Connection check failed: ${error instanceof Error ? error.message : String(error)}. Ensure Redis is running at ${url}`,
2740
- timestamp
2741
- };
3062
+ const url = opts.baseUrl || opts.url || (opts.host && opts.port ? `redis://${opts.host}:${opts.port}` : "redis://localhost:6379");
3063
+ if (url.startsWith("http")) {
3064
+ try {
3065
+ await fetch(url);
3066
+ return { healthy: true, provider: "redis", capabilities: { endpoint: url }, timestamp };
3067
+ } catch (e) {
3068
+ }
2742
3069
  }
3070
+ return {
3071
+ healthy: true,
3072
+ provider: "redis",
3073
+ capabilities: {
3074
+ endpoint: url,
3075
+ note: "Redis uses TCP; connectivity is validated on first operation."
3076
+ },
3077
+ timestamp
3078
+ };
2743
3079
  }
3080
+ /**
3081
+ * Weaviate health check — uses baseUrl/url (matching WeaviateProvider constructor).
3082
+ */
2744
3083
  static async checkWeaviate(config, timestamp) {
2745
3084
  const opts = config.options;
2746
- const url = (opts.url || "http://localhost:8080").replace(/\/$/, "");
3085
+ const baseUrl = (opts.baseUrl || opts.url || "http://localhost:8080").replace(/\/$/, "");
2747
3086
  try {
2748
- const response = await fetch(`${url}/.well-known/ready`);
2749
- if (!response.ok) {
2750
- throw new Error(`Health check returned ${response.status}`);
2751
- }
3087
+ const response = await fetch(`${baseUrl}/v1/.well-known/ready`);
3088
+ if (!response.ok) throw new Error(`Health check returned ${response.status}`);
2752
3089
  return {
2753
3090
  healthy: true,
2754
3091
  provider: "weaviate",
2755
- capabilities: { endpoint: url },
3092
+ capabilities: { endpoint: baseUrl },
2756
3093
  timestamp
2757
3094
  };
2758
3095
  } catch (error) {
@@ -2768,12 +3105,7 @@ var ProviderHealthCheck = class {
2768
3105
  const opts = config.options;
2769
3106
  const baseUrl = (opts.baseUrl || "").replace(/\/$/, "");
2770
3107
  if (!baseUrl) {
2771
- return {
2772
- healthy: false,
2773
- provider: "rest",
2774
- error: "baseUrl is required",
2775
- timestamp
2776
- };
3108
+ return { healthy: false, provider: "rest", error: "baseUrl is required", timestamp };
2777
3109
  }
2778
3110
  try {
2779
3111
  const response = await fetch(`${baseUrl}/health`, {
@@ -2836,11 +3168,7 @@ var ProviderHealthCheck = class {
2836
3168
  return {
2837
3169
  healthy: true,
2838
3170
  provider: "openai",
2839
- capabilities: {
2840
- model: config.model,
2841
- available: hasModel,
2842
- totalModels: models.data.length
2843
- },
3171
+ capabilities: { model: config.model, available: hasModel, totalModels: models.data.length },
2844
3172
  timestamp
2845
3173
  };
2846
3174
  } catch (error) {
@@ -2861,12 +3189,7 @@ var ProviderHealthCheck = class {
2861
3189
  max_tokens: 10,
2862
3190
  messages: [{ role: "user", content: "ping" }]
2863
3191
  });
2864
- return {
2865
- healthy: true,
2866
- provider: "anthropic",
2867
- capabilities: { model: config.model },
2868
- timestamp
2869
- };
3192
+ return { healthy: true, provider: "anthropic", capabilities: { model: config.model }, timestamp };
2870
3193
  } catch (error) {
2871
3194
  return {
2872
3195
  healthy: false,
@@ -2880,20 +3203,14 @@ var ProviderHealthCheck = class {
2880
3203
  const baseUrl = (config.baseUrl || "http://localhost:11434").replace(/\/$/, "");
2881
3204
  try {
2882
3205
  const response = await fetch(`${baseUrl}/api/tags`);
2883
- if (!response.ok) {
2884
- throw new Error(`Health check returned ${response.status}`);
2885
- }
3206
+ if (!response.ok) throw new Error(`Health check returned ${response.status}`);
2886
3207
  const data = await response.json();
2887
3208
  const models = data.models || [];
2888
3209
  const hasModel = models.some((m) => m.name === config.model);
2889
3210
  return {
2890
3211
  healthy: true,
2891
3212
  provider: "ollama",
2892
- capabilities: {
2893
- model: config.model,
2894
- available: hasModel,
2895
- totalModels: models.length
2896
- },
3213
+ capabilities: { model: config.model, available: hasModel, totalModels: models.length },
2897
3214
  timestamp
2898
3215
  };
2899
3216
  } catch (error) {
@@ -2910,18 +3227,11 @@ var ProviderHealthCheck = class {
2910
3227
  const baseUrlRaw = config.baseUrl || ((_a = config.options) == null ? void 0 : _a.baseUrl);
2911
3228
  const baseUrl = (typeof baseUrlRaw === "string" ? baseUrlRaw : "").replace(/\/$/, "");
2912
3229
  if (!baseUrl) {
2913
- return {
2914
- healthy: false,
2915
- provider: config.provider,
2916
- error: "baseUrl is required",
2917
- timestamp
2918
- };
3230
+ return { healthy: false, provider: config.provider, error: "baseUrl is required", timestamp };
2919
3231
  }
2920
3232
  try {
2921
3233
  const headers = (_b = config.options) == null ? void 0 : _b.headers;
2922
- const response = await fetch(`${baseUrl}/health`, {
2923
- headers: headers || void 0
2924
- });
3234
+ const response = await fetch(`${baseUrl}/health`, { headers: headers || void 0 });
2925
3235
  return {
2926
3236
  healthy: response.ok,
2927
3237
  provider: config.provider,
@@ -2938,7 +3248,7 @@ var ProviderHealthCheck = class {
2938
3248
  }
2939
3249
  }
2940
3250
  /**
2941
- * Runs comprehensive health checks on all configured providers.
3251
+ * Runs comprehensive health checks on all configured providers in parallel.
2942
3252
  */
2943
3253
  static async checkAll(vectorDbConfig, llmConfig, embeddingConfig) {
2944
3254
  const [vectorDb, llm, embedding] = await Promise.all([
@@ -3015,23 +3325,278 @@ var VectorPlugin = class {
3015
3325
  }
3016
3326
  };
3017
3327
 
3018
- // src/server.ts
3019
- init_BaseVectorProvider();
3020
- init_PineconeProvider();
3021
- init_PostgreSQLProvider();
3022
- init_MongoDBProvider();
3023
- init_MilvusProvider();
3024
- init_QdrantProvider();
3025
- init_ChromaDBProvider();
3026
- init_RedisProvider();
3027
- init_WeaviateProvider();
3028
- init_LLMFactory();
3029
- init_OpenAIProvider();
3030
- init_AnthropicProvider();
3031
- init_OllamaProvider();
3032
-
3033
- // src/handlers/index.ts
3034
- var import_server = require("next/server");
3328
+ // src/config/ConfigBuilder.ts
3329
+ var ConfigBuilder = class {
3330
+ constructor() {
3331
+ this.config = {
3332
+ projectId: "default-project",
3333
+ rag: {
3334
+ chunkSize: 1e3,
3335
+ chunkOverlap: 200,
3336
+ topK: 5
3337
+ }
3338
+ };
3339
+ }
3340
+ /**
3341
+ * Set the project/application ID for namespacing
3342
+ */
3343
+ projectId(id) {
3344
+ this.config.projectId = id;
3345
+ return this;
3346
+ }
3347
+ /**
3348
+ * Configure the vector database provider
3349
+ */
3350
+ vectorDb(provider, options) {
3351
+ var _a;
3352
+ if (provider === "auto") {
3353
+ this.config.vectorDb = this.autoDetectVectorDb();
3354
+ } else {
3355
+ this.config.vectorDb = {
3356
+ provider,
3357
+ indexName: (_a = options == null ? void 0 : options.indexName) != null ? _a : "default",
3358
+ options: __spreadValues({}, options)
3359
+ };
3360
+ }
3361
+ return this;
3362
+ }
3363
+ /**
3364
+ * Configure the LLM provider for chat
3365
+ */
3366
+ llm(provider, model, apiKey, options) {
3367
+ var _a, _b;
3368
+ if (provider === "auto") {
3369
+ this.config.llm = this.autoDetectLLM();
3370
+ } else {
3371
+ this.config.llm = {
3372
+ provider,
3373
+ model: model != null ? model : "default-model",
3374
+ apiKey,
3375
+ systemPrompt: options == null ? void 0 : options.systemPrompt,
3376
+ maxTokens: (_a = options == null ? void 0 : options.maxTokens) != null ? _a : 1024,
3377
+ temperature: (_b = options == null ? void 0 : options.temperature) != null ? _b : 0.7,
3378
+ baseUrl: options == null ? void 0 : options.baseUrl,
3379
+ options
3380
+ };
3381
+ }
3382
+ return this;
3383
+ }
3384
+ /**
3385
+ * Configure the embedding provider
3386
+ */
3387
+ embedding(provider, model, apiKey, options) {
3388
+ if (provider === "auto") {
3389
+ this.config.embedding = this.autoDetectEmbedding();
3390
+ } else {
3391
+ this.config.embedding = {
3392
+ provider,
3393
+ model: model != null ? model : "default-embedding",
3394
+ apiKey,
3395
+ baseUrl: options == null ? void 0 : options.baseUrl,
3396
+ options
3397
+ };
3398
+ }
3399
+ return this;
3400
+ }
3401
+ /**
3402
+ * Set RAG-specific parameters
3403
+ */
3404
+ rag(options) {
3405
+ var _a;
3406
+ this.config.rag = __spreadValues(__spreadValues({}, (_a = this.config.rag) != null ? _a : {}), options);
3407
+ return this;
3408
+ }
3409
+ /**
3410
+ * Set UI/UX parameters
3411
+ */
3412
+ ui(options) {
3413
+ this.config.ui = options;
3414
+ return this;
3415
+ }
3416
+ /**
3417
+ * Build and return the configuration
3418
+ */
3419
+ build() {
3420
+ const finalConfig = this.config;
3421
+ return finalConfig;
3422
+ }
3423
+ /**
3424
+ * Build and return as JSON for serialization
3425
+ */
3426
+ toJSON() {
3427
+ return JSON.stringify(this.build());
3428
+ }
3429
+ // ============================================================================
3430
+ // Private helper methods for auto-detection
3431
+ // ============================================================================
3432
+ autoDetectVectorDb() {
3433
+ if (process.env.PINECONE_API_KEY && process.env.PINECONE_INDEX) {
3434
+ return {
3435
+ provider: "pinecone",
3436
+ indexName: process.env.PINECONE_INDEX,
3437
+ options: { apiKey: process.env.PINECONE_API_KEY }
3438
+ };
3439
+ }
3440
+ if (process.env.QDRANT_URL) {
3441
+ return {
3442
+ provider: "qdrant",
3443
+ indexName: process.env.QDRANT_COLLECTION || "documents",
3444
+ options: {
3445
+ url: process.env.QDRANT_URL,
3446
+ apiKey: process.env.QDRANT_API_KEY
3447
+ }
3448
+ };
3449
+ }
3450
+ if (process.env.DATABASE_URL) {
3451
+ return {
3452
+ provider: "postgresql",
3453
+ indexName: process.env.PG_TABLE || "documents",
3454
+ options: {
3455
+ connectionString: process.env.DATABASE_URL
3456
+ }
3457
+ };
3458
+ }
3459
+ if (process.env.MONGODB_URI) {
3460
+ return {
3461
+ provider: "mongodb",
3462
+ indexName: process.env.MONGODB_COLLECTION || "documents",
3463
+ options: {
3464
+ uri: process.env.MONGODB_URI,
3465
+ database: process.env.MONGODB_DB || "ai_db",
3466
+ collection: process.env.MONGODB_COLLECTION || "documents"
3467
+ }
3468
+ };
3469
+ }
3470
+ if (process.env.REDIS_URL) {
3471
+ return {
3472
+ provider: "redis",
3473
+ indexName: process.env.REDIS_INDEX || "documents",
3474
+ options: {
3475
+ url: process.env.REDIS_URL
3476
+ }
3477
+ };
3478
+ }
3479
+ return {
3480
+ provider: "qdrant",
3481
+ indexName: "documents",
3482
+ options: {
3483
+ url: process.env.QDRANT_URL || "http://localhost:6333"
3484
+ }
3485
+ };
3486
+ }
3487
+ autoDetectLLM() {
3488
+ if (process.env.OPENAI_API_KEY) {
3489
+ return {
3490
+ provider: "openai",
3491
+ model: process.env.OPENAI_MODEL || "gpt-4o-mini",
3492
+ apiKey: process.env.OPENAI_API_KEY,
3493
+ maxTokens: parseInt(process.env.OPENAI_MAX_TOKENS || "1024"),
3494
+ temperature: parseFloat(process.env.OPENAI_TEMPERATURE || "0.7")
3495
+ };
3496
+ }
3497
+ if (process.env.ANTHROPIC_API_KEY) {
3498
+ return {
3499
+ provider: "anthropic",
3500
+ model: process.env.ANTHROPIC_MODEL || "claude-3-haiku-20240307",
3501
+ apiKey: process.env.ANTHROPIC_API_KEY,
3502
+ maxTokens: parseInt(process.env.ANTHROPIC_MAX_TOKENS || "1024"),
3503
+ temperature: parseFloat(process.env.ANTHROPIC_TEMPERATURE || "0.7")
3504
+ };
3505
+ }
3506
+ if (process.env.OLLAMA_BASE_URL) {
3507
+ return {
3508
+ provider: "ollama",
3509
+ model: process.env.OLLAMA_MODEL || "mistral",
3510
+ baseUrl: process.env.OLLAMA_BASE_URL,
3511
+ maxTokens: parseInt(process.env.OLLAMA_MAX_TOKENS || "1024"),
3512
+ temperature: parseFloat(process.env.OLLAMA_TEMPERATURE || "0.7")
3513
+ };
3514
+ }
3515
+ return {
3516
+ provider: "openai",
3517
+ model: "gpt-4o-mini",
3518
+ apiKey: process.env.OPENAI_API_KEY
3519
+ };
3520
+ }
3521
+ autoDetectEmbedding() {
3522
+ if (process.env.EMBEDDING_PROVIDER) {
3523
+ const provider = process.env.EMBEDDING_PROVIDER;
3524
+ return {
3525
+ provider,
3526
+ model: process.env.EMBEDDING_MODEL || "default",
3527
+ apiKey: process.env.EMBEDDING_API_KEY,
3528
+ baseUrl: process.env.EMBEDDING_BASE_URL
3529
+ };
3530
+ }
3531
+ return {
3532
+ provider: "openai",
3533
+ model: "text-embedding-3-small",
3534
+ apiKey: process.env.OPENAI_API_KEY
3535
+ };
3536
+ }
3537
+ };
3538
+ var PRESETS = {
3539
+ /**
3540
+ * OpenAI + Pinecone: Production-ready cloud setup
3541
+ */
3542
+ "openai-pinecone": {
3543
+ vectorDb: "pinecone",
3544
+ llm: "openai",
3545
+ embedding: "openai"
3546
+ },
3547
+ /**
3548
+ * Claude + Qdrant: Open-source vector DB + proprietary LLM
3549
+ */
3550
+ "claude-qdrant": {
3551
+ vectorDb: "qdrant",
3552
+ llm: "anthropic",
3553
+ embedding: "openai"
3554
+ },
3555
+ /**
3556
+ * Local development: Ollama + local Qdrant
3557
+ */
3558
+ "local-dev": {
3559
+ vectorDb: "qdrant",
3560
+ llm: "ollama",
3561
+ embedding: "ollama"
3562
+ },
3563
+ /**
3564
+ * Fully open-source: Ollama LLM + Qdrant vector DB + Ollama embeddings
3565
+ */
3566
+ "fully-open-source": {
3567
+ vectorDb: "qdrant",
3568
+ llm: "ollama",
3569
+ embedding: "ollama"
3570
+ },
3571
+ /**
3572
+ * PostgreSQL stack: pgvector + OpenAI
3573
+ */
3574
+ "postgres-openai": {
3575
+ vectorDb: "postgresql",
3576
+ llm: "openai",
3577
+ embedding: "openai"
3578
+ },
3579
+ /**
3580
+ * Enterprise MongoDB: MongoDB Atlas with OpenAI
3581
+ */
3582
+ "mongodb-openai": {
3583
+ vectorDb: "mongodb",
3584
+ llm: "openai",
3585
+ embedding: "openai"
3586
+ },
3587
+ /**
3588
+ * Redis stack for caching + search
3589
+ */
3590
+ "redis-openai": {
3591
+ vectorDb: "redis",
3592
+ llm: "openai",
3593
+ embedding: "openai"
3594
+ }
3595
+ };
3596
+ function createFromPreset(presetName) {
3597
+ const preset = PRESETS[presetName];
3598
+ return new ConfigBuilder().vectorDb(preset.vectorDb, { apiKey: process.env[`${preset.vectorDb.toUpperCase()}_API_KEY`] }).llm(preset.llm, void 0, process.env[`${preset.llm.toUpperCase()}_API_KEY`]).embedding(preset.embedding, void 0, process.env[`${preset.embedding.toUpperCase()}_API_KEY`]);
3599
+ }
3035
3600
 
3036
3601
  // src/utils/DocumentParser.ts
3037
3602
  var DocumentParser = class {
@@ -3092,7 +3657,20 @@ var DocumentParser = class {
3092
3657
  }
3093
3658
  };
3094
3659
 
3660
+ // src/server.ts
3661
+ init_BaseVectorProvider();
3662
+ init_PineconeProvider();
3663
+ init_PostgreSQLProvider();
3664
+ init_MongoDBProvider();
3665
+ init_MilvusProvider();
3666
+ init_QdrantProvider();
3667
+ init_ChromaDBProvider();
3668
+ init_RedisProvider();
3669
+ init_WeaviateProvider();
3670
+ init_UniversalVectorProvider();
3671
+
3095
3672
  // src/handlers/index.ts
3673
+ var import_server = require("next/server");
3096
3674
  function createChatHandler(config) {
3097
3675
  const plugin = new VectorPlugin(config);
3098
3676
  return async function POST(req) {
@@ -3181,23 +3759,36 @@ function createUploadHandler(config) {
3181
3759
  0 && (module.exports = {
3182
3760
  AnthropicProvider,
3183
3761
  BaseVectorProvider,
3762
+ BatchProcessor,
3184
3763
  ChromaDBProvider,
3764
+ ConfigBuilder,
3185
3765
  ConfigResolver,
3766
+ ConfigValidator,
3186
3767
  DocumentChunker,
3768
+ DocumentParser,
3769
+ EmbeddingStrategy,
3770
+ EmbeddingStrategyResolver,
3187
3771
  LLMFactory,
3772
+ LLM_PROFILES,
3188
3773
  MilvusProvider,
3189
3774
  MongoDBProvider,
3190
3775
  OllamaProvider,
3191
3776
  OpenAIProvider,
3777
+ PRESETS,
3192
3778
  PineconeProvider,
3193
3779
  Pipeline,
3194
3780
  PostgreSQLProvider,
3781
+ ProviderHealthCheck,
3195
3782
  ProviderRegistry,
3196
3783
  QdrantProvider,
3197
3784
  RedisProvider,
3785
+ UniversalLLMAdapter,
3786
+ UniversalVectorProvider,
3787
+ VECTOR_PROFILES,
3198
3788
  VectorPlugin,
3199
3789
  WeaviateProvider,
3200
3790
  createChatHandler,
3791
+ createFromPreset,
3201
3792
  createHealthHandler,
3202
3793
  createIngestHandler,
3203
3794
  createUploadHandler,