failsafe-llm-model-resolver 1.0.0 → 1.0.2

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/index.js +26 -4
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -46,7 +46,15 @@ const PREFERENCE = {
46
46
  // Prefer flagship grok-*, skip fast / mini / code-fast variants when possible
47
47
  xai: {
48
48
  include: /^grok-/i,
49
- exclude: /fast|mini|lite|code-fast/i,
49
+ // "non-reasoning" is intentionally its own term here, not "reasoning" -
50
+ // xAI ships paired variants like grok-4.20-0309-reasoning and
51
+ // grok-4.20-0309-non-reasoning. Excluding bare /reasoning/ would match
52
+ // BOTH strings (non-reasoning contains "reasoning" as a substring) and
53
+ // throw away the good one along with the bad one. non-?reasoning also
54
+ // catches an unhyphenated "nonreasoning" form if xAI ever ships one.
55
+ // Tagging/classification work benefits from the reasoning variant, so
56
+ // steer away from the faster-but-shallower non-reasoning one by default.
57
+ exclude: /fast|mini|lite|code-fast|non-?reasoning/i,
50
58
  },
51
59
  // Prefer sonnet/opus over haiku; newest first already gives us the latest
52
60
  anthropic: {
@@ -104,14 +112,28 @@ async function fetchGeminiModels(apiKey) {
104
112
  // Gemini uses query-string key and a different envelope
105
113
  const url = `https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(apiKey)}&pageSize=1000`;
106
114
  const json = await httpGet(url);
107
- // Shape: { models: [ { name: "models/gemini-…", … } ] }
108
- // The ID used in generateContent is the part after "models/"
115
+ // Shape: { models: [ { name: "models/gemini-…", supportedGenerationMethods: [...], … } ] }
116
+ //
117
+ // BUGFIX (was throwing ReferenceError on every real call): the previous
118
+ // version called .filter() AFTER .map() had already reduced each model
119
+ // object down to a bare id string - by the time the filter ran, the only
120
+ // thing it had to inspect was `id` (a string), yet it tried to read
121
+ // `m.supportedGenerationMethods` on a variable `m` that was never in scope
122
+ // in that callback. This wasn't just a typo to rename; the whole ordering
123
+ // was backwards. The fix: filter on the full model object FIRST (while
124
+ // supportedGenerationMethods is still available), THEN map down to the id
125
+ // string. No IIFE, no scope trick needed - the property we need is simply
126
+ // read before it's thrown away.
109
127
  const list = (json.models || [])
128
+ .filter(m => {
129
+ const methods = m.supportedGenerationMethods || m.supported_actions || [];
130
+ return methods.some(x => /generateContent/i.test(x));
131
+ })
110
132
  .map(m => {
111
133
  const name = m.name || '';
134
+ // The ID used in generateContent is the part after "models/"
112
135
  return name.startsWith('models/') ? name.slice(7) : name;
113
136
  })
114
- .filter(id => id && /generateContent/i.test((m => (m.supportedGenerationMethods || m.supported_actions || []).join(','))(m) || 'generateContent'))
115
137
  .filter(Boolean);
116
138
  return list;
117
139
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "failsafe-llm-model-resolver",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Self-healing, failsafe resolver for the current frontier model across xAI, Anthropic, Gemini, and OpenRouter. Live /models fetch + preference rules + env fallbacks so a network blip never kills a batch job.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",