Skip to content

Commit dc0f33d

Browse files
authored
fix(catalog): publish only callable models with aligned release manifest (#120)
* fix(catalog): exclude unavailable models * fix(release): align published manifest version * fix(catalog): route sync writes through validated artifacts * fix(catalog): harden review coverage for sync and release guards
1 parent 27b2bfd commit dc0f33d

15 files changed

Lines changed: 681 additions & 280 deletions

manifest.json

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,58 @@
11
{
22
"schemaVersion": 1,
3-
"generatedAt": "2026-09-20T12:00:52.504Z",
3+
"generatedAt": "2026-09-20T16:38:04.091Z",
44
"pluginVersion": "0.7.72",
55
"commandCodeVersion": "1.58.1",
66
"commandCodeTarball": "https://registry.npmjs.org/command-code/-/command-code-1.58.1.tgz",
7-
"modelCount": 78,
8-
"reasoningModelCount": 67,
7+
"modelCount": 71,
8+
"reasoningModelCount": 61,
99
"extraction": {
1010
"modelCatalog": "ok",
1111
"costCatalog": "cli",
1212
"costCatalogError": null
1313
},
1414
"costSources": {
15-
"cli": 22,
15+
"cli": 21,
1616
"officialDocs": 50,
1717
"thirdParty": 0,
18-
"free": 6,
18+
"free": 0,
1919
"fallback": 0,
2020
"unmatched": 0
2121
},
2222
"review": {
2323
"thirdParty": [],
24-
"free": [
25-
"inclusionai/ling-3.0-flash-free",
26-
"meituan/LongCat-2.0:free",
27-
"minimax/minimax-m2.7-free",
28-
"minimax/minimax-m3-free",
29-
"MiniMaxAI/MiniMax-M3-Free",
30-
"tencent/Hy3"
31-
],
32-
"unmatched": []
24+
"free": [],
25+
"unmatched": [],
26+
"unavailable": [
27+
{
28+
"id": "MiniMaxAI/MiniMax-M3-Free",
29+
"reason": "not-listed-by-provider-api"
30+
},
31+
{
32+
"id": "gpt-6-astra",
33+
"reason": "not-listed-by-provider-api"
34+
},
35+
{
36+
"id": "inclusionai/ling-3.0-flash-free",
37+
"reason": "not-listed-by-provider-api"
38+
},
39+
{
40+
"id": "meituan/LongCat-2.0:free",
41+
"reason": "not-listed-by-provider-api"
42+
},
43+
{
44+
"id": "minimax/minimax-m2.7-free",
45+
"reason": "not-listed-by-provider-api"
46+
},
47+
{
48+
"id": "minimax/minimax-m3-free",
49+
"reason": "not-listed-by-provider-api"
50+
},
51+
{
52+
"id": "tencent/Hy3",
53+
"reason": "not-listed-by-provider-api"
54+
}
55+
]
3356
},
3457
"status": "healthy"
3558
}

models.json

Lines changed: 0 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -401,41 +401,6 @@
401401
]
402402
}
403403
},
404-
{
405-
"id": "gpt-6-astra",
406-
"name": "GPT-6 Astra",
407-
"tier": "premium",
408-
"reasoning": true,
409-
"reasoningEfforts": [
410-
"low",
411-
"medium",
412-
"high",
413-
"xhigh",
414-
"max"
415-
],
416-
"tool_call": true,
417-
"cost": {
418-
"input": 10,
419-
"output": 50,
420-
"cache_read": 1,
421-
"cache_write": 12.5
422-
},
423-
"limit": {
424-
"context": 1050000,
425-
"output": 65536
426-
},
427-
"attachment": true,
428-
"modalities": {
429-
"input": [
430-
"text",
431-
"image",
432-
"pdf"
433-
],
434-
"output": [
435-
"text"
436-
]
437-
}
438-
},
439404
{
440405
"id": "deepseek/deepseek-v4-flash",
441406
"name": "DeepSeek V4 Flash (latest)",
@@ -1400,30 +1365,6 @@
14001365
]
14011366
}
14021367
},
1403-
{
1404-
"id": "inclusionai/ling-3.0-flash-free",
1405-
"name": "Ling 3.0 Flash",
1406-
"tier": "open-source",
1407-
"reasoning": true,
1408-
"tool_call": true,
1409-
"cost": {
1410-
"input": 0,
1411-
"output": 0
1412-
},
1413-
"limit": {
1414-
"context": 256000,
1415-
"output": 32768
1416-
},
1417-
"attachment": false,
1418-
"modalities": {
1419-
"input": [
1420-
"text"
1421-
],
1422-
"output": [
1423-
"text"
1424-
]
1425-
}
1426-
},
14271368
{
14281369
"id": "inclusionai/ling-3.0-flash-sante:free",
14291370
"name": "Ling 3.0 Flash Sante",
@@ -1474,30 +1415,6 @@
14741415
]
14751416
}
14761417
},
1477-
{
1478-
"id": "meituan/LongCat-2.0:free",
1479-
"name": "LongCat 2.0 (Free)",
1480-
"tier": "open-source",
1481-
"reasoning": true,
1482-
"tool_call": true,
1483-
"cost": {
1484-
"input": 0,
1485-
"output": 0
1486-
},
1487-
"limit": {
1488-
"context": 1048576,
1489-
"output": 65536
1490-
},
1491-
"attachment": false,
1492-
"modalities": {
1493-
"input": [
1494-
"text"
1495-
],
1496-
"output": [
1497-
"text"
1498-
]
1499-
}
1500-
},
15011418
{
15021419
"id": "xiaomi/mimo-v2.5",
15031420
"name": "MiMo V2.5",
@@ -1600,30 +1517,6 @@
16001517
]
16011518
}
16021519
},
1603-
{
1604-
"id": "minimax/minimax-m2.7-free",
1605-
"name": "MiniMax M2.7 (Free)",
1606-
"tier": "open-source",
1607-
"reasoning": false,
1608-
"tool_call": true,
1609-
"cost": {
1610-
"input": 0,
1611-
"output": 0
1612-
},
1613-
"limit": {
1614-
"context": 197000,
1615-
"output": 65536
1616-
},
1617-
"attachment": false,
1618-
"modalities": {
1619-
"input": [
1620-
"text"
1621-
],
1622-
"output": [
1623-
"text"
1624-
]
1625-
}
1626-
},
16271520
{
16281521
"id": "MiniMaxAI/MiniMax-M3",
16291522
"name": "MiniMax M3",
@@ -1656,68 +1549,6 @@
16561549
]
16571550
}
16581551
},
1659-
{
1660-
"id": "minimax/minimax-m3-free",
1661-
"name": "MiniMax M3 (Free)",
1662-
"tier": "open-source",
1663-
"reasoning": true,
1664-
"reasoningEfforts": [
1665-
"low",
1666-
"medium",
1667-
"high"
1668-
],
1669-
"tool_call": true,
1670-
"cost": {
1671-
"input": 0,
1672-
"output": 0
1673-
},
1674-
"limit": {
1675-
"context": 1000000,
1676-
"output": 65536
1677-
},
1678-
"attachment": true,
1679-
"modalities": {
1680-
"input": [
1681-
"text",
1682-
"image",
1683-
"video"
1684-
],
1685-
"output": [
1686-
"text"
1687-
]
1688-
}
1689-
},
1690-
{
1691-
"id": "MiniMaxAI/MiniMax-M3-Free",
1692-
"name": "MiniMax M3 Free",
1693-
"tier": "open-source",
1694-
"reasoning": true,
1695-
"reasoningEfforts": [
1696-
"low",
1697-
"medium",
1698-
"high"
1699-
],
1700-
"tool_call": true,
1701-
"cost": {
1702-
"input": 0,
1703-
"output": 0
1704-
},
1705-
"limit": {
1706-
"context": 1000000,
1707-
"output": 65536
1708-
},
1709-
"attachment": true,
1710-
"modalities": {
1711-
"input": [
1712-
"text",
1713-
"image",
1714-
"video"
1715-
],
1716-
"output": [
1717-
"text"
1718-
]
1719-
}
1720-
},
17211552
{
17221553
"id": "meta/muse-spark-1.1",
17231554
"name": "Muse Spark 1.1",
@@ -2294,30 +2125,6 @@
22942125
]
22952126
}
22962127
},
2297-
{
2298-
"id": "tencent/Hy3",
2299-
"name": "Tencent Hy3 (Free)",
2300-
"tier": "open-source",
2301-
"reasoning": true,
2302-
"tool_call": true,
2303-
"cost": {
2304-
"input": 0,
2305-
"output": 0
2306-
},
2307-
"limit": {
2308-
"context": 262144,
2309-
"output": 65536
2310-
},
2311-
"attachment": false,
2312-
"modalities": {
2313-
"input": [
2314-
"text"
2315-
],
2316-
"output": [
2317-
"text"
2318-
]
2319-
}
2320-
},
23212128
{
23222129
"id": "tencent/hy4-preview",
23232130
"name": "Tencent Hy4 Preview",

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"test:integration": "bun test tests/integration/",
6363
"test:all": "bun test",
6464
"typecheck": "tsc --noEmit",
65+
"prepack": "bun run scripts/verify-manifest-version.ts",
6566
"verify:release-candidate": "bun run scripts/verify-release-candidate.ts",
6667
"generate-readme": "bun run scripts/generate-readme.ts",
6768
"sync": "bun run scripts/sync-models.ts",

release.config.cjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ module.exports = {
77
"@semantic-release/exec",
88
{
99
analyzeCommitsCmd: "bun scripts/analyze-release-scope.ts",
10+
// Stamp manifest.pluginVersion from nextRelease.version before
11+
// the npm plugin packs, so the published tarball embeds the
12+
// version it is published as.
13+
prepareCmd: "bun scripts/prepare-release-manifest.ts ${nextRelease.version}",
1014
},
1115
],
1216
"./scripts/semantic-release-catalog-notes.cjs",

scripts/catalog-sync-ci.ts

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,13 @@ import { existsSync, readFileSync } from "fs";
33
import { join } from "path";
44
import { execSync } from "child_process";
55
import { catalogBreakTitle, renderCatalogBreakBody } from "../src/catalog-break.js";
6-
import {
7-
lastSuccessfulModelCount,
8-
meetsModelCountFloor,
9-
type CatalogManifest,
10-
} from "../src/manifest.js";
116
import { decideCatalogSync } from "../src/publish-policy.js";
127
import { npmLatestVersion, npmPackageVersions } from "./npm-registry.js";
138

149
const ROOT = join(import.meta.dir, "..");
1510
const CATALOG_FILES = ["models.json", "_version.txt", "manifest.json"];
1611
const CATALOG_BRANCH = "chore/catalog-sync";
1712

18-
function readJson<T>(path: string): T | null {
19-
if (!existsSync(path)) return null;
20-
try {
21-
return JSON.parse(readFileSync(path, "utf-8")) as T;
22-
} catch {
23-
return null;
24-
}
25-
}
26-
2713
function bundledCommandCodeVersion(): string | null {
2814
const path = join(ROOT, "_version.txt");
2915
if (!existsSync(path)) return null;
@@ -123,7 +109,9 @@ async function main(): Promise<void> {
123109
return;
124110
}
125111

126-
const prior = readJson<CatalogManifest>(join(ROOT, "manifest.json"));
112+
// sync-models.ts validates availability and the model-count floor before the
113+
// first artifact write, so any failure there leaves the last-good catalog
114+
// untouched and routes here through the catalog-break issue path.
127115
const beforeModels = existsSync(join(ROOT, "models.json"))
128116
? readFileSync(join(ROOT, "models.json"), "utf-8")
129117
: "";
@@ -143,19 +131,6 @@ async function main(): Promise<void> {
143131
}
144132

145133
const afterModels = readFileSync(join(ROOT, "models.json"), "utf-8");
146-
const entries = JSON.parse(afterModels) as unknown[];
147-
const lastCount = lastSuccessfulModelCount(prior);
148-
if (!meetsModelCountFloor(entries.length, lastCount)) {
149-
const message = `model count ${entries.length} below floor (lastSuccessful=${lastCount})`;
150-
try {
151-
openOrUpdateCatalogBreak({ commandCodeVersion: latestCc, error: message });
152-
} catch (issueErr) {
153-
console.error("failed to open catalog-break issue", issueErr);
154-
}
155-
execSync(`git checkout -- ${CATALOG_FILES.join(" ")}`, { cwd: ROOT, stdio: "inherit" });
156-
process.exitCode = 1;
157-
return;
158-
}
159134

160135
const changed = afterModels !== beforeModels || bundledCommandCodeVersion() !== beforeVersion;
161136
if (!changed) {

0 commit comments

Comments
 (0)