CrispStrobe commited on
Commit
e9acff4
·
1 Parent(s): d699da8

feat: include eu-endpoint tagging in OpenRouter data

Browse files
data/providers.json CHANGED
The diff for this file is too large to render. See raw diff
 
scripts/providers/openrouter.js CHANGED
@@ -12,6 +12,7 @@ loadEnv();
12
  const { getJson } = require('../fetch-utils');
13
 
14
  const API_URL = 'https://openrouter.ai/api/v1/models';
 
15
 
16
  // OpenRouter stores per-token prices; multiply by 1e6 to get per-1M price.
17
  const toPerMillion = (val) => (val ? parseFloat(val) * 1_000_000 : 0);
@@ -65,10 +66,30 @@ async function fetchOpenRouter() {
65
  };
66
  if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`;
67
 
68
- const data = await getJson(API_URL, { headers });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  const models = [];
70
 
71
- for (const model of data.data || []) {
72
  const pricing = model.pricing || {};
73
  const inputPrice = toPerMillion(pricing.prompt);
74
  const outputPrice = toPerMillion(pricing.completion);
@@ -86,6 +107,11 @@ async function fetchOpenRouter() {
86
 
87
  const type = getModelType(model.architecture);
88
  const capabilities = getCapabilities(model.architecture, model.supported_parameters);
 
 
 
 
 
89
 
90
  const modelEntry = {
91
  name: model.id,
@@ -145,15 +171,12 @@ if (require.main === module) {
145
  const free = models.filter(m => m.input_price_per_1m === 0 && !m.price_per_image);
146
  const vision = models.filter(m => m.type === 'vision');
147
  const imageGen = models.filter(m => m.type === 'image');
 
148
  console.log(`Fetched ${models.length} models from OpenRouter API ${apiKey ? '(authenticated)' : '(public – set OPENROUTER_API_KEY for more models)'}`);
149
- console.log(` Free: ${free.length}, Vision: ${vision.length}, Image-gen: ${imageGen.length}`);
150
- console.log('\nFirst 5 paid:');
151
- models.filter(m => m.input_price_per_1m > 0).slice(0, 5).forEach((m) =>
152
- console.log(` ${m.name.padEnd(55)} $${m.input_price_per_1m} / $${m.output_price_per_1m} [${m.type}] ${(m.capabilities||[]).join(',')}`)
153
- );
154
- console.log('\nFirst 5 free:');
155
- free.slice(0, 5).forEach((m) =>
156
- console.log(` ${m.name.padEnd(55)} [${m.type}] ${(m.capabilities||[]).join(',')}`)
157
  );
158
  })
159
  .catch((err) => {
 
12
  const { getJson } = require('../fetch-utils');
13
 
14
  const API_URL = 'https://openrouter.ai/api/v1/models';
15
+ const EU_API_URL = 'https://eu.openrouter.ai/api/v1/models';
16
 
17
  // OpenRouter stores per-token prices; multiply by 1e6 to get per-1M price.
18
  const toPerMillion = (val) => (val ? parseFloat(val) * 1_000_000 : 0);
 
66
  };
67
  if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`;
68
 
69
+ // If we have an API key, use the /user endpoint to get EU-filtered models correctly.
70
+ // Standard /models endpoint doesn't filter by subdomain.
71
+ const globalUrl = apiKey ? `${API_URL}/user` : API_URL;
72
+ const euUrl = apiKey ? `${EU_API_URL}/user` : EU_API_URL;
73
+
74
+ process.stdout.write('OpenRouter: fetching Global... ');
75
+ const globalData = await getJson(globalUrl, { headers });
76
+
77
+ let euModelIds = new Set();
78
+ if (apiKey) {
79
+ process.stdout.write('EU... ');
80
+ try {
81
+ const euData = await getJson(euUrl, { headers });
82
+ if (euData?.data) {
83
+ euModelIds = new Set(euData.data.map(m => m.id));
84
+ }
85
+ } catch (e) {
86
+ console.warn(`\n ⚠ Failed to fetch EU models: ${e.message}`);
87
+ }
88
+ }
89
+
90
  const models = [];
91
 
92
+ for (const model of globalData.data || []) {
93
  const pricing = model.pricing || {};
94
  const inputPrice = toPerMillion(pricing.prompt);
95
  const outputPrice = toPerMillion(pricing.completion);
 
107
 
108
  const type = getModelType(model.architecture);
109
  const capabilities = getCapabilities(model.architecture, model.supported_parameters);
110
+
111
+ // Tag with eu-endpoint if model is available via EU subdomain
112
+ if (euModelIds.has(model.id)) {
113
+ capabilities.push('eu-endpoint');
114
+ }
115
 
116
  const modelEntry = {
117
  name: model.id,
 
171
  const free = models.filter(m => m.input_price_per_1m === 0 && !m.price_per_image);
172
  const vision = models.filter(m => m.type === 'vision');
173
  const imageGen = models.filter(m => m.type === 'image');
174
+ const eu = models.filter(m => m.capabilities?.includes('eu-endpoint'));
175
  console.log(`Fetched ${models.length} models from OpenRouter API ${apiKey ? '(authenticated)' : '(public – set OPENROUTER_API_KEY for more models)'}`);
176
+ console.log(` Free: ${free.length}, Vision: ${vision.length}, Image-gen: ${imageGen.length}, EU-Endpoint: ${eu.length}`);
177
+ console.log('\nFirst 5 EU-available:');
178
+ eu.slice(0, 5).forEach((m) =>
179
+ console.log(` ${m.name.padEnd(55)} $${m.input_price_per_1m} / $${m.output_price_per_1m} [${m.type}]`)
 
 
 
 
180
  );
181
  })
182
  .catch((err) => {