@retrivora-ai/rag-engine 2.2.6 → 2.2.8

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/index.mjs CHANGED
@@ -18,6 +18,12 @@ var __spreadValues = (a, b) => {
18
18
  return a;
19
19
  };
20
20
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
22
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
23
+ }) : x)(function(x) {
24
+ if (typeof require !== "undefined") return require.apply(this, arguments);
25
+ throw Error('Dynamic require of "' + x + '" is not supported');
26
+ });
21
27
  var __objRest = (source, exclude) => {
22
28
  var target = {};
23
29
  for (var prop in source)
@@ -2759,7 +2765,7 @@ function useRagChat(projectId, options = {}) {
2759
2765
  }, [messages]);
2760
2766
  const sendMessage = useCallback(
2761
2767
  async (text, opts) => {
2762
- var _a, _b, _c, _d, _e;
2768
+ var _a, _b, _c, _d, _e, _f;
2763
2769
  const trimmed = text.trim();
2764
2770
  if (!trimmed || isLoading) return;
2765
2771
  lastInputRef.current = trimmed;
@@ -2791,9 +2797,18 @@ function useRagChat(projectId, options = {}) {
2791
2797
  messageId: assistantMessageId,
2792
2798
  userMessageId: userMsgId
2793
2799
  });
2794
- const fetchHeaders = __spreadValues({
2800
+ const getHeader = (headersObj, name) => {
2801
+ if (!headersObj) return void 0;
2802
+ const target = name.toLowerCase();
2803
+ for (const [k, v] of Object.entries(headersObj)) {
2804
+ if (k.toLowerCase() === target) return v;
2805
+ }
2806
+ return void 0;
2807
+ };
2808
+ const resolvedLicenseKey = options.licenseKey || getHeader(options.headers, "x-license-key") || ((_b = getHeader(options.headers, "authorization")) == null ? void 0 : _b.replace(/^Bearer\s+/i, "")) || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY || process.env.RETRIVORA_LICENSE_KEY : "") || "";
2809
+ const fetchHeaders = __spreadValues(__spreadValues({
2795
2810
  "Content-Type": "application/json"
2796
- }, options.headers || {});
2811
+ }, resolvedLicenseKey ? { "x-license-key": resolvedLicenseKey } : {}), options.headers || {});
2797
2812
  let response = await fetch(primaryUrl, {
2798
2813
  method: "POST",
2799
2814
  headers: fetchHeaders,
@@ -2811,10 +2826,10 @@ function useRagChat(projectId, options = {}) {
2811
2826
  }
2812
2827
  if (!response.ok) {
2813
2828
  const errorData = await response.json().catch(() => ({}));
2814
- if (response.status === 403 || response.status === 401 || typeof errorData.error === "string" && errorData.error.toLowerCase().includes("license") || ((_b = errorData.error) == null ? void 0 : _b.type) === "license_revoked") {
2829
+ if (response.status === 403 || response.status === 401 || typeof errorData.error === "string" && errorData.error.toLowerCase().includes("license") || ((_c = errorData.error) == null ? void 0 : _c.type) === "license_revoked") {
2815
2830
  throw new Error("Your Retrivora license is no longer valid. Please contact your administrator or obtain a valid license key.");
2816
2831
  }
2817
- throw new Error(((_c = errorData.error) == null ? void 0 : _c.message) || errorData.error || `Server returned ${response.status}`);
2832
+ throw new Error(((_d = errorData.error) == null ? void 0 : _d.message) || errorData.error || `Server returned ${response.status}`);
2818
2833
  }
2819
2834
  if (!response.body) {
2820
2835
  throw new Error("No response body received from server");
@@ -2878,7 +2893,7 @@ function useRagChat(projectId, options = {}) {
2878
2893
  pendingThinkingRef.current = thinkingContent;
2879
2894
  scheduleFlush(assistantMessageId);
2880
2895
  } else if (frame.type === "metadata") {
2881
- sources = (_d = frame.sources) != null ? _d : [];
2896
+ sources = (_e = frame.sources) != null ? _e : [];
2882
2897
  thinkingMs = frame.thinkingMs;
2883
2898
  } else if (frame.type === "ui_transformation") {
2884
2899
  uiTransformation = frame.data;
@@ -2894,7 +2909,7 @@ function useRagChat(projectId, options = {}) {
2894
2909
  if (frame.type === "text" && frame.text) assistantContent += frame.text;
2895
2910
  else if (frame.type === "thinking" && frame.text) thinkingContent += frame.text;
2896
2911
  else if (frame.type === "metadata") {
2897
- sources = (_e = frame.sources) != null ? _e : [];
2912
+ sources = (_f = frame.sources) != null ? _f : [];
2898
2913
  thinkingMs = frame.thinkingMs;
2899
2914
  } else if (frame.type === "observability") trace = frame.data;
2900
2915
  }
@@ -2919,7 +2934,10 @@ function useRagChat(projectId, options = {}) {
2919
2934
  console.log("[useRagChat] Streaming stopped by user.");
2920
2935
  return;
2921
2936
  }
2922
- const msg = err instanceof Error ? err.message : "Something went wrong. Please try again.";
2937
+ let msg = err instanceof Error ? err.message : "Something went wrong. Please try again.";
2938
+ if (msg.includes("403") || msg.toLowerCase().includes("license") || msg.toLowerCase().includes("revoked") || msg.toLowerCase().includes("terminated")) {
2939
+ msg = "Your Retrivora license key has been terminated, suspended, or revoked. Access denied.";
2940
+ }
2923
2941
  setError(msg);
2924
2942
  onError == null ? void 0 : onError(msg);
2925
2943
  } finally {
@@ -3031,7 +3049,7 @@ function useRagChat(projectId, options = {}) {
3031
3049
  // package.json
3032
3050
  var package_default = {
3033
3051
  name: "@retrivora-ai/rag-engine",
3034
- version: "2.2.6",
3052
+ version: "2.2.8",
3035
3053
  description: "Retrivora AI is a plug-and-play AI engine for RAG chat experiences \u2014 generic vector DB + LLM provider, embeddable or standalone.",
3036
3054
  author: "Abhinav Alkuchi",
3037
3055
  license: "UNLICENSED",
@@ -3171,6 +3189,407 @@ var package_default = {
3171
3189
  // src/version.ts
3172
3190
  var SDK_VERSION = package_default.version || "2.1.3";
3173
3191
 
3192
+ // src/exceptions/index.ts
3193
+ var RetrivoraError = class extends Error {
3194
+ constructor(message, code, details) {
3195
+ super(message);
3196
+ this.name = new.target.name;
3197
+ this.code = code;
3198
+ this.details = details;
3199
+ }
3200
+ };
3201
+ var ProviderNotFoundException = class extends RetrivoraError {
3202
+ constructor(providerType, provider, details) {
3203
+ super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
3204
+ }
3205
+ };
3206
+ var EmbeddingFailedException = class extends RetrivoraError {
3207
+ constructor(message = "Embedding generation failed", details) {
3208
+ super(message, "EMBEDDING_FAILED", details);
3209
+ }
3210
+ };
3211
+ var RetrievalException = class extends RetrivoraError {
3212
+ constructor(message = "Retrieval failed", details) {
3213
+ super(message, "RETRIEVAL_FAILED", details);
3214
+ }
3215
+ };
3216
+ var RateLimitException = class extends RetrivoraError {
3217
+ constructor(message = "Provider rate limit exceeded", details) {
3218
+ super(message, "RATE_LIMITED", details);
3219
+ }
3220
+ };
3221
+ var ConfigurationException = class extends RetrivoraError {
3222
+ constructor(message, details) {
3223
+ super(message, "CONFIGURATION_ERROR", details);
3224
+ }
3225
+ };
3226
+ var AuthenticationException = class extends RetrivoraError {
3227
+ constructor(message = "Provider authentication failed", details) {
3228
+ super(message, "AUTHENTICATION_ERROR", details);
3229
+ }
3230
+ };
3231
+ var SDKVersionUnsupportedError = class extends RetrivoraError {
3232
+ constructor(message = "This SDK version is no longer supported.", details) {
3233
+ super(message, "SDK_VERSION_UNSUPPORTED", details);
3234
+ }
3235
+ };
3236
+ var LicenseValidationError = class extends RetrivoraError {
3237
+ constructor(message = "License validation failed.", details) {
3238
+ super(message, "LICENSE_VALIDATION_ERROR", details);
3239
+ }
3240
+ };
3241
+
3242
+ // src/core/LicenseVerifier.ts
3243
+ import * as crypto from "crypto";
3244
+ var LicenseVerifier = class {
3245
+ /**
3246
+ * Decodes, verifies signature, and checks metadata of a license key.
3247
+ *
3248
+ * @param licenseKey - Base64url signed JWT license key.
3249
+ * @param currentProjectId - Project namespace ID.
3250
+ * @param publicKeyOverride - Optional override for unit/integration tests.
3251
+ */
3252
+ static verify(licenseKey, currentProjectId, provider, publicKeyOverride) {
3253
+ const isProduction = process.env.NODE_ENV === "production";
3254
+ const now = Date.now();
3255
+ if (licenseKey) {
3256
+ const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
3257
+ const cached = this.cache.get(cacheKey);
3258
+ if (cached && now - cached.cachedAt < this.CACHE_TTL_MS) {
3259
+ const currentTimestampSec = Math.floor(now / 1e3);
3260
+ if (cached.payload.expiresAt && currentTimestampSec > cached.payload.expiresAt) {
3261
+ this.cache.delete(cacheKey);
3262
+ } else {
3263
+ return cached.payload;
3264
+ }
3265
+ }
3266
+ }
3267
+ if (!licenseKey) {
3268
+ if (isProduction) {
3269
+ throw new ConfigurationException(
3270
+ "[Retrivora SDK] License key (licenseKey) is required in production environments."
3271
+ );
3272
+ }
3273
+ console.warn(
3274
+ `\x1B[33m[Retrivora SDK] WARNING: Running without a license key. This namespace (${currentProjectId}) is permitted for local development only.\x1B[0m`
3275
+ );
3276
+ return {
3277
+ projectId: currentProjectId,
3278
+ expiresAt: Math.floor(Date.now() / 1e3) + 86400,
3279
+ // Valid for 24h
3280
+ tier: "hobby"
3281
+ };
3282
+ }
3283
+ try {
3284
+ const rawToken = licenseKey.replace(/^rtv_/i, "").trim();
3285
+ const parts = rawToken.split(".");
3286
+ if (parts.length !== 3) {
3287
+ throw new Error("Malformed token structure (expected 3 parts).");
3288
+ }
3289
+ const [headerB64, payloadB64, signatureB64] = parts;
3290
+ const dataToVerify = `${headerB64}.${payloadB64}`;
3291
+ const publicKey = publicKeyOverride != null ? publicKeyOverride : this.PUBLIC_KEY;
3292
+ const signature = Buffer.from(signatureB64, "base64url");
3293
+ const data = Buffer.from(dataToVerify);
3294
+ const isValid = crypto.verify(
3295
+ "sha256",
3296
+ data,
3297
+ publicKey,
3298
+ signature
3299
+ );
3300
+ if (!isValid) {
3301
+ throw new Error("Signature verification failed.");
3302
+ }
3303
+ const payload = JSON.parse(
3304
+ Buffer.from(payloadB64, "base64url").toString("utf8")
3305
+ );
3306
+ if (!payload.projectId) {
3307
+ throw new Error('License payload is missing "projectId".');
3308
+ }
3309
+ const isProjectMatch = payload.projectId === currentProjectId || payload.projectId === `retrivora-${currentProjectId}` || `retrivora-${payload.projectId}` === currentProjectId;
3310
+ if (!isProjectMatch) {
3311
+ throw new Error(
3312
+ `Project ID mismatch. License is bound to project namespace "${payload.projectId}" but configuration has "${currentProjectId}".`
3313
+ );
3314
+ }
3315
+ if (!payload.expiresAt) {
3316
+ throw new Error('License payload is missing expiration ("expiresAt").');
3317
+ }
3318
+ const currentTimestampSec = Math.floor(Date.now() / 1e3);
3319
+ if (currentTimestampSec > payload.expiresAt) {
3320
+ throw new Error(
3321
+ `License key has expired. Expiration: ${new Date(
3322
+ payload.expiresAt * 1e3
3323
+ ).toDateString()}`
3324
+ );
3325
+ }
3326
+ if (isProduction && provider) {
3327
+ const tier = (payload.tier || "").toLowerCase();
3328
+ const normalizedProvider = provider.toLowerCase();
3329
+ if (tier === "hobby") {
3330
+ const allowedHobby = ["postgresql", "pgvector", "supabase"];
3331
+ if (!allowedHobby.includes(normalizedProvider)) {
3332
+ throw new Error(
3333
+ `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.`
3334
+ );
3335
+ }
3336
+ } else if (tier === "pro" || tier === "developer_pro" || tier === "premium" || tier === "growth" || tier === "free_trial" || tier === "free_tier" || tier === "free") {
3337
+ const allowedPro = [
3338
+ "postgresql",
3339
+ "pgvector",
3340
+ "supabase",
3341
+ "pinecone",
3342
+ "qdrant",
3343
+ "mongodb",
3344
+ "milvus",
3345
+ "chroma",
3346
+ "chromadb"
3347
+ ];
3348
+ if (!allowedPro.includes(normalizedProvider)) {
3349
+ throw new Error(
3350
+ `The database provider "${provider}" is not allowed on the Developer Pro tier. Please upgrade to an Enterprise plan.`
3351
+ );
3352
+ }
3353
+ }
3354
+ }
3355
+ if (licenseKey) {
3356
+ const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
3357
+ this.cache.set(cacheKey, { payload, cachedAt: now });
3358
+ }
3359
+ return payload;
3360
+ } catch (err) {
3361
+ const message = err instanceof Error ? err.message : String(err);
3362
+ throw new ConfigurationException(
3363
+ `[Retrivora SDK] License key validation failed: ${message}`
3364
+ );
3365
+ }
3366
+ }
3367
+ static async verifyIP(licenseKey) {
3368
+ if (!licenseKey) return;
3369
+ try {
3370
+ const parts = licenseKey.split(".");
3371
+ if (parts.length !== 3) return;
3372
+ const [, payloadB64] = parts;
3373
+ const payload = JSON.parse(
3374
+ Buffer.from(payloadB64, "base64url").toString("utf8")
3375
+ );
3376
+ const tier = (payload.tier || "").toLowerCase();
3377
+ if (tier === "enterprise" || tier === "custom") {
3378
+ return;
3379
+ }
3380
+ if (payload.ipv4 || payload.ipv6) {
3381
+ let currentIpv4 = "";
3382
+ let currentIpv6 = "";
3383
+ try {
3384
+ const res = await fetch("https://api4.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
3385
+ const data = await res.json();
3386
+ currentIpv4 = data.ip;
3387
+ } catch (e) {
3388
+ }
3389
+ try {
3390
+ const res = await fetch("https://api6.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
3391
+ const data = await res.json();
3392
+ currentIpv6 = data.ip;
3393
+ } catch (e) {
3394
+ }
3395
+ const localIps = [];
3396
+ try {
3397
+ const osModule = __require("os");
3398
+ const interfaces = osModule.networkInterfaces();
3399
+ for (const name of Object.keys(interfaces)) {
3400
+ for (const iface of interfaces[name] || []) {
3401
+ if (!iface.internal) {
3402
+ localIps.push(iface.address);
3403
+ }
3404
+ }
3405
+ }
3406
+ } catch (e) {
3407
+ }
3408
+ const isIpv4Match = payload.ipv4 && (currentIpv4 === payload.ipv4 || localIps.includes(payload.ipv4));
3409
+ const isIpv6Match = payload.ipv6 && (currentIpv6 === payload.ipv6 || localIps.includes(payload.ipv6));
3410
+ if (payload.ipv4 && payload.ipv6) {
3411
+ if (!isIpv4Match && !isIpv6Match) {
3412
+ throw new Error(
3413
+ `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.`
3414
+ );
3415
+ }
3416
+ } else if (payload.ipv4 && !isIpv4Match) {
3417
+ throw new Error(
3418
+ `License key access restricted. This license key was created for a different system (authorized IPv4: ${payload.ipv4}) and cannot be used on this machine.`
3419
+ );
3420
+ } else if (payload.ipv6 && !isIpv6Match) {
3421
+ throw new Error(
3422
+ `License key access restricted. This license key was created for a different system (authorized IPv6: ${payload.ipv6}) and cannot be used on this machine.`
3423
+ );
3424
+ }
3425
+ }
3426
+ } catch (err) {
3427
+ if (err.message.includes("License key access restricted")) {
3428
+ throw new ConfigurationException(`[Retrivora SDK] ${err.message}`);
3429
+ }
3430
+ }
3431
+ }
3432
+ };
3433
+ // A simple in-memory cache to save CPU overhead of cryptographic signature checks.
3434
+ LicenseVerifier.cache = /* @__PURE__ */ new Map();
3435
+ LicenseVerifier.CACHE_TTL_MS = 60 * 1e3;
3436
+ // Cache verified license for 60 seconds
3437
+ // Retrivora's Public Key used to verify the license key signature.
3438
+ // In production, this matches the private key held by Retrivora SaaS.
3439
+ LicenseVerifier.PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
3440
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMieCkCBtTfByRNOserm
3441
+ XM4T0Am29JyNzB4XQPe+WJJ56CN73H1HLXx9n1ByFcxkEJ9po+SURj5DnvUXwEy+
3442
+ xstx33wDPpVmcMQe33j5CRYS0S4gICiNqIRN7XkTlJtrcXqrmh1/hdOAwfRbjO1T
3443
+ NVtORHwUwWfI/lBLyxUPGtKPed+0fQ7NtcW4o00JXxs3EjCB5BV9CbnXoTjQb/4h
3444
+ iwZof4l8rb7oaNzOsVg0RSyxsETX7Ex5sI0CjBz1p2mYp4oVhw/A/h8Ls7H0XzjC
3445
+ +Eb6BLtsytt5JHoSp0jExLlCpDmpys2L+kETcBVx+IqiXtdN1n6KbkksvEDUVzLI
3446
+ MwIDAQAB
3447
+ -----END PUBLIC KEY-----`;
3448
+
3449
+ // src/core/LicenseValidator.ts
3450
+ var _LicenseValidator = class _LicenseValidator {
3451
+ // 5-minute TTL for successful validation only
3452
+ constructor() {
3453
+ this.cache = /* @__PURE__ */ new Map();
3454
+ }
3455
+ static getInstance() {
3456
+ if (!_LicenseValidator.instance) {
3457
+ _LicenseValidator.instance = new _LicenseValidator();
3458
+ }
3459
+ return _LicenseValidator.instance;
3460
+ }
3461
+ /**
3462
+ * Invalidate local validation cache for a license key
3463
+ */
3464
+ purgeCache(licenseKey) {
3465
+ if (licenseKey) {
3466
+ this.cache.delete(licenseKey);
3467
+ } else {
3468
+ this.cache.clear();
3469
+ }
3470
+ }
3471
+ /**
3472
+ * Validate license status and SDK version against Retrivora License Service
3473
+ */
3474
+ async validate(request) {
3475
+ var _a;
3476
+ const {
3477
+ licenseKey,
3478
+ projectId,
3479
+ sdkVersion = SDK_VERSION,
3480
+ sdk = "@retrivora-ai/rag-engine",
3481
+ platform = typeof window !== "undefined" ? "browser" : "node",
3482
+ retrivoraApiBase,
3483
+ headers: customHeaders
3484
+ } = request;
3485
+ const getHeader = (name) => {
3486
+ if (!customHeaders) return void 0;
3487
+ const target = name.toLowerCase();
3488
+ for (const [k, v] of Object.entries(customHeaders)) {
3489
+ if (k.toLowerCase() === target) return v;
3490
+ }
3491
+ return void 0;
3492
+ };
3493
+ const effectiveLicenseKey = licenseKey || getHeader("x-license-key") || ((_a = getHeader("authorization")) == null ? void 0 : _a.replace(/^Bearer\s+/i, "")) || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY || process.env.RETRIVORA_LICENSE_KEY : "") || "";
3494
+ if (!effectiveLicenseKey) {
3495
+ this.purgeCache(effectiveLicenseKey);
3496
+ throw new LicenseValidationError("Missing RETRIVORA_LICENSE_KEY in request.");
3497
+ }
3498
+ const cached = this.cache.get(effectiveLicenseKey);
3499
+ if (cached) {
3500
+ const isFresh = Date.now() - cached.timestamp < _LicenseValidator.SUCCESS_CACHE_TTL_MS;
3501
+ if (isFresh && cached.response.valid && cached.response.licenseStatus === "ACTIVE" && !cached.response.forceUpgrade) {
3502
+ return cached.response;
3503
+ } else {
3504
+ this.cache.delete(effectiveLicenseKey);
3505
+ }
3506
+ }
3507
+ const base = retrivoraApiBase || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_RETRIVORA_API_BASE || process.env.RETRIVORA_API_BASE : "") || "/api/retrivora";
3508
+ const validateUrl = `${base.replace(/\/$/, "")}/v1/license/validate`;
3509
+ let res = null;
3510
+ try {
3511
+ res = await fetch(validateUrl, {
3512
+ method: "POST",
3513
+ cache: "no-store",
3514
+ headers: __spreadValues({
3515
+ "Content-Type": "application/json",
3516
+ "x-license-key": effectiveLicenseKey,
3517
+ "x-sdk-version": sdkVersion
3518
+ }, customHeaders || {}),
3519
+ body: JSON.stringify({
3520
+ licenseKey,
3521
+ projectId,
3522
+ sdkVersion,
3523
+ sdk,
3524
+ platform
3525
+ })
3526
+ });
3527
+ } catch (err) {
3528
+ try {
3529
+ const payload = LicenseVerifier.verify(licenseKey, projectId || "my-rag-app");
3530
+ const fallbackResp = {
3531
+ valid: true,
3532
+ licenseStatus: "ACTIVE",
3533
+ minimumSupportedVersion: "2.1.0",
3534
+ latestVersion: SDK_VERSION,
3535
+ forceUpgrade: false,
3536
+ expiresAt: payload.expiresAt ? new Date(payload.expiresAt * 1e3).toISOString() : null,
3537
+ message: "Local license verification active."
3538
+ };
3539
+ this.cache.set(licenseKey, { response: fallbackResp, timestamp: Date.now() });
3540
+ return fallbackResp;
3541
+ } catch (e) {
3542
+ this.purgeCache(licenseKey);
3543
+ throw new LicenseValidationError(`License validation request failed: ${(err == null ? void 0 : err.message) || "Network error"}`);
3544
+ }
3545
+ }
3546
+ if (res && !res.ok) {
3547
+ try {
3548
+ const payload = LicenseVerifier.verify(licenseKey, projectId || "my-rag-app");
3549
+ const fallbackResp = {
3550
+ valid: true,
3551
+ licenseStatus: "ACTIVE",
3552
+ minimumSupportedVersion: "2.1.0",
3553
+ latestVersion: SDK_VERSION,
3554
+ forceUpgrade: false,
3555
+ expiresAt: payload.expiresAt ? new Date(payload.expiresAt * 1e3).toISOString() : null,
3556
+ message: "Local license verification active."
3557
+ };
3558
+ this.cache.set(licenseKey, { response: fallbackResp, timestamp: Date.now() });
3559
+ return fallbackResp;
3560
+ } catch (e) {
3561
+ }
3562
+ }
3563
+ const data = await res.json().catch(() => ({
3564
+ valid: false,
3565
+ licenseStatus: "REVOKED",
3566
+ minimumSupportedVersion: "2.1.0",
3567
+ latestVersion: SDK_VERSION,
3568
+ forceUpgrade: false,
3569
+ expiresAt: null,
3570
+ message: "Failed to parse license validation response."
3571
+ }));
3572
+ if (!res.ok || !data.valid || data.licenseStatus !== "ACTIVE" || data.forceUpgrade) {
3573
+ this.purgeCache(licenseKey);
3574
+ if (data.forceUpgrade || res.status === 426) {
3575
+ throw new SDKVersionUnsupportedError(
3576
+ data.message || `This SDK version (${sdkVersion}) is no longer supported. Upgrade to version ${data.latestVersion || "2.2.6"} or later.`,
3577
+ data
3578
+ );
3579
+ }
3580
+ const errMsg = data.message || `License validation failed with status: ${data.licenseStatus}. Access denied.`;
3581
+ throw new LicenseValidationError(errMsg, data);
3582
+ }
3583
+ this.cache.set(licenseKey, {
3584
+ response: data,
3585
+ timestamp: Date.now()
3586
+ });
3587
+ return data;
3588
+ }
3589
+ };
3590
+ _LicenseValidator.SUCCESS_CACHE_TTL_MS = 5 * 60 * 1e3;
3591
+ var LicenseValidator = _LicenseValidator;
3592
+
3174
3593
  // src/components/ChatWindow.tsx
3175
3594
  import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
3176
3595
  function ChatWindow({
@@ -3186,6 +3605,7 @@ function ChatWindow({
3186
3605
  onAddToCart,
3187
3606
  apiUrl,
3188
3607
  retrivoraApiBase,
3608
+ licenseKey: licenseKeyProp,
3189
3609
  headers
3190
3610
  }) {
3191
3611
  var _a;
@@ -3200,6 +3620,7 @@ function ChatWindow({
3200
3620
  namespace: projectId,
3201
3621
  apiUrl,
3202
3622
  retrivoraApiBase,
3623
+ licenseKey: licenseKeyProp,
3203
3624
  headers
3204
3625
  });
3205
3626
  const [suggestions, setSuggestions] = useState6([]);
@@ -3214,42 +3635,40 @@ function ChatWindow({
3214
3635
  async function validateSessionLicense() {
3215
3636
  var _a2;
3216
3637
  try {
3217
- const base = retrivoraApiBase || "/api/retrivora";
3218
- const configUrl = `${base.replace(/\/$/, "")}/config?sdkVersion=${SDK_VERSION}`;
3219
- const res = await fetch(configUrl, {
3220
- method: "GET",
3221
- cache: "no-store",
3222
- headers: __spreadValues({
3223
- "Content-Type": "application/json",
3224
- "x-sdk-version": SDK_VERSION
3225
- }, headers || {})
3226
- });
3227
- if (!res.ok) {
3228
- const data = await res.json().catch(() => ({}));
3229
- if (res.status === 426 || data.code === "SDK_VERSION_OUTDATED") {
3230
- if (isMounted) {
3231
- setVersionError(data.error || "Your Retrivora SDK package is outdated. Please update your package to the latest version to continue.");
3232
- }
3233
- } else if (res.status === 403 || res.status === 401 || typeof data.error === "string" && data.error.toLowerCase().includes("license")) {
3234
- if (isMounted) {
3235
- const errMsg = typeof data.error === "string" ? data.error : ((_a2 = data.error) == null ? void 0 : _a2.message) || "Your Retrivora license is no longer valid. Please contact your administrator or obtain a valid license key.";
3236
- setLicenseError(errMsg);
3237
- }
3638
+ const getHeader = (name) => {
3639
+ if (!headers) return void 0;
3640
+ const target = name.toLowerCase();
3641
+ for (const [k, v] of Object.entries(headers)) {
3642
+ if (k.toLowerCase() === target) return v;
3238
3643
  }
3239
- } else {
3240
- if (isMounted) {
3241
- setLicenseError(null);
3242
- setVersionError(null);
3644
+ return void 0;
3645
+ };
3646
+ const resolvedLicenseKey = licenseKeyProp || getHeader("x-license-key") || ((_a2 = getHeader("authorization")) == null ? void 0 : _a2.replace(/^Bearer\s+/i, "")) || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY || process.env.RETRIVORA_LICENSE_KEY : "") || "";
3647
+ await LicenseValidator.getInstance().validate({
3648
+ licenseKey: resolvedLicenseKey,
3649
+ projectId,
3650
+ retrivoraApiBase,
3651
+ headers
3652
+ });
3653
+ if (isMounted) {
3654
+ setLicenseError(null);
3655
+ setVersionError(null);
3656
+ }
3657
+ } catch (err) {
3658
+ if (isMounted) {
3659
+ if ((err == null ? void 0 : err.code) === "SDK_VERSION_UNSUPPORTED") {
3660
+ setVersionError((err == null ? void 0 : err.message) || "SDK version unsupported.");
3661
+ } else {
3662
+ setLicenseError((err == null ? void 0 : err.message) || "License validation failed.");
3243
3663
  }
3244
3664
  }
3245
- } catch (e) {
3246
3665
  }
3247
3666
  }
3248
3667
  validateSessionLicense();
3249
3668
  return () => {
3250
3669
  isMounted = false;
3251
3670
  };
3252
- }, [retrivoraApiBase, headers]);
3671
+ }, [retrivoraApiBase, headers, projectId]);
3253
3672
  useEffect5(() => {
3254
3673
  if (typeof window !== "undefined") {
3255
3674
  const win = window;
@@ -3697,8 +4116,8 @@ var GEMINI_STYLES = `
3697
4116
  --circle: shape(evenodd from 13.482% 79.505%, curve by -7.1945% -12.47% with -1.4985% -1.8575% / -6.328% -10.225%, curve by 0.0985% -33.8965% with -4.1645% -10.7945% / -4.1685% -23.0235%, curve by 6.9955% -12.101% with 1.72% -4.3825% / 4.0845% -8.458%, curve by 30.125% -17.119% with 7.339% -9.1825% / 18.4775% -15.5135%, curve by 13.4165% 0.095% with 4.432% -0.6105% / 8.9505% -0.5855%, curve by 29.364% 16.9% with 11.6215% 1.77% / 22.102% 7.9015%, curve by 7.176% 12.4145% with 3.002% 3.7195% / 5.453% 7.968%, curve by -0.0475% 33.8925% with 4.168% 10.756% / 4.2305% 22.942%, curve by -7.1135% 12.2825% with -1.74% 4.4535% / -4.1455% 8.592%, curve by -29.404% 16.9075% with -7.202% 8.954% / -18.019% 15.137%, curve by -14.19% -0.018% with -4.6635% 0.7255% / -9.4575% 0.7205%, curve by -29.226% -16.8875% with -11.573% -1.8065% / -21.9955% -7.9235%, close);
3698
4117
  }
3699
4118
  `;
3700
- function ChatWidget({ position = "bottom-right", onAddToCart, apiUrl, retrivoraApiBase, headers }) {
3701
- const { ui } = useConfig();
4119
+ function ChatWidget({ position = "bottom-right", onAddToCart, apiUrl, retrivoraApiBase, licenseKey: licenseKeyProp, headers }) {
4120
+ const { ui, projectId } = useConfig();
3702
4121
  const [isOpen, setIsOpen] = useState7(false);
3703
4122
  const [hasUnread, setHasUnread] = useState7(false);
3704
4123
  const [dimensions, setDimensions] = useState7(DEFAULT_DIMENSIONS);
@@ -3714,36 +4133,27 @@ function ChatWidget({ position = "bottom-right", onAddToCart, apiUrl, retrivoraA
3714
4133
  var _a;
3715
4134
  setIsValidating(true);
3716
4135
  try {
3717
- const base = retrivoraApiBase || "/api/retrivora";
3718
- const configUrl = `${base.replace(/\/$/, "")}/config?sdkVersion=${SDK_VERSION}`;
3719
- const res = await fetch(configUrl, {
3720
- method: "GET",
3721
- cache: "no-store",
3722
- headers: __spreadValues({
3723
- "Content-Type": "application/json",
3724
- "x-sdk-version": SDK_VERSION
3725
- }, headers || {})
3726
- });
3727
- if (!res.ok) {
3728
- const data = await res.json().catch(() => ({}));
3729
- if (res.status === 426 || data.code === "SDK_VERSION_OUTDATED") {
3730
- const msg = data.error || "Your Retrivora SDK package version is outdated. Please update your package to the latest version to continue.";
3731
- setWidgetError(msg);
3732
- setIsOpen(false);
3733
- return;
3734
- }
3735
- if (res.status === 403 || res.status === 401 || typeof data.error === "string" && data.error.toLowerCase().includes("license")) {
3736
- const msg = (typeof data.error === "string" ? data.error : (_a = data.error) == null ? void 0 : _a.message) || "Your Retrivora license is no longer valid. Please contact your administrator or obtain a valid license key.";
3737
- setWidgetError(msg);
3738
- setIsOpen(false);
3739
- return;
4136
+ const getHeader = (name) => {
4137
+ if (!headers) return void 0;
4138
+ const target = name.toLowerCase();
4139
+ for (const [k, v] of Object.entries(headers)) {
4140
+ if (k.toLowerCase() === target) return v;
3740
4141
  }
3741
- }
4142
+ return void 0;
4143
+ };
4144
+ const resolvedLicenseKey = licenseKeyProp || getHeader("x-license-key") || ((_a = getHeader("authorization")) == null ? void 0 : _a.replace(/^Bearer\s+/i, "")) || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY || process.env.RETRIVORA_LICENSE_KEY : "") || "";
4145
+ await LicenseValidator.getInstance().validate({
4146
+ licenseKey: resolvedLicenseKey,
4147
+ projectId,
4148
+ retrivoraApiBase,
4149
+ headers
4150
+ });
3742
4151
  setWidgetError(null);
3743
4152
  setIsOpen(true);
3744
4153
  setHasUnread(false);
3745
- } catch (e) {
3746
- setIsOpen(true);
4154
+ } catch (err) {
4155
+ setWidgetError((err == null ? void 0 : err.message) || "Access denied.");
4156
+ setIsOpen(false);
3747
4157
  } finally {
3748
4158
  setIsValidating(false);
3749
4159
  }
@@ -3815,6 +4225,7 @@ function ChatWidget({ position = "bottom-right", onAddToCart, apiUrl, retrivoraA
3815
4225
  onAddToCart,
3816
4226
  apiUrl,
3817
4227
  retrivoraApiBase,
4228
+ licenseKey: licenseKeyProp,
3818
4229
  headers
3819
4230
  }
3820
4231
  ),
@@ -5882,46 +6293,6 @@ _RendererRegistry.registerStrategy(new CarouselRendererStrategy());
5882
6293
  _RendererRegistry.registerStrategy(new ChartRendererStrategy());
5883
6294
  _RendererRegistry.registerStrategy(new MixedRendererStrategy());
5884
6295
  var RendererRegistry = _RendererRegistry;
5885
-
5886
- // src/exceptions/index.ts
5887
- var RetrivoraError = class extends Error {
5888
- constructor(message, code, details) {
5889
- super(message);
5890
- this.name = new.target.name;
5891
- this.code = code;
5892
- this.details = details;
5893
- }
5894
- };
5895
- var ProviderNotFoundException = class extends RetrivoraError {
5896
- constructor(providerType, provider, details) {
5897
- super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
5898
- }
5899
- };
5900
- var EmbeddingFailedException = class extends RetrivoraError {
5901
- constructor(message = "Embedding generation failed", details) {
5902
- super(message, "EMBEDDING_FAILED", details);
5903
- }
5904
- };
5905
- var RetrievalException = class extends RetrivoraError {
5906
- constructor(message = "Retrieval failed", details) {
5907
- super(message, "RETRIEVAL_FAILED", details);
5908
- }
5909
- };
5910
- var RateLimitException = class extends RetrivoraError {
5911
- constructor(message = "Provider rate limit exceeded", details) {
5912
- super(message, "RATE_LIMITED", details);
5913
- }
5914
- };
5915
- var ConfigurationException = class extends RetrivoraError {
5916
- constructor(message, details) {
5917
- super(message, "CONFIGURATION_ERROR", details);
5918
- }
5919
- };
5920
- var AuthenticationException = class extends RetrivoraError {
5921
- constructor(message = "Provider authentication failed", details) {
5922
- super(message, "AUTHENTICATION_ERROR", details);
5923
- }
5924
- };
5925
6296
  export {
5926
6297
  AuthenticationException,
5927
6298
  ChatWidget,
@@ -5932,6 +6303,8 @@ export {
5932
6303
  DocumentUpload,
5933
6304
  EmbeddingFailedException,
5934
6305
  IntentClassifier,
6306
+ LicenseValidationError,
6307
+ LicenseValidator,
5935
6308
  MessageBubble,
5936
6309
  ObservabilityPanel,
5937
6310
  ProductCard,
@@ -5942,6 +6315,7 @@ export {
5942
6315
  RetrievalException,
5943
6316
  RetrivoraError,
5944
6317
  RuleEngine,
6318
+ SDKVersionUnsupportedError,
5945
6319
  SDK_VERSION,
5946
6320
  SourceCard,
5947
6321
  VisualizationDecisionEngine,