@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.js CHANGED
@@ -69,6 +69,8 @@ __export(index_exports, {
69
69
  DocumentUpload: () => DocumentUpload,
70
70
  EmbeddingFailedException: () => EmbeddingFailedException,
71
71
  IntentClassifier: () => IntentClassifier,
72
+ LicenseValidationError: () => LicenseValidationError,
73
+ LicenseValidator: () => LicenseValidator,
72
74
  MessageBubble: () => MessageBubble,
73
75
  ObservabilityPanel: () => ObservabilityPanel,
74
76
  ProductCard: () => ProductCard,
@@ -79,6 +81,7 @@ __export(index_exports, {
79
81
  RetrievalException: () => RetrievalException,
80
82
  RetrivoraError: () => RetrivoraError,
81
83
  RuleEngine: () => RuleEngine,
84
+ SDKVersionUnsupportedError: () => SDKVersionUnsupportedError,
82
85
  SDK_VERSION: () => SDK_VERSION,
83
86
  SourceCard: () => SourceCard,
84
87
  VisualizationDecisionEngine: () => VisualizationDecisionEngine,
@@ -2757,7 +2760,7 @@ function useRagChat(projectId, options = {}) {
2757
2760
  }, [messages]);
2758
2761
  const sendMessage = (0, import_react11.useCallback)(
2759
2762
  async (text, opts) => {
2760
- var _a, _b, _c, _d, _e;
2763
+ var _a, _b, _c, _d, _e, _f;
2761
2764
  const trimmed = text.trim();
2762
2765
  if (!trimmed || isLoading) return;
2763
2766
  lastInputRef.current = trimmed;
@@ -2789,9 +2792,18 @@ function useRagChat(projectId, options = {}) {
2789
2792
  messageId: assistantMessageId,
2790
2793
  userMessageId: userMsgId
2791
2794
  });
2792
- const fetchHeaders = __spreadValues({
2795
+ const getHeader = (headersObj, name) => {
2796
+ if (!headersObj) return void 0;
2797
+ const target = name.toLowerCase();
2798
+ for (const [k, v] of Object.entries(headersObj)) {
2799
+ if (k.toLowerCase() === target) return v;
2800
+ }
2801
+ return void 0;
2802
+ };
2803
+ 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 : "") || "";
2804
+ const fetchHeaders = __spreadValues(__spreadValues({
2793
2805
  "Content-Type": "application/json"
2794
- }, options.headers || {});
2806
+ }, resolvedLicenseKey ? { "x-license-key": resolvedLicenseKey } : {}), options.headers || {});
2795
2807
  let response = await fetch(primaryUrl, {
2796
2808
  method: "POST",
2797
2809
  headers: fetchHeaders,
@@ -2809,10 +2821,10 @@ function useRagChat(projectId, options = {}) {
2809
2821
  }
2810
2822
  if (!response.ok) {
2811
2823
  const errorData = await response.json().catch(() => ({}));
2812
- 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") {
2824
+ 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") {
2813
2825
  throw new Error("Your Retrivora license is no longer valid. Please contact your administrator or obtain a valid license key.");
2814
2826
  }
2815
- throw new Error(((_c = errorData.error) == null ? void 0 : _c.message) || errorData.error || `Server returned ${response.status}`);
2827
+ throw new Error(((_d = errorData.error) == null ? void 0 : _d.message) || errorData.error || `Server returned ${response.status}`);
2816
2828
  }
2817
2829
  if (!response.body) {
2818
2830
  throw new Error("No response body received from server");
@@ -2876,7 +2888,7 @@ function useRagChat(projectId, options = {}) {
2876
2888
  pendingThinkingRef.current = thinkingContent;
2877
2889
  scheduleFlush(assistantMessageId);
2878
2890
  } else if (frame.type === "metadata") {
2879
- sources = (_d = frame.sources) != null ? _d : [];
2891
+ sources = (_e = frame.sources) != null ? _e : [];
2880
2892
  thinkingMs = frame.thinkingMs;
2881
2893
  } else if (frame.type === "ui_transformation") {
2882
2894
  uiTransformation = frame.data;
@@ -2892,7 +2904,7 @@ function useRagChat(projectId, options = {}) {
2892
2904
  if (frame.type === "text" && frame.text) assistantContent += frame.text;
2893
2905
  else if (frame.type === "thinking" && frame.text) thinkingContent += frame.text;
2894
2906
  else if (frame.type === "metadata") {
2895
- sources = (_e = frame.sources) != null ? _e : [];
2907
+ sources = (_f = frame.sources) != null ? _f : [];
2896
2908
  thinkingMs = frame.thinkingMs;
2897
2909
  } else if (frame.type === "observability") trace = frame.data;
2898
2910
  }
@@ -2917,7 +2929,10 @@ function useRagChat(projectId, options = {}) {
2917
2929
  console.log("[useRagChat] Streaming stopped by user.");
2918
2930
  return;
2919
2931
  }
2920
- const msg = err instanceof Error ? err.message : "Something went wrong. Please try again.";
2932
+ let msg = err instanceof Error ? err.message : "Something went wrong. Please try again.";
2933
+ if (msg.includes("403") || msg.toLowerCase().includes("license") || msg.toLowerCase().includes("revoked") || msg.toLowerCase().includes("terminated")) {
2934
+ msg = "Your Retrivora license key has been terminated, suspended, or revoked. Access denied.";
2935
+ }
2921
2936
  setError(msg);
2922
2937
  onError == null ? void 0 : onError(msg);
2923
2938
  } finally {
@@ -3029,7 +3044,7 @@ function useRagChat(projectId, options = {}) {
3029
3044
  // package.json
3030
3045
  var package_default = {
3031
3046
  name: "@retrivora-ai/rag-engine",
3032
- version: "2.2.6",
3047
+ version: "2.2.8",
3033
3048
  description: "Retrivora AI is a plug-and-play AI engine for RAG chat experiences \u2014 generic vector DB + LLM provider, embeddable or standalone.",
3034
3049
  author: "Abhinav Alkuchi",
3035
3050
  license: "UNLICENSED",
@@ -3169,6 +3184,407 @@ var package_default = {
3169
3184
  // src/version.ts
3170
3185
  var SDK_VERSION = package_default.version || "2.1.3";
3171
3186
 
3187
+ // src/exceptions/index.ts
3188
+ var RetrivoraError = class extends Error {
3189
+ constructor(message, code, details) {
3190
+ super(message);
3191
+ this.name = new.target.name;
3192
+ this.code = code;
3193
+ this.details = details;
3194
+ }
3195
+ };
3196
+ var ProviderNotFoundException = class extends RetrivoraError {
3197
+ constructor(providerType, provider, details) {
3198
+ super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
3199
+ }
3200
+ };
3201
+ var EmbeddingFailedException = class extends RetrivoraError {
3202
+ constructor(message = "Embedding generation failed", details) {
3203
+ super(message, "EMBEDDING_FAILED", details);
3204
+ }
3205
+ };
3206
+ var RetrievalException = class extends RetrivoraError {
3207
+ constructor(message = "Retrieval failed", details) {
3208
+ super(message, "RETRIEVAL_FAILED", details);
3209
+ }
3210
+ };
3211
+ var RateLimitException = class extends RetrivoraError {
3212
+ constructor(message = "Provider rate limit exceeded", details) {
3213
+ super(message, "RATE_LIMITED", details);
3214
+ }
3215
+ };
3216
+ var ConfigurationException = class extends RetrivoraError {
3217
+ constructor(message, details) {
3218
+ super(message, "CONFIGURATION_ERROR", details);
3219
+ }
3220
+ };
3221
+ var AuthenticationException = class extends RetrivoraError {
3222
+ constructor(message = "Provider authentication failed", details) {
3223
+ super(message, "AUTHENTICATION_ERROR", details);
3224
+ }
3225
+ };
3226
+ var SDKVersionUnsupportedError = class extends RetrivoraError {
3227
+ constructor(message = "This SDK version is no longer supported.", details) {
3228
+ super(message, "SDK_VERSION_UNSUPPORTED", details);
3229
+ }
3230
+ };
3231
+ var LicenseValidationError = class extends RetrivoraError {
3232
+ constructor(message = "License validation failed.", details) {
3233
+ super(message, "LICENSE_VALIDATION_ERROR", details);
3234
+ }
3235
+ };
3236
+
3237
+ // src/core/LicenseVerifier.ts
3238
+ var crypto = __toESM(require("crypto"));
3239
+ var LicenseVerifier = class {
3240
+ /**
3241
+ * Decodes, verifies signature, and checks metadata of a license key.
3242
+ *
3243
+ * @param licenseKey - Base64url signed JWT license key.
3244
+ * @param currentProjectId - Project namespace ID.
3245
+ * @param publicKeyOverride - Optional override for unit/integration tests.
3246
+ */
3247
+ static verify(licenseKey, currentProjectId, provider, publicKeyOverride) {
3248
+ const isProduction = process.env.NODE_ENV === "production";
3249
+ const now = Date.now();
3250
+ if (licenseKey) {
3251
+ const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
3252
+ const cached = this.cache.get(cacheKey);
3253
+ if (cached && now - cached.cachedAt < this.CACHE_TTL_MS) {
3254
+ const currentTimestampSec = Math.floor(now / 1e3);
3255
+ if (cached.payload.expiresAt && currentTimestampSec > cached.payload.expiresAt) {
3256
+ this.cache.delete(cacheKey);
3257
+ } else {
3258
+ return cached.payload;
3259
+ }
3260
+ }
3261
+ }
3262
+ if (!licenseKey) {
3263
+ if (isProduction) {
3264
+ throw new ConfigurationException(
3265
+ "[Retrivora SDK] License key (licenseKey) is required in production environments."
3266
+ );
3267
+ }
3268
+ console.warn(
3269
+ `\x1B[33m[Retrivora SDK] WARNING: Running without a license key. This namespace (${currentProjectId}) is permitted for local development only.\x1B[0m`
3270
+ );
3271
+ return {
3272
+ projectId: currentProjectId,
3273
+ expiresAt: Math.floor(Date.now() / 1e3) + 86400,
3274
+ // Valid for 24h
3275
+ tier: "hobby"
3276
+ };
3277
+ }
3278
+ try {
3279
+ const rawToken = licenseKey.replace(/^rtv_/i, "").trim();
3280
+ const parts = rawToken.split(".");
3281
+ if (parts.length !== 3) {
3282
+ throw new Error("Malformed token structure (expected 3 parts).");
3283
+ }
3284
+ const [headerB64, payloadB64, signatureB64] = parts;
3285
+ const dataToVerify = `${headerB64}.${payloadB64}`;
3286
+ const publicKey = publicKeyOverride != null ? publicKeyOverride : this.PUBLIC_KEY;
3287
+ const signature = Buffer.from(signatureB64, "base64url");
3288
+ const data = Buffer.from(dataToVerify);
3289
+ const isValid = crypto.verify(
3290
+ "sha256",
3291
+ data,
3292
+ publicKey,
3293
+ signature
3294
+ );
3295
+ if (!isValid) {
3296
+ throw new Error("Signature verification failed.");
3297
+ }
3298
+ const payload = JSON.parse(
3299
+ Buffer.from(payloadB64, "base64url").toString("utf8")
3300
+ );
3301
+ if (!payload.projectId) {
3302
+ throw new Error('License payload is missing "projectId".');
3303
+ }
3304
+ const isProjectMatch = payload.projectId === currentProjectId || payload.projectId === `retrivora-${currentProjectId}` || `retrivora-${payload.projectId}` === currentProjectId;
3305
+ if (!isProjectMatch) {
3306
+ throw new Error(
3307
+ `Project ID mismatch. License is bound to project namespace "${payload.projectId}" but configuration has "${currentProjectId}".`
3308
+ );
3309
+ }
3310
+ if (!payload.expiresAt) {
3311
+ throw new Error('License payload is missing expiration ("expiresAt").');
3312
+ }
3313
+ const currentTimestampSec = Math.floor(Date.now() / 1e3);
3314
+ if (currentTimestampSec > payload.expiresAt) {
3315
+ throw new Error(
3316
+ `License key has expired. Expiration: ${new Date(
3317
+ payload.expiresAt * 1e3
3318
+ ).toDateString()}`
3319
+ );
3320
+ }
3321
+ if (isProduction && provider) {
3322
+ const tier = (payload.tier || "").toLowerCase();
3323
+ const normalizedProvider = provider.toLowerCase();
3324
+ if (tier === "hobby") {
3325
+ const allowedHobby = ["postgresql", "pgvector", "supabase"];
3326
+ if (!allowedHobby.includes(normalizedProvider)) {
3327
+ throw new Error(
3328
+ `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.`
3329
+ );
3330
+ }
3331
+ } else if (tier === "pro" || tier === "developer_pro" || tier === "premium" || tier === "growth" || tier === "free_trial" || tier === "free_tier" || tier === "free") {
3332
+ const allowedPro = [
3333
+ "postgresql",
3334
+ "pgvector",
3335
+ "supabase",
3336
+ "pinecone",
3337
+ "qdrant",
3338
+ "mongodb",
3339
+ "milvus",
3340
+ "chroma",
3341
+ "chromadb"
3342
+ ];
3343
+ if (!allowedPro.includes(normalizedProvider)) {
3344
+ throw new Error(
3345
+ `The database provider "${provider}" is not allowed on the Developer Pro tier. Please upgrade to an Enterprise plan.`
3346
+ );
3347
+ }
3348
+ }
3349
+ }
3350
+ if (licenseKey) {
3351
+ const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
3352
+ this.cache.set(cacheKey, { payload, cachedAt: now });
3353
+ }
3354
+ return payload;
3355
+ } catch (err) {
3356
+ const message = err instanceof Error ? err.message : String(err);
3357
+ throw new ConfigurationException(
3358
+ `[Retrivora SDK] License key validation failed: ${message}`
3359
+ );
3360
+ }
3361
+ }
3362
+ static async verifyIP(licenseKey) {
3363
+ if (!licenseKey) return;
3364
+ try {
3365
+ const parts = licenseKey.split(".");
3366
+ if (parts.length !== 3) return;
3367
+ const [, payloadB64] = parts;
3368
+ const payload = JSON.parse(
3369
+ Buffer.from(payloadB64, "base64url").toString("utf8")
3370
+ );
3371
+ const tier = (payload.tier || "").toLowerCase();
3372
+ if (tier === "enterprise" || tier === "custom") {
3373
+ return;
3374
+ }
3375
+ if (payload.ipv4 || payload.ipv6) {
3376
+ let currentIpv4 = "";
3377
+ let currentIpv6 = "";
3378
+ try {
3379
+ const res = await fetch("https://api4.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
3380
+ const data = await res.json();
3381
+ currentIpv4 = data.ip;
3382
+ } catch (e) {
3383
+ }
3384
+ try {
3385
+ const res = await fetch("https://api6.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
3386
+ const data = await res.json();
3387
+ currentIpv6 = data.ip;
3388
+ } catch (e) {
3389
+ }
3390
+ const localIps = [];
3391
+ try {
3392
+ const osModule = require("os");
3393
+ const interfaces = osModule.networkInterfaces();
3394
+ for (const name of Object.keys(interfaces)) {
3395
+ for (const iface of interfaces[name] || []) {
3396
+ if (!iface.internal) {
3397
+ localIps.push(iface.address);
3398
+ }
3399
+ }
3400
+ }
3401
+ } catch (e) {
3402
+ }
3403
+ const isIpv4Match = payload.ipv4 && (currentIpv4 === payload.ipv4 || localIps.includes(payload.ipv4));
3404
+ const isIpv6Match = payload.ipv6 && (currentIpv6 === payload.ipv6 || localIps.includes(payload.ipv6));
3405
+ if (payload.ipv4 && payload.ipv6) {
3406
+ if (!isIpv4Match && !isIpv6Match) {
3407
+ throw new Error(
3408
+ `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.`
3409
+ );
3410
+ }
3411
+ } else if (payload.ipv4 && !isIpv4Match) {
3412
+ throw new Error(
3413
+ `License key access restricted. This license key was created for a different system (authorized IPv4: ${payload.ipv4}) and cannot be used on this machine.`
3414
+ );
3415
+ } else if (payload.ipv6 && !isIpv6Match) {
3416
+ throw new Error(
3417
+ `License key access restricted. This license key was created for a different system (authorized IPv6: ${payload.ipv6}) and cannot be used on this machine.`
3418
+ );
3419
+ }
3420
+ }
3421
+ } catch (err) {
3422
+ if (err.message.includes("License key access restricted")) {
3423
+ throw new ConfigurationException(`[Retrivora SDK] ${err.message}`);
3424
+ }
3425
+ }
3426
+ }
3427
+ };
3428
+ // A simple in-memory cache to save CPU overhead of cryptographic signature checks.
3429
+ LicenseVerifier.cache = /* @__PURE__ */ new Map();
3430
+ LicenseVerifier.CACHE_TTL_MS = 60 * 1e3;
3431
+ // Cache verified license for 60 seconds
3432
+ // Retrivora's Public Key used to verify the license key signature.
3433
+ // In production, this matches the private key held by Retrivora SaaS.
3434
+ LicenseVerifier.PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
3435
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMieCkCBtTfByRNOserm
3436
+ XM4T0Am29JyNzB4XQPe+WJJ56CN73H1HLXx9n1ByFcxkEJ9po+SURj5DnvUXwEy+
3437
+ xstx33wDPpVmcMQe33j5CRYS0S4gICiNqIRN7XkTlJtrcXqrmh1/hdOAwfRbjO1T
3438
+ NVtORHwUwWfI/lBLyxUPGtKPed+0fQ7NtcW4o00JXxs3EjCB5BV9CbnXoTjQb/4h
3439
+ iwZof4l8rb7oaNzOsVg0RSyxsETX7Ex5sI0CjBz1p2mYp4oVhw/A/h8Ls7H0XzjC
3440
+ +Eb6BLtsytt5JHoSp0jExLlCpDmpys2L+kETcBVx+IqiXtdN1n6KbkksvEDUVzLI
3441
+ MwIDAQAB
3442
+ -----END PUBLIC KEY-----`;
3443
+
3444
+ // src/core/LicenseValidator.ts
3445
+ var _LicenseValidator = class _LicenseValidator {
3446
+ // 5-minute TTL for successful validation only
3447
+ constructor() {
3448
+ this.cache = /* @__PURE__ */ new Map();
3449
+ }
3450
+ static getInstance() {
3451
+ if (!_LicenseValidator.instance) {
3452
+ _LicenseValidator.instance = new _LicenseValidator();
3453
+ }
3454
+ return _LicenseValidator.instance;
3455
+ }
3456
+ /**
3457
+ * Invalidate local validation cache for a license key
3458
+ */
3459
+ purgeCache(licenseKey) {
3460
+ if (licenseKey) {
3461
+ this.cache.delete(licenseKey);
3462
+ } else {
3463
+ this.cache.clear();
3464
+ }
3465
+ }
3466
+ /**
3467
+ * Validate license status and SDK version against Retrivora License Service
3468
+ */
3469
+ async validate(request) {
3470
+ var _a;
3471
+ const {
3472
+ licenseKey,
3473
+ projectId,
3474
+ sdkVersion = SDK_VERSION,
3475
+ sdk = "@retrivora-ai/rag-engine",
3476
+ platform = typeof window !== "undefined" ? "browser" : "node",
3477
+ retrivoraApiBase,
3478
+ headers: customHeaders
3479
+ } = request;
3480
+ const getHeader = (name) => {
3481
+ if (!customHeaders) return void 0;
3482
+ const target = name.toLowerCase();
3483
+ for (const [k, v] of Object.entries(customHeaders)) {
3484
+ if (k.toLowerCase() === target) return v;
3485
+ }
3486
+ return void 0;
3487
+ };
3488
+ 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 : "") || "";
3489
+ if (!effectiveLicenseKey) {
3490
+ this.purgeCache(effectiveLicenseKey);
3491
+ throw new LicenseValidationError("Missing RETRIVORA_LICENSE_KEY in request.");
3492
+ }
3493
+ const cached = this.cache.get(effectiveLicenseKey);
3494
+ if (cached) {
3495
+ const isFresh = Date.now() - cached.timestamp < _LicenseValidator.SUCCESS_CACHE_TTL_MS;
3496
+ if (isFresh && cached.response.valid && cached.response.licenseStatus === "ACTIVE" && !cached.response.forceUpgrade) {
3497
+ return cached.response;
3498
+ } else {
3499
+ this.cache.delete(effectiveLicenseKey);
3500
+ }
3501
+ }
3502
+ const base = retrivoraApiBase || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_RETRIVORA_API_BASE || process.env.RETRIVORA_API_BASE : "") || "/api/retrivora";
3503
+ const validateUrl = `${base.replace(/\/$/, "")}/v1/license/validate`;
3504
+ let res = null;
3505
+ try {
3506
+ res = await fetch(validateUrl, {
3507
+ method: "POST",
3508
+ cache: "no-store",
3509
+ headers: __spreadValues({
3510
+ "Content-Type": "application/json",
3511
+ "x-license-key": effectiveLicenseKey,
3512
+ "x-sdk-version": sdkVersion
3513
+ }, customHeaders || {}),
3514
+ body: JSON.stringify({
3515
+ licenseKey,
3516
+ projectId,
3517
+ sdkVersion,
3518
+ sdk,
3519
+ platform
3520
+ })
3521
+ });
3522
+ } catch (err) {
3523
+ try {
3524
+ const payload = LicenseVerifier.verify(licenseKey, projectId || "my-rag-app");
3525
+ const fallbackResp = {
3526
+ valid: true,
3527
+ licenseStatus: "ACTIVE",
3528
+ minimumSupportedVersion: "2.1.0",
3529
+ latestVersion: SDK_VERSION,
3530
+ forceUpgrade: false,
3531
+ expiresAt: payload.expiresAt ? new Date(payload.expiresAt * 1e3).toISOString() : null,
3532
+ message: "Local license verification active."
3533
+ };
3534
+ this.cache.set(licenseKey, { response: fallbackResp, timestamp: Date.now() });
3535
+ return fallbackResp;
3536
+ } catch (e) {
3537
+ this.purgeCache(licenseKey);
3538
+ throw new LicenseValidationError(`License validation request failed: ${(err == null ? void 0 : err.message) || "Network error"}`);
3539
+ }
3540
+ }
3541
+ if (res && !res.ok) {
3542
+ try {
3543
+ const payload = LicenseVerifier.verify(licenseKey, projectId || "my-rag-app");
3544
+ const fallbackResp = {
3545
+ valid: true,
3546
+ licenseStatus: "ACTIVE",
3547
+ minimumSupportedVersion: "2.1.0",
3548
+ latestVersion: SDK_VERSION,
3549
+ forceUpgrade: false,
3550
+ expiresAt: payload.expiresAt ? new Date(payload.expiresAt * 1e3).toISOString() : null,
3551
+ message: "Local license verification active."
3552
+ };
3553
+ this.cache.set(licenseKey, { response: fallbackResp, timestamp: Date.now() });
3554
+ return fallbackResp;
3555
+ } catch (e) {
3556
+ }
3557
+ }
3558
+ const data = await res.json().catch(() => ({
3559
+ valid: false,
3560
+ licenseStatus: "REVOKED",
3561
+ minimumSupportedVersion: "2.1.0",
3562
+ latestVersion: SDK_VERSION,
3563
+ forceUpgrade: false,
3564
+ expiresAt: null,
3565
+ message: "Failed to parse license validation response."
3566
+ }));
3567
+ if (!res.ok || !data.valid || data.licenseStatus !== "ACTIVE" || data.forceUpgrade) {
3568
+ this.purgeCache(licenseKey);
3569
+ if (data.forceUpgrade || res.status === 426) {
3570
+ throw new SDKVersionUnsupportedError(
3571
+ data.message || `This SDK version (${sdkVersion}) is no longer supported. Upgrade to version ${data.latestVersion || "2.2.6"} or later.`,
3572
+ data
3573
+ );
3574
+ }
3575
+ const errMsg = data.message || `License validation failed with status: ${data.licenseStatus}. Access denied.`;
3576
+ throw new LicenseValidationError(errMsg, data);
3577
+ }
3578
+ this.cache.set(licenseKey, {
3579
+ response: data,
3580
+ timestamp: Date.now()
3581
+ });
3582
+ return data;
3583
+ }
3584
+ };
3585
+ _LicenseValidator.SUCCESS_CACHE_TTL_MS = 5 * 60 * 1e3;
3586
+ var LicenseValidator = _LicenseValidator;
3587
+
3172
3588
  // src/components/ChatWindow.tsx
3173
3589
  var import_jsx_runtime13 = require("react/jsx-runtime");
3174
3590
  function ChatWindow({
@@ -3184,6 +3600,7 @@ function ChatWindow({
3184
3600
  onAddToCart,
3185
3601
  apiUrl,
3186
3602
  retrivoraApiBase,
3603
+ licenseKey: licenseKeyProp,
3187
3604
  headers
3188
3605
  }) {
3189
3606
  var _a;
@@ -3198,6 +3615,7 @@ function ChatWindow({
3198
3615
  namespace: projectId,
3199
3616
  apiUrl,
3200
3617
  retrivoraApiBase,
3618
+ licenseKey: licenseKeyProp,
3201
3619
  headers
3202
3620
  });
3203
3621
  const [suggestions, setSuggestions] = (0, import_react12.useState)([]);
@@ -3212,42 +3630,40 @@ function ChatWindow({
3212
3630
  async function validateSessionLicense() {
3213
3631
  var _a2;
3214
3632
  try {
3215
- const base = retrivoraApiBase || "/api/retrivora";
3216
- const configUrl = `${base.replace(/\/$/, "")}/config?sdkVersion=${SDK_VERSION}`;
3217
- const res = await fetch(configUrl, {
3218
- method: "GET",
3219
- cache: "no-store",
3220
- headers: __spreadValues({
3221
- "Content-Type": "application/json",
3222
- "x-sdk-version": SDK_VERSION
3223
- }, headers || {})
3224
- });
3225
- if (!res.ok) {
3226
- const data = await res.json().catch(() => ({}));
3227
- if (res.status === 426 || data.code === "SDK_VERSION_OUTDATED") {
3228
- if (isMounted) {
3229
- setVersionError(data.error || "Your Retrivora SDK package is outdated. Please update your package to the latest version to continue.");
3230
- }
3231
- } else if (res.status === 403 || res.status === 401 || typeof data.error === "string" && data.error.toLowerCase().includes("license")) {
3232
- if (isMounted) {
3233
- 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.";
3234
- setLicenseError(errMsg);
3235
- }
3633
+ const getHeader = (name) => {
3634
+ if (!headers) return void 0;
3635
+ const target = name.toLowerCase();
3636
+ for (const [k, v] of Object.entries(headers)) {
3637
+ if (k.toLowerCase() === target) return v;
3236
3638
  }
3237
- } else {
3238
- if (isMounted) {
3239
- setLicenseError(null);
3240
- setVersionError(null);
3639
+ return void 0;
3640
+ };
3641
+ 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 : "") || "";
3642
+ await LicenseValidator.getInstance().validate({
3643
+ licenseKey: resolvedLicenseKey,
3644
+ projectId,
3645
+ retrivoraApiBase,
3646
+ headers
3647
+ });
3648
+ if (isMounted) {
3649
+ setLicenseError(null);
3650
+ setVersionError(null);
3651
+ }
3652
+ } catch (err) {
3653
+ if (isMounted) {
3654
+ if ((err == null ? void 0 : err.code) === "SDK_VERSION_UNSUPPORTED") {
3655
+ setVersionError((err == null ? void 0 : err.message) || "SDK version unsupported.");
3656
+ } else {
3657
+ setLicenseError((err == null ? void 0 : err.message) || "License validation failed.");
3241
3658
  }
3242
3659
  }
3243
- } catch (e) {
3244
3660
  }
3245
3661
  }
3246
3662
  validateSessionLicense();
3247
3663
  return () => {
3248
3664
  isMounted = false;
3249
3665
  };
3250
- }, [retrivoraApiBase, headers]);
3666
+ }, [retrivoraApiBase, headers, projectId]);
3251
3667
  (0, import_react12.useEffect)(() => {
3252
3668
  if (typeof window !== "undefined") {
3253
3669
  const win = window;
@@ -3695,8 +4111,8 @@ var GEMINI_STYLES = `
3695
4111
  --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);
3696
4112
  }
3697
4113
  `;
3698
- function ChatWidget({ position = "bottom-right", onAddToCart, apiUrl, retrivoraApiBase, headers }) {
3699
- const { ui } = useConfig();
4114
+ function ChatWidget({ position = "bottom-right", onAddToCart, apiUrl, retrivoraApiBase, licenseKey: licenseKeyProp, headers }) {
4115
+ const { ui, projectId } = useConfig();
3700
4116
  const [isOpen, setIsOpen] = (0, import_react13.useState)(false);
3701
4117
  const [hasUnread, setHasUnread] = (0, import_react13.useState)(false);
3702
4118
  const [dimensions, setDimensions] = (0, import_react13.useState)(DEFAULT_DIMENSIONS);
@@ -3712,36 +4128,27 @@ function ChatWidget({ position = "bottom-right", onAddToCart, apiUrl, retrivoraA
3712
4128
  var _a;
3713
4129
  setIsValidating(true);
3714
4130
  try {
3715
- const base = retrivoraApiBase || "/api/retrivora";
3716
- const configUrl = `${base.replace(/\/$/, "")}/config?sdkVersion=${SDK_VERSION}`;
3717
- const res = await fetch(configUrl, {
3718
- method: "GET",
3719
- cache: "no-store",
3720
- headers: __spreadValues({
3721
- "Content-Type": "application/json",
3722
- "x-sdk-version": SDK_VERSION
3723
- }, headers || {})
3724
- });
3725
- if (!res.ok) {
3726
- const data = await res.json().catch(() => ({}));
3727
- if (res.status === 426 || data.code === "SDK_VERSION_OUTDATED") {
3728
- const msg = data.error || "Your Retrivora SDK package version is outdated. Please update your package to the latest version to continue.";
3729
- setWidgetError(msg);
3730
- setIsOpen(false);
3731
- return;
3732
- }
3733
- if (res.status === 403 || res.status === 401 || typeof data.error === "string" && data.error.toLowerCase().includes("license")) {
3734
- 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.";
3735
- setWidgetError(msg);
3736
- setIsOpen(false);
3737
- return;
4131
+ const getHeader = (name) => {
4132
+ if (!headers) return void 0;
4133
+ const target = name.toLowerCase();
4134
+ for (const [k, v] of Object.entries(headers)) {
4135
+ if (k.toLowerCase() === target) return v;
3738
4136
  }
3739
- }
4137
+ return void 0;
4138
+ };
4139
+ 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 : "") || "";
4140
+ await LicenseValidator.getInstance().validate({
4141
+ licenseKey: resolvedLicenseKey,
4142
+ projectId,
4143
+ retrivoraApiBase,
4144
+ headers
4145
+ });
3740
4146
  setWidgetError(null);
3741
4147
  setIsOpen(true);
3742
4148
  setHasUnread(false);
3743
- } catch (e) {
3744
- setIsOpen(true);
4149
+ } catch (err) {
4150
+ setWidgetError((err == null ? void 0 : err.message) || "Access denied.");
4151
+ setIsOpen(false);
3745
4152
  } finally {
3746
4153
  setIsValidating(false);
3747
4154
  }
@@ -3813,6 +4220,7 @@ function ChatWidget({ position = "bottom-right", onAddToCart, apiUrl, retrivoraA
3813
4220
  onAddToCart,
3814
4221
  apiUrl,
3815
4222
  retrivoraApiBase,
4223
+ licenseKey: licenseKeyProp,
3816
4224
  headers
3817
4225
  }
3818
4226
  ),
@@ -5880,46 +6288,6 @@ _RendererRegistry.registerStrategy(new CarouselRendererStrategy());
5880
6288
  _RendererRegistry.registerStrategy(new ChartRendererStrategy());
5881
6289
  _RendererRegistry.registerStrategy(new MixedRendererStrategy());
5882
6290
  var RendererRegistry = _RendererRegistry;
5883
-
5884
- // src/exceptions/index.ts
5885
- var RetrivoraError = class extends Error {
5886
- constructor(message, code, details) {
5887
- super(message);
5888
- this.name = new.target.name;
5889
- this.code = code;
5890
- this.details = details;
5891
- }
5892
- };
5893
- var ProviderNotFoundException = class extends RetrivoraError {
5894
- constructor(providerType, provider, details) {
5895
- super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
5896
- }
5897
- };
5898
- var EmbeddingFailedException = class extends RetrivoraError {
5899
- constructor(message = "Embedding generation failed", details) {
5900
- super(message, "EMBEDDING_FAILED", details);
5901
- }
5902
- };
5903
- var RetrievalException = class extends RetrivoraError {
5904
- constructor(message = "Retrieval failed", details) {
5905
- super(message, "RETRIEVAL_FAILED", details);
5906
- }
5907
- };
5908
- var RateLimitException = class extends RetrivoraError {
5909
- constructor(message = "Provider rate limit exceeded", details) {
5910
- super(message, "RATE_LIMITED", details);
5911
- }
5912
- };
5913
- var ConfigurationException = class extends RetrivoraError {
5914
- constructor(message, details) {
5915
- super(message, "CONFIGURATION_ERROR", details);
5916
- }
5917
- };
5918
- var AuthenticationException = class extends RetrivoraError {
5919
- constructor(message = "Provider authentication failed", details) {
5920
- super(message, "AUTHENTICATION_ERROR", details);
5921
- }
5922
- };
5923
6291
  // Annotate the CommonJS export names for ESM import in node:
5924
6292
  0 && (module.exports = {
5925
6293
  AuthenticationException,
@@ -5931,6 +6299,8 @@ var AuthenticationException = class extends RetrivoraError {
5931
6299
  DocumentUpload,
5932
6300
  EmbeddingFailedException,
5933
6301
  IntentClassifier,
6302
+ LicenseValidationError,
6303
+ LicenseValidator,
5934
6304
  MessageBubble,
5935
6305
  ObservabilityPanel,
5936
6306
  ProductCard,
@@ -5941,6 +6311,7 @@ var AuthenticationException = class extends RetrivoraError {
5941
6311
  RetrievalException,
5942
6312
  RetrivoraError,
5943
6313
  RuleEngine,
6314
+ SDKVersionUnsupportedError,
5944
6315
  SDK_VERSION,
5945
6316
  SourceCard,
5946
6317
  VisualizationDecisionEngine,