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/README.md +7 -0
- package/dist/cli.cjs +835 -48
- package/dist/index.cjs +242 -7
- package/dist/index.mjs +242 -7
- package/dist/types/index.d.ts +532 -13
- package/package.json +1 -1
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.
|
|
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
|
-
|
|
64313
|
-
|
|
64314
|
-
|
|
64315
|
-
|
|
64316
|
-
|
|
64317
|
-
|
|
64318
|
-
|
|
64319
|
-
|
|
64320
|
-
|
|
64321
|
-
|
|
64322
|
-
|
|
64323
|
-
|
|
64324
|
-
|
|
64325
|
-
|
|
64326
|
-
|
|
64327
|
-
|
|
64328
|
-
|
|
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,
|
|
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
|
-
|
|
65080
|
+
SECONDS_PER_HOUR3 = 3600;
|
|
64825
65081
|
HOURS_PER_DAY4 = 24;
|
|
64826
|
-
MS_PER_HOUR3 =
|
|
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,
|
|
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
|
-
|
|
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,
|
|
65852
|
-
[ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY5 *
|
|
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 *
|
|
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 *
|
|
65953
|
-
WEEK_MS = DAYS_PER_WEEK2 * HOURS_PER_DAY5 *
|
|
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
|
|
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) && !
|
|
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) =>
|
|
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
|
|
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);
|