@llmops/core 0.2.13 → 0.3.0-beta.1

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.cjs CHANGED
@@ -1,5 +1,5 @@
1
- const require_db = require('./db-BOe6mM51.cjs');
2
- const require_neon_dialect = require('./neon-dialect-BQey5lUw.cjs');
1
+ const require_db = require('./db-Du2xmkGS.cjs');
2
+ const require_neon_dialect = require('./neon-dialect-BR1nZmKX.cjs');
3
3
  let __llmops_gateway = require("@llmops/gateway");
4
4
  __llmops_gateway = require_db.__toESM(__llmops_gateway);
5
5
  let kysely = require("kysely");
@@ -9,6 +9,8 @@ let node_path = require("node:path");
9
9
  node_path = require_db.__toESM(node_path);
10
10
  let __better_auth_utils_random = require("@better-auth/utils/random");
11
11
  let node_crypto = require("node:crypto");
12
+ let json_logic_js = require("json-logic-js");
13
+ json_logic_js = require_db.__toESM(json_logic_js);
12
14
 
13
15
  //#region src/providers/supported-providers.ts
14
16
  /**
@@ -840,7 +842,10 @@ var CacheService = class {
840
842
  }
841
843
  createBackend(config) {
842
844
  switch (config.backend) {
843
- case "memory": return new MemoryCacheBackend(config.maxSize, config.cleanupInterval);
845
+ case "memory": return new MemoryCacheBackend({
846
+ maxSize: config.maxSize,
847
+ cleanupIntervalMs: config.cleanupInterval
848
+ });
844
849
  case "file": return new FileCacheBackend(config.dataDir, config.fileName, config.saveInterval, config.cleanupInterval);
845
850
  default: throw new Error(`Unsupported cache backend: ${config.backend}`);
846
851
  }
@@ -1229,9 +1234,9 @@ const createConfigVariantDataLayer = (db) => {
1229
1234
  const value = await getVariantJsonDataForConfig.safeParseAsync(params);
1230
1235
  if (!value.success) throw new LLMOpsError(`Invalid parameters: ${value.error.message}`);
1231
1236
  const { configId: configIdOrSlug, envSecret } = value.data;
1232
- const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1237
+ const UUID_REGEX$1 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1233
1238
  let resolvedConfigId;
1234
- if (UUID_REGEX.test(configIdOrSlug)) resolvedConfigId = configIdOrSlug;
1239
+ if (UUID_REGEX$1.test(configIdOrSlug)) resolvedConfigId = configIdOrSlug;
1235
1240
  else {
1236
1241
  const config = await db.selectFrom("configs").select("id").where("slug", "=", configIdOrSlug).executeTakeFirst();
1237
1242
  if (!config) throw new LLMOpsError(`Config not found: ${configIdOrSlug}`);
@@ -1267,7 +1272,7 @@ const createConfigVariantDataLayer = (db) => {
1267
1272
  if (!versionData) throw new LLMOpsError(`No variant version found for variant ${configVariant.variantId}`);
1268
1273
  let finalProvider = versionData.provider;
1269
1274
  let providerConfigId = null;
1270
- if (UUID_REGEX.test(versionData.provider)) {
1275
+ if (UUID_REGEX$1.test(versionData.provider)) {
1271
1276
  const providerConfig = await db.selectFrom("provider_configs").select(["id", "providerId"]).where("id", "=", versionData.provider).executeTakeFirst();
1272
1277
  if (providerConfig) {
1273
1278
  finalProvider = providerConfig.providerId;
@@ -1798,20 +1803,40 @@ const createLLMRequestsDataLayer = (db) => {
1798
1803
 
1799
1804
  //#endregion
1800
1805
  //#region src/datalayer/providerConfigs.ts
1806
+ /**
1807
+ * Generate a unique slug for a provider config.
1808
+ * If the base slug already exists, appends -01, -02, etc.
1809
+ */
1810
+ async function generateUniqueSlug(db, baseSlug) {
1811
+ const existing = await db.selectFrom("provider_configs").select("slug").where("slug", "like", `${baseSlug}%`).execute();
1812
+ if (existing.length === 0) return baseSlug;
1813
+ const existingSlugs = new Set(existing.map((e) => e.slug));
1814
+ if (!existingSlugs.has(baseSlug)) return baseSlug;
1815
+ let counter = 1;
1816
+ while (counter < 100) {
1817
+ const candidateSlug = `${baseSlug}-${counter.toString().padStart(2, "0")}`;
1818
+ if (!existingSlugs.has(candidateSlug)) return candidateSlug;
1819
+ counter++;
1820
+ }
1821
+ return `${baseSlug}-${(0, node_crypto.randomUUID)().slice(0, 8)}`;
1822
+ }
1801
1823
  const createProviderConfig = require_db.zod_default.object({
1802
1824
  providerId: require_db.zod_default.string().min(1),
1825
+ slug: require_db.zod_default.string().nullable().optional(),
1803
1826
  name: require_db.zod_default.string().nullable().optional(),
1804
1827
  config: require_db.zod_default.record(require_db.zod_default.string(), require_db.zod_default.unknown()),
1805
1828
  enabled: require_db.zod_default.boolean().optional().default(true)
1806
1829
  });
1807
1830
  const updateProviderConfig = require_db.zod_default.object({
1808
1831
  id: require_db.zod_default.uuidv4(),
1832
+ slug: require_db.zod_default.string().nullable().optional(),
1809
1833
  name: require_db.zod_default.string().nullable().optional(),
1810
1834
  config: require_db.zod_default.record(require_db.zod_default.string(), require_db.zod_default.unknown()).optional(),
1811
1835
  enabled: require_db.zod_default.boolean().optional()
1812
1836
  });
1813
1837
  const getProviderConfigById = require_db.zod_default.object({ id: require_db.zod_default.uuidv4() });
1814
1838
  const getProviderConfigByProviderId = require_db.zod_default.object({ providerId: require_db.zod_default.string().min(1) });
1839
+ const getProviderConfigBySlug = require_db.zod_default.object({ slug: require_db.zod_default.string().min(1) });
1815
1840
  const deleteProviderConfig = require_db.zod_default.object({ id: require_db.zod_default.uuidv4() });
1816
1841
  const listProviderConfigs = require_db.zod_default.object({
1817
1842
  limit: require_db.zod_default.number().int().positive().optional(),
@@ -1822,10 +1847,12 @@ const createProviderConfigsDataLayer = (db) => {
1822
1847
  createProviderConfig: async (params) => {
1823
1848
  const value = await createProviderConfig.safeParseAsync(params);
1824
1849
  if (!value.success) throw new LLMOpsError(`Invalid parameters: ${value.error.message}`);
1825
- const { providerId, name, config, enabled } = value.data;
1850
+ const { providerId, slug, name, config, enabled } = value.data;
1851
+ const finalSlug = slug ?? await generateUniqueSlug(db, providerId);
1826
1852
  return db.insertInto("provider_configs").values({
1827
1853
  id: (0, node_crypto.randomUUID)(),
1828
1854
  providerId,
1855
+ slug: finalSlug,
1829
1856
  name: name ?? null,
1830
1857
  config: JSON.stringify(config),
1831
1858
  enabled,
@@ -1836,8 +1863,9 @@ const createProviderConfigsDataLayer = (db) => {
1836
1863
  updateProviderConfig: async (params) => {
1837
1864
  const value = await updateProviderConfig.safeParseAsync(params);
1838
1865
  if (!value.success) throw new LLMOpsError(`Invalid parameters: ${value.error.message}`);
1839
- const { id, name, config, enabled } = value.data;
1866
+ const { id, slug, name, config, enabled } = value.data;
1840
1867
  const updateData = { updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
1868
+ if (slug !== void 0) updateData.slug = slug;
1841
1869
  if (name !== void 0) updateData.name = name;
1842
1870
  if (config !== void 0) updateData.config = JSON.stringify(config);
1843
1871
  if (enabled !== void 0) updateData.enabled = enabled;
@@ -1855,6 +1883,12 @@ const createProviderConfigsDataLayer = (db) => {
1855
1883
  const { providerId } = value.data;
1856
1884
  return db.selectFrom("provider_configs").selectAll().where("providerId", "=", providerId).executeTakeFirst();
1857
1885
  },
1886
+ getProviderConfigBySlug: async (params) => {
1887
+ const value = await getProviderConfigBySlug.safeParseAsync(params);
1888
+ if (!value.success) throw new LLMOpsError(`Invalid parameters: ${value.error.message}`);
1889
+ const { slug } = value.data;
1890
+ return db.selectFrom("provider_configs").selectAll().where("slug", "=", slug).executeTakeFirst();
1891
+ },
1858
1892
  deleteProviderConfig: async (params) => {
1859
1893
  const value = await deleteProviderConfig.safeParseAsync(params);
1860
1894
  if (!value.success) throw new LLMOpsError(`Invalid parameters: ${value.error.message}`);
@@ -1874,17 +1908,23 @@ const createProviderConfigsDataLayer = (db) => {
1874
1908
  upsertProviderConfig: async (params) => {
1875
1909
  const value = await createProviderConfig.safeParseAsync(params);
1876
1910
  if (!value.success) throw new LLMOpsError(`Invalid parameters: ${value.error.message}`);
1877
- const { providerId, name, config, enabled } = value.data;
1911
+ const { providerId, slug, name, config, enabled } = value.data;
1878
1912
  const existing = await db.selectFrom("provider_configs").selectAll().where("providerId", "=", providerId).executeTakeFirst();
1879
- if (existing) return db.updateTable("provider_configs").set({
1880
- name: name ?? existing.name,
1881
- config: JSON.stringify(config),
1882
- enabled,
1883
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1884
- }).where("id", "=", existing.id).returningAll().executeTakeFirst();
1913
+ if (existing) {
1914
+ const finalSlug$1 = slug ?? existing.slug ?? await generateUniqueSlug(db, providerId);
1915
+ return db.updateTable("provider_configs").set({
1916
+ slug: finalSlug$1,
1917
+ name: name ?? existing.name,
1918
+ config: JSON.stringify(config),
1919
+ enabled,
1920
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1921
+ }).where("id", "=", existing.id).returningAll().executeTakeFirst();
1922
+ }
1923
+ const finalSlug = slug ?? await generateUniqueSlug(db, providerId);
1885
1924
  return db.insertInto("provider_configs").values({
1886
1925
  id: (0, node_crypto.randomUUID)(),
1887
1926
  providerId,
1927
+ slug: finalSlug,
1888
1928
  name: name ?? null,
1889
1929
  config: JSON.stringify(config),
1890
1930
  enabled,
@@ -2580,10 +2620,341 @@ function getDefaultPricingProvider() {
2580
2620
  return defaultProvider;
2581
2621
  }
2582
2622
 
2623
+ //#endregion
2624
+ //#region src/manifest/builder.ts
2625
+ const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2626
+ /**
2627
+ * Builds the gateway routing manifest from database
2628
+ */
2629
+ var ManifestBuilder = class {
2630
+ constructor(db) {
2631
+ this.db = db;
2632
+ }
2633
+ /**
2634
+ * Build the complete routing manifest from database
2635
+ */
2636
+ async build() {
2637
+ const [configs, environments, environmentSecrets, targetingRules, configVariants, variantVersions, providerConfigs] = await Promise.all([
2638
+ this.db.selectFrom("configs").selectAll().execute(),
2639
+ this.db.selectFrom("environments").selectAll().execute(),
2640
+ this.db.selectFrom("environment_secrets").selectAll().execute(),
2641
+ this.db.selectFrom("targeting_rules").where("enabled", "=", true).selectAll().execute(),
2642
+ this.db.selectFrom("config_variants").selectAll().execute(),
2643
+ this.db.selectFrom("variant_versions").selectAll().execute(),
2644
+ this.db.selectFrom("provider_configs").selectAll().execute()
2645
+ ]);
2646
+ const manifestConfigs = {};
2647
+ const configsBySlug = {};
2648
+ for (const config of configs) {
2649
+ manifestConfigs[config.id] = {
2650
+ id: config.id,
2651
+ slug: config.slug,
2652
+ name: config.name ?? null
2653
+ };
2654
+ configsBySlug[config.slug] = config.id;
2655
+ }
2656
+ const manifestEnvironments = {};
2657
+ const environmentsBySlug = {};
2658
+ for (const env of environments) {
2659
+ manifestEnvironments[env.id] = {
2660
+ id: env.id,
2661
+ slug: env.slug,
2662
+ name: env.name,
2663
+ isProd: env.isProd
2664
+ };
2665
+ environmentsBySlug[env.slug] = env.id;
2666
+ }
2667
+ const secretToEnvironment = {};
2668
+ for (const secret of environmentSecrets) secretToEnvironment[secret.keyValue] = secret.environmentId;
2669
+ const configVariantMap = new Map(configVariants.map((cv) => [cv.id, cv]));
2670
+ const providerConfigMap = new Map(providerConfigs.map((pc) => [pc.id, pc]));
2671
+ const versionsByVariant = /* @__PURE__ */ new Map();
2672
+ for (const vv of variantVersions) {
2673
+ const list = versionsByVariant.get(vv.variantId) || [];
2674
+ list.push(vv);
2675
+ versionsByVariant.set(vv.variantId, list);
2676
+ }
2677
+ for (const list of versionsByVariant.values()) list.sort((a, b) => b.version - a.version);
2678
+ const versionById = new Map(variantVersions.map((vv) => [vv.id, vv]));
2679
+ const resolveProvider = (provider) => {
2680
+ if (UUID_REGEX.test(provider)) {
2681
+ const pc = providerConfigMap.get(provider);
2682
+ if (pc) return {
2683
+ providerId: pc.providerId,
2684
+ providerConfigId: pc.id
2685
+ };
2686
+ }
2687
+ return {
2688
+ providerId: provider,
2689
+ providerConfigId: null
2690
+ };
2691
+ };
2692
+ const buildVersion = (vv) => {
2693
+ const { providerId, providerConfigId } = resolveProvider(vv.provider);
2694
+ const jsonData = typeof vv.jsonData === "string" ? JSON.parse(vv.jsonData) : vv.jsonData;
2695
+ return {
2696
+ id: vv.id,
2697
+ variantId: vv.variantId,
2698
+ version: vv.version,
2699
+ provider: providerId,
2700
+ providerConfigId,
2701
+ modelName: vv.modelName,
2702
+ jsonData
2703
+ };
2704
+ };
2705
+ const routingTable = {};
2706
+ for (const rule of targetingRules) {
2707
+ const configVariant = configVariantMap.get(rule.configVariantId);
2708
+ if (!configVariant) continue;
2709
+ const variantId = configVariant.variantId;
2710
+ let resolvedVersionData;
2711
+ if (rule.variantVersionId) resolvedVersionData = versionById.get(rule.variantVersionId);
2712
+ else resolvedVersionData = versionsByVariant.get(variantId)?.[0];
2713
+ if (!resolvedVersionData) continue;
2714
+ let conditions = null;
2715
+ if (rule.conditions) {
2716
+ const conditionsObj = typeof rule.conditions === "string" ? JSON.parse(rule.conditions) : rule.conditions;
2717
+ if (conditionsObj && Object.keys(conditionsObj).length > 0) conditions = conditionsObj;
2718
+ }
2719
+ const manifestRule = {
2720
+ id: rule.id,
2721
+ configVariantId: rule.configVariantId,
2722
+ variantVersionId: rule.variantVersionId,
2723
+ weight: rule.weight,
2724
+ priority: rule.priority,
2725
+ enabled: rule.enabled,
2726
+ conditions,
2727
+ resolvedVersion: buildVersion(resolvedVersionData)
2728
+ };
2729
+ if (!routingTable[rule.configId]) routingTable[rule.configId] = {};
2730
+ if (!routingTable[rule.configId][rule.environmentId]) routingTable[rule.configId][rule.environmentId] = [];
2731
+ routingTable[rule.configId][rule.environmentId].push(manifestRule);
2732
+ }
2733
+ for (const configRules of Object.values(routingTable)) for (const envRules of Object.values(configRules)) envRules.sort((a, b) => {
2734
+ if (b.priority !== a.priority) return b.priority - a.priority;
2735
+ return b.weight - a.weight;
2736
+ });
2737
+ return {
2738
+ version: Date.now(),
2739
+ builtAt: (/* @__PURE__ */ new Date()).toISOString(),
2740
+ configs: manifestConfigs,
2741
+ configsBySlug,
2742
+ environments: manifestEnvironments,
2743
+ environmentsBySlug,
2744
+ routingTable,
2745
+ secretToEnvironment
2746
+ };
2747
+ }
2748
+ };
2749
+
2750
+ //#endregion
2751
+ //#region src/manifest/service.ts
2752
+ const MANIFEST_CACHE_KEY = "manifest";
2753
+ const MANIFEST_NAMESPACE = "gateway";
2754
+ const DEFAULT_TTL_MS = 300 * 1e3;
2755
+ const log = require_db.logger.child({ module: "ManifestService" });
2756
+ var ManifestService = class {
2757
+ builder;
2758
+ constructor(cache, db, ttlMs = DEFAULT_TTL_MS) {
2759
+ this.cache = cache;
2760
+ this.ttlMs = ttlMs;
2761
+ this.builder = new ManifestBuilder(db);
2762
+ log.debug({ ttlMs }, "ManifestService initialized");
2763
+ }
2764
+ /**
2765
+ * Get the current manifest, building if necessary
2766
+ */
2767
+ async getManifest() {
2768
+ log.debug("Getting manifest from cache or building");
2769
+ const manifest = await this.cache.getOrSet(MANIFEST_CACHE_KEY, async () => {
2770
+ log.info("Building new manifest");
2771
+ const built = await this.builder.build();
2772
+ log.info({
2773
+ version: built.version,
2774
+ configCount: Object.keys(built.configs).length,
2775
+ environmentCount: Object.keys(built.environments).length
2776
+ }, "Manifest built successfully");
2777
+ return built;
2778
+ }, {
2779
+ namespace: MANIFEST_NAMESPACE,
2780
+ ttl: this.ttlMs
2781
+ });
2782
+ log.debug({ version: manifest.version }, "Manifest retrieved");
2783
+ return manifest;
2784
+ }
2785
+ /**
2786
+ * Force invalidate the manifest (called on mutations)
2787
+ */
2788
+ async invalidate() {
2789
+ log.info("Invalidating manifest cache");
2790
+ await this.cache.delete(MANIFEST_CACHE_KEY, MANIFEST_NAMESPACE);
2791
+ }
2792
+ /**
2793
+ * Invalidate and immediately rebuild (atomic refresh)
2794
+ */
2795
+ async refresh() {
2796
+ log.info("Refreshing manifest (invalidate + rebuild)");
2797
+ await this.invalidate();
2798
+ return this.getManifest();
2799
+ }
2800
+ /**
2801
+ * Get manifest version without fetching full manifest
2802
+ * Useful for checking if manifest is stale
2803
+ */
2804
+ async getVersion() {
2805
+ const version = (await this.cache.get(MANIFEST_CACHE_KEY, MANIFEST_NAMESPACE))?.version ?? null;
2806
+ log.debug({ version }, "Got manifest version");
2807
+ return version;
2808
+ }
2809
+ /**
2810
+ * Check if manifest exists in cache
2811
+ */
2812
+ async hasManifest() {
2813
+ const exists = await this.cache.has(MANIFEST_CACHE_KEY, MANIFEST_NAMESPACE);
2814
+ log.debug({ exists }, "Checked manifest existence");
2815
+ return exists;
2816
+ }
2817
+ };
2818
+
2819
+ //#endregion
2820
+ //#region src/manifest/router.ts
2821
+ /**
2822
+ * Router for evaluating the gateway manifest and selecting variants
2823
+ */
2824
+ var ManifestRouter = class {
2825
+ constructor(manifest) {
2826
+ this.manifest = manifest;
2827
+ }
2828
+ /**
2829
+ * Resolve a config identifier (UUID or slug) to config ID
2830
+ */
2831
+ resolveConfigId(configIdOrSlug) {
2832
+ if (this.manifest.configs[configIdOrSlug]) return configIdOrSlug;
2833
+ return this.manifest.configsBySlug[configIdOrSlug] ?? null;
2834
+ }
2835
+ /**
2836
+ * Resolve environment from secret value
2837
+ */
2838
+ resolveEnvironmentFromSecret(secretValue) {
2839
+ return this.manifest.secretToEnvironment[secretValue] ?? null;
2840
+ }
2841
+ /**
2842
+ * Get production environment ID
2843
+ */
2844
+ getProductionEnvironmentId() {
2845
+ for (const env of Object.values(this.manifest.environments)) if (env.isProd) return env.id;
2846
+ return null;
2847
+ }
2848
+ /**
2849
+ * Get environment by ID
2850
+ */
2851
+ getEnvironment(environmentId) {
2852
+ return this.manifest.environments[environmentId] ?? null;
2853
+ }
2854
+ /**
2855
+ * Get config by ID
2856
+ */
2857
+ getConfig(configId) {
2858
+ return this.manifest.configs[configId] ?? null;
2859
+ }
2860
+ /**
2861
+ * Route a request to the appropriate variant version (first match wins)
2862
+ */
2863
+ route(configIdOrSlug, environmentId, context = {}) {
2864
+ const configId = this.resolveConfigId(configIdOrSlug);
2865
+ if (!configId) return null;
2866
+ const rules = this.manifest.routingTable[configId]?.[environmentId];
2867
+ if (!rules || rules.length === 0) return null;
2868
+ const evalContext = {
2869
+ ...context,
2870
+ timestamp: context.timestamp ?? Date.now()
2871
+ };
2872
+ for (const rule of rules) {
2873
+ if (!rule.enabled) continue;
2874
+ if (rule.conditions) try {
2875
+ if (!json_logic_js.default.apply(rule.conditions, evalContext)) continue;
2876
+ } catch (error) {
2877
+ console.warn(`JSONLogic evaluation error for rule ${rule.id}:`, error);
2878
+ continue;
2879
+ }
2880
+ return {
2881
+ configId,
2882
+ environmentId,
2883
+ variantId: rule.resolvedVersion.variantId,
2884
+ version: rule.resolvedVersion,
2885
+ rule
2886
+ };
2887
+ }
2888
+ return null;
2889
+ }
2890
+ /**
2891
+ * Route with weighted random selection among matching rules of same priority
2892
+ */
2893
+ routeWithWeights(configIdOrSlug, environmentId, context = {}) {
2894
+ const configId = this.resolveConfigId(configIdOrSlug);
2895
+ if (!configId) return null;
2896
+ const rules = this.manifest.routingTable[configId]?.[environmentId];
2897
+ if (!rules || rules.length === 0) return null;
2898
+ const evalContext = {
2899
+ ...context,
2900
+ timestamp: context.timestamp ?? Date.now()
2901
+ };
2902
+ const rulesByPriority = /* @__PURE__ */ new Map();
2903
+ for (const rule$1 of rules) {
2904
+ if (!rule$1.enabled) continue;
2905
+ if (rule$1.conditions) try {
2906
+ if (!json_logic_js.default.apply(rule$1.conditions, evalContext)) continue;
2907
+ } catch {
2908
+ continue;
2909
+ }
2910
+ const list = rulesByPriority.get(rule$1.priority) || [];
2911
+ list.push(rule$1);
2912
+ rulesByPriority.set(rule$1.priority, list);
2913
+ }
2914
+ const priorities = Array.from(rulesByPriority.keys()).sort((a, b) => b - a);
2915
+ if (priorities.length === 0) return null;
2916
+ const topPriorityRules = rulesByPriority.get(priorities[0]);
2917
+ if (topPriorityRules.length === 1) {
2918
+ const rule$1 = topPriorityRules[0];
2919
+ return {
2920
+ configId,
2921
+ environmentId,
2922
+ variantId: rule$1.resolvedVersion.variantId,
2923
+ version: rule$1.resolvedVersion,
2924
+ rule: rule$1
2925
+ };
2926
+ }
2927
+ const totalWeight = topPriorityRules.reduce((sum, r) => sum + r.weight, 0);
2928
+ if (totalWeight === 0) return null;
2929
+ let random = Math.random() * totalWeight;
2930
+ for (const rule$1 of topPriorityRules) {
2931
+ random -= rule$1.weight;
2932
+ if (random <= 0) return {
2933
+ configId,
2934
+ environmentId,
2935
+ variantId: rule$1.resolvedVersion.variantId,
2936
+ version: rule$1.resolvedVersion,
2937
+ rule: rule$1
2938
+ };
2939
+ }
2940
+ const rule = topPriorityRules[0];
2941
+ return {
2942
+ configId,
2943
+ environmentId,
2944
+ variantId: rule.resolvedVersion.variantId,
2945
+ version: rule.resolvedVersion,
2946
+ rule
2947
+ };
2948
+ }
2949
+ };
2950
+
2583
2951
  //#endregion
2584
2952
  exports.CacheService = CacheService;
2585
2953
  exports.FileCacheBackend = FileCacheBackend;
2586
2954
  exports.MS = MS;
2955
+ exports.ManifestBuilder = ManifestBuilder;
2956
+ exports.ManifestRouter = ManifestRouter;
2957
+ exports.ManifestService = ManifestService;
2587
2958
  exports.MemoryCacheBackend = MemoryCacheBackend;
2588
2959
  exports.ModelsDevPricingProvider = ModelsDevPricingProvider;
2589
2960
  exports.SCHEMA_METADATA = require_db.SCHEMA_METADATA;