agent-shim 11.31.1 → 11.33.0

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/cli.cjs CHANGED
@@ -26987,7 +26987,7 @@ function isTimeZone(name) {
26987
26987
  return false;
26988
26988
  }
26989
26989
  }
26990
- var import_node_path4, CATEGORY_NAMES, OVERRIDABLE_CATEGORIES, CategoryMapSchema, DURATION_RE, DurationSchema, WhenConditionObjectSchema, WhenSchema, EntryValueSchema, ENTRY_KEY_RE, EntriesSchema, LaunchSchema, CREDENTIAL_TARGETS, PROVIDER_CREDENTIAL_TARGETS, CREDENTIAL_TARGET_VARS, ArgvSchema, CommandSourceOptions, EnvCredentialSourceSchema, FileCredentialSourceSchema, CommandCredentialSourceSchema, OpCredentialSourceSchema, KeychainCredentialSourceSchema, LiteralCredentialSourceSchema, CredentialSourceSchema, RemoteCredentialSourceSchema, CREDENTIAL_CACHE_STORES, CredentialCacheSchema, CredentialSchema, ProviderCredentialSchema, RESERVED_PROVIDER_ENV_KEYS, ProviderEnvSchema, PROVIDER_KINDS, ANTIGRAVITY_MODES, CLAUDE_TIERS, ANTIGRAVITY_EFFORTS, ANTIGRAVITY_DEFAULT_MODE, ANTIGRAVITY_DEFAULT_MODEL, ANTIGRAVITY_DEFAULT_TIER_MODELS, ANTIGRAVITY_DEFAULT_EFFORT, AntigravityModelTargetSchema, AntigravityProviderConfigSchema, CODEX_EFFORTS, CODEX_LOGINS, CODEX_DEFAULT_LOGIN, CODEX_DEFAULT_MODEL, CODEX_DEFAULT_TIER_MODELS, CODEX_DEFAULT_EFFORT, CodexProviderConfigSchema, ProviderRouteSchema, PickerModelSchema, PickerModelsSchema, ProviderCatalogueSchema, HttpProviderSchema, CodexProviderSchema, AntigravityProviderSchema, ProviderSchema, ConfigProfileSchema, POOL_SELECTOR_PREFIX, POOL_NAME_PATTERN, IDENTITY_NAME_PATTERN, PoolNameSchema, SELECTOR_RE, IdentitySelectorSchema, PoolMemberSchema, POOL_PREFERENCES, PoolPreferenceSchema, WHOLE_PERCENT_MAX, CompactAtUtilisationSchema, PoolSchema, WEEKDAYS, AnchorSchema, JOB_WINDOWS, JobTriggerSchema, JobTargetSchema, JobSchema, DirectoryRuleSchema, DirectoryRulesSchema, PortableConfigSchema, HEADROOM_MODES, HEADROOM_CCR_MODES, HEADROOM_ROLLOUT_CHANNELS, INTERCEPT_CHANNELS, READ_MATURATION_CHANNELS, HeadroomGlobalConfigObjectSchema, HeadroomGlobalConfigSchema, HEADROOM_DEFAULT_SOURCE, HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES, FRONTDOOR_DEFAULT_IDLE_SHUTDOWN_MINUTES, FrontDoorGlobalConfigSchema, UPDATE_MODES, UpdateGlobalConfigSchema, GlobalConfigSchema, IdentitySchema, CategoryClassificationSchema, CategoryClassificationOverlaySchema, SHIPPED_CATEGORY_DEFAULTS;
26990
+ var import_node_path4, CATEGORY_NAMES, OVERRIDABLE_CATEGORIES, CategoryMapSchema, DURATION_RE, DurationSchema, WhenConditionObjectSchema, WhenSchema, EntryValueSchema, ENTRY_KEY_RE, EntriesSchema, LaunchSchema, CREDENTIAL_TARGETS, PROVIDER_CREDENTIAL_TARGETS, CREDENTIAL_TARGET_VARS, ArgvSchema, CommandSourceOptions, EnvCredentialSourceSchema, FileCredentialSourceSchema, CommandCredentialSourceSchema, OpCredentialSourceSchema, KeychainCredentialSourceSchema, LiteralCredentialSourceSchema, CredentialSourceSchema, RemoteCredentialSourceSchema, CREDENTIAL_CACHE_STORES, CredentialCacheSchema, CredentialSchema, ProviderCredentialSchema, RESERVED_PROVIDER_ENV_KEYS, ProviderEnvSchema, PROVIDER_KINDS, ANTIGRAVITY_MODES, CLAUDE_TIERS, ANTIGRAVITY_EFFORTS, ANTIGRAVITY_DEFAULT_MODE, ANTIGRAVITY_DEFAULT_MODEL, ANTIGRAVITY_DEFAULT_TIER_MODELS, ANTIGRAVITY_DEFAULT_EFFORT, AntigravityModelTargetSchema, AntigravityProviderConfigSchema, CODEX_EFFORTS, CODEX_LOGINS, CODEX_DEFAULT_LOGIN, CODEX_DEFAULT_MODEL, CODEX_DEFAULT_TIER_MODELS, CODEX_DEFAULT_EFFORT, CodexProviderConfigSchema, ProviderRouteSchema, PickerModelSchema, PickerModelsSchema, ProviderCatalogueSchema, HttpProviderSchema, CodexProviderSchema, AntigravityProviderSchema, ProviderSchema, SELECTION_MODES, VirtualModelSchema, ModelPricesSchema, ModelsConfigSchema, ModelsLayerSchema, ConfigProfileSchema, POOL_SELECTOR_PREFIX, POOL_NAME_PATTERN, IDENTITY_NAME_PATTERN, PoolNameSchema, SELECTOR_RE, IdentitySelectorSchema, PoolMemberSchema, POOL_PREFERENCES, PoolPreferenceSchema, WHOLE_PERCENT_MAX, CompactAtUtilisationSchema, PoolSchema, WEEKDAYS, AnchorSchema, JOB_WINDOWS, JobTriggerSchema, JobTargetSchema, JobSchema, DirectoryRuleSchema, DirectoryRulesSchema, PortableConfigSchema, HEADROOM_MODES, HEADROOM_CCR_MODES, HEADROOM_ROLLOUT_CHANNELS, INTERCEPT_CHANNELS, READ_MATURATION_CHANNELS, HeadroomGlobalConfigObjectSchema, HeadroomGlobalConfigSchema, HEADROOM_DEFAULT_SOURCE, HEADROOM_DEFAULT_IDLE_SHUTDOWN_MINUTES, FRONTDOOR_DEFAULT_IDLE_SHUTDOWN_MINUTES, FrontDoorGlobalConfigSchema, UPDATE_MODES, UpdateGlobalConfigSchema, GlobalConfigSchema, IdentitySchema, CategoryClassificationSchema, CategoryClassificationOverlaySchema, SHIPPED_CATEGORY_DEFAULTS;
26991
26991
  var init_schema = __esm({
26992
26992
  "src/config/schema.ts"() {
26993
26993
  "use strict";
@@ -27216,13 +27216,54 @@ var init_schema = __esm({
27216
27216
  antigravity: AntigravityProviderConfigSchema.optional()
27217
27217
  });
27218
27218
  ProviderSchema = external_exports.discriminatedUnion("kind", [HttpProviderSchema, CodexProviderSchema, AntigravityProviderSchema]);
27219
+ SELECTION_MODES = ["ordered", "most-allowance", "soonest-reset", "spread", "adaptive", "lowest-latency", "highest-success", "cheapest"];
27220
+ VirtualModelSchema = external_exports.strictObject({
27221
+ /** How the virtual model chooses its member for a request. */
27222
+ mode: external_exports.enum(SELECTION_MODES),
27223
+ /** The members to choose among, in preference order where the mode reads order. Each names a target (`z/glm-5.3`), an account model (`acct:work/opus`), another virtual model, or a family (`family:<canonical>`). */
27224
+ members: external_exports.array(external_exports.string().min(1)).min(1)
27225
+ });
27226
+ ModelPricesSchema = external_exports.strictObject({
27227
+ input: external_exports.number().positive(),
27228
+ output: external_exports.number().positive()
27229
+ });
27230
+ ModelsConfigSchema = external_exports.strictObject({
27231
+ /** Virtual models, by name. */
27232
+ virtual: external_exports.record(external_exports.string().min(1), VirtualModelSchema).optional(),
27233
+ /** Which model ref each Claude tier (`fable`, `opus`, `sonnet`, `haiku`) points at: a concrete target, an account model, a virtual model, or a family. */
27234
+ tiers: external_exports.strictObject({
27235
+ fable: external_exports.string().min(1).optional(),
27236
+ opus: external_exports.string().min(1).optional(),
27237
+ sonnet: external_exports.string().min(1).optional(),
27238
+ haiku: external_exports.string().min(1).optional()
27239
+ }).optional(),
27240
+ /** Prices per model ref, for the `cheapest` mode. */
27241
+ prices: external_exports.record(external_exports.string().min(1), ModelPricesSchema).optional(),
27242
+ /** Model refs hidden from the picker and from routing, whatever else names them. */
27243
+ hide: external_exports.array(external_exports.string().min(1)).optional(),
27244
+ /** When set, the only model refs visible; everything else is hidden. */
27245
+ show: external_exports.array(external_exports.string().min(1)).optional()
27246
+ });
27247
+ ModelsLayerSchema = external_exports.strictObject({
27248
+ virtual: external_exports.record(external_exports.string().min(1), external_exports.union([VirtualModelSchema, external_exports.null()])).optional(),
27249
+ tiers: external_exports.strictObject({
27250
+ fable: external_exports.union([external_exports.string().min(1), external_exports.null()]).optional(),
27251
+ opus: external_exports.union([external_exports.string().min(1), external_exports.null()]).optional(),
27252
+ sonnet: external_exports.union([external_exports.string().min(1), external_exports.null()]).optional(),
27253
+ haiku: external_exports.union([external_exports.string().min(1), external_exports.null()]).optional()
27254
+ }).optional(),
27255
+ prices: external_exports.record(external_exports.string().min(1), external_exports.union([ModelPricesSchema, external_exports.null()])).optional(),
27256
+ hide: external_exports.array(external_exports.string().min(1)).optional(),
27257
+ show: external_exports.array(external_exports.string().min(1)).optional()
27258
+ });
27219
27259
  ConfigProfileSchema = external_exports.strictObject({
27220
27260
  $schema: external_exports.string().optional(),
27221
27261
  description: external_exports.string().optional(),
27222
27262
  extends: external_exports.array(external_exports.string().min(1)).optional(),
27223
27263
  categories: CategoryMapSchema.optional(),
27224
27264
  entries: EntriesSchema.optional(),
27225
- launch: LaunchSchema.optional()
27265
+ launch: LaunchSchema.optional(),
27266
+ models: ModelsLayerSchema.optional()
27226
27267
  });
27227
27268
  POOL_SELECTOR_PREFIX = "pool:";
27228
27269
  POOL_NAME_PATTERN = "[A-Za-z0-9][A-Za-z0-9._-]*";
@@ -27333,6 +27374,7 @@ var init_schema = __esm({
27333
27374
  frontdoor: FrontDoorGlobalConfigSchema.optional(),
27334
27375
  update: UpdateGlobalConfigSchema.optional(),
27335
27376
  pools: external_exports.record(PoolNameSchema, PoolSchema).optional(),
27377
+ models: ModelsConfigSchema.optional(),
27336
27378
  jobs: external_exports.record(PoolNameSchema, JobSchema).optional()
27337
27379
  });
27338
27380
  IdentitySchema = external_exports.strictObject({
@@ -31833,7 +31875,8 @@ function profileLayers(rootName, load, startId) {
31833
31875
  ...source.profile.categories === void 0 ? {} : { categories: source.profile.categories },
31834
31876
  ...source.profile.entries === void 0 ? {} : { entries: source.profile.entries },
31835
31877
  ...source.entryOrder === void 0 ? {} : { entryOrder: source.entryOrder },
31836
- ...source.profile.launch === void 0 ? {} : { launch: source.profile.launch }
31878
+ ...source.profile.launch === void 0 ? {} : { launch: source.profile.launch },
31879
+ ...source.profile.models === void 0 ? {} : { models: source.profile.models }
31837
31880
  });
31838
31881
  nextId += 1;
31839
31882
  }
@@ -31921,7 +31964,8 @@ function assembleCascade(input2) {
31921
31964
  ...source.config.categories === void 0 ? {} : { categories: source.config.categories },
31922
31965
  ...source.config.entries === void 0 ? {} : { entries: source.config.entries },
31923
31966
  ...source.entryOrder === void 0 ? {} : { entryOrder: source.entryOrder },
31924
- ...source.config.launch === void 0 ? {} : { launch: source.config.launch }
31967
+ ...source.config.launch === void 0 ? {} : { launch: source.config.launch },
31968
+ ...source.config.models === void 0 ? {} : { models: source.config.models }
31925
31969
  });
31926
31970
  nextId += 1;
31927
31971
  }
@@ -32539,6 +32583,7 @@ function flattenLayers(layers, options) {
32539
32583
  const rules = /* @__PURE__ */ new Map();
32540
32584
  const launch = {};
32541
32585
  const diagnostics = [];
32586
+ let models;
32542
32587
  for (const layer of layers) {
32543
32588
  if (layer.categories !== void 0) {
32544
32589
  for (const [name, value2] of Object.entries(layer.categories)) {
@@ -32577,6 +32622,9 @@ function flattenLayers(layers, options) {
32577
32622
  launch.explain = layer.launch.explain;
32578
32623
  }
32579
32624
  }
32625
+ if (layer.models !== void 0) {
32626
+ models = mergeModels(models, layer.models);
32627
+ }
32580
32628
  if (layer.entries === void 0) {
32581
32629
  continue;
32582
32630
  }
@@ -32639,7 +32687,7 @@ function flattenLayers(layers, options) {
32639
32687
  rules.set(pattern, rule);
32640
32688
  }
32641
32689
  }
32642
- return { categories, rules, launch, diagnostics };
32690
+ return { categories, rules, launch, ...models === void 0 ? {} : { models }, diagnostics };
32643
32691
  }
32644
32692
  function orderedKeys(layer) {
32645
32693
  const present = new Set(Object.keys(layer.entries ?? {}));
@@ -32664,6 +32712,67 @@ function matchingRules(flattened, relPath) {
32664
32712
  }
32665
32713
  return matches.sort((a10, b) => compareSpecificity(b, a10));
32666
32714
  }
32715
+ function mergeModels(current, layer) {
32716
+ const pieces = { ...current ?? {} };
32717
+ if (layer.virtual !== void 0) {
32718
+ const virtual = {};
32719
+ for (const [name, definition] of Object.entries(current?.virtual ?? {})) {
32720
+ if (layer.virtual[name] === void 0) {
32721
+ virtual[name] = definition;
32722
+ }
32723
+ }
32724
+ for (const [name, definition] of Object.entries(layer.virtual)) {
32725
+ if (definition !== null) {
32726
+ virtual[name] = definition;
32727
+ }
32728
+ }
32729
+ pieces.virtual = virtual;
32730
+ }
32731
+ if (layer.tiers !== void 0) {
32732
+ const tiers = {};
32733
+ for (const tier of ["fable", "opus", "sonnet", "haiku"]) {
32734
+ const ref = layer.tiers[tier];
32735
+ const inherited = current?.tiers?.[tier];
32736
+ if (ref !== null && ref !== void 0) {
32737
+ tiers[tier] = ref;
32738
+ } else if (ref === void 0 && inherited !== void 0) {
32739
+ tiers[tier] = inherited;
32740
+ }
32741
+ }
32742
+ pieces.tiers = tiers;
32743
+ }
32744
+ if (layer.prices !== void 0) {
32745
+ const priced = {};
32746
+ for (const [ref, prices] of Object.entries(current?.prices ?? {})) {
32747
+ if (layer.prices[ref] === void 0) {
32748
+ priced[ref] = prices;
32749
+ }
32750
+ }
32751
+ for (const [ref, prices] of Object.entries(layer.prices)) {
32752
+ if (prices !== null) {
32753
+ priced[ref] = prices;
32754
+ }
32755
+ }
32756
+ pieces.prices = priced;
32757
+ }
32758
+ if (layer.hide !== void 0) {
32759
+ pieces.hide = layer.hide;
32760
+ }
32761
+ if (layer.show !== void 0) {
32762
+ pieces.show = layer.show;
32763
+ }
32764
+ const merged = modelsOf(pieces);
32765
+ return Object.keys(merged).length === 0 ? void 0 : merged;
32766
+ }
32767
+ function modelsOf(pieces) {
32768
+ return {
32769
+ ...pieces.virtual === void 0 || Object.keys(pieces.virtual).length === 0 ? {} : { virtual: pieces.virtual },
32770
+ ...pieces.tiers === void 0 || Object.keys(pieces.tiers).length === 0 ? {} : { tiers: pieces.tiers },
32771
+ ...pieces.prices === void 0 || Object.keys(pieces.prices).length === 0 ? {} : { prices: pieces.prices },
32772
+ ...pieces.hide === void 0 || pieces.hide.length === 0 ? {} : { hide: [...pieces.hide] },
32773
+ ...pieces.show === void 0 || pieces.show.length === 0 ? {} : { show: [...pieces.show] }
32774
+ };
32775
+ }
32667
32776
  var init_flatten = __esm({
32668
32777
  "src/resolve/flatten.ts"() {
32669
32778
  "use strict";
@@ -34323,7 +34432,7 @@ var init_package = __esm({
34323
34432
  "package.json"() {
34324
34433
  package_default = {
34325
34434
  name: "agent-shim",
34326
- version: "11.31.1",
34435
+ version: "11.33.0",
34327
34436
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
34328
34437
  license: "MIT",
34329
34438
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -63767,6 +63876,158 @@ var init_launchReport = __esm({
63767
63876
  }
63768
63877
  });
63769
63878
 
63879
+ // src/selection/engine.ts
63880
+ function compareMaybe(left, right, preferHigh) {
63881
+ if (left === void 0 && right === void 0) {
63882
+ return 0;
63883
+ }
63884
+ if (left === void 0) {
63885
+ return 1;
63886
+ }
63887
+ if (right === void 0) {
63888
+ return -1;
63889
+ }
63890
+ return preferHigh ? right - left : left - right;
63891
+ }
63892
+ function by(comparator, candidates) {
63893
+ return [...candidates].sort((left, right) => comparator(left, right) || left.order - right.order || (left.ref < right.ref ? -1 : left.ref > right.ref ? 1 : 0));
63894
+ }
63895
+ function selectOrdered(candidates) {
63896
+ const reasons = candidates.map((candidate) => `${candidate.ref}${availability(candidate)}`);
63897
+ const unspent = candidates.filter((candidate) => candidate.available);
63898
+ const current = unspent.find((candidate) => candidate.isCurrent);
63899
+ if (current !== void 0) {
63900
+ return { ref: current.ref, reasons: [...reasons, `${current.ref} is the model this session is already on and still has quota`] };
63901
+ }
63902
+ const first = by((left, right) => left.order - right.order, candidates)[0];
63903
+ if (first?.available === true) {
63904
+ return { ref: first.ref, reasons: [...reasons, `${first.ref} is the first member with quota`] };
63905
+ }
63906
+ const byPressure = by((left, right) => compareMaybe(left.pressure, right.pressure, true), unspent);
63907
+ const top = byPressure[0];
63908
+ if (top !== void 0) {
63909
+ return { ref: top.ref, reasons: [...reasons, `${top.ref} carries the most allowance its reset would waste`] };
63910
+ }
63911
+ const byReset = by((left, right) => compareMaybe(left.hoursToReset, right.hoursToReset, false), candidates);
63912
+ return { ref: byReset[0]?.ref, reasons: [...reasons, "every member is spent; serving from the one whose window lifts soonest"] };
63913
+ }
63914
+ function selectRanked(candidates, comparator, what, why) {
63915
+ const ordered = selectOrdered(candidates);
63916
+ const available = candidates.filter((candidate) => candidate.available);
63917
+ if (available.length === 0) {
63918
+ return ordered;
63919
+ }
63920
+ const ranked = by(comparator, available);
63921
+ const best = ranked[0];
63922
+ if (best === void 0) {
63923
+ return ordered;
63924
+ }
63925
+ const current = available.find((candidate) => candidate.isCurrent);
63926
+ const chosen = current !== void 0 && (comparator(current, best) === 0 || best.isCurrent) ? current : best;
63927
+ if (chosen.isCurrent || current === void 0) {
63928
+ return { ref: chosen.ref, reasons: [...ordered.reasons, `${chosen.ref} ${what}`] };
63929
+ }
63930
+ return { ref: best.ref, reasons: [...ordered.reasons, `${best.ref} ${what}; the switch from the current member is worth re-sending the conversation because ${why}`] };
63931
+ }
63932
+ function selectMember(mode, candidates, options = {}) {
63933
+ const plain = candidates.map((entry) => entry.candidate);
63934
+ switch (mode) {
63935
+ case "ordered":
63936
+ return selectOrdered(plain);
63937
+ case "most-allowance":
63938
+ return selectRanked(plain, (left, right) => compareMaybe(left.remainingAllowance, right.remainingAllowance, true), "holds the most remaining allowance", "its allowance is the largest");
63939
+ case "soonest-reset":
63940
+ return selectRanked(plain, (left, right) => compareMaybe(left.hoursToReset, right.hoursToReset, false), "resets soonest, so its allowance is the most use-it-or-lose-it", "its reset is the soonest");
63941
+ case "lowest-latency":
63942
+ return selectRanked(plain, (left, right) => compareMaybe(left.latencyMs, right.latencyMs, false), "has answered fastest of late", "its latency is the lowest observed");
63943
+ case "highest-success":
63944
+ return selectRanked(plain, (left, right) => compareMaybe(left.successRate, right.successRate, true), "has succeeded most reliably of late", "its success rate is the highest observed");
63945
+ case "cheapest":
63946
+ return selectRanked(plain, (left, right) => compareMaybe(left.pricePerMTok, right.pricePerMTok, false), "is the cheapest for the tokens this session sends", "its blended price is the lowest");
63947
+ case "spread": {
63948
+ const ordered = selectOrdered(plain);
63949
+ const available = plain.filter((candidate) => candidate.available);
63950
+ if (available.length === 0) {
63951
+ return ordered;
63952
+ }
63953
+ const rotation = options.rotation ?? 0;
63954
+ const orderedByList = by((left, right) => left.order - right.order, available);
63955
+ const chosen = orderedByList[rotation % orderedByList.length];
63956
+ return chosen === void 0 ? ordered : { ref: chosen.ref, reasons: [...ordered.reasons, `${chosen.ref} is turn ${String(rotation % orderedByList.length + 1)} of the spread across the members with quota`] };
63957
+ }
63958
+ case "adaptive":
63959
+ return selectAdaptive(candidates, options.needs);
63960
+ }
63961
+ return selectOrdered(plain);
63962
+ }
63963
+ function selectAdaptive(candidates, needs) {
63964
+ const plain = candidates.map((entry) => entry.candidate);
63965
+ const ruledOut = candidates.map((entry) => {
63966
+ const { candidate, capabilities } = entry;
63967
+ if (needs?.hasImage === true && !capabilities.vision) {
63968
+ return `${candidate.ref} does not accept images`;
63969
+ }
63970
+ if (needs?.hasTools === true && !capabilities.tools) {
63971
+ return `${candidate.ref} does not accept tools`;
63972
+ }
63973
+ if (needs?.thinking === true && !capabilities.thinking) {
63974
+ return `${candidate.ref} does not think`;
63975
+ }
63976
+ if (candidate.available && !candidate.feasible) {
63977
+ return `${candidate.ref} would run dry before its window resets`;
63978
+ }
63979
+ if (candidate.successRate !== void 0 && candidate.successRate < ADAPTIVE_HEALTH_FLOOR) {
63980
+ return `${candidate.ref} has been failing`;
63981
+ }
63982
+ return void 0;
63983
+ }).filter((line) => line !== void 0);
63984
+ const standing = candidates.filter((entry) => {
63985
+ const { candidate, capabilities } = entry;
63986
+ if (!candidate.available) {
63987
+ return false;
63988
+ }
63989
+ if (needs?.hasImage === true && !capabilities.vision) {
63990
+ return false;
63991
+ }
63992
+ if (needs?.hasTools === true && !capabilities.tools) {
63993
+ return false;
63994
+ }
63995
+ if (needs?.thinking === true && !capabilities.thinking) {
63996
+ return false;
63997
+ }
63998
+ if (!candidate.feasible) {
63999
+ return false;
64000
+ }
64001
+ return !(candidate.successRate !== void 0 && candidate.successRate < ADAPTIVE_HEALTH_FLOOR);
64002
+ });
64003
+ const reasons = [...ruledOut];
64004
+ if (standing.length === 0) {
64005
+ const fallback = selectOrdered(plain);
64006
+ return { ref: fallback.ref, reasons: [...reasons, "nothing stands: serving by order"] };
64007
+ }
64008
+ const current = standing.find((entry) => entry.candidate.isCurrent);
64009
+ if (current !== void 0) {
64010
+ return { ref: current.candidate.ref, reasons: [...reasons, `${current.candidate.ref} stands and is the model this session is already on, so the conversation is not re-sent`] };
64011
+ }
64012
+ const ranked = by(
64013
+ (left, right) => compareMaybe(left.pressure, right.pressure, true) || compareMaybe(left.hoursToReset, right.hoursToReset, false) || compareMaybe(left.successRate, right.successRate, true),
64014
+ standing.map((entry) => entry.candidate)
64015
+ );
64016
+ const best = ranked[0];
64017
+ if (best === void 0) {
64018
+ return { ref: void 0, reasons };
64019
+ }
64020
+ return { ref: best.ref, reasons: [...reasons, `${best.ref} stands and carries the most allowance its reset would waste`] };
64021
+ }
64022
+ var ADAPTIVE_HEALTH_FLOOR, availability;
64023
+ var init_engine = __esm({
64024
+ "src/selection/engine.ts"() {
64025
+ "use strict";
64026
+ ADAPTIVE_HEALTH_FLOOR = 0.5;
64027
+ availability = (candidate) => candidate.available ? "" : "quota spent";
64028
+ }
64029
+ });
64030
+
63770
64031
  // src/antigravity/cloudUpstream.ts
63771
64032
  function isCcpaEndpoint(endpoint) {
63772
64033
  return endpoint.includes("cloudcode-pa.googleapis.com");
@@ -64309,32 +64570,24 @@ function chooseCandidate(candidates, routing) {
64309
64570
  if (routing === void 0 || candidates.length === 1) {
64310
64571
  return first;
64311
64572
  }
64312
- if (routing.previous !== void 0 && candidates.includes(routing.previous) && antigravityQuotaExhaustion(routing.quota, routing.previous, routing.nowMs) === void 0) {
64313
- return routing.previous;
64314
- }
64315
- const unspent = candidates.filter((model) => antigravityQuotaExhaustion(routing.quota, model, routing.nowMs) === void 0);
64316
- if (unspent[0] === first) {
64317
- return first;
64318
- }
64319
- const neutral = 1;
64320
- let best;
64321
- for (const model of unspent) {
64322
- const pressure = antigravityQuotaPressure(routing.quota, model) ?? neutral;
64323
- if (best === void 0 || pressure > best.pressure) {
64324
- best = { model, pressure };
64325
- }
64326
- }
64327
- if (best !== void 0) {
64328
- return best.model;
64329
- }
64330
- let soonest;
64331
- for (const model of candidates) {
64332
- const exhaustion = antigravityQuotaExhaustion(routing.quota, model, routing.nowMs);
64333
- if (exhaustion !== void 0 && (soonest === void 0 || exhaustion.resetSec < soonest.resetSec)) {
64334
- soonest = { model, resetSec: exhaustion.resetSec };
64335
- }
64336
- }
64337
- return soonest?.model ?? first;
64573
+ const exhaustionOf = (model) => antigravityQuotaExhaustion(routing.quota, model, routing.nowMs);
64574
+ const evaluated = candidates.map((model, index) => {
64575
+ const exhaustion = exhaustionOf(model);
64576
+ return {
64577
+ candidate: {
64578
+ ref: model,
64579
+ order: index,
64580
+ available: exhaustion === void 0,
64581
+ // A quota the map does not measure competes at the neutral pressure the old in-place ranking gave it, not as an unknown that always loses.
64582
+ pressure: antigravityQuotaPressure(routing.quota, model) ?? NEUTRAL_PRESSURE,
64583
+ hoursToReset: exhaustion === void 0 ? void 0 : exhaustion.resetSec / SECONDS_PER_HOUR2,
64584
+ feasible: true,
64585
+ isCurrent: routing.previous === model
64586
+ },
64587
+ capabilities: { vision: true, tools: true, thinking: true }
64588
+ };
64589
+ });
64590
+ return selectMember("ordered", evaluated).ref ?? first;
64338
64591
  }
64339
64592
  function mapEffort(request7, config2) {
64340
64593
  const requested = request7.output_config?.effort;
@@ -64526,15 +64779,18 @@ function translateRequest(request7, config2, routing) {
64526
64779
  toolNames
64527
64780
  };
64528
64781
  }
64529
- var import_node_crypto16, AUTO_ALIAS, CONTEXT_MARKER_1M, BACKEND_FAMILY_PREFIXES, BACKEND_CLAUDE_NAME, EFFORT_TO_BUDGET, BILLING_HEADER_LINE, ANTIGRAVITY_TOOL_NAME_LIMIT, TOOL_NAME_HASH_CHARS, NON_TEXT_TOOL_RESULT, EMPTY_SCHEMA, EFFORT_SUFFIXES;
64782
+ var import_node_crypto16, SECONDS_PER_HOUR2, NEUTRAL_PRESSURE, AUTO_ALIAS, CONTEXT_MARKER_1M, BACKEND_FAMILY_PREFIXES, BACKEND_CLAUDE_NAME, EFFORT_TO_BUDGET, BILLING_HEADER_LINE, ANTIGRAVITY_TOOL_NAME_LIMIT, TOOL_NAME_HASH_CHARS, NON_TEXT_TOOL_RESULT, EMPTY_SCHEMA, EFFORT_SUFFIXES;
64530
64783
  var init_translate = __esm({
64531
64784
  "src/antigravity/translate.ts"() {
64532
64785
  "use strict";
64533
64786
  import_node_crypto16 = require("node:crypto");
64787
+ init_engine();
64534
64788
  init_quota();
64535
64789
  init_signatures();
64536
64790
  init_schema();
64537
64791
  init_anthropic();
64792
+ SECONDS_PER_HOUR2 = 3600;
64793
+ NEUTRAL_PRESSURE = 1;
64538
64794
  AUTO_ALIAS = "auto";
64539
64795
  CONTEXT_MARKER_1M = "[1m]";
64540
64796
  BACKEND_FAMILY_PREFIXES = ["gemini-", "antigravity-", "gpt-oss-"];
@@ -64812,7 +65068,7 @@ async function fetchCatalogue(params) {
64812
65068
  }
64813
65069
  throw new CatalogueFetchError(`no catalogue from ${outcomes.join("; ")}`);
64814
65070
  }
64815
- var import_node_path42, import_picomatch3, DEFAULT_CANDIDATE_URLS, MS_PER_SECOND8, SECONDS_PER_HOUR2, HOURS_PER_DAY4, MS_PER_HOUR3, HOURS_BETWEEN_RETRIES, HTTP_OK, HTTP_MULTIPLE_CHOICES, CATALOGUE_MAX_AGE_MS, CATALOGUE_RETRY_MS, CATALOGUE_REQUEST_SECONDS, CATALOGUE_REQUEST_TIMEOUT_MS, CATALOGUE_REFRESH_TIMEOUT_MS, CatalogueModelSchema, CatalogueCacheSchema, CatalogueFetchError;
65071
+ var import_node_path42, import_picomatch3, DEFAULT_CANDIDATE_URLS, MS_PER_SECOND8, SECONDS_PER_HOUR3, HOURS_PER_DAY4, MS_PER_HOUR3, HOURS_BETWEEN_RETRIES, HTTP_OK, HTTP_MULTIPLE_CHOICES, CATALOGUE_MAX_AGE_MS, CATALOGUE_RETRY_MS, CATALOGUE_REQUEST_SECONDS, CATALOGUE_REQUEST_TIMEOUT_MS, CATALOGUE_REFRESH_TIMEOUT_MS, CatalogueModelSchema, CatalogueCacheSchema, CatalogueFetchError;
64816
65072
  var init_providerCatalogue = __esm({
64817
65073
  "src/providerCatalogue.ts"() {
64818
65074
  "use strict";
@@ -64821,9 +65077,9 @@ var init_providerCatalogue = __esm({
64821
65077
  init_zod();
64822
65078
  DEFAULT_CANDIDATE_URLS = 2;
64823
65079
  MS_PER_SECOND8 = 1e3;
64824
- SECONDS_PER_HOUR2 = 3600;
65080
+ SECONDS_PER_HOUR3 = 3600;
64825
65081
  HOURS_PER_DAY4 = 24;
64826
- MS_PER_HOUR3 = SECONDS_PER_HOUR2 * MS_PER_SECOND8;
65082
+ MS_PER_HOUR3 = SECONDS_PER_HOUR3 * MS_PER_SECOND8;
64827
65083
  HOURS_BETWEEN_RETRIES = 1;
64828
65084
  HTTP_OK = 200;
64829
65085
  HTTP_MULTIPLE_CHOICES = 300;
@@ -65823,7 +66079,7 @@ function quotaFreshnessMs(quota) {
65823
66079
  const lengths = quota.windows.flatMap((window) => window.periodMs === void 0 ? [] : [window.periodMs]);
65824
66080
  return lengths.length === 0 ? Number.POSITIVE_INFINITY : Math.min(...lengths) / PERCENT3;
65825
66081
  }
65826
- var ProviderQuotaError, MS_PER_SECOND9, SECONDS_PER_HOUR3, HOURS_PER_DAY5, DAYS_PER_MONTH, PERCENT3, HTTP_OK2, ZAI_SOURCE, ZAI_HOST, ZAI_QUOTA_URL, ZAI_UNIT_HOURS, ZAI_UNIT_MONTHS, ZAI_UNIT_MS, ZAI_MEASURES, ZaiLimitSchema, ZaiResponseSchema, zaiQuotaAdapter, OPENROUTER_SOURCE, OPENROUTER_HOST, OPENROUTER_KEY_URL, OPENROUTER_CREDITS_URL, HTTP_FORBIDDEN, MS_PER_DAY2, OpenRouterKeySchema, OpenRouterCreditsSchema, openRouterQuotaAdapter, ANTIGRAVITY_SOURCE, ANTIGRAVITY_HOST, ANTIGRAVITY_QUOTA_URL, ANTIGRAVITY_USER_URL, GOOGLE_TOKENINFO_URL, FIVE_HOURS2, DAYS_PER_WEEK2, FIVE_HOURS_MS, WEEK_MS, AntigravityBucketSchema, AntigravitySummarySchema, GoogleTokenInfoSchema, AntigravityUserSchema, ANTIGRAVITY_WINDOW_MS, antigravityQuotaAdapter, PROVIDER_QUOTA_ADAPTERS;
66082
+ var ProviderQuotaError, MS_PER_SECOND9, SECONDS_PER_HOUR4, HOURS_PER_DAY5, DAYS_PER_MONTH, PERCENT3, HTTP_OK2, ZAI_SOURCE, ZAI_HOST, ZAI_QUOTA_URL, ZAI_UNIT_HOURS, ZAI_UNIT_MONTHS, ZAI_UNIT_MS, ZAI_MEASURES, ZaiLimitSchema, ZaiResponseSchema, zaiQuotaAdapter, OPENROUTER_SOURCE, OPENROUTER_HOST, OPENROUTER_KEY_URL, OPENROUTER_CREDITS_URL, HTTP_FORBIDDEN, MS_PER_DAY2, OpenRouterKeySchema, OpenRouterCreditsSchema, openRouterQuotaAdapter, ANTIGRAVITY_SOURCE, ANTIGRAVITY_HOST, ANTIGRAVITY_QUOTA_URL, ANTIGRAVITY_USER_URL, GOOGLE_TOKENINFO_URL, FIVE_HOURS2, DAYS_PER_WEEK2, FIVE_HOURS_MS, WEEK_MS, AntigravityBucketSchema, AntigravitySummarySchema, GoogleTokenInfoSchema, AntigravityUserSchema, ANTIGRAVITY_WINDOW_MS, antigravityQuotaAdapter, PROVIDER_QUOTA_ADAPTERS;
65827
66083
  var init_providerQuota = __esm({
65828
66084
  "src/usage/providerQuota.ts"() {
65829
66085
  "use strict";
@@ -65837,7 +66093,7 @@ var init_providerQuota = __esm({
65837
66093
  }
65838
66094
  };
65839
66095
  MS_PER_SECOND9 = 1e3;
65840
- SECONDS_PER_HOUR3 = 3600;
66096
+ SECONDS_PER_HOUR4 = 3600;
65841
66097
  HOURS_PER_DAY5 = 24;
65842
66098
  DAYS_PER_MONTH = 30;
65843
66099
  PERCENT3 = 100;
@@ -65848,8 +66104,8 @@ var init_providerQuota = __esm({
65848
66104
  ZAI_UNIT_HOURS = 3;
65849
66105
  ZAI_UNIT_MONTHS = 5;
65850
66106
  ZAI_UNIT_MS = /* @__PURE__ */ new Map([
65851
- [ZAI_UNIT_HOURS, SECONDS_PER_HOUR3 * MS_PER_SECOND9],
65852
- [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY5 * SECONDS_PER_HOUR3 * MS_PER_SECOND9]
66107
+ [ZAI_UNIT_HOURS, SECONDS_PER_HOUR4 * MS_PER_SECOND9],
66108
+ [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY5 * SECONDS_PER_HOUR4 * MS_PER_SECOND9]
65853
66109
  ]);
65854
66110
  ZAI_MEASURES = { TOKENS_LIMIT: "tokens", TIME_LIMIT: "tool-calls" };
65855
66111
  ZaiLimitSchema = external_exports.object({
@@ -65901,7 +66157,7 @@ var init_providerQuota = __esm({
65901
66157
  OPENROUTER_KEY_URL = `https://${OPENROUTER_HOST}/api/v1/key`;
65902
66158
  OPENROUTER_CREDITS_URL = `https://${OPENROUTER_HOST}/api/v1/credits`;
65903
66159
  HTTP_FORBIDDEN = 403;
65904
- MS_PER_DAY2 = HOURS_PER_DAY5 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
66160
+ MS_PER_DAY2 = HOURS_PER_DAY5 * SECONDS_PER_HOUR4 * MS_PER_SECOND9;
65905
66161
  OpenRouterKeySchema = external_exports.object({
65906
66162
  data: external_exports.object({
65907
66163
  limit: external_exports.number().nonnegative().nullable(),
@@ -65949,8 +66205,8 @@ var init_providerQuota = __esm({
65949
66205
  GOOGLE_TOKENINFO_URL = "https://oauth2.googleapis.com/tokeninfo";
65950
66206
  FIVE_HOURS2 = 5;
65951
66207
  DAYS_PER_WEEK2 = 7;
65952
- FIVE_HOURS_MS = FIVE_HOURS2 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
65953
- WEEK_MS = DAYS_PER_WEEK2 * HOURS_PER_DAY5 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
66208
+ FIVE_HOURS_MS = FIVE_HOURS2 * SECONDS_PER_HOUR4 * MS_PER_SECOND9;
66209
+ WEEK_MS = DAYS_PER_WEEK2 * HOURS_PER_DAY5 * SECONDS_PER_HOUR4 * MS_PER_SECOND9;
65954
66210
  AntigravityBucketSchema = external_exports.object({
65955
66211
  bucketId: external_exports.string(),
65956
66212
  remainingFraction: external_exports.number().optional(),
@@ -67064,7 +67320,7 @@ function Lp(e14) {
67064
67320
  function my(e14) {
67065
67321
  return e14.replace(/[\u200c-\u200f\u202a-\u202e\u206a-\u206f\ufeff]/g, "").toUpperCase().toLowerCase();
67066
67322
  }
67067
- function by(e14, t10) {
67323
+ function by2(e14, t10) {
67068
67324
  if (Qo(e14)) return true;
67069
67325
  if (Yn(e14)) {
67070
67326
  let n10 = hc(e14);
@@ -67672,7 +67928,7 @@ function ri(e14) {
67672
67928
  return po(e14);
67673
67929
  }
67674
67930
  function Vp(e14, t10) {
67675
- return t10 !== void 0 && t10.some((n10) => po(n10) && !by(e14, n10) && (Xy(e14, n10) || Yn(e14)));
67931
+ return t10 !== void 0 && t10.some((n10) => po(n10) && !by2(e14, n10) && (Xy(e14, n10) || Yn(e14)));
67676
67932
  }
67677
67933
  function Ck(e14, t10) {
67678
67934
  return t10 !== void 0 && t10.some((n10) => po(n10) && Xy(n10, e14));
@@ -67682,7 +67938,7 @@ function Xy(e14, t10) {
67682
67938
  return r10 === o || r10.startsWith(o === "/" ? o : o + "/");
67683
67939
  }
67684
67940
  function Zp(e14, t10) {
67685
- return t10 === void 0 || t10.every((n10) => by(e14, n10));
67941
+ return t10 === void 0 || t10.every((n10) => by2(e14, n10));
67686
67942
  }
67687
67943
  function vk(e14, t10) {
67688
67944
  return t10 === void 0 || t10.every((n10) => zO(e14, n10));
@@ -118864,6 +119120,162 @@ init_credentialCache();
118864
119120
  init_realCredentialCache();
118865
119121
  init_source();
118866
119122
 
119123
+ // src/modelsStore.ts
119124
+ init_store();
119125
+ init_schema();
119126
+ function readModels(paths) {
119127
+ return readGlobalConfig(paths)?.models;
119128
+ }
119129
+ function writeModels(paths, models) {
119130
+ const emptied = models !== void 0 && Object.keys(models).length === 0 ? void 0 : models;
119131
+ applyPatch(paths.globalConfigFile, GlobalConfigSchema, { models: emptied }, { defaults: {} });
119132
+ }
119133
+ function stripEmpty(models) {
119134
+ const kept = {};
119135
+ if (models.virtual !== void 0 && Object.keys(models.virtual).length > 0) {
119136
+ kept.virtual = models.virtual;
119137
+ }
119138
+ if (models.tiers !== void 0 && Object.keys(models.tiers).length > 0) {
119139
+ kept.tiers = models.tiers;
119140
+ }
119141
+ if (models.prices !== void 0 && Object.keys(models.prices).length > 0) {
119142
+ kept.prices = models.prices;
119143
+ }
119144
+ if (models.hide !== void 0 && models.hide.length > 0) {
119145
+ kept.hide = models.hide;
119146
+ }
119147
+ if (models.show !== void 0 && models.show.length > 0) {
119148
+ kept.show = models.show;
119149
+ }
119150
+ return kept;
119151
+ }
119152
+ var VirtualModelNotFoundError = class extends Error {
119153
+ constructor(name) {
119154
+ super(`No virtual model named "${name}".`);
119155
+ this.name = "VirtualModelNotFoundError";
119156
+ }
119157
+ };
119158
+ function memberKindOf(ref, models) {
119159
+ if (ref.startsWith("acct:")) {
119160
+ return "account";
119161
+ }
119162
+ if (ref.startsWith("family:")) {
119163
+ return "family";
119164
+ }
119165
+ return models?.virtual !== void 0 && ref in models.virtual ? "virtual" : "provider";
119166
+ }
119167
+ function expandMembers(name, models) {
119168
+ const virtual = models?.virtual ?? {};
119169
+ const expanded = [];
119170
+ const walk2 = (current, chain) => {
119171
+ const nested = virtual[current];
119172
+ if (nested !== void 0) {
119173
+ if (chain.includes(current)) {
119174
+ throw new Error(`virtual model cycle: ${[...chain, current].join(" -> ")}`);
119175
+ }
119176
+ for (const member of nested.members) {
119177
+ walk2(member, [...chain, current]);
119178
+ }
119179
+ return;
119180
+ }
119181
+ if (!expanded.includes(current)) {
119182
+ expanded.push(current);
119183
+ }
119184
+ };
119185
+ const top = virtual[name];
119186
+ if (top === void 0) {
119187
+ throw new VirtualModelNotFoundError(name);
119188
+ }
119189
+ for (const member of top.members) {
119190
+ walk2(member, [name]);
119191
+ }
119192
+ return expanded;
119193
+ }
119194
+ function setVirtualModel(paths, name, model) {
119195
+ const current = readModels(paths) ?? {};
119196
+ writeModels(paths, { ...current, virtual: { ...current.virtual ?? {}, [name]: model } });
119197
+ }
119198
+ function removeVirtualModel(paths, name) {
119199
+ const current = readModels(paths);
119200
+ if (current?.virtual?.[name] === void 0) {
119201
+ throw new VirtualModelNotFoundError(name);
119202
+ }
119203
+ const virtual = Object.fromEntries(Object.entries(current.virtual ?? {}).filter(([existing]) => existing !== name));
119204
+ writeModels(paths, stripEmpty({ ...current, virtual: Object.keys(virtual).length === 0 ? void 0 : virtual }));
119205
+ }
119206
+ function setPrice(paths, ref, prices) {
119207
+ const current = readModels(paths) ?? {};
119208
+ const priced = Object.fromEntries(Object.entries(current.prices ?? {}).filter(([existing]) => existing !== ref));
119209
+ const next = prices === void 0 ? priced : { ...priced, [ref]: prices };
119210
+ writeModels(paths, stripEmpty({ ...current, prices: Object.keys(next).length === 0 ? void 0 : next }));
119211
+ }
119212
+ function setTier(paths, tier, ref) {
119213
+ const current = readModels(paths) ?? {};
119214
+ const tiers = {};
119215
+ const merged = { ...current.tiers ?? {}, [tier]: ref };
119216
+ for (const [key, value2] of Object.entries(merged)) {
119217
+ if (value2 !== void 0) {
119218
+ tiers[key] = value2;
119219
+ }
119220
+ }
119221
+ writeModels(paths, stripEmpty({ ...current, tiers: Object.keys(tiers).length === 0 ? void 0 : tiers }));
119222
+ }
119223
+
119224
+ // src/models/doctor.ts
119225
+ function modelsFindings(input2) {
119226
+ const findings = [];
119227
+ const { models } = input2;
119228
+ const providers = new Set(input2.providers);
119229
+ const identities = new Set(input2.identities);
119230
+ const virtualNames = new Set(Object.keys(models.virtual ?? {}));
119231
+ for (const [name, model] of Object.entries(models.virtual ?? {})) {
119232
+ for (const member of model.members) {
119233
+ const kind = memberKindOf(member, models);
119234
+ if (kind === "provider" && !member.includes("/")) {
119235
+ findings.push({ severity: "fail", message: `Virtual model "${name}" names member "${member}", which is neither a defined virtual model nor a provider model (a provider model is <provider>/<model>).` });
119236
+ } else if (kind === "provider" && !providers.has(member.split("/")[0] ?? "")) {
119237
+ findings.push({ severity: "fail", message: `Virtual model "${name}" names member "${member}", but no provider "${member.split("/")[0] ?? ""}" is defined.` });
119238
+ }
119239
+ if (kind === "virtual" && !virtualNames.has(member)) {
119240
+ findings.push({ severity: "fail", message: `Virtual model "${name}" names member "${member}", but no virtual model "${member}" is defined.` });
119241
+ }
119242
+ if (kind === "account") {
119243
+ const identity = member.slice("acct:".length).split("/")[0] ?? "";
119244
+ if (!identities.has(identity)) {
119245
+ findings.push({ severity: "fail", message: `Virtual model "${name}" names member "${member}", but no identity "${identity}" is defined.` });
119246
+ }
119247
+ }
119248
+ }
119249
+ try {
119250
+ expandMembers(name, models);
119251
+ } catch (error63) {
119252
+ findings.push({ severity: "fail", message: `Virtual model "${name}" cannot be expanded: ${error63 instanceof Error ? error63.message : String(error63)}` });
119253
+ }
119254
+ if (model.mode === "cheapest") {
119255
+ const expanded = expandMembers(name, models);
119256
+ const unpriced = expanded.filter((member) => models.prices?.[member] === void 0 && memberKindOf(member, models) !== "virtual");
119257
+ if (unpriced.length > 0) {
119258
+ findings.push({ severity: "warn", message: `Virtual model "${name}" chooses by price, but no prices are set for: ${unpriced.join(", ")}.` });
119259
+ }
119260
+ }
119261
+ }
119262
+ for (const [tier, ref] of Object.entries(models.tiers ?? {})) {
119263
+ const kind = memberKindOf(ref, models);
119264
+ const known = kind === "virtual" ? virtualNames.has(ref) : kind === "provider" ? providers.has(ref.split("/")[0] ?? "") : true;
119265
+ if (!known) {
119266
+ findings.push({ severity: "fail", message: `Tier ${tier} points at "${ref}", which names nothing defined.` });
119267
+ }
119268
+ }
119269
+ const hidden = new Set(models.hide ?? []);
119270
+ const shown = new Set(models.show ?? []);
119271
+ for (const ref of hidden) {
119272
+ if (shown.has(ref)) {
119273
+ findings.push({ severity: "fail", message: `Model ref "${ref}" is both hidden and in the show-only list.` });
119274
+ }
119275
+ }
119276
+ return findings;
119277
+ }
119278
+
118867
119279
  // src/headroom/allowlistDrift.ts
118868
119280
  init_earlierRelease();
118869
119281
  init_state2();
@@ -119050,7 +119462,8 @@ var DOCTOR_SECTIONS = [
119050
119462
  "categories-local",
119051
119463
  "active-identity",
119052
119464
  "headroom",
119053
- "frontdoor"
119465
+ "frontdoor",
119466
+ "models"
119054
119467
  ];
119055
119468
  function refinePathShadow(status, ownExecutablePath, realpath) {
119056
119469
  if (status.status !== "shadowed") {
@@ -119202,6 +119615,9 @@ function pushLegacyName(push, params) {
119202
119615
  );
119203
119616
  }
119204
119617
  }
119618
+ function parsedModelsOf(paths) {
119619
+ return readGlobalConfig(paths)?.models;
119620
+ }
119205
119621
  function runDoctor(params) {
119206
119622
  const findings = [];
119207
119623
  const push = (section, severity, message, subject) => {
@@ -119403,6 +119819,17 @@ function runDoctor(params) {
119403
119819
  }
119404
119820
  }
119405
119821
  }
119822
+ {
119823
+ const models = params.models;
119824
+ if (models === void 0) {
119825
+ push("models", "pass", "No models block configured.");
119826
+ } else {
119827
+ for (const finding of modelsFindings({ models, providers: params.providers.map((entry) => entry.name), identities: params.identities.map((entry) => entry.name) })) {
119828
+ push("models", finding.severity, finding.message);
119829
+ }
119830
+ push("models", "pass", "The models block is consistent.");
119831
+ }
119832
+ }
119406
119833
  if (params.categoriesLocal.raw === void 0) {
119407
119834
  push("categories-local", "pass", "No categories.local.json configured.");
119408
119835
  } else {
@@ -119497,6 +119924,7 @@ function runDoctor(params) {
119497
119924
  return { findings, ok: !findings.some((finding) => finding.severity === "fail") };
119498
119925
  }
119499
119926
  var SECTION_TITLES = {
119927
+ models: "Virtual models",
119500
119928
  "ambient-credential": "Ambient-credential exposure",
119501
119929
  "binary-discovery": "Claude Code binary discovery",
119502
119930
  "claude-shim": "`claude` command shim",
@@ -119629,6 +120057,7 @@ function collectDoctorReport(params) {
119629
120057
  providers,
119630
120058
  directoryRules: { path: paths.directoryRulesFile, raw: realFsPort.readFileUtf8(paths.directoryRulesFile) },
119631
120059
  globalConfig: { path: paths.globalConfigFile, raw: realFsPort.readFileUtf8(paths.globalConfigFile) },
120060
+ models: parsedModelsOf(paths),
119632
120061
  categoriesLocal: { path: paths.categoriesLocalFile, raw: realFsPort.readFileUtf8(paths.categoriesLocalFile) },
119633
120062
  activeIdentity: { path: paths.activeIdentityFile, raw: realFsPort.readFileUtf8(paths.activeIdentityFile) },
119634
120063
  binaryDiscovery,
@@ -133875,6 +134304,67 @@ function createRealQuotaRefresher(params) {
133875
134304
 
133876
134305
  // src/frontdoor/commands.ts
133877
134306
  init_store2();
134307
+
134308
+ // src/selection/targetStore.ts
134309
+ init_read();
134310
+
134311
+ // src/selection/signals.ts
134312
+ function targetOf(record2) {
134313
+ return record2.model === void 0 ? void 0 : `${record2.provider}/${record2.model}`;
134314
+ }
134315
+ function median(values) {
134316
+ if (values.length === 0) {
134317
+ return void 0;
134318
+ }
134319
+ const sorted = [...values].sort((left, right) => left - right);
134320
+ const middle = Math.floor(sorted.length / 2);
134321
+ const above = sorted[middle];
134322
+ const below = sorted[middle - 1];
134323
+ return sorted.length % 2 === 0 && above !== void 0 && below !== void 0 ? (above + below) / 2 : sorted[middle];
134324
+ }
134325
+ var OBSERVATION_WINDOW = 20;
134326
+ function observeRecord(observations, record2) {
134327
+ const target = targetOf(record2);
134328
+ if (target === void 0) {
134329
+ return new Map(observations);
134330
+ }
134331
+ const kept = [...observations.get(target) ?? [], record2].slice(-OBSERVATION_WINDOW);
134332
+ return new Map(observations).set(target, kept);
134333
+ }
134334
+ function observationOf(records) {
134335
+ const completed = records.filter((record2) => record2.outcome === "completed");
134336
+ const latencies = completed.map((record2) => record2.latencyMs);
134337
+ const usage = records.flatMap((record2) => record2.usage === void 0 ? [] : [record2.usage]);
134338
+ const input2 = usage.reduce((sum, entry) => sum + (entry.inputTokens ?? 0), 0);
134339
+ const output2 = usage.reduce((sum, entry) => sum + (entry.outputTokens ?? 0), 0);
134340
+ const cacheRead = usage.reduce((sum, entry) => sum + (entry.cacheReadInputTokens ?? 0), 0);
134341
+ return {
134342
+ latencyMs: median(latencies),
134343
+ successRate: records.length === 0 ? void 0 : completed.length / records.length,
134344
+ tokenMix: input2 + output2 + cacheRead === 0 ? void 0 : { input: input2, output: output2, cacheRead }
134345
+ };
134346
+ }
134347
+
134348
+ // src/selection/targetStore.ts
134349
+ var SEED_LOOKBACK_RECORDS = 500;
134350
+ function createTargetObservationStore(fs26, paths) {
134351
+ let observations = /* @__PURE__ */ new Map();
134352
+ const seeded = readUsageLog(fs26, paths.usageLogDir, {}).records.slice(-SEED_LOOKBACK_RECORDS);
134353
+ for (const record2 of seeded) {
134354
+ observations = observeRecord(observations, record2);
134355
+ }
134356
+ return {
134357
+ observe: (record2) => {
134358
+ observations = observeRecord(observations, record2);
134359
+ },
134360
+ observation: (target) => {
134361
+ const records = observations.get(target);
134362
+ return records === void 0 ? void 0 : observationOf(records);
134363
+ }
134364
+ };
134365
+ }
134366
+
134367
+ // src/frontdoor/commands.ts
133878
134368
  function respawnInvocation(paths) {
133879
134369
  const env = {};
133880
134370
  for (const [name, value2] of Object.entries({ ...process.env, AGENT_SHIM_HOME: paths.root })) {
@@ -134061,7 +134551,11 @@ function realFrontDoorSupervisorPorts(paths) {
134061
134551
  catalogueKeeper.tick();
134062
134552
  setInterval(catalogueKeeper.tick, ANTHROPIC_USAGE_FRESHNESS_MS).unref();
134063
134553
  const headroomDecision = createHeadroomDecision(createRoutingSettingReader(paths));
134064
- const recordUsage = withQuotaRefresh(usageStore.record, quotaRefresher);
134554
+ const targetObservations = createTargetObservationStore(realFarmFs, paths);
134555
+ const recordUsage = (record2) => {
134556
+ withQuotaRefresh(usageStore.record, quotaRefresher)(record2);
134557
+ targetObservations.observe(record2);
134558
+ };
134065
134559
  const usageMiddleware = createUsageMiddleware({
134066
134560
  // Each finished response also tells the per-session headroom decision when the session's cache was last touched and whether it read from it.
134067
134561
  record: (record2, event) => {
@@ -146610,6 +147104,298 @@ function registerProviderCommand(program2, deps) {
146610
147104
  );
146611
147105
  }
146612
147106
 
147107
+ // src/models.ts
147108
+ init_commandDeps();
147109
+ init_providersStore();
147110
+ init_modelPicker();
147111
+ init_providerCatalogue();
147112
+ init_realPorts();
147113
+ init_schema();
147114
+ init_cliError();
147115
+
147116
+ // src/models/identity.ts
147117
+ var NON_IDENTITY_BRACKET_RE = /\[[^\]]*\]/g;
147118
+ var DATE_STAMP_RE = /-(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])$/;
147119
+ var KNOWN_VARIANTS = /* @__PURE__ */ new Set(["high", "medium", "low", "thinking", "xhigh", "max", "highspeed", "sol", "terra", "luna", "mini", "flash-lite", "turbo"]);
147120
+ var VENDOR_BY_NAMESPACE = Object.freeze({
147121
+ anthropic: "anthropic",
147122
+ google: "google",
147123
+ openai: "openai",
147124
+ zai: "zai",
147125
+ "z-ai": "zai",
147126
+ minimax: "minimax",
147127
+ qwen: "qwen",
147128
+ deepseek: "deepseek",
147129
+ moonshot: "moonshot",
147130
+ meta: "meta",
147131
+ mistral: "mistral"
147132
+ });
147133
+ var VENDOR_BY_TOKEN = Object.freeze({
147134
+ claude: "anthropic",
147135
+ gemini: "google",
147136
+ antigravity: "google",
147137
+ gpt: "openai",
147138
+ glm: "zai",
147139
+ minimax: "minimax",
147140
+ qwen: "qwen",
147141
+ deepseek: "deepseek",
147142
+ kimi: "moonshot",
147143
+ llama: "meta",
147144
+ mistral: "mistral",
147145
+ mixtral: "mistral"
147146
+ });
147147
+ function canonicalText(name) {
147148
+ return name.trim().toLowerCase().replace(NON_IDENTITY_BRACKET_RE, "").replace(/[\s_]+/g, "-").replace(/([a-z])(\d+(?:\.\d+)+)/g, "$1-$2").replace(/-+/g, "-").replace(/^-|-$/g, "");
147149
+ }
147150
+ function splitVariants(tokens) {
147151
+ const variants = [];
147152
+ let end = tokens.length;
147153
+ for (; ; ) {
147154
+ const token = tokens[end - 1];
147155
+ if (token === void 0 || !KNOWN_VARIANTS.has(token)) {
147156
+ return { familyTokens: tokens.slice(0, end), variants };
147157
+ }
147158
+ variants.unshift(token);
147159
+ end -= 1;
147160
+ }
147161
+ }
147162
+ function versionOf(tokens) {
147163
+ for (let index = 0; index < tokens.length; index += 1) {
147164
+ const token = tokens[index];
147165
+ const next = tokens[index + 1];
147166
+ if (token === void 0) {
147167
+ return "";
147168
+ }
147169
+ if (/^\d+$/.test(token) && next !== void 0 && /^\d+$/.test(next)) {
147170
+ return `${token}.${next}`;
147171
+ }
147172
+ const dotted = /^\d+(?:\.\d+)+$/.exec(token);
147173
+ if (dotted !== null) {
147174
+ return dotted[0];
147175
+ }
147176
+ }
147177
+ return "";
147178
+ }
147179
+ function modelIdentity(rawName) {
147180
+ const segments = rawName.trim().toLowerCase().split("/");
147181
+ const stripped = canonicalText(segments[segments.length - 1] ?? "").split(":")[0] ?? "";
147182
+ const withoutDate = stripped.replace(DATE_STAMP_RE, "");
147183
+ const tokens = withoutDate.split("-").filter((token) => token !== "");
147184
+ const { familyTokens, variants } = splitVariants(tokens);
147185
+ const version2 = versionOf(familyTokens);
147186
+ const versionless = familyTokens.filter((token, index) => {
147187
+ if (version2 === "") {
147188
+ return true;
147189
+ }
147190
+ const dotted = /^\d+(?:\.\d+)+$/.test(token);
147191
+ const previous = familyTokens[index - 1];
147192
+ const next = familyTokens[index + 1];
147193
+ const insideVersionRun = dotted || /^\d+$/.test(token) && (previous !== void 0 && /^\d+$/.test(previous) || next !== void 0 && /^\d+$/.test(next));
147194
+ return !insideVersionRun;
147195
+ });
147196
+ const family = versionless.join("-");
147197
+ const tokenVendor = familyTokens.find((token) => Object.keys(VENDOR_BY_TOKEN).some((key) => token === key || token.startsWith(key)));
147198
+ const namespace = segments.length >= 2 ? (segments[0] ?? "").split(":").pop() ?? "" : "";
147199
+ const namespaceVendor = VENDOR_BY_NAMESPACE[namespace] ?? "";
147200
+ const tokenVendorName = tokenVendor === void 0 ? "" : VENDOR_BY_TOKEN[Object.keys(VENDOR_BY_TOKEN).find((key) => tokenVendor === key || tokenVendor.startsWith(key)) ?? ""] ?? "";
147201
+ return {
147202
+ vendor: tokenVendorName === "" ? namespaceVendor : tokenVendorName,
147203
+ vendorConflict: tokenVendorName !== "" && namespaceVendor !== "" && tokenVendorName !== namespaceVendor,
147204
+ family,
147205
+ version: version2,
147206
+ variant: variants.join("-"),
147207
+ familyAndVersion: version2 === "" ? family : `${family}-${version2.replace(/\./g, "-")}`
147208
+ };
147209
+ }
147210
+ function relateModels(left, right) {
147211
+ const a10 = modelIdentity(left);
147212
+ const b = modelIdentity(right);
147213
+ if (a10.familyAndVersion !== b.familyAndVersion) {
147214
+ return sameFamilyOtherVersion(a10, b) ? "similar" : "distinct";
147215
+ }
147216
+ if (a10.variant !== b.variant || a10.vendorConflict || b.vendorConflict || a10.vendor !== "" && b.vendor !== "" && a10.vendor !== b.vendor) {
147217
+ return "similar";
147218
+ }
147219
+ return "same";
147220
+ }
147221
+ function sameFamilyOtherVersion(a10, b) {
147222
+ if (a10.family !== b.family) {
147223
+ return false;
147224
+ }
147225
+ if (a10.vendor !== "" && b.vendor !== "" && a10.vendor !== b.vendor) {
147226
+ return false;
147227
+ }
147228
+ return true;
147229
+ }
147230
+
147231
+ // src/models.ts
147232
+ function providerModels(paths) {
147233
+ return listProviders(paths).flatMap((entry) => {
147234
+ const catalogue = parseCatalogueCache(realFsPort.readFileUtf8(catalogueCachePath(paths, entry.name)));
147235
+ return providerModelRows(entry.provider, catalogue?.models).map((row) => ({ provider: entry.name, model: row.model }));
147236
+ });
147237
+ }
147238
+ function matchModels(models) {
147239
+ const same = [];
147240
+ for (const model of models) {
147241
+ const group = same.find((candidates) => candidates.some((other) => relateModels(other.model, model.model) === "same" && other.provider !== model.provider));
147242
+ if (group === void 0) {
147243
+ same.push([model]);
147244
+ } else {
147245
+ group.push(model);
147246
+ }
147247
+ }
147248
+ const similar = [];
147249
+ for (let outer = 0; outer < models.length; outer += 1) {
147250
+ for (let inner = outer + 1; inner < models.length; inner += 1) {
147251
+ const left = models[outer];
147252
+ const right = models[inner];
147253
+ if (left === void 0 || right === void 0 || left.provider === right.provider) {
147254
+ continue;
147255
+ }
147256
+ if (relateModels(left.model, right.model) === "similar" && !same.some((group) => group.includes(left) && group.includes(right))) {
147257
+ similar.push([left, right]);
147258
+ }
147259
+ }
147260
+ }
147261
+ return { same: same.filter((group) => group.length > 1), similar };
147262
+ }
147263
+ function registerModelsCommand(program2, deps) {
147264
+ const { paths } = deps;
147265
+ const modelsCommand = program2.command("model").description("Define and inspect the models the providers offer and the virtual models chosen among them.");
147266
+ withExamples(modelsCommand, ["agent-shim model match", "agent-shim model add fast --mode soonest-reset --member z/glm-5.3 --member m/MiniMax-M3"]);
147267
+ withExamples(
147268
+ modelsCommand.command("match").description("List every model every provider offers, grouped into the ones that are the same model across providers, with the pairs that are merely similar named beside them.").option("--json", "Print the match as JSON."),
147269
+ ["agent-shim model match"]
147270
+ ).action((options) => {
147271
+ const models = providerModels(paths);
147272
+ const { same, similar } = matchModels(models);
147273
+ if (options.json === true) {
147274
+ printJson({ models, same, similar });
147275
+ return;
147276
+ }
147277
+ console.log(`Models of ${String(models.length)} across the defined providers:`);
147278
+ if (same.length === 0 && similar.length === 0) {
147279
+ console.log(" no two names are the same model, and none look alike");
147280
+ return;
147281
+ }
147282
+ for (const group of same) {
147283
+ console.log(` same: ${group.map((entry) => `${entry.provider}/${entry.model}`).join(" = ")}`);
147284
+ }
147285
+ for (const [left, right] of similar) {
147286
+ console.log(` similar: ${left.provider}/${left.model} ~ ${right.provider}/${right.model}`);
147287
+ }
147288
+ });
147289
+ withExamples(
147290
+ modelsCommand.command("add <name>").description("Define a virtual model: a named choice over members, taken by its mode.").requiredOption("--mode <mode>", "How the virtual model chooses its member.", (value2) => asMode(value2)).option("--member <ref>", "One member it chooses among: a provider model (z/glm-5.3), an account model (acct:work/opus), another virtual model, or a family (family:<canonical>). Repeatable; order is the preference where the mode reads it.", collectRepeated),
147291
+ ["agent-shim model add fast --mode soonest-reset --member z/glm-5.3 --member m/MiniMax-M3"]
147292
+ ).action((name, options) => {
147293
+ if (options.member === void 0 || options.member.length === 0) {
147294
+ throw new UsageError("A virtual model needs at least one member: pass --member <ref> (repeatable).");
147295
+ }
147296
+ setVirtualModel(paths, name, { mode: options.mode, members: options.member });
147297
+ console.log(`Defined virtual model "${name}" (${options.mode}): ${options.member.join(", ")}`);
147298
+ });
147299
+ withExamples(
147300
+ modelsCommand.command("set <name>").description("Change a virtual model's mode or replace its member list; members not named are kept.").option("--mode <mode>", "The new mode.", (value2) => asMode(value2)).option("--member <ref>", "Add or replace one member (repeatable).", collectRepeated),
147301
+ ["agent-shim model set fast --mode most-allowance"]
147302
+ ).action((name, options) => {
147303
+ const existing = readModels(paths)?.virtual?.[name];
147304
+ if (existing === void 0) {
147305
+ throw new VirtualModelNotFoundError(name);
147306
+ }
147307
+ if (options.mode === void 0 && options.member === void 0) {
147308
+ throw new UsageError("Nothing to change: pass --mode or --member.");
147309
+ }
147310
+ const members2 = options.member === void 0 ? existing.members : [.../* @__PURE__ */ new Set([...existing.members, ...options.member])];
147311
+ setVirtualModel(paths, name, { mode: options.mode ?? existing.mode, members: members2 });
147312
+ console.log(`Updated virtual model "${name}" (${options.mode ?? existing.mode}): ${members2.join(", ")}`);
147313
+ });
147314
+ withExamples(
147315
+ modelsCommand.command("remove <name>").description("Remove a virtual model definition.").option("--yes", "Remove without asking for confirmation.").option("--json", "Print the result as JSON."),
147316
+ ["agent-shim model remove fast --yes"]
147317
+ ).action(async (name, options) => {
147318
+ await confirmRemoval(deps, options.yes, `virtual model "${name}"`);
147319
+ removeVirtualModel(paths, name);
147320
+ reportMutation(options.json, { action: "removed", kind: "model", name, value: void 0 }, () => {
147321
+ console.log(`Removed virtual model "${name}".`);
147322
+ });
147323
+ });
147324
+ withExamples(
147325
+ modelsCommand.command("tier <tier>").description("Point one Claude tier (fable, opus, sonnet, haiku) at a model ref: a concrete target, an account model, a virtual model, or a family.").option("--ref <ref>", "The model ref the tier points at. Omit with --clear to reset the tier to its per-provider behaviour.").option("--clear", "Reset the tier to its per-provider behaviour."),
147326
+ ["agent-shim model tier opus --ref fast", "agent-shim model tier opus --clear"]
147327
+ ).action((tier, options) => {
147328
+ const which = asTier(tier);
147329
+ if (options.clear === true) {
147330
+ setTier(paths, which, void 0);
147331
+ console.log(`Tier ${which} reset to its per-provider behaviour.`);
147332
+ return;
147333
+ }
147334
+ if (options.ref === void 0) {
147335
+ throw new UsageError("Pass --ref <ref>, or --clear to reset the tier.");
147336
+ }
147337
+ setTier(paths, which, options.ref);
147338
+ console.log(`Tier ${which} points at ${options.ref}.`);
147339
+ });
147340
+ withExamples(
147341
+ modelsCommand.command("price <ref>").description("Set a model ref's prices, in USD per million tokens, for the cheapest mode.").option("--input <usd>", "The input price per million tokens.", (value2) => asPrice(value2)).option("--output <usd>", "The output price per million tokens.", (value2) => asPrice(value2)).option("--clear", "Remove the ref's prices instead."),
147342
+ ["agent-shim model price z/glm-5.3 --input 0.6 --output 2.2"]
147343
+ ).action((ref, options) => {
147344
+ if (options.clear !== true && (options.input === void 0 || options.output === void 0)) {
147345
+ throw new UsageError("Pass both --input and --output, or --clear to remove the ref's prices.");
147346
+ }
147347
+ setPrice(paths, ref, options.clear === true ? void 0 : { input: options.input ?? 0, output: options.output ?? 0 });
147348
+ console.log(options.clear === true ? `Removed prices for ${ref}.` : `Prices for ${ref}: ${String(options.input)} in, ${String(options.output)} out per million tokens.`);
147349
+ });
147350
+ withExamples(
147351
+ modelsCommand.command("list").description("List the defined virtual models, the tier pointers and the visibility filter.").option("--json", "Print the models block as JSON."),
147352
+ ["agent-shim model list"]
147353
+ ).action((options) => {
147354
+ const found = readModels(paths);
147355
+ if (options.json === true) {
147356
+ printJson(found ?? null);
147357
+ return;
147358
+ }
147359
+ if (found === void 0) {
147360
+ console.log("No models block is configured.");
147361
+ return;
147362
+ }
147363
+ for (const [name, model] of Object.entries(found.virtual ?? {})) {
147364
+ console.log(`${name} (${model.mode}): ${model.members.join(", ")}`);
147365
+ }
147366
+ for (const [tier, ref] of Object.entries(found.tiers ?? {})) {
147367
+ console.log(`tier ${tier} -> ${ref}`);
147368
+ }
147369
+ if (found.hide !== void 0) {
147370
+ console.log(`hidden: ${found.hide.join(", ")}`);
147371
+ }
147372
+ if (found.show !== void 0) {
147373
+ console.log(`visible only: ${found.show.join(", ")}`);
147374
+ }
147375
+ });
147376
+ }
147377
+ function asMode(value2) {
147378
+ const mode = SELECTION_MODES.find((candidate) => candidate === value2);
147379
+ if (mode === void 0) {
147380
+ throw new UsageError(`Unknown mode "${value2}". Known modes: ${SELECTION_MODES.join(", ")}.`);
147381
+ }
147382
+ return mode;
147383
+ }
147384
+ function asPrice(value2) {
147385
+ const parsed = Number(value2);
147386
+ if (!Number.isFinite(parsed) || parsed <= 0) {
147387
+ throw new UsageError(`"${value2}" is not a price: pass a positive number of US dollars.`);
147388
+ }
147389
+ return parsed;
147390
+ }
147391
+ function asTier(value2) {
147392
+ const tier = CLAUDE_TIERS.find((candidate) => candidate === value2);
147393
+ if (tier === void 0) {
147394
+ throw new UsageError(`Unknown tier "${value2}". Known tiers: ${CLAUDE_TIERS.join(", ")}.`);
147395
+ }
147396
+ return tier;
147397
+ }
147398
+
146613
147399
  // src/directoryRules.ts
146614
147400
  init_commandDeps();
146615
147401
  init_cliError();
@@ -147104,6 +147890,7 @@ function buildProgram(deps) {
147104
147890
  registerJobCommand(program2, deps);
147105
147891
  registerHeadlessCommands(program2, deps);
147106
147892
  registerProviderCommand(program2, deps);
147893
+ registerModelsCommand(program2, deps);
147107
147894
  registerRuleCommand(program2, deps);
147108
147895
  registerCredentialCommand(program2, deps, deps.credentialPorts);
147109
147896
  registerCheckCommand(program2, deps);