claudish 7.43.0 → 7.44.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.
Files changed (2) hide show
  1. package/dist/index.js +635 -296
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -729,7 +729,7 @@ var init_onepassword_config = __esm(() => {
729
729
  });
730
730
 
731
731
  // src/version.ts
732
- var VERSION = "7.43.0";
732
+ var VERSION = "7.44.0";
733
733
 
734
734
  // src/logger.ts
735
735
  var exports_logger = {};
@@ -28338,6 +28338,7 @@ var init_provider_definitions = __esm(() => {
28338
28338
  { prefix: "ollama:", stripPrefix: true }
28339
28339
  ],
28340
28340
  isLocal: true,
28341
+ modelDiscovery: { path: "/api/tags", format: "ollama-tags" },
28341
28342
  description: "Local Ollama (ollama@)"
28342
28343
  },
28343
28344
  {
@@ -28359,6 +28360,7 @@ var init_provider_definitions = __esm(() => {
28359
28360
  { prefix: "mlstudio:", stripPrefix: true }
28360
28361
  ],
28361
28362
  isLocal: true,
28363
+ modelDiscovery: { path: "/v1/models", format: "openai-models-list" },
28362
28364
  description: "Local LM Studio (lms@)"
28363
28365
  },
28364
28366
  {
@@ -28553,6 +28555,208 @@ var init_auto_route = __esm(() => {
28553
28555
  })();
28554
28556
  });
28555
28557
 
28558
+ // src/providers/all-models-cache.ts
28559
+ import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
28560
+ import { homedir as homedir8 } from "os";
28561
+ import { dirname as dirname5, join as join8 } from "path";
28562
+ function readAllModelsCache(path = ALL_MODELS_CACHE_PATH) {
28563
+ if (!existsSync6(path))
28564
+ return null;
28565
+ let raw;
28566
+ try {
28567
+ raw = JSON.parse(readFileSync6(path, "utf-8"));
28568
+ } catch {
28569
+ return null;
28570
+ }
28571
+ if (!raw || typeof raw !== "object")
28572
+ return null;
28573
+ const data = raw;
28574
+ const lastUpdated = typeof data.lastUpdated === "string" ? data.lastUpdated : new Date(0).toISOString();
28575
+ const models = Array.isArray(data.models) ? data.models : [];
28576
+ const entries = Array.isArray(data.entries) ? data.entries : [];
28577
+ return {
28578
+ version: 2,
28579
+ lastUpdated,
28580
+ entries,
28581
+ models
28582
+ };
28583
+ }
28584
+ function writeAllModelsCache(data, path = ALL_MODELS_CACHE_PATH) {
28585
+ const existing = readAllModelsCache(path);
28586
+ const merged = {
28587
+ version: 2,
28588
+ lastUpdated: data.lastUpdated ?? new Date().toISOString(),
28589
+ entries: data.entries ?? existing?.entries ?? [],
28590
+ models: data.models ?? existing?.models ?? []
28591
+ };
28592
+ mkdirSync6(dirname5(path), { recursive: true });
28593
+ writeFileSync6(path, JSON.stringify(merged), "utf-8");
28594
+ }
28595
+ var ALL_MODELS_CACHE_PATH;
28596
+ var init_all_models_cache = __esm(() => {
28597
+ ALL_MODELS_CACHE_PATH = join8(homedir8(), ".claudish", "all-models.json");
28598
+ });
28599
+
28600
+ // src/providers/catalog-client.ts
28601
+ function getCatalogEntries() {
28602
+ if (_memCache)
28603
+ return _memCache;
28604
+ const cache = readAllModelsCache();
28605
+ if (!cache)
28606
+ return null;
28607
+ if (cache.entries.length > 0) {
28608
+ _memCache = cache.entries;
28609
+ return _memCache;
28610
+ }
28611
+ if (cache.models.length > 0) {
28612
+ _memCache = cache.models.map((m) => ({
28613
+ modelId: m.id.includes("/") ? m.id.split("/").slice(1).join("/") : m.id,
28614
+ aliases: [],
28615
+ sources: { "openrouter-api": { externalId: m.id } }
28616
+ }));
28617
+ return _memCache;
28618
+ }
28619
+ return null;
28620
+ }
28621
+ function isCatalogWarm() {
28622
+ return _memCache !== null && _memCache.length > 0;
28623
+ }
28624
+ function externalIdFor(entry, provider) {
28625
+ const agg = entry.aggregators?.find((a) => a.provider === provider);
28626
+ if (agg?.externalId)
28627
+ return agg.externalId;
28628
+ if (provider !== "openrouter")
28629
+ return null;
28630
+ const orSource = entry.sources["openrouter-api"];
28631
+ if (orSource?.externalId)
28632
+ return orSource.externalId;
28633
+ for (const src of Object.values(entry.sources)) {
28634
+ if (src.externalId.includes("/"))
28635
+ return src.externalId;
28636
+ }
28637
+ return null;
28638
+ }
28639
+ function resolveExternalId(userInput, provider) {
28640
+ const entries = getCatalogEntries();
28641
+ if (userInput.includes("/")) {
28642
+ if (entries) {
28643
+ for (const entry of entries) {
28644
+ for (const src of Object.values(entry.sources)) {
28645
+ if (src.externalId === userInput)
28646
+ return userInput;
28647
+ }
28648
+ }
28649
+ }
28650
+ return userInput;
28651
+ }
28652
+ if (!entries)
28653
+ return null;
28654
+ const byModelId = entries.find((e) => e.modelId === userInput);
28655
+ if (byModelId)
28656
+ return externalIdFor(byModelId, provider);
28657
+ const byAlias = entries.find((e) => e.aliases.includes(userInput));
28658
+ if (byAlias) {
28659
+ const id = externalIdFor(byAlias, provider);
28660
+ if (id)
28661
+ return id;
28662
+ }
28663
+ for (const entry of entries) {
28664
+ for (const src of Object.values(entry.sources)) {
28665
+ if (src.externalId === userInput) {
28666
+ const id = externalIdFor(entry, provider);
28667
+ if (id)
28668
+ return id;
28669
+ }
28670
+ }
28671
+ }
28672
+ const suffix = `/${userInput}`;
28673
+ for (const entry of entries) {
28674
+ const id = externalIdFor(entry, provider);
28675
+ if (id?.endsWith(suffix))
28676
+ return id;
28677
+ }
28678
+ const lowerSuffix = `/${userInput.toLowerCase()}`;
28679
+ for (const entry of entries) {
28680
+ const id = externalIdFor(entry, provider);
28681
+ if (id?.toLowerCase().endsWith(lowerSuffix))
28682
+ return id;
28683
+ }
28684
+ return null;
28685
+ }
28686
+ function resolveModelNameSync(userInput, targetProvider) {
28687
+ if (targetProvider !== "openrouter" && userInput.includes("/")) {
28688
+ return { resolvedId: userInput, wasResolved: false, sourceLabel: "passthrough" };
28689
+ }
28690
+ const resolved = resolveExternalId(userInput, targetProvider);
28691
+ if (!resolved || resolved === userInput) {
28692
+ return { resolvedId: userInput, wasResolved: false, sourceLabel: "passthrough" };
28693
+ }
28694
+ return { resolvedId: resolved, wasResolved: true, sourceLabel: `${targetProvider} catalog` };
28695
+ }
28696
+ function logResolution(userInput, result, quiet = false) {
28697
+ if (result.wasResolved && !quiet) {
28698
+ process.stderr.write(`[Model] Resolved "${userInput}" \u2192 "${result.resolvedId}" (${result.sourceLabel})
28699
+ `);
28700
+ }
28701
+ }
28702
+ async function refreshCatalog(timeoutMs) {
28703
+ let response;
28704
+ try {
28705
+ response = await fetch(FIREBASE_CATALOG_URL, { signal: AbortSignal.timeout(timeoutMs) });
28706
+ } catch (err) {
28707
+ const name = err?.name;
28708
+ const reason = name === "TimeoutError" || name === "AbortError" ? "timeout" : "network";
28709
+ return { kind: "fetch_failed", reason };
28710
+ }
28711
+ if (!response.ok)
28712
+ return { kind: "fetch_failed", reason: "http_error" };
28713
+ let data;
28714
+ try {
28715
+ data = await response.json();
28716
+ } catch {
28717
+ return { kind: "fetch_failed", reason: "network" };
28718
+ }
28719
+ if (!Array.isArray(data.models) || data.models.length === 0) {
28720
+ return { kind: "fetch_failed", reason: "empty" };
28721
+ }
28722
+ const backwardCompatModels = [];
28723
+ for (const entry of data.models) {
28724
+ const id = externalIdFor(entry, "openrouter");
28725
+ if (id)
28726
+ backwardCompatModels.push({ id });
28727
+ }
28728
+ _memCache = data.models;
28729
+ writeAllModelsCache({ entries: data.models, models: backwardCompatModels });
28730
+ _warmPromise = Promise.resolve();
28731
+ return { kind: "refreshed", modelCount: data.models.length };
28732
+ }
28733
+ async function warmCatalog() {
28734
+ if (!_warmPromise) {
28735
+ _warmPromise = refreshCatalog(8000).then(() => {
28736
+ return;
28737
+ });
28738
+ }
28739
+ await _warmPromise;
28740
+ }
28741
+ async function ensureCatalogReady(timeoutMs = 5000) {
28742
+ if (isCatalogWarm())
28743
+ return;
28744
+ if (!_warmPromise) {
28745
+ _warmPromise = refreshCatalog(8000).then(() => {
28746
+ return;
28747
+ });
28748
+ }
28749
+ await Promise.race([
28750
+ _warmPromise,
28751
+ new Promise((resolve) => setTimeout(resolve, timeoutMs))
28752
+ ]);
28753
+ }
28754
+ var FIREBASE_CATALOG_URL, _memCache = null, _warmPromise = null;
28755
+ var init_catalog_client = __esm(() => {
28756
+ init_all_models_cache();
28757
+ FIREBASE_CATALOG_URL = process.env.CLAUDISH_CATALOG_URL ?? process.env.FIREBASE_CATALOG_URL ?? "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels?status=active&catalog=slim&limit=1000";
28758
+ });
28759
+
28556
28760
  // ../../node_modules/.bun/zod@4.1.13/node_modules/zod/index.js
28557
28761
  var init_zod = __esm(() => {
28558
28762
  init_external2();
@@ -28612,48 +28816,6 @@ var init_remote_provider_types = __esm(() => {
28612
28816
  };
28613
28817
  });
28614
28818
 
28615
- // src/providers/all-models-cache.ts
28616
- import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
28617
- import { homedir as homedir8 } from "os";
28618
- import { dirname as dirname5, join as join8 } from "path";
28619
- function readAllModelsCache(path = ALL_MODELS_CACHE_PATH) {
28620
- if (!existsSync6(path))
28621
- return null;
28622
- let raw;
28623
- try {
28624
- raw = JSON.parse(readFileSync6(path, "utf-8"));
28625
- } catch {
28626
- return null;
28627
- }
28628
- if (!raw || typeof raw !== "object")
28629
- return null;
28630
- const data = raw;
28631
- const lastUpdated = typeof data.lastUpdated === "string" ? data.lastUpdated : new Date(0).toISOString();
28632
- const models = Array.isArray(data.models) ? data.models : [];
28633
- const entries = Array.isArray(data.entries) ? data.entries : [];
28634
- return {
28635
- version: 2,
28636
- lastUpdated,
28637
- entries,
28638
- models
28639
- };
28640
- }
28641
- function writeAllModelsCache(data, path = ALL_MODELS_CACHE_PATH) {
28642
- const existing = readAllModelsCache(path);
28643
- const merged = {
28644
- version: 2,
28645
- lastUpdated: data.lastUpdated ?? new Date().toISOString(),
28646
- entries: data.entries ?? existing?.entries ?? [],
28647
- models: data.models ?? existing?.models ?? []
28648
- };
28649
- mkdirSync6(dirname5(path), { recursive: true });
28650
- writeFileSync6(path, JSON.stringify(merged), "utf-8");
28651
- }
28652
- var ALL_MODELS_CACHE_PATH;
28653
- var init_all_models_cache = __esm(() => {
28654
- ALL_MODELS_CACHE_PATH = join8(homedir8(), ".claudish", "all-models.json");
28655
- });
28656
-
28657
28819
  // src/adapters/model-catalog.ts
28658
28820
  function lookupModel(modelId, cachePath) {
28659
28821
  const entry = findCacheEntry(modelId, cachePath);
@@ -30447,10 +30609,10 @@ ${lines.join(`
30447
30609
  }
30448
30610
  var ANTIGRAVITY_BASE = "https://cloudcode-pa.googleapis.com", ANTIGRAVITY_ENDPOINT, MAX_RETRY_ATTEMPTS = 3, DEFAULT_RATE_LIMIT_DELAY_MS = 1e4, REASONING_TIER_RANK;
30449
30611
  var init_antigravity = __esm(() => {
30612
+ init_model_catalog();
30450
30613
  init_antigravity_token();
30451
- init_authority();
30452
30614
  init_antigravity_user();
30453
- init_model_catalog();
30615
+ init_authority();
30454
30616
  init_gemini_queue();
30455
30617
  init_logger();
30456
30618
  ANTIGRAVITY_ENDPOINT = `${ANTIGRAVITY_BASE}/v1internal:streamGenerateContent?alt=sse`;
@@ -34927,6 +35089,11 @@ var init_digest = __esm(() => {
34927
35089
  });
34928
35090
 
34929
35091
  // src/providers/ollama-discovery.ts
35092
+ var exports_ollama_discovery = {};
35093
+ __export(exports_ollama_discovery, {
35094
+ ollamaBaseUrl: () => ollamaBaseUrl,
35095
+ fetchOllamaModels: () => fetchOllamaModels
35096
+ });
34930
35097
  function ollamaBaseUrl() {
34931
35098
  return process.env.OLLAMA_HOST || process.env.OLLAMA_BASE_URL || "http://localhost:11434";
34932
35099
  }
@@ -40796,6 +40963,7 @@ __export(exports_devin_models, {
40796
40963
  getServedDevinModels: () => getServedDevinModels,
40797
40964
  fetchDevinModelConfigs: () => fetchDevinModelConfigs,
40798
40965
  fetchDevinAllowedUids: () => fetchDevinAllowedUids,
40966
+ decodeModelConfigs: () => decodeModelConfigs,
40799
40967
  _resetDevinModelCache: () => _resetDevinModelCache
40800
40968
  });
40801
40969
  function unaryMetadata(apiKey) {
@@ -40835,11 +41003,59 @@ function decodeModelDetails(payload) {
40835
41003
  }
40836
41004
  return { maxOutput, family };
40837
41005
  }
41006
+ function decodeFamilyMetadata(payload) {
41007
+ let groupLabel;
41008
+ const axes = [];
41009
+ for (const sub of parseTLV(payload)) {
41010
+ if (sub.no === 1 && sub.wire === 2) {
41011
+ groupLabel = readString(sub) || undefined;
41012
+ continue;
41013
+ }
41014
+ if (sub.no !== 2 || sub.wire !== 2)
41015
+ continue;
41016
+ const axis = { key: "", enabled: false };
41017
+ for (const entry of parseTLV(sub.payload)) {
41018
+ if (entry.no === 1 && entry.wire === 2)
41019
+ axis.key = readString(entry);
41020
+ else if (entry.no === 2 && entry.wire === 2) {
41021
+ for (const value of parseTLV(entry.payload)) {
41022
+ if (value.no === 1 && value.wire === 0)
41023
+ axis.enabled = readVarintValue(value) === 1;
41024
+ else if (value.no === 2 && value.wire === 2)
41025
+ axis.label = readString(value) || undefined;
41026
+ }
41027
+ }
41028
+ }
41029
+ if (axis.key)
41030
+ axes.push(axis);
41031
+ }
41032
+ return { groupLabel, axes };
41033
+ }
41034
+ function decodePromo(payload) {
41035
+ for (const sub of parseTLV(payload)) {
41036
+ if (sub.wire !== 2)
41037
+ continue;
41038
+ for (const inner of parseTLV(sub.payload)) {
41039
+ if (inner.no === 1 && inner.wire === 0) {
41040
+ const expiresAt = readVarintValue(inner);
41041
+ if (expiresAt > 0)
41042
+ return { expiresAt };
41043
+ }
41044
+ }
41045
+ }
41046
+ return;
41047
+ }
40838
41048
  function decodeModelConfig(payload) {
40839
41049
  let uid = "";
40840
41050
  let displayName = "";
40841
41051
  let contextWindow = 0;
40842
41052
  let details = { maxOutput: 0, family: "" };
41053
+ let family = { axes: [] };
41054
+ let creditMultiplier;
41055
+ let costTier;
41056
+ let isFamilyDefault = false;
41057
+ let isRecommended = false;
41058
+ let promo;
40843
41059
  for (const field of parseTLV(payload)) {
40844
41060
  if (field.no === 22 && field.wire === 2)
40845
41061
  uid = readString(field);
@@ -40849,10 +41065,34 @@ function decodeModelConfig(payload) {
40849
41065
  contextWindow = readVarintValue(field);
40850
41066
  else if (field.no === 23 && field.wire === 2)
40851
41067
  details = decodeModelDetails(field.payload);
41068
+ else if (field.no === 30 && field.wire === 2)
41069
+ family = decodeFamilyMetadata(field.payload);
41070
+ else if (field.no === 3 && field.wire === 5)
41071
+ creditMultiplier = readFloat32LE(field);
41072
+ else if (field.no === 24 && field.wire === 0)
41073
+ costTier = readVarintValue(field);
41074
+ else if (field.no === 31 && field.wire === 0)
41075
+ isFamilyDefault = readVarintValue(field) === 1;
41076
+ else if (field.no === 11 && field.wire === 0)
41077
+ isRecommended = readVarintValue(field) === 1;
41078
+ else if (field.no === 19 && field.wire === 2)
41079
+ promo = decodePromo(field.payload);
40852
41080
  }
40853
41081
  if (!uid)
40854
41082
  return null;
40855
- return { uid, displayName: displayName || uid, contextWindow, ...details };
41083
+ return {
41084
+ uid,
41085
+ displayName: displayName || uid,
41086
+ contextWindow,
41087
+ ...details,
41088
+ groupLabel: family.groupLabel,
41089
+ axes: family.axes,
41090
+ creditMultiplier,
41091
+ costTier,
41092
+ isFamilyDefault,
41093
+ isRecommended,
41094
+ promo
41095
+ };
40856
41096
  }
40857
41097
  function topLevelDelimited(body, fieldNumber) {
40858
41098
  return parseTLV(body).filter((field) => field.no === fieldNumber && field.wire === 2);
@@ -40861,13 +41101,17 @@ async function fetchDevinModelConfigs(apiKey) {
40861
41101
  const body = await postUnary(MODEL_CONFIGS_PATH, apiKey);
40862
41102
  if (!body)
40863
41103
  return [];
41104
+ const configs = decodeModelConfigs(body);
41105
+ log(`[Devin] GetCliModelConfigs: ${configs.length} configs`);
41106
+ return configs;
41107
+ }
41108
+ function decodeModelConfigs(body) {
40864
41109
  const configs = [];
40865
41110
  for (const field of topLevelDelimited(body, 1)) {
40866
41111
  const config2 = decodeModelConfig(field.payload);
40867
41112
  if (config2)
40868
41113
  configs.push(config2);
40869
41114
  }
40870
- log(`[Devin] GetCliModelConfigs: ${configs.length} configs`);
40871
41115
  return configs;
40872
41116
  }
40873
41117
  async function fetchDevinAllowedUids(apiKey) {
@@ -40923,7 +41167,246 @@ var init_devin_models = __esm(() => {
40923
41167
  ROSTER_TTL_MS = 5 * 60 * 1000;
40924
41168
  });
40925
41169
 
41170
+ // src/providers/model-resolvers/types.ts
41171
+ function nonEmpty(value) {
41172
+ const trimmed2 = value?.trim();
41173
+ return trimmed2 ? trimmed2 : undefined;
41174
+ }
41175
+ function groupKeyOf(entry) {
41176
+ return nonEmpty(entry.groupLabel) ?? nonEmpty(entry.family) ?? entry.wireId;
41177
+ }
41178
+ function offerIsLive(offer, now = Date.now()) {
41179
+ if (!offer)
41180
+ return false;
41181
+ if (offer.expiresAt === undefined)
41182
+ return true;
41183
+ return offer.expiresAt * 1000 > now;
41184
+ }
41185
+
41186
+ // src/providers/model-resolvers/devin.ts
41187
+ var exports_devin = {};
41188
+ __export(exports_devin, {
41189
+ devinRosterEntry: () => devinRosterEntry,
41190
+ devinHasSpeedPremium: () => devinHasSpeedPremium,
41191
+ devinEffortOf: () => devinEffortOf,
41192
+ DevinModelResolver: () => DevinModelResolver
41193
+ });
41194
+ function toEffortLevel(label) {
41195
+ const normalised = label?.toLowerCase().replace(/[^a-z]/g, "");
41196
+ if (!normalised)
41197
+ return;
41198
+ if (normalised === "nothinking")
41199
+ return "none";
41200
+ return isEffortLevel(normalised) ? normalised : undefined;
41201
+ }
41202
+ function effortFromUid(uid) {
41203
+ for (const part of uid.toLowerCase().split("-").reverse()) {
41204
+ if (isEffortLevel(part))
41205
+ return part;
41206
+ if (!SPEED_SUFFIXES.includes(part) && part !== "1m")
41207
+ break;
41208
+ }
41209
+ return;
41210
+ }
41211
+ function devinEffortOf(config2) {
41212
+ const axis = config2.axes.find((a) => EFFORT_AXIS_KEYS.includes(a.key.toLowerCase()));
41213
+ return toEffortLevel(axis?.label) ?? effortFromUid(config2.uid);
41214
+ }
41215
+ function devinHasSpeedPremium(config2) {
41216
+ const axis = config2.axes.find((a) => a.key.toLowerCase() === SPEED_AXIS_KEY);
41217
+ if (axis)
41218
+ return axis.enabled;
41219
+ return SPEED_SUFFIXES.some((suffix) => config2.uid.toLowerCase().endsWith(`-${suffix}`));
41220
+ }
41221
+ function namesEffortTier(id) {
41222
+ return id.toLowerCase().split("-").some((part) => isEffortLevel(part));
41223
+ }
41224
+ function modifiersOf(config2) {
41225
+ const parts = config2.uid.toLowerCase().split("-");
41226
+ const named = SPEED_SUFFIXES.filter((suffix) => parts.includes(suffix));
41227
+ if (named.length > 0)
41228
+ return named;
41229
+ return devinHasSpeedPremium(config2) ? ["premium"] : [];
41230
+ }
41231
+ function devinRosterEntry(config2) {
41232
+ return {
41233
+ wireId: config2.uid,
41234
+ displayName: config2.displayName,
41235
+ contextWindow: config2.contextWindow,
41236
+ groupLabel: config2.groupLabel,
41237
+ family: config2.family,
41238
+ costFactor: config2.creditMultiplier,
41239
+ costTier: config2.costTier,
41240
+ isFamilyDefault: config2.isFamilyDefault,
41241
+ isRecommended: config2.isRecommended,
41242
+ axes: config2.axes,
41243
+ offer: config2.promo ? { kind: "promo", expiresAt: config2.promo.expiresAt } : undefined
41244
+ };
41245
+ }
41246
+ function asConfig(entry) {
41247
+ return {
41248
+ uid: entry.wireId,
41249
+ displayName: entry.displayName ?? entry.wireId,
41250
+ contextWindow: entry.contextWindow ?? 0,
41251
+ maxOutput: 0,
41252
+ family: entry.family ?? "",
41253
+ groupLabel: entry.groupLabel,
41254
+ axes: entry.axes ?? [],
41255
+ creditMultiplier: entry.costFactor,
41256
+ costTier: entry.costTier,
41257
+ isFamilyDefault: entry.isFamilyDefault ?? false,
41258
+ isRecommended: entry.isRecommended ?? false
41259
+ };
41260
+ }
41261
+ function byCost(a, b) {
41262
+ const tier = (a.costTier ?? Number.MAX_SAFE_INTEGER) - (b.costTier ?? Number.MAX_SAFE_INTEGER);
41263
+ if (tier !== 0)
41264
+ return tier;
41265
+ const cost = (a.costFactor ?? Number.MAX_SAFE_INTEGER) - (b.costFactor ?? Number.MAX_SAFE_INTEGER);
41266
+ if (cost !== 0)
41267
+ return cost;
41268
+ const length = a.wireId.length - b.wireId.length;
41269
+ return length !== 0 ? length : a.wireId.localeCompare(b.wireId);
41270
+ }
41271
+ function defaultOf(group) {
41272
+ const declared = group.find((entry) => entry.isFamilyDefault);
41273
+ if (declared)
41274
+ return declared;
41275
+ const plain = group.filter((entry) => !devinHasSpeedPremium(asConfig(entry)));
41276
+ const pool = plain.length > 0 ? plain : group;
41277
+ const tierless = pool.filter((entry) => !namesEffortTier(entry.wireId));
41278
+ return [...tierless.length > 0 ? tierless : pool].sort(byCost)[0];
41279
+ }
41280
+ function keyOf(entry) {
41281
+ return `${groupKeyOf(entry)}\x00${entry.contextWindow ?? 0}`;
41282
+ }
41283
+ function formatWindow(tokens) {
41284
+ return tokens >= 1e6 ? `${Math.round(tokens / 1e5) / 10}M`.replace(".0M", "M") : `${Math.round(tokens / 1000)}K`;
41285
+ }
41286
+
41287
+ class DevinModelResolver {
41288
+ provider = "devin";
41289
+ collapse(roster) {
41290
+ const groups = new Map;
41291
+ for (const entry of roster) {
41292
+ const key = keyOf(entry);
41293
+ const bucket = groups.get(key);
41294
+ if (bucket)
41295
+ bucket.push(entry);
41296
+ else
41297
+ groups.set(key, [entry]);
41298
+ }
41299
+ const windowsPerLabel = new Map;
41300
+ for (const entry of roster) {
41301
+ const label = groupKeyOf(entry);
41302
+ const seen = windowsPerLabel.get(label) ?? new Set;
41303
+ seen.add(entry.contextWindow ?? 0);
41304
+ windowsPerLabel.set(label, seen);
41305
+ }
41306
+ const choices = [];
41307
+ for (const group of groups.values()) {
41308
+ const chosen = defaultOf(group);
41309
+ const label = groupKeyOf(chosen);
41310
+ const ambiguous = (windowsPerLabel.get(label)?.size ?? 1) > 1;
41311
+ const window2 = chosen.contextWindow ?? 0;
41312
+ const variants = group.map((entry) => {
41313
+ const config2 = asConfig(entry);
41314
+ return {
41315
+ wireId: entry.wireId,
41316
+ effort: devinEffortOf(config2),
41317
+ modifiers: modifiersOf(config2),
41318
+ costFactor: entry.costFactor
41319
+ };
41320
+ });
41321
+ choices.push({
41322
+ id: chosen.wireId,
41323
+ displayName: ambiguous && window2 > 0 ? `${label} (${formatWindow(window2)})` : label,
41324
+ contextWindow: chosen.contextWindow,
41325
+ variants,
41326
+ costFactor: chosen.costFactor,
41327
+ offer: chosen.offer,
41328
+ isRecommended: chosen.isRecommended
41329
+ });
41330
+ }
41331
+ return choices;
41332
+ }
41333
+ expand(selection, roster, ctx) {
41334
+ const requested = selection.trim();
41335
+ if (!requested || roster.length === 0)
41336
+ return requested || selection;
41337
+ const groups = new Map;
41338
+ for (const entry of roster) {
41339
+ const key = keyOf(entry);
41340
+ const bucket = groups.get(key);
41341
+ if (bucket)
41342
+ bucket.push(entry);
41343
+ else
41344
+ groups.set(key, [entry]);
41345
+ }
41346
+ const lower = requested.toLowerCase();
41347
+ const exact = roster.find((entry) => entry.wireId.toLowerCase() === lower);
41348
+ if (exact) {
41349
+ if (!ctx.effort)
41350
+ return exact.wireId;
41351
+ const group = groups.get(keyOf(exact));
41352
+ if (exact.wireId === defaultOf(group).wireId)
41353
+ return pickForEffort(group, ctx.effort).wireId;
41354
+ if (namesEffortTier(exact.wireId))
41355
+ return exact.wireId;
41356
+ return pickForEffort(group, ctx.effort).wireId;
41357
+ }
41358
+ const named = roster.filter((entry) => {
41359
+ const label = nonEmpty(entry.groupLabel)?.toLowerCase();
41360
+ const family = nonEmpty(entry.family)?.toLowerCase();
41361
+ return label === lower || family === lower;
41362
+ });
41363
+ const pool = named.length > 0 ? named : roster.filter((entry) => entry.wireId.toLowerCase().startsWith(`${lower}-`));
41364
+ if (pool.length === 0)
41365
+ return requested;
41366
+ if (named.length === 0 && new Set(pool.map(keyOf)).size > 1)
41367
+ return requested;
41368
+ const chosen = pool.filter((entry) => entry.isFamilyDefault).sort(byCost)[0] ?? pool.slice().sort(byCost)[0];
41369
+ return pickForEffort(groups.get(keyOf(chosen)), ctx.effort).wireId;
41370
+ }
41371
+ }
41372
+ function pickForEffort(group, effort) {
41373
+ if (!effort)
41374
+ return defaultOf(group);
41375
+ const plain = group.filter((entry) => !devinHasSpeedPremium(asConfig(entry)));
41376
+ const pool = plain.length > 0 ? plain : group;
41377
+ const tiered = pool.map((entry) => ({ entry, effort: devinEffortOf(asConfig(entry)) })).filter((row) => row.effort !== undefined);
41378
+ if (tiered.length === 0)
41379
+ return defaultOf(group);
41380
+ const target = EFFORT_LEVELS.indexOf(effort);
41381
+ const ranked = tiered.slice().sort((a, b) => {
41382
+ const distanceA = Math.abs(EFFORT_LEVELS.indexOf(a.effort) - target);
41383
+ const distanceB = Math.abs(EFFORT_LEVELS.indexOf(b.effort) - target);
41384
+ if (distanceA !== distanceB)
41385
+ return distanceA - distanceB;
41386
+ const levelA = EFFORT_LEVELS.indexOf(a.effort);
41387
+ const levelB = EFFORT_LEVELS.indexOf(b.effort);
41388
+ if (levelA !== levelB)
41389
+ return levelB - levelA;
41390
+ const defaultA = a.entry.isFamilyDefault ? 0 : 1;
41391
+ const defaultB = b.entry.isFamilyDefault ? 0 : 1;
41392
+ if (defaultA !== defaultB)
41393
+ return defaultA - defaultB;
41394
+ return byCost(a.entry, b.entry);
41395
+ });
41396
+ return ranked[0].entry;
41397
+ }
41398
+ var EFFORT_AXIS_KEYS, SPEED_AXIS_KEY = "fast mode", SPEED_SUFFIXES;
41399
+ var init_devin = __esm(() => {
41400
+ init_base_api_format();
41401
+ EFFORT_AXIS_KEYS = ["effort", "reasoning effort"];
41402
+ SPEED_SUFFIXES = ["fast", "priority"];
41403
+ });
41404
+
40926
41405
  // src/providers/model-discovery.ts
41406
+ function toRosterEntry(model) {
41407
+ const { id, ...rest } = model;
41408
+ return { wireId: id, ...rest };
41409
+ }
40927
41410
  function resolveBaseUrl(catalogName) {
40928
41411
  const def = getProviderByName(catalogName);
40929
41412
  if (!def)
@@ -40990,26 +41473,46 @@ async function discoverProviderModels(providerName) {
40990
41473
  log(`[model-discovery:${providerName}] no models for this subscription`);
40991
41474
  return [];
40992
41475
  }
40993
- const models2 = served.map((model) => ({
40994
- id: model.uid,
40995
- displayName: model.displayName,
40996
- contextWindow: model.contextWindow
40997
- }));
41476
+ const { devinRosterEntry: devinRosterEntry2 } = await Promise.resolve().then(() => (init_devin(), exports_devin));
41477
+ const models2 = served.map((model) => {
41478
+ const { wireId, ...rest } = devinRosterEntry2(model);
41479
+ return { id: wireId, ...rest };
41480
+ });
40998
41481
  log(`[model-discovery:${providerName}] discovered ${models2.length} models`);
40999
41482
  _cache.set(providerName, { models: models2, expiresAt: Date.now() + CACHE_TTL_MS });
41000
41483
  return models2;
41001
41484
  }
41485
+ if (descriptor.format === "ollama-tags") {
41486
+ const { fetchOllamaModels: fetchOllamaModels2 } = await Promise.resolve().then(() => exports_ollama_discovery);
41487
+ const installed = await fetchOllamaModels2({ enrichCapabilities: false });
41488
+ if (installed.length === 0)
41489
+ return [];
41490
+ const models2 = installed.map((model) => ({
41491
+ id: model.name,
41492
+ displayName: model.name,
41493
+ supportsTools: model.supportsTools
41494
+ }));
41495
+ log(`[model-discovery:${providerName}] discovered ${models2.length} local models`);
41496
+ _cache.set(providerName, { models: models2, expiresAt: Date.now() + CACHE_TTL_MS });
41497
+ return models2;
41498
+ }
41002
41499
  const baseUrl = resolveBaseUrl(providerName);
41003
41500
  if (!baseUrl)
41004
41501
  return [];
41005
41502
  const endpoint = `${baseUrl}${descriptor.path}`;
41006
41503
  let headers = {};
41007
- try {
41008
- const auth = await credentials.getRequestAuth(providerName, { model: "" });
41009
- headers = { ...auth.headers };
41010
- } catch (e) {
41011
- log(`[model-discovery:${providerName}] no credentials, skipping: ${e?.message}`);
41012
- return [];
41504
+ if (def.isLocal) {
41505
+ const key = def.apiKeyEnvVar ? process.env[def.apiKeyEnvVar] : undefined;
41506
+ if (key)
41507
+ headers = { Authorization: `Bearer ${key}` };
41508
+ } else {
41509
+ try {
41510
+ const auth = await credentials.getRequestAuth(providerName, { model: "" });
41511
+ headers = { ...auth.headers };
41512
+ } catch (e) {
41513
+ log(`[model-discovery:${providerName}] no credentials, skipping: ${e?.message}`);
41514
+ return [];
41515
+ }
41013
41516
  }
41014
41517
  let response;
41015
41518
  try {
@@ -41789,166 +42292,6 @@ var init_custom_endpoints_loader = __esm(() => {
41789
42292
  init_openai();
41790
42293
  });
41791
42294
 
41792
- // src/providers/catalog-client.ts
41793
- function getCatalogEntries() {
41794
- if (_memCache)
41795
- return _memCache;
41796
- const cache2 = readAllModelsCache();
41797
- if (!cache2)
41798
- return null;
41799
- if (cache2.entries.length > 0) {
41800
- _memCache = cache2.entries;
41801
- return _memCache;
41802
- }
41803
- if (cache2.models.length > 0) {
41804
- _memCache = cache2.models.map((m) => ({
41805
- modelId: m.id.includes("/") ? m.id.split("/").slice(1).join("/") : m.id,
41806
- aliases: [],
41807
- sources: { "openrouter-api": { externalId: m.id } }
41808
- }));
41809
- return _memCache;
41810
- }
41811
- return null;
41812
- }
41813
- function isCatalogWarm() {
41814
- return _memCache !== null && _memCache.length > 0;
41815
- }
41816
- function externalIdFor(entry, provider) {
41817
- const agg = entry.aggregators?.find((a) => a.provider === provider);
41818
- if (agg?.externalId)
41819
- return agg.externalId;
41820
- if (provider !== "openrouter")
41821
- return null;
41822
- const orSource = entry.sources["openrouter-api"];
41823
- if (orSource?.externalId)
41824
- return orSource.externalId;
41825
- for (const src of Object.values(entry.sources)) {
41826
- if (src.externalId.includes("/"))
41827
- return src.externalId;
41828
- }
41829
- return null;
41830
- }
41831
- function resolveExternalId(userInput, provider) {
41832
- const entries = getCatalogEntries();
41833
- if (userInput.includes("/")) {
41834
- if (entries) {
41835
- for (const entry of entries) {
41836
- for (const src of Object.values(entry.sources)) {
41837
- if (src.externalId === userInput)
41838
- return userInput;
41839
- }
41840
- }
41841
- }
41842
- return userInput;
41843
- }
41844
- if (!entries)
41845
- return null;
41846
- const byModelId = entries.find((e) => e.modelId === userInput);
41847
- if (byModelId)
41848
- return externalIdFor(byModelId, provider);
41849
- const byAlias = entries.find((e) => e.aliases.includes(userInput));
41850
- if (byAlias) {
41851
- const id = externalIdFor(byAlias, provider);
41852
- if (id)
41853
- return id;
41854
- }
41855
- for (const entry of entries) {
41856
- for (const src of Object.values(entry.sources)) {
41857
- if (src.externalId === userInput) {
41858
- const id = externalIdFor(entry, provider);
41859
- if (id)
41860
- return id;
41861
- }
41862
- }
41863
- }
41864
- const suffix = `/${userInput}`;
41865
- for (const entry of entries) {
41866
- const id = externalIdFor(entry, provider);
41867
- if (id?.endsWith(suffix))
41868
- return id;
41869
- }
41870
- const lowerSuffix = `/${userInput.toLowerCase()}`;
41871
- for (const entry of entries) {
41872
- const id = externalIdFor(entry, provider);
41873
- if (id?.toLowerCase().endsWith(lowerSuffix))
41874
- return id;
41875
- }
41876
- return null;
41877
- }
41878
- function resolveModelNameSync(userInput, targetProvider) {
41879
- if (targetProvider !== "openrouter" && userInput.includes("/")) {
41880
- return { resolvedId: userInput, wasResolved: false, sourceLabel: "passthrough" };
41881
- }
41882
- const resolved = resolveExternalId(userInput, targetProvider);
41883
- if (!resolved || resolved === userInput) {
41884
- return { resolvedId: userInput, wasResolved: false, sourceLabel: "passthrough" };
41885
- }
41886
- return { resolvedId: resolved, wasResolved: true, sourceLabel: `${targetProvider} catalog` };
41887
- }
41888
- function logResolution(userInput, result, quiet = false) {
41889
- if (result.wasResolved && !quiet) {
41890
- process.stderr.write(`[Model] Resolved "${userInput}" \u2192 "${result.resolvedId}" (${result.sourceLabel})
41891
- `);
41892
- }
41893
- }
41894
- async function refreshCatalog(timeoutMs) {
41895
- let response;
41896
- try {
41897
- response = await fetch(FIREBASE_CATALOG_URL, { signal: AbortSignal.timeout(timeoutMs) });
41898
- } catch (err) {
41899
- const name = err?.name;
41900
- const reason = name === "TimeoutError" || name === "AbortError" ? "timeout" : "network";
41901
- return { kind: "fetch_failed", reason };
41902
- }
41903
- if (!response.ok)
41904
- return { kind: "fetch_failed", reason: "http_error" };
41905
- let data;
41906
- try {
41907
- data = await response.json();
41908
- } catch {
41909
- return { kind: "fetch_failed", reason: "network" };
41910
- }
41911
- if (!Array.isArray(data.models) || data.models.length === 0) {
41912
- return { kind: "fetch_failed", reason: "empty" };
41913
- }
41914
- const backwardCompatModels = [];
41915
- for (const entry of data.models) {
41916
- const id = externalIdFor(entry, "openrouter");
41917
- if (id)
41918
- backwardCompatModels.push({ id });
41919
- }
41920
- _memCache = data.models;
41921
- writeAllModelsCache({ entries: data.models, models: backwardCompatModels });
41922
- _warmPromise = Promise.resolve();
41923
- return { kind: "refreshed", modelCount: data.models.length };
41924
- }
41925
- async function warmCatalog() {
41926
- if (!_warmPromise) {
41927
- _warmPromise = refreshCatalog(8000).then(() => {
41928
- return;
41929
- });
41930
- }
41931
- await _warmPromise;
41932
- }
41933
- async function ensureCatalogReady(timeoutMs = 5000) {
41934
- if (isCatalogWarm())
41935
- return;
41936
- if (!_warmPromise) {
41937
- _warmPromise = refreshCatalog(8000).then(() => {
41938
- return;
41939
- });
41940
- }
41941
- await Promise.race([
41942
- _warmPromise,
41943
- new Promise((resolve2) => setTimeout(resolve2, timeoutMs))
41944
- ]);
41945
- }
41946
- var FIREBASE_CATALOG_URL, _memCache = null, _warmPromise = null;
41947
- var init_catalog_client = __esm(() => {
41948
- init_all_models_cache();
41949
- FIREBASE_CATALOG_URL = process.env.CLAUDISH_CATALOG_URL ?? process.env.FIREBASE_CATALOG_URL ?? "https://us-central1-claudish-6da10.cloudfunctions.net/queryModels?status=active&catalog=slim&limit=1000";
41950
- });
41951
-
41952
42295
  // src/providers/provider-registry.ts
41953
42296
  function resolveBaseUrl2(envVar, fallbackEnvVars, staticDefault) {
41954
42297
  for (const v of [envVar, ...fallbackEnvVars]) {
@@ -42447,8 +42790,8 @@ var init_routing_rules = __esm(() => {
42447
42790
  init_authority();
42448
42791
  init_profile_config();
42449
42792
  init_auto_route();
42450
- init_default_routing_rules();
42451
42793
  init_catalog_client();
42794
+ init_default_routing_rules();
42452
42795
  init_model_parser();
42453
42796
  init_model_parser();
42454
42797
  init_routing_hints();
@@ -42857,8 +43200,8 @@ var CATALOG_WARM_TIMEOUT_MS = 5000, parentRoutingContextReady = false;
42857
43200
  var init_prehydrate = __esm(() => {
42858
43201
  init_profile_config();
42859
43202
  init_auto_route();
42860
- init_custom_endpoints_loader();
42861
43203
  init_catalog_client();
43204
+ init_custom_endpoints_loader();
42862
43205
  init_model_parser();
42863
43206
  init_onepassword();
42864
43207
  init_provider_resolver();
@@ -46237,8 +46580,8 @@ Be direct. Limit your response to 300-500 words.`, COLLECTOR_SYSTEM_PROMPT = `Yo
46237
46580
  Be concise. Do not attribute advice to specific models.`;
46238
46581
  var init_native_handler_advisor = __esm(() => {
46239
46582
  init_logger();
46240
- init_catalog_query();
46241
46583
  init_catalog_client();
46584
+ init_catalog_query();
46242
46585
  init_model_parser();
46243
46586
  advisorToolUseIds = new Set;
46244
46587
  });
@@ -46989,56 +47332,44 @@ var init_api_key_provenance = __esm(() => {
46989
47332
  import_dotenv = __toESM(require_main(), 1);
46990
47333
  });
46991
47334
 
46992
- // src/providers/devin/model-id-resolver.ts
46993
- function parseDevinUidTier(uid) {
46994
- let base = uid.trim();
46995
- let fast = false;
46996
- if (base.toLowerCase().endsWith(FAST_SUFFIX)) {
46997
- fast = true;
46998
- base = base.slice(0, -FAST_SUFFIX.length);
46999
- }
47000
- const match2 = base.match(TIER_SUFFIX_RE);
47001
- const candidate = match2?.[1]?.toLowerCase();
47002
- return { tier: isEffortLevel(candidate) ? candidate : null, fast };
47335
+ // src/providers/model-resolvers/registry.ts
47336
+ function getModelResolver(provider) {
47337
+ return BY_PROVIDER.get(provider);
47338
+ }
47339
+ function collapseRoster(provider, roster) {
47340
+ const resolver = getModelResolver(provider);
47341
+ if (resolver)
47342
+ return resolver.collapse(roster);
47343
+ return roster.map((entry) => ({
47344
+ id: entry.wireId,
47345
+ displayName: entry.displayName ?? entry.wireId,
47346
+ contextWindow: entry.contextWindow,
47347
+ variants: [{ wireId: entry.wireId, modifiers: [] }],
47348
+ costFactor: entry.costFactor,
47349
+ offer: entry.offer,
47350
+ isRecommended: entry.isRecommended
47351
+ }));
47003
47352
  }
47004
- function effortIndex(level) {
47005
- return EFFORT_LEVELS.indexOf(level);
47353
+ function expandSelection(provider, selection, roster, ctx = {}) {
47354
+ return getModelResolver(provider)?.expand(selection, roster, ctx) ?? selection;
47006
47355
  }
47356
+ var RESOLVERS, BY_PROVIDER;
47357
+ var init_registry2 = __esm(() => {
47358
+ init_devin();
47359
+ RESOLVERS = [new DevinModelResolver];
47360
+ BY_PROVIDER = new Map(RESOLVERS.map((resolver) => [resolver.provider, resolver]));
47361
+ });
47362
+
47363
+ // src/providers/devin/model-id-resolver.ts
47007
47364
  function resolveDevinModelUid(requested, effort, served) {
47008
- const req = requested.trim();
47009
- if (!req || served.length === 0)
47010
- return req || requested;
47011
- const lower = req.toLowerCase();
47012
- const exact = served.find((model) => model.uid.toLowerCase() === lower);
47013
- if (exact)
47014
- return exact.uid;
47015
- const prefix = `${lower}-`;
47016
- const candidates = served.filter((model) => model.family.toLowerCase() === lower || model.uid.toLowerCase().startsWith(prefix));
47017
- if (candidates.length === 0)
47018
- return req;
47019
- const nonFast = candidates.filter((model) => !parseDevinUidTier(model.uid).fast);
47020
- const pool = nonFast.length > 0 ? nonFast : candidates;
47021
- if (pool.length === 1)
47022
- return pool[0].uid;
47023
- const tiered = pool.map((model) => ({ model, tier: parseDevinUidTier(model.uid).tier })).filter((entry) => entry.tier !== null);
47024
- if (tiered.length === 0)
47025
- return pool[0].uid;
47026
- const target = effort ? effortIndex(effort) : EFFORT_LEVELS.length - 1;
47027
- let best = tiered[0];
47028
- let bestDistance = Number.POSITIVE_INFINITY;
47029
- for (const entry of tiered) {
47030
- const distance = Math.abs(effortIndex(entry.tier) - target);
47031
- if (distance < bestDistance || distance === bestDistance && effortIndex(entry.tier) > effortIndex(best.tier)) {
47032
- best = entry;
47033
- bestDistance = distance;
47034
- }
47035
- }
47036
- return best.model.uid;
47365
+ const trimmed2 = requested.trim();
47366
+ if (!trimmed2 || served.length === 0)
47367
+ return trimmed2 || requested;
47368
+ return expandSelection("devin", trimmed2, served.map(devinRosterEntry), { effort });
47037
47369
  }
47038
- var FAST_SUFFIX = "-fast", TIER_SUFFIX_RE;
47039
47370
  var init_model_id_resolver = __esm(() => {
47040
- init_base_api_format();
47041
- TIER_SUFFIX_RE = new RegExp(`-(${[...EFFORT_LEVELS].sort((a, b) => b.length - a.length).join("|")})$`, "i");
47371
+ init_devin();
47372
+ init_registry2();
47042
47373
  });
47043
47374
 
47044
47375
  // src/providers/transport/devin.ts
@@ -47134,7 +47465,7 @@ class DevinProviderTransport {
47134
47465
  }
47135
47466
  }
47136
47467
  var CHAT_PATH = "/exa.api_server_pb.ApiServerService/GetChatMessage", CHAT_CONTENT_TYPE = "application/connect+proto";
47137
- var init_devin = __esm(() => {
47468
+ var init_devin2 = __esm(() => {
47138
47469
  init_authority();
47139
47470
  init_devin_credential();
47140
47471
  init_logger();
@@ -47352,7 +47683,7 @@ var init_provider_profiles = __esm(() => {
47352
47683
  init_runtime_providers();
47353
47684
  init_anthropic_compat();
47354
47685
  init_antigravity();
47355
- init_devin();
47686
+ init_devin2();
47356
47687
  init_gemini_apikey();
47357
47688
  init_litellm();
47358
47689
  init_ollamacloud();
@@ -48812,8 +49143,8 @@ var init_proxy_server = __esm(() => {
48812
49143
  init_model_loader();
48813
49144
  init_profile_config();
48814
49145
  init_api_key_map();
48815
- init_custom_endpoints_loader();
48816
49146
  init_catalog_client();
49147
+ init_custom_endpoints_loader();
48817
49148
  init_model_parser();
48818
49149
  init_provider_profiles();
48819
49150
  init_provider_registry();
@@ -64574,28 +64905,52 @@ async function pickModelFromList(provider, displayName, tierName, models) {
64574
64905
  });
64575
64906
  return selected === CUSTOM_VALUE ? null : selected;
64576
64907
  }
64908
+ function describeOffer(offer) {
64909
+ if (!offerIsLive(offer) || offer?.kind !== "promo")
64910
+ return;
64911
+ if (offer.expiresAt === undefined)
64912
+ return "FREE";
64913
+ const until = new Date(offer.expiresAt * 1000).toLocaleDateString("en-US", {
64914
+ month: "short",
64915
+ day: "numeric"
64916
+ });
64917
+ return `FREE until ${until}`;
64918
+ }
64577
64919
  async function buildDiscoveredModelRows(provider, displayName, catalog) {
64578
64920
  const discovered = rankDiscoveredModels(await discoverProviderModels(provider)).filter((m) => isChatCapable(m.id));
64579
64921
  if (discovered.length === 0)
64580
64922
  return [];
64581
64923
  const subscription = isSubscriptionProvider(provider);
64582
- const pricingById = subscription ? new Map : new Map((await loadModelsForPickerProvider(provider, catalog)).map((m) => [
64924
+ const local = getProviderByName(provider)?.isLocal === true;
64925
+ const flatRate = subscription || local;
64926
+ const pricingById = flatRate ? new Map : new Map((await loadModelsForPickerProvider(provider, catalog)).map((m) => [
64583
64927
  m.id.toLowerCase(),
64584
64928
  m.pricing
64585
64929
  ]));
64586
- const rows = discovered.map((m) => {
64587
- const contextLength = resolveDiscoveredContextLength(m);
64930
+ const choices = collapseRoster(provider, discovered.map(toRosterEntry));
64931
+ const discoveredById = new Map(discovered.map((m) => [m.id, m]));
64932
+ const rows = choices.map((c) => {
64933
+ const source = discoveredById.get(c.id);
64934
+ const contextLength = source ? resolveDiscoveredContextLength(source) : c.contextWindow ?? 0;
64935
+ const parts = [c.displayName];
64936
+ if (contextLength)
64937
+ parts.push(`${Math.round(contextLength / 1024)}K context`);
64938
+ if (subscription && c.costFactor !== undefined)
64939
+ parts.push(`\xD7${c.costFactor}`);
64940
+ const promo = describeOffer(c.offer);
64941
+ if (promo)
64942
+ parts.push(promo);
64588
64943
  return {
64589
- id: m.id,
64590
- name: m.displayName || m.id,
64591
- description: contextLength ? `${m.displayName ?? m.id} \xB7 ${Math.round(contextLength / 1024)}K context` : m.displayName ?? m.id,
64944
+ id: c.id,
64945
+ name: c.displayName,
64946
+ description: parts.join(" \xB7 "),
64592
64947
  provider: displayName,
64593
- releaseDate: resolveDiscoveredReleaseDate(m),
64594
- pricing: subscription ? SUBSCRIPTION_PRICING : pricingById.get(m.id.toLowerCase()),
64948
+ releaseDate: source ? resolveDiscoveredReleaseDate(source) : undefined,
64949
+ pricing: subscription ? SUBSCRIPTION_PRICING : pricingById.get(c.id.toLowerCase()),
64595
64950
  context: formatContextLength(contextLength),
64596
64951
  contextLength,
64597
- supportsTools: lookupModelCapabilities(m.id)?.supportsTools ?? true,
64598
- isFree: subscription,
64952
+ supportsTools: lookupModelCapabilities(c.id)?.supportsTools ?? source?.supportsTools ?? true,
64953
+ isFree: flatRate,
64599
64954
  source: displayName
64600
64955
  };
64601
64956
  });
@@ -64613,23 +64968,6 @@ async function selectModelFromProvider(provider, tierName, recommendedModels, _f
64613
64968
  return picked;
64614
64969
  }
64615
64970
  }
64616
- if (provider === "ollama") {
64617
- const ollamaModels = await fetchOllamaModels({ enrichCapabilities: false });
64618
- const chatModels = sortModelsNewestFirst(ollamaModels.map((m) => ({
64619
- id: m.name,
64620
- name: m.name,
64621
- description: m.description,
64622
- provider: displayName,
64623
- supportsTools: m.supportsTools,
64624
- isFree: true,
64625
- source: displayName
64626
- })));
64627
- if (chatModels.length > 0) {
64628
- const picked = await pickModelFromList(provider, displayName, tierName, chatModels);
64629
- if (picked)
64630
- return picked;
64631
- }
64632
- }
64633
64971
  if (isUserDeployedProvider(provider)) {
64634
64972
  const modelName = await dist_default5({
64635
64973
  message: tierName === "interactive session" ? `Enter ${displayName} model name:` : `Enter ${displayName} model name for ${tierName}:`,
@@ -64793,6 +65131,7 @@ var init_model_selector = __esm(() => {
64793
65131
  init_model_loader();
64794
65132
  init_model_catalog2();
64795
65133
  init_model_discovery();
65134
+ init_registry2();
64796
65135
  init_provider_definitions();
64797
65136
  init_probe_discovery();
64798
65137
  pickerProviderToFirebaseSlug = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.43.0",
3
+ "version": "7.44.0",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,10 +60,10 @@
60
60
  "ai"
61
61
  ],
62
62
  "optionalDependencies": {
63
- "@claudish/magmux-darwin-arm64": "7.43.0",
64
- "@claudish/magmux-darwin-x64": "7.43.0",
65
- "@claudish/magmux-linux-arm64": "7.43.0",
66
- "@claudish/magmux-linux-x64": "7.43.0"
63
+ "@claudish/magmux-darwin-arm64": "7.44.0",
64
+ "@claudish/magmux-darwin-x64": "7.44.0",
65
+ "@claudish/magmux-linux-arm64": "7.44.0",
66
+ "@claudish/magmux-linux-x64": "7.44.0"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",