@lucasschirm/devinp 0.1.0 → 0.1.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.
- package/README.md +19 -17
- package/bin/command.js +57 -57
- package/data/benchlm-scores.json +293 -0
- package/package.json +3 -3
- package/data/swe-scores.json +0 -73
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# devinp
|
|
2
2
|
|
|
3
3
|
Pretty pricing table for [Devin](https://devin.ai) models — reads live prices
|
|
4
|
-
from `devin models list`, joins
|
|
4
|
+
from `devin models list`, joins BenchLM coding scores, and renders a
|
|
5
5
|
sorted table in your terminal or a web page.
|
|
6
6
|
|
|
7
7
|
Thinking-effort variants that share a price (`low`, `medium`, `high`, `xhigh`,
|
|
@@ -27,12 +27,12 @@ The package ships as a self-contained bundle — no dependencies are installed.
|
|
|
27
27
|
## Usage
|
|
28
28
|
|
|
29
29
|
```sh
|
|
30
|
-
devinp # table sorted by best value (
|
|
30
|
+
devinp # table sorted by best value (Bench % ÷ output price)
|
|
31
31
|
devinp -o=input # cheapest input price first
|
|
32
32
|
devinp -o=cached # cheapest cached-input price first
|
|
33
33
|
devinp -o=output # cheapest output price first
|
|
34
|
-
devinp -o=
|
|
35
|
-
devinp -o=value # default: best
|
|
34
|
+
devinp -o=bench # highest BenchLM coding score first
|
|
35
|
+
devinp -o=value # default: best Bench score per output dollar
|
|
36
36
|
|
|
37
37
|
devinp -g=family # section the table by model family
|
|
38
38
|
devinp -g=price # section by identical price tier
|
|
@@ -48,33 +48,35 @@ devinp --json # emit normalized rows as JSON
|
|
|
48
48
|
### Reading the table
|
|
49
49
|
|
|
50
50
|
```
|
|
51
|
-
│ # │ Model │ Ctx │ Input │ Cached │ Output │
|
|
52
|
-
│ 1 │ Gemini 3 Flash
|
|
51
|
+
│ # │ Model │ Ctx │ Input │ Cached │ Output │ Bench % │ Value │ Sidekick i/c/o │
|
|
52
|
+
│ 1 │ Gemini 3.8 Flash│ 1.05M │ $0.75 │ $0.08 │ $3.75 │ 64.1% │ 17.10 │ — │
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
- Prices are USD per 1M tokens; columns are heat-colored green → red.
|
|
56
|
-
- **Value** = `
|
|
57
|
-
Free models show `∞`; models without a
|
|
58
|
-
under `-o=
|
|
56
|
+
- **Value** = `Bench % ÷ output $/1M` — the score you buy per output dollar.
|
|
57
|
+
Free models show `∞`; models without a Bench score show `—` and sort last
|
|
58
|
+
under `-o=bench` / `-o=value`.
|
|
59
59
|
- Markers: `β` = beta, `●` = new, magenta name = free. `Sidekick` shows the
|
|
60
60
|
partner-model pricing for Fusion rows.
|
|
61
61
|
- Colors disable automatically when piping; `NO_COLOR` / `FORCE_COLOR` are
|
|
62
62
|
respected.
|
|
63
63
|
|
|
64
|
-
##
|
|
64
|
+
## BenchLM scores
|
|
65
65
|
|
|
66
|
-
Scores live in `data/
|
|
66
|
+
Scores live in `data/benchlm-scores.json` and ship with the package. To refresh
|
|
67
67
|
them (maintainers, manual — not automated):
|
|
68
68
|
|
|
69
69
|
```sh
|
|
70
|
-
npm run update-
|
|
70
|
+
npm run update-benchlm
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
This
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
This fetches the [BenchLM](https://benchlm.ai/embed) leaderboard API
|
|
74
|
+
(`api/data/leaderboard?category=coding&limit=200` — the limit is raised from
|
|
75
|
+
the default 50 so the long tail of the board is included) and writes
|
|
76
|
+
`data/benchlm-scores.json`. Model names are
|
|
77
|
+
matched to Devin family slugs order-insensitively; names that still don't map
|
|
78
|
+
are reported under `unmatched` — add entries to `MANUAL_MAP` in
|
|
79
|
+
`scripts/update-benchlm.js` to fix them.
|
|
78
80
|
|
|
79
81
|
## Development
|
|
80
82
|
|
package/bin/command.js
CHANGED
|
@@ -54630,10 +54630,10 @@ function formatContext(tokens) {
|
|
|
54630
54630
|
function priceKey(cost) {
|
|
54631
54631
|
return [cost.input, cost.cached, cost.output, cost.sidekick?.input, cost.sidekick?.cached, cost.sidekick?.output].map((n) => n == null ? "-" : n).join("/");
|
|
54632
54632
|
}
|
|
54633
|
-
function buildRows(data,
|
|
54633
|
+
function buildRows(data, scores = {}) {
|
|
54634
54634
|
const rows = /* @__PURE__ */ new Map();
|
|
54635
54635
|
for (const family of data.families ?? []) {
|
|
54636
|
-
const
|
|
54636
|
+
const bench = scores.models?.[family.slug] ?? null;
|
|
54637
54637
|
for (const variant of family.variants ?? []) {
|
|
54638
54638
|
const cost = parseCostSummary(variant.cost_summary);
|
|
54639
54639
|
const label = normalizeLabel(variant.label, family.family_label);
|
|
@@ -54658,26 +54658,26 @@ function buildRows(data, sweScores = {}) {
|
|
|
54658
54658
|
isBeta: Boolean(variant.is_beta),
|
|
54659
54659
|
isNew: Boolean(variant.is_new),
|
|
54660
54660
|
variantCount: 1,
|
|
54661
|
-
|
|
54662
|
-
value: computeValue(
|
|
54661
|
+
bench: bench ? { score: bench.score, benchName: bench.benchName } : null,
|
|
54662
|
+
value: computeValue(bench?.score, cost.output)
|
|
54663
54663
|
});
|
|
54664
54664
|
}
|
|
54665
54665
|
}
|
|
54666
54666
|
return [...rows.values()];
|
|
54667
54667
|
}
|
|
54668
|
-
function computeValue(
|
|
54669
|
-
if (
|
|
54668
|
+
function computeValue(score, output) {
|
|
54669
|
+
if (score == null) return null;
|
|
54670
54670
|
if (output == null) return null;
|
|
54671
54671
|
if (output === 0) return Number.POSITIVE_INFINITY;
|
|
54672
|
-
return
|
|
54672
|
+
return score / output;
|
|
54673
54673
|
}
|
|
54674
54674
|
var priceAsc = (field) => (a2, b) => (a2[field] ?? Number.POSITIVE_INFINITY) - (b[field] ?? Number.POSITIVE_INFINITY) || (a2.output ?? Number.POSITIVE_INFINITY) - (b.output ?? Number.POSITIVE_INFINITY) || a2.label.localeCompare(b.label);
|
|
54675
54675
|
var SORTS = {
|
|
54676
54676
|
input: priceAsc("input"),
|
|
54677
54677
|
cached: priceAsc("cached"),
|
|
54678
54678
|
output: priceAsc("output"),
|
|
54679
|
-
|
|
54680
|
-
value: (a2, b) => (b.value ?? -1) - (a2.value ?? -1) || (b.
|
|
54679
|
+
bench: (a2, b) => (b.bench?.score ?? -1) - (a2.bench?.score ?? -1) || (a2.output ?? Number.POSITIVE_INFINITY) - (b.output ?? Number.POSITIVE_INFINITY) || a2.label.localeCompare(b.label),
|
|
54680
|
+
value: (a2, b) => (b.value ?? -1) - (a2.value ?? -1) || (b.bench?.score ?? -1) - (a2.bench?.score ?? -1) || a2.label.localeCompare(b.label)
|
|
54681
54681
|
};
|
|
54682
54682
|
var SORT_IDS = Object.keys(SORTS);
|
|
54683
54683
|
var GROUPS = {
|
|
@@ -54745,10 +54745,10 @@ function formatValue(c, row) {
|
|
|
54745
54745
|
if (!Number.isFinite(row.value)) return c.magenta("\u221E");
|
|
54746
54746
|
return c.bold.green(row.value.toFixed(2));
|
|
54747
54747
|
}
|
|
54748
|
-
function
|
|
54749
|
-
if (row.
|
|
54750
|
-
const text = `${row.
|
|
54751
|
-
return row.
|
|
54748
|
+
function formatBench(c, row) {
|
|
54749
|
+
if (row.bench == null) return c.dim("\u2014");
|
|
54750
|
+
const text = `${row.bench.score}%`;
|
|
54751
|
+
return row.bench.score >= 70 ? c.cyan.bold(text) : c.cyan(text);
|
|
54752
54752
|
}
|
|
54753
54753
|
function formatLabel(c, row) {
|
|
54754
54754
|
let text = row.free ? c.magenta(row.label) : c.bold(row.label);
|
|
@@ -54769,7 +54769,7 @@ function colorsEnabled(stream = process.stdout) {
|
|
|
54769
54769
|
if (process.env.NO_COLOR) return false;
|
|
54770
54770
|
return Boolean(stream.isTTY);
|
|
54771
54771
|
}
|
|
54772
|
-
function renderTable(sections, {
|
|
54772
|
+
function renderTable(sections, { benchMeta, colors = colorsEnabled() } = {}) {
|
|
54773
54773
|
const c = colors ? ansis_default : plain;
|
|
54774
54774
|
const allRows = sections.flatMap((s) => s.rows);
|
|
54775
54775
|
const hasSidekick = allRows.some((r) => r.sidekick);
|
|
@@ -54785,7 +54785,7 @@ function renderTable(sections, { sweMeta, colors = colorsEnabled() } = {}) {
|
|
|
54785
54785
|
{ title: "Input", align: "right" },
|
|
54786
54786
|
{ title: "Cached", align: "right" },
|
|
54787
54787
|
{ title: "Output", align: "right" },
|
|
54788
|
-
{ title: "
|
|
54788
|
+
{ title: "Bench %", align: "right" },
|
|
54789
54789
|
{ title: "Value", align: "right" }
|
|
54790
54790
|
];
|
|
54791
54791
|
if (hasSidekick) columns.push({ title: "Sidekick i/c/o", align: "left" });
|
|
@@ -54803,7 +54803,7 @@ function renderTable(sections, { sweMeta, colors = colorsEnabled() } = {}) {
|
|
|
54803
54803
|
formatPrice(c, row.input, ...ranges.input),
|
|
54804
54804
|
formatPrice(c, row.cached, ...ranges.cached),
|
|
54805
54805
|
formatPrice(c, row.output, ...ranges.output),
|
|
54806
|
-
|
|
54806
|
+
formatBench(c, row),
|
|
54807
54807
|
formatValue(c, row),
|
|
54808
54808
|
...hasSidekick ? [formatSidekick(c, row)] : []
|
|
54809
54809
|
]
|
|
@@ -54830,13 +54830,29 @@ function renderTable(sections, { sweMeta, colors = colorsEnabled() } = {}) {
|
|
|
54830
54830
|
out.push(line("\u2570", "\u2534", "\u256F"));
|
|
54831
54831
|
const legend = [
|
|
54832
54832
|
c.dim("prices per 1M tokens"),
|
|
54833
|
-
c.dim("value =
|
|
54834
|
-
|
|
54833
|
+
c.dim("value = Bench % \xF7 output $/1M"),
|
|
54834
|
+
benchMeta?.updated ? c.dim(`BenchLM (coding) \xB7 updated ${benchMeta.updated}`) : c.dim("Bench scores: not available")
|
|
54835
54835
|
];
|
|
54836
54836
|
return `${out.join("\n")}
|
|
54837
54837
|
${legend.join(c.dim(" \xB7 "))}`;
|
|
54838
54838
|
}
|
|
54839
54839
|
|
|
54840
|
+
// src/lib/scores.js
|
|
54841
|
+
import { readFile } from "node:fs/promises";
|
|
54842
|
+
import { join } from "node:path";
|
|
54843
|
+
async function loadScores(root) {
|
|
54844
|
+
const path = join(root, "data", "benchlm-scores.json");
|
|
54845
|
+
try {
|
|
54846
|
+
const parsed = JSON.parse(await readFile(path, "utf8"));
|
|
54847
|
+
return {
|
|
54848
|
+
models: parsed.models ?? {},
|
|
54849
|
+
meta: { updated: parsed.updated, source: parsed.source, unmatched: parsed.unmatched ?? [] }
|
|
54850
|
+
};
|
|
54851
|
+
} catch {
|
|
54852
|
+
return { models: {}, meta: {} };
|
|
54853
|
+
}
|
|
54854
|
+
}
|
|
54855
|
+
|
|
54840
54856
|
// src/lib/server.js
|
|
54841
54857
|
var import_fastify = __toESM(require_fastify(), 1);
|
|
54842
54858
|
import { execFile as execFile3 } from "node:child_process";
|
|
@@ -54871,7 +54887,7 @@ var PAGE = `<!doctype html>
|
|
|
54871
54887
|
td.name, th.name { text-align: left; font-weight: 600; }
|
|
54872
54888
|
td.dim { color: #64748b; }
|
|
54873
54889
|
td.free { color: #e879f9; }
|
|
54874
|
-
td.
|
|
54890
|
+
td.bench { color: #22d3ee; font-weight: 600; }
|
|
54875
54891
|
td.value { color: #4ade80; font-weight: 700; }
|
|
54876
54892
|
tr.section td {
|
|
54877
54893
|
color: #7dd3fc; font-weight: 700; text-align: left;
|
|
@@ -54882,12 +54898,12 @@ var PAGE = `<!doctype html>
|
|
|
54882
54898
|
</head>
|
|
54883
54899
|
<body>
|
|
54884
54900
|
<h1>devinp</h1>
|
|
54885
|
-
<div class="sub">Devin model prices \xB7 per 1M tokens \xB7 value =
|
|
54901
|
+
<div class="sub">Devin model prices \xB7 per 1M tokens \xB7 value = Bench % \xF7 output $/1M</div>
|
|
54886
54902
|
<div class="controls">
|
|
54887
54903
|
<label>sort
|
|
54888
54904
|
<select id="order">
|
|
54889
|
-
<option value="value">best value (
|
|
54890
|
-
<option value="
|
|
54905
|
+
<option value="value">best value (Bench \xF7 output)</option>
|
|
54906
|
+
<option value="bench">BenchLM score</option>
|
|
54891
54907
|
<option value="input">input price</option>
|
|
54892
54908
|
<option value="cached">cached price</option>
|
|
54893
54909
|
<option value="output">output price</option>
|
|
@@ -54906,7 +54922,7 @@ var PAGE = `<!doctype html>
|
|
|
54906
54922
|
<table>
|
|
54907
54923
|
<thead><tr>
|
|
54908
54924
|
<th>#</th><th class="name">Model</th><th>Ctx</th><th>Input</th>
|
|
54909
|
-
<th>Cached</th><th>Output</th><th>
|
|
54925
|
+
<th>Cached</th><th>Output</th><th>Bench %</th><th>Value</th><th id="sk"></th>
|
|
54910
54926
|
</tr></thead>
|
|
54911
54927
|
<tbody id="body"></tbody>
|
|
54912
54928
|
</table>
|
|
@@ -54920,7 +54936,7 @@ const heat = (v, lo, hi) => v == null ? '<span class="dim">\u2014</span>'
|
|
|
54920
54936
|
|
|
54921
54937
|
async function main() {
|
|
54922
54938
|
const res = await fetch('/api/models');
|
|
54923
|
-
const {rows,
|
|
54939
|
+
const {rows, bench} = await res.json();
|
|
54924
54940
|
const range = (f) => { const vs = rows.map(r => r[f]).filter(v => v != null); return [Math.min(...vs), Math.max(...vs)]; };
|
|
54925
54941
|
const RI = range('input'), RC = range('cached'), RO = range('output');
|
|
54926
54942
|
const hasSk = rows.some(r => r.sidekick);
|
|
@@ -54930,8 +54946,8 @@ async function main() {
|
|
|
54930
54946
|
input: (a, b) => (a.input ?? 1e9) - (b.input ?? 1e9) || (a.output ?? 1e9) - (b.output ?? 1e9) || a.label.localeCompare(b.label),
|
|
54931
54947
|
cached: (a, b) => (a.cached ?? 1e9) - (b.cached ?? 1e9) || (a.output ?? 1e9) - (b.output ?? 1e9) || a.label.localeCompare(b.label),
|
|
54932
54948
|
output: (a, b) => (a.output ?? 1e9) - (b.output ?? 1e9) || a.label.localeCompare(b.label),
|
|
54933
|
-
|
|
54934
|
-
value: (a, b) => (b.value ?? -1) - (a.value ?? -1) || (b.
|
|
54949
|
+
bench: (a, b) => (b.bench?.score ?? -1) - (a.bench?.score ?? -1) || (a.output ?? 1e9) - (b.output ?? 1e9) || a.label.localeCompare(b.label),
|
|
54950
|
+
value: (a, b) => (b.value ?? -1) - (a.value ?? -1) || (b.bench?.score ?? -1) - (a.bench?.score ?? -1) || a.label.localeCompare(b.label),
|
|
54935
54951
|
};
|
|
54936
54952
|
const GROUPS = {
|
|
54937
54953
|
family: {key: r => r.familySlug, head: r => r.familyLabel},
|
|
@@ -54967,7 +54983,7 @@ async function main() {
|
|
|
54967
54983
|
+ '<td>' + heat(r.input, ...RI) + '</td>'
|
|
54968
54984
|
+ '<td>' + heat(r.cached, ...RC) + '</td>'
|
|
54969
54985
|
+ '<td>' + heat(r.output, ...RO) + '</td>'
|
|
54970
|
-
+ '<td class="
|
|
54986
|
+
+ '<td class="bench">' + (r.bench ? r.bench.score + '%' : '<span class="dim">\u2014</span>') + '</td>'
|
|
54971
54987
|
+ '<td class="value">' + (r.value == null ? '<span class="dim">\u2014</span>' : !isFinite(r.value) ? '\u221E' : r.value.toFixed(2)) + '</td>'
|
|
54972
54988
|
+ (hasSk ? '<td class="dim">' + (r.sidekick ? '$' + r.sidekick.input + '/$' + r.sidekick.cached + '/$' + r.sidekick.output : '\u2014') + '</td>' : '')
|
|
54973
54989
|
+ '</tr>';
|
|
@@ -54975,9 +54991,9 @@ async function main() {
|
|
|
54975
54991
|
}
|
|
54976
54992
|
document.getElementById('body').innerHTML = html;
|
|
54977
54993
|
document.getElementById('count').textContent = n + ' rows';
|
|
54978
|
-
document.getElementById('legend').textContent =
|
|
54979
|
-
? '
|
|
54980
|
-
: '
|
|
54994
|
+
document.getElementById('legend').textContent = bench.updated
|
|
54995
|
+
? 'BenchLM (coding) \xB7 scores updated ' + bench.updated
|
|
54996
|
+
: 'Bench scores not available';
|
|
54981
54997
|
}
|
|
54982
54998
|
document.getElementById('order').onchange = render;
|
|
54983
54999
|
document.getElementById('group').onchange = render;
|
|
@@ -54987,12 +55003,12 @@ main();
|
|
|
54987
55003
|
</script>
|
|
54988
55004
|
</body>
|
|
54989
55005
|
</html>`;
|
|
54990
|
-
async function startServer({ rows,
|
|
55006
|
+
async function startServer({ rows, benchMeta, port, log }) {
|
|
54991
55007
|
const app = (0, import_fastify.default)({ logger: false });
|
|
54992
55008
|
app.get("/", async (_request, reply) => {
|
|
54993
55009
|
reply.type("text/html").send(PAGE);
|
|
54994
55010
|
});
|
|
54995
|
-
app.get("/api/models", async () => ({ rows,
|
|
55011
|
+
app.get("/api/models", async () => ({ rows, bench: benchMeta ?? {} }));
|
|
54996
55012
|
const address = await app.listen({ port, host: "127.0.0.1" });
|
|
54997
55013
|
log(`devinp web \u2014 ${address}`);
|
|
54998
55014
|
const opener = process.platform === "darwin" ? "open" : "xdg-open";
|
|
@@ -55008,14 +55024,14 @@ async function startServer({ rows, sweMeta, port, log }) {
|
|
|
55008
55024
|
|
|
55009
55025
|
// src/lib/source.js
|
|
55010
55026
|
import { execFile as execFile4 } from "node:child_process";
|
|
55011
|
-
import { readFile } from "node:fs/promises";
|
|
55027
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
55012
55028
|
import { promisify as promisify3 } from "node:util";
|
|
55013
55029
|
var execFileAsync = promisify3(execFile4);
|
|
55014
55030
|
async function loadModelData({ source } = {}) {
|
|
55015
55031
|
if (source) {
|
|
55016
55032
|
let raw;
|
|
55017
55033
|
try {
|
|
55018
|
-
raw = await
|
|
55034
|
+
raw = await readFile2(source, "utf8");
|
|
55019
55035
|
} catch (error) {
|
|
55020
55036
|
throw new Error(`Unable to get model prices: cannot read source file "${source}" (${error.code ?? error.message})`);
|
|
55021
55037
|
}
|
|
@@ -55045,35 +55061,19 @@ async function loadModelData({ source } = {}) {
|
|
|
55045
55061
|
}
|
|
55046
55062
|
}
|
|
55047
55063
|
|
|
55048
|
-
// src/lib/swe.js
|
|
55049
|
-
import { readFile as readFile2 } from "node:fs/promises";
|
|
55050
|
-
import { join } from "node:path";
|
|
55051
|
-
async function loadSweScores(root) {
|
|
55052
|
-
const path = join(root, "data", "swe-scores.json");
|
|
55053
|
-
try {
|
|
55054
|
-
const parsed = JSON.parse(await readFile2(path, "utf8"));
|
|
55055
|
-
return {
|
|
55056
|
-
models: parsed.models ?? {},
|
|
55057
|
-
meta: { updated: parsed.updated, source: parsed.source, unmatched: parsed.unmatched ?? [] }
|
|
55058
|
-
};
|
|
55059
|
-
} catch {
|
|
55060
|
-
return { models: {}, meta: {} };
|
|
55061
|
-
}
|
|
55062
|
-
}
|
|
55063
|
-
|
|
55064
55064
|
// src/command.js
|
|
55065
55065
|
var Devinp = class _Devinp extends import_core.Command {
|
|
55066
55066
|
static summary = "Show Devin model prices in a pretty table";
|
|
55067
55067
|
static description = [
|
|
55068
55068
|
"Reads prices from `devin models list --format json` (or a saved snapshot via",
|
|
55069
|
-
"--source), joins
|
|
55069
|
+
"--source), joins BenchLM coding scores from data/benchlm-scores.json, and",
|
|
55070
55070
|
"renders a sorted pricing table. Thinking-effort variants that share a price",
|
|
55071
55071
|
"are collapsed into one row."
|
|
55072
55072
|
].join("\n");
|
|
55073
55073
|
static examples = [
|
|
55074
55074
|
"<%= config.bin %>",
|
|
55075
55075
|
"<%= config.bin %> -o=input",
|
|
55076
|
-
"<%= config.bin %> -o=
|
|
55076
|
+
"<%= config.bin %> -o=bench -g=family",
|
|
55077
55077
|
"<%= config.bin %> --web --port 8080",
|
|
55078
55078
|
"<%= config.bin %> --source sample/models.json"
|
|
55079
55079
|
];
|
|
@@ -55082,7 +55082,7 @@ var Devinp = class _Devinp extends import_core.Command {
|
|
|
55082
55082
|
char: "o",
|
|
55083
55083
|
options: SORT_IDS,
|
|
55084
55084
|
default: "value",
|
|
55085
|
-
summary: "sort by input | cached | output price,
|
|
55085
|
+
summary: "sort by input | cached | output price, bench score, or value (Bench \xF7 output)"
|
|
55086
55086
|
}),
|
|
55087
55087
|
group: import_core.Flags.string({
|
|
55088
55088
|
char: "g",
|
|
@@ -55115,18 +55115,18 @@ var Devinp = class _Devinp extends import_core.Command {
|
|
|
55115
55115
|
} catch (error) {
|
|
55116
55116
|
this.error(error instanceof Error ? error.message : String(error), { exit: 1 });
|
|
55117
55117
|
}
|
|
55118
|
-
const
|
|
55119
|
-
const rows = buildRows(data,
|
|
55118
|
+
const scores = await loadScores(this.config.root);
|
|
55119
|
+
const rows = buildRows(data, scores);
|
|
55120
55120
|
if (flags.json) {
|
|
55121
55121
|
this.log(JSON.stringify(rows, null, 2));
|
|
55122
55122
|
return;
|
|
55123
55123
|
}
|
|
55124
55124
|
if (flags.web) {
|
|
55125
|
-
await startServer({ rows,
|
|
55125
|
+
await startServer({ rows, benchMeta: scores.meta, port: flags.port, log: (m) => this.log(m) });
|
|
55126
55126
|
return;
|
|
55127
55127
|
}
|
|
55128
55128
|
const sections = arrangeRows(rows, { order: flags.order, group: flags.group });
|
|
55129
|
-
this.log(renderTable(sections, {
|
|
55129
|
+
this.log(renderTable(sections, { benchMeta: scores.meta }));
|
|
55130
55130
|
}
|
|
55131
55131
|
};
|
|
55132
55132
|
export {
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
{
|
|
2
|
+
"updated": "2026-09-22",
|
|
3
|
+
"source": "https://benchlm.ai/api/data/leaderboard?category=coding&limit=200",
|
|
4
|
+
"models": {
|
|
5
|
+
"claude-fable-5": {
|
|
6
|
+
"score": 74.47,
|
|
7
|
+
"benchName": "Claude Fable 5",
|
|
8
|
+
"supported": true
|
|
9
|
+
},
|
|
10
|
+
"claude-fable-5.1": {
|
|
11
|
+
"score": 81.29,
|
|
12
|
+
"benchName": "Claude Fable 5.1",
|
|
13
|
+
"supported": true
|
|
14
|
+
},
|
|
15
|
+
"claude-haiku-4.5": {
|
|
16
|
+
"score": 19.77,
|
|
17
|
+
"benchName": "Claude Haiku 4.5",
|
|
18
|
+
"supported": true
|
|
19
|
+
},
|
|
20
|
+
"claude-opus-4.5": {
|
|
21
|
+
"score": 46.1,
|
|
22
|
+
"benchName": "Claude Opus 4.5",
|
|
23
|
+
"supported": false
|
|
24
|
+
},
|
|
25
|
+
"claude-opus-4.6": {
|
|
26
|
+
"score": 51.32,
|
|
27
|
+
"benchName": "Claude Opus 4.6",
|
|
28
|
+
"supported": true
|
|
29
|
+
},
|
|
30
|
+
"claude-opus-4.7": {
|
|
31
|
+
"score": 59.77,
|
|
32
|
+
"benchName": "Claude Opus 4.7",
|
|
33
|
+
"supported": true
|
|
34
|
+
},
|
|
35
|
+
"claude-opus-4.8": {
|
|
36
|
+
"score": 63.58,
|
|
37
|
+
"benchName": "Claude Opus 4.8",
|
|
38
|
+
"supported": true
|
|
39
|
+
},
|
|
40
|
+
"claude-opus-5": {
|
|
41
|
+
"score": 72.91,
|
|
42
|
+
"benchName": "Claude Opus 5",
|
|
43
|
+
"supported": true
|
|
44
|
+
},
|
|
45
|
+
"claude-opus-5.5": {
|
|
46
|
+
"score": 86.85,
|
|
47
|
+
"benchName": "Claude Opus 5.5",
|
|
48
|
+
"supported": true
|
|
49
|
+
},
|
|
50
|
+
"claude-sonnet-4.6": {
|
|
51
|
+
"score": 48.52,
|
|
52
|
+
"benchName": "Claude Sonnet 4.6",
|
|
53
|
+
"supported": true
|
|
54
|
+
},
|
|
55
|
+
"claude-sonnet-5": {
|
|
56
|
+
"score": 61.05,
|
|
57
|
+
"benchName": "Claude Sonnet 5",
|
|
58
|
+
"supported": true
|
|
59
|
+
},
|
|
60
|
+
"gemini-3-flash": {
|
|
61
|
+
"score": 36.84,
|
|
62
|
+
"benchName": "Gemini 3 Flash",
|
|
63
|
+
"supported": true
|
|
64
|
+
},
|
|
65
|
+
"gemini-3.1-pro": {
|
|
66
|
+
"score": 43.36,
|
|
67
|
+
"benchName": "Gemini 3.1 Pro",
|
|
68
|
+
"supported": true
|
|
69
|
+
},
|
|
70
|
+
"gemini-3.5-flash": {
|
|
71
|
+
"score": 53.7,
|
|
72
|
+
"benchName": "Gemini 3.5 Flash",
|
|
73
|
+
"supported": true
|
|
74
|
+
},
|
|
75
|
+
"gemini-3.6-flash": {
|
|
76
|
+
"score": 54.73,
|
|
77
|
+
"benchName": "Gemini 3.6 Flash",
|
|
78
|
+
"supported": true
|
|
79
|
+
},
|
|
80
|
+
"gemini-3.7-flash": {
|
|
81
|
+
"score": 59.79,
|
|
82
|
+
"benchName": "Gemini 3.7 Flash",
|
|
83
|
+
"supported": true
|
|
84
|
+
},
|
|
85
|
+
"gemini-3.8-flash": {
|
|
86
|
+
"score": 64.14,
|
|
87
|
+
"benchName": "Gemini 3.8 Flash",
|
|
88
|
+
"supported": true
|
|
89
|
+
},
|
|
90
|
+
"glm-5.2": {
|
|
91
|
+
"score": 57.32,
|
|
92
|
+
"benchName": "GLM-5.2",
|
|
93
|
+
"supported": true
|
|
94
|
+
},
|
|
95
|
+
"glm-5.3": {
|
|
96
|
+
"score": 58.15,
|
|
97
|
+
"benchName": "GLM-5.3",
|
|
98
|
+
"supported": true
|
|
99
|
+
},
|
|
100
|
+
"glm-5.3-flash": {
|
|
101
|
+
"score": 51.6,
|
|
102
|
+
"benchName": "GLM-5.3-Flash",
|
|
103
|
+
"supported": true
|
|
104
|
+
},
|
|
105
|
+
"gpt-5.1": {
|
|
106
|
+
"score": 39.77,
|
|
107
|
+
"benchName": "GPT-5.1",
|
|
108
|
+
"supported": true
|
|
109
|
+
},
|
|
110
|
+
"gpt-5.2": {
|
|
111
|
+
"score": 41.57,
|
|
112
|
+
"benchName": "GPT-5.2",
|
|
113
|
+
"supported": true
|
|
114
|
+
},
|
|
115
|
+
"gpt-5.3-codex": {
|
|
116
|
+
"score": 56.8,
|
|
117
|
+
"benchName": "GPT-5.3 Codex",
|
|
118
|
+
"supported": true
|
|
119
|
+
},
|
|
120
|
+
"gpt-5.4": {
|
|
121
|
+
"score": 50.93,
|
|
122
|
+
"benchName": "GPT-5.4",
|
|
123
|
+
"supported": true
|
|
124
|
+
},
|
|
125
|
+
"gpt-5.4-mini": {
|
|
126
|
+
"score": 38.61,
|
|
127
|
+
"benchName": "GPT-5.4 mini",
|
|
128
|
+
"supported": true
|
|
129
|
+
},
|
|
130
|
+
"gpt-5.5": {
|
|
131
|
+
"score": 64.47,
|
|
132
|
+
"benchName": "GPT-5.5",
|
|
133
|
+
"supported": true
|
|
134
|
+
},
|
|
135
|
+
"gpt-5.6-luna": {
|
|
136
|
+
"score": 64.72,
|
|
137
|
+
"benchName": "GPT-5.6 Luna",
|
|
138
|
+
"supported": true
|
|
139
|
+
},
|
|
140
|
+
"gpt-5.6-sol": {
|
|
141
|
+
"score": 71.77,
|
|
142
|
+
"benchName": "GPT-5.6 Sol",
|
|
143
|
+
"supported": true
|
|
144
|
+
},
|
|
145
|
+
"gpt-5.6-terra": {
|
|
146
|
+
"score": 65.05,
|
|
147
|
+
"benchName": "GPT-5.6 Terra",
|
|
148
|
+
"supported": true
|
|
149
|
+
},
|
|
150
|
+
"gpt-6-astra": {
|
|
151
|
+
"score": 74.43,
|
|
152
|
+
"benchName": "GPT-6 Astra",
|
|
153
|
+
"supported": true
|
|
154
|
+
},
|
|
155
|
+
"gpt-6-luna": {
|
|
156
|
+
"score": 59.93,
|
|
157
|
+
"benchName": "GPT-6 Luna",
|
|
158
|
+
"supported": true
|
|
159
|
+
},
|
|
160
|
+
"gpt-6-sol": {
|
|
161
|
+
"score": 65.48,
|
|
162
|
+
"benchName": "GPT-6 Sol",
|
|
163
|
+
"supported": true
|
|
164
|
+
},
|
|
165
|
+
"grok-4.5": {
|
|
166
|
+
"score": 58.55,
|
|
167
|
+
"benchName": "Grok 4.5",
|
|
168
|
+
"supported": true
|
|
169
|
+
},
|
|
170
|
+
"grok-4.6": {
|
|
171
|
+
"score": 62.55,
|
|
172
|
+
"benchName": "Grok 4.6",
|
|
173
|
+
"supported": true
|
|
174
|
+
},
|
|
175
|
+
"inkling": {
|
|
176
|
+
"score": 37.23,
|
|
177
|
+
"benchName": "Inkling",
|
|
178
|
+
"supported": true
|
|
179
|
+
},
|
|
180
|
+
"kimi-k2.6": {
|
|
181
|
+
"score": 47.36,
|
|
182
|
+
"benchName": "Kimi K2.6",
|
|
183
|
+
"supported": true
|
|
184
|
+
},
|
|
185
|
+
"kimi-k3": {
|
|
186
|
+
"score": 63.31,
|
|
187
|
+
"benchName": "Kimi K3",
|
|
188
|
+
"supported": true
|
|
189
|
+
},
|
|
190
|
+
"nemotron-3-ultra": {
|
|
191
|
+
"score": 23.53,
|
|
192
|
+
"benchName": "Nemotron 3 Ultra",
|
|
193
|
+
"supported": true
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
"unmatched": [
|
|
197
|
+
"Apodex 1.1",
|
|
198
|
+
"Claude 3 Opus",
|
|
199
|
+
"Command A+",
|
|
200
|
+
"DeepSeek V3",
|
|
201
|
+
"DeepSeek V3.2",
|
|
202
|
+
"DeepSeek V3.2 (Thinking)",
|
|
203
|
+
"DeepSeek V4 Pro 0813",
|
|
204
|
+
"GLM-4.6",
|
|
205
|
+
"GLM-4.7",
|
|
206
|
+
"GLM-5",
|
|
207
|
+
"GLM-5.1",
|
|
208
|
+
"GLM-5V-Turbo",
|
|
209
|
+
"GPT-4 Turbo",
|
|
210
|
+
"GPT-4.1 mini",
|
|
211
|
+
"GPT-4.1 nano",
|
|
212
|
+
"GPT-4o mini",
|
|
213
|
+
"GPT-5 (medium)",
|
|
214
|
+
"GPT-5 mini",
|
|
215
|
+
"GPT-5.1-Codex",
|
|
216
|
+
"GPT-5.2-Codex",
|
|
217
|
+
"GPT-5.4 nano",
|
|
218
|
+
"GPT-OSS 120B",
|
|
219
|
+
"GPT-OSS 20B",
|
|
220
|
+
"Gemini 1.5 Pro",
|
|
221
|
+
"Gemini 2.5 Pro",
|
|
222
|
+
"Gemini 3 Pro",
|
|
223
|
+
"Gemini 3.1 Flash-Lite",
|
|
224
|
+
"Gemini 3.5 Flash-Lite",
|
|
225
|
+
"Gemma 3 27B",
|
|
226
|
+
"Gemma 4 12B",
|
|
227
|
+
"Gemma 4 26B A4B",
|
|
228
|
+
"Gemma 4 31B",
|
|
229
|
+
"Gemma 4 E2B",
|
|
230
|
+
"Gemma 4 E4B",
|
|
231
|
+
"Granite 4.2 8B",
|
|
232
|
+
"Grok 4 Fast (Reasoning)",
|
|
233
|
+
"Grok 4.1 Fast (Reasoning)",
|
|
234
|
+
"Grok 4.20",
|
|
235
|
+
"Grok 4.3",
|
|
236
|
+
"Grok Build 0.1",
|
|
237
|
+
"Grok Code Fast 1",
|
|
238
|
+
"Hy3",
|
|
239
|
+
"Hy3 Preview",
|
|
240
|
+
"Hy4 preview",
|
|
241
|
+
"Inkling-Small",
|
|
242
|
+
"K-Exaone",
|
|
243
|
+
"Kimi K2.5",
|
|
244
|
+
"Kimi K2.7 Code",
|
|
245
|
+
"LFM2.5-2.6B",
|
|
246
|
+
"Laguna M.1",
|
|
247
|
+
"Laguna XS.2",
|
|
248
|
+
"Ling 2.6 Flash",
|
|
249
|
+
"Ling 3.0 Flash",
|
|
250
|
+
"Llama 4 Maverick",
|
|
251
|
+
"Llama 4 Scout",
|
|
252
|
+
"Mercury 2",
|
|
253
|
+
"Mercury 2.5",
|
|
254
|
+
"MiMo-V2-Flash",
|
|
255
|
+
"MiMo-V2-Pro",
|
|
256
|
+
"MiMo-V2.5",
|
|
257
|
+
"MiMo-V2.5-Pro",
|
|
258
|
+
"MiniMax M2.5",
|
|
259
|
+
"MiniMax M2.7",
|
|
260
|
+
"MiniMax M3",
|
|
261
|
+
"Ministral 3 14B",
|
|
262
|
+
"Ministral 3 3B",
|
|
263
|
+
"Ministral 3 8B",
|
|
264
|
+
"Mistral Large 3",
|
|
265
|
+
"Mistral Medium 3.5 128B",
|
|
266
|
+
"Mistral Small 4",
|
|
267
|
+
"Muse Glimmer 30B",
|
|
268
|
+
"Muse Spark",
|
|
269
|
+
"Muse Spark 1.1",
|
|
270
|
+
"Muse Spark 1.2",
|
|
271
|
+
"Nemotron 3 Nano Omni 30B A3B",
|
|
272
|
+
"Nemotron 3.5 Lightning 30B A3B NVFP4",
|
|
273
|
+
"Ornith-1.5-35B-A3B",
|
|
274
|
+
"Ornith-1.5-397B",
|
|
275
|
+
"Qwen 3.6 Max (preview)",
|
|
276
|
+
"Qwen3.5 Flash",
|
|
277
|
+
"Qwen3.5-122B-A10B",
|
|
278
|
+
"Qwen3.5-27B",
|
|
279
|
+
"Qwen3.5-35B-A3B",
|
|
280
|
+
"Qwen3.6 Plus",
|
|
281
|
+
"Qwen3.6-27B",
|
|
282
|
+
"Qwen3.6-35B-A3B",
|
|
283
|
+
"Qwen3.7 Max",
|
|
284
|
+
"Qwen3.7 Plus",
|
|
285
|
+
"Qwen3.8 Max",
|
|
286
|
+
"Qwen3.8-27B",
|
|
287
|
+
"Qwen3.8-Flash-Next",
|
|
288
|
+
"Step 3.7 Flash",
|
|
289
|
+
"Trinity-Large-Thinking",
|
|
290
|
+
"o1",
|
|
291
|
+
"o1-preview"
|
|
292
|
+
]
|
|
293
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lucasschirm/devinp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Pretty pricing table for Devin models, powered by `devin models list`",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"devin",
|
|
24
24
|
"pricing",
|
|
25
25
|
"models",
|
|
26
|
-
"
|
|
26
|
+
"benchlm",
|
|
27
27
|
"cli"
|
|
28
28
|
],
|
|
29
29
|
"engines": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"prepack": "npm run build",
|
|
36
36
|
"prepare": "npm run build",
|
|
37
37
|
"test": "node --test",
|
|
38
|
-
"update-
|
|
38
|
+
"update-benchlm": "node scripts/update-benchlm.js"
|
|
39
39
|
},
|
|
40
40
|
"oclif": {
|
|
41
41
|
"bin": "devinp",
|
package/data/swe-scores.json
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"updated": "2026-09-21",
|
|
3
|
-
"source": "https://www.swebench.com/index.html (Verified · mini-SWE-agent)",
|
|
4
|
-
"models": {
|
|
5
|
-
"gemini-3-flash": {
|
|
6
|
-
"resolved": 75.8,
|
|
7
|
-
"sweName": "Gemini 3 Flash (high)",
|
|
8
|
-
"checked": false,
|
|
9
|
-
"date": "2026-02-17"
|
|
10
|
-
},
|
|
11
|
-
"gpt-4.1": {
|
|
12
|
-
"resolved": 39.58,
|
|
13
|
-
"sweName": "GPT 4.1 (2025-04-14)",
|
|
14
|
-
"checked": true,
|
|
15
|
-
"date": "2025-07-26"
|
|
16
|
-
},
|
|
17
|
-
"gpt-5.1": {
|
|
18
|
-
"resolved": 66,
|
|
19
|
-
"sweName": "GPT 5.1 (2025-11-13) (medium)",
|
|
20
|
-
"checked": false,
|
|
21
|
-
"date": "2025-11-20"
|
|
22
|
-
},
|
|
23
|
-
"gpt-5.2": {
|
|
24
|
-
"resolved": 72.8,
|
|
25
|
-
"sweName": "GPT 5.2 (high)",
|
|
26
|
-
"checked": false,
|
|
27
|
-
"date": "2026-02-17"
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
"unmatched": [
|
|
31
|
-
"Claude 3.7 Sonnet (20250219)",
|
|
32
|
-
"Claude 4 Opus (20250514)",
|
|
33
|
-
"Claude 4 Sonnet (20250514)",
|
|
34
|
-
"Claude 4.5 Haiku (high)",
|
|
35
|
-
"Claude 4.5 Opus (20251101) (medium)",
|
|
36
|
-
"Claude 4.5 Opus (high)",
|
|
37
|
-
"Claude 4.5 Sonnet (20250929)",
|
|
38
|
-
"Claude 4.5 Sonnet (high)",
|
|
39
|
-
"Claude 4.6 Opus",
|
|
40
|
-
"DeepSeek V3.2 (high)",
|
|
41
|
-
"DeepSeek V3.2 Reasoner",
|
|
42
|
-
"Devstral (2512)",
|
|
43
|
-
"Devstral Small (2512)",
|
|
44
|
-
"GLM 4.5 (2025-08-22)",
|
|
45
|
-
"GLM 4.6 (T=1)",
|
|
46
|
-
"GLM 5 (high)",
|
|
47
|
-
"GPT 4.1 mini (2025-04-14)",
|
|
48
|
-
"GPT 4o (2024-11-20)",
|
|
49
|
-
"GPT 5 (2025-08-07) (medium)",
|
|
50
|
-
"GPT 5 mini",
|
|
51
|
-
"GPT 5 mini (2025-08-07) (medium)",
|
|
52
|
-
"GPT 5 nano (2025-08-07) (medium)",
|
|
53
|
-
"GPT 5.1 Codex (medium)",
|
|
54
|
-
"GPT 5.2 Codex",
|
|
55
|
-
"Gemini 2.0 Flash",
|
|
56
|
-
"Gemini 2.5 Flash (2025-04-17)",
|
|
57
|
-
"Gemini 2.5 Pro (2025-05-06)",
|
|
58
|
-
"Gemini 3 Pro",
|
|
59
|
-
"Gemini 3 Pro Preview (2025-11-18)",
|
|
60
|
-
"Kimi K2 Instruct",
|
|
61
|
-
"Kimi K2 Thinking",
|
|
62
|
-
"Kimi K2.5 (high)",
|
|
63
|
-
"Llama 4 Maverick Instruct",
|
|
64
|
-
"Llama 4 Scout Instruct",
|
|
65
|
-
"MiniMax M2",
|
|
66
|
-
"MiniMax M2.5 (high)",
|
|
67
|
-
"Qwen2.5-Coder 32B Instruct",
|
|
68
|
-
"Qwen3-Coder 480B/A35B Instruct",
|
|
69
|
-
"gpt-oss-120b",
|
|
70
|
-
"o3 (2025-04-16)",
|
|
71
|
-
"o4-mini (2025-04-16)"
|
|
72
|
-
]
|
|
73
|
-
}
|