@retrivora-ai/rag-engine 0.1.2 → 0.1.4

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 (73) hide show
  1. package/dist/ChromaDBProvider-QNI7UCX4.mjs +8 -0
  2. package/dist/DocumentChunker-BQ5kQD7B.d.ts +155 -0
  3. package/dist/DocumentChunker-D9-fObJp.d.mts +155 -0
  4. package/dist/LLMFactory-XC55FTD2.mjs +7 -0
  5. package/dist/MilvusProvider-OO6QGZDZ.mjs +8 -0
  6. package/dist/MongoDBProvider-WWVJG3WT.mjs +8 -0
  7. package/dist/PineconeProvider-NJ675H7U.mjs +8 -0
  8. package/dist/{RAGPipeline-BmkIv1HD.d.mts → Pipeline-Bo6CUCox.d.mts} +76 -159
  9. package/dist/{RAGPipeline-BmkIv1HD.d.ts → Pipeline-Bo6CUCox.d.ts} +76 -159
  10. package/dist/PostgreSQLProvider-ISNMD3BE.mjs +8 -0
  11. package/dist/QdrantProvider-LJWOIGES.mjs +8 -0
  12. package/dist/RedisProvider-ASONNYBI.mjs +8 -0
  13. package/dist/WeaviateProvider-PSDCUGC7.mjs +8 -0
  14. package/dist/chunk-6FODXNUF.mjs +91 -0
  15. package/dist/chunk-7NXI6ZWX.mjs +89 -0
  16. package/dist/chunk-AALIF3AL.mjs +91 -0
  17. package/dist/chunk-AIAB2IEE.mjs +394 -0
  18. package/dist/chunk-FGGSVVSY.mjs +162 -0
  19. package/dist/chunk-GD3QJFNN.mjs +424 -0
  20. package/dist/chunk-HUGLYKD6.mjs +84 -0
  21. package/dist/chunk-I4E63NIC.mjs +24 -0
  22. package/dist/chunk-QEYVWVT5.mjs +102 -0
  23. package/dist/chunk-S5DRHETN.mjs +110 -0
  24. package/dist/chunk-V75V7BT2.mjs +117 -0
  25. package/dist/chunk-VOIWNO5O.mjs +11 -0
  26. package/dist/chunk-VPNRDXIA.mjs +74 -0
  27. package/dist/handlers/index.d.mts +9 -33
  28. package/dist/handlers/index.d.ts +9 -33
  29. package/dist/handlers/index.js +1477 -959
  30. package/dist/handlers/index.mjs +4 -2
  31. package/dist/index.d.mts +3 -3
  32. package/dist/index.d.ts +3 -3
  33. package/dist/index.js +1646 -19
  34. package/dist/index.mjs +14 -2
  35. package/dist/server.d.mts +93 -56
  36. package/dist/server.d.ts +93 -56
  37. package/dist/server.js +1531 -1096
  38. package/dist/server.mjs +56 -131
  39. package/package.json +1 -1
  40. package/src/app/page.tsx +1 -1
  41. package/src/components/MessageBubble.tsx +1 -1
  42. package/src/components/SourceCard.tsx +1 -1
  43. package/src/config/RagConfig.ts +1 -1
  44. package/src/config/serverConfig.ts +2 -2
  45. package/src/core/ConfigResolver.ts +69 -0
  46. package/src/core/Pipeline.ts +109 -0
  47. package/src/core/ProviderRegistry.ts +71 -0
  48. package/src/core/VectorPlugin.ts +51 -0
  49. package/src/handlers/index.ts +21 -100
  50. package/src/hooks/useRagChat.ts +1 -1
  51. package/src/index.ts +8 -6
  52. package/src/providers/vectordb/BaseVectorProvider.ts +61 -0
  53. package/src/providers/vectordb/ChromaDBProvider.ts +94 -0
  54. package/src/providers/vectordb/MilvusProvider.ts +100 -0
  55. package/src/providers/vectordb/MongoDBProvider.ts +118 -0
  56. package/src/{vectordb/adapters/PineconeAdapter.ts → providers/vectordb/PineconeProvider.ts} +21 -56
  57. package/src/{vectordb/adapters/PgVectorAdapter.ts → providers/vectordb/PostgreSQLProvider.ts} +23 -58
  58. package/src/providers/vectordb/QdrantProvider.ts +95 -0
  59. package/src/providers/vectordb/RedisProvider.ts +84 -0
  60. package/src/providers/vectordb/WeaviateProvider.ts +124 -0
  61. package/src/server.ts +16 -8
  62. package/src/test-refactor.ts +59 -0
  63. package/src/types/index.ts +13 -0
  64. package/src/utils/templateUtils.ts +6 -6
  65. package/dist/DocumentChunker-BUrIrcPk.d.mts +0 -43
  66. package/dist/DocumentChunker-BUrIrcPk.d.ts +0 -43
  67. package/dist/chunk-W57OWMJK.mjs +0 -1256
  68. package/dist/chunk-ZPXLQR5Q.mjs +0 -67
  69. package/src/rag/RAGPipeline.ts +0 -196
  70. package/src/vectordb/IVectorDB.ts +0 -75
  71. package/src/vectordb/VectorDBFactory.ts +0 -41
  72. package/src/vectordb/adapters/MongoDbAdapter.ts +0 -175
  73. package/src/vectordb/adapters/UniversalVectorDBAdapter.ts +0 -177
package/dist/server.js CHANGED
@@ -22,6 +22,9 @@ var __spreadValues = (a, b) => {
22
22
  return a;
23
23
  };
24
24
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __esm = (fn, res) => function __init() {
26
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
27
+ };
25
28
  var __export = (target, all) => {
26
29
  for (var name in all)
27
30
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -44,237 +47,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
44
47
  ));
45
48
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
46
49
 
47
- // src/server.ts
48
- var server_exports = {};
49
- __export(server_exports, {
50
- AnthropicProvider: () => AnthropicProvider,
51
- DocumentChunker: () => DocumentChunker,
52
- LLMFactory: () => LLMFactory,
53
- MongoDbAdapter: () => MongoDbAdapter,
54
- OllamaProvider: () => OllamaProvider,
55
- OpenAIProvider: () => OpenAIProvider,
56
- PgVectorAdapter: () => PgVectorAdapter,
57
- PineconeAdapter: () => PineconeAdapter,
58
- RAGPipeline: () => RAGPipeline,
59
- VectorDBFactory: () => VectorDBFactory,
60
- createChatHandler: () => createChatHandler,
61
- createHealthHandler: () => createHealthHandler,
62
- createIngestHandler: () => createIngestHandler,
63
- createUploadHandler: () => createUploadHandler,
64
- getRagConfig: () => getRagConfig
65
- });
66
- module.exports = __toCommonJS(server_exports);
67
-
68
- // src/vectordb/adapters/PineconeAdapter.ts
69
- var import_pinecone = require("@pinecone-database/pinecone");
70
- var PineconeAdapter = class {
71
- constructor(config) {
72
- this.indexName = config.indexName;
73
- const opts = config.options;
74
- if (!opts.apiKey) throw new Error("[PineconeAdapter] options.apiKey is required");
75
- this.apiKey = opts.apiKey;
76
- }
77
- async initialize() {
78
- var _a, _b;
79
- this.client = new import_pinecone.Pinecone({ apiKey: this.apiKey });
80
- const indexes = await this.client.listIndexes();
81
- const names = (_b = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _b : [];
82
- if (!names.includes(this.indexName)) {
83
- throw new Error(
84
- `[PineconeAdapter] Index "${this.indexName}" not found. Available: ${names.join(", ")}`
85
- );
86
- }
87
- }
88
- index(namespace) {
89
- const idx = this.client.index(this.indexName);
90
- return namespace ? idx.namespace(namespace) : idx.namespace("");
91
- }
92
- async upsert(doc, namespace) {
93
- var _a;
94
- await this.index(namespace).upsert({
95
- records: [
96
- {
97
- id: doc.id,
98
- values: doc.vector,
99
- metadata: __spreadValues({
100
- content: doc.content
101
- }, (_a = doc.metadata) != null ? _a : {})
102
- }
103
- ]
104
- });
105
- }
106
- async batchUpsert(docs, namespace) {
107
- const BATCH = 100;
108
- for (let i = 0; i < docs.length; i += BATCH) {
109
- const records = docs.slice(i, i + BATCH).map((d) => {
110
- var _a;
111
- return {
112
- id: d.id,
113
- values: d.vector,
114
- metadata: __spreadValues({
115
- content: d.content
116
- }, (_a = d.metadata) != null ? _a : {})
117
- };
118
- });
119
- await this.index(namespace).upsert({ records });
120
- }
121
- }
122
- async query(vector, topK, namespace, filter) {
123
- var _a;
124
- const result = await this.index(namespace).query(__spreadValues({
125
- vector,
126
- topK,
127
- includeMetadata: true
128
- }, filter ? { filter } : {}));
129
- return ((_a = result.matches) != null ? _a : []).map((m) => {
130
- var _a2;
131
- const metadata = m.metadata;
132
- const content = (metadata == null ? void 0 : metadata.content) || (metadata == null ? void 0 : metadata.text) || (metadata == null ? void 0 : metadata.body) || (metadata == null ? void 0 : metadata.description) || "";
133
- return {
134
- id: m.id,
135
- score: (_a2 = m.score) != null ? _a2 : 0,
136
- content,
137
- metadata
138
- };
139
- });
140
- }
141
- async delete(id, namespace) {
142
- await this.index(namespace).deleteOne({ id });
143
- }
144
- async deleteNamespace(namespace) {
145
- await this.client.index(this.indexName).namespace(namespace).deleteAll();
146
- }
147
- async ping() {
148
- try {
149
- await this.client.listIndexes();
150
- return true;
151
- } catch (err) {
152
- console.error("[PineconeAdapter] Ping failed:", err);
153
- return false;
154
- }
155
- }
156
- async disconnect() {
157
- }
158
- };
159
-
160
- // src/vectordb/adapters/PgVectorAdapter.ts
161
- var import_pg = require("pg");
162
- var PgVectorAdapter = class {
163
- constructor(config) {
164
- var _a;
165
- this.tableName = config.indexName.replace(/[^a-z0-9_]/gi, "_");
166
- const opts = config.options;
167
- if (!opts.connectionString) {
168
- throw new Error("[PgVectorAdapter] options.connectionString is required");
169
- }
170
- this.connectionString = opts.connectionString;
171
- this.dimensions = (_a = opts.dimensions) != null ? _a : 1536;
172
- }
173
- async initialize() {
174
- this.pool = new import_pg.Pool({ connectionString: this.connectionString });
175
- const client = await this.pool.connect();
176
- try {
177
- await client.query("CREATE EXTENSION IF NOT EXISTS vector");
178
- await client.query(`
179
- CREATE TABLE IF NOT EXISTS ${this.tableName} (
180
- id TEXT PRIMARY KEY,
181
- namespace TEXT NOT NULL DEFAULT '',
182
- content TEXT NOT NULL,
183
- metadata JSONB,
184
- embedding VECTOR(${this.dimensions})
185
- )
186
- `);
187
- await client.query(`
188
- CREATE INDEX IF NOT EXISTS ${this.tableName}_embedding_idx
189
- ON ${this.tableName}
190
- USING hnsw (embedding vector_cosine_ops)
191
- `);
192
- } finally {
193
- client.release();
194
- }
195
- }
196
- async upsert(doc, namespace = "") {
197
- var _a;
198
- const vectorLiteral = `[${doc.vector.join(",")}]`;
199
- await this.pool.query(
200
- `INSERT INTO ${this.tableName} (id, namespace, content, metadata, embedding)
201
- VALUES ($1, $2, $3, $4, $5::vector)
202
- ON CONFLICT (id) DO UPDATE
203
- SET namespace = EXCLUDED.namespace,
204
- content = EXCLUDED.content,
205
- metadata = EXCLUDED.metadata,
206
- embedding = EXCLUDED.embedding`,
207
- [doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), vectorLiteral]
208
- );
209
- }
210
- async batchUpsert(docs, namespace = "") {
211
- for (const doc of docs) {
212
- await this.upsert(doc, namespace);
213
- }
214
- }
215
- async query(vector, topK, namespace, filter) {
216
- const vectorLiteral = `[${vector.join(",")}]`;
217
- let whereClause = namespace ? `WHERE namespace = $3` : "";
218
- const params = [vectorLiteral, topK];
219
- if (namespace) params.push(namespace);
220
- if (filter && Object.keys(filter).length > 0) {
221
- const filterConditions = Object.entries(filter).map(([key, val]) => {
222
- const paramIdx = params.length + 1;
223
- params.push(JSON.stringify(val));
224
- return `metadata->>'${key}' = $${paramIdx}`;
225
- }).join(" AND ");
226
- whereClause = whereClause ? `${whereClause} AND ${filterConditions}` : `WHERE ${filterConditions}`;
227
- }
228
- const result = await this.pool.query(
229
- `SELECT id,
230
- content,
231
- metadata,
232
- 1 - (embedding <=> $1::vector) AS score
233
- FROM ${this.tableName}
234
- ${whereClause}
235
- ORDER BY embedding <=> $1::vector
236
- LIMIT $2`,
237
- params
238
- );
239
- return result.rows.map((row) => ({
240
- id: String(row.id),
241
- score: parseFloat(String(row.score)),
242
- content: String(row.content),
243
- metadata: row.metadata
244
- }));
245
- }
246
- async delete(id, namespace) {
247
- const where = namespace ? "WHERE id = $1 AND namespace = $2" : "WHERE id = $1";
248
- const params = namespace ? [id, namespace] : [id];
249
- await this.pool.query(`DELETE FROM ${this.tableName} ${where}`, params);
250
- }
251
- async deleteNamespace(namespace) {
252
- await this.pool.query(
253
- `DELETE FROM ${this.tableName} WHERE namespace = $1`,
254
- [namespace]
255
- );
256
- }
257
- async ping() {
258
- try {
259
- await this.pool.query("SELECT 1");
260
- return true;
261
- } catch (err) {
262
- console.error("[PgVectorAdapter] Ping failed:", err);
263
- return false;
264
- }
265
- }
266
- async disconnect() {
267
- try {
268
- await this.pool.end();
269
- } catch (err) {
270
- console.error("[PgVectorAdapter] Failed to disconnect:", err);
271
- }
272
- }
273
- };
274
-
275
- // src/vectordb/adapters/UniversalVectorDBAdapter.ts
276
- var import_axios = __toESM(require("axios"));
277
-
278
50
  // src/utils/templateUtils.ts
279
51
  function isRecord(value) {
280
52
  return typeof value === "object" && value !== null;
@@ -302,676 +74,1412 @@ function buildPayload(template, vars) {
302
74
  Raw payload: ${raw}`);
303
75
  }
304
76
  }
305
-
306
- // src/config/UniversalProfiles.ts
307
- var OPENAI_BASE = {
308
- chatPath: "/chat/completions",
309
- embedPath: "/embeddings",
310
- responseExtractPath: "choices[0].message.content",
311
- embedExtractPath: "data[0].embedding",
312
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}}}'
313
- };
314
- var LLM_PROFILES = {
315
- "openai-compatible": OPENAI_BASE,
316
- "litellm": __spreadProps(__spreadValues({}, OPENAI_BASE), {
317
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
318
- }),
319
- "anthropic-claude": {
320
- chatPath: "/v1/messages",
321
- responseExtractPath: "content[0].text",
322
- headers: { "anthropic-version": "2023-06-01" },
323
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}}}'
324
- },
325
- "google-gemini": {
326
- chatPath: "/v1beta/models/{{model}}:generateContent",
327
- responseExtractPath: "candidates[0].content.parts[0].text",
328
- chatPayloadTemplate: '{"contents":[{"parts":[{"text":"{{messages}}"}]}]}'
329
- },
330
- "github-copilot": __spreadProps(__spreadValues({}, OPENAI_BASE), {
331
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"temperature":{{temperature}}}'
332
- }),
333
- "ollama-standard": {
334
- chatPath: "/api/chat",
335
- embedPath: "/api/embeddings",
336
- responseExtractPath: "message.content",
337
- embedExtractPath: "embedding",
338
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"stream":false}',
339
- embedPayloadTemplate: '{"model":"{{model}}","prompt":"{{input}}"}'
340
- }
341
- };
342
- var VECTOR_PROFILES = {
343
- "pinecone-rest": {
344
- queryPath: "/query",
345
- upsertPath: "/vectors/upsert",
346
- responseExtractPath: "matches",
347
- idPath: "id",
348
- scorePath: "score",
349
- contentPath: "metadata.content",
350
- metadataPath: "metadata",
351
- queryPayloadTemplate: '{"vector":{{vector}},"topK":{{topK}},"includeMetadata":true,"namespace":"{{namespace}}"}'
352
- },
353
- "mongodb-atlas": {
354
- queryPath: "/action/aggregate",
355
- responseExtractPath: "documents",
356
- idPath: "_id",
357
- scorePath: "score",
358
- contentPath: "content",
359
- metadataPath: "metadata",
360
- 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"}}}]}'
361
- },
362
- "chromadb": {
363
- queryPath: "/api/v1/collections/{{index}}/query",
364
- upsertPath: "/api/v1/collections/{{index}}/add",
365
- responseExtractPath: "matches",
366
- idPath: "id",
367
- scorePath: "distance",
368
- contentPath: "document",
369
- metadataPath: "metadata"
370
- },
371
- "qdrant": {
372
- queryPath: "/collections/{{index}}/points/search",
373
- upsertPath: "/collections/{{index}}/points",
374
- responseExtractPath: "result",
375
- idPath: "id",
376
- scorePath: "score",
377
- contentPath: "payload.content",
378
- metadataPath: "payload"
379
- }
380
- };
381
-
382
- // src/vectordb/adapters/UniversalVectorDBAdapter.ts
383
- var UniversalVectorDBAdapter = class {
384
- constructor(config) {
385
- var _a, _b, _c;
386
- this.indexName = config.indexName;
387
- const options = (_a = config.options) != null ? _a : {};
388
- let profile = {};
389
- if (typeof options.profile === "string") {
390
- profile = VECTOR_PROFILES[options.profile] || {};
391
- } else if (typeof options.profile === "object" && options.profile !== null) {
392
- profile = options.profile;
393
- }
394
- this.opts = __spreadValues(__spreadValues({}, profile), (_b = config.options) != null ? _b : {});
395
- if (!this.opts.baseUrl) {
396
- throw new Error("[UniversalVectorDBAdapter] options.baseUrl is required");
397
- }
398
- this.http = import_axios.default.create({
399
- baseURL: this.opts.baseUrl,
400
- headers: __spreadValues({
401
- "Content-Type": "application/json"
402
- }, this.opts.headers || {}),
403
- timeout: (_c = this.opts.timeout) != null ? _c : 3e4
404
- });
405
- }
406
- async initialize() {
407
- if (this.opts.pingPath) {
408
- const ok = await this.ping();
409
- if (!ok) {
410
- throw new Error(`[UniversalVectorDBAdapter] Could not reach health endpoint: ${this.opts.pingPath}`);
411
- }
412
- }
413
- }
414
- async upsert(doc, namespace) {
415
- var _a, _b;
416
- const path = (_a = this.opts.upsertPath) != null ? _a : "/upsert";
417
- if (this.opts.upsertPayloadTemplate) {
418
- const payload = buildPayload(this.opts.upsertPayloadTemplate, {
419
- id: doc.id,
420
- vector: doc.vector,
421
- content: doc.content,
422
- metadata: (_b = doc.metadata) != null ? _b : {},
423
- namespace: namespace != null ? namespace : "",
424
- index: this.indexName
425
- });
426
- await this.http.post(path, payload);
427
- } else {
428
- await this.http.post(path, __spreadValues({
429
- index: this.indexName,
430
- namespace
431
- }, doc));
432
- }
433
- }
434
- async batchUpsert(docs, namespace) {
435
- var _a;
436
- const path = (_a = this.opts.upsertPath) != null ? _a : "/upsert";
437
- if (this.opts.batchUpsertPayloadTemplate) {
438
- const payload = buildPayload(this.opts.batchUpsertPayloadTemplate, {
439
- vectors: docs,
440
- namespace: namespace != null ? namespace : "",
441
- index: this.indexName
442
- });
443
- await this.http.post(path, payload);
444
- } else {
445
- await Promise.all(docs.map((doc) => this.upsert(doc, namespace)));
77
+ function mergeDefined(base, override) {
78
+ const merged = __spreadValues({}, base || {});
79
+ if (!override) {
80
+ return merged;
81
+ }
82
+ for (const [key, value] of Object.entries(override)) {
83
+ if (value !== void 0 && value !== null && value !== "") {
84
+ merged[key] = value;
446
85
  }
447
86
  }
448
- async query(vector, topK, namespace, filter) {
449
- var _a, _b, _c, _d, _e, _f;
450
- const path = (_a = this.opts.queryPath) != null ? _a : "/query";
451
- let payload;
452
- if (this.opts.queryPayloadTemplate) {
453
- payload = buildPayload(this.opts.queryPayloadTemplate, {
454
- vector,
455
- topK,
456
- namespace: namespace != null ? namespace : "",
457
- index: this.indexName,
458
- filter: filter != null ? filter : {}
459
- });
460
- } else {
461
- payload = { index: this.indexName, namespace, vector, topK, filter };
462
- }
463
- const { data } = await this.http.post(path, payload);
464
- const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "matches";
465
- const matchesRaw = resolvePath(data, extractPath);
466
- if (!Array.isArray(matchesRaw)) {
467
- throw new Error(`[UniversalVectorDBAdapter] Expected an array at responseExtractPath '${extractPath}', but got ${typeof matchesRaw}`);
468
- }
469
- const idPath = (_c = this.opts.idPath) != null ? _c : "id";
470
- const scorePath = (_d = this.opts.scorePath) != null ? _d : "score";
471
- const contentPath = (_e = this.opts.contentPath) != null ? _e : "content";
472
- const metadataPath = (_f = this.opts.metadataPath) != null ? _f : "metadata";
473
- return matchesRaw.map((match) => ({
474
- id: String(resolvePath(match, idPath) || ""),
475
- score: Number(resolvePath(match, scorePath) || 0),
476
- content: String(resolvePath(match, contentPath) || ""),
477
- metadata: resolvePath(match, metadataPath) || {}
478
- }));
479
- }
480
- async delete(id, namespace) {
481
- var _a;
482
- const path = (_a = this.opts.deletePath) != null ? _a : "/delete";
483
- await this.http.post(path, { index: this.indexName, namespace, id });
484
- }
485
- async deleteNamespace(namespace) {
486
- var _a;
487
- const path = (_a = this.opts.deleteNamespacePath) != null ? _a : "/delete-namespace";
488
- await this.http.post(path, { index: this.indexName, namespace });
87
+ return merged;
88
+ }
89
+ var init_templateUtils = __esm({
90
+ "src/utils/templateUtils.ts"() {
91
+ "use strict";
489
92
  }
490
- async ping() {
491
- try {
492
- if (this.opts.pingPath) {
493
- await this.http.get(this.opts.pingPath);
93
+ });
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;
494
107
  }
495
- return true;
496
- } catch (err) {
497
- console.error("[UniversalVectorDBAdapter] Ping failed:", err);
498
- return false;
499
- }
500
- }
501
- async disconnect() {
502
- }
503
- };
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.
504
111
 
505
- // src/vectordb/adapters/MongoDbAdapter.ts
506
- var import_mongodb = require("mongodb");
507
- var MongoDbAdapter = class {
508
- constructor(options) {
509
- this.uri = options.uri;
510
- this.dbName = options.database;
511
- this.collectionName = options.collection;
512
- this.indexName = options.indexName || "vector_index";
513
- this.embeddingKey = options.embeddingKey || "embedding";
514
- this.contentKey = options.contentKey || "content";
515
- this.metadataKey = options.metadataKey || "metadata";
516
- if (!this.uri || !this.dbName || !this.collectionName) {
517
- throw new Error("MongoDbAdapter requires uri, database, and collection options.");
518
- }
519
- this.client = new import_mongodb.MongoClient(this.uri);
520
- }
521
- async initialize() {
522
- await this.client.connect();
523
- this.db = this.client.db(this.dbName);
524
- this.collection = this.db.collection(this.collectionName);
525
- }
526
- async upsert(doc, namespace) {
527
- if (!this.collection) await this.initialize();
528
- const document = __spreadValues({
529
- _id: doc.id,
530
- [this.embeddingKey]: doc.vector,
531
- [this.contentKey]: doc.content,
532
- [this.metadataKey]: doc.metadata || {}
533
- }, namespace ? { namespace } : {});
534
- await this.collection.updateOne(
535
- { _id: doc.id },
536
- { $set: document },
537
- { upsert: true }
538
- );
539
- }
540
- async batchUpsert(docs, namespace) {
541
- if (!this.collection) await this.initialize();
542
- const operations = docs.map((doc) => ({
543
- updateOne: {
544
- filter: { _id: doc.id },
545
- update: {
546
- $set: __spreadValues({
547
- _id: doc.id,
548
- [this.embeddingKey]: doc.vector,
549
- [this.contentKey]: doc.content,
550
- [this.metadataKey]: doc.metadata || {}
551
- }, namespace ? { namespace } : {})
552
- },
553
- upsert: true
554
- }
555
- }));
556
- await this.collection.bulkWrite(operations);
557
- }
558
- async query(vector, topK, namespace, filter) {
559
- if (!this.collection) await this.initialize();
560
- const pipeline = [
561
- {
562
- $vectorSearch: __spreadValues({
563
- index: this.indexName,
564
- path: this.embeddingKey,
565
- queryVector: vector,
566
- numCandidates: Math.max(topK * 10, 100),
567
- limit: topK
568
- }, filter || namespace ? {
569
- filter: __spreadValues(__spreadValues({}, filter || {}), namespace ? { namespace } : {})
570
- } : {})
571
- },
572
- {
573
- $project: {
574
- score: { $meta: "vectorSearchScore" },
575
- content: `$${this.contentKey}`,
576
- metadata: `$${this.metadataKey}`
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;
577
156
  }
578
157
  }
579
- ];
580
- const results = await this.collection.aggregate(pipeline).toArray();
581
- return results.map((res) => ({
582
- id: res._id.toString(),
583
- score: res.score,
584
- content: res.content,
585
- metadata: res.metadata
586
- }));
587
- }
588
- async delete(id, namespace) {
589
- if (!this.collection) await this.initialize();
590
- const query = __spreadValues({ _id: id }, namespace ? { namespace } : {});
591
- await this.collection.deleteOne(query);
592
- }
593
- async deleteNamespace(namespace) {
594
- if (!this.collection) await this.initialize();
595
- await this.collection.deleteMany({ namespace });
596
- }
597
- async ping() {
598
- try {
599
- if (!this.collection) await this.initialize();
600
- await this.db.command({ ping: 1 });
601
- return true;
602
- } catch (err) {
603
- console.error("[MongoDbAdapter] Ping failed:", err);
604
- return false;
605
- }
606
- }
607
- async disconnect() {
608
- try {
609
- await this.client.close();
610
- this.db = void 0;
611
- this.collection = void 0;
612
- } catch (err) {
613
- console.error("[MongoDbAdapter] Failed to disconnect:", err);
614
- }
158
+ };
615
159
  }
616
- };
160
+ });
617
161
 
618
- // src/vectordb/VectorDBFactory.ts
619
- var VectorDBFactory = class {
620
- static create(config) {
621
- var _a;
622
- switch (config.provider) {
623
- case "pinecone":
624
- return new PineconeAdapter(config);
625
- case "pgvector":
626
- return new PgVectorAdapter(config);
627
- case "mongodb":
628
- return new MongoDbAdapter(config.options);
629
- case "rest":
630
- case "universal_rest":
631
- case "custom":
632
- return new UniversalVectorDBAdapter(config);
633
- default:
634
- if ((_a = config.options) == null ? void 0 : _a.baseUrl) {
635
- return new UniversalVectorDBAdapter(config);
636
- }
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;
637
206
  throw new Error(
638
- `[VectorDBFactory] Unknown provider "${config.provider}". Supported: pinecone | pgvector | mongodb | rest`
207
+ '[AnthropicProvider] Anthropic does not provide an embedding API. Set embedding.provider to "openai" or "ollama" in your RagConfig.'
639
208
  );
640
- }
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
+ };
641
227
  }
642
- };
228
+ });
643
229
 
644
- // src/llm/providers/OpenAIProvider.ts
645
- var import_openai = __toESM(require("openai"));
646
- var OpenAIProvider = class {
647
- constructor(llmConfig, embeddingConfig) {
648
- if (!llmConfig.apiKey) throw new Error("[OpenAIProvider] llmConfig.apiKey is required");
649
- this.client = new import_openai.default({ apiKey: llmConfig.apiKey });
650
- this.llmConfig = llmConfig;
651
- this.embeddingConfig = embeddingConfig;
652
- }
653
- async chat(messages, context, options) {
654
- var _a, _b, _c, _d, _e, _f, _g, _h;
655
- const systemContent = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
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.
656
247
 
657
248
  Context:
658
249
  ${context}`;
659
- const systemMessage = {
660
- role: "system",
661
- content: systemContent.includes("{{context}}") ? systemContent.replace("{{context}}", context) : `${systemContent}
250
+ const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
662
251
 
663
252
  Context:
664
- ${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
+ }
665
295
  };
666
- const formattedMessages = [
667
- systemMessage,
668
- ...messages.map((m) => ({
669
- role: m.role,
670
- content: m.content
671
- }))
672
- ];
673
- const completion = await this.client.chat.completions.create({
674
- model: this.llmConfig.model,
675
- messages: formattedMessages,
676
- max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
677
- temperature: (_e = (_d = options == null ? void 0 : options.temperature) != null ? _d : this.llmConfig.temperature) != null ? _e : 0.7,
678
- stop: options == null ? void 0 : options.stop
679
- });
680
- return (_h = (_g = (_f = completion.choices[0]) == null ? void 0 : _f.message) == null ? void 0 : _g.content) != null ? _h : "";
681
296
  }
682
- async embed(text, options) {
683
- const results = await this.batchEmbed([text], options);
684
- return results[0];
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
+ };
685
454
  }
686
- async batchEmbed(texts, options) {
687
- var _a, _b, _c, _d, _e;
688
- 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";
689
- const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
690
- const client = apiKey !== this.llmConfig.apiKey ? new import_openai.default({ apiKey }) : this.client;
691
- const response = await client.embeddings.create({ model, input: texts });
692
- return response.data.map((d) => d.embedding);
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
+ };
693
508
  }
694
- async ping() {
695
- try {
696
- await this.client.models.list();
697
- return true;
698
- } catch (err) {
699
- console.error("[OpenAIProvider] Ping failed:", err);
700
- return false;
509
+ });
510
+
511
+ // src/providers/vectordb/BaseVectorProvider.ts
512
+ var BaseVectorProvider;
513
+ var init_BaseVectorProvider = __esm({
514
+ "src/providers/vectordb/BaseVectorProvider.ts"() {
515
+ "use strict";
516
+ BaseVectorProvider = class {
517
+ constructor(config) {
518
+ this.config = config;
519
+ this.indexName = config.indexName || "default";
520
+ }
521
+ };
522
+ }
523
+ });
524
+
525
+ // src/providers/vectordb/PineconeProvider.ts
526
+ var PineconeProvider_exports = {};
527
+ __export(PineconeProvider_exports, {
528
+ PineconeProvider: () => PineconeProvider
529
+ });
530
+ var import_pinecone, PineconeProvider;
531
+ var init_PineconeProvider = __esm({
532
+ "src/providers/vectordb/PineconeProvider.ts"() {
533
+ "use strict";
534
+ import_pinecone = require("@pinecone-database/pinecone");
535
+ init_BaseVectorProvider();
536
+ PineconeProvider = class extends BaseVectorProvider {
537
+ constructor(config) {
538
+ super(config);
539
+ const opts = config.options;
540
+ if (!opts.apiKey) throw new Error("[PineconeProvider] options.apiKey is required");
541
+ this.apiKey = opts.apiKey;
542
+ }
543
+ async initialize() {
544
+ var _a, _b;
545
+ this.client = new import_pinecone.Pinecone({ apiKey: this.apiKey });
546
+ const indexes = await this.client.listIndexes();
547
+ const names = (_b = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _b : [];
548
+ if (!names.includes(this.indexName)) {
549
+ throw new Error(`[PineconeProvider] Index "${this.indexName}" not found.`);
550
+ }
551
+ }
552
+ index(namespace) {
553
+ const idx = this.client.index(this.indexName);
554
+ return namespace ? idx.namespace(namespace) : idx.namespace("");
555
+ }
556
+ async upsert(doc, namespace) {
557
+ var _a;
558
+ await this.index(namespace).upsert({
559
+ records: [{
560
+ id: doc.id,
561
+ values: doc.vector,
562
+ metadata: __spreadValues({ content: doc.content }, (_a = doc.metadata) != null ? _a : {})
563
+ }]
564
+ });
565
+ }
566
+ async batchUpsert(docs, namespace) {
567
+ const BATCH = 100;
568
+ for (let i = 0; i < docs.length; i += BATCH) {
569
+ const records = docs.slice(i, i + BATCH).map((d) => {
570
+ var _a;
571
+ return {
572
+ id: d.id,
573
+ values: d.vector,
574
+ metadata: __spreadValues({ content: d.content }, (_a = d.metadata) != null ? _a : {})
575
+ };
576
+ });
577
+ await this.index(namespace).upsert({ records });
578
+ }
579
+ }
580
+ async query(vector, topK, namespace, filter) {
581
+ var _a;
582
+ const result = await this.index(namespace).query(__spreadValues({
583
+ vector,
584
+ topK,
585
+ includeMetadata: true
586
+ }, filter ? { filter } : {}));
587
+ return ((_a = result.matches) != null ? _a : []).map((m) => {
588
+ var _a2, _b;
589
+ return {
590
+ id: m.id,
591
+ score: (_a2 = m.score) != null ? _a2 : 0,
592
+ content: ((_b = m.metadata) == null ? void 0 : _b.content) || "",
593
+ metadata: m.metadata
594
+ };
595
+ });
596
+ }
597
+ async delete(id, namespace) {
598
+ await this.index(namespace).deleteOne({ id });
599
+ }
600
+ async deleteNamespace(namespace) {
601
+ await this.client.index(this.indexName).namespace(namespace).deleteAll();
602
+ }
603
+ async ping() {
604
+ try {
605
+ await this.client.listIndexes();
606
+ return true;
607
+ } catch (e) {
608
+ return false;
609
+ }
610
+ }
611
+ async disconnect() {
612
+ }
613
+ };
614
+ }
615
+ });
616
+
617
+ // src/providers/vectordb/PostgreSQLProvider.ts
618
+ var PostgreSQLProvider_exports = {};
619
+ __export(PostgreSQLProvider_exports, {
620
+ PostgreSQLProvider: () => PostgreSQLProvider
621
+ });
622
+ var import_pg, PostgreSQLProvider;
623
+ var init_PostgreSQLProvider = __esm({
624
+ "src/providers/vectordb/PostgreSQLProvider.ts"() {
625
+ "use strict";
626
+ import_pg = require("pg");
627
+ init_BaseVectorProvider();
628
+ PostgreSQLProvider = class extends BaseVectorProvider {
629
+ constructor(config) {
630
+ var _a;
631
+ super(config);
632
+ this.tableName = this.indexName.replace(/[^a-z0-9_]/gi, "_");
633
+ const opts = config.options;
634
+ if (!opts.connectionString) throw new Error("[PostgreSQLProvider] options.connectionString is required");
635
+ this.connectionString = opts.connectionString;
636
+ this.dimensions = (_a = opts.dimensions) != null ? _a : 1536;
637
+ }
638
+ async initialize() {
639
+ this.pool = new import_pg.Pool({ connectionString: this.connectionString });
640
+ const client = await this.pool.connect();
641
+ try {
642
+ await client.query("CREATE EXTENSION IF NOT EXISTS vector");
643
+ await client.query(`
644
+ CREATE TABLE IF NOT EXISTS ${this.tableName} (
645
+ id TEXT PRIMARY KEY,
646
+ namespace TEXT NOT NULL DEFAULT '',
647
+ content TEXT NOT NULL,
648
+ metadata JSONB,
649
+ embedding VECTOR(${this.dimensions})
650
+ )
651
+ `);
652
+ await client.query(`
653
+ CREATE INDEX IF NOT EXISTS ${this.tableName}_embedding_idx
654
+ ON ${this.tableName}
655
+ USING hnsw (embedding vector_cosine_ops)
656
+ `);
657
+ } finally {
658
+ client.release();
659
+ }
660
+ }
661
+ async upsert(doc, namespace = "") {
662
+ var _a;
663
+ const vectorLiteral = `[${doc.vector.join(",")}]`;
664
+ await this.pool.query(
665
+ `INSERT INTO ${this.tableName} (id, namespace, content, metadata, embedding)
666
+ VALUES ($1, $2, $3, $4, $5::vector)
667
+ ON CONFLICT (id) DO UPDATE
668
+ SET namespace = EXCLUDED.namespace,
669
+ content = EXCLUDED.content,
670
+ metadata = EXCLUDED.metadata,
671
+ embedding = EXCLUDED.embedding`,
672
+ [doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), vectorLiteral]
673
+ );
674
+ }
675
+ async batchUpsert(docs, namespace = "") {
676
+ for (const doc of docs) {
677
+ await this.upsert(doc, namespace);
678
+ }
679
+ }
680
+ async query(vector, topK, namespace, filter) {
681
+ const vectorLiteral = `[${vector.join(",")}]`;
682
+ let whereClause = namespace ? `WHERE namespace = $3` : "";
683
+ const params = [vectorLiteral, topK];
684
+ if (namespace) params.push(namespace);
685
+ if (filter && Object.keys(filter).length > 0) {
686
+ const filterConditions = Object.entries(filter).map(([key, val]) => {
687
+ const paramIdx = params.length + 1;
688
+ params.push(JSON.stringify(val));
689
+ return `metadata->>'${key}' = $${paramIdx}`;
690
+ }).join(" AND ");
691
+ whereClause = whereClause ? `${whereClause} AND ${filterConditions}` : `WHERE ${filterConditions}`;
692
+ }
693
+ const result = await this.pool.query(
694
+ `SELECT id, content, metadata, 1 - (embedding <=> $1::vector) AS score
695
+ FROM ${this.tableName}
696
+ ${whereClause}
697
+ ORDER BY embedding <=> $1::vector
698
+ LIMIT $2`,
699
+ params
700
+ );
701
+ return result.rows.map((row) => ({
702
+ id: String(row["id"]),
703
+ score: parseFloat(String(row["score"])),
704
+ content: String(row["content"]),
705
+ metadata: row["metadata"]
706
+ }));
707
+ }
708
+ async delete(id, namespace) {
709
+ const where = namespace ? "WHERE id = $1 AND namespace = $2" : "WHERE id = $1";
710
+ const params = namespace ? [id, namespace] : [id];
711
+ await this.pool.query(`DELETE FROM ${this.tableName} ${where}`, params);
712
+ }
713
+ async deleteNamespace(namespace) {
714
+ await this.pool.query(`DELETE FROM ${this.tableName} WHERE namespace = $1`, [namespace]);
715
+ }
716
+ async ping() {
717
+ try {
718
+ await this.pool.query("SELECT 1");
719
+ return true;
720
+ } catch (e) {
721
+ return false;
722
+ }
723
+ }
724
+ async disconnect() {
725
+ await this.pool.end();
726
+ }
727
+ };
728
+ }
729
+ });
730
+
731
+ // src/providers/vectordb/MongoDBProvider.ts
732
+ var MongoDBProvider_exports = {};
733
+ __export(MongoDBProvider_exports, {
734
+ MongoDBProvider: () => MongoDBProvider
735
+ });
736
+ var import_mongodb, MongoDBProvider;
737
+ var init_MongoDBProvider = __esm({
738
+ "src/providers/vectordb/MongoDBProvider.ts"() {
739
+ "use strict";
740
+ import_mongodb = require("mongodb");
741
+ init_BaseVectorProvider();
742
+ MongoDBProvider = class extends BaseVectorProvider {
743
+ constructor(config) {
744
+ super(config);
745
+ const opts = config.options;
746
+ if (!opts.uri || !opts.database || !opts.collection) {
747
+ throw new Error("[MongoDBProvider] options uri, database, and collection are required.");
748
+ }
749
+ this.client = new import_mongodb.MongoClient(opts.uri);
750
+ this.dbName = opts.database;
751
+ this.collectionName = opts.collection;
752
+ this.embeddingKey = opts.embeddingKey || "embedding";
753
+ this.contentKey = opts.contentKey || "content";
754
+ this.metadataKey = opts.metadataKey || "metadata";
755
+ }
756
+ async initialize() {
757
+ await this.client.connect();
758
+ this.db = this.client.db(this.dbName);
759
+ this.collection = this.db.collection(this.collectionName);
760
+ }
761
+ async upsert(doc, namespace) {
762
+ const document = __spreadValues({
763
+ _id: doc.id,
764
+ [this.embeddingKey]: doc.vector,
765
+ [this.contentKey]: doc.content,
766
+ [this.metadataKey]: doc.metadata || {}
767
+ }, namespace ? { namespace } : {});
768
+ await this.collection.updateOne({ _id: doc.id }, { $set: document }, { upsert: true });
769
+ }
770
+ async batchUpsert(docs, namespace) {
771
+ const operations = docs.map((doc) => ({
772
+ updateOne: {
773
+ filter: { _id: doc.id },
774
+ update: {
775
+ $set: __spreadValues({
776
+ [this.embeddingKey]: doc.vector,
777
+ [this.contentKey]: doc.content,
778
+ [this.metadataKey]: doc.metadata || {}
779
+ }, namespace ? { namespace } : {})
780
+ },
781
+ upsert: true
782
+ }
783
+ }));
784
+ await this.collection.bulkWrite(operations);
785
+ }
786
+ async query(vector, topK, namespace, filter) {
787
+ const pipeline = [
788
+ {
789
+ $vectorSearch: __spreadValues({
790
+ index: this.config.options.indexName || "vector_index",
791
+ path: this.embeddingKey,
792
+ queryVector: vector,
793
+ numCandidates: Math.max(topK * 10, 100),
794
+ limit: topK
795
+ }, filter || namespace ? { filter: __spreadValues(__spreadValues({}, filter || {}), namespace ? { namespace } : {}) } : {})
796
+ },
797
+ {
798
+ $project: {
799
+ score: { $meta: "vectorSearchScore" },
800
+ content: `$${this.contentKey}`,
801
+ metadata: `$${this.metadataKey}`
802
+ }
803
+ }
804
+ ];
805
+ const results = await this.collection.aggregate(pipeline).toArray();
806
+ return results.map((res) => ({
807
+ id: res["_id"].toString(),
808
+ score: res["score"],
809
+ content: res["content"],
810
+ metadata: res["metadata"]
811
+ }));
812
+ }
813
+ async delete(id, namespace) {
814
+ await this.collection.deleteOne(__spreadValues({ _id: id }, namespace ? { namespace } : {}));
815
+ }
816
+ async deleteNamespace(namespace) {
817
+ await this.collection.deleteMany({ namespace });
818
+ }
819
+ async ping() {
820
+ try {
821
+ await this.db.command({ ping: 1 });
822
+ return true;
823
+ } catch (e) {
824
+ return false;
825
+ }
826
+ }
827
+ async disconnect() {
828
+ await this.client.close();
829
+ }
830
+ };
831
+ }
832
+ });
833
+
834
+ // src/providers/vectordb/MilvusProvider.ts
835
+ var MilvusProvider_exports = {};
836
+ __export(MilvusProvider_exports, {
837
+ MilvusProvider: () => MilvusProvider
838
+ });
839
+ var import_axios3, MilvusProvider;
840
+ var init_MilvusProvider = __esm({
841
+ "src/providers/vectordb/MilvusProvider.ts"() {
842
+ "use strict";
843
+ import_axios3 = __toESM(require("axios"));
844
+ init_BaseVectorProvider();
845
+ MilvusProvider = class extends BaseVectorProvider {
846
+ constructor(config) {
847
+ super(config);
848
+ const opts = config.options;
849
+ const baseUrl = opts.baseUrl || opts.uri;
850
+ if (!baseUrl) throw new Error("[MilvusProvider] baseUrl/uri is required");
851
+ this.http = import_axios3.default.create({
852
+ baseURL: baseUrl,
853
+ headers: __spreadValues(__spreadValues({
854
+ "Content-Type": "application/json"
855
+ }, opts.headers || {}), opts.apiKey ? { Authorization: `Bearer ${opts.apiKey}` } : {})
856
+ });
857
+ }
858
+ async initialize() {
859
+ await this.ping();
860
+ }
861
+ async upsert(doc, namespace) {
862
+ const payload = {
863
+ collectionName: this.indexName,
864
+ data: [__spreadValues({
865
+ vector: doc.vector,
866
+ content: doc.content,
867
+ metadata: doc.metadata || {}
868
+ }, namespace ? { namespace } : {})]
869
+ };
870
+ await this.http.post("/v1/vector/upsert", payload);
871
+ }
872
+ async batchUpsert(docs, namespace) {
873
+ const payload = {
874
+ collectionName: this.indexName,
875
+ data: docs.map((doc) => __spreadValues({
876
+ vector: doc.vector,
877
+ content: doc.content,
878
+ metadata: doc.metadata || {}
879
+ }, namespace ? { namespace } : {}))
880
+ };
881
+ await this.http.post("/v1/vector/upsert", payload);
882
+ }
883
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
884
+ async query(vector, topK, namespace, _filter) {
885
+ const payload = {
886
+ collectionName: this.indexName,
887
+ vector,
888
+ limit: topK,
889
+ filter: namespace ? `namespace == "${namespace}"` : void 0,
890
+ outputFields: ["content", "metadata"]
891
+ };
892
+ const { data } = await this.http.post("/v1/vector/search", payload);
893
+ return (data.data || []).map((res) => ({
894
+ id: String(res["id"]),
895
+ score: res["distance"],
896
+ content: res["content"],
897
+ metadata: res["metadata"]
898
+ }));
899
+ }
900
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
901
+ async delete(id, _namespace) {
902
+ await this.http.post("/v1/vector/delete", {
903
+ collectionName: this.indexName,
904
+ id
905
+ });
906
+ }
907
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
908
+ async deleteNamespace(_namespace) {
909
+ }
910
+ async ping() {
911
+ try {
912
+ await this.http.get("/v1/health");
913
+ return true;
914
+ } catch (e) {
915
+ return false;
916
+ }
917
+ }
918
+ async disconnect() {
919
+ }
920
+ };
921
+ }
922
+ });
923
+
924
+ // src/providers/vectordb/QdrantProvider.ts
925
+ var QdrantProvider_exports = {};
926
+ __export(QdrantProvider_exports, {
927
+ QdrantProvider: () => QdrantProvider
928
+ });
929
+ var import_axios4, QdrantProvider;
930
+ var init_QdrantProvider = __esm({
931
+ "src/providers/vectordb/QdrantProvider.ts"() {
932
+ "use strict";
933
+ import_axios4 = __toESM(require("axios"));
934
+ init_BaseVectorProvider();
935
+ QdrantProvider = class extends BaseVectorProvider {
936
+ constructor(config) {
937
+ super(config);
938
+ const opts = config.options;
939
+ const baseUrl = opts.baseUrl;
940
+ if (!baseUrl) throw new Error("[QdrantProvider] baseUrl is required");
941
+ this.http = import_axios4.default.create({
942
+ baseURL: baseUrl,
943
+ headers: __spreadValues({
944
+ "Content-Type": "application/json"
945
+ }, opts.apiKey ? { "api-key": opts.apiKey } : {})
946
+ });
947
+ }
948
+ async initialize() {
949
+ await this.ping();
950
+ }
951
+ async upsert(doc, namespace) {
952
+ await this.batchUpsert([doc], namespace);
953
+ }
954
+ async batchUpsert(docs, namespace) {
955
+ const payload = {
956
+ points: docs.map((doc) => ({
957
+ id: doc.id,
958
+ vector: doc.vector,
959
+ payload: __spreadValues({
960
+ content: doc.content,
961
+ metadata: doc.metadata || {}
962
+ }, namespace ? { namespace } : {})
963
+ }))
964
+ };
965
+ await this.http.put(`/collections/${this.indexName}/points`, payload);
966
+ }
967
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
968
+ async query(vector, topK, namespace, _filter) {
969
+ const payload = {
970
+ vector,
971
+ limit: topK,
972
+ with_payload: true,
973
+ filter: namespace ? {
974
+ must: [{ key: "namespace", match: { value: namespace } }]
975
+ } : void 0
976
+ };
977
+ const { data } = await this.http.post(`/collections/${this.indexName}/points/search`, payload);
978
+ return (data.result || []).map((res) => {
979
+ var _a, _b;
980
+ return {
981
+ id: res["id"],
982
+ score: res["score"],
983
+ content: ((_a = res["payload"]) == null ? void 0 : _a.content) || "",
984
+ metadata: ((_b = res["payload"]) == null ? void 0 : _b.metadata) || {}
985
+ };
986
+ });
987
+ }
988
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
989
+ async delete(id, _namespace) {
990
+ await this.http.post(`/collections/${this.indexName}/points/delete`, {
991
+ points: [id]
992
+ });
993
+ }
994
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
995
+ async deleteNamespace(_namespace) {
996
+ await this.http.post(`/collections/${this.indexName}/points/delete`, {
997
+ filter: {
998
+ must: [{ key: "namespace", match: { value: _namespace } }]
999
+ }
1000
+ });
1001
+ }
1002
+ async ping() {
1003
+ try {
1004
+ await this.http.get("/healthz");
1005
+ return true;
1006
+ } catch (e) {
1007
+ return false;
1008
+ }
1009
+ }
1010
+ async disconnect() {
1011
+ }
1012
+ };
1013
+ }
1014
+ });
1015
+
1016
+ // src/providers/vectordb/ChromaDBProvider.ts
1017
+ var ChromaDBProvider_exports = {};
1018
+ __export(ChromaDBProvider_exports, {
1019
+ ChromaDBProvider: () => ChromaDBProvider
1020
+ });
1021
+ var import_axios5, ChromaDBProvider;
1022
+ var init_ChromaDBProvider = __esm({
1023
+ "src/providers/vectordb/ChromaDBProvider.ts"() {
1024
+ "use strict";
1025
+ import_axios5 = __toESM(require("axios"));
1026
+ init_BaseVectorProvider();
1027
+ ChromaDBProvider = class extends BaseVectorProvider {
1028
+ constructor(config) {
1029
+ super(config);
1030
+ this.collectionId = "";
1031
+ const opts = config.options;
1032
+ const baseUrl = opts.baseUrl;
1033
+ if (!baseUrl) throw new Error("[ChromaDBProvider] baseUrl is required");
1034
+ this.http = import_axios5.default.create({
1035
+ baseURL: baseUrl,
1036
+ headers: { "Content-Type": "application/json" }
1037
+ });
1038
+ }
1039
+ async initialize() {
1040
+ const { data } = await this.http.get(`/api/v1/collections/${this.indexName}`);
1041
+ this.collectionId = data.id;
1042
+ }
1043
+ async upsert(doc, namespace) {
1044
+ await this.batchUpsert([doc], namespace);
1045
+ }
1046
+ async batchUpsert(docs, namespace) {
1047
+ const payload = {
1048
+ ids: docs.map((d) => d.id),
1049
+ embeddings: docs.map((d) => d.vector),
1050
+ documents: docs.map((d) => d.content),
1051
+ metadatas: docs.map((d) => __spreadValues(__spreadValues({}, d.metadata || {}), namespace ? { namespace } : {}))
1052
+ };
1053
+ await this.http.post(`/api/v1/collections/${this.collectionId}/add`, payload);
1054
+ }
1055
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1056
+ async query(vector, topK, namespace, _filter) {
1057
+ const payload = {
1058
+ query_embeddings: [vector],
1059
+ n_results: topK,
1060
+ where: namespace ? { namespace: { $eq: namespace } } : void 0
1061
+ };
1062
+ const { data } = await this.http.post(`/api/v1/collections/${this.collectionId}/query`, payload);
1063
+ const matches = [];
1064
+ if (data.ids && data.ids[0]) {
1065
+ for (let i = 0; i < data.ids[0].length; i++) {
1066
+ matches.push({
1067
+ id: data.ids[0][i],
1068
+ score: data.distances ? 1 - data.distances[0][i] : 0,
1069
+ content: data.documents ? data.documents[0][i] : "",
1070
+ metadata: data.metadatas ? data.metadatas[0][i] : {}
1071
+ });
1072
+ }
1073
+ }
1074
+ return matches;
1075
+ }
1076
+ async delete(id, _namespace) {
1077
+ await this.http.post(`/api/v1/collections/${this.collectionId}/delete`, {
1078
+ ids: [id],
1079
+ where: _namespace ? { namespace: { $eq: _namespace } } : void 0
1080
+ });
1081
+ }
1082
+ async deleteNamespace(_namespace) {
1083
+ await this.http.post(`/api/v1/collections/${this.collectionId}/delete`, {
1084
+ where: { namespace: { $eq: _namespace } }
1085
+ });
1086
+ }
1087
+ async ping() {
1088
+ try {
1089
+ await this.http.get("/api/v1/heartbeat");
1090
+ return true;
1091
+ } catch (e) {
1092
+ return false;
1093
+ }
1094
+ }
1095
+ async disconnect() {
1096
+ }
1097
+ };
1098
+ }
1099
+ });
1100
+
1101
+ // src/providers/vectordb/RedisProvider.ts
1102
+ var RedisProvider_exports = {};
1103
+ __export(RedisProvider_exports, {
1104
+ RedisProvider: () => RedisProvider
1105
+ });
1106
+ var import_axios6, RedisProvider;
1107
+ var init_RedisProvider = __esm({
1108
+ "src/providers/vectordb/RedisProvider.ts"() {
1109
+ "use strict";
1110
+ import_axios6 = __toESM(require("axios"));
1111
+ init_BaseVectorProvider();
1112
+ RedisProvider = class extends BaseVectorProvider {
1113
+ constructor(config) {
1114
+ super(config);
1115
+ const opts = config.options;
1116
+ const baseUrl = opts.baseUrl;
1117
+ if (!baseUrl) throw new Error("[RedisProvider] baseUrl is required");
1118
+ this.http = import_axios6.default.create({
1119
+ baseURL: baseUrl,
1120
+ headers: {
1121
+ "Content-Type": "application/json",
1122
+ Authorization: `Bearer ${opts.apiKey}`
1123
+ }
1124
+ });
1125
+ }
1126
+ async initialize() {
1127
+ await this.ping();
1128
+ }
1129
+ async upsert(doc, namespace) {
1130
+ const key = namespace ? `${namespace}:${doc.id}` : doc.id;
1131
+ await this.http.post("/", ["JSON.SET", key, "$", JSON.stringify({
1132
+ vector: doc.vector,
1133
+ content: doc.content,
1134
+ metadata: doc.metadata || {}
1135
+ })]);
1136
+ }
1137
+ async batchUpsert(docs, namespace) {
1138
+ for (const doc of docs) {
1139
+ await this.upsert(doc, namespace);
1140
+ }
1141
+ }
1142
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1143
+ async query(vector, topK, namespace, _filter) {
1144
+ const payload = {
1145
+ index: this.indexName,
1146
+ vector,
1147
+ topK,
1148
+ namespace
1149
+ };
1150
+ const { data } = await this.http.post("/search", payload);
1151
+ return (data.results || []).map((res) => ({
1152
+ id: res["id"],
1153
+ score: res["score"],
1154
+ content: res["content"],
1155
+ metadata: res["metadata"]
1156
+ }));
1157
+ }
1158
+ async delete(id, namespace) {
1159
+ const key = namespace ? `${namespace}:${id}` : id;
1160
+ await this.http.post("/", ["DEL", key]);
1161
+ }
1162
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1163
+ async deleteNamespace(_namespace) {
1164
+ }
1165
+ async ping() {
1166
+ try {
1167
+ await this.http.post("/", ["PING"]);
1168
+ return true;
1169
+ } catch (e) {
1170
+ return false;
1171
+ }
1172
+ }
1173
+ async disconnect() {
1174
+ }
1175
+ };
1176
+ }
1177
+ });
1178
+
1179
+ // src/providers/vectordb/WeaviateProvider.ts
1180
+ var WeaviateProvider_exports = {};
1181
+ __export(WeaviateProvider_exports, {
1182
+ WeaviateProvider: () => WeaviateProvider
1183
+ });
1184
+ var import_axios7, WeaviateProvider;
1185
+ var init_WeaviateProvider = __esm({
1186
+ "src/providers/vectordb/WeaviateProvider.ts"() {
1187
+ "use strict";
1188
+ import_axios7 = __toESM(require("axios"));
1189
+ init_BaseVectorProvider();
1190
+ WeaviateProvider = class extends BaseVectorProvider {
1191
+ constructor(config) {
1192
+ super(config);
1193
+ const opts = config.options;
1194
+ const baseUrl = opts.baseUrl;
1195
+ if (!baseUrl) throw new Error("[WeaviateProvider] baseUrl is required");
1196
+ this.http = import_axios7.default.create({
1197
+ baseURL: baseUrl,
1198
+ headers: __spreadValues({
1199
+ "Content-Type": "application/json"
1200
+ }, opts.apiKey ? {
1201
+ "X-OpenAI-Api-Key": opts.apiKey,
1202
+ "Authorization": `Bearer ${opts.apiKey}`
1203
+ } : {})
1204
+ });
1205
+ }
1206
+ async initialize() {
1207
+ await this.ping();
1208
+ }
1209
+ async upsert(doc, namespace) {
1210
+ const payload = {
1211
+ class: this.indexName,
1212
+ id: doc.id,
1213
+ vector: doc.vector,
1214
+ properties: {
1215
+ content: doc.content,
1216
+ metadata: JSON.stringify(doc.metadata || {}),
1217
+ namespace: namespace || ""
1218
+ }
1219
+ };
1220
+ await this.http.post("/v1/objects", payload);
1221
+ }
1222
+ async batchUpsert(docs, namespace) {
1223
+ const payload = {
1224
+ objects: docs.map((doc) => ({
1225
+ class: this.indexName,
1226
+ id: doc.id,
1227
+ vector: doc.vector,
1228
+ properties: {
1229
+ content: doc.content,
1230
+ metadata: JSON.stringify(doc.metadata || {}),
1231
+ namespace: namespace || ""
1232
+ }
1233
+ }))
1234
+ };
1235
+ await this.http.post("/v1/batch/objects", payload);
1236
+ }
1237
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1238
+ async query(vector, topK, namespace, _filter) {
1239
+ var _a, _b;
1240
+ const graphqlQuery = {
1241
+ query: `
1242
+ {
1243
+ Get {
1244
+ ${this.indexName}(
1245
+ nearVector: {
1246
+ vector: ${JSON.stringify(vector)}
1247
+ }
1248
+ limit: ${topK}
1249
+ ${namespace ? `where: { path: ["namespace"], operator: Equal, valueString: "${namespace}" }` : ""}
1250
+ ) {
1251
+ content
1252
+ metadata
1253
+ _additional {
1254
+ id
1255
+ distance
1256
+ }
1257
+ }
1258
+ }
1259
+ }
1260
+ `
1261
+ };
1262
+ const { data } = await this.http.post("/v1/graphql", graphqlQuery);
1263
+ const results = ((_b = (_a = data.data) == null ? void 0 : _a.Get) == null ? void 0 : _b[this.indexName]) || [];
1264
+ return results.map((res) => ({
1265
+ id: res["_additional"].id,
1266
+ score: 1 - res["_additional"].distance,
1267
+ content: res["content"],
1268
+ metadata: res["metadata"] ? JSON.parse(res["metadata"]) : {}
1269
+ }));
1270
+ }
1271
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1272
+ async delete(id, _namespace) {
1273
+ await this.http.delete(`/v1/objects/${this.indexName}/${id}`);
1274
+ }
1275
+ async deleteNamespace(namespace) {
1276
+ await this.http.post("/v1/batch/objects", {
1277
+ match: {
1278
+ class: this.indexName,
1279
+ where: { path: ["namespace"], operator: "Equal", valueString: namespace }
1280
+ }
1281
+ });
1282
+ }
1283
+ async ping() {
1284
+ try {
1285
+ await this.http.get("/v1/.well-known/live");
1286
+ return true;
1287
+ } catch (e) {
1288
+ return false;
1289
+ }
1290
+ }
1291
+ async disconnect() {
1292
+ }
1293
+ };
1294
+ }
1295
+ });
1296
+
1297
+ // src/server.ts
1298
+ var server_exports = {};
1299
+ __export(server_exports, {
1300
+ AnthropicProvider: () => AnthropicProvider,
1301
+ BaseVectorProvider: () => BaseVectorProvider,
1302
+ ChromaDBProvider: () => ChromaDBProvider,
1303
+ ConfigResolver: () => ConfigResolver,
1304
+ DocumentChunker: () => DocumentChunker,
1305
+ LLMFactory: () => LLMFactory,
1306
+ MilvusProvider: () => MilvusProvider,
1307
+ MongoDBProvider: () => MongoDBProvider,
1308
+ OllamaProvider: () => OllamaProvider,
1309
+ OpenAIProvider: () => OpenAIProvider,
1310
+ PineconeProvider: () => PineconeProvider,
1311
+ Pipeline: () => Pipeline,
1312
+ PostgreSQLProvider: () => PostgreSQLProvider,
1313
+ ProviderRegistry: () => ProviderRegistry,
1314
+ QdrantProvider: () => QdrantProvider,
1315
+ RedisProvider: () => RedisProvider,
1316
+ VectorPlugin: () => VectorPlugin,
1317
+ WeaviateProvider: () => WeaviateProvider,
1318
+ createChatHandler: () => createChatHandler,
1319
+ createHealthHandler: () => createHealthHandler,
1320
+ createIngestHandler: () => createIngestHandler,
1321
+ createUploadHandler: () => createUploadHandler,
1322
+ getRagConfig: () => getRagConfig
1323
+ });
1324
+ module.exports = __toCommonJS(server_exports);
1325
+
1326
+ // src/core/ConfigResolver.ts
1327
+ init_templateUtils();
1328
+
1329
+ // src/config/serverConfig.ts
1330
+ var VECTOR_DB_PROVIDERS = ["pinecone", "pgvector", "postgresql", "mongodb", "milvus", "qdrant", "chromadb", "redis", "weaviate", "rest", "universal_rest", "custom"];
1331
+ var LLM_PROVIDERS = ["openai", "anthropic", "ollama", "rest", "universal_rest", "custom"];
1332
+ var EMBEDDING_PROVIDERS = ["openai", "ollama", "rest", "universal_rest", "custom"];
1333
+ function readString(env, name) {
1334
+ var _a;
1335
+ const value = (_a = env[name]) == null ? void 0 : _a.trim();
1336
+ return value ? value : void 0;
1337
+ }
1338
+ function readNumber(env, name, fallback) {
1339
+ const value = env[name];
1340
+ if (!value) return fallback;
1341
+ const parsed = Number(value);
1342
+ if (!Number.isFinite(parsed)) {
1343
+ throw new Error(`[getRagConfig] ${name} must be a valid number`);
1344
+ }
1345
+ return parsed;
1346
+ }
1347
+ function readEnum(env, name, fallback, allowed) {
1348
+ var _a;
1349
+ const value = (_a = readString(env, name)) != null ? _a : fallback;
1350
+ if (allowed.includes(value)) {
1351
+ return value;
1352
+ }
1353
+ throw new Error(`[getRagConfig] ${name} must be one of: ${allowed.join(", ")}`);
1354
+ }
1355
+ function getRagConfig(env = process.env) {
1356
+ 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;
1357
+ const projectId = (_b = (_a = readString(env, "RAG_PROJECT_ID")) != null ? _a : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : "__default__";
1358
+ const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
1359
+ const llmProvider = readEnum(env, "LLM_PROVIDER", "openai", LLM_PROVIDERS);
1360
+ const embeddingProvider = readEnum(env, "EMBEDDING_PROVIDER", "openai", EMBEDDING_PROVIDERS);
1361
+ const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 1536);
1362
+ const vectorDbOptions = {};
1363
+ if (vectorProvider === "pinecone") {
1364
+ vectorDbOptions.apiKey = (_c = readString(env, "PINECONE_API_KEY")) != null ? _c : "";
1365
+ vectorDbOptions.environment = (_d = readString(env, "PINECONE_ENVIRONMENT")) != null ? _d : "";
1366
+ } else if (vectorProvider === "pgvector") {
1367
+ vectorDbOptions.connectionString = (_e = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _e : "";
1368
+ vectorDbOptions.dimensions = embeddingDimensions;
1369
+ } else if (vectorProvider === "rest") {
1370
+ vectorDbOptions.baseUrl = (_f = readString(env, "VECTOR_DB_REST_URL")) != null ? _f : "";
1371
+ vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { "api-key": readString(env, "VECTOR_DB_REST_API_KEY") } : {};
1372
+ } else if (vectorProvider === "universal_rest") {
1373
+ vectorDbOptions.baseUrl = (_h = (_g = readString(env, "VECTOR_BASE_URL")) != null ? _g : readString(env, "VECTOR_DB_REST_URL")) != null ? _h : "";
1374
+ vectorDbOptions.profile = readString(env, "VECTOR_UNIVERSAL_PROFILE");
1375
+ vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { Authorization: `Bearer ${readString(env, "VECTOR_DB_REST_API_KEY")}` } : {};
1376
+ } else if (vectorProvider === "mongodb") {
1377
+ vectorDbOptions.uri = (_i = readString(env, "MONGODB_URI")) != null ? _i : "";
1378
+ vectorDbOptions.database = (_j = readString(env, "MONGODB_DB")) != null ? _j : "";
1379
+ vectorDbOptions.collection = (_k = readString(env, "MONGODB_COLLECTION")) != null ? _k : "";
1380
+ vectorDbOptions.indexName = (_l = readString(env, "MONGODB_INDEX_NAME")) != null ? _l : "vector_index";
1381
+ }
1382
+ const llmApiKeyByProvider = {
1383
+ openai: readString(env, "OPENAI_API_KEY"),
1384
+ anthropic: readString(env, "ANTHROPIC_API_KEY"),
1385
+ ollama: void 0,
1386
+ universal_rest: readString(env, "LLM_API_KEY")
1387
+ };
1388
+ const embeddingApiKeyByProvider = {
1389
+ openai: readString(env, "OPENAI_API_KEY"),
1390
+ ollama: void 0,
1391
+ custom: (_m = readString(env, "EMBEDDING_API_KEY")) != null ? _m : readString(env, "OPENAI_API_KEY")
1392
+ };
1393
+ return {
1394
+ projectId,
1395
+ vectorDb: {
1396
+ provider: vectorProvider,
1397
+ indexName: (_n = readString(env, "VECTOR_DB_INDEX")) != null ? _n : "rag-index",
1398
+ options: vectorDbOptions
1399
+ },
1400
+ llm: {
1401
+ provider: llmProvider,
1402
+ model: (_o = readString(env, "LLM_MODEL")) != null ? _o : "gpt-4o",
1403
+ apiKey: (_p = llmApiKeyByProvider[llmProvider]) != null ? _p : "",
1404
+ baseUrl: readString(env, "LLM_BASE_URL"),
1405
+ systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
1406
+ maxTokens: readNumber(env, "LLM_MAX_TOKENS", 1024),
1407
+ temperature: readNumber(env, "LLM_TEMPERATURE", 0.7),
1408
+ options: {
1409
+ profile: readString(env, "LLM_UNIVERSAL_PROFILE")
1410
+ }
1411
+ },
1412
+ embedding: {
1413
+ provider: embeddingProvider,
1414
+ model: (_q = readString(env, "EMBEDDING_MODEL")) != null ? _q : "text-embedding-3-small",
1415
+ apiKey: embeddingApiKeyByProvider[embeddingProvider],
1416
+ baseUrl: readString(env, "EMBEDDING_BASE_URL"),
1417
+ dimensions: embeddingDimensions,
1418
+ options: {
1419
+ profile: readString(env, "EMBEDDING_UNIVERSAL_PROFILE")
1420
+ }
1421
+ },
1422
+ ui: {
1423
+ title: (_s = (_r = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _r : readString(env, "UI_TITLE")) != null ? _s : "AI Assistant",
1424
+ subtitle: (_u = (_t = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _t : readString(env, "UI_SUBTITLE")) != null ? _u : "Powered by RAG",
1425
+ primaryColor: (_w = (_v = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _v : readString(env, "UI_PRIMARY_COLOR")) != null ? _w : "#10b981",
1426
+ accentColor: (_y = (_x = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _x : readString(env, "UI_ACCENT_COLOR")) != null ? _y : "#3b82f6",
1427
+ logoUrl: (_z = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _z : readString(env, "UI_LOGO_URL"),
1428
+ placeholder: (_B = (_A = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _A : readString(env, "UI_PLACEHOLDER")) != null ? _B : "Ask me anything\u2026",
1429
+ showSources: ((_D = (_C = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _C : readString(env, "UI_SHOW_SOURCES")) != null ? _D : "true") !== "false",
1430
+ welcomeMessage: (_F = (_E = readString(env, "NEXT_PUBLIC_WELCOME_MESSAGE")) != null ? _E : readString(env, "UI_WELCOME_MESSAGE")) != null ? _F : "Hello! I'm your AI assistant. Ask me anything about your documents.",
1431
+ visualStyle: (_H = (_G = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _G : readString(env, "UI_VISUAL_STYLE")) != null ? _H : "glass",
1432
+ borderRadius: (_J = (_I = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _I : readString(env, "UI_BORDER_RADIUS")) != null ? _J : "xl"
1433
+ },
1434
+ rag: {
1435
+ topK: readNumber(env, "RAG_TOP_K", 5),
1436
+ scoreThreshold: readNumber(env, "RAG_SCORE_THRESHOLD", 0),
1437
+ chunkSize: readNumber(env, "RAG_CHUNK_SIZE", 1e3),
1438
+ chunkOverlap: readNumber(env, "RAG_CHUNK_OVERLAP", 200)
701
1439
  }
702
- }
703
- };
704
-
705
- // src/llm/providers/AnthropicProvider.ts
706
- var import_sdk = __toESM(require("@anthropic-ai/sdk"));
707
- var AnthropicProvider = class {
708
- constructor(llmConfig, embeddingConfig) {
709
- if (!llmConfig.apiKey) throw new Error("[AnthropicProvider] llmConfig.apiKey is required");
710
- this.client = new import_sdk.default({ apiKey: llmConfig.apiKey });
711
- this.llmConfig = llmConfig;
712
- this.embeddingConfig = embeddingConfig;
713
- }
714
- async chat(messages, context, options) {
715
- var _a, _b, _c;
716
- const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
717
-
718
- Context:
719
- ${context}`;
720
- const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
1440
+ };
1441
+ }
721
1442
 
722
- Context:
723
- ${context}`;
724
- const anthropicMessages = messages.map((m) => ({
725
- role: m.role === "assistant" ? "assistant" : "user",
726
- content: m.content
727
- }));
728
- const response = await this.client.messages.create({
729
- model: this.llmConfig.model,
730
- max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
731
- system,
732
- messages: anthropicMessages
733
- });
734
- const block = response.content[0];
735
- return block.type === "text" ? block.text : "";
736
- }
1443
+ // src/core/ConfigResolver.ts
1444
+ var ConfigResolver = class {
737
1445
  /**
738
- * Anthropic does not offer an embedding API.
739
- * This method throws with a clear error so developers know to configure
740
- * a separate embedding provider (OpenAI or Ollama).
1446
+ * Resolves the final configuration by merging host-provided config with defaults.
1447
+ * @param hostConfig - Partial configuration passed from the host application.
741
1448
  */
742
- async embed(text, options) {
743
- void text;
744
- void options;
745
- throw new Error(
746
- '[AnthropicProvider] Anthropic does not provide an embedding API. Set embedding.provider to "openai" or "ollama" in your RagConfig.'
747
- );
748
- }
749
- async batchEmbed(texts, options) {
750
- void texts;
751
- void options;
752
- throw new Error(
753
- "[AnthropicProvider] Anthropic does not provide an embedding API."
754
- );
755
- }
756
- async ping() {
757
- try {
758
- await this.client.models.list();
759
- return true;
760
- } catch (err) {
761
- console.error("[AnthropicProvider] Ping failed:", err);
762
- return false;
763
- }
764
- }
765
- };
766
-
767
- // src/llm/providers/OllamaProvider.ts
768
- var import_axios2 = __toESM(require("axios"));
769
- var OllamaProvider = class {
770
- constructor(llmConfig, embeddingConfig) {
771
- var _a;
772
- const baseURL = (_a = llmConfig.baseUrl) != null ? _a : "http://localhost:11434";
773
- this.http = import_axios2.default.create({ baseURL, timeout: 12e4 });
774
- this.llmConfig = llmConfig;
775
- this.embeddingConfig = embeddingConfig;
776
- }
777
- async chat(messages, context, options) {
778
- var _a, _b, _c, _d, _e;
779
- const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the provided context to answer the user's question.
780
-
781
- Context:
782
- ${context}`;
783
- const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
784
-
785
- Context:
786
- ${context}`;
787
- const { data } = await this.http.post("/api/chat", {
788
- model: this.llmConfig.model,
789
- stream: false,
790
- options: {
791
- temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
792
- num_predict: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024
793
- },
794
- messages: [
795
- { role: "system", content: system },
796
- ...messages.map((m) => ({ role: m.role, content: m.content }))
797
- ]
798
- });
799
- return data.message.content;
800
- }
801
- async embed(text, options) {
802
- var _a, _b, _c, _d, _e, _f, _g;
803
- 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";
804
- const baseURL = (_f = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.baseUrl) != null ? _e : this.llmConfig.baseUrl) != null ? _f : "http://localhost:11434";
805
- const client = baseURL !== ((_g = this.llmConfig.baseUrl) != null ? _g : "http://localhost:11434") ? import_axios2.default.create({ baseURL, timeout: 6e4 }) : this.http;
806
- const { data } = await client.post("/api/embeddings", {
807
- model,
808
- prompt: text
809
- });
810
- return data.embedding;
811
- }
812
- async batchEmbed(texts, options) {
813
- const vectors = [];
814
- for (const text of texts) {
815
- vectors.push(await this.embed(text, options));
1449
+ static resolve(hostConfig) {
1450
+ const envConfig = getRagConfig();
1451
+ if (!hostConfig) {
1452
+ return envConfig;
816
1453
  }
817
- return vectors;
818
- }
819
- async ping() {
820
- try {
821
- await this.http.get("/api/tags");
822
- return true;
823
- } catch (err) {
824
- console.error("[OllamaProvider] Ping failed:", err);
825
- return false;
826
- }
827
- }
828
- };
829
-
830
- // src/llm/providers/UniversalLLMAdapter.ts
831
- var import_axios3 = __toESM(require("axios"));
832
- var UniversalLLMAdapter = class {
833
- constructor(config) {
834
- var _a, _b, _c, _d, _e, _f, _g;
835
- this.model = config.model;
836
- const llmConfig = config;
837
- const options = (_a = llmConfig.options) != null ? _a : {};
838
- let profile = {};
839
- if (typeof options.profile === "string") {
840
- profile = LLM_PROFILES[options.profile] || {};
841
- } else if (typeof options.profile === "object" && options.profile !== null) {
842
- profile = options.profile;
843
- }
844
- this.opts = __spreadValues(__spreadValues({}, profile), (_b = llmConfig.options) != null ? _b : {});
845
- this.systemPrompt = (_c = llmConfig.systemPrompt) != null ? _c : "You are a helpful AI assistant. Use the provided context to answer the user.";
846
- this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
847
- this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
848
- const baseUrl = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl;
849
- if (!baseUrl) {
850
- throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
851
- }
852
- this.http = import_axios3.default.create({
853
- baseURL: baseUrl,
854
- headers: __spreadValues(__spreadValues({
855
- "Content-Type": "application/json"
856
- }, config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}), this.opts.headers || {}),
857
- timeout: (_g = this.opts.timeout) != null ? _g : 6e4
1454
+ return __spreadProps(__spreadValues(__spreadValues({}, envConfig), hostConfig), {
1455
+ projectId: hostConfig.projectId || envConfig.projectId,
1456
+ vectorDb: hostConfig.vectorDb ? __spreadProps(__spreadValues(__spreadValues({}, envConfig.vectorDb), hostConfig.vectorDb), {
1457
+ options: __spreadValues(__spreadValues({}, envConfig.vectorDb.options), hostConfig.vectorDb.options || {})
1458
+ }) : envConfig.vectorDb,
1459
+ llm: hostConfig.llm ? __spreadProps(__spreadValues(__spreadValues({}, envConfig.llm), hostConfig.llm), {
1460
+ options: __spreadValues(__spreadValues({}, envConfig.llm.options || {}), hostConfig.llm.options || {})
1461
+ }) : envConfig.llm,
1462
+ embedding: hostConfig.embedding ? __spreadProps(__spreadValues(__spreadValues({}, envConfig.embedding), hostConfig.embedding), {
1463
+ options: __spreadValues(__spreadValues({}, envConfig.embedding.options || {}), hostConfig.embedding.options || {})
1464
+ }) : envConfig.embedding,
1465
+ ui: hostConfig.ui ? mergeDefined(envConfig.ui, hostConfig.ui) : envConfig.ui,
1466
+ rag: hostConfig.rag ? __spreadValues(__spreadValues({}, envConfig.rag), hostConfig.rag) : envConfig.rag
858
1467
  });
859
1468
  }
860
- async chat(messages, context) {
861
- var _a, _b;
862
- const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
863
- const formattedMessages = [
864
- { role: "system", content: `${this.systemPrompt}
865
-
866
- Context:
867
- ${context != null ? context : "None"}` },
868
- ...messages
869
- ];
870
- let payload;
871
- if (this.opts.chatPayloadTemplate) {
872
- payload = buildPayload(this.opts.chatPayloadTemplate, {
873
- model: this.model,
874
- messages: formattedMessages,
875
- maxTokens: this.maxTokens,
876
- temperature: this.temperature
877
- });
878
- } else {
879
- payload = {
880
- model: this.model,
881
- messages: formattedMessages,
882
- max_tokens: this.maxTokens,
883
- temperature: this.temperature
884
- };
885
- }
886
- const { data } = await this.http.post(path, payload);
887
- const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
888
- const result = resolvePath(data, extractPath);
889
- if (result === void 0) {
890
- throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
891
- }
892
- return String(result);
893
- }
894
- async embed(text) {
895
- var _a, _b;
896
- const path = (_a = this.opts.embedPath) != null ? _a : "/embeddings";
897
- let payload;
898
- if (this.opts.embedPayloadTemplate) {
899
- payload = buildPayload(this.opts.embedPayloadTemplate, {
900
- model: this.model,
901
- input: text
902
- });
903
- } else {
904
- payload = {
905
- model: this.model,
906
- input: text
907
- };
908
- }
909
- const { data } = await this.http.post(path, payload);
910
- const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
911
- const vector = resolvePath(data, extractPath);
912
- if (!Array.isArray(vector)) {
913
- throw new Error(`[UniversalLLMAdapter] Expected a number array at '${extractPath}' for embeddings.`);
914
- }
915
- return vector;
916
- }
917
- async batchEmbed(texts) {
918
- const vectors = [];
919
- for (const text of texts) {
920
- vectors.push(await this.embed(text));
1469
+ /**
1470
+ * Validates the configuration for required fields.
1471
+ */
1472
+ static validate(config) {
1473
+ if (!config.projectId) {
1474
+ throw new Error("[ConfigResolver] projectId is required");
921
1475
  }
922
- return vectors;
923
- }
924
- async ping() {
925
- try {
926
- if (this.opts.pingPath) {
927
- await this.http.get(this.opts.pingPath);
928
- }
929
- return true;
930
- } catch (err) {
931
- console.error("[UniversalLLMAdapter] Ping failed:", err);
932
- return false;
1476
+ if (!config.vectorDb.provider) {
1477
+ throw new Error("[ConfigResolver] vectorDb.provider is required");
933
1478
  }
934
- }
935
- };
936
-
937
- // src/llm/LLMFactory.ts
938
- var LLMFactory = class _LLMFactory {
939
- static create(llmConfig, embeddingConfig) {
940
- var _a;
941
- switch (llmConfig.provider) {
942
- case "openai":
943
- return new OpenAIProvider(llmConfig, embeddingConfig);
944
- case "anthropic":
945
- return new AnthropicProvider(llmConfig, embeddingConfig);
946
- case "ollama":
947
- return new OllamaProvider(llmConfig, embeddingConfig);
948
- case "rest":
949
- case "universal_rest":
950
- case "custom":
951
- return new UniversalLLMAdapter(llmConfig);
952
- default:
953
- if (llmConfig.baseUrl || ((_a = llmConfig.options) == null ? void 0 : _a.baseUrl)) {
954
- return new UniversalLLMAdapter(llmConfig);
955
- }
956
- throw new Error(
957
- `[LLMFactory] Unknown provider "${llmConfig.provider}". Supported: openai | anthropic | ollama | rest | custom`
958
- );
1479
+ if (!config.llm.provider) {
1480
+ throw new Error("[ConfigResolver] llm.provider is required");
959
1481
  }
960
1482
  }
961
- /**
962
- * Creates a dedicated embedding-only provider.
963
- * Useful when the LLM provider (e.g. Anthropic) doesn't support embeddings.
964
- */
965
- static createEmbeddingProvider(embeddingConfig) {
966
- const fakeLLMConfig = {
967
- provider: embeddingConfig.provider,
968
- model: embeddingConfig.model,
969
- apiKey: embeddingConfig.apiKey,
970
- baseUrl: embeddingConfig.baseUrl,
971
- options: embeddingConfig.options
972
- };
973
- return _LLMFactory.create(fakeLLMConfig, embeddingConfig);
974
- }
975
1483
  };
976
1484
 
977
1485
  // src/rag/DocumentChunker.ts
@@ -1033,42 +1541,88 @@ var DocumentChunker = class {
1033
1541
  }
1034
1542
  };
1035
1543
 
1036
- // src/rag/RAGPipeline.ts
1037
- var RAGPipeline = class {
1038
- constructor(config, adapters) {
1544
+ // src/core/ProviderRegistry.ts
1545
+ init_LLMFactory();
1546
+ var ProviderRegistry = class {
1547
+ /**
1548
+ * Register a custom vector provider.
1549
+ */
1550
+ static registerVectorProvider(name, providerClass) {
1551
+ this.vectorProviders[name] = providerClass;
1552
+ }
1553
+ /**
1554
+ * Creates a vector database provider based on the configuration.
1555
+ */
1556
+ static async createVectorProvider(config) {
1557
+ const { provider } = config;
1558
+ if (this.vectorProviders[provider]) {
1559
+ return new this.vectorProviders[provider](config);
1560
+ }
1561
+ switch (provider) {
1562
+ case "pinecone":
1563
+ const { PineconeProvider: PineconeProvider2 } = await Promise.resolve().then(() => (init_PineconeProvider(), PineconeProvider_exports));
1564
+ return new PineconeProvider2(config);
1565
+ case "pgvector":
1566
+ case "postgresql":
1567
+ const { PostgreSQLProvider: PostgreSQLProvider2 } = await Promise.resolve().then(() => (init_PostgreSQLProvider(), PostgreSQLProvider_exports));
1568
+ return new PostgreSQLProvider2(config);
1569
+ case "mongodb":
1570
+ const { MongoDBProvider: MongoDBProvider2 } = await Promise.resolve().then(() => (init_MongoDBProvider(), MongoDBProvider_exports));
1571
+ return new MongoDBProvider2(config);
1572
+ case "milvus":
1573
+ const { MilvusProvider: MilvusProvider2 } = await Promise.resolve().then(() => (init_MilvusProvider(), MilvusProvider_exports));
1574
+ return new MilvusProvider2(config);
1575
+ case "qdrant":
1576
+ const { QdrantProvider: QdrantProvider2 } = await Promise.resolve().then(() => (init_QdrantProvider(), QdrantProvider_exports));
1577
+ return new QdrantProvider2(config);
1578
+ case "chromadb":
1579
+ const { ChromaDBProvider: ChromaDBProvider2 } = await Promise.resolve().then(() => (init_ChromaDBProvider(), ChromaDBProvider_exports));
1580
+ return new ChromaDBProvider2(config);
1581
+ case "redis":
1582
+ const { RedisProvider: RedisProvider2 } = await Promise.resolve().then(() => (init_RedisProvider(), RedisProvider_exports));
1583
+ return new RedisProvider2(config);
1584
+ case "weaviate":
1585
+ const { WeaviateProvider: WeaviateProvider2 } = await Promise.resolve().then(() => (init_WeaviateProvider(), WeaviateProvider_exports));
1586
+ return new WeaviateProvider2(config);
1587
+ default:
1588
+ throw new Error(`[ProviderRegistry] Unsupported vector provider: ${provider}`);
1589
+ }
1590
+ }
1591
+ /**
1592
+ * Creates an LLM provider based on the configuration.
1593
+ */
1594
+ static createLLMProvider(llmConfig, embeddingConfig) {
1595
+ return LLMFactory.create(llmConfig, embeddingConfig);
1596
+ }
1597
+ };
1598
+ ProviderRegistry.vectorProviders = {};
1599
+
1600
+ // src/core/Pipeline.ts
1601
+ var Pipeline = class {
1602
+ constructor(config) {
1039
1603
  this.initialised = false;
1040
- var _a, _b, _c, _d, _e, _f;
1604
+ var _a, _b, _c, _d;
1041
1605
  this.config = config;
1042
- this.vectorDB = (_a = adapters == null ? void 0 : adapters.vectorDB) != null ? _a : VectorDBFactory.create(config.vectorDb);
1043
- this.llmProvider = (_b = adapters == null ? void 0 : adapters.llmProvider) != null ? _b : LLMFactory.create(config.llm, config.embedding);
1044
- if (adapters == null ? void 0 : adapters.embeddingProvider) {
1045
- this.embeddingProvider = adapters.embeddingProvider;
1046
- } else if (config.llm.provider === "anthropic") {
1047
- this.embeddingProvider = LLMFactory.createEmbeddingProvider(config.embedding);
1048
- } else {
1049
- this.embeddingProvider = this.llmProvider;
1050
- }
1051
1606
  this.chunker = new DocumentChunker(
1052
- (_d = (_c = config.rag) == null ? void 0 : _c.chunkSize) != null ? _d : 1e3,
1053
- (_f = (_e = config.rag) == null ? void 0 : _e.chunkOverlap) != null ? _f : 200
1607
+ (_b = (_a = config.rag) == null ? void 0 : _a.chunkSize) != null ? _b : 1e3,
1608
+ (_d = (_c = config.rag) == null ? void 0 : _c.chunkOverlap) != null ? _d : 200
1054
1609
  );
1055
1610
  }
1056
- /** Lazily initialise the vector DB connection */
1057
- async init() {
1058
- if (!this.initialised) {
1059
- await this.vectorDB.initialize();
1060
- this.initialised = true;
1611
+ async initialize() {
1612
+ if (this.initialised) return;
1613
+ this.vectorDB = await ProviderRegistry.createVectorProvider(this.config.vectorDb);
1614
+ this.llmProvider = ProviderRegistry.createLLMProvider(this.config.llm, this.config.embedding);
1615
+ if (this.config.llm.provider === "anthropic") {
1616
+ const { LLMFactory: LLMFactory2 } = await Promise.resolve().then(() => (init_LLMFactory(), LLMFactory_exports));
1617
+ this.embeddingProvider = LLMFactory2.createEmbeddingProvider(this.config.embedding);
1618
+ } else {
1619
+ this.embeddingProvider = this.llmProvider;
1061
1620
  }
1621
+ await this.vectorDB.initialize();
1622
+ this.initialised = true;
1062
1623
  }
1063
- // ---------------------------------------------------------------------------
1064
- // INGEST
1065
- // ---------------------------------------------------------------------------
1066
- /**
1067
- * Ingest one or more documents into the vector DB.
1068
- * Automatically chunks, embeds, and upserts each chunk.
1069
- */
1070
1624
  async ingest(documents, namespace) {
1071
- await this.init();
1625
+ await this.initialize();
1072
1626
  const ns = namespace != null ? namespace : this.config.projectId;
1073
1627
  const results = [];
1074
1628
  for (const doc of documents) {
@@ -1076,8 +1630,7 @@ var RAGPipeline = class {
1076
1630
  docId: doc.docId,
1077
1631
  metadata: doc.metadata
1078
1632
  });
1079
- const chunkTexts = chunks.map((c) => c.content);
1080
- const vectors = await this.embeddingProvider.batchEmbed(chunkTexts);
1633
+ const vectors = await this.embeddingProvider.batchEmbed(chunks.map((c) => c.content));
1081
1634
  const upsertDocs = chunks.map((chunk, i) => ({
1082
1635
  id: chunk.id,
1083
1636
  vector: vectors[i],
@@ -1086,24 +1639,12 @@ var RAGPipeline = class {
1086
1639
  }));
1087
1640
  await this.vectorDB.batchUpsert(upsertDocs, ns);
1088
1641
  results.push({ docId: doc.docId, chunksIngested: chunks.length });
1089
- console.log(`[RAGPipeline] Ingested ${chunks.length} chunks for doc: ${doc.docId}`);
1090
1642
  }
1091
1643
  return results;
1092
1644
  }
1093
- // ---------------------------------------------------------------------------
1094
- // ASK
1095
- // ---------------------------------------------------------------------------
1096
- /**
1097
- * Run a full RAG query:
1098
- * 1. Embed the user question
1099
- * 2. Retrieve top-K relevant chunks from the vector DB
1100
- * 3. Filter by score threshold
1101
- * 4. Build context string
1102
- * 5. Call the LLM with chat history + context
1103
- */
1104
1645
  async ask(question, history = [], namespace) {
1105
1646
  var _a, _b, _c, _d;
1106
- await this.init();
1647
+ await this.initialize();
1107
1648
  const ns = namespace != null ? namespace : this.config.projectId;
1108
1649
  const topK = (_b = (_a = this.config.rag) == null ? void 0 : _a.topK) != null ? _b : 5;
1109
1650
  const scoreThreshold = (_d = (_c = this.config.rag) == null ? void 0 : _c.scoreThreshold) != null ? _d : 0;
@@ -1112,151 +1653,71 @@ var RAGPipeline = class {
1112
1653
  const sources = rawMatches.filter((m) => m.score >= scoreThreshold);
1113
1654
  const context = sources.length ? sources.map((m, i) => `[Source ${i + 1}]
1114
1655
  ${m.content}`).join("\n\n---\n\n") : "No relevant context found.";
1115
- const messages = [
1116
- ...history,
1117
- { role: "user", content: question }
1118
- ];
1656
+ const messages = [...history, { role: "user", content: question }];
1119
1657
  const reply = await this.llmProvider.chat(messages, context);
1120
1658
  return { reply, sources };
1121
1659
  }
1122
- // ---------------------------------------------------------------------------
1123
- // HEALTH
1124
- // ---------------------------------------------------------------------------
1125
1660
  async health() {
1661
+ await this.initialize();
1126
1662
  const [vectorDB, llm] = await Promise.all([
1127
1663
  this.vectorDB.ping().catch(() => false),
1128
1664
  this.llmProvider.ping().catch(() => false)
1129
1665
  ]);
1130
1666
  return { vectorDB, llm };
1131
1667
  }
1132
- // ---------------------------------------------------------------------------
1133
- // DATA MANAGEMENT
1134
- // ---------------------------------------------------------------------------
1135
- async deleteDocument(docId, namespace) {
1136
- await this.init();
1137
- const ns = namespace != null ? namespace : this.config.projectId;
1138
- await this.vectorDB.delete(docId, ns);
1139
- }
1140
- async deleteProject(namespace) {
1141
- await this.init();
1142
- const ns = namespace != null ? namespace : this.config.projectId;
1143
- await this.vectorDB.deleteNamespace(ns);
1144
- }
1145
1668
  };
1146
1669
 
1147
- // src/config/serverConfig.ts
1148
- var VECTOR_DB_PROVIDERS = ["pinecone", "pgvector", "mongodb", "rest", "universal_rest", "custom"];
1149
- var LLM_PROVIDERS = ["openai", "anthropic", "ollama", "rest", "universal_rest", "custom"];
1150
- var EMBEDDING_PROVIDERS = ["openai", "ollama", "rest", "universal_rest", "custom"];
1151
- function readString(env, name) {
1152
- var _a;
1153
- const value = (_a = env[name]) == null ? void 0 : _a.trim();
1154
- return value ? value : void 0;
1155
- }
1156
- function readNumber(env, name, fallback) {
1157
- const value = env[name];
1158
- if (!value) return fallback;
1159
- const parsed = Number(value);
1160
- if (!Number.isFinite(parsed)) {
1161
- throw new Error(`[getRagConfig] ${name} must be a valid number`);
1670
+ // src/core/VectorPlugin.ts
1671
+ var VectorPlugin = class {
1672
+ /**
1673
+ * Initializes the plugin with the host configuration.
1674
+ * @param hostConfig - Configuration object passed from the host application.
1675
+ */
1676
+ constructor(hostConfig) {
1677
+ this.config = ConfigResolver.resolve(hostConfig);
1678
+ ConfigResolver.validate(this.config);
1679
+ this.pipeline = new Pipeline(this.config);
1162
1680
  }
1163
- return parsed;
1164
- }
1165
- function readEnum(env, name, fallback, allowed) {
1166
- var _a;
1167
- const value = (_a = readString(env, name)) != null ? _a : fallback;
1168
- if (allowed.includes(value)) {
1169
- return value;
1681
+ /**
1682
+ * Get the current resolved configuration.
1683
+ */
1684
+ getConfig() {
1685
+ return this.config;
1170
1686
  }
1171
- throw new Error(`[getRagConfig] ${name} must be one of: ${allowed.join(", ")}`);
1172
- }
1173
- function getRagConfig(env = process.env) {
1174
- 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;
1175
- const projectId = (_b = (_a = readString(env, "RAG_PROJECT_ID")) != null ? _a : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : "default";
1176
- const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
1177
- const llmProvider = readEnum(env, "LLM_PROVIDER", "openai", LLM_PROVIDERS);
1178
- const embeddingProvider = readEnum(env, "EMBEDDING_PROVIDER", "openai", EMBEDDING_PROVIDERS);
1179
- const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 1536);
1180
- const vectorDbOptions = {};
1181
- if (vectorProvider === "pinecone") {
1182
- vectorDbOptions.apiKey = (_c = readString(env, "PINECONE_API_KEY")) != null ? _c : "";
1183
- vectorDbOptions.environment = (_d = readString(env, "PINECONE_ENVIRONMENT")) != null ? _d : "";
1184
- } else if (vectorProvider === "pgvector") {
1185
- vectorDbOptions.connectionString = (_e = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _e : "";
1186
- vectorDbOptions.dimensions = embeddingDimensions;
1187
- } else if (vectorProvider === "rest") {
1188
- vectorDbOptions.baseUrl = (_f = readString(env, "VECTOR_DB_REST_URL")) != null ? _f : "";
1189
- vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { "api-key": readString(env, "VECTOR_DB_REST_API_KEY") } : {};
1190
- } else if (vectorProvider === "universal_rest") {
1191
- vectorDbOptions.baseUrl = (_h = (_g = readString(env, "VECTOR_BASE_URL")) != null ? _g : readString(env, "VECTOR_DB_REST_URL")) != null ? _h : "";
1192
- vectorDbOptions.profile = readString(env, "VECTOR_UNIVERSAL_PROFILE");
1193
- vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { Authorization: `Bearer ${readString(env, "VECTOR_DB_REST_API_KEY")}` } : {};
1194
- } else if (vectorProvider === "mongodb") {
1195
- vectorDbOptions.uri = (_i = readString(env, "MONGODB_URI")) != null ? _i : "";
1196
- vectorDbOptions.database = (_j = readString(env, "MONGODB_DB")) != null ? _j : "";
1197
- vectorDbOptions.collection = (_k = readString(env, "MONGODB_COLLECTION")) != null ? _k : "";
1198
- vectorDbOptions.indexName = (_l = readString(env, "MONGODB_INDEX_NAME")) != null ? _l : "vector_index";
1687
+ /**
1688
+ * Run a chat query.
1689
+ */
1690
+ async chat(message, history = [], namespace) {
1691
+ return this.pipeline.ask(message, history, namespace);
1199
1692
  }
1200
- const llmApiKeyByProvider = {
1201
- openai: readString(env, "OPENAI_API_KEY"),
1202
- anthropic: readString(env, "ANTHROPIC_API_KEY"),
1203
- ollama: void 0,
1204
- universal_rest: readString(env, "LLM_API_KEY")
1205
- };
1206
- const embeddingApiKeyByProvider = {
1207
- openai: readString(env, "OPENAI_API_KEY"),
1208
- ollama: void 0,
1209
- custom: (_m = readString(env, "EMBEDDING_API_KEY")) != null ? _m : readString(env, "OPENAI_API_KEY")
1210
- };
1211
- return {
1212
- projectId,
1213
- vectorDb: {
1214
- provider: vectorProvider,
1215
- indexName: (_n = readString(env, "VECTOR_DB_INDEX")) != null ? _n : "rag-index",
1216
- options: vectorDbOptions
1217
- },
1218
- llm: {
1219
- provider: llmProvider,
1220
- model: (_o = readString(env, "LLM_MODEL")) != null ? _o : "gpt-4o",
1221
- apiKey: (_p = llmApiKeyByProvider[llmProvider]) != null ? _p : "",
1222
- baseUrl: readString(env, "LLM_BASE_URL"),
1223
- systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
1224
- maxTokens: readNumber(env, "LLM_MAX_TOKENS", 1024),
1225
- temperature: readNumber(env, "LLM_TEMPERATURE", 0.7),
1226
- options: {
1227
- profile: readString(env, "LLM_UNIVERSAL_PROFILE")
1228
- }
1229
- },
1230
- embedding: {
1231
- provider: embeddingProvider,
1232
- model: (_q = readString(env, "EMBEDDING_MODEL")) != null ? _q : "text-embedding-3-small",
1233
- apiKey: embeddingApiKeyByProvider[embeddingProvider],
1234
- baseUrl: readString(env, "EMBEDDING_BASE_URL"),
1235
- dimensions: embeddingDimensions,
1236
- options: {
1237
- profile: readString(env, "EMBEDDING_UNIVERSAL_PROFILE")
1238
- }
1239
- },
1240
- ui: {
1241
- title: (_s = (_r = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _r : readString(env, "UI_TITLE")) != null ? _s : "AI Assistant",
1242
- subtitle: (_u = (_t = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _t : readString(env, "UI_SUBTITLE")) != null ? _u : "Powered by RAG",
1243
- primaryColor: (_w = (_v = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _v : readString(env, "UI_PRIMARY_COLOR")) != null ? _w : "#10b981",
1244
- accentColor: (_y = (_x = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _x : readString(env, "UI_ACCENT_COLOR")) != null ? _y : "#3b82f6",
1245
- logoUrl: (_z = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _z : readString(env, "UI_LOGO_URL"),
1246
- placeholder: (_B = (_A = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _A : readString(env, "UI_PLACEHOLDER")) != null ? _B : "Ask me anything\u2026",
1247
- showSources: ((_D = (_C = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _C : readString(env, "UI_SHOW_SOURCES")) != null ? _D : "true") !== "false",
1248
- welcomeMessage: (_F = (_E = readString(env, "NEXT_PUBLIC_WELCOME_MESSAGE")) != null ? _E : readString(env, "UI_WELCOME_MESSAGE")) != null ? _F : "Hello! I'm your AI assistant. Ask me anything about your documents.",
1249
- visualStyle: (_H = (_G = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _G : readString(env, "UI_VISUAL_STYLE")) != null ? _H : "glass",
1250
- borderRadius: (_J = (_I = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _I : readString(env, "UI_BORDER_RADIUS")) != null ? _J : "xl"
1251
- },
1252
- rag: {
1253
- topK: readNumber(env, "RAG_TOP_K", 5),
1254
- scoreThreshold: readNumber(env, "RAG_SCORE_THRESHOLD", 0),
1255
- chunkSize: readNumber(env, "RAG_CHUNK_SIZE", 1e3),
1256
- chunkOverlap: readNumber(env, "RAG_CHUNK_OVERLAP", 200)
1257
- }
1258
- };
1259
- }
1693
+ /**
1694
+ * Ingest documents into the vector database.
1695
+ */
1696
+ async ingest(documents, namespace) {
1697
+ return this.pipeline.ingest(documents, namespace);
1698
+ }
1699
+ /**
1700
+ * Check the health of the connected providers.
1701
+ */
1702
+ async health() {
1703
+ return this.pipeline.health();
1704
+ }
1705
+ };
1706
+
1707
+ // src/server.ts
1708
+ init_BaseVectorProvider();
1709
+ init_PineconeProvider();
1710
+ init_PostgreSQLProvider();
1711
+ init_MongoDBProvider();
1712
+ init_MilvusProvider();
1713
+ init_QdrantProvider();
1714
+ init_ChromaDBProvider();
1715
+ init_RedisProvider();
1716
+ init_WeaviateProvider();
1717
+ init_LLMFactory();
1718
+ init_OpenAIProvider();
1719
+ init_AnthropicProvider();
1720
+ init_OllamaProvider();
1260
1721
 
1261
1722
  // src/handlers/index.ts
1262
1723
  var import_server = require("next/server");
@@ -1321,12 +1782,8 @@ var DocumentParser = class {
1321
1782
  };
1322
1783
 
1323
1784
  // src/handlers/index.ts
1324
- function createChatHandler(config, adapters) {
1325
- let pipeline = null;
1326
- function getPipeline() {
1327
- if (!pipeline) pipeline = new RAGPipeline(config, adapters);
1328
- return pipeline;
1329
- }
1785
+ function createChatHandler(config) {
1786
+ const plugin = new VectorPlugin(config);
1330
1787
  return async function POST(req) {
1331
1788
  try {
1332
1789
  const body = await req.json();
@@ -1334,8 +1791,7 @@ function createChatHandler(config, adapters) {
1334
1791
  if (!(message == null ? void 0 : message.trim())) {
1335
1792
  return import_server.NextResponse.json({ error: "message is required" }, { status: 400 });
1336
1793
  }
1337
- const rag = getPipeline();
1338
- const result = await rag.ask(message, history, namespace);
1794
+ const result = await plugin.chat(message, history, namespace);
1339
1795
  return import_server.NextResponse.json(result);
1340
1796
  } catch (err) {
1341
1797
  const message = err instanceof Error ? err.message : "Internal server error";
@@ -1343,64 +1799,42 @@ function createChatHandler(config, adapters) {
1343
1799
  }
1344
1800
  };
1345
1801
  }
1346
- function createIngestHandler(config, adapters) {
1347
- let pipeline = null;
1348
- function getPipeline() {
1349
- if (!pipeline) pipeline = new RAGPipeline(config, adapters);
1350
- return pipeline;
1351
- }
1802
+ function createIngestHandler(config) {
1803
+ const plugin = new VectorPlugin(config);
1352
1804
  return async function POST(req) {
1353
1805
  try {
1354
1806
  const body = await req.json();
1355
1807
  const { documents, namespace } = body;
1356
1808
  if (!Array.isArray(documents) || documents.length === 0) {
1357
- return import_server.NextResponse.json(
1358
- { error: "documents array is required and must not be empty" },
1359
- { status: 400 }
1360
- );
1809
+ return import_server.NextResponse.json({ error: "documents array is required" }, { status: 400 });
1361
1810
  }
1362
- const rag = getPipeline();
1363
- const results = await rag.ingest(documents, namespace);
1364
- const totalChunks = results.reduce((sum, r) => sum + r.chunksIngested, 0);
1365
- return import_server.NextResponse.json({ results, totalChunks });
1811
+ const results = await plugin.ingest(documents, namespace);
1812
+ return import_server.NextResponse.json({ results });
1366
1813
  } catch (err) {
1367
1814
  const message = err instanceof Error ? err.message : "Internal server error";
1368
1815
  return import_server.NextResponse.json({ error: message }, { status: 500 });
1369
1816
  }
1370
1817
  };
1371
1818
  }
1372
- function createHealthHandler(config, adapters) {
1373
- let pipeline = null;
1374
- function getPipeline() {
1375
- if (!pipeline) pipeline = new RAGPipeline(config, adapters);
1376
- return pipeline;
1377
- }
1819
+ function createHealthHandler(config) {
1820
+ const plugin = new VectorPlugin(config);
1378
1821
  return async function GET() {
1379
1822
  try {
1380
- const rag = getPipeline();
1381
- const health = await rag.health();
1823
+ const health = await plugin.health();
1382
1824
  const status = health.vectorDB && health.llm ? "ok" : "degraded";
1383
1825
  return import_server.NextResponse.json(__spreadProps(__spreadValues({
1384
1826
  status
1385
1827
  }, health), {
1386
- project: config.projectId,
1387
1828
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1388
1829
  }));
1389
1830
  } catch (err) {
1390
1831
  const message = err instanceof Error ? err.message : "Unknown error";
1391
- return import_server.NextResponse.json(
1392
- { status: "error", error: message, timestamp: (/* @__PURE__ */ new Date()).toISOString() },
1393
- { status: 500 }
1394
- );
1832
+ return import_server.NextResponse.json({ status: "error", error: message }, { status: 500 });
1395
1833
  }
1396
1834
  };
1397
1835
  }
1398
- function createUploadHandler(config, adapters) {
1399
- let pipeline = null;
1400
- function getPipeline() {
1401
- if (!pipeline) pipeline = new RAGPipeline(config, adapters);
1402
- return pipeline;
1403
- }
1836
+ function createUploadHandler(config) {
1837
+ const plugin = new VectorPlugin(config);
1404
1838
  return async function POST(req) {
1405
1839
  try {
1406
1840
  const formData = await req.formData();
@@ -1424,15 +1858,8 @@ function createUploadHandler(config, adapters) {
1424
1858
  };
1425
1859
  })
1426
1860
  );
1427
- const rag = getPipeline();
1428
- const results = await rag.ingest(documents, namespace);
1429
- const totalChunks = results.reduce((sum, r) => sum + r.chunksIngested, 0);
1430
- return import_server.NextResponse.json({
1431
- message: "Upload successful",
1432
- filesProcessed: files.length,
1433
- totalChunks,
1434
- results
1435
- });
1861
+ const results = await plugin.ingest(documents, namespace);
1862
+ return import_server.NextResponse.json({ message: "Upload successful", results });
1436
1863
  } catch (err) {
1437
1864
  const message = err instanceof Error ? err.message : "Upload failed";
1438
1865
  return import_server.NextResponse.json({ error: message }, { status: 500 });
@@ -1442,15 +1869,23 @@ function createUploadHandler(config, adapters) {
1442
1869
  // Annotate the CommonJS export names for ESM import in node:
1443
1870
  0 && (module.exports = {
1444
1871
  AnthropicProvider,
1872
+ BaseVectorProvider,
1873
+ ChromaDBProvider,
1874
+ ConfigResolver,
1445
1875
  DocumentChunker,
1446
1876
  LLMFactory,
1447
- MongoDbAdapter,
1877
+ MilvusProvider,
1878
+ MongoDBProvider,
1448
1879
  OllamaProvider,
1449
1880
  OpenAIProvider,
1450
- PgVectorAdapter,
1451
- PineconeAdapter,
1452
- RAGPipeline,
1453
- VectorDBFactory,
1881
+ PineconeProvider,
1882
+ Pipeline,
1883
+ PostgreSQLProvider,
1884
+ ProviderRegistry,
1885
+ QdrantProvider,
1886
+ RedisProvider,
1887
+ VectorPlugin,
1888
+ WeaviateProvider,
1454
1889
  createChatHandler,
1455
1890
  createHealthHandler,
1456
1891
  createIngestHandler,