@retrivora-ai/rag-engine 2.1.9 → 2.2.0
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.
- package/dist/handlers/index.js +122 -15
- package/dist/handlers/index.mjs +122 -15
- package/dist/server.d.mts +3 -3
- package/dist/server.d.ts +3 -3
- package/dist/server.js +122 -15
- package/dist/server.mjs +122 -15
- package/package.json +1 -1
- package/src/config/serverConfig.ts +4 -1
- package/src/core/ConfigFetcher.ts +112 -0
- package/src/providers/vectordb/BaseVectorProvider.ts +1 -1
- package/src/providers/vectordb/PineconeProvider.ts +49 -15
package/dist/handlers/index.js
CHANGED
|
@@ -793,6 +793,84 @@ var init_BaseVectorProvider = __esm({
|
|
|
793
793
|
}
|
|
794
794
|
});
|
|
795
795
|
|
|
796
|
+
// src/core/ConfigFetcher.ts
|
|
797
|
+
var ConfigFetcher;
|
|
798
|
+
var init_ConfigFetcher = __esm({
|
|
799
|
+
"src/core/ConfigFetcher.ts"() {
|
|
800
|
+
"use strict";
|
|
801
|
+
ConfigFetcher = class {
|
|
802
|
+
// 5-minute in-memory session cache
|
|
803
|
+
/**
|
|
804
|
+
* Fetch full project configuration (vectorDb + embedding + llm) from Retrivora Control Plane.
|
|
805
|
+
*/
|
|
806
|
+
static async fetchRemoteConfig(projectId, licenseKey) {
|
|
807
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
|
|
808
|
+
const cacheKey = `${projectId}:${licenseKey || ""}`;
|
|
809
|
+
const now = Date.now();
|
|
810
|
+
const cached = this.cache.get(cacheKey);
|
|
811
|
+
if (cached && now - cached.cachedAt < this.TTL_MS) {
|
|
812
|
+
return cached.config;
|
|
813
|
+
}
|
|
814
|
+
const controlPlaneUrls = [
|
|
815
|
+
process.env.RETRIVORA_CONTROL_PLANE_URL,
|
|
816
|
+
process.env.NEXT_PUBLIC_RETRIVORA_CONTROL_PLANE_URL,
|
|
817
|
+
"https://retrivora.com",
|
|
818
|
+
"http://localhost:3000"
|
|
819
|
+
].filter(Boolean);
|
|
820
|
+
for (const baseUrl of controlPlaneUrls) {
|
|
821
|
+
try {
|
|
822
|
+
const url = `${baseUrl.replace(/\/$/, "")}/api/v1/config?projectId=${encodeURIComponent(projectId)}${licenseKey ? `&licenseKey=${encodeURIComponent(licenseKey)}` : ""}`;
|
|
823
|
+
const res = await fetch(url, {
|
|
824
|
+
method: "GET",
|
|
825
|
+
headers: __spreadValues({
|
|
826
|
+
"Content-Type": "application/json"
|
|
827
|
+
}, licenseKey ? { "x-license-key": licenseKey } : {})
|
|
828
|
+
});
|
|
829
|
+
if (res.ok) {
|
|
830
|
+
const data = await res.json();
|
|
831
|
+
if ((data == null ? void 0 : data.success) && ((_a2 = data == null ? void 0 : data.vectorDb) == null ? void 0 : _a2.apiKey)) {
|
|
832
|
+
const config = {
|
|
833
|
+
vectorDb: {
|
|
834
|
+
apiKey: data.vectorDb.apiKey,
|
|
835
|
+
indexName: data.vectorDb.indexName || "retrivora-free",
|
|
836
|
+
provider: data.vectorDb.provider || "pinecone"
|
|
837
|
+
},
|
|
838
|
+
embedding: {
|
|
839
|
+
provider: ((_b = data.embedding) == null ? void 0 : _b.provider) || "universal_rest",
|
|
840
|
+
model: ((_c = data.embedding) == null ? void 0 : _c.model) || "text-embedding-004",
|
|
841
|
+
baseUrl: ((_d = data.embedding) == null ? void 0 : _d.baseUrl) || "https://llm.retrivora.com/api/v1",
|
|
842
|
+
apiKey: ((_e = data.embedding) == null ? void 0 : _e.apiKey) || licenseKey || "",
|
|
843
|
+
profile: ((_f = data.embedding) == null ? void 0 : _f.profile) || "litellm"
|
|
844
|
+
},
|
|
845
|
+
llm: {
|
|
846
|
+
provider: ((_g2 = data.llm) == null ? void 0 : _g2.provider) || "universal_rest",
|
|
847
|
+
model: ((_h = data.llm) == null ? void 0 : _h.model) || "llama-3.1-8b-instant",
|
|
848
|
+
baseUrl: ((_i = data.llm) == null ? void 0 : _i.baseUrl) || "https://llm.retrivora.com/api/v1",
|
|
849
|
+
apiKey: ((_j = data.llm) == null ? void 0 : _j.apiKey) || licenseKey || "",
|
|
850
|
+
profile: ((_k = data.llm) == null ? void 0 : _k.profile) || "litellm"
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
this.cache.set(cacheKey, { config, cachedAt: now });
|
|
854
|
+
return config;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
} catch (e) {
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
return null;
|
|
861
|
+
}
|
|
862
|
+
/** Convenience: fetch only vector DB config (backwards compat). */
|
|
863
|
+
static async fetchRemoteVectorConfig(projectId, licenseKey) {
|
|
864
|
+
var _a2;
|
|
865
|
+
const config = await this.fetchRemoteConfig(projectId, licenseKey);
|
|
866
|
+
return (_a2 = config == null ? void 0 : config.vectorDb) != null ? _a2 : null;
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
ConfigFetcher.cache = /* @__PURE__ */ new Map();
|
|
870
|
+
ConfigFetcher.TTL_MS = 5 * 60 * 1e3;
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
|
|
796
874
|
// src/providers/vectordb/PineconeProvider.ts
|
|
797
875
|
var PineconeProvider_exports = {};
|
|
798
876
|
__export(PineconeProvider_exports, {
|
|
@@ -804,6 +882,7 @@ var init_PineconeProvider = __esm({
|
|
|
804
882
|
"use strict";
|
|
805
883
|
import_pinecone = require("@pinecone-database/pinecone");
|
|
806
884
|
init_BaseVectorProvider();
|
|
885
|
+
init_ConfigFetcher();
|
|
807
886
|
PineconeProvider = class extends BaseVectorProvider {
|
|
808
887
|
constructor(config) {
|
|
809
888
|
super(config);
|
|
@@ -869,27 +948,49 @@ var init_PineconeProvider = __esm({
|
|
|
869
948
|
}
|
|
870
949
|
async initialize() {
|
|
871
950
|
var _a2, _b;
|
|
872
|
-
|
|
951
|
+
if (this.client) return;
|
|
952
|
+
let key = this.apiKey || process.env.PINECONE_API_KEY || "";
|
|
953
|
+
if (!key) {
|
|
954
|
+
const projectId = process.env.RAG_PROJECT_ID || process.env.NEXT_PUBLIC_RAG_PROJECT_ID || "my-rag-app";
|
|
955
|
+
const licenseKey = process.env.RETRIVORA_LICENSE_KEY || process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY;
|
|
956
|
+
const remoteConfig = await ConfigFetcher.fetchRemoteVectorConfig(projectId, licenseKey);
|
|
957
|
+
if (remoteConfig == null ? void 0 : remoteConfig.apiKey) {
|
|
958
|
+
key = remoteConfig.apiKey;
|
|
959
|
+
this.apiKey = key;
|
|
960
|
+
if (remoteConfig.indexName) {
|
|
961
|
+
this.indexName = remoteConfig.indexName;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
873
965
|
if (!key) {
|
|
874
|
-
console.
|
|
966
|
+
console.warn("[PineconeProvider] Warning: No Pinecone API key available locally or remotely.");
|
|
875
967
|
return;
|
|
876
968
|
}
|
|
877
969
|
this.client = new import_pinecone.Pinecone({ apiKey: key });
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
`[PineconeProvider]
|
|
883
|
-
|
|
970
|
+
try {
|
|
971
|
+
const indexes = await this.client.listIndexes();
|
|
972
|
+
const names = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
|
|
973
|
+
if (!names.includes(this.indexName)) {
|
|
974
|
+
console.warn(`[PineconeProvider] Target index "${this.indexName}" not listed. Proceeding with configured index name.`);
|
|
975
|
+
}
|
|
976
|
+
} catch (err) {
|
|
977
|
+
console.warn("[PineconeProvider] List index verification warning:", err instanceof Error ? err.message : String(err));
|
|
884
978
|
}
|
|
885
979
|
}
|
|
886
|
-
|
|
980
|
+
async getActiveIndex(namespace) {
|
|
981
|
+
if (!this.client) {
|
|
982
|
+
await this.initialize();
|
|
983
|
+
}
|
|
984
|
+
if (!this.client) {
|
|
985
|
+
throw new Error("[PineconeProvider] Cannot execute vector operation: Pinecone client failed to initialize.");
|
|
986
|
+
}
|
|
887
987
|
const idx = this.client.index(this.indexName);
|
|
888
988
|
return namespace ? idx.namespace(namespace) : idx.namespace("");
|
|
889
989
|
}
|
|
890
990
|
async upsert(doc, namespace) {
|
|
891
991
|
var _a2;
|
|
892
|
-
await this.
|
|
992
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
993
|
+
await targetIdx.upsert({
|
|
893
994
|
records: [{
|
|
894
995
|
id: String(doc.id),
|
|
895
996
|
values: doc.vector,
|
|
@@ -898,6 +999,7 @@ var init_PineconeProvider = __esm({
|
|
|
898
999
|
});
|
|
899
1000
|
}
|
|
900
1001
|
async batchUpsert(docs, namespace) {
|
|
1002
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
901
1003
|
const BATCH = 100;
|
|
902
1004
|
for (let i = 0; i < docs.length; i += BATCH) {
|
|
903
1005
|
const records = docs.slice(i, i + BATCH).map((d) => {
|
|
@@ -908,13 +1010,14 @@ var init_PineconeProvider = __esm({
|
|
|
908
1010
|
metadata: __spreadValues({ content: d.content }, (_a2 = d.metadata) != null ? _a2 : {})
|
|
909
1011
|
};
|
|
910
1012
|
});
|
|
911
|
-
await
|
|
1013
|
+
await targetIdx.upsert({ records });
|
|
912
1014
|
}
|
|
913
1015
|
}
|
|
914
1016
|
async query(vector, topK, namespace, filter) {
|
|
915
1017
|
var _a2;
|
|
1018
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
916
1019
|
const pineconeFilter = this.sanitizeFilter(filter);
|
|
917
|
-
const result = await
|
|
1020
|
+
const result = await targetIdx.query(__spreadValues({
|
|
918
1021
|
vector,
|
|
919
1022
|
topK,
|
|
920
1023
|
includeMetadata: true
|
|
@@ -930,13 +1033,17 @@ var init_PineconeProvider = __esm({
|
|
|
930
1033
|
});
|
|
931
1034
|
}
|
|
932
1035
|
async delete(id, namespace) {
|
|
933
|
-
await this.
|
|
1036
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
1037
|
+
await targetIdx.deleteOne({ id: String(id) });
|
|
934
1038
|
}
|
|
935
1039
|
async deleteNamespace(namespace) {
|
|
936
|
-
await this.
|
|
1040
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
1041
|
+
await targetIdx.deleteAll();
|
|
937
1042
|
}
|
|
938
1043
|
async ping() {
|
|
939
1044
|
try {
|
|
1045
|
+
if (!this.client) await this.initialize();
|
|
1046
|
+
if (!this.client) return false;
|
|
940
1047
|
await this.client.listIndexes();
|
|
941
1048
|
return true;
|
|
942
1049
|
} catch (e) {
|
|
@@ -3167,7 +3274,7 @@ function getEnvConfig(env = process.env, base) {
|
|
|
3167
3274
|
return true;
|
|
3168
3275
|
}
|
|
3169
3276
|
})();
|
|
3170
|
-
const defaultGatewayUrl = (_pa = (_oa = readString(env, "LITELLM_BASE_URL")) != null ? _oa : readString(env, "LLM_BASE_URL")) != null ? _pa : "https://
|
|
3277
|
+
const defaultGatewayUrl = (_pa = (_oa = readString(env, "LITELLM_BASE_URL")) != null ? _oa : readString(env, "LLM_BASE_URL")) != null ? _pa : "https://retrivora.com/api/v1";
|
|
3171
3278
|
const defaultLlmProvider = isFreeTier ? "universal_rest" : "universal_rest";
|
|
3172
3279
|
const llmProvider = (_sa = (_ra = readEnum(env, "LLM_PROVIDER", defaultLlmProvider, LLM_PROVIDERS)) != null ? _ra : (_qa = base == null ? void 0 : base.llm) == null ? void 0 : _qa.provider) != null ? _sa : defaultLlmProvider;
|
|
3173
3280
|
const llmBaseUrl = (_wa = (_va = (_ta = readString(env, "LITELLM_BASE_URL")) != null ? _ta : readString(env, "LLM_BASE_URL")) != null ? _va : (_ua = base == null ? void 0 : base.llm) == null ? void 0 : _ua.baseUrl) != null ? _wa : defaultGatewayUrl;
|
package/dist/handlers/index.mjs
CHANGED
|
@@ -778,6 +778,84 @@ var init_BaseVectorProvider = __esm({
|
|
|
778
778
|
}
|
|
779
779
|
});
|
|
780
780
|
|
|
781
|
+
// src/core/ConfigFetcher.ts
|
|
782
|
+
var ConfigFetcher;
|
|
783
|
+
var init_ConfigFetcher = __esm({
|
|
784
|
+
"src/core/ConfigFetcher.ts"() {
|
|
785
|
+
"use strict";
|
|
786
|
+
ConfigFetcher = class {
|
|
787
|
+
// 5-minute in-memory session cache
|
|
788
|
+
/**
|
|
789
|
+
* Fetch full project configuration (vectorDb + embedding + llm) from Retrivora Control Plane.
|
|
790
|
+
*/
|
|
791
|
+
static async fetchRemoteConfig(projectId, licenseKey) {
|
|
792
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
|
|
793
|
+
const cacheKey = `${projectId}:${licenseKey || ""}`;
|
|
794
|
+
const now = Date.now();
|
|
795
|
+
const cached = this.cache.get(cacheKey);
|
|
796
|
+
if (cached && now - cached.cachedAt < this.TTL_MS) {
|
|
797
|
+
return cached.config;
|
|
798
|
+
}
|
|
799
|
+
const controlPlaneUrls = [
|
|
800
|
+
process.env.RETRIVORA_CONTROL_PLANE_URL,
|
|
801
|
+
process.env.NEXT_PUBLIC_RETRIVORA_CONTROL_PLANE_URL,
|
|
802
|
+
"https://retrivora.com",
|
|
803
|
+
"http://localhost:3000"
|
|
804
|
+
].filter(Boolean);
|
|
805
|
+
for (const baseUrl of controlPlaneUrls) {
|
|
806
|
+
try {
|
|
807
|
+
const url = `${baseUrl.replace(/\/$/, "")}/api/v1/config?projectId=${encodeURIComponent(projectId)}${licenseKey ? `&licenseKey=${encodeURIComponent(licenseKey)}` : ""}`;
|
|
808
|
+
const res = await fetch(url, {
|
|
809
|
+
method: "GET",
|
|
810
|
+
headers: __spreadValues({
|
|
811
|
+
"Content-Type": "application/json"
|
|
812
|
+
}, licenseKey ? { "x-license-key": licenseKey } : {})
|
|
813
|
+
});
|
|
814
|
+
if (res.ok) {
|
|
815
|
+
const data = await res.json();
|
|
816
|
+
if ((data == null ? void 0 : data.success) && ((_a2 = data == null ? void 0 : data.vectorDb) == null ? void 0 : _a2.apiKey)) {
|
|
817
|
+
const config = {
|
|
818
|
+
vectorDb: {
|
|
819
|
+
apiKey: data.vectorDb.apiKey,
|
|
820
|
+
indexName: data.vectorDb.indexName || "retrivora-free",
|
|
821
|
+
provider: data.vectorDb.provider || "pinecone"
|
|
822
|
+
},
|
|
823
|
+
embedding: {
|
|
824
|
+
provider: ((_b = data.embedding) == null ? void 0 : _b.provider) || "universal_rest",
|
|
825
|
+
model: ((_c = data.embedding) == null ? void 0 : _c.model) || "text-embedding-004",
|
|
826
|
+
baseUrl: ((_d = data.embedding) == null ? void 0 : _d.baseUrl) || "https://llm.retrivora.com/api/v1",
|
|
827
|
+
apiKey: ((_e = data.embedding) == null ? void 0 : _e.apiKey) || licenseKey || "",
|
|
828
|
+
profile: ((_f = data.embedding) == null ? void 0 : _f.profile) || "litellm"
|
|
829
|
+
},
|
|
830
|
+
llm: {
|
|
831
|
+
provider: ((_g2 = data.llm) == null ? void 0 : _g2.provider) || "universal_rest",
|
|
832
|
+
model: ((_h = data.llm) == null ? void 0 : _h.model) || "llama-3.1-8b-instant",
|
|
833
|
+
baseUrl: ((_i = data.llm) == null ? void 0 : _i.baseUrl) || "https://llm.retrivora.com/api/v1",
|
|
834
|
+
apiKey: ((_j = data.llm) == null ? void 0 : _j.apiKey) || licenseKey || "",
|
|
835
|
+
profile: ((_k = data.llm) == null ? void 0 : _k.profile) || "litellm"
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
this.cache.set(cacheKey, { config, cachedAt: now });
|
|
839
|
+
return config;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
} catch (e) {
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
return null;
|
|
846
|
+
}
|
|
847
|
+
/** Convenience: fetch only vector DB config (backwards compat). */
|
|
848
|
+
static async fetchRemoteVectorConfig(projectId, licenseKey) {
|
|
849
|
+
var _a2;
|
|
850
|
+
const config = await this.fetchRemoteConfig(projectId, licenseKey);
|
|
851
|
+
return (_a2 = config == null ? void 0 : config.vectorDb) != null ? _a2 : null;
|
|
852
|
+
}
|
|
853
|
+
};
|
|
854
|
+
ConfigFetcher.cache = /* @__PURE__ */ new Map();
|
|
855
|
+
ConfigFetcher.TTL_MS = 5 * 60 * 1e3;
|
|
856
|
+
}
|
|
857
|
+
});
|
|
858
|
+
|
|
781
859
|
// src/providers/vectordb/PineconeProvider.ts
|
|
782
860
|
var PineconeProvider_exports = {};
|
|
783
861
|
__export(PineconeProvider_exports, {
|
|
@@ -789,6 +867,7 @@ var init_PineconeProvider = __esm({
|
|
|
789
867
|
"src/providers/vectordb/PineconeProvider.ts"() {
|
|
790
868
|
"use strict";
|
|
791
869
|
init_BaseVectorProvider();
|
|
870
|
+
init_ConfigFetcher();
|
|
792
871
|
PineconeProvider = class extends BaseVectorProvider {
|
|
793
872
|
constructor(config) {
|
|
794
873
|
super(config);
|
|
@@ -854,27 +933,49 @@ var init_PineconeProvider = __esm({
|
|
|
854
933
|
}
|
|
855
934
|
async initialize() {
|
|
856
935
|
var _a2, _b;
|
|
857
|
-
|
|
936
|
+
if (this.client) return;
|
|
937
|
+
let key = this.apiKey || process.env.PINECONE_API_KEY || "";
|
|
938
|
+
if (!key) {
|
|
939
|
+
const projectId = process.env.RAG_PROJECT_ID || process.env.NEXT_PUBLIC_RAG_PROJECT_ID || "my-rag-app";
|
|
940
|
+
const licenseKey = process.env.RETRIVORA_LICENSE_KEY || process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY;
|
|
941
|
+
const remoteConfig = await ConfigFetcher.fetchRemoteVectorConfig(projectId, licenseKey);
|
|
942
|
+
if (remoteConfig == null ? void 0 : remoteConfig.apiKey) {
|
|
943
|
+
key = remoteConfig.apiKey;
|
|
944
|
+
this.apiKey = key;
|
|
945
|
+
if (remoteConfig.indexName) {
|
|
946
|
+
this.indexName = remoteConfig.indexName;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
858
950
|
if (!key) {
|
|
859
|
-
console.
|
|
951
|
+
console.warn("[PineconeProvider] Warning: No Pinecone API key available locally or remotely.");
|
|
860
952
|
return;
|
|
861
953
|
}
|
|
862
954
|
this.client = new Pinecone({ apiKey: key });
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
`[PineconeProvider]
|
|
868
|
-
|
|
955
|
+
try {
|
|
956
|
+
const indexes = await this.client.listIndexes();
|
|
957
|
+
const names = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
|
|
958
|
+
if (!names.includes(this.indexName)) {
|
|
959
|
+
console.warn(`[PineconeProvider] Target index "${this.indexName}" not listed. Proceeding with configured index name.`);
|
|
960
|
+
}
|
|
961
|
+
} catch (err) {
|
|
962
|
+
console.warn("[PineconeProvider] List index verification warning:", err instanceof Error ? err.message : String(err));
|
|
869
963
|
}
|
|
870
964
|
}
|
|
871
|
-
|
|
965
|
+
async getActiveIndex(namespace) {
|
|
966
|
+
if (!this.client) {
|
|
967
|
+
await this.initialize();
|
|
968
|
+
}
|
|
969
|
+
if (!this.client) {
|
|
970
|
+
throw new Error("[PineconeProvider] Cannot execute vector operation: Pinecone client failed to initialize.");
|
|
971
|
+
}
|
|
872
972
|
const idx = this.client.index(this.indexName);
|
|
873
973
|
return namespace ? idx.namespace(namespace) : idx.namespace("");
|
|
874
974
|
}
|
|
875
975
|
async upsert(doc, namespace) {
|
|
876
976
|
var _a2;
|
|
877
|
-
await this.
|
|
977
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
978
|
+
await targetIdx.upsert({
|
|
878
979
|
records: [{
|
|
879
980
|
id: String(doc.id),
|
|
880
981
|
values: doc.vector,
|
|
@@ -883,6 +984,7 @@ var init_PineconeProvider = __esm({
|
|
|
883
984
|
});
|
|
884
985
|
}
|
|
885
986
|
async batchUpsert(docs, namespace) {
|
|
987
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
886
988
|
const BATCH = 100;
|
|
887
989
|
for (let i = 0; i < docs.length; i += BATCH) {
|
|
888
990
|
const records = docs.slice(i, i + BATCH).map((d) => {
|
|
@@ -893,13 +995,14 @@ var init_PineconeProvider = __esm({
|
|
|
893
995
|
metadata: __spreadValues({ content: d.content }, (_a2 = d.metadata) != null ? _a2 : {})
|
|
894
996
|
};
|
|
895
997
|
});
|
|
896
|
-
await
|
|
998
|
+
await targetIdx.upsert({ records });
|
|
897
999
|
}
|
|
898
1000
|
}
|
|
899
1001
|
async query(vector, topK, namespace, filter) {
|
|
900
1002
|
var _a2;
|
|
1003
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
901
1004
|
const pineconeFilter = this.sanitizeFilter(filter);
|
|
902
|
-
const result = await
|
|
1005
|
+
const result = await targetIdx.query(__spreadValues({
|
|
903
1006
|
vector,
|
|
904
1007
|
topK,
|
|
905
1008
|
includeMetadata: true
|
|
@@ -915,13 +1018,17 @@ var init_PineconeProvider = __esm({
|
|
|
915
1018
|
});
|
|
916
1019
|
}
|
|
917
1020
|
async delete(id, namespace) {
|
|
918
|
-
await this.
|
|
1021
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
1022
|
+
await targetIdx.deleteOne({ id: String(id) });
|
|
919
1023
|
}
|
|
920
1024
|
async deleteNamespace(namespace) {
|
|
921
|
-
await this.
|
|
1025
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
1026
|
+
await targetIdx.deleteAll();
|
|
922
1027
|
}
|
|
923
1028
|
async ping() {
|
|
924
1029
|
try {
|
|
1030
|
+
if (!this.client) await this.initialize();
|
|
1031
|
+
if (!this.client) return false;
|
|
925
1032
|
await this.client.listIndexes();
|
|
926
1033
|
return true;
|
|
927
1034
|
} catch (e) {
|
|
@@ -3132,7 +3239,7 @@ function getEnvConfig(env = process.env, base) {
|
|
|
3132
3239
|
return true;
|
|
3133
3240
|
}
|
|
3134
3241
|
})();
|
|
3135
|
-
const defaultGatewayUrl = (_pa = (_oa = readString(env, "LITELLM_BASE_URL")) != null ? _oa : readString(env, "LLM_BASE_URL")) != null ? _pa : "https://
|
|
3242
|
+
const defaultGatewayUrl = (_pa = (_oa = readString(env, "LITELLM_BASE_URL")) != null ? _oa : readString(env, "LLM_BASE_URL")) != null ? _pa : "https://retrivora.com/api/v1";
|
|
3136
3243
|
const defaultLlmProvider = isFreeTier ? "universal_rest" : "universal_rest";
|
|
3137
3244
|
const llmProvider = (_sa = (_ra = readEnum(env, "LLM_PROVIDER", defaultLlmProvider, LLM_PROVIDERS)) != null ? _ra : (_qa = base == null ? void 0 : base.llm) == null ? void 0 : _qa.provider) != null ? _sa : defaultLlmProvider;
|
|
3138
3245
|
const llmBaseUrl = (_wa = (_va = (_ta = readString(env, "LITELLM_BASE_URL")) != null ? _ta : readString(env, "LLM_BASE_URL")) != null ? _va : (_ua = base == null ? void 0 : base.llm) == null ? void 0 : _ua.baseUrl) != null ? _wa : defaultGatewayUrl;
|
package/dist/server.d.mts
CHANGED
|
@@ -198,7 +198,7 @@ declare class ConfigResolver {
|
|
|
198
198
|
*/
|
|
199
199
|
declare abstract class BaseVectorProvider {
|
|
200
200
|
protected readonly config: VectorDBConfig;
|
|
201
|
-
protected
|
|
201
|
+
protected indexName: string;
|
|
202
202
|
constructor(config: VectorDBConfig);
|
|
203
203
|
/**
|
|
204
204
|
* Initialise the connection (create tables, verify index, etc.)
|
|
@@ -615,12 +615,12 @@ declare class DocumentParser {
|
|
|
615
615
|
*/
|
|
616
616
|
declare class PineconeProvider extends BaseVectorProvider {
|
|
617
617
|
private client;
|
|
618
|
-
private
|
|
618
|
+
private apiKey;
|
|
619
619
|
constructor(config: VectorDBConfig);
|
|
620
620
|
static getValidator(): IProviderValidator;
|
|
621
621
|
static getHealthChecker(): IProviderHealthChecker;
|
|
622
622
|
initialize(): Promise<void>;
|
|
623
|
-
private
|
|
623
|
+
private getActiveIndex;
|
|
624
624
|
upsert(doc: UpsertDocument, namespace?: string): Promise<void>;
|
|
625
625
|
batchUpsert(docs: UpsertDocument[], namespace?: string): Promise<void>;
|
|
626
626
|
query(vector: number[], topK: number, namespace?: string, filter?: Record<string, unknown>): Promise<VectorMatch[]>;
|
package/dist/server.d.ts
CHANGED
|
@@ -198,7 +198,7 @@ declare class ConfigResolver {
|
|
|
198
198
|
*/
|
|
199
199
|
declare abstract class BaseVectorProvider {
|
|
200
200
|
protected readonly config: VectorDBConfig;
|
|
201
|
-
protected
|
|
201
|
+
protected indexName: string;
|
|
202
202
|
constructor(config: VectorDBConfig);
|
|
203
203
|
/**
|
|
204
204
|
* Initialise the connection (create tables, verify index, etc.)
|
|
@@ -615,12 +615,12 @@ declare class DocumentParser {
|
|
|
615
615
|
*/
|
|
616
616
|
declare class PineconeProvider extends BaseVectorProvider {
|
|
617
617
|
private client;
|
|
618
|
-
private
|
|
618
|
+
private apiKey;
|
|
619
619
|
constructor(config: VectorDBConfig);
|
|
620
620
|
static getValidator(): IProviderValidator;
|
|
621
621
|
static getHealthChecker(): IProviderHealthChecker;
|
|
622
622
|
initialize(): Promise<void>;
|
|
623
|
-
private
|
|
623
|
+
private getActiveIndex;
|
|
624
624
|
upsert(doc: UpsertDocument, namespace?: string): Promise<void>;
|
|
625
625
|
batchUpsert(docs: UpsertDocument[], namespace?: string): Promise<void>;
|
|
626
626
|
query(vector: number[], topK: number, namespace?: string, filter?: Record<string, unknown>): Promise<VectorMatch[]>;
|
package/dist/server.js
CHANGED
|
@@ -793,6 +793,84 @@ var init_BaseVectorProvider = __esm({
|
|
|
793
793
|
}
|
|
794
794
|
});
|
|
795
795
|
|
|
796
|
+
// src/core/ConfigFetcher.ts
|
|
797
|
+
var ConfigFetcher;
|
|
798
|
+
var init_ConfigFetcher = __esm({
|
|
799
|
+
"src/core/ConfigFetcher.ts"() {
|
|
800
|
+
"use strict";
|
|
801
|
+
ConfigFetcher = class {
|
|
802
|
+
// 5-minute in-memory session cache
|
|
803
|
+
/**
|
|
804
|
+
* Fetch full project configuration (vectorDb + embedding + llm) from Retrivora Control Plane.
|
|
805
|
+
*/
|
|
806
|
+
static async fetchRemoteConfig(projectId, licenseKey) {
|
|
807
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
|
|
808
|
+
const cacheKey = `${projectId}:${licenseKey || ""}`;
|
|
809
|
+
const now = Date.now();
|
|
810
|
+
const cached = this.cache.get(cacheKey);
|
|
811
|
+
if (cached && now - cached.cachedAt < this.TTL_MS) {
|
|
812
|
+
return cached.config;
|
|
813
|
+
}
|
|
814
|
+
const controlPlaneUrls = [
|
|
815
|
+
process.env.RETRIVORA_CONTROL_PLANE_URL,
|
|
816
|
+
process.env.NEXT_PUBLIC_RETRIVORA_CONTROL_PLANE_URL,
|
|
817
|
+
"https://retrivora.com",
|
|
818
|
+
"http://localhost:3000"
|
|
819
|
+
].filter(Boolean);
|
|
820
|
+
for (const baseUrl of controlPlaneUrls) {
|
|
821
|
+
try {
|
|
822
|
+
const url = `${baseUrl.replace(/\/$/, "")}/api/v1/config?projectId=${encodeURIComponent(projectId)}${licenseKey ? `&licenseKey=${encodeURIComponent(licenseKey)}` : ""}`;
|
|
823
|
+
const res = await fetch(url, {
|
|
824
|
+
method: "GET",
|
|
825
|
+
headers: __spreadValues({
|
|
826
|
+
"Content-Type": "application/json"
|
|
827
|
+
}, licenseKey ? { "x-license-key": licenseKey } : {})
|
|
828
|
+
});
|
|
829
|
+
if (res.ok) {
|
|
830
|
+
const data = await res.json();
|
|
831
|
+
if ((data == null ? void 0 : data.success) && ((_a2 = data == null ? void 0 : data.vectorDb) == null ? void 0 : _a2.apiKey)) {
|
|
832
|
+
const config = {
|
|
833
|
+
vectorDb: {
|
|
834
|
+
apiKey: data.vectorDb.apiKey,
|
|
835
|
+
indexName: data.vectorDb.indexName || "retrivora-free",
|
|
836
|
+
provider: data.vectorDb.provider || "pinecone"
|
|
837
|
+
},
|
|
838
|
+
embedding: {
|
|
839
|
+
provider: ((_b = data.embedding) == null ? void 0 : _b.provider) || "universal_rest",
|
|
840
|
+
model: ((_c = data.embedding) == null ? void 0 : _c.model) || "text-embedding-004",
|
|
841
|
+
baseUrl: ((_d = data.embedding) == null ? void 0 : _d.baseUrl) || "https://llm.retrivora.com/api/v1",
|
|
842
|
+
apiKey: ((_e = data.embedding) == null ? void 0 : _e.apiKey) || licenseKey || "",
|
|
843
|
+
profile: ((_f = data.embedding) == null ? void 0 : _f.profile) || "litellm"
|
|
844
|
+
},
|
|
845
|
+
llm: {
|
|
846
|
+
provider: ((_g2 = data.llm) == null ? void 0 : _g2.provider) || "universal_rest",
|
|
847
|
+
model: ((_h = data.llm) == null ? void 0 : _h.model) || "llama-3.1-8b-instant",
|
|
848
|
+
baseUrl: ((_i = data.llm) == null ? void 0 : _i.baseUrl) || "https://llm.retrivora.com/api/v1",
|
|
849
|
+
apiKey: ((_j = data.llm) == null ? void 0 : _j.apiKey) || licenseKey || "",
|
|
850
|
+
profile: ((_k = data.llm) == null ? void 0 : _k.profile) || "litellm"
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
this.cache.set(cacheKey, { config, cachedAt: now });
|
|
854
|
+
return config;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
} catch (e) {
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
return null;
|
|
861
|
+
}
|
|
862
|
+
/** Convenience: fetch only vector DB config (backwards compat). */
|
|
863
|
+
static async fetchRemoteVectorConfig(projectId, licenseKey) {
|
|
864
|
+
var _a2;
|
|
865
|
+
const config = await this.fetchRemoteConfig(projectId, licenseKey);
|
|
866
|
+
return (_a2 = config == null ? void 0 : config.vectorDb) != null ? _a2 : null;
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
ConfigFetcher.cache = /* @__PURE__ */ new Map();
|
|
870
|
+
ConfigFetcher.TTL_MS = 5 * 60 * 1e3;
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
|
|
796
874
|
// src/providers/vectordb/PineconeProvider.ts
|
|
797
875
|
var PineconeProvider_exports = {};
|
|
798
876
|
__export(PineconeProvider_exports, {
|
|
@@ -804,6 +882,7 @@ var init_PineconeProvider = __esm({
|
|
|
804
882
|
"use strict";
|
|
805
883
|
import_pinecone = require("@pinecone-database/pinecone");
|
|
806
884
|
init_BaseVectorProvider();
|
|
885
|
+
init_ConfigFetcher();
|
|
807
886
|
PineconeProvider = class extends BaseVectorProvider {
|
|
808
887
|
constructor(config) {
|
|
809
888
|
super(config);
|
|
@@ -869,27 +948,49 @@ var init_PineconeProvider = __esm({
|
|
|
869
948
|
}
|
|
870
949
|
async initialize() {
|
|
871
950
|
var _a2, _b;
|
|
872
|
-
|
|
951
|
+
if (this.client) return;
|
|
952
|
+
let key = this.apiKey || process.env.PINECONE_API_KEY || "";
|
|
953
|
+
if (!key) {
|
|
954
|
+
const projectId = process.env.RAG_PROJECT_ID || process.env.NEXT_PUBLIC_RAG_PROJECT_ID || "my-rag-app";
|
|
955
|
+
const licenseKey = process.env.RETRIVORA_LICENSE_KEY || process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY;
|
|
956
|
+
const remoteConfig = await ConfigFetcher.fetchRemoteVectorConfig(projectId, licenseKey);
|
|
957
|
+
if (remoteConfig == null ? void 0 : remoteConfig.apiKey) {
|
|
958
|
+
key = remoteConfig.apiKey;
|
|
959
|
+
this.apiKey = key;
|
|
960
|
+
if (remoteConfig.indexName) {
|
|
961
|
+
this.indexName = remoteConfig.indexName;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
873
965
|
if (!key) {
|
|
874
|
-
console.
|
|
966
|
+
console.warn("[PineconeProvider] Warning: No Pinecone API key available locally or remotely.");
|
|
875
967
|
return;
|
|
876
968
|
}
|
|
877
969
|
this.client = new import_pinecone.Pinecone({ apiKey: key });
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
`[PineconeProvider]
|
|
883
|
-
|
|
970
|
+
try {
|
|
971
|
+
const indexes = await this.client.listIndexes();
|
|
972
|
+
const names = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
|
|
973
|
+
if (!names.includes(this.indexName)) {
|
|
974
|
+
console.warn(`[PineconeProvider] Target index "${this.indexName}" not listed. Proceeding with configured index name.`);
|
|
975
|
+
}
|
|
976
|
+
} catch (err) {
|
|
977
|
+
console.warn("[PineconeProvider] List index verification warning:", err instanceof Error ? err.message : String(err));
|
|
884
978
|
}
|
|
885
979
|
}
|
|
886
|
-
|
|
980
|
+
async getActiveIndex(namespace) {
|
|
981
|
+
if (!this.client) {
|
|
982
|
+
await this.initialize();
|
|
983
|
+
}
|
|
984
|
+
if (!this.client) {
|
|
985
|
+
throw new Error("[PineconeProvider] Cannot execute vector operation: Pinecone client failed to initialize.");
|
|
986
|
+
}
|
|
887
987
|
const idx = this.client.index(this.indexName);
|
|
888
988
|
return namespace ? idx.namespace(namespace) : idx.namespace("");
|
|
889
989
|
}
|
|
890
990
|
async upsert(doc, namespace) {
|
|
891
991
|
var _a2;
|
|
892
|
-
await this.
|
|
992
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
993
|
+
await targetIdx.upsert({
|
|
893
994
|
records: [{
|
|
894
995
|
id: String(doc.id),
|
|
895
996
|
values: doc.vector,
|
|
@@ -898,6 +999,7 @@ var init_PineconeProvider = __esm({
|
|
|
898
999
|
});
|
|
899
1000
|
}
|
|
900
1001
|
async batchUpsert(docs, namespace) {
|
|
1002
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
901
1003
|
const BATCH = 100;
|
|
902
1004
|
for (let i = 0; i < docs.length; i += BATCH) {
|
|
903
1005
|
const records = docs.slice(i, i + BATCH).map((d) => {
|
|
@@ -908,13 +1010,14 @@ var init_PineconeProvider = __esm({
|
|
|
908
1010
|
metadata: __spreadValues({ content: d.content }, (_a2 = d.metadata) != null ? _a2 : {})
|
|
909
1011
|
};
|
|
910
1012
|
});
|
|
911
|
-
await
|
|
1013
|
+
await targetIdx.upsert({ records });
|
|
912
1014
|
}
|
|
913
1015
|
}
|
|
914
1016
|
async query(vector, topK, namespace, filter) {
|
|
915
1017
|
var _a2;
|
|
1018
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
916
1019
|
const pineconeFilter = this.sanitizeFilter(filter);
|
|
917
|
-
const result = await
|
|
1020
|
+
const result = await targetIdx.query(__spreadValues({
|
|
918
1021
|
vector,
|
|
919
1022
|
topK,
|
|
920
1023
|
includeMetadata: true
|
|
@@ -930,13 +1033,17 @@ var init_PineconeProvider = __esm({
|
|
|
930
1033
|
});
|
|
931
1034
|
}
|
|
932
1035
|
async delete(id, namespace) {
|
|
933
|
-
await this.
|
|
1036
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
1037
|
+
await targetIdx.deleteOne({ id: String(id) });
|
|
934
1038
|
}
|
|
935
1039
|
async deleteNamespace(namespace) {
|
|
936
|
-
await this.
|
|
1040
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
1041
|
+
await targetIdx.deleteAll();
|
|
937
1042
|
}
|
|
938
1043
|
async ping() {
|
|
939
1044
|
try {
|
|
1045
|
+
if (!this.client) await this.initialize();
|
|
1046
|
+
if (!this.client) return false;
|
|
940
1047
|
await this.client.listIndexes();
|
|
941
1048
|
return true;
|
|
942
1049
|
} catch (e) {
|
|
@@ -3229,7 +3336,7 @@ function getEnvConfig(env = process.env, base) {
|
|
|
3229
3336
|
return true;
|
|
3230
3337
|
}
|
|
3231
3338
|
})();
|
|
3232
|
-
const defaultGatewayUrl = (_pa = (_oa = readString(env, "LITELLM_BASE_URL")) != null ? _oa : readString(env, "LLM_BASE_URL")) != null ? _pa : "https://
|
|
3339
|
+
const defaultGatewayUrl = (_pa = (_oa = readString(env, "LITELLM_BASE_URL")) != null ? _oa : readString(env, "LLM_BASE_URL")) != null ? _pa : "https://retrivora.com/api/v1";
|
|
3233
3340
|
const defaultLlmProvider = isFreeTier ? "universal_rest" : "universal_rest";
|
|
3234
3341
|
const llmProvider = (_sa = (_ra = readEnum(env, "LLM_PROVIDER", defaultLlmProvider, LLM_PROVIDERS)) != null ? _ra : (_qa = base == null ? void 0 : base.llm) == null ? void 0 : _qa.provider) != null ? _sa : defaultLlmProvider;
|
|
3235
3342
|
const llmBaseUrl = (_wa = (_va = (_ta = readString(env, "LITELLM_BASE_URL")) != null ? _ta : readString(env, "LLM_BASE_URL")) != null ? _va : (_ua = base == null ? void 0 : base.llm) == null ? void 0 : _ua.baseUrl) != null ? _wa : defaultGatewayUrl;
|
package/dist/server.mjs
CHANGED
|
@@ -778,6 +778,84 @@ var init_BaseVectorProvider = __esm({
|
|
|
778
778
|
}
|
|
779
779
|
});
|
|
780
780
|
|
|
781
|
+
// src/core/ConfigFetcher.ts
|
|
782
|
+
var ConfigFetcher;
|
|
783
|
+
var init_ConfigFetcher = __esm({
|
|
784
|
+
"src/core/ConfigFetcher.ts"() {
|
|
785
|
+
"use strict";
|
|
786
|
+
ConfigFetcher = class {
|
|
787
|
+
// 5-minute in-memory session cache
|
|
788
|
+
/**
|
|
789
|
+
* Fetch full project configuration (vectorDb + embedding + llm) from Retrivora Control Plane.
|
|
790
|
+
*/
|
|
791
|
+
static async fetchRemoteConfig(projectId, licenseKey) {
|
|
792
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
|
|
793
|
+
const cacheKey = `${projectId}:${licenseKey || ""}`;
|
|
794
|
+
const now = Date.now();
|
|
795
|
+
const cached = this.cache.get(cacheKey);
|
|
796
|
+
if (cached && now - cached.cachedAt < this.TTL_MS) {
|
|
797
|
+
return cached.config;
|
|
798
|
+
}
|
|
799
|
+
const controlPlaneUrls = [
|
|
800
|
+
process.env.RETRIVORA_CONTROL_PLANE_URL,
|
|
801
|
+
process.env.NEXT_PUBLIC_RETRIVORA_CONTROL_PLANE_URL,
|
|
802
|
+
"https://retrivora.com",
|
|
803
|
+
"http://localhost:3000"
|
|
804
|
+
].filter(Boolean);
|
|
805
|
+
for (const baseUrl of controlPlaneUrls) {
|
|
806
|
+
try {
|
|
807
|
+
const url = `${baseUrl.replace(/\/$/, "")}/api/v1/config?projectId=${encodeURIComponent(projectId)}${licenseKey ? `&licenseKey=${encodeURIComponent(licenseKey)}` : ""}`;
|
|
808
|
+
const res = await fetch(url, {
|
|
809
|
+
method: "GET",
|
|
810
|
+
headers: __spreadValues({
|
|
811
|
+
"Content-Type": "application/json"
|
|
812
|
+
}, licenseKey ? { "x-license-key": licenseKey } : {})
|
|
813
|
+
});
|
|
814
|
+
if (res.ok) {
|
|
815
|
+
const data = await res.json();
|
|
816
|
+
if ((data == null ? void 0 : data.success) && ((_a2 = data == null ? void 0 : data.vectorDb) == null ? void 0 : _a2.apiKey)) {
|
|
817
|
+
const config = {
|
|
818
|
+
vectorDb: {
|
|
819
|
+
apiKey: data.vectorDb.apiKey,
|
|
820
|
+
indexName: data.vectorDb.indexName || "retrivora-free",
|
|
821
|
+
provider: data.vectorDb.provider || "pinecone"
|
|
822
|
+
},
|
|
823
|
+
embedding: {
|
|
824
|
+
provider: ((_b = data.embedding) == null ? void 0 : _b.provider) || "universal_rest",
|
|
825
|
+
model: ((_c = data.embedding) == null ? void 0 : _c.model) || "text-embedding-004",
|
|
826
|
+
baseUrl: ((_d = data.embedding) == null ? void 0 : _d.baseUrl) || "https://llm.retrivora.com/api/v1",
|
|
827
|
+
apiKey: ((_e = data.embedding) == null ? void 0 : _e.apiKey) || licenseKey || "",
|
|
828
|
+
profile: ((_f = data.embedding) == null ? void 0 : _f.profile) || "litellm"
|
|
829
|
+
},
|
|
830
|
+
llm: {
|
|
831
|
+
provider: ((_g2 = data.llm) == null ? void 0 : _g2.provider) || "universal_rest",
|
|
832
|
+
model: ((_h = data.llm) == null ? void 0 : _h.model) || "llama-3.1-8b-instant",
|
|
833
|
+
baseUrl: ((_i = data.llm) == null ? void 0 : _i.baseUrl) || "https://llm.retrivora.com/api/v1",
|
|
834
|
+
apiKey: ((_j = data.llm) == null ? void 0 : _j.apiKey) || licenseKey || "",
|
|
835
|
+
profile: ((_k = data.llm) == null ? void 0 : _k.profile) || "litellm"
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
this.cache.set(cacheKey, { config, cachedAt: now });
|
|
839
|
+
return config;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
} catch (e) {
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
return null;
|
|
846
|
+
}
|
|
847
|
+
/** Convenience: fetch only vector DB config (backwards compat). */
|
|
848
|
+
static async fetchRemoteVectorConfig(projectId, licenseKey) {
|
|
849
|
+
var _a2;
|
|
850
|
+
const config = await this.fetchRemoteConfig(projectId, licenseKey);
|
|
851
|
+
return (_a2 = config == null ? void 0 : config.vectorDb) != null ? _a2 : null;
|
|
852
|
+
}
|
|
853
|
+
};
|
|
854
|
+
ConfigFetcher.cache = /* @__PURE__ */ new Map();
|
|
855
|
+
ConfigFetcher.TTL_MS = 5 * 60 * 1e3;
|
|
856
|
+
}
|
|
857
|
+
});
|
|
858
|
+
|
|
781
859
|
// src/providers/vectordb/PineconeProvider.ts
|
|
782
860
|
var PineconeProvider_exports = {};
|
|
783
861
|
__export(PineconeProvider_exports, {
|
|
@@ -789,6 +867,7 @@ var init_PineconeProvider = __esm({
|
|
|
789
867
|
"src/providers/vectordb/PineconeProvider.ts"() {
|
|
790
868
|
"use strict";
|
|
791
869
|
init_BaseVectorProvider();
|
|
870
|
+
init_ConfigFetcher();
|
|
792
871
|
PineconeProvider = class extends BaseVectorProvider {
|
|
793
872
|
constructor(config) {
|
|
794
873
|
super(config);
|
|
@@ -854,27 +933,49 @@ var init_PineconeProvider = __esm({
|
|
|
854
933
|
}
|
|
855
934
|
async initialize() {
|
|
856
935
|
var _a2, _b;
|
|
857
|
-
|
|
936
|
+
if (this.client) return;
|
|
937
|
+
let key = this.apiKey || process.env.PINECONE_API_KEY || "";
|
|
938
|
+
if (!key) {
|
|
939
|
+
const projectId = process.env.RAG_PROJECT_ID || process.env.NEXT_PUBLIC_RAG_PROJECT_ID || "my-rag-app";
|
|
940
|
+
const licenseKey = process.env.RETRIVORA_LICENSE_KEY || process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY;
|
|
941
|
+
const remoteConfig = await ConfigFetcher.fetchRemoteVectorConfig(projectId, licenseKey);
|
|
942
|
+
if (remoteConfig == null ? void 0 : remoteConfig.apiKey) {
|
|
943
|
+
key = remoteConfig.apiKey;
|
|
944
|
+
this.apiKey = key;
|
|
945
|
+
if (remoteConfig.indexName) {
|
|
946
|
+
this.indexName = remoteConfig.indexName;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
858
950
|
if (!key) {
|
|
859
|
-
console.
|
|
951
|
+
console.warn("[PineconeProvider] Warning: No Pinecone API key available locally or remotely.");
|
|
860
952
|
return;
|
|
861
953
|
}
|
|
862
954
|
this.client = new Pinecone({ apiKey: key });
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
`[PineconeProvider]
|
|
868
|
-
|
|
955
|
+
try {
|
|
956
|
+
const indexes = await this.client.listIndexes();
|
|
957
|
+
const names = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
|
|
958
|
+
if (!names.includes(this.indexName)) {
|
|
959
|
+
console.warn(`[PineconeProvider] Target index "${this.indexName}" not listed. Proceeding with configured index name.`);
|
|
960
|
+
}
|
|
961
|
+
} catch (err) {
|
|
962
|
+
console.warn("[PineconeProvider] List index verification warning:", err instanceof Error ? err.message : String(err));
|
|
869
963
|
}
|
|
870
964
|
}
|
|
871
|
-
|
|
965
|
+
async getActiveIndex(namespace) {
|
|
966
|
+
if (!this.client) {
|
|
967
|
+
await this.initialize();
|
|
968
|
+
}
|
|
969
|
+
if (!this.client) {
|
|
970
|
+
throw new Error("[PineconeProvider] Cannot execute vector operation: Pinecone client failed to initialize.");
|
|
971
|
+
}
|
|
872
972
|
const idx = this.client.index(this.indexName);
|
|
873
973
|
return namespace ? idx.namespace(namespace) : idx.namespace("");
|
|
874
974
|
}
|
|
875
975
|
async upsert(doc, namespace) {
|
|
876
976
|
var _a2;
|
|
877
|
-
await this.
|
|
977
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
978
|
+
await targetIdx.upsert({
|
|
878
979
|
records: [{
|
|
879
980
|
id: String(doc.id),
|
|
880
981
|
values: doc.vector,
|
|
@@ -883,6 +984,7 @@ var init_PineconeProvider = __esm({
|
|
|
883
984
|
});
|
|
884
985
|
}
|
|
885
986
|
async batchUpsert(docs, namespace) {
|
|
987
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
886
988
|
const BATCH = 100;
|
|
887
989
|
for (let i = 0; i < docs.length; i += BATCH) {
|
|
888
990
|
const records = docs.slice(i, i + BATCH).map((d) => {
|
|
@@ -893,13 +995,14 @@ var init_PineconeProvider = __esm({
|
|
|
893
995
|
metadata: __spreadValues({ content: d.content }, (_a2 = d.metadata) != null ? _a2 : {})
|
|
894
996
|
};
|
|
895
997
|
});
|
|
896
|
-
await
|
|
998
|
+
await targetIdx.upsert({ records });
|
|
897
999
|
}
|
|
898
1000
|
}
|
|
899
1001
|
async query(vector, topK, namespace, filter) {
|
|
900
1002
|
var _a2;
|
|
1003
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
901
1004
|
const pineconeFilter = this.sanitizeFilter(filter);
|
|
902
|
-
const result = await
|
|
1005
|
+
const result = await targetIdx.query(__spreadValues({
|
|
903
1006
|
vector,
|
|
904
1007
|
topK,
|
|
905
1008
|
includeMetadata: true
|
|
@@ -915,13 +1018,17 @@ var init_PineconeProvider = __esm({
|
|
|
915
1018
|
});
|
|
916
1019
|
}
|
|
917
1020
|
async delete(id, namespace) {
|
|
918
|
-
await this.
|
|
1021
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
1022
|
+
await targetIdx.deleteOne({ id: String(id) });
|
|
919
1023
|
}
|
|
920
1024
|
async deleteNamespace(namespace) {
|
|
921
|
-
await this.
|
|
1025
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
1026
|
+
await targetIdx.deleteAll();
|
|
922
1027
|
}
|
|
923
1028
|
async ping() {
|
|
924
1029
|
try {
|
|
1030
|
+
if (!this.client) await this.initialize();
|
|
1031
|
+
if (!this.client) return false;
|
|
925
1032
|
await this.client.listIndexes();
|
|
926
1033
|
return true;
|
|
927
1034
|
} catch (e) {
|
|
@@ -3132,7 +3239,7 @@ function getEnvConfig(env = process.env, base) {
|
|
|
3132
3239
|
return true;
|
|
3133
3240
|
}
|
|
3134
3241
|
})();
|
|
3135
|
-
const defaultGatewayUrl = (_pa = (_oa = readString(env, "LITELLM_BASE_URL")) != null ? _oa : readString(env, "LLM_BASE_URL")) != null ? _pa : "https://
|
|
3242
|
+
const defaultGatewayUrl = (_pa = (_oa = readString(env, "LITELLM_BASE_URL")) != null ? _oa : readString(env, "LLM_BASE_URL")) != null ? _pa : "https://retrivora.com/api/v1";
|
|
3136
3243
|
const defaultLlmProvider = isFreeTier ? "universal_rest" : "universal_rest";
|
|
3137
3244
|
const llmProvider = (_sa = (_ra = readEnum(env, "LLM_PROVIDER", defaultLlmProvider, LLM_PROVIDERS)) != null ? _ra : (_qa = base == null ? void 0 : base.llm) == null ? void 0 : _qa.provider) != null ? _sa : defaultLlmProvider;
|
|
3138
3245
|
const llmBaseUrl = (_wa = (_va = (_ta = readString(env, "LITELLM_BASE_URL")) != null ? _ta : readString(env, "LLM_BASE_URL")) != null ? _va : (_ua = base == null ? void 0 : base.llm) == null ? void 0 : _ua.baseUrl) != null ? _wa : defaultGatewayUrl;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retrivora-ai/rag-engine",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Retrivora AI is a plug-and-play AI engine for RAG chat experiences — generic vector DB + LLM provider, embeddable or standalone.",
|
|
5
5
|
"author": "Abhinav Alkuchi",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -171,7 +171,10 @@ export function getEnvConfig(env: Record<string, string | undefined> = process.e
|
|
|
171
171
|
}
|
|
172
172
|
})();
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
// Default gateway: retrivora.com/api/v1 acts as a secure proxy that validates the license key
|
|
175
|
+
// and forwards to llm.retrivora.com with LITELLM_MASTER_KEY (which end-users never need to know).
|
|
176
|
+
// Developers who self-host can override with LITELLM_BASE_URL.
|
|
177
|
+
const defaultGatewayUrl = readString(env, 'LITELLM_BASE_URL') ?? readString(env, 'LLM_BASE_URL') ?? 'https://retrivora.com/api/v1';
|
|
175
178
|
|
|
176
179
|
const defaultLlmProvider = isFreeTier ? 'universal_rest' : 'universal_rest';
|
|
177
180
|
const llmProvider = (readEnum(env, 'LLM_PROVIDER', defaultLlmProvider, LLM_PROVIDERS) ?? base?.llm?.provider ?? defaultLlmProvider) as LLMProvider;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ConfigFetcher.ts — Dynamically fetches project credentials from Retrivora Control Plane
|
|
3
|
+
* without hardcoding plain-text master keys in NPM package binaries.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface RemoteVectorConfig {
|
|
7
|
+
apiKey: string;
|
|
8
|
+
indexName: string;
|
|
9
|
+
provider: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface RemoteEmbeddingConfig {
|
|
13
|
+
provider: string;
|
|
14
|
+
model: string;
|
|
15
|
+
baseUrl: string;
|
|
16
|
+
apiKey: string;
|
|
17
|
+
profile?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface RemoteLLMConfig {
|
|
21
|
+
provider: string;
|
|
22
|
+
model: string;
|
|
23
|
+
baseUrl: string;
|
|
24
|
+
apiKey: string;
|
|
25
|
+
profile?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface RemoteConfig {
|
|
29
|
+
vectorDb: RemoteVectorConfig;
|
|
30
|
+
embedding: RemoteEmbeddingConfig;
|
|
31
|
+
llm: RemoteLLMConfig;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Legacy alias
|
|
35
|
+
export type { RemoteVectorConfig as RemoteConfig_ };
|
|
36
|
+
|
|
37
|
+
export class ConfigFetcher {
|
|
38
|
+
private static cache = new Map<string, { config: RemoteConfig; cachedAt: number }>();
|
|
39
|
+
private static readonly TTL_MS = 5 * 60 * 1000; // 5-minute in-memory session cache
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Fetch full project configuration (vectorDb + embedding + llm) from Retrivora Control Plane.
|
|
43
|
+
*/
|
|
44
|
+
static async fetchRemoteConfig(projectId: string, licenseKey?: string): Promise<RemoteConfig | null> {
|
|
45
|
+
const cacheKey = `${projectId}:${licenseKey || ''}`;
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
const cached = this.cache.get(cacheKey);
|
|
48
|
+
|
|
49
|
+
if (cached && now - cached.cachedAt < this.TTL_MS) {
|
|
50
|
+
return cached.config;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const controlPlaneUrls = [
|
|
54
|
+
process.env.RETRIVORA_CONTROL_PLANE_URL,
|
|
55
|
+
process.env.NEXT_PUBLIC_RETRIVORA_CONTROL_PLANE_URL,
|
|
56
|
+
'https://retrivora.com',
|
|
57
|
+
'http://localhost:3000',
|
|
58
|
+
].filter(Boolean) as string[];
|
|
59
|
+
|
|
60
|
+
for (const baseUrl of controlPlaneUrls) {
|
|
61
|
+
try {
|
|
62
|
+
const url = `${baseUrl.replace(/\/$/, '')}/api/v1/config?projectId=${encodeURIComponent(projectId)}${licenseKey ? `&licenseKey=${encodeURIComponent(licenseKey)}` : ''}`;
|
|
63
|
+
const res = await fetch(url, {
|
|
64
|
+
method: 'GET',
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
...(licenseKey ? { 'x-license-key': licenseKey } : {}),
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (res.ok) {
|
|
72
|
+
const data = await res.json();
|
|
73
|
+
if (data?.success && data?.vectorDb?.apiKey) {
|
|
74
|
+
const config: RemoteConfig = {
|
|
75
|
+
vectorDb: {
|
|
76
|
+
apiKey: data.vectorDb.apiKey,
|
|
77
|
+
indexName: data.vectorDb.indexName || 'retrivora-free',
|
|
78
|
+
provider: data.vectorDb.provider || 'pinecone',
|
|
79
|
+
},
|
|
80
|
+
embedding: {
|
|
81
|
+
provider: data.embedding?.provider || 'universal_rest',
|
|
82
|
+
model: data.embedding?.model || 'text-embedding-004',
|
|
83
|
+
baseUrl: data.embedding?.baseUrl || 'https://llm.retrivora.com/api/v1',
|
|
84
|
+
apiKey: data.embedding?.apiKey || licenseKey || '',
|
|
85
|
+
profile: data.embedding?.profile || 'litellm',
|
|
86
|
+
},
|
|
87
|
+
llm: {
|
|
88
|
+
provider: data.llm?.provider || 'universal_rest',
|
|
89
|
+
model: data.llm?.model || 'llama-3.1-8b-instant',
|
|
90
|
+
baseUrl: data.llm?.baseUrl || 'https://llm.retrivora.com/api/v1',
|
|
91
|
+
apiKey: data.llm?.apiKey || licenseKey || '',
|
|
92
|
+
profile: data.llm?.profile || 'litellm',
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
this.cache.set(cacheKey, { config, cachedAt: now });
|
|
96
|
+
return config;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} catch {
|
|
100
|
+
/* Try next fallback URL */
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Convenience: fetch only vector DB config (backwards compat). */
|
|
108
|
+
static async fetchRemoteVectorConfig(projectId: string, licenseKey?: string): Promise<RemoteVectorConfig | null> {
|
|
109
|
+
const config = await this.fetchRemoteConfig(projectId, licenseKey);
|
|
110
|
+
return config?.vectorDb ?? null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -8,7 +8,7 @@ import { IProviderValidator, IProviderHealthChecker } from '../../core/ProviderI
|
|
|
8
8
|
*/
|
|
9
9
|
export abstract class BaseVectorProvider {
|
|
10
10
|
protected readonly config: VectorDBConfig;
|
|
11
|
-
protected
|
|
11
|
+
protected indexName: string;
|
|
12
12
|
|
|
13
13
|
constructor(config: VectorDBConfig) {
|
|
14
14
|
this.config = config;
|
|
@@ -4,13 +4,14 @@ import { BaseVectorProvider } from './BaseVectorProvider';
|
|
|
4
4
|
import { VectorMatch, UpsertDocument } from '../../types';
|
|
5
5
|
import { IProviderValidator, IProviderHealthChecker, HealthCheckResult } from '../../core/ProviderInterfaces';
|
|
6
6
|
import { ValidationError } from '../../core/ConfigValidator';
|
|
7
|
+
import { ConfigFetcher } from '../../core/ConfigFetcher';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* PineconeProvider — Pinecone vector database implementation.
|
|
10
11
|
*/
|
|
11
12
|
export class PineconeProvider extends BaseVectorProvider {
|
|
12
13
|
private client!: Pinecone;
|
|
13
|
-
private
|
|
14
|
+
private apiKey: string;
|
|
14
15
|
|
|
15
16
|
constructor(config: VectorDBConfig) {
|
|
16
17
|
super(config);
|
|
@@ -82,28 +83,55 @@ export class PineconeProvider extends BaseVectorProvider {
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
async initialize(): Promise<void> {
|
|
85
|
-
|
|
86
|
+
if (this.client) return;
|
|
87
|
+
|
|
88
|
+
let key = this.apiKey || process.env.PINECONE_API_KEY || '';
|
|
89
|
+
|
|
90
|
+
if (!key) {
|
|
91
|
+
const projectId = process.env.RAG_PROJECT_ID || process.env.NEXT_PUBLIC_RAG_PROJECT_ID || 'my-rag-app';
|
|
92
|
+
const licenseKey = process.env.RETRIVORA_LICENSE_KEY || process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY;
|
|
93
|
+
|
|
94
|
+
const remoteConfig = await ConfigFetcher.fetchRemoteVectorConfig(projectId, licenseKey);
|
|
95
|
+
if (remoteConfig?.apiKey) {
|
|
96
|
+
key = remoteConfig.apiKey;
|
|
97
|
+
this.apiKey = key;
|
|
98
|
+
if (remoteConfig.indexName) {
|
|
99
|
+
this.indexName = remoteConfig.indexName;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
86
104
|
if (!key) {
|
|
87
|
-
console.
|
|
105
|
+
console.warn('[PineconeProvider] Warning: No Pinecone API key available locally or remotely.');
|
|
88
106
|
return;
|
|
89
107
|
}
|
|
108
|
+
|
|
90
109
|
this.client = new Pinecone({ apiKey: key });
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
`[PineconeProvider]
|
|
96
|
-
|
|
110
|
+
try {
|
|
111
|
+
const indexes = await this.client.listIndexes();
|
|
112
|
+
const names = indexes.indexes?.map((i) => i.name) ?? [];
|
|
113
|
+
if (!names.includes(this.indexName)) {
|
|
114
|
+
console.warn(`[PineconeProvider] Target index "${this.indexName}" not listed. Proceeding with configured index name.`);
|
|
115
|
+
}
|
|
116
|
+
} catch (err) {
|
|
117
|
+
console.warn('[PineconeProvider] List index verification warning:', err instanceof Error ? err.message : String(err));
|
|
97
118
|
}
|
|
98
119
|
}
|
|
99
120
|
|
|
100
|
-
private
|
|
121
|
+
private async getActiveIndex(namespace?: string) {
|
|
122
|
+
if (!this.client) {
|
|
123
|
+
await this.initialize();
|
|
124
|
+
}
|
|
125
|
+
if (!this.client) {
|
|
126
|
+
throw new Error('[PineconeProvider] Cannot execute vector operation: Pinecone client failed to initialize.');
|
|
127
|
+
}
|
|
101
128
|
const idx = this.client.index(this.indexName);
|
|
102
129
|
return namespace ? idx.namespace(namespace) : idx.namespace('');
|
|
103
130
|
}
|
|
104
131
|
|
|
105
132
|
async upsert(doc: UpsertDocument, namespace?: string): Promise<void> {
|
|
106
|
-
await this.
|
|
133
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
134
|
+
await targetIdx.upsert({
|
|
107
135
|
records: [{
|
|
108
136
|
id: String(doc.id),
|
|
109
137
|
values: doc.vector,
|
|
@@ -113,6 +141,7 @@ export class PineconeProvider extends BaseVectorProvider {
|
|
|
113
141
|
}
|
|
114
142
|
|
|
115
143
|
async batchUpsert(docs: UpsertDocument[], namespace?: string): Promise<void> {
|
|
144
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
116
145
|
const BATCH = 100;
|
|
117
146
|
for (let i = 0; i < docs.length; i += BATCH) {
|
|
118
147
|
const records = docs.slice(i, i + BATCH).map((d) => ({
|
|
@@ -120,7 +149,7 @@ export class PineconeProvider extends BaseVectorProvider {
|
|
|
120
149
|
values: d.vector,
|
|
121
150
|
metadata: { content: d.content, ...(d.metadata ?? {}) } as RecordMetadata,
|
|
122
151
|
}));
|
|
123
|
-
await
|
|
152
|
+
await targetIdx.upsert({ records });
|
|
124
153
|
}
|
|
125
154
|
}
|
|
126
155
|
|
|
@@ -130,8 +159,9 @@ export class PineconeProvider extends BaseVectorProvider {
|
|
|
130
159
|
namespace?: string,
|
|
131
160
|
filter?: Record<string, unknown>
|
|
132
161
|
): Promise<VectorMatch[]> {
|
|
162
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
133
163
|
const pineconeFilter = this.sanitizeFilter(filter);
|
|
134
|
-
const result = await
|
|
164
|
+
const result = await targetIdx.query({
|
|
135
165
|
vector,
|
|
136
166
|
topK,
|
|
137
167
|
includeMetadata: true,
|
|
@@ -146,15 +176,19 @@ export class PineconeProvider extends BaseVectorProvider {
|
|
|
146
176
|
}
|
|
147
177
|
|
|
148
178
|
async delete(id: string | number, namespace?: string): Promise<void> {
|
|
149
|
-
await this.
|
|
179
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
180
|
+
await targetIdx.deleteOne({ id: String(id) });
|
|
150
181
|
}
|
|
151
182
|
|
|
152
183
|
async deleteNamespace(namespace: string): Promise<void> {
|
|
153
|
-
await this.
|
|
184
|
+
const targetIdx = await this.getActiveIndex(namespace);
|
|
185
|
+
await targetIdx.deleteAll();
|
|
154
186
|
}
|
|
155
187
|
|
|
156
188
|
async ping(): Promise<boolean> {
|
|
157
189
|
try {
|
|
190
|
+
if (!this.client) await this.initialize();
|
|
191
|
+
if (!this.client) return false;
|
|
158
192
|
await this.client.listIndexes();
|
|
159
193
|
return true;
|
|
160
194
|
} catch {
|