@retrivora-ai/rag-engine 2.0.4 → 2.0.6
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 +486 -356
- package/dist/handlers/index.mjs +488 -358
- package/dist/server.js +486 -356
- package/dist/server.mjs +488 -358
- package/package.json +2 -2
- package/src/config/serverConfig.ts +40 -13
- package/src/core/DatabaseStorage.ts +26 -4
- package/src/core/Pipeline.ts +10 -5
- package/src/handlers/index.ts +22 -9
- package/src/index.css +3956 -0
- package/src/llm/providers/OllamaProvider.ts +4 -2
- package/src/llm/providers/UniversalLLMAdapter.ts +82 -12
package/dist/server.js
CHANGED
|
@@ -2151,6 +2151,285 @@ module.exports = __toCommonJS(server_exports);
|
|
|
2151
2151
|
// src/core/ConfigResolver.ts
|
|
2152
2152
|
init_templateUtils();
|
|
2153
2153
|
|
|
2154
|
+
// src/core/LicenseVerifier.ts
|
|
2155
|
+
var crypto = __toESM(require("crypto"));
|
|
2156
|
+
|
|
2157
|
+
// src/exceptions/index.ts
|
|
2158
|
+
var RetrivoraError = class extends Error {
|
|
2159
|
+
constructor(message, code, details) {
|
|
2160
|
+
super(message);
|
|
2161
|
+
this.name = new.target.name;
|
|
2162
|
+
this.code = code;
|
|
2163
|
+
this.details = details;
|
|
2164
|
+
}
|
|
2165
|
+
};
|
|
2166
|
+
var ProviderNotFoundException = class extends RetrivoraError {
|
|
2167
|
+
constructor(providerType, provider, details) {
|
|
2168
|
+
super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
|
|
2169
|
+
}
|
|
2170
|
+
};
|
|
2171
|
+
var EmbeddingFailedException = class extends RetrivoraError {
|
|
2172
|
+
constructor(message = "Embedding generation failed", details) {
|
|
2173
|
+
super(message, "EMBEDDING_FAILED", details);
|
|
2174
|
+
}
|
|
2175
|
+
};
|
|
2176
|
+
var RetrievalException = class extends RetrivoraError {
|
|
2177
|
+
constructor(message = "Retrieval failed", details) {
|
|
2178
|
+
super(message, "RETRIEVAL_FAILED", details);
|
|
2179
|
+
}
|
|
2180
|
+
};
|
|
2181
|
+
var RateLimitException = class extends RetrivoraError {
|
|
2182
|
+
constructor(message = "Provider rate limit exceeded", details) {
|
|
2183
|
+
super(message, "RATE_LIMITED", details);
|
|
2184
|
+
}
|
|
2185
|
+
};
|
|
2186
|
+
var ConfigurationException = class extends RetrivoraError {
|
|
2187
|
+
constructor(message, details) {
|
|
2188
|
+
super(message, "CONFIGURATION_ERROR", details);
|
|
2189
|
+
}
|
|
2190
|
+
};
|
|
2191
|
+
var AuthenticationException = class extends RetrivoraError {
|
|
2192
|
+
constructor(message = "Provider authentication failed", details) {
|
|
2193
|
+
super(message, "AUTHENTICATION_ERROR", details);
|
|
2194
|
+
}
|
|
2195
|
+
};
|
|
2196
|
+
function wrapError(err, defaultCode, defaultMessage) {
|
|
2197
|
+
var _a2;
|
|
2198
|
+
if (err instanceof RetrivoraError) {
|
|
2199
|
+
return err;
|
|
2200
|
+
}
|
|
2201
|
+
const error = err;
|
|
2202
|
+
const message = (error == null ? void 0 : error.message) || defaultMessage || String(err);
|
|
2203
|
+
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);
|
|
2204
|
+
const code = error == null ? void 0 : error.code;
|
|
2205
|
+
if (status === 429 || /rate[- ]?limit/i.test(message) || code === "RATE_LIMIT_EXCEEDED") {
|
|
2206
|
+
return new RateLimitException(message, err);
|
|
2207
|
+
}
|
|
2208
|
+
if (status === 401 || status === 403 || /unauthorized|auth|api[- ]?key/i.test(message) || code === "INVALID_API_KEY") {
|
|
2209
|
+
return new AuthenticationException(message, err);
|
|
2210
|
+
}
|
|
2211
|
+
switch (defaultCode) {
|
|
2212
|
+
case "PROVIDER_NOT_FOUND":
|
|
2213
|
+
return new ProviderNotFoundException("provider", message, err);
|
|
2214
|
+
case "EMBEDDING_FAILED":
|
|
2215
|
+
return new EmbeddingFailedException(message, err);
|
|
2216
|
+
case "RETRIEVAL_FAILED":
|
|
2217
|
+
return new RetrievalException(message, err);
|
|
2218
|
+
case "RATE_LIMITED":
|
|
2219
|
+
return new RateLimitException(message, err);
|
|
2220
|
+
case "CONFIGURATION_ERROR":
|
|
2221
|
+
return new ConfigurationException(message, err);
|
|
2222
|
+
case "AUTHENTICATION_ERROR":
|
|
2223
|
+
return new AuthenticationException(message, err);
|
|
2224
|
+
default:
|
|
2225
|
+
return new RetrivoraError(message, defaultCode, err);
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
// src/core/LicenseVerifier.ts
|
|
2230
|
+
var LicenseVerifier = class {
|
|
2231
|
+
/**
|
|
2232
|
+
* Decodes, verifies signature, and checks metadata of a license key.
|
|
2233
|
+
*
|
|
2234
|
+
* @param licenseKey - Base64url signed JWT license key.
|
|
2235
|
+
* @param currentProjectId - Project namespace ID.
|
|
2236
|
+
* @param publicKeyOverride - Optional override for unit/integration tests.
|
|
2237
|
+
*/
|
|
2238
|
+
static verify(licenseKey, currentProjectId, provider, publicKeyOverride) {
|
|
2239
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
2240
|
+
const now = Date.now();
|
|
2241
|
+
if (licenseKey) {
|
|
2242
|
+
const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
|
|
2243
|
+
const cached = this.cache.get(cacheKey);
|
|
2244
|
+
if (cached && now - cached.cachedAt < this.CACHE_TTL_MS) {
|
|
2245
|
+
const currentTimestampSec = Math.floor(now / 1e3);
|
|
2246
|
+
if (cached.payload.expiresAt && currentTimestampSec > cached.payload.expiresAt) {
|
|
2247
|
+
this.cache.delete(cacheKey);
|
|
2248
|
+
} else {
|
|
2249
|
+
return cached.payload;
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
if (!licenseKey) {
|
|
2254
|
+
if (isProduction) {
|
|
2255
|
+
throw new ConfigurationException(
|
|
2256
|
+
"[Retrivora SDK] License key (licenseKey) is required in production environments."
|
|
2257
|
+
);
|
|
2258
|
+
}
|
|
2259
|
+
console.warn(
|
|
2260
|
+
`\x1B[33m[Retrivora SDK] WARNING: Running without a license key. This namespace (${currentProjectId}) is permitted for local development only.\x1B[0m`
|
|
2261
|
+
);
|
|
2262
|
+
return {
|
|
2263
|
+
projectId: currentProjectId,
|
|
2264
|
+
expiresAt: Math.floor(Date.now() / 1e3) + 86400,
|
|
2265
|
+
// Valid for 24h
|
|
2266
|
+
tier: "hobby"
|
|
2267
|
+
};
|
|
2268
|
+
}
|
|
2269
|
+
try {
|
|
2270
|
+
const parts = licenseKey.split(".");
|
|
2271
|
+
if (parts.length !== 3) {
|
|
2272
|
+
throw new Error("Malformed token structure (expected 3 parts).");
|
|
2273
|
+
}
|
|
2274
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
2275
|
+
const dataToVerify = `${headerB64}.${payloadB64}`;
|
|
2276
|
+
const publicKey = publicKeyOverride != null ? publicKeyOverride : this.PUBLIC_KEY;
|
|
2277
|
+
const signature = Buffer.from(signatureB64, "base64url");
|
|
2278
|
+
const data = Buffer.from(dataToVerify);
|
|
2279
|
+
const isValid = crypto.verify(
|
|
2280
|
+
"sha256",
|
|
2281
|
+
data,
|
|
2282
|
+
publicKey,
|
|
2283
|
+
signature
|
|
2284
|
+
);
|
|
2285
|
+
if (!isValid) {
|
|
2286
|
+
throw new Error("Signature verification failed.");
|
|
2287
|
+
}
|
|
2288
|
+
const payload = JSON.parse(
|
|
2289
|
+
Buffer.from(payloadB64, "base64url").toString("utf8")
|
|
2290
|
+
);
|
|
2291
|
+
if (!payload.projectId) {
|
|
2292
|
+
throw new Error('License payload is missing "projectId".');
|
|
2293
|
+
}
|
|
2294
|
+
if (payload.projectId !== currentProjectId) {
|
|
2295
|
+
throw new Error(
|
|
2296
|
+
`Project ID mismatch. License is bound to project namespace "${payload.projectId}" but configuration has "${currentProjectId}".`
|
|
2297
|
+
);
|
|
2298
|
+
}
|
|
2299
|
+
if (!payload.expiresAt) {
|
|
2300
|
+
throw new Error('License payload is missing expiration ("expiresAt").');
|
|
2301
|
+
}
|
|
2302
|
+
const currentTimestampSec = Math.floor(Date.now() / 1e3);
|
|
2303
|
+
if (currentTimestampSec > payload.expiresAt) {
|
|
2304
|
+
throw new Error(
|
|
2305
|
+
`License key has expired. Expiration: ${new Date(
|
|
2306
|
+
payload.expiresAt * 1e3
|
|
2307
|
+
).toDateString()}`
|
|
2308
|
+
);
|
|
2309
|
+
}
|
|
2310
|
+
if (isProduction && provider) {
|
|
2311
|
+
const tier = (payload.tier || "").toLowerCase();
|
|
2312
|
+
const normalizedProvider = provider.toLowerCase();
|
|
2313
|
+
if (tier === "hobby") {
|
|
2314
|
+
const allowedHobby = ["postgresql", "pgvector", "supabase"];
|
|
2315
|
+
if (!allowedHobby.includes(normalizedProvider)) {
|
|
2316
|
+
throw new Error(
|
|
2317
|
+
`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.`
|
|
2318
|
+
);
|
|
2319
|
+
}
|
|
2320
|
+
} else if (tier === "pro" || tier === "developer_pro" || tier === "premium" || tier === "growth" || tier === "free_trial" || tier === "free_tier" || tier === "free") {
|
|
2321
|
+
const allowedPro = [
|
|
2322
|
+
"postgresql",
|
|
2323
|
+
"pgvector",
|
|
2324
|
+
"supabase",
|
|
2325
|
+
"pinecone",
|
|
2326
|
+
"qdrant",
|
|
2327
|
+
"mongodb",
|
|
2328
|
+
"milvus",
|
|
2329
|
+
"chroma",
|
|
2330
|
+
"chromadb"
|
|
2331
|
+
];
|
|
2332
|
+
if (!allowedPro.includes(normalizedProvider)) {
|
|
2333
|
+
throw new Error(
|
|
2334
|
+
`The database provider "${provider}" is not allowed on the Developer Pro tier. Please upgrade to an Enterprise plan.`
|
|
2335
|
+
);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
if (licenseKey) {
|
|
2340
|
+
const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
|
|
2341
|
+
this.cache.set(cacheKey, { payload, cachedAt: now });
|
|
2342
|
+
}
|
|
2343
|
+
return payload;
|
|
2344
|
+
} catch (err) {
|
|
2345
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2346
|
+
throw new ConfigurationException(
|
|
2347
|
+
`[Retrivora SDK] License key validation failed: ${message}`
|
|
2348
|
+
);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
static async verifyIP(licenseKey) {
|
|
2352
|
+
if (!licenseKey) return;
|
|
2353
|
+
try {
|
|
2354
|
+
const parts = licenseKey.split(".");
|
|
2355
|
+
if (parts.length !== 3) return;
|
|
2356
|
+
const [, payloadB64] = parts;
|
|
2357
|
+
const payload = JSON.parse(
|
|
2358
|
+
Buffer.from(payloadB64, "base64url").toString("utf8")
|
|
2359
|
+
);
|
|
2360
|
+
const tier = (payload.tier || "").toLowerCase();
|
|
2361
|
+
if (tier === "enterprise" || tier === "custom") {
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
if (payload.ipv4 || payload.ipv6) {
|
|
2365
|
+
let currentIpv4 = "";
|
|
2366
|
+
let currentIpv6 = "";
|
|
2367
|
+
try {
|
|
2368
|
+
const res = await fetch("https://api4.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
|
|
2369
|
+
const data = await res.json();
|
|
2370
|
+
currentIpv4 = data.ip;
|
|
2371
|
+
} catch (e) {
|
|
2372
|
+
}
|
|
2373
|
+
try {
|
|
2374
|
+
const res = await fetch("https://api6.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
|
|
2375
|
+
const data = await res.json();
|
|
2376
|
+
currentIpv6 = data.ip;
|
|
2377
|
+
} catch (e) {
|
|
2378
|
+
}
|
|
2379
|
+
const localIps = [];
|
|
2380
|
+
try {
|
|
2381
|
+
const osModule = require("os");
|
|
2382
|
+
const interfaces = osModule.networkInterfaces();
|
|
2383
|
+
for (const name of Object.keys(interfaces)) {
|
|
2384
|
+
for (const iface of interfaces[name] || []) {
|
|
2385
|
+
if (!iface.internal) {
|
|
2386
|
+
localIps.push(iface.address);
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
} catch (e) {
|
|
2391
|
+
}
|
|
2392
|
+
const isIpv4Match = payload.ipv4 && (currentIpv4 === payload.ipv4 || localIps.includes(payload.ipv4));
|
|
2393
|
+
const isIpv6Match = payload.ipv6 && (currentIpv6 === payload.ipv6 || localIps.includes(payload.ipv6));
|
|
2394
|
+
if (payload.ipv4 && payload.ipv6) {
|
|
2395
|
+
if (!isIpv4Match && !isIpv6Match) {
|
|
2396
|
+
throw new Error(
|
|
2397
|
+
`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.`
|
|
2398
|
+
);
|
|
2399
|
+
}
|
|
2400
|
+
} else if (payload.ipv4 && !isIpv4Match) {
|
|
2401
|
+
throw new Error(
|
|
2402
|
+
`License key access restricted. This license key was created for a different system (authorized IPv4: ${payload.ipv4}) and cannot be used on this machine.`
|
|
2403
|
+
);
|
|
2404
|
+
} else if (payload.ipv6 && !isIpv6Match) {
|
|
2405
|
+
throw new Error(
|
|
2406
|
+
`License key access restricted. This license key was created for a different system (authorized IPv6: ${payload.ipv6}) and cannot be used on this machine.`
|
|
2407
|
+
);
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
} catch (err) {
|
|
2411
|
+
if (err.message.includes("License key access restricted")) {
|
|
2412
|
+
throw new ConfigurationException(`[Retrivora SDK] ${err.message}`);
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
};
|
|
2417
|
+
// A simple in-memory cache to save CPU overhead of cryptographic signature checks.
|
|
2418
|
+
LicenseVerifier.cache = /* @__PURE__ */ new Map();
|
|
2419
|
+
LicenseVerifier.CACHE_TTL_MS = 60 * 1e3;
|
|
2420
|
+
// Cache verified license for 60 seconds
|
|
2421
|
+
// Retrivora's Public Key used to verify the license key signature.
|
|
2422
|
+
// In production, this matches the private key held by Retrivora SaaS.
|
|
2423
|
+
LicenseVerifier.PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
|
|
2424
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMieCkCBtTfByRNOserm
|
|
2425
|
+
XM4T0Am29JyNzB4XQPe+WJJ56CN73H1HLXx9n1ByFcxkEJ9po+SURj5DnvUXwEy+
|
|
2426
|
+
xstx33wDPpVmcMQe33j5CRYS0S4gICiNqIRN7XkTlJtrcXqrmh1/hdOAwfRbjO1T
|
|
2427
|
+
NVtORHwUwWfI/lBLyxUPGtKPed+0fQ7NtcW4o00JXxs3EjCB5BV9CbnXoTjQb/4h
|
|
2428
|
+
iwZof4l8rb7oaNzOsVg0RSyxsETX7Ex5sI0CjBz1p2mYp4oVhw/A/h8Ls7H0XzjC
|
|
2429
|
+
+Eb6BLtsytt5JHoSp0jExLlCpDmpys2L+kETcBVx+IqiXtdN1n6KbkksvEDUVzLI
|
|
2430
|
+
MwIDAQAB
|
|
2431
|
+
-----END PUBLIC KEY-----`;
|
|
2432
|
+
|
|
2154
2433
|
// src/config/constants.ts
|
|
2155
2434
|
var VECTOR_DB_PROVIDERS = [
|
|
2156
2435
|
"pinecone",
|
|
@@ -2223,14 +2502,12 @@ function getRagConfig(baseConfig, env = process.env) {
|
|
|
2223
2502
|
return getEnvConfig(env, baseConfig);
|
|
2224
2503
|
}
|
|
2225
2504
|
function getEnvConfig(env = process.env, base) {
|
|
2226
|
-
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;
|
|
2505
|
+
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;
|
|
2227
2506
|
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__";
|
|
2228
2507
|
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;
|
|
2229
2508
|
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);
|
|
2230
2509
|
const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
|
|
2231
|
-
const
|
|
2232
|
-
const embeddingProvider = readEnum(env, "EMBEDDING_PROVIDER", "openai", EMBEDDING_PROVIDERS);
|
|
2233
|
-
const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 1536);
|
|
2510
|
+
const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 768);
|
|
2234
2511
|
const vectorDbOptions = {};
|
|
2235
2512
|
if (vectorProvider === "pinecone") {
|
|
2236
2513
|
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 : "";
|
|
@@ -2295,65 +2572,88 @@ function getEnvConfig(env = process.env, base) {
|
|
|
2295
2572
|
rest: "default",
|
|
2296
2573
|
custom: "default"
|
|
2297
2574
|
};
|
|
2575
|
+
const isFreeTier = (() => {
|
|
2576
|
+
if (!licenseKey) return true;
|
|
2577
|
+
try {
|
|
2578
|
+
const payload = LicenseVerifier.verify(licenseKey, projectId);
|
|
2579
|
+
const tier = (payload.tier || "").toLowerCase();
|
|
2580
|
+
return tier === "free_trial" || tier === "free_tier" || tier === "free" || tier === "hobby";
|
|
2581
|
+
} catch (e) {
|
|
2582
|
+
return true;
|
|
2583
|
+
}
|
|
2584
|
+
})();
|
|
2585
|
+
const DEFAULT_FREE_GATEWAY = "https://llm.retrivora.com/api/v1";
|
|
2586
|
+
const defaultLlmProvider = isFreeTier ? "universal_rest" : "universal_rest";
|
|
2587
|
+
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;
|
|
2588
|
+
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;
|
|
2589
|
+
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";
|
|
2590
|
+
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";
|
|
2591
|
+
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";
|
|
2592
|
+
const defaultEmbeddingProvider = isFreeTier ? "universal_rest" : "universal_rest";
|
|
2593
|
+
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;
|
|
2594
|
+
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;
|
|
2595
|
+
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";
|
|
2596
|
+
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";
|
|
2597
|
+
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";
|
|
2298
2598
|
return __spreadProps(__spreadValues({
|
|
2299
2599
|
projectId,
|
|
2300
|
-
licenseKey
|
|
2600
|
+
licenseKey,
|
|
2301
2601
|
vectorDb: {
|
|
2302
2602
|
provider: vectorProvider,
|
|
2303
|
-
indexName: (
|
|
2603
|
+
indexName: (_Wa = (_Va = readString(env, "VECTOR_DB_INDEX")) != null ? _Va : vectorDbOptions.indexName) != null ? _Wa : "rag-index",
|
|
2304
2604
|
options: vectorDbOptions
|
|
2305
2605
|
},
|
|
2306
2606
|
llm: {
|
|
2307
2607
|
provider: llmProvider,
|
|
2308
|
-
model:
|
|
2309
|
-
apiKey:
|
|
2310
|
-
baseUrl:
|
|
2608
|
+
model: llmModel,
|
|
2609
|
+
apiKey: llmApiKey,
|
|
2610
|
+
baseUrl: llmBaseUrl,
|
|
2311
2611
|
systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
|
|
2312
2612
|
maxTokens: readNumber(env, "LLM_MAX_TOKENS", 4096),
|
|
2313
2613
|
temperature: readNumber(env, "LLM_TEMPERATURE", 0.7),
|
|
2314
2614
|
options: {
|
|
2315
|
-
profile:
|
|
2615
|
+
profile: llmProfile,
|
|
2316
2616
|
thinking: readString(env, "LLM_THINKING") === "true" || readString(env, "LLM_THINKING") === "enabled" ? true : readString(env, "LLM_THINKING") === "false" ? false : void 0,
|
|
2317
2617
|
thinkingBudget: env.LLM_THINKING_BUDGET ? parseInt(env.LLM_THINKING_BUDGET, 10) : void 0
|
|
2318
2618
|
}
|
|
2319
2619
|
},
|
|
2320
2620
|
embedding: {
|
|
2321
2621
|
provider: embeddingProvider,
|
|
2322
|
-
model:
|
|
2323
|
-
apiKey:
|
|
2324
|
-
baseUrl:
|
|
2622
|
+
model: embeddingModel,
|
|
2623
|
+
apiKey: embeddingApiKey,
|
|
2624
|
+
baseUrl: embeddingBaseUrl,
|
|
2325
2625
|
dimensions: embeddingDimensions,
|
|
2326
2626
|
queryPrefix: readString(env, "EMBEDDING_QUERY_PREFIX"),
|
|
2327
2627
|
documentPrefix: readString(env, "EMBEDDING_DOCUMENT_PREFIX"),
|
|
2328
2628
|
options: {
|
|
2329
|
-
profile:
|
|
2629
|
+
profile: embeddingProfile
|
|
2330
2630
|
}
|
|
2331
2631
|
},
|
|
2332
2632
|
ui: {
|
|
2333
|
-
title: (
|
|
2334
|
-
subtitle: (
|
|
2335
|
-
primaryColor: (
|
|
2336
|
-
accentColor: (
|
|
2337
|
-
logoUrl: (
|
|
2338
|
-
placeholder: (
|
|
2339
|
-
showSources: ((
|
|
2340
|
-
welcomeMessage: (
|
|
2341
|
-
visualStyle: (
|
|
2342
|
-
borderRadius: (
|
|
2343
|
-
allowUpload: ((
|
|
2633
|
+
title: (_Ya = (_Xa = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _Xa : readString(env, "UI_TITLE")) != null ? _Ya : "AI Assistant",
|
|
2634
|
+
subtitle: (__a = (_Za = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _Za : readString(env, "UI_SUBTITLE")) != null ? __a : "Powered by RAG",
|
|
2635
|
+
primaryColor: (_ab = (_$a = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _$a : readString(env, "UI_PRIMARY_COLOR")) != null ? _ab : "#10b981",
|
|
2636
|
+
accentColor: (_cb = (_bb = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _bb : readString(env, "UI_ACCENT_COLOR")) != null ? _cb : "#3b82f6",
|
|
2637
|
+
logoUrl: (_db = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _db : readString(env, "UI_LOGO_URL"),
|
|
2638
|
+
placeholder: (_fb = (_eb = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _eb : readString(env, "UI_PLACEHOLDER")) != null ? _fb : "Ask me anything\u2026",
|
|
2639
|
+
showSources: ((_hb = (_gb = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _gb : readString(env, "UI_SHOW_SOURCES")) != null ? _hb : "true") !== "false",
|
|
2640
|
+
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.",
|
|
2641
|
+
visualStyle: (_lb = (_kb = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _kb : readString(env, "UI_VISUAL_STYLE")) != null ? _lb : "glass",
|
|
2642
|
+
borderRadius: (_nb = (_mb = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _mb : readString(env, "UI_BORDER_RADIUS")) != null ? _nb : "xl",
|
|
2643
|
+
allowUpload: ((_pb = (_ob = readString(env, "NEXT_PUBLIC_ALLOW_UPLOAD")) != null ? _ob : readString(env, "UI_ALLOW_UPLOAD")) != null ? _pb : "false") === "true"
|
|
2344
2644
|
},
|
|
2345
2645
|
rag: {
|
|
2346
2646
|
topK: readNumber(env, "RAG_TOP_K", 5),
|
|
2347
2647
|
scoreThreshold: readNumber(env, "RAG_SCORE_THRESHOLD", 0),
|
|
2348
2648
|
chunkSize: readNumber(env, "RAG_CHUNK_SIZE", 1e3),
|
|
2349
2649
|
chunkOverlap: readNumber(env, "RAG_CHUNK_OVERLAP", 200),
|
|
2350
|
-
filterableFields: (
|
|
2650
|
+
filterableFields: (_qb = readString(env, "RAG_FILTERABLE_FIELDS")) == null ? void 0 : _qb.split(",").map((f) => f.trim()),
|
|
2351
2651
|
// Query pipeline toggles — read from .env.local
|
|
2352
2652
|
useQueryTransformation: readString(env, "RAG_USE_QUERY_TRANSFORMATION") === "true",
|
|
2353
2653
|
useReranking: readString(env, "RAG_USE_RERANKING") === "true",
|
|
2354
2654
|
useGraphRetrieval: readString(env, "RAG_USE_GRAPH_RETRIEVAL") === "true",
|
|
2355
|
-
architecture: (
|
|
2356
|
-
chunkingStrategy: (
|
|
2655
|
+
architecture: (_rb = readString(env, "RAG_ARCHITECTURE")) != null ? _rb : "simple",
|
|
2656
|
+
chunkingStrategy: (_sb = readString(env, "RAG_CHUNKING_STRATEGY")) != null ? _sb : "recursive",
|
|
2357
2657
|
uiMapping: (() => {
|
|
2358
2658
|
const raw = readString(env, "RAG_UI_MAPPING");
|
|
2359
2659
|
if (!raw) return void 0;
|
|
@@ -2366,7 +2666,7 @@ function getEnvConfig(env = process.env, base) {
|
|
|
2366
2666
|
},
|
|
2367
2667
|
telemetry: {
|
|
2368
2668
|
enabled: telemetryEnabled,
|
|
2369
|
-
url: (
|
|
2669
|
+
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"
|
|
2370
2670
|
}
|
|
2371
2671
|
}, readString(env, "GRAPH_DB_PROVIDER") ? {
|
|
2372
2672
|
graphDb: {
|
|
@@ -2853,10 +3153,12 @@ var AnthropicProvider = class {
|
|
|
2853
3153
|
var import_axios = __toESM(require("axios"));
|
|
2854
3154
|
var OllamaProvider = class {
|
|
2855
3155
|
constructor(llmConfig, embeddingConfig) {
|
|
2856
|
-
var _a2, _b;
|
|
2857
|
-
const
|
|
3156
|
+
var _a2, _b, _c;
|
|
3157
|
+
const rawBaseURL = ((_a2 = llmConfig.baseUrl) != null ? _a2 : "http://localhost:11434").replace(/\/+$/, "");
|
|
3158
|
+
const baseURL = rawBaseURL.replace(/\/(?:api\/v1|v1|api)$/i, "");
|
|
2858
3159
|
const timeout = Number((_b = llmConfig.options) == null ? void 0 : _b.timeout) || 3e5;
|
|
2859
|
-
|
|
3160
|
+
const headers = ((_c = llmConfig.options) == null ? void 0 : _c.headers) || {};
|
|
3161
|
+
this.http = import_axios.default.create({ baseURL, timeout, headers });
|
|
2860
3162
|
this.llmConfig = llmConfig;
|
|
2861
3163
|
this.embeddingConfig = embeddingConfig;
|
|
2862
3164
|
}
|
|
@@ -3705,7 +4007,7 @@ var UniversalLLMAdapter = class {
|
|
|
3705
4007
|
});
|
|
3706
4008
|
}
|
|
3707
4009
|
async chat(messages, context) {
|
|
3708
|
-
var _a2, _b;
|
|
4010
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
3709
4011
|
const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
|
|
3710
4012
|
const formattedMessages = [
|
|
3711
4013
|
{ role: "system", content: `${this.systemPrompt}
|
|
@@ -3730,8 +4032,26 @@ ${context != null ? context : "None"}` },
|
|
|
3730
4032
|
temperature: this.temperature
|
|
3731
4033
|
};
|
|
3732
4034
|
}
|
|
4035
|
+
const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
|
|
4036
|
+
if (isSelfHost || Boolean(process.env.VERCEL)) {
|
|
4037
|
+
try {
|
|
4038
|
+
const _g2 = globalThis;
|
|
4039
|
+
if (typeof _g2.__retrivoraDispatchChat === "function") {
|
|
4040
|
+
const res = await _g2.__retrivoraDispatchChat({
|
|
4041
|
+
model: this.model,
|
|
4042
|
+
messages: formattedMessages,
|
|
4043
|
+
max_tokens: this.maxTokens,
|
|
4044
|
+
temperature: this.temperature
|
|
4045
|
+
}, this.apiKey);
|
|
4046
|
+
if ((_e = (_d = (_c = (_b = res == null ? void 0 : res.response) == null ? void 0 : _b.choices) == null ? void 0 : _c[0]) == null ? void 0 : _d.message) == null ? void 0 : _e.content) {
|
|
4047
|
+
return res.response.choices[0].message.content;
|
|
4048
|
+
}
|
|
4049
|
+
}
|
|
4050
|
+
} catch (e) {
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
3733
4053
|
const { data } = await this.http.post(path2, payload);
|
|
3734
|
-
const extractPath = (
|
|
4054
|
+
const extractPath = (_f = this.opts.responseExtractPath) != null ? _f : "choices[0].message.content";
|
|
3735
4055
|
const result = resolvePath(data, extractPath);
|
|
3736
4056
|
if (result === void 0) {
|
|
3737
4057
|
throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
|
|
@@ -3745,7 +4065,7 @@ ${context != null ? context : "None"}` },
|
|
|
3745
4065
|
*/
|
|
3746
4066
|
chatStream(messages, context) {
|
|
3747
4067
|
return __asyncGenerator(this, null, function* () {
|
|
3748
|
-
var _a2, _b, _c;
|
|
4068
|
+
var _a2, _b, _c, _d, _e, _f, _g2;
|
|
3749
4069
|
const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
|
|
3750
4070
|
const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
|
|
3751
4071
|
const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
|
|
@@ -3776,19 +4096,45 @@ ${context != null ? context : "None"}` },
|
|
|
3776
4096
|
stream: true
|
|
3777
4097
|
};
|
|
3778
4098
|
}
|
|
3779
|
-
const
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
4099
|
+
const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
|
|
4100
|
+
let streamBody = null;
|
|
4101
|
+
if (isSelfHost || Boolean(process.env.VERCEL)) {
|
|
4102
|
+
try {
|
|
4103
|
+
const _g3 = globalThis;
|
|
4104
|
+
if (typeof _g3.__retrivoraDispatchChat === "function") {
|
|
4105
|
+
const res = yield new __await(_g3.__retrivoraDispatchChat({
|
|
4106
|
+
model: this.model,
|
|
4107
|
+
messages: formattedMessages,
|
|
4108
|
+
max_tokens: this.maxTokens,
|
|
4109
|
+
temperature: this.temperature,
|
|
4110
|
+
stream: true
|
|
4111
|
+
}, this.apiKey));
|
|
4112
|
+
if (res == null ? void 0 : res.stream) {
|
|
4113
|
+
streamBody = res.stream;
|
|
4114
|
+
} else if ((_f = (_e = (_d = (_c = res == null ? void 0 : res.response) == null ? void 0 : _c.choices) == null ? void 0 : _d[0]) == null ? void 0 : _e.message) == null ? void 0 : _f.content) {
|
|
4115
|
+
yield res.response.choices[0].message.content;
|
|
4116
|
+
return;
|
|
4117
|
+
}
|
|
4118
|
+
}
|
|
4119
|
+
} catch (e) {
|
|
4120
|
+
}
|
|
3787
4121
|
}
|
|
3788
|
-
if (!
|
|
3789
|
-
|
|
4122
|
+
if (!streamBody) {
|
|
4123
|
+
const response = yield new __await(fetch(url, {
|
|
4124
|
+
method: "POST",
|
|
4125
|
+
headers: this.resolvedHeaders,
|
|
4126
|
+
body: JSON.stringify(payload)
|
|
4127
|
+
}));
|
|
4128
|
+
if (!response.ok) {
|
|
4129
|
+
const errorText = yield new __await(response.text().catch(() => response.statusText));
|
|
4130
|
+
throw new Error(`[UniversalLLMAdapter] Streaming request failed (${response.status}): ${errorText}`);
|
|
4131
|
+
}
|
|
4132
|
+
if (!response.body) {
|
|
4133
|
+
throw new Error("[UniversalLLMAdapter] Response body is null \u2014 server did not send a streaming response.");
|
|
4134
|
+
}
|
|
4135
|
+
streamBody = response.body;
|
|
3790
4136
|
}
|
|
3791
|
-
const reader =
|
|
4137
|
+
const reader = streamBody.getReader();
|
|
3792
4138
|
const decoder = new TextDecoder("utf-8");
|
|
3793
4139
|
let buffer = "";
|
|
3794
4140
|
try {
|
|
@@ -3797,7 +4143,7 @@ ${context != null ? context : "None"}` },
|
|
|
3797
4143
|
if (done) break;
|
|
3798
4144
|
buffer += decoder.decode(value, { stream: true });
|
|
3799
4145
|
const lines = buffer.split("\n");
|
|
3800
|
-
buffer = (
|
|
4146
|
+
buffer = (_g2 = lines.pop()) != null ? _g2 : "";
|
|
3801
4147
|
for (const line of lines) {
|
|
3802
4148
|
const trimmed = line.trim();
|
|
3803
4149
|
if (!trimmed || trimmed === "data: [DONE]") continue;
|
|
@@ -3825,7 +4171,7 @@ ${context != null ? context : "None"}` },
|
|
|
3825
4171
|
});
|
|
3826
4172
|
}
|
|
3827
4173
|
async embed(text) {
|
|
3828
|
-
var _a2, _b;
|
|
4174
|
+
var _a2, _b, _c, _d;
|
|
3829
4175
|
const path2 = (_a2 = this.opts.embedPath) != null ? _a2 : "/embeddings";
|
|
3830
4176
|
let payload;
|
|
3831
4177
|
if (this.opts.embedPayloadTemplate) {
|
|
@@ -3839,105 +4185,49 @@ ${context != null ? context : "None"}` },
|
|
|
3839
4185
|
input: text
|
|
3840
4186
|
};
|
|
3841
4187
|
}
|
|
4188
|
+
const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
|
|
4189
|
+
if (isSelfHost || Boolean(process.env.VERCEL)) {
|
|
4190
|
+
try {
|
|
4191
|
+
const _g2 = globalThis;
|
|
4192
|
+
if (typeof _g2.__retrivoraDispatchEmbedding === "function") {
|
|
4193
|
+
const res = await _g2.__retrivoraDispatchEmbedding({
|
|
4194
|
+
model: this.model,
|
|
4195
|
+
input: text
|
|
4196
|
+
}, this.apiKey);
|
|
4197
|
+
if ((_c = (_b = res == null ? void 0 : res.data) == null ? void 0 : _b[0]) == null ? void 0 : _c.embedding) {
|
|
4198
|
+
return res.data[0].embedding;
|
|
4199
|
+
}
|
|
4200
|
+
}
|
|
4201
|
+
} catch (e) {
|
|
4202
|
+
}
|
|
4203
|
+
}
|
|
3842
4204
|
const { data } = await this.http.post(path2, payload);
|
|
3843
|
-
const extractPath = (
|
|
4205
|
+
const extractPath = (_d = this.opts.embedExtractPath) != null ? _d : "data[0].embedding";
|
|
3844
4206
|
const vector = resolvePath(data, extractPath);
|
|
3845
4207
|
if (!Array.isArray(vector)) {
|
|
3846
4208
|
throw new Error(`[UniversalLLMAdapter] Expected a number array at '${extractPath}' for embeddings.`);
|
|
3847
4209
|
}
|
|
3848
4210
|
return vector;
|
|
3849
4211
|
}
|
|
3850
|
-
async batchEmbed(texts) {
|
|
3851
|
-
const vectors = [];
|
|
3852
|
-
for (const text of texts) {
|
|
3853
|
-
vectors.push(await this.embed(text));
|
|
3854
|
-
}
|
|
3855
|
-
return vectors;
|
|
3856
|
-
}
|
|
3857
|
-
async ping() {
|
|
3858
|
-
try {
|
|
3859
|
-
if (this.opts.pingPath) {
|
|
3860
|
-
await this.http.get(this.opts.pingPath);
|
|
3861
|
-
}
|
|
3862
|
-
return true;
|
|
3863
|
-
} catch (err) {
|
|
3864
|
-
console.error("[UniversalLLMAdapter] Ping failed:", err);
|
|
3865
|
-
return false;
|
|
3866
|
-
}
|
|
3867
|
-
}
|
|
3868
|
-
};
|
|
3869
|
-
|
|
3870
|
-
// src/exceptions/index.ts
|
|
3871
|
-
var RetrivoraError = class extends Error {
|
|
3872
|
-
constructor(message, code, details) {
|
|
3873
|
-
super(message);
|
|
3874
|
-
this.name = new.target.name;
|
|
3875
|
-
this.code = code;
|
|
3876
|
-
this.details = details;
|
|
3877
|
-
}
|
|
3878
|
-
};
|
|
3879
|
-
var ProviderNotFoundException = class extends RetrivoraError {
|
|
3880
|
-
constructor(providerType, provider, details) {
|
|
3881
|
-
super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
|
|
3882
|
-
}
|
|
3883
|
-
};
|
|
3884
|
-
var EmbeddingFailedException = class extends RetrivoraError {
|
|
3885
|
-
constructor(message = "Embedding generation failed", details) {
|
|
3886
|
-
super(message, "EMBEDDING_FAILED", details);
|
|
3887
|
-
}
|
|
3888
|
-
};
|
|
3889
|
-
var RetrievalException = class extends RetrivoraError {
|
|
3890
|
-
constructor(message = "Retrieval failed", details) {
|
|
3891
|
-
super(message, "RETRIEVAL_FAILED", details);
|
|
3892
|
-
}
|
|
3893
|
-
};
|
|
3894
|
-
var RateLimitException = class extends RetrivoraError {
|
|
3895
|
-
constructor(message = "Provider rate limit exceeded", details) {
|
|
3896
|
-
super(message, "RATE_LIMITED", details);
|
|
3897
|
-
}
|
|
3898
|
-
};
|
|
3899
|
-
var ConfigurationException = class extends RetrivoraError {
|
|
3900
|
-
constructor(message, details) {
|
|
3901
|
-
super(message, "CONFIGURATION_ERROR", details);
|
|
3902
|
-
}
|
|
3903
|
-
};
|
|
3904
|
-
var AuthenticationException = class extends RetrivoraError {
|
|
3905
|
-
constructor(message = "Provider authentication failed", details) {
|
|
3906
|
-
super(message, "AUTHENTICATION_ERROR", details);
|
|
3907
|
-
}
|
|
3908
|
-
};
|
|
3909
|
-
function wrapError(err, defaultCode, defaultMessage) {
|
|
3910
|
-
var _a2;
|
|
3911
|
-
if (err instanceof RetrivoraError) {
|
|
3912
|
-
return err;
|
|
3913
|
-
}
|
|
3914
|
-
const error = err;
|
|
3915
|
-
const message = (error == null ? void 0 : error.message) || defaultMessage || String(err);
|
|
3916
|
-
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);
|
|
3917
|
-
const code = error == null ? void 0 : error.code;
|
|
3918
|
-
if (status === 429 || /rate[- ]?limit/i.test(message) || code === "RATE_LIMIT_EXCEEDED") {
|
|
3919
|
-
return new RateLimitException(message, err);
|
|
3920
|
-
}
|
|
3921
|
-
if (status === 401 || status === 403 || /unauthorized|auth|api[- ]?key/i.test(message) || code === "INVALID_API_KEY") {
|
|
3922
|
-
return new AuthenticationException(message, err);
|
|
4212
|
+
async batchEmbed(texts) {
|
|
4213
|
+
const vectors = [];
|
|
4214
|
+
for (const text of texts) {
|
|
4215
|
+
vectors.push(await this.embed(text));
|
|
4216
|
+
}
|
|
4217
|
+
return vectors;
|
|
3923
4218
|
}
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
return
|
|
3933
|
-
|
|
3934
|
-
return new ConfigurationException(message, err);
|
|
3935
|
-
case "AUTHENTICATION_ERROR":
|
|
3936
|
-
return new AuthenticationException(message, err);
|
|
3937
|
-
default:
|
|
3938
|
-
return new RetrivoraError(message, defaultCode, err);
|
|
4219
|
+
async ping() {
|
|
4220
|
+
try {
|
|
4221
|
+
if (this.opts.pingPath) {
|
|
4222
|
+
await this.http.get(this.opts.pingPath);
|
|
4223
|
+
}
|
|
4224
|
+
return true;
|
|
4225
|
+
} catch (err) {
|
|
4226
|
+
console.error("[UniversalLLMAdapter] Ping failed:", err);
|
|
4227
|
+
return false;
|
|
4228
|
+
}
|
|
3939
4229
|
}
|
|
3940
|
-
}
|
|
4230
|
+
};
|
|
3941
4231
|
|
|
3942
4232
|
// src/llm/LLMFactory.ts
|
|
3943
4233
|
var customProviders = /* @__PURE__ */ new Map();
|
|
@@ -4336,211 +4626,6 @@ var ConfigValidator = class {
|
|
|
4336
4626
|
}
|
|
4337
4627
|
};
|
|
4338
4628
|
|
|
4339
|
-
// src/core/LicenseVerifier.ts
|
|
4340
|
-
var crypto2 = __toESM(require("crypto"));
|
|
4341
|
-
var LicenseVerifier = class {
|
|
4342
|
-
/**
|
|
4343
|
-
* Decodes, verifies signature, and checks metadata of a license key.
|
|
4344
|
-
*
|
|
4345
|
-
* @param licenseKey - Base64url signed JWT license key.
|
|
4346
|
-
* @param currentProjectId - Project namespace ID.
|
|
4347
|
-
* @param publicKeyOverride - Optional override for unit/integration tests.
|
|
4348
|
-
*/
|
|
4349
|
-
static verify(licenseKey, currentProjectId, provider, publicKeyOverride) {
|
|
4350
|
-
const isProduction = process.env.NODE_ENV === "production";
|
|
4351
|
-
const now = Date.now();
|
|
4352
|
-
if (licenseKey) {
|
|
4353
|
-
const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
|
|
4354
|
-
const cached = this.cache.get(cacheKey);
|
|
4355
|
-
if (cached && now - cached.cachedAt < this.CACHE_TTL_MS) {
|
|
4356
|
-
const currentTimestampSec = Math.floor(now / 1e3);
|
|
4357
|
-
if (cached.payload.expiresAt && currentTimestampSec > cached.payload.expiresAt) {
|
|
4358
|
-
this.cache.delete(cacheKey);
|
|
4359
|
-
} else {
|
|
4360
|
-
return cached.payload;
|
|
4361
|
-
}
|
|
4362
|
-
}
|
|
4363
|
-
}
|
|
4364
|
-
if (!licenseKey) {
|
|
4365
|
-
if (isProduction) {
|
|
4366
|
-
throw new ConfigurationException(
|
|
4367
|
-
"[Retrivora SDK] License key (licenseKey) is required in production environments."
|
|
4368
|
-
);
|
|
4369
|
-
}
|
|
4370
|
-
console.warn(
|
|
4371
|
-
`\x1B[33m[Retrivora SDK] WARNING: Running without a license key. This namespace (${currentProjectId}) is permitted for local development only.\x1B[0m`
|
|
4372
|
-
);
|
|
4373
|
-
return {
|
|
4374
|
-
projectId: currentProjectId,
|
|
4375
|
-
expiresAt: Math.floor(Date.now() / 1e3) + 86400,
|
|
4376
|
-
// Valid for 24h
|
|
4377
|
-
tier: "hobby"
|
|
4378
|
-
};
|
|
4379
|
-
}
|
|
4380
|
-
try {
|
|
4381
|
-
const parts = licenseKey.split(".");
|
|
4382
|
-
if (parts.length !== 3) {
|
|
4383
|
-
throw new Error("Malformed token structure (expected 3 parts).");
|
|
4384
|
-
}
|
|
4385
|
-
const [headerB64, payloadB64, signatureB64] = parts;
|
|
4386
|
-
const dataToVerify = `${headerB64}.${payloadB64}`;
|
|
4387
|
-
const publicKey = publicKeyOverride != null ? publicKeyOverride : this.PUBLIC_KEY;
|
|
4388
|
-
const signature = Buffer.from(signatureB64, "base64url");
|
|
4389
|
-
const data = Buffer.from(dataToVerify);
|
|
4390
|
-
const isValid = crypto2.verify(
|
|
4391
|
-
"sha256",
|
|
4392
|
-
data,
|
|
4393
|
-
publicKey,
|
|
4394
|
-
signature
|
|
4395
|
-
);
|
|
4396
|
-
if (!isValid) {
|
|
4397
|
-
throw new Error("Signature verification failed.");
|
|
4398
|
-
}
|
|
4399
|
-
const payload = JSON.parse(
|
|
4400
|
-
Buffer.from(payloadB64, "base64url").toString("utf8")
|
|
4401
|
-
);
|
|
4402
|
-
if (!payload.projectId) {
|
|
4403
|
-
throw new Error('License payload is missing "projectId".');
|
|
4404
|
-
}
|
|
4405
|
-
if (payload.projectId !== currentProjectId) {
|
|
4406
|
-
throw new Error(
|
|
4407
|
-
`Project ID mismatch. License is bound to project namespace "${payload.projectId}" but configuration has "${currentProjectId}".`
|
|
4408
|
-
);
|
|
4409
|
-
}
|
|
4410
|
-
if (!payload.expiresAt) {
|
|
4411
|
-
throw new Error('License payload is missing expiration ("expiresAt").');
|
|
4412
|
-
}
|
|
4413
|
-
const currentTimestampSec = Math.floor(Date.now() / 1e3);
|
|
4414
|
-
if (currentTimestampSec > payload.expiresAt) {
|
|
4415
|
-
throw new Error(
|
|
4416
|
-
`License key has expired. Expiration: ${new Date(
|
|
4417
|
-
payload.expiresAt * 1e3
|
|
4418
|
-
).toDateString()}`
|
|
4419
|
-
);
|
|
4420
|
-
}
|
|
4421
|
-
if (isProduction && provider) {
|
|
4422
|
-
const tier = (payload.tier || "").toLowerCase();
|
|
4423
|
-
const normalizedProvider = provider.toLowerCase();
|
|
4424
|
-
if (tier === "hobby") {
|
|
4425
|
-
const allowedHobby = ["postgresql", "pgvector", "supabase"];
|
|
4426
|
-
if (!allowedHobby.includes(normalizedProvider)) {
|
|
4427
|
-
throw new Error(
|
|
4428
|
-
`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.`
|
|
4429
|
-
);
|
|
4430
|
-
}
|
|
4431
|
-
} else if (tier === "pro" || tier === "developer_pro" || tier === "premium" || tier === "growth" || tier === "free_trial" || tier === "free_tier" || tier === "free") {
|
|
4432
|
-
const allowedPro = [
|
|
4433
|
-
"postgresql",
|
|
4434
|
-
"pgvector",
|
|
4435
|
-
"supabase",
|
|
4436
|
-
"pinecone",
|
|
4437
|
-
"qdrant",
|
|
4438
|
-
"mongodb",
|
|
4439
|
-
"milvus",
|
|
4440
|
-
"chroma",
|
|
4441
|
-
"chromadb"
|
|
4442
|
-
];
|
|
4443
|
-
if (!allowedPro.includes(normalizedProvider)) {
|
|
4444
|
-
throw new Error(
|
|
4445
|
-
`The database provider "${provider}" is not allowed on the Developer Pro tier. Please upgrade to an Enterprise plan.`
|
|
4446
|
-
);
|
|
4447
|
-
}
|
|
4448
|
-
}
|
|
4449
|
-
}
|
|
4450
|
-
if (licenseKey) {
|
|
4451
|
-
const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
|
|
4452
|
-
this.cache.set(cacheKey, { payload, cachedAt: now });
|
|
4453
|
-
}
|
|
4454
|
-
return payload;
|
|
4455
|
-
} catch (err) {
|
|
4456
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
4457
|
-
throw new ConfigurationException(
|
|
4458
|
-
`[Retrivora SDK] License key validation failed: ${message}`
|
|
4459
|
-
);
|
|
4460
|
-
}
|
|
4461
|
-
}
|
|
4462
|
-
static async verifyIP(licenseKey) {
|
|
4463
|
-
if (!licenseKey) return;
|
|
4464
|
-
try {
|
|
4465
|
-
const parts = licenseKey.split(".");
|
|
4466
|
-
if (parts.length !== 3) return;
|
|
4467
|
-
const [, payloadB64] = parts;
|
|
4468
|
-
const payload = JSON.parse(
|
|
4469
|
-
Buffer.from(payloadB64, "base64url").toString("utf8")
|
|
4470
|
-
);
|
|
4471
|
-
const tier = (payload.tier || "").toLowerCase();
|
|
4472
|
-
if (tier === "enterprise" || tier === "custom") {
|
|
4473
|
-
return;
|
|
4474
|
-
}
|
|
4475
|
-
if (payload.ipv4 || payload.ipv6) {
|
|
4476
|
-
let currentIpv4 = "";
|
|
4477
|
-
let currentIpv6 = "";
|
|
4478
|
-
try {
|
|
4479
|
-
const res = await fetch("https://api4.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
|
|
4480
|
-
const data = await res.json();
|
|
4481
|
-
currentIpv4 = data.ip;
|
|
4482
|
-
} catch (e) {
|
|
4483
|
-
}
|
|
4484
|
-
try {
|
|
4485
|
-
const res = await fetch("https://api6.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
|
|
4486
|
-
const data = await res.json();
|
|
4487
|
-
currentIpv6 = data.ip;
|
|
4488
|
-
} catch (e) {
|
|
4489
|
-
}
|
|
4490
|
-
const localIps = [];
|
|
4491
|
-
try {
|
|
4492
|
-
const osModule = require("os");
|
|
4493
|
-
const interfaces = osModule.networkInterfaces();
|
|
4494
|
-
for (const name of Object.keys(interfaces)) {
|
|
4495
|
-
for (const iface of interfaces[name] || []) {
|
|
4496
|
-
if (!iface.internal) {
|
|
4497
|
-
localIps.push(iface.address);
|
|
4498
|
-
}
|
|
4499
|
-
}
|
|
4500
|
-
}
|
|
4501
|
-
} catch (e) {
|
|
4502
|
-
}
|
|
4503
|
-
const isIpv4Match = payload.ipv4 && (currentIpv4 === payload.ipv4 || localIps.includes(payload.ipv4));
|
|
4504
|
-
const isIpv6Match = payload.ipv6 && (currentIpv6 === payload.ipv6 || localIps.includes(payload.ipv6));
|
|
4505
|
-
if (payload.ipv4 && payload.ipv6) {
|
|
4506
|
-
if (!isIpv4Match && !isIpv6Match) {
|
|
4507
|
-
throw new Error(
|
|
4508
|
-
`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.`
|
|
4509
|
-
);
|
|
4510
|
-
}
|
|
4511
|
-
} else if (payload.ipv4 && !isIpv4Match) {
|
|
4512
|
-
throw new Error(
|
|
4513
|
-
`License key access restricted. This license key was created for a different system (authorized IPv4: ${payload.ipv4}) and cannot be used on this machine.`
|
|
4514
|
-
);
|
|
4515
|
-
} else if (payload.ipv6 && !isIpv6Match) {
|
|
4516
|
-
throw new Error(
|
|
4517
|
-
`License key access restricted. This license key was created for a different system (authorized IPv6: ${payload.ipv6}) and cannot be used on this machine.`
|
|
4518
|
-
);
|
|
4519
|
-
}
|
|
4520
|
-
}
|
|
4521
|
-
} catch (err) {
|
|
4522
|
-
if (err.message.includes("License key access restricted")) {
|
|
4523
|
-
throw new ConfigurationException(`[Retrivora SDK] ${err.message}`);
|
|
4524
|
-
}
|
|
4525
|
-
}
|
|
4526
|
-
}
|
|
4527
|
-
};
|
|
4528
|
-
// A simple in-memory cache to save CPU overhead of cryptographic signature checks.
|
|
4529
|
-
LicenseVerifier.cache = /* @__PURE__ */ new Map();
|
|
4530
|
-
LicenseVerifier.CACHE_TTL_MS = 60 * 1e3;
|
|
4531
|
-
// Cache verified license for 60 seconds
|
|
4532
|
-
// Retrivora's Public Key used to verify the license key signature.
|
|
4533
|
-
// In production, this matches the private key held by Retrivora SaaS.
|
|
4534
|
-
LicenseVerifier.PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
|
|
4535
|
-
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMieCkCBtTfByRNOserm
|
|
4536
|
-
XM4T0Am29JyNzB4XQPe+WJJ56CN73H1HLXx9n1ByFcxkEJ9po+SURj5DnvUXwEy+
|
|
4537
|
-
xstx33wDPpVmcMQe33j5CRYS0S4gICiNqIRN7XkTlJtrcXqrmh1/hdOAwfRbjO1T
|
|
4538
|
-
NVtORHwUwWfI/lBLyxUPGtKPed+0fQ7NtcW4o00JXxs3EjCB5BV9CbnXoTjQb/4h
|
|
4539
|
-
iwZof4l8rb7oaNzOsVg0RSyxsETX7Ex5sI0CjBz1p2mYp4oVhw/A/h8Ls7H0XzjC
|
|
4540
|
-
+Eb6BLtsytt5JHoSp0jExLlCpDmpys2L+kETcBVx+IqiXtdN1n6KbkksvEDUVzLI
|
|
4541
|
-
MwIDAQAB
|
|
4542
|
-
-----END PUBLIC KEY-----`;
|
|
4543
|
-
|
|
4544
4629
|
// src/rag/DocumentChunker.ts
|
|
4545
4630
|
var DocumentChunker = class {
|
|
4546
4631
|
constructor(chunkSize = 1e3, chunkOverlap = 200, separators = ["\n# ", "\n## ", "\n### ", "\n#### ", "\n\n", "\n", " ", ""]) {
|
|
@@ -8467,8 +8552,11 @@ ${m.content}`).join("\n\n---\n\n");
|
|
|
8467
8552
|
fullSources = fullSources.slice(0, topK);
|
|
8468
8553
|
}
|
|
8469
8554
|
const rerankMs = performance.now() - rerankStart;
|
|
8470
|
-
let context = fullSources.length ? fullSources.map((m, i) =>
|
|
8471
|
-
|
|
8555
|
+
let context = fullSources.length ? fullSources.map((m, i) => {
|
|
8556
|
+
var _a3;
|
|
8557
|
+
return `[Source ${i + 1}]
|
|
8558
|
+
${(_a3 = m == null ? void 0 : m.content) != null ? _a3 : ""}`;
|
|
8559
|
+
}).join("\n\n---\n\n") : "No relevant context found.";
|
|
8472
8560
|
let displayCount = 15;
|
|
8473
8561
|
if (hasMetadataFilter) {
|
|
8474
8562
|
displayCount = fullSources.length;
|
|
@@ -8552,7 +8640,10 @@ ${context}`;
|
|
|
8552
8640
|
if (isSimulatedThinking) {
|
|
8553
8641
|
finalRestrictionSuffix += "\n\n(IMPORTANT: You must think step-by-step before answering. Write your thinking process inside a `<think>...</think>` block. Write the `<think>` block first, then follow it with your final response. Keep the thinking process thorough and detailed. Example: `<think>Thinking details here...</think>Final answer text here.`)";
|
|
8554
8642
|
}
|
|
8555
|
-
const hardenedHistory = [
|
|
8643
|
+
const hardenedHistory = (Array.isArray(history) ? history : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
|
|
8644
|
+
role: m.role || "user",
|
|
8645
|
+
content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
|
|
8646
|
+
}));
|
|
8556
8647
|
const userQuestion = { role: "user", content: question + finalRestrictionSuffix };
|
|
8557
8648
|
const messages = [...hardenedHistory, userQuestion];
|
|
8558
8649
|
const systemPrompt = (_v = this.config.llm.systemPrompt) != null ? _v : "";
|
|
@@ -8699,13 +8790,13 @@ ${context}`;
|
|
|
8699
8790
|
rewrittenQuery,
|
|
8700
8791
|
systemPrompt,
|
|
8701
8792
|
userPrompt: question + finalRestrictionSuffix,
|
|
8702
|
-
chunks: sources.map((s) => {
|
|
8703
|
-
var _a3;
|
|
8793
|
+
chunks: (sources || []).filter(Boolean).map((s) => {
|
|
8794
|
+
var _a3, _b2;
|
|
8704
8795
|
return {
|
|
8705
8796
|
id: s.id,
|
|
8706
8797
|
score: s.score,
|
|
8707
|
-
content: s.content,
|
|
8708
|
-
metadata: (
|
|
8798
|
+
content: (_a3 = s == null ? void 0 : s.content) != null ? _a3 : "",
|
|
8799
|
+
metadata: (_b2 = s == null ? void 0 : s.metadata) != null ? _b2 : {},
|
|
8709
8800
|
namespace: ns
|
|
8710
8801
|
};
|
|
8711
8802
|
}),
|
|
@@ -9606,6 +9697,7 @@ var import_server = require("next/server");
|
|
|
9606
9697
|
// src/core/DatabaseStorage.ts
|
|
9607
9698
|
var fs = __toESM(require("fs"));
|
|
9608
9699
|
var path = __toESM(require("path"));
|
|
9700
|
+
var os = __toESM(require("os"));
|
|
9609
9701
|
var DatabaseStorage = class {
|
|
9610
9702
|
constructor(config) {
|
|
9611
9703
|
// Dynamic PG Pool
|
|
@@ -9614,7 +9706,8 @@ var DatabaseStorage = class {
|
|
|
9614
9706
|
this.mongoClient = null;
|
|
9615
9707
|
this.mongoDbName = "";
|
|
9616
9708
|
// Filesystem fallback configuration
|
|
9617
|
-
this.
|
|
9709
|
+
this.isServerless = Boolean(process.env.VERCEL || process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.LAMBDA_TASK_ROOT);
|
|
9710
|
+
this.fallbackDir = this.isServerless ? path.join(os.tmpdir(), ".retrivora") : path.join(process.cwd(), ".retrivora");
|
|
9618
9711
|
this.historyFile = path.join(this.fallbackDir, "history.json");
|
|
9619
9712
|
this.feedbackFile = path.join(this.fallbackDir, "feedback.json");
|
|
9620
9713
|
var _a2, _b, _c, _d, _e;
|
|
@@ -9744,10 +9837,27 @@ var DatabaseStorage = class {
|
|
|
9744
9837
|
}
|
|
9745
9838
|
// Helper for FS fallback writes
|
|
9746
9839
|
writeLocalFile(filePath, data) {
|
|
9747
|
-
|
|
9748
|
-
|
|
9840
|
+
try {
|
|
9841
|
+
const dir = path.dirname(filePath);
|
|
9842
|
+
if (!fs.existsSync(dir)) {
|
|
9843
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
9844
|
+
}
|
|
9845
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
9846
|
+
} catch (err) {
|
|
9847
|
+
if (err.code === "EROFS") {
|
|
9848
|
+
try {
|
|
9849
|
+
const tmpDir = path.join(os.tmpdir(), ".retrivora");
|
|
9850
|
+
if (!fs.existsSync(tmpDir)) {
|
|
9851
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
9852
|
+
}
|
|
9853
|
+
const tmpFilePath = path.join(tmpDir, path.basename(filePath));
|
|
9854
|
+
fs.writeFileSync(tmpFilePath, JSON.stringify(data, null, 2), "utf-8");
|
|
9855
|
+
} catch (e) {
|
|
9856
|
+
}
|
|
9857
|
+
} else {
|
|
9858
|
+
console.warn(`[DatabaseStorage] Failed to write local fallback file: ${err.message}`);
|
|
9859
|
+
}
|
|
9749
9860
|
}
|
|
9750
|
-
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
9751
9861
|
}
|
|
9752
9862
|
// ─── Message History Operations ──────────────────────────────────────────
|
|
9753
9863
|
async saveMessage(sessionId, message) {
|
|
@@ -10179,7 +10289,17 @@ function createChatHandler(configOrPlugin, options) {
|
|
|
10179
10289
|
if (rateLimited) return rateLimited;
|
|
10180
10290
|
try {
|
|
10181
10291
|
const body = await req.json();
|
|
10182
|
-
const
|
|
10292
|
+
const bodyObj = body != null ? body : {};
|
|
10293
|
+
let rawMessage = bodyObj.message;
|
|
10294
|
+
if (!rawMessage && Array.isArray(bodyObj.messages) && bodyObj.messages.length > 0) {
|
|
10295
|
+
const lastMsg = bodyObj.messages[bodyObj.messages.length - 1];
|
|
10296
|
+
rawMessage = typeof lastMsg === "string" ? lastMsg : (lastMsg == null ? void 0 : lastMsg.content) || (lastMsg == null ? void 0 : lastMsg.text);
|
|
10297
|
+
}
|
|
10298
|
+
if (!rawMessage && typeof bodyObj.prompt === "string") {
|
|
10299
|
+
rawMessage = bodyObj.prompt;
|
|
10300
|
+
}
|
|
10301
|
+
const history = bodyObj.history || (Array.isArray(bodyObj.messages) ? bodyObj.messages.slice(0, -1) : []);
|
|
10302
|
+
const { namespace, sessionId = "default", messageId, userMessageId } = bodyObj;
|
|
10183
10303
|
const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
|
|
10184
10304
|
if (!sanitized.ok) {
|
|
10185
10305
|
return import_server.NextResponse.json({ error: { code: "INVALID_INPUT", message: sanitized.error } }, { status: 400 });
|
|
@@ -10231,7 +10351,17 @@ function createStreamHandler(configOrPlugin, options) {
|
|
|
10231
10351
|
headers: { "Content-Type": "application/json" }
|
|
10232
10352
|
});
|
|
10233
10353
|
}
|
|
10234
|
-
const
|
|
10354
|
+
const bodyObj = body != null ? body : {};
|
|
10355
|
+
let rawMessage = bodyObj.message;
|
|
10356
|
+
if (!rawMessage && Array.isArray(bodyObj.messages) && bodyObj.messages.length > 0) {
|
|
10357
|
+
const lastMsg = bodyObj.messages[bodyObj.messages.length - 1];
|
|
10358
|
+
rawMessage = typeof lastMsg === "string" ? lastMsg : (lastMsg == null ? void 0 : lastMsg.content) || (lastMsg == null ? void 0 : lastMsg.text);
|
|
10359
|
+
}
|
|
10360
|
+
if (!rawMessage && typeof bodyObj.prompt === "string") {
|
|
10361
|
+
rawMessage = bodyObj.prompt;
|
|
10362
|
+
}
|
|
10363
|
+
const history = bodyObj.history || (Array.isArray(bodyObj.messages) ? bodyObj.messages.slice(0, -1) : []);
|
|
10364
|
+
const { namespace, sessionId = "default", messageId, userMessageId } = bodyObj;
|
|
10235
10365
|
const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
|
|
10236
10366
|
if (!sanitized.ok) {
|
|
10237
10367
|
return new Response(
|