File size: 2,684 Bytes
2b64d42 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #!/usr/bin/env node
/**
* Regenerate the MODELS array embedded in docs/index.html from the canonical
* src/models.js catalog so the GitHub Pages site never drifts.
*
* Run: node scripts/gen-docs-models.js
* — writes back to docs/index.html in place
*/
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { MODELS } from '../src/models.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const docsPath = path.join(__dirname, '..', 'docs', 'index.html');
const PROVIDER_ALIAS = { alibaba: 'qwen' };
function isThinking(id, info) {
if (id.includes('thinking')) return true;
if (info.modelUid && /THINKING|REASONING/.test(info.modelUid)) return true;
return false;
}
const FREE_TIER_HINTS = new Set([
'gemini-2.5-flash', 'gemini-3.0-flash-minimal', 'glm-4.7', 'swe-1.5-fast',
]);
function buildEntries() {
const entries = [];
for (const [id, info] of Object.entries(MODELS)) {
if (info.deprecated) continue;
const provider = PROVIDER_ALIAS[info.provider] || info.provider;
const e = { k: id, p: provider, c: info.credit ?? 0 };
if (isThinking(id, info)) e.thinking = 1;
if (FREE_TIER_HINTS.has(id)) e.free = 1;
entries.push(e);
}
return entries;
}
function formatEntry(e) {
const parts = [`k:'${e.k}'`, `p:'${e.p}'`, `c:${e.c}`];
if (e.thinking) parts.push('thinking:1');
if (e.free) parts.push('free:1');
return ` {${parts.join(',')}}`;
}
function buildArrayLiteral(entries) {
return [
' const MODELS = [',
entries.map(formatEntry).join(',\n') + ',',
' ];',
].join('\n');
}
const html = fs.readFileSync(docsPath, 'utf8');
const start = html.indexOf('const MODELS = [');
if (start === -1) {
console.error('Could not find "const MODELS = [" anchor in docs/index.html');
process.exit(1);
}
const endMarker = '\n ];';
const end = html.indexOf(endMarker, start);
if (end === -1) {
console.error('Could not find closing "];" for MODELS array');
process.exit(1);
}
const lineStart = html.lastIndexOf('\n', start);
const prefix = lineStart === -1 ? '' : html.slice(0, lineStart + 1);
const suffix = html.slice(end + endMarker.length);
const entries = buildEntries();
const literal = buildArrayLiteral(entries);
const next = `${prefix}${literal}${suffix}`;
fs.writeFileSync(docsPath, next, 'utf8');
const byProvider = entries.reduce((acc, e) => {
acc[e.p] = (acc[e.p] || 0) + 1;
return acc;
}, {});
console.log(`docs/index.html updated: ${entries.length} models`);
console.log('By provider:', byProvider);
console.log(`thinking: ${entries.filter(e => e.thinking).length}, free: ${entries.filter(e => e.free).length}`);
|