@retrivora-ai/rag-engine 2.0.3 → 2.0.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.
- package/dist/handlers/index.js +389 -344
- package/dist/handlers/index.mjs +391 -346
- package/dist/server.js +389 -344
- package/dist/server.mjs +391 -346
- package/package.json +2 -2
- package/src/config/serverConfig.ts +40 -13
- package/src/core/DatabaseStorage.ts +5 -1
- package/src/core/LicenseVerifier.ts +1 -1
- package/src/handlers/index.ts +22 -9
- package/src/index.css +3956 -0
- package/src/llm/providers/OllamaProvider.ts +4 -2
package/dist/handlers/index.js
CHANGED
|
@@ -2093,6 +2093,285 @@ var import_server = require("next/server");
|
|
|
2093
2093
|
// src/core/ConfigResolver.ts
|
|
2094
2094
|
init_templateUtils();
|
|
2095
2095
|
|
|
2096
|
+
// src/core/LicenseVerifier.ts
|
|
2097
|
+
var crypto = __toESM(require("crypto"));
|
|
2098
|
+
|
|
2099
|
+
// src/exceptions/index.ts
|
|
2100
|
+
var RetrivoraError = class extends Error {
|
|
2101
|
+
constructor(message, code, details) {
|
|
2102
|
+
super(message);
|
|
2103
|
+
this.name = new.target.name;
|
|
2104
|
+
this.code = code;
|
|
2105
|
+
this.details = details;
|
|
2106
|
+
}
|
|
2107
|
+
};
|
|
2108
|
+
var ProviderNotFoundException = class extends RetrivoraError {
|
|
2109
|
+
constructor(providerType, provider, details) {
|
|
2110
|
+
super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
|
|
2111
|
+
}
|
|
2112
|
+
};
|
|
2113
|
+
var EmbeddingFailedException = class extends RetrivoraError {
|
|
2114
|
+
constructor(message = "Embedding generation failed", details) {
|
|
2115
|
+
super(message, "EMBEDDING_FAILED", details);
|
|
2116
|
+
}
|
|
2117
|
+
};
|
|
2118
|
+
var RetrievalException = class extends RetrivoraError {
|
|
2119
|
+
constructor(message = "Retrieval failed", details) {
|
|
2120
|
+
super(message, "RETRIEVAL_FAILED", details);
|
|
2121
|
+
}
|
|
2122
|
+
};
|
|
2123
|
+
var RateLimitException = class extends RetrivoraError {
|
|
2124
|
+
constructor(message = "Provider rate limit exceeded", details) {
|
|
2125
|
+
super(message, "RATE_LIMITED", details);
|
|
2126
|
+
}
|
|
2127
|
+
};
|
|
2128
|
+
var ConfigurationException = class extends RetrivoraError {
|
|
2129
|
+
constructor(message, details) {
|
|
2130
|
+
super(message, "CONFIGURATION_ERROR", details);
|
|
2131
|
+
}
|
|
2132
|
+
};
|
|
2133
|
+
var AuthenticationException = class extends RetrivoraError {
|
|
2134
|
+
constructor(message = "Provider authentication failed", details) {
|
|
2135
|
+
super(message, "AUTHENTICATION_ERROR", details);
|
|
2136
|
+
}
|
|
2137
|
+
};
|
|
2138
|
+
function wrapError(err, defaultCode, defaultMessage) {
|
|
2139
|
+
var _a2;
|
|
2140
|
+
if (err instanceof RetrivoraError) {
|
|
2141
|
+
return err;
|
|
2142
|
+
}
|
|
2143
|
+
const error = err;
|
|
2144
|
+
const message = (error == null ? void 0 : error.message) || defaultMessage || String(err);
|
|
2145
|
+
const status = (error == null ? void 0 : error.status) || (error == null ? void 0 : error.statusCode) || ((_a2 = error == null ? void 0 : error.response) == null ? void 0 : _a2.status);
|
|
2146
|
+
const code = error == null ? void 0 : error.code;
|
|
2147
|
+
if (status === 429 || /rate[- ]?limit/i.test(message) || code === "RATE_LIMIT_EXCEEDED") {
|
|
2148
|
+
return new RateLimitException(message, err);
|
|
2149
|
+
}
|
|
2150
|
+
if (status === 401 || status === 403 || /unauthorized|auth|api[- ]?key/i.test(message) || code === "INVALID_API_KEY") {
|
|
2151
|
+
return new AuthenticationException(message, err);
|
|
2152
|
+
}
|
|
2153
|
+
switch (defaultCode) {
|
|
2154
|
+
case "PROVIDER_NOT_FOUND":
|
|
2155
|
+
return new ProviderNotFoundException("provider", message, err);
|
|
2156
|
+
case "EMBEDDING_FAILED":
|
|
2157
|
+
return new EmbeddingFailedException(message, err);
|
|
2158
|
+
case "RETRIEVAL_FAILED":
|
|
2159
|
+
return new RetrievalException(message, err);
|
|
2160
|
+
case "RATE_LIMITED":
|
|
2161
|
+
return new RateLimitException(message, err);
|
|
2162
|
+
case "CONFIGURATION_ERROR":
|
|
2163
|
+
return new ConfigurationException(message, err);
|
|
2164
|
+
case "AUTHENTICATION_ERROR":
|
|
2165
|
+
return new AuthenticationException(message, err);
|
|
2166
|
+
default:
|
|
2167
|
+
return new RetrivoraError(message, defaultCode, err);
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
// src/core/LicenseVerifier.ts
|
|
2172
|
+
var LicenseVerifier = class {
|
|
2173
|
+
/**
|
|
2174
|
+
* Decodes, verifies signature, and checks metadata of a license key.
|
|
2175
|
+
*
|
|
2176
|
+
* @param licenseKey - Base64url signed JWT license key.
|
|
2177
|
+
* @param currentProjectId - Project namespace ID.
|
|
2178
|
+
* @param publicKeyOverride - Optional override for unit/integration tests.
|
|
2179
|
+
*/
|
|
2180
|
+
static verify(licenseKey, currentProjectId, provider, publicKeyOverride) {
|
|
2181
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
2182
|
+
const now = Date.now();
|
|
2183
|
+
if (licenseKey) {
|
|
2184
|
+
const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
|
|
2185
|
+
const cached = this.cache.get(cacheKey);
|
|
2186
|
+
if (cached && now - cached.cachedAt < this.CACHE_TTL_MS) {
|
|
2187
|
+
const currentTimestampSec = Math.floor(now / 1e3);
|
|
2188
|
+
if (cached.payload.expiresAt && currentTimestampSec > cached.payload.expiresAt) {
|
|
2189
|
+
this.cache.delete(cacheKey);
|
|
2190
|
+
} else {
|
|
2191
|
+
return cached.payload;
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
if (!licenseKey) {
|
|
2196
|
+
if (isProduction) {
|
|
2197
|
+
throw new ConfigurationException(
|
|
2198
|
+
"[Retrivora SDK] License key (licenseKey) is required in production environments."
|
|
2199
|
+
);
|
|
2200
|
+
}
|
|
2201
|
+
console.warn(
|
|
2202
|
+
`\x1B[33m[Retrivora SDK] WARNING: Running without a license key. This namespace (${currentProjectId}) is permitted for local development only.\x1B[0m`
|
|
2203
|
+
);
|
|
2204
|
+
return {
|
|
2205
|
+
projectId: currentProjectId,
|
|
2206
|
+
expiresAt: Math.floor(Date.now() / 1e3) + 86400,
|
|
2207
|
+
// Valid for 24h
|
|
2208
|
+
tier: "hobby"
|
|
2209
|
+
};
|
|
2210
|
+
}
|
|
2211
|
+
try {
|
|
2212
|
+
const parts = licenseKey.split(".");
|
|
2213
|
+
if (parts.length !== 3) {
|
|
2214
|
+
throw new Error("Malformed token structure (expected 3 parts).");
|
|
2215
|
+
}
|
|
2216
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
2217
|
+
const dataToVerify = `${headerB64}.${payloadB64}`;
|
|
2218
|
+
const publicKey = publicKeyOverride != null ? publicKeyOverride : this.PUBLIC_KEY;
|
|
2219
|
+
const signature = Buffer.from(signatureB64, "base64url");
|
|
2220
|
+
const data = Buffer.from(dataToVerify);
|
|
2221
|
+
const isValid = crypto.verify(
|
|
2222
|
+
"sha256",
|
|
2223
|
+
data,
|
|
2224
|
+
publicKey,
|
|
2225
|
+
signature
|
|
2226
|
+
);
|
|
2227
|
+
if (!isValid) {
|
|
2228
|
+
throw new Error("Signature verification failed.");
|
|
2229
|
+
}
|
|
2230
|
+
const payload = JSON.parse(
|
|
2231
|
+
Buffer.from(payloadB64, "base64url").toString("utf8")
|
|
2232
|
+
);
|
|
2233
|
+
if (!payload.projectId) {
|
|
2234
|
+
throw new Error('License payload is missing "projectId".');
|
|
2235
|
+
}
|
|
2236
|
+
if (payload.projectId !== currentProjectId) {
|
|
2237
|
+
throw new Error(
|
|
2238
|
+
`Project ID mismatch. License is bound to project namespace "${payload.projectId}" but configuration has "${currentProjectId}".`
|
|
2239
|
+
);
|
|
2240
|
+
}
|
|
2241
|
+
if (!payload.expiresAt) {
|
|
2242
|
+
throw new Error('License payload is missing expiration ("expiresAt").');
|
|
2243
|
+
}
|
|
2244
|
+
const currentTimestampSec = Math.floor(Date.now() / 1e3);
|
|
2245
|
+
if (currentTimestampSec > payload.expiresAt) {
|
|
2246
|
+
throw new Error(
|
|
2247
|
+
`License key has expired. Expiration: ${new Date(
|
|
2248
|
+
payload.expiresAt * 1e3
|
|
2249
|
+
).toDateString()}`
|
|
2250
|
+
);
|
|
2251
|
+
}
|
|
2252
|
+
if (isProduction && provider) {
|
|
2253
|
+
const tier = (payload.tier || "").toLowerCase();
|
|
2254
|
+
const normalizedProvider = provider.toLowerCase();
|
|
2255
|
+
if (tier === "hobby") {
|
|
2256
|
+
const allowedHobby = ["postgresql", "pgvector", "supabase"];
|
|
2257
|
+
if (!allowedHobby.includes(normalizedProvider)) {
|
|
2258
|
+
throw new Error(
|
|
2259
|
+
`The database provider "${provider}" is not allowed on the Hobby tier. Hobby tier is restricted to PostgreSQL and Supabase. Please upgrade to a Developer Pro or Enterprise plan.`
|
|
2260
|
+
);
|
|
2261
|
+
}
|
|
2262
|
+
} else if (tier === "pro" || tier === "developer_pro" || tier === "premium" || tier === "growth" || tier === "free_trial" || tier === "free_tier" || tier === "free") {
|
|
2263
|
+
const allowedPro = [
|
|
2264
|
+
"postgresql",
|
|
2265
|
+
"pgvector",
|
|
2266
|
+
"supabase",
|
|
2267
|
+
"pinecone",
|
|
2268
|
+
"qdrant",
|
|
2269
|
+
"mongodb",
|
|
2270
|
+
"milvus",
|
|
2271
|
+
"chroma",
|
|
2272
|
+
"chromadb"
|
|
2273
|
+
];
|
|
2274
|
+
if (!allowedPro.includes(normalizedProvider)) {
|
|
2275
|
+
throw new Error(
|
|
2276
|
+
`The database provider "${provider}" is not allowed on the Developer Pro tier. Please upgrade to an Enterprise plan.`
|
|
2277
|
+
);
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
if (licenseKey) {
|
|
2282
|
+
const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
|
|
2283
|
+
this.cache.set(cacheKey, { payload, cachedAt: now });
|
|
2284
|
+
}
|
|
2285
|
+
return payload;
|
|
2286
|
+
} catch (err) {
|
|
2287
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2288
|
+
throw new ConfigurationException(
|
|
2289
|
+
`[Retrivora SDK] License key validation failed: ${message}`
|
|
2290
|
+
);
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
static async verifyIP(licenseKey) {
|
|
2294
|
+
if (!licenseKey) return;
|
|
2295
|
+
try {
|
|
2296
|
+
const parts = licenseKey.split(".");
|
|
2297
|
+
if (parts.length !== 3) return;
|
|
2298
|
+
const [, payloadB64] = parts;
|
|
2299
|
+
const payload = JSON.parse(
|
|
2300
|
+
Buffer.from(payloadB64, "base64url").toString("utf8")
|
|
2301
|
+
);
|
|
2302
|
+
const tier = (payload.tier || "").toLowerCase();
|
|
2303
|
+
if (tier === "enterprise" || tier === "custom") {
|
|
2304
|
+
return;
|
|
2305
|
+
}
|
|
2306
|
+
if (payload.ipv4 || payload.ipv6) {
|
|
2307
|
+
let currentIpv4 = "";
|
|
2308
|
+
let currentIpv6 = "";
|
|
2309
|
+
try {
|
|
2310
|
+
const res = await fetch("https://api4.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
|
|
2311
|
+
const data = await res.json();
|
|
2312
|
+
currentIpv4 = data.ip;
|
|
2313
|
+
} catch (e) {
|
|
2314
|
+
}
|
|
2315
|
+
try {
|
|
2316
|
+
const res = await fetch("https://api6.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
|
|
2317
|
+
const data = await res.json();
|
|
2318
|
+
currentIpv6 = data.ip;
|
|
2319
|
+
} catch (e) {
|
|
2320
|
+
}
|
|
2321
|
+
const localIps = [];
|
|
2322
|
+
try {
|
|
2323
|
+
const osModule = require("os");
|
|
2324
|
+
const interfaces = osModule.networkInterfaces();
|
|
2325
|
+
for (const name of Object.keys(interfaces)) {
|
|
2326
|
+
for (const iface of interfaces[name] || []) {
|
|
2327
|
+
if (!iface.internal) {
|
|
2328
|
+
localIps.push(iface.address);
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
} catch (e) {
|
|
2333
|
+
}
|
|
2334
|
+
const isIpv4Match = payload.ipv4 && (currentIpv4 === payload.ipv4 || localIps.includes(payload.ipv4));
|
|
2335
|
+
const isIpv6Match = payload.ipv6 && (currentIpv6 === payload.ipv6 || localIps.includes(payload.ipv6));
|
|
2336
|
+
if (payload.ipv4 && payload.ipv6) {
|
|
2337
|
+
if (!isIpv4Match && !isIpv6Match) {
|
|
2338
|
+
throw new Error(
|
|
2339
|
+
`License key access restricted. This license key was created for a different system (authorized IPv4: ${payload.ipv4}, IPv6: ${payload.ipv6}) and cannot be used on this machine.`
|
|
2340
|
+
);
|
|
2341
|
+
}
|
|
2342
|
+
} else if (payload.ipv4 && !isIpv4Match) {
|
|
2343
|
+
throw new Error(
|
|
2344
|
+
`License key access restricted. This license key was created for a different system (authorized IPv4: ${payload.ipv4}) and cannot be used on this machine.`
|
|
2345
|
+
);
|
|
2346
|
+
} else if (payload.ipv6 && !isIpv6Match) {
|
|
2347
|
+
throw new Error(
|
|
2348
|
+
`License key access restricted. This license key was created for a different system (authorized IPv6: ${payload.ipv6}) and cannot be used on this machine.`
|
|
2349
|
+
);
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
} catch (err) {
|
|
2353
|
+
if (err.message.includes("License key access restricted")) {
|
|
2354
|
+
throw new ConfigurationException(`[Retrivora SDK] ${err.message}`);
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
};
|
|
2359
|
+
// A simple in-memory cache to save CPU overhead of cryptographic signature checks.
|
|
2360
|
+
LicenseVerifier.cache = /* @__PURE__ */ new Map();
|
|
2361
|
+
LicenseVerifier.CACHE_TTL_MS = 60 * 1e3;
|
|
2362
|
+
// Cache verified license for 60 seconds
|
|
2363
|
+
// Retrivora's Public Key used to verify the license key signature.
|
|
2364
|
+
// In production, this matches the private key held by Retrivora SaaS.
|
|
2365
|
+
LicenseVerifier.PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
|
|
2366
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMieCkCBtTfByRNOserm
|
|
2367
|
+
XM4T0Am29JyNzB4XQPe+WJJ56CN73H1HLXx9n1ByFcxkEJ9po+SURj5DnvUXwEy+
|
|
2368
|
+
xstx33wDPpVmcMQe33j5CRYS0S4gICiNqIRN7XkTlJtrcXqrmh1/hdOAwfRbjO1T
|
|
2369
|
+
NVtORHwUwWfI/lBLyxUPGtKPed+0fQ7NtcW4o00JXxs3EjCB5BV9CbnXoTjQb/4h
|
|
2370
|
+
iwZof4l8rb7oaNzOsVg0RSyxsETX7Ex5sI0CjBz1p2mYp4oVhw/A/h8Ls7H0XzjC
|
|
2371
|
+
+Eb6BLtsytt5JHoSp0jExLlCpDmpys2L+kETcBVx+IqiXtdN1n6KbkksvEDUVzLI
|
|
2372
|
+
MwIDAQAB
|
|
2373
|
+
-----END PUBLIC KEY-----`;
|
|
2374
|
+
|
|
2096
2375
|
// src/config/constants.ts
|
|
2097
2376
|
var VECTOR_DB_PROVIDERS = [
|
|
2098
2377
|
"pinecone",
|
|
@@ -2162,14 +2441,12 @@ function readEnum(env, name, fallback, allowed) {
|
|
|
2162
2441
|
throw new Error(`[getRagConfig] ${name} must be one of: ${allowed.join(", ")}`);
|
|
2163
2442
|
}
|
|
2164
2443
|
function getEnvConfig(env = process.env, base) {
|
|
2165
|
-
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa, _Ra, _Sa, _Ta, _Ua;
|
|
2444
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa, _Ra, _Sa, _Ta, _Ua, _Va, _Wa, _Xa, _Ya, _Za, __a, _$a, _ab, _bb, _cb, _db, _eb, _fb, _gb, _hb, _ib, _jb, _kb, _lb, _mb, _nb, _ob, _pb, _qb, _rb, _sb, _tb, _ub, _vb, _wb;
|
|
2166
2445
|
const projectId = (_c = (_b = (_a2 = readString(env, "RAG_PROJECT_ID")) != null ? _a2 : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : base == null ? void 0 : base.projectId) != null ? _c : "__default__";
|
|
2167
2446
|
const licenseKey = (_g2 = (_f = (_e = (_d = readString(env, "RAG_LICENSE_KEY")) != null ? _d : readString(env, "RETRIVORA_LICENSE_KEY")) != null ? _e : readString(env, "NEXT_PUBLIC_RETRIVORA_LICENSE_KEY")) != null ? _f : readString(env, "LICENSE_KEY")) != null ? _g2 : base == null ? void 0 : base.licenseKey;
|
|
2168
2447
|
const telemetryEnabled = readString(env, "TELEMETRY_ENABLED") === "true" || readString(env, "NEXT_PUBLIC_TELEMETRY_ENABLED") === "true" || ((_h = base == null ? void 0 : base.telemetry) == null ? void 0 : _h.enabled) || Boolean(licenseKey);
|
|
2169
2448
|
const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
|
|
2170
|
-
const
|
|
2171
|
-
const embeddingProvider = readEnum(env, "EMBEDDING_PROVIDER", "openai", EMBEDDING_PROVIDERS);
|
|
2172
|
-
const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 1536);
|
|
2449
|
+
const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 768);
|
|
2173
2450
|
const vectorDbOptions = {};
|
|
2174
2451
|
if (vectorProvider === "pinecone") {
|
|
2175
2452
|
vectorDbOptions.apiKey = (_l = (_k = readString(env, "PINECONE_API_KEY")) != null ? _k : (_j = (_i = base == null ? void 0 : base.vectorDb) == null ? void 0 : _i.options) == null ? void 0 : _j.apiKey) != null ? _l : "";
|
|
@@ -2234,65 +2511,88 @@ function getEnvConfig(env = process.env, base) {
|
|
|
2234
2511
|
rest: "default",
|
|
2235
2512
|
custom: "default"
|
|
2236
2513
|
};
|
|
2514
|
+
const isFreeTier = (() => {
|
|
2515
|
+
if (!licenseKey) return true;
|
|
2516
|
+
try {
|
|
2517
|
+
const payload = LicenseVerifier.verify(licenseKey, projectId);
|
|
2518
|
+
const tier = (payload.tier || "").toLowerCase();
|
|
2519
|
+
return tier === "free_trial" || tier === "free_tier" || tier === "free" || tier === "hobby";
|
|
2520
|
+
} catch (e) {
|
|
2521
|
+
return true;
|
|
2522
|
+
}
|
|
2523
|
+
})();
|
|
2524
|
+
const DEFAULT_FREE_GATEWAY = "https://llm.retrivora.com/api/v1";
|
|
2525
|
+
const defaultLlmProvider = isFreeTier ? "universal_rest" : "universal_rest";
|
|
2526
|
+
const llmProvider = (_na = (_ma = readEnum(env, "LLM_PROVIDER", defaultLlmProvider, LLM_PROVIDERS)) != null ? _ma : (_la = base == null ? void 0 : base.llm) == null ? void 0 : _la.provider) != null ? _na : defaultLlmProvider;
|
|
2527
|
+
const llmBaseUrl = (_qa = (_pa = readString(env, "LLM_BASE_URL")) != null ? _pa : (_oa = base == null ? void 0 : base.llm) == null ? void 0 : _oa.baseUrl) != null ? _qa : DEFAULT_FREE_GATEWAY;
|
|
2528
|
+
const llmModel = (_ua = (_sa = readString(env, "LLM_MODEL")) != null ? _sa : (_ra = base == null ? void 0 : base.llm) == null ? void 0 : _ra.model) != null ? _ua : isFreeTier ? "llama-3.1-8b-instant" : (_ta = DEFAULT_MODEL_BY_PROVIDER[llmProvider]) != null ? _ta : "gpt-4o";
|
|
2529
|
+
const llmApiKey = (_ya = (_xa = (_va = llmApiKeyByProvider[llmProvider]) != null ? _va : readString(env, "LLM_API_KEY")) != null ? _xa : (_wa = base == null ? void 0 : base.llm) == null ? void 0 : _wa.apiKey) != null ? _ya : "sk-retrivora-cancer-280590";
|
|
2530
|
+
const llmProfile = (_Ca = (_Ba = readString(env, "LLM_UNIVERSAL_PROFILE")) != null ? _Ba : (_Aa = (_za = base == null ? void 0 : base.llm) == null ? void 0 : _za.options) == null ? void 0 : _Aa.profile) != null ? _Ca : "litellm";
|
|
2531
|
+
const defaultEmbeddingProvider = isFreeTier ? "universal_rest" : "universal_rest";
|
|
2532
|
+
const embeddingProvider = (_Fa = (_Ea = readEnum(env, "EMBEDDING_PROVIDER", defaultEmbeddingProvider, EMBEDDING_PROVIDERS)) != null ? _Ea : (_Da = base == null ? void 0 : base.embedding) == null ? void 0 : _Da.provider) != null ? _Fa : defaultEmbeddingProvider;
|
|
2533
|
+
const embeddingBaseUrl = (_Ia = (_Ha = readString(env, "EMBEDDING_BASE_URL")) != null ? _Ha : (_Ga = base == null ? void 0 : base.embedding) == null ? void 0 : _Ga.baseUrl) != null ? _Ia : DEFAULT_FREE_GATEWAY;
|
|
2534
|
+
const embeddingModel = (_La = (_Ka = readString(env, "EMBEDDING_MODEL")) != null ? _Ka : (_Ja = base == null ? void 0 : base.embedding) == null ? void 0 : _Ja.model) != null ? _La : "text-embedding-004";
|
|
2535
|
+
const embeddingApiKey = (_Qa = (_Pa = (_Na = (_Ma = embeddingApiKeyByProvider[embeddingProvider]) != null ? _Ma : readString(env, "EMBEDDING_API_KEY")) != null ? _Na : readString(env, "LLM_API_KEY")) != null ? _Pa : (_Oa = base == null ? void 0 : base.embedding) == null ? void 0 : _Oa.apiKey) != null ? _Qa : "sk-retrivora-cancer-280590";
|
|
2536
|
+
const embeddingProfile = (_Ua = (_Ta = readString(env, "EMBEDDING_UNIVERSAL_PROFILE")) != null ? _Ta : (_Sa = (_Ra = base == null ? void 0 : base.embedding) == null ? void 0 : _Ra.options) == null ? void 0 : _Sa.profile) != null ? _Ua : "litellm";
|
|
2237
2537
|
return __spreadProps(__spreadValues({
|
|
2238
2538
|
projectId,
|
|
2239
|
-
licenseKey
|
|
2539
|
+
licenseKey,
|
|
2240
2540
|
vectorDb: {
|
|
2241
2541
|
provider: vectorProvider,
|
|
2242
|
-
indexName: (
|
|
2542
|
+
indexName: (_Wa = (_Va = readString(env, "VECTOR_DB_INDEX")) != null ? _Va : vectorDbOptions.indexName) != null ? _Wa : "rag-index",
|
|
2243
2543
|
options: vectorDbOptions
|
|
2244
2544
|
},
|
|
2245
2545
|
llm: {
|
|
2246
2546
|
provider: llmProvider,
|
|
2247
|
-
model:
|
|
2248
|
-
apiKey:
|
|
2249
|
-
baseUrl:
|
|
2547
|
+
model: llmModel,
|
|
2548
|
+
apiKey: llmApiKey,
|
|
2549
|
+
baseUrl: llmBaseUrl,
|
|
2250
2550
|
systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
|
|
2251
2551
|
maxTokens: readNumber(env, "LLM_MAX_TOKENS", 4096),
|
|
2252
2552
|
temperature: readNumber(env, "LLM_TEMPERATURE", 0.7),
|
|
2253
2553
|
options: {
|
|
2254
|
-
profile:
|
|
2554
|
+
profile: llmProfile,
|
|
2255
2555
|
thinking: readString(env, "LLM_THINKING") === "true" || readString(env, "LLM_THINKING") === "enabled" ? true : readString(env, "LLM_THINKING") === "false" ? false : void 0,
|
|
2256
2556
|
thinkingBudget: env.LLM_THINKING_BUDGET ? parseInt(env.LLM_THINKING_BUDGET, 10) : void 0
|
|
2257
2557
|
}
|
|
2258
2558
|
},
|
|
2259
2559
|
embedding: {
|
|
2260
2560
|
provider: embeddingProvider,
|
|
2261
|
-
model:
|
|
2262
|
-
apiKey:
|
|
2263
|
-
baseUrl:
|
|
2561
|
+
model: embeddingModel,
|
|
2562
|
+
apiKey: embeddingApiKey,
|
|
2563
|
+
baseUrl: embeddingBaseUrl,
|
|
2264
2564
|
dimensions: embeddingDimensions,
|
|
2265
2565
|
queryPrefix: readString(env, "EMBEDDING_QUERY_PREFIX"),
|
|
2266
2566
|
documentPrefix: readString(env, "EMBEDDING_DOCUMENT_PREFIX"),
|
|
2267
2567
|
options: {
|
|
2268
|
-
profile:
|
|
2568
|
+
profile: embeddingProfile
|
|
2269
2569
|
}
|
|
2270
2570
|
},
|
|
2271
2571
|
ui: {
|
|
2272
|
-
title: (
|
|
2273
|
-
subtitle: (
|
|
2274
|
-
primaryColor: (
|
|
2275
|
-
accentColor: (
|
|
2276
|
-
logoUrl: (
|
|
2277
|
-
placeholder: (
|
|
2278
|
-
showSources: ((
|
|
2279
|
-
welcomeMessage: (
|
|
2280
|
-
visualStyle: (
|
|
2281
|
-
borderRadius: (
|
|
2282
|
-
allowUpload: ((
|
|
2572
|
+
title: (_Ya = (_Xa = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _Xa : readString(env, "UI_TITLE")) != null ? _Ya : "AI Assistant",
|
|
2573
|
+
subtitle: (__a = (_Za = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _Za : readString(env, "UI_SUBTITLE")) != null ? __a : "Powered by RAG",
|
|
2574
|
+
primaryColor: (_ab = (_$a = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _$a : readString(env, "UI_PRIMARY_COLOR")) != null ? _ab : "#10b981",
|
|
2575
|
+
accentColor: (_cb = (_bb = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _bb : readString(env, "UI_ACCENT_COLOR")) != null ? _cb : "#3b82f6",
|
|
2576
|
+
logoUrl: (_db = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _db : readString(env, "UI_LOGO_URL"),
|
|
2577
|
+
placeholder: (_fb = (_eb = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _eb : readString(env, "UI_PLACEHOLDER")) != null ? _fb : "Ask me anything\u2026",
|
|
2578
|
+
showSources: ((_hb = (_gb = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _gb : readString(env, "UI_SHOW_SOURCES")) != null ? _hb : "true") !== "false",
|
|
2579
|
+
welcomeMessage: (_jb = (_ib = readString(env, "NEXT_PUBLIC_WELCOME_MESSAGE")) != null ? _ib : readString(env, "UI_WELCOME_MESSAGE")) != null ? _jb : "Hello! I'm your AI assistant. Ask me anything about your documents.",
|
|
2580
|
+
visualStyle: (_lb = (_kb = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _kb : readString(env, "UI_VISUAL_STYLE")) != null ? _lb : "glass",
|
|
2581
|
+
borderRadius: (_nb = (_mb = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _mb : readString(env, "UI_BORDER_RADIUS")) != null ? _nb : "xl",
|
|
2582
|
+
allowUpload: ((_pb = (_ob = readString(env, "NEXT_PUBLIC_ALLOW_UPLOAD")) != null ? _ob : readString(env, "UI_ALLOW_UPLOAD")) != null ? _pb : "false") === "true"
|
|
2283
2583
|
},
|
|
2284
2584
|
rag: {
|
|
2285
2585
|
topK: readNumber(env, "RAG_TOP_K", 5),
|
|
2286
2586
|
scoreThreshold: readNumber(env, "RAG_SCORE_THRESHOLD", 0),
|
|
2287
2587
|
chunkSize: readNumber(env, "RAG_CHUNK_SIZE", 1e3),
|
|
2288
2588
|
chunkOverlap: readNumber(env, "RAG_CHUNK_OVERLAP", 200),
|
|
2289
|
-
filterableFields: (
|
|
2589
|
+
filterableFields: (_qb = readString(env, "RAG_FILTERABLE_FIELDS")) == null ? void 0 : _qb.split(",").map((f) => f.trim()),
|
|
2290
2590
|
// Query pipeline toggles — read from .env.local
|
|
2291
2591
|
useQueryTransformation: readString(env, "RAG_USE_QUERY_TRANSFORMATION") === "true",
|
|
2292
2592
|
useReranking: readString(env, "RAG_USE_RERANKING") === "true",
|
|
2293
2593
|
useGraphRetrieval: readString(env, "RAG_USE_GRAPH_RETRIEVAL") === "true",
|
|
2294
|
-
architecture: (
|
|
2295
|
-
chunkingStrategy: (
|
|
2594
|
+
architecture: (_rb = readString(env, "RAG_ARCHITECTURE")) != null ? _rb : "simple",
|
|
2595
|
+
chunkingStrategy: (_sb = readString(env, "RAG_CHUNKING_STRATEGY")) != null ? _sb : "recursive",
|
|
2296
2596
|
uiMapping: (() => {
|
|
2297
2597
|
const raw = readString(env, "RAG_UI_MAPPING");
|
|
2298
2598
|
if (!raw) return void 0;
|
|
@@ -2305,7 +2605,7 @@ function getEnvConfig(env = process.env, base) {
|
|
|
2305
2605
|
},
|
|
2306
2606
|
telemetry: {
|
|
2307
2607
|
enabled: telemetryEnabled,
|
|
2308
|
-
url: (
|
|
2608
|
+
url: (_wb = (_vb = (_tb = readString(env, "TELEMETRY_URL")) != null ? _tb : readString(env, "NEXT_PUBLIC_TELEMETRY_URL")) != null ? _vb : (_ub = base == null ? void 0 : base.telemetry) == null ? void 0 : _ub.url) != null ? _wb : process.env.NODE_ENV === "development" ? "http://localhost:3001/api/telemetry" : "https://retrivora.com/api/telemetry"
|
|
2309
2609
|
}
|
|
2310
2610
|
}, readString(env, "GRAPH_DB_PROVIDER") ? {
|
|
2311
2611
|
graphDb: {
|
|
@@ -2792,10 +3092,12 @@ var AnthropicProvider = class {
|
|
|
2792
3092
|
var import_axios = __toESM(require("axios"));
|
|
2793
3093
|
var OllamaProvider = class {
|
|
2794
3094
|
constructor(llmConfig, embeddingConfig) {
|
|
2795
|
-
var _a2, _b;
|
|
2796
|
-
const
|
|
3095
|
+
var _a2, _b, _c;
|
|
3096
|
+
const rawBaseURL = ((_a2 = llmConfig.baseUrl) != null ? _a2 : "http://localhost:11434").replace(/\/+$/, "");
|
|
3097
|
+
const baseURL = rawBaseURL.replace(/\/(?:api\/v1|v1|api)$/i, "");
|
|
2797
3098
|
const timeout = Number((_b = llmConfig.options) == null ? void 0 : _b.timeout) || 3e5;
|
|
2798
|
-
|
|
3099
|
+
const headers = ((_c = llmConfig.options) == null ? void 0 : _c.headers) || {};
|
|
3100
|
+
this.http = import_axios.default.create({ baseURL, timeout, headers });
|
|
2799
3101
|
this.llmConfig = llmConfig;
|
|
2800
3102
|
this.embeddingConfig = embeddingConfig;
|
|
2801
3103
|
}
|
|
@@ -3731,113 +4033,41 @@ ${context != null ? context : "None"}` },
|
|
|
3731
4033
|
if (this.opts.embedPayloadTemplate) {
|
|
3732
4034
|
payload = buildPayload(this.opts.embedPayloadTemplate, {
|
|
3733
4035
|
model: this.model,
|
|
3734
|
-
input: text
|
|
3735
|
-
});
|
|
3736
|
-
} else {
|
|
3737
|
-
payload = {
|
|
3738
|
-
model: this.model,
|
|
3739
|
-
input: text
|
|
3740
|
-
};
|
|
3741
|
-
}
|
|
3742
|
-
const { data } = await this.http.post(path2, payload);
|
|
3743
|
-
const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
|
|
3744
|
-
const vector = resolvePath(data, extractPath);
|
|
3745
|
-
if (!Array.isArray(vector)) {
|
|
3746
|
-
throw new Error(`[UniversalLLMAdapter] Expected a number array at '${extractPath}' for embeddings.`);
|
|
3747
|
-
}
|
|
3748
|
-
return vector;
|
|
3749
|
-
}
|
|
3750
|
-
async batchEmbed(texts) {
|
|
3751
|
-
const vectors = [];
|
|
3752
|
-
for (const text of texts) {
|
|
3753
|
-
vectors.push(await this.embed(text));
|
|
3754
|
-
}
|
|
3755
|
-
return vectors;
|
|
3756
|
-
}
|
|
3757
|
-
async ping() {
|
|
3758
|
-
try {
|
|
3759
|
-
if (this.opts.pingPath) {
|
|
3760
|
-
await this.http.get(this.opts.pingPath);
|
|
3761
|
-
}
|
|
3762
|
-
return true;
|
|
3763
|
-
} catch (err) {
|
|
3764
|
-
console.error("[UniversalLLMAdapter] Ping failed:", err);
|
|
3765
|
-
return false;
|
|
3766
|
-
}
|
|
3767
|
-
}
|
|
3768
|
-
};
|
|
3769
|
-
|
|
3770
|
-
// src/exceptions/index.ts
|
|
3771
|
-
var RetrivoraError = class extends Error {
|
|
3772
|
-
constructor(message, code, details) {
|
|
3773
|
-
super(message);
|
|
3774
|
-
this.name = new.target.name;
|
|
3775
|
-
this.code = code;
|
|
3776
|
-
this.details = details;
|
|
3777
|
-
}
|
|
3778
|
-
};
|
|
3779
|
-
var ProviderNotFoundException = class extends RetrivoraError {
|
|
3780
|
-
constructor(providerType, provider, details) {
|
|
3781
|
-
super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
|
|
3782
|
-
}
|
|
3783
|
-
};
|
|
3784
|
-
var EmbeddingFailedException = class extends RetrivoraError {
|
|
3785
|
-
constructor(message = "Embedding generation failed", details) {
|
|
3786
|
-
super(message, "EMBEDDING_FAILED", details);
|
|
3787
|
-
}
|
|
3788
|
-
};
|
|
3789
|
-
var RetrievalException = class extends RetrivoraError {
|
|
3790
|
-
constructor(message = "Retrieval failed", details) {
|
|
3791
|
-
super(message, "RETRIEVAL_FAILED", details);
|
|
3792
|
-
}
|
|
3793
|
-
};
|
|
3794
|
-
var RateLimitException = class extends RetrivoraError {
|
|
3795
|
-
constructor(message = "Provider rate limit exceeded", details) {
|
|
3796
|
-
super(message, "RATE_LIMITED", details);
|
|
3797
|
-
}
|
|
3798
|
-
};
|
|
3799
|
-
var ConfigurationException = class extends RetrivoraError {
|
|
3800
|
-
constructor(message, details) {
|
|
3801
|
-
super(message, "CONFIGURATION_ERROR", details);
|
|
3802
|
-
}
|
|
3803
|
-
};
|
|
3804
|
-
var AuthenticationException = class extends RetrivoraError {
|
|
3805
|
-
constructor(message = "Provider authentication failed", details) {
|
|
3806
|
-
super(message, "AUTHENTICATION_ERROR", details);
|
|
3807
|
-
}
|
|
3808
|
-
};
|
|
3809
|
-
function wrapError(err, defaultCode, defaultMessage) {
|
|
3810
|
-
var _a2;
|
|
3811
|
-
if (err instanceof RetrivoraError) {
|
|
3812
|
-
return err;
|
|
3813
|
-
}
|
|
3814
|
-
const error = err;
|
|
3815
|
-
const message = (error == null ? void 0 : error.message) || defaultMessage || String(err);
|
|
3816
|
-
const status = (error == null ? void 0 : error.status) || (error == null ? void 0 : error.statusCode) || ((_a2 = error == null ? void 0 : error.response) == null ? void 0 : _a2.status);
|
|
3817
|
-
const code = error == null ? void 0 : error.code;
|
|
3818
|
-
if (status === 429 || /rate[- ]?limit/i.test(message) || code === "RATE_LIMIT_EXCEEDED") {
|
|
3819
|
-
return new RateLimitException(message, err);
|
|
4036
|
+
input: text
|
|
4037
|
+
});
|
|
4038
|
+
} else {
|
|
4039
|
+
payload = {
|
|
4040
|
+
model: this.model,
|
|
4041
|
+
input: text
|
|
4042
|
+
};
|
|
4043
|
+
}
|
|
4044
|
+
const { data } = await this.http.post(path2, payload);
|
|
4045
|
+
const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
|
|
4046
|
+
const vector = resolvePath(data, extractPath);
|
|
4047
|
+
if (!Array.isArray(vector)) {
|
|
4048
|
+
throw new Error(`[UniversalLLMAdapter] Expected a number array at '${extractPath}' for embeddings.`);
|
|
4049
|
+
}
|
|
4050
|
+
return vector;
|
|
3820
4051
|
}
|
|
3821
|
-
|
|
3822
|
-
|
|
4052
|
+
async batchEmbed(texts) {
|
|
4053
|
+
const vectors = [];
|
|
4054
|
+
for (const text of texts) {
|
|
4055
|
+
vectors.push(await this.embed(text));
|
|
4056
|
+
}
|
|
4057
|
+
return vectors;
|
|
3823
4058
|
}
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
return
|
|
3833
|
-
|
|
3834
|
-
return new ConfigurationException(message, err);
|
|
3835
|
-
case "AUTHENTICATION_ERROR":
|
|
3836
|
-
return new AuthenticationException(message, err);
|
|
3837
|
-
default:
|
|
3838
|
-
return new RetrivoraError(message, defaultCode, err);
|
|
4059
|
+
async ping() {
|
|
4060
|
+
try {
|
|
4061
|
+
if (this.opts.pingPath) {
|
|
4062
|
+
await this.http.get(this.opts.pingPath);
|
|
4063
|
+
}
|
|
4064
|
+
return true;
|
|
4065
|
+
} catch (err) {
|
|
4066
|
+
console.error("[UniversalLLMAdapter] Ping failed:", err);
|
|
4067
|
+
return false;
|
|
4068
|
+
}
|
|
3839
4069
|
}
|
|
3840
|
-
}
|
|
4070
|
+
};
|
|
3841
4071
|
|
|
3842
4072
|
// src/llm/LLMFactory.ts
|
|
3843
4073
|
var customProviders = /* @__PURE__ */ new Map();
|
|
@@ -8764,211 +8994,6 @@ var ProviderHealthCheck = class {
|
|
|
8764
8994
|
}
|
|
8765
8995
|
};
|
|
8766
8996
|
|
|
8767
|
-
// src/core/LicenseVerifier.ts
|
|
8768
|
-
var crypto2 = __toESM(require("crypto"));
|
|
8769
|
-
var LicenseVerifier = class {
|
|
8770
|
-
/**
|
|
8771
|
-
* Decodes, verifies signature, and checks metadata of a license key.
|
|
8772
|
-
*
|
|
8773
|
-
* @param licenseKey - Base64url signed JWT license key.
|
|
8774
|
-
* @param currentProjectId - Project namespace ID.
|
|
8775
|
-
* @param publicKeyOverride - Optional override for unit/integration tests.
|
|
8776
|
-
*/
|
|
8777
|
-
static verify(licenseKey, currentProjectId, provider, publicKeyOverride) {
|
|
8778
|
-
const isProduction = process.env.NODE_ENV === "production";
|
|
8779
|
-
const now = Date.now();
|
|
8780
|
-
if (licenseKey) {
|
|
8781
|
-
const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
|
|
8782
|
-
const cached = this.cache.get(cacheKey);
|
|
8783
|
-
if (cached && now - cached.cachedAt < this.CACHE_TTL_MS) {
|
|
8784
|
-
const currentTimestampSec = Math.floor(now / 1e3);
|
|
8785
|
-
if (cached.payload.expiresAt && currentTimestampSec > cached.payload.expiresAt) {
|
|
8786
|
-
this.cache.delete(cacheKey);
|
|
8787
|
-
} else {
|
|
8788
|
-
return cached.payload;
|
|
8789
|
-
}
|
|
8790
|
-
}
|
|
8791
|
-
}
|
|
8792
|
-
if (!licenseKey) {
|
|
8793
|
-
if (isProduction) {
|
|
8794
|
-
throw new ConfigurationException(
|
|
8795
|
-
"[Retrivora SDK] License key (licenseKey) is required in production environments."
|
|
8796
|
-
);
|
|
8797
|
-
}
|
|
8798
|
-
console.warn(
|
|
8799
|
-
`\x1B[33m[Retrivora SDK] WARNING: Running without a license key. This namespace (${currentProjectId}) is permitted for local development only.\x1B[0m`
|
|
8800
|
-
);
|
|
8801
|
-
return {
|
|
8802
|
-
projectId: currentProjectId,
|
|
8803
|
-
expiresAt: Math.floor(Date.now() / 1e3) + 86400,
|
|
8804
|
-
// Valid for 24h
|
|
8805
|
-
tier: "hobby"
|
|
8806
|
-
};
|
|
8807
|
-
}
|
|
8808
|
-
try {
|
|
8809
|
-
const parts = licenseKey.split(".");
|
|
8810
|
-
if (parts.length !== 3) {
|
|
8811
|
-
throw new Error("Malformed token structure (expected 3 parts).");
|
|
8812
|
-
}
|
|
8813
|
-
const [headerB64, payloadB64, signatureB64] = parts;
|
|
8814
|
-
const dataToVerify = `${headerB64}.${payloadB64}`;
|
|
8815
|
-
const publicKey = publicKeyOverride != null ? publicKeyOverride : this.PUBLIC_KEY;
|
|
8816
|
-
const signature = Buffer.from(signatureB64, "base64url");
|
|
8817
|
-
const data = Buffer.from(dataToVerify);
|
|
8818
|
-
const isValid = crypto2.verify(
|
|
8819
|
-
"sha256",
|
|
8820
|
-
data,
|
|
8821
|
-
publicKey,
|
|
8822
|
-
signature
|
|
8823
|
-
);
|
|
8824
|
-
if (!isValid) {
|
|
8825
|
-
throw new Error("Signature verification failed.");
|
|
8826
|
-
}
|
|
8827
|
-
const payload = JSON.parse(
|
|
8828
|
-
Buffer.from(payloadB64, "base64url").toString("utf8")
|
|
8829
|
-
);
|
|
8830
|
-
if (!payload.projectId) {
|
|
8831
|
-
throw new Error('License payload is missing "projectId".');
|
|
8832
|
-
}
|
|
8833
|
-
if (payload.projectId !== currentProjectId) {
|
|
8834
|
-
throw new Error(
|
|
8835
|
-
`Project ID mismatch. License is bound to project namespace "${payload.projectId}" but configuration has "${currentProjectId}".`
|
|
8836
|
-
);
|
|
8837
|
-
}
|
|
8838
|
-
if (!payload.expiresAt) {
|
|
8839
|
-
throw new Error('License payload is missing expiration ("expiresAt").');
|
|
8840
|
-
}
|
|
8841
|
-
const currentTimestampSec = Math.floor(Date.now() / 1e3);
|
|
8842
|
-
if (currentTimestampSec > payload.expiresAt) {
|
|
8843
|
-
throw new Error(
|
|
8844
|
-
`License key has expired. Expiration: ${new Date(
|
|
8845
|
-
payload.expiresAt * 1e3
|
|
8846
|
-
).toDateString()}`
|
|
8847
|
-
);
|
|
8848
|
-
}
|
|
8849
|
-
if (isProduction && provider) {
|
|
8850
|
-
const tier = (payload.tier || "").toLowerCase();
|
|
8851
|
-
const normalizedProvider = provider.toLowerCase();
|
|
8852
|
-
if (tier === "hobby") {
|
|
8853
|
-
const allowedHobby = ["postgresql", "pgvector", "supabase"];
|
|
8854
|
-
if (!allowedHobby.includes(normalizedProvider)) {
|
|
8855
|
-
throw new Error(
|
|
8856
|
-
`The database provider "${provider}" is not allowed on the Hobby tier. Hobby tier is restricted to PostgreSQL and Supabase. Please upgrade to a Developer Pro or Enterprise plan.`
|
|
8857
|
-
);
|
|
8858
|
-
}
|
|
8859
|
-
} else if (tier === "pro" || tier === "developer_pro" || tier === "premium" || tier === "growth") {
|
|
8860
|
-
const allowedPro = [
|
|
8861
|
-
"postgresql",
|
|
8862
|
-
"pgvector",
|
|
8863
|
-
"supabase",
|
|
8864
|
-
"pinecone",
|
|
8865
|
-
"qdrant",
|
|
8866
|
-
"mongodb",
|
|
8867
|
-
"milvus",
|
|
8868
|
-
"chroma",
|
|
8869
|
-
"chromadb"
|
|
8870
|
-
];
|
|
8871
|
-
if (!allowedPro.includes(normalizedProvider)) {
|
|
8872
|
-
throw new Error(
|
|
8873
|
-
`The database provider "${provider}" is not allowed on the Developer Pro tier. Please upgrade to an Enterprise plan.`
|
|
8874
|
-
);
|
|
8875
|
-
}
|
|
8876
|
-
}
|
|
8877
|
-
}
|
|
8878
|
-
if (licenseKey) {
|
|
8879
|
-
const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
|
|
8880
|
-
this.cache.set(cacheKey, { payload, cachedAt: now });
|
|
8881
|
-
}
|
|
8882
|
-
return payload;
|
|
8883
|
-
} catch (err) {
|
|
8884
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
8885
|
-
throw new ConfigurationException(
|
|
8886
|
-
`[Retrivora SDK] License key validation failed: ${message}`
|
|
8887
|
-
);
|
|
8888
|
-
}
|
|
8889
|
-
}
|
|
8890
|
-
static async verifyIP(licenseKey) {
|
|
8891
|
-
if (!licenseKey) return;
|
|
8892
|
-
try {
|
|
8893
|
-
const parts = licenseKey.split(".");
|
|
8894
|
-
if (parts.length !== 3) return;
|
|
8895
|
-
const [, payloadB64] = parts;
|
|
8896
|
-
const payload = JSON.parse(
|
|
8897
|
-
Buffer.from(payloadB64, "base64url").toString("utf8")
|
|
8898
|
-
);
|
|
8899
|
-
const tier = (payload.tier || "").toLowerCase();
|
|
8900
|
-
if (tier === "enterprise" || tier === "custom") {
|
|
8901
|
-
return;
|
|
8902
|
-
}
|
|
8903
|
-
if (payload.ipv4 || payload.ipv6) {
|
|
8904
|
-
let currentIpv4 = "";
|
|
8905
|
-
let currentIpv6 = "";
|
|
8906
|
-
try {
|
|
8907
|
-
const res = await fetch("https://api4.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
|
|
8908
|
-
const data = await res.json();
|
|
8909
|
-
currentIpv4 = data.ip;
|
|
8910
|
-
} catch (e) {
|
|
8911
|
-
}
|
|
8912
|
-
try {
|
|
8913
|
-
const res = await fetch("https://api6.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
|
|
8914
|
-
const data = await res.json();
|
|
8915
|
-
currentIpv6 = data.ip;
|
|
8916
|
-
} catch (e) {
|
|
8917
|
-
}
|
|
8918
|
-
const localIps = [];
|
|
8919
|
-
try {
|
|
8920
|
-
const osModule = require("os");
|
|
8921
|
-
const interfaces = osModule.networkInterfaces();
|
|
8922
|
-
for (const name of Object.keys(interfaces)) {
|
|
8923
|
-
for (const iface of interfaces[name] || []) {
|
|
8924
|
-
if (!iface.internal) {
|
|
8925
|
-
localIps.push(iface.address);
|
|
8926
|
-
}
|
|
8927
|
-
}
|
|
8928
|
-
}
|
|
8929
|
-
} catch (e) {
|
|
8930
|
-
}
|
|
8931
|
-
const isIpv4Match = payload.ipv4 && (currentIpv4 === payload.ipv4 || localIps.includes(payload.ipv4));
|
|
8932
|
-
const isIpv6Match = payload.ipv6 && (currentIpv6 === payload.ipv6 || localIps.includes(payload.ipv6));
|
|
8933
|
-
if (payload.ipv4 && payload.ipv6) {
|
|
8934
|
-
if (!isIpv4Match && !isIpv6Match) {
|
|
8935
|
-
throw new Error(
|
|
8936
|
-
`License key access restricted. This license key was created for a different system (authorized IPv4: ${payload.ipv4}, IPv6: ${payload.ipv6}) and cannot be used on this machine.`
|
|
8937
|
-
);
|
|
8938
|
-
}
|
|
8939
|
-
} else if (payload.ipv4 && !isIpv4Match) {
|
|
8940
|
-
throw new Error(
|
|
8941
|
-
`License key access restricted. This license key was created for a different system (authorized IPv4: ${payload.ipv4}) and cannot be used on this machine.`
|
|
8942
|
-
);
|
|
8943
|
-
} else if (payload.ipv6 && !isIpv6Match) {
|
|
8944
|
-
throw new Error(
|
|
8945
|
-
`License key access restricted. This license key was created for a different system (authorized IPv6: ${payload.ipv6}) and cannot be used on this machine.`
|
|
8946
|
-
);
|
|
8947
|
-
}
|
|
8948
|
-
}
|
|
8949
|
-
} catch (err) {
|
|
8950
|
-
if (err.message.includes("License key access restricted")) {
|
|
8951
|
-
throw new ConfigurationException(`[Retrivora SDK] ${err.message}`);
|
|
8952
|
-
}
|
|
8953
|
-
}
|
|
8954
|
-
}
|
|
8955
|
-
};
|
|
8956
|
-
// A simple in-memory cache to save CPU overhead of cryptographic signature checks.
|
|
8957
|
-
LicenseVerifier.cache = /* @__PURE__ */ new Map();
|
|
8958
|
-
LicenseVerifier.CACHE_TTL_MS = 60 * 1e3;
|
|
8959
|
-
// Cache verified license for 60 seconds
|
|
8960
|
-
// Retrivora's Public Key used to verify the license key signature.
|
|
8961
|
-
// In production, this matches the private key held by Retrivora SaaS.
|
|
8962
|
-
LicenseVerifier.PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
|
|
8963
|
-
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMieCkCBtTfByRNOserm
|
|
8964
|
-
XM4T0Am29JyNzB4XQPe+WJJ56CN73H1HLXx9n1ByFcxkEJ9po+SURj5DnvUXwEy+
|
|
8965
|
-
xstx33wDPpVmcMQe33j5CRYS0S4gICiNqIRN7XkTlJtrcXqrmh1/hdOAwfRbjO1T
|
|
8966
|
-
NVtORHwUwWfI/lBLyxUPGtKPed+0fQ7NtcW4o00JXxs3EjCB5BV9CbnXoTjQb/4h
|
|
8967
|
-
iwZof4l8rb7oaNzOsVg0RSyxsETX7Ex5sI0CjBz1p2mYp4oVhw/A/h8Ls7H0XzjC
|
|
8968
|
-
+Eb6BLtsytt5JHoSp0jExLlCpDmpys2L+kETcBVx+IqiXtdN1n6KbkksvEDUVzLI
|
|
8969
|
-
MwIDAQAB
|
|
8970
|
-
-----END PUBLIC KEY-----`;
|
|
8971
|
-
|
|
8972
8997
|
// src/core/VectorPlugin.ts
|
|
8973
8998
|
var VectorPlugin = class {
|
|
8974
8999
|
constructor(hostConfig) {
|
|
@@ -9229,7 +9254,7 @@ var DatabaseStorage = class {
|
|
|
9229
9254
|
try {
|
|
9230
9255
|
const payload = LicenseVerifier.verify(this.config.licenseKey, this.config.projectId);
|
|
9231
9256
|
const tier = (payload.tier || "").toLowerCase();
|
|
9232
|
-
if (tier !== "premium" && tier !== "enterprise" && tier !== "growth" && tier !== "pro" && tier !== "developer_pro") {
|
|
9257
|
+
if (tier !== "premium" && tier !== "enterprise" && tier !== "growth" && tier !== "pro" && tier !== "developer_pro" && tier !== "free_trial" && tier !== "free_tier" && tier !== "free" && tier !== "hobby") {
|
|
9233
9258
|
throw new Error(
|
|
9234
9259
|
`[Retrivora SDK] Chat History and Feedback features are not available on the "${tier}" tier. Please upgrade to a Developer Pro or Enterprise plan.`
|
|
9235
9260
|
);
|
|
@@ -9766,7 +9791,17 @@ function createChatHandler(configOrPlugin, options) {
|
|
|
9766
9791
|
if (rateLimited) return rateLimited;
|
|
9767
9792
|
try {
|
|
9768
9793
|
const body = await req.json();
|
|
9769
|
-
const
|
|
9794
|
+
const bodyObj = body != null ? body : {};
|
|
9795
|
+
let rawMessage = bodyObj.message;
|
|
9796
|
+
if (!rawMessage && Array.isArray(bodyObj.messages) && bodyObj.messages.length > 0) {
|
|
9797
|
+
const lastMsg = bodyObj.messages[bodyObj.messages.length - 1];
|
|
9798
|
+
rawMessage = typeof lastMsg === "string" ? lastMsg : (lastMsg == null ? void 0 : lastMsg.content) || (lastMsg == null ? void 0 : lastMsg.text);
|
|
9799
|
+
}
|
|
9800
|
+
if (!rawMessage && typeof bodyObj.prompt === "string") {
|
|
9801
|
+
rawMessage = bodyObj.prompt;
|
|
9802
|
+
}
|
|
9803
|
+
const history = bodyObj.history || (Array.isArray(bodyObj.messages) ? bodyObj.messages.slice(0, -1) : []);
|
|
9804
|
+
const { namespace, sessionId = "default", messageId, userMessageId } = bodyObj;
|
|
9770
9805
|
const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
|
|
9771
9806
|
if (!sanitized.ok) {
|
|
9772
9807
|
return import_server.NextResponse.json({ error: { code: "INVALID_INPUT", message: sanitized.error } }, { status: 400 });
|
|
@@ -9818,7 +9853,17 @@ function createStreamHandler(configOrPlugin, options) {
|
|
|
9818
9853
|
headers: { "Content-Type": "application/json" }
|
|
9819
9854
|
});
|
|
9820
9855
|
}
|
|
9821
|
-
const
|
|
9856
|
+
const bodyObj = body != null ? body : {};
|
|
9857
|
+
let rawMessage = bodyObj.message;
|
|
9858
|
+
if (!rawMessage && Array.isArray(bodyObj.messages) && bodyObj.messages.length > 0) {
|
|
9859
|
+
const lastMsg = bodyObj.messages[bodyObj.messages.length - 1];
|
|
9860
|
+
rawMessage = typeof lastMsg === "string" ? lastMsg : (lastMsg == null ? void 0 : lastMsg.content) || (lastMsg == null ? void 0 : lastMsg.text);
|
|
9861
|
+
}
|
|
9862
|
+
if (!rawMessage && typeof bodyObj.prompt === "string") {
|
|
9863
|
+
rawMessage = bodyObj.prompt;
|
|
9864
|
+
}
|
|
9865
|
+
const history = bodyObj.history || (Array.isArray(bodyObj.messages) ? bodyObj.messages.slice(0, -1) : []);
|
|
9866
|
+
const { namespace, sessionId = "default", messageId, userMessageId } = bodyObj;
|
|
9822
9867
|
const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
|
|
9823
9868
|
if (!sanitized.ok) {
|
|
9824
9869
|
return new Response(
|