@retrivora-ai/rag-engine 0.1.3 → 0.1.5

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 (74) hide show
  1. package/dist/ChromaDBProvider-QNI7UCX4.mjs +8 -0
  2. package/dist/DocumentChunker-cfaMidtA.d.mts +93 -0
  3. package/dist/DocumentChunker-cfaMidtA.d.ts +93 -0
  4. package/dist/LLMFactory-JFOY2V4X.mjs +8 -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/PostgreSQLProvider-ISNMD3BE.mjs +8 -0
  9. package/dist/QdrantProvider-LJWOIGES.mjs +8 -0
  10. package/dist/RagConfig-DG_0f8ka.d.mts +145 -0
  11. package/dist/RagConfig-DG_0f8ka.d.ts +145 -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-BP4U4TT5.mjs +548 -0
  18. package/dist/chunk-HUGLYKD6.mjs +84 -0
  19. package/dist/chunk-I4E63NIC.mjs +24 -0
  20. package/dist/chunk-JI6VD5TJ.mjs +387 -0
  21. package/dist/chunk-QEYVWVT5.mjs +102 -0
  22. package/dist/chunk-S5DRHETN.mjs +110 -0
  23. package/dist/{chunk-ZPXLQR5Q.mjs → chunk-UKDXCXW7.mjs} +5 -23
  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 -962
  30. package/dist/handlers/index.mjs +4 -2
  31. package/dist/index.d.mts +4 -3
  32. package/dist/index.d.ts +4 -3
  33. package/dist/index.js +2 -2
  34. package/dist/index.mjs +4 -2
  35. package/dist/server.d.mts +220 -53
  36. package/dist/server.d.ts +220 -53
  37. package/dist/server.js +1531 -1099
  38. package/dist/server.mjs +55 -131
  39. package/package.json +19 -2
  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 +101 -0
  47. package/src/core/ProviderRegistry.ts +71 -0
  48. package/src/core/VectorPlugin.ts +52 -0
  49. package/src/handlers/index.ts +21 -100
  50. package/src/hooks/useRagChat.ts +1 -1
  51. package/src/index.ts +2 -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 +24 -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/RAGPipeline-BmkIv1HD.d.mts +0 -298
  68. package/dist/RAGPipeline-BmkIv1HD.d.ts +0 -298
  69. package/dist/chunk-NVOMLHXW.mjs +0 -1259
  70. package/src/rag/RAGPipeline.ts +0 -200
  71. package/src/vectordb/IVectorDB.ts +0 -75
  72. package/src/vectordb/VectorDBFactory.ts +0 -41
  73. package/src/vectordb/adapters/MongoDbAdapter.ts +0 -175
  74. 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,180 +1639,85 @@ 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;
1110
- console.log(`[RAGPipeline] Searching Pinecone (Namespace: "${ns}", TopK: ${topK})...`);
1111
1651
  const queryVector = await this.embeddingProvider.embed(question);
1112
1652
  const rawMatches = await this.vectorDB.query(queryVector, topK, ns);
1113
- console.log(`[RAGPipeline] Found ${rawMatches.length} raw matches in Pinecone.`);
1114
1653
  const sources = rawMatches.filter((m) => m.score >= scoreThreshold);
1115
- console.log(`[RAGPipeline] ${sources.length} sources remaining after threshold filter (min: ${scoreThreshold}).`);
1116
1654
  const context = sources.length ? sources.map((m, i) => `[Source ${i + 1}]
1117
1655
  ${m.content}`).join("\n\n---\n\n") : "No relevant context found.";
1118
- const messages = [
1119
- ...history,
1120
- { role: "user", content: question }
1121
- ];
1656
+ const messages = [...history, { role: "user", content: question }];
1122
1657
  const reply = await this.llmProvider.chat(messages, context);
1123
1658
  return { reply, sources };
1124
1659
  }
1125
- // ---------------------------------------------------------------------------
1126
- // HEALTH
1127
- // ---------------------------------------------------------------------------
1128
1660
  async health() {
1661
+ await this.initialize();
1129
1662
  const [vectorDB, llm] = await Promise.all([
1130
1663
  this.vectorDB.ping().catch(() => false),
1131
1664
  this.llmProvider.ping().catch(() => false)
1132
1665
  ]);
1133
1666
  return { vectorDB, llm };
1134
1667
  }
1135
- // ---------------------------------------------------------------------------
1136
- // DATA MANAGEMENT
1137
- // ---------------------------------------------------------------------------
1138
- async deleteDocument(docId, namespace) {
1139
- await this.init();
1140
- const ns = namespace != null ? namespace : this.config.projectId;
1141
- await this.vectorDB.delete(docId, ns);
1142
- }
1143
- async deleteProject(namespace) {
1144
- await this.init();
1145
- const ns = namespace != null ? namespace : this.config.projectId;
1146
- await this.vectorDB.deleteNamespace(ns);
1147
- }
1148
1668
  };
1149
1669
 
1150
- // src/config/serverConfig.ts
1151
- var VECTOR_DB_PROVIDERS = ["pinecone", "pgvector", "mongodb", "rest", "universal_rest", "custom"];
1152
- var LLM_PROVIDERS = ["openai", "anthropic", "ollama", "rest", "universal_rest", "custom"];
1153
- var EMBEDDING_PROVIDERS = ["openai", "ollama", "rest", "universal_rest", "custom"];
1154
- function readString(env, name) {
1155
- var _a;
1156
- const value = (_a = env[name]) == null ? void 0 : _a.trim();
1157
- return value ? value : void 0;
1158
- }
1159
- function readNumber(env, name, fallback) {
1160
- const value = env[name];
1161
- if (!value) return fallback;
1162
- const parsed = Number(value);
1163
- if (!Number.isFinite(parsed)) {
1164
- 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);
1165
1680
  }
1166
- return parsed;
1167
- }
1168
- function readEnum(env, name, fallback, allowed) {
1169
- var _a;
1170
- const value = (_a = readString(env, name)) != null ? _a : fallback;
1171
- if (allowed.includes(value)) {
1172
- return value;
1681
+ /**
1682
+ * Get the current resolved configuration.
1683
+ */
1684
+ getConfig() {
1685
+ return this.config;
1173
1686
  }
1174
- throw new Error(`[getRagConfig] ${name} must be one of: ${allowed.join(", ")}`);
1175
- }
1176
- function getRagConfig(env = process.env) {
1177
- 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;
1178
- const projectId = (_b = (_a = readString(env, "RAG_PROJECT_ID")) != null ? _a : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : "default";
1179
- const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
1180
- const llmProvider = readEnum(env, "LLM_PROVIDER", "openai", LLM_PROVIDERS);
1181
- const embeddingProvider = readEnum(env, "EMBEDDING_PROVIDER", "openai", EMBEDDING_PROVIDERS);
1182
- const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 1536);
1183
- const vectorDbOptions = {};
1184
- if (vectorProvider === "pinecone") {
1185
- vectorDbOptions.apiKey = (_c = readString(env, "PINECONE_API_KEY")) != null ? _c : "";
1186
- vectorDbOptions.environment = (_d = readString(env, "PINECONE_ENVIRONMENT")) != null ? _d : "";
1187
- } else if (vectorProvider === "pgvector") {
1188
- vectorDbOptions.connectionString = (_e = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _e : "";
1189
- vectorDbOptions.dimensions = embeddingDimensions;
1190
- } else if (vectorProvider === "rest") {
1191
- vectorDbOptions.baseUrl = (_f = readString(env, "VECTOR_DB_REST_URL")) != null ? _f : "";
1192
- vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { "api-key": readString(env, "VECTOR_DB_REST_API_KEY") } : {};
1193
- } else if (vectorProvider === "universal_rest") {
1194
- vectorDbOptions.baseUrl = (_h = (_g = readString(env, "VECTOR_BASE_URL")) != null ? _g : readString(env, "VECTOR_DB_REST_URL")) != null ? _h : "";
1195
- vectorDbOptions.profile = readString(env, "VECTOR_UNIVERSAL_PROFILE");
1196
- vectorDbOptions.headers = readString(env, "VECTOR_DB_REST_API_KEY") ? { Authorization: `Bearer ${readString(env, "VECTOR_DB_REST_API_KEY")}` } : {};
1197
- } else if (vectorProvider === "mongodb") {
1198
- vectorDbOptions.uri = (_i = readString(env, "MONGODB_URI")) != null ? _i : "";
1199
- vectorDbOptions.database = (_j = readString(env, "MONGODB_DB")) != null ? _j : "";
1200
- vectorDbOptions.collection = (_k = readString(env, "MONGODB_COLLECTION")) != null ? _k : "";
1201
- 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);
1202
1692
  }
1203
- const llmApiKeyByProvider = {
1204
- openai: readString(env, "OPENAI_API_KEY"),
1205
- anthropic: readString(env, "ANTHROPIC_API_KEY"),
1206
- ollama: void 0,
1207
- universal_rest: readString(env, "LLM_API_KEY")
1208
- };
1209
- const embeddingApiKeyByProvider = {
1210
- openai: readString(env, "OPENAI_API_KEY"),
1211
- ollama: void 0,
1212
- custom: (_m = readString(env, "EMBEDDING_API_KEY")) != null ? _m : readString(env, "OPENAI_API_KEY")
1213
- };
1214
- return {
1215
- projectId,
1216
- vectorDb: {
1217
- provider: vectorProvider,
1218
- indexName: (_n = readString(env, "VECTOR_DB_INDEX")) != null ? _n : "rag-index",
1219
- options: vectorDbOptions
1220
- },
1221
- llm: {
1222
- provider: llmProvider,
1223
- model: (_o = readString(env, "LLM_MODEL")) != null ? _o : "gpt-4o",
1224
- apiKey: (_p = llmApiKeyByProvider[llmProvider]) != null ? _p : "",
1225
- baseUrl: readString(env, "LLM_BASE_URL"),
1226
- systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
1227
- maxTokens: readNumber(env, "LLM_MAX_TOKENS", 1024),
1228
- temperature: readNumber(env, "LLM_TEMPERATURE", 0.7),
1229
- options: {
1230
- profile: readString(env, "LLM_UNIVERSAL_PROFILE")
1231
- }
1232
- },
1233
- embedding: {
1234
- provider: embeddingProvider,
1235
- model: (_q = readString(env, "EMBEDDING_MODEL")) != null ? _q : "text-embedding-3-small",
1236
- apiKey: embeddingApiKeyByProvider[embeddingProvider],
1237
- baseUrl: readString(env, "EMBEDDING_BASE_URL"),
1238
- dimensions: embeddingDimensions,
1239
- options: {
1240
- profile: readString(env, "EMBEDDING_UNIVERSAL_PROFILE")
1241
- }
1242
- },
1243
- ui: {
1244
- title: (_s = (_r = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _r : readString(env, "UI_TITLE")) != null ? _s : "AI Assistant",
1245
- subtitle: (_u = (_t = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _t : readString(env, "UI_SUBTITLE")) != null ? _u : "Powered by RAG",
1246
- primaryColor: (_w = (_v = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _v : readString(env, "UI_PRIMARY_COLOR")) != null ? _w : "#10b981",
1247
- accentColor: (_y = (_x = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _x : readString(env, "UI_ACCENT_COLOR")) != null ? _y : "#3b82f6",
1248
- logoUrl: (_z = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _z : readString(env, "UI_LOGO_URL"),
1249
- placeholder: (_B = (_A = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _A : readString(env, "UI_PLACEHOLDER")) != null ? _B : "Ask me anything\u2026",
1250
- showSources: ((_D = (_C = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _C : readString(env, "UI_SHOW_SOURCES")) != null ? _D : "true") !== "false",
1251
- 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.",
1252
- visualStyle: (_H = (_G = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _G : readString(env, "UI_VISUAL_STYLE")) != null ? _H : "glass",
1253
- borderRadius: (_J = (_I = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _I : readString(env, "UI_BORDER_RADIUS")) != null ? _J : "xl"
1254
- },
1255
- rag: {
1256
- topK: readNumber(env, "RAG_TOP_K", 5),
1257
- scoreThreshold: readNumber(env, "RAG_SCORE_THRESHOLD", 0),
1258
- chunkSize: readNumber(env, "RAG_CHUNK_SIZE", 1e3),
1259
- chunkOverlap: readNumber(env, "RAG_CHUNK_OVERLAP", 200)
1260
- }
1261
- };
1262
- }
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();
1263
1721
 
1264
1722
  // src/handlers/index.ts
1265
1723
  var import_server = require("next/server");
@@ -1324,12 +1782,8 @@ var DocumentParser = class {
1324
1782
  };
1325
1783
 
1326
1784
  // src/handlers/index.ts
1327
- function createChatHandler(config, adapters) {
1328
- let pipeline = null;
1329
- function getPipeline() {
1330
- if (!pipeline) pipeline = new RAGPipeline(config, adapters);
1331
- return pipeline;
1332
- }
1785
+ function createChatHandler(config) {
1786
+ const plugin = new VectorPlugin(config);
1333
1787
  return async function POST(req) {
1334
1788
  try {
1335
1789
  const body = await req.json();
@@ -1337,8 +1791,7 @@ function createChatHandler(config, adapters) {
1337
1791
  if (!(message == null ? void 0 : message.trim())) {
1338
1792
  return import_server.NextResponse.json({ error: "message is required" }, { status: 400 });
1339
1793
  }
1340
- const rag = getPipeline();
1341
- const result = await rag.ask(message, history, namespace);
1794
+ const result = await plugin.chat(message, history, namespace);
1342
1795
  return import_server.NextResponse.json(result);
1343
1796
  } catch (err) {
1344
1797
  const message = err instanceof Error ? err.message : "Internal server error";
@@ -1346,64 +1799,42 @@ function createChatHandler(config, adapters) {
1346
1799
  }
1347
1800
  };
1348
1801
  }
1349
- function createIngestHandler(config, adapters) {
1350
- let pipeline = null;
1351
- function getPipeline() {
1352
- if (!pipeline) pipeline = new RAGPipeline(config, adapters);
1353
- return pipeline;
1354
- }
1802
+ function createIngestHandler(config) {
1803
+ const plugin = new VectorPlugin(config);
1355
1804
  return async function POST(req) {
1356
1805
  try {
1357
1806
  const body = await req.json();
1358
1807
  const { documents, namespace } = body;
1359
1808
  if (!Array.isArray(documents) || documents.length === 0) {
1360
- return import_server.NextResponse.json(
1361
- { error: "documents array is required and must not be empty" },
1362
- { status: 400 }
1363
- );
1809
+ return import_server.NextResponse.json({ error: "documents array is required" }, { status: 400 });
1364
1810
  }
1365
- const rag = getPipeline();
1366
- const results = await rag.ingest(documents, namespace);
1367
- const totalChunks = results.reduce((sum, r) => sum + r.chunksIngested, 0);
1368
- return import_server.NextResponse.json({ results, totalChunks });
1811
+ const results = await plugin.ingest(documents, namespace);
1812
+ return import_server.NextResponse.json({ results });
1369
1813
  } catch (err) {
1370
1814
  const message = err instanceof Error ? err.message : "Internal server error";
1371
1815
  return import_server.NextResponse.json({ error: message }, { status: 500 });
1372
1816
  }
1373
1817
  };
1374
1818
  }
1375
- function createHealthHandler(config, adapters) {
1376
- let pipeline = null;
1377
- function getPipeline() {
1378
- if (!pipeline) pipeline = new RAGPipeline(config, adapters);
1379
- return pipeline;
1380
- }
1819
+ function createHealthHandler(config) {
1820
+ const plugin = new VectorPlugin(config);
1381
1821
  return async function GET() {
1382
1822
  try {
1383
- const rag = getPipeline();
1384
- const health = await rag.health();
1823
+ const health = await plugin.health();
1385
1824
  const status = health.vectorDB && health.llm ? "ok" : "degraded";
1386
1825
  return import_server.NextResponse.json(__spreadProps(__spreadValues({
1387
1826
  status
1388
1827
  }, health), {
1389
- project: config.projectId,
1390
1828
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1391
1829
  }));
1392
1830
  } catch (err) {
1393
1831
  const message = err instanceof Error ? err.message : "Unknown error";
1394
- return import_server.NextResponse.json(
1395
- { status: "error", error: message, timestamp: (/* @__PURE__ */ new Date()).toISOString() },
1396
- { status: 500 }
1397
- );
1832
+ return import_server.NextResponse.json({ status: "error", error: message }, { status: 500 });
1398
1833
  }
1399
1834
  };
1400
1835
  }
1401
- function createUploadHandler(config, adapters) {
1402
- let pipeline = null;
1403
- function getPipeline() {
1404
- if (!pipeline) pipeline = new RAGPipeline(config, adapters);
1405
- return pipeline;
1406
- }
1836
+ function createUploadHandler(config) {
1837
+ const plugin = new VectorPlugin(config);
1407
1838
  return async function POST(req) {
1408
1839
  try {
1409
1840
  const formData = await req.formData();
@@ -1427,15 +1858,8 @@ function createUploadHandler(config, adapters) {
1427
1858
  };
1428
1859
  })
1429
1860
  );
1430
- const rag = getPipeline();
1431
- const results = await rag.ingest(documents, namespace);
1432
- const totalChunks = results.reduce((sum, r) => sum + r.chunksIngested, 0);
1433
- return import_server.NextResponse.json({
1434
- message: "Upload successful",
1435
- filesProcessed: files.length,
1436
- totalChunks,
1437
- results
1438
- });
1861
+ const results = await plugin.ingest(documents, namespace);
1862
+ return import_server.NextResponse.json({ message: "Upload successful", results });
1439
1863
  } catch (err) {
1440
1864
  const message = err instanceof Error ? err.message : "Upload failed";
1441
1865
  return import_server.NextResponse.json({ error: message }, { status: 500 });
@@ -1445,15 +1869,23 @@ function createUploadHandler(config, adapters) {
1445
1869
  // Annotate the CommonJS export names for ESM import in node:
1446
1870
  0 && (module.exports = {
1447
1871
  AnthropicProvider,
1872
+ BaseVectorProvider,
1873
+ ChromaDBProvider,
1874
+ ConfigResolver,
1448
1875
  DocumentChunker,
1449
1876
  LLMFactory,
1450
- MongoDbAdapter,
1877
+ MilvusProvider,
1878
+ MongoDBProvider,
1451
1879
  OllamaProvider,
1452
1880
  OpenAIProvider,
1453
- PgVectorAdapter,
1454
- PineconeAdapter,
1455
- RAGPipeline,
1456
- VectorDBFactory,
1881
+ PineconeProvider,
1882
+ Pipeline,
1883
+ PostgreSQLProvider,
1884
+ ProviderRegistry,
1885
+ QdrantProvider,
1886
+ RedisProvider,
1887
+ VectorPlugin,
1888
+ WeaviateProvider,
1457
1889
  createChatHandler,
1458
1890
  createHealthHandler,
1459
1891
  createIngestHandler,