Files
pi/scripts/model-catalog-protocol.test.ts
Armin Ronacher 7fd564cbb7 feat: share model catalog protocol with pi.dev (#9763)
Move catalog layout, index validation, version selection, and request
negotiation into scripts/model-catalog-protocol.ts. pi.dev keeps an
identical copy, so the publisher and a test running the current client
exercise the same selection pi.dev performs. Replaces the cross-repository
compatibility dispatch.

Related to #9099.
2026-09-23 20:08:05 +02:00

121 lines
4.6 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import {
compareModelCatalogPiVersions,
getModelCatalogArtifactKey,
getModelCatalogProviderKey,
type ModelCatalogIndex,
parseModelCatalogIndex,
parseModelCatalogRepresentation,
parseModelCatalogRequest,
selectModelCatalog,
} from "./model-catalog-protocol.ts";
const legacyRevision = `sha256-${"a".repeat(64)}`;
const mixedApiRevision = `sha256-${"b".repeat(64)}`;
const index: ModelCatalogIndex = {
schemaVersion: 1,
defaultRevision: mixedApiRevision,
catalogs: [
{ minimumPiVersion: "0.80.7", revision: legacyRevision },
{ minimumPiVersion: "0.85.0", revision: mixedApiRevision },
],
};
test("builds revision scoped storage keys", () => {
assert.equal(
getModelCatalogArtifactKey(legacyRevision, "models.json"),
`models/v1/revisions/${legacyRevision}/models.json`,
);
assert.equal(
getModelCatalogProviderKey(legacyRevision, "openrouter", "legacy"),
`models/v1/revisions/${legacyRevision}/providers/openrouter.json`,
);
assert.equal(
getModelCatalogProviderKey(legacyRevision, "openrouter", "typed"),
`models/v1/revisions/${legacyRevision}/providers/openrouter.all.json`,
);
});
test("orders Pi versions with semver precedence", () => {
assert.ok(compareModelCatalogPiVersions("0.85.0", "0.84.4") > 0);
assert.ok(compareModelCatalogPiVersions("0.85.0-rc.1", "0.85.0") < 0);
assert.ok(compareModelCatalogPiVersions("0.85.0-rc.2", "0.85.0-rc.10") < 0);
assert.equal(compareModelCatalogPiVersions("v1.0.0", "1.0.0+build"), 0);
assert.throws(() => compareModelCatalogPiVersions("0.85", "0.85.0"), /Invalid Pi version/);
});
test("selects the newest catalog a Pi version supports", () => {
// Regression test for #9099: released clients before 0.85.0 cannot use the mixed-API catalog.
assert.equal(selectModelCatalog(index, "0.84.4")?.revision, legacyRevision);
assert.equal(selectModelCatalog(index, "0.85.0-rc.1")?.revision, legacyRevision);
assert.equal(selectModelCatalog(index, "0.85.0")?.revision, mixedApiRevision);
assert.equal(selectModelCatalog(index, "1.0.0")?.revision, mixedApiRevision);
assert.equal(selectModelCatalog(index, "0.80.6"), undefined);
assert.equal(selectModelCatalog(index, undefined)?.revision, mixedApiRevision);
});
test("redirects Pi user agents to an explicit catalog version", () => {
// Regression test for #9099: released clients identify themselves only by User-Agent.
assert.deepEqual(
parseModelCatalogRequest(
"https://pi.dev/api/models/providers/openrouter?types=chat%2Cimage",
"pi/0.84.4 (linux; node/v22.0.0; x64)",
),
{
kind: "redirect",
location: "https://pi.dev/api/models/providers/openrouter?types=chat%2Cimage&pi-version=0.84.4",
},
);
assert.deepEqual(parseModelCatalogRequest("https://pi.dev/api/models", "pi/0.84.4"), {
kind: "redirect",
location: "https://pi.dev/api/models?pi-version=0.84.4",
});
});
test("serves explicit and unversioned catalog requests without redirecting", () => {
assert.deepEqual(
parseModelCatalogRequest("https://pi.dev/api/models?pi-version=0.83.0", "pi/0.85.1 (linux; node/v22.0.0; x64)"),
{ kind: "catalog", piVersion: "0.83.0", representation: "legacy" },
);
assert.deepEqual(parseModelCatalogRequest("https://pi.dev/api/models?types=chat", "curl/8.0.0"), {
kind: "catalog",
piVersion: undefined,
representation: "typed",
});
assert.deepEqual(parseModelCatalogRequest("https://pi.dev/api/models", "pi/latest"), {
kind: "catalog",
piVersion: undefined,
representation: "legacy",
});
});
test("rejects invalid catalog request parameters", () => {
assert.deepEqual(parseModelCatalogRequest("https://pi.dev/api/models?pi-version=latest", undefined), {
kind: "invalid",
error: "Invalid Pi version.",
});
assert.deepEqual(parseModelCatalogRequest("https://pi.dev/api/models?types=", "pi/0.84.4"), {
kind: "invalid",
error: "Invalid model types.",
});
assert.equal(parseModelCatalogRepresentation("chat,-image"), undefined);
assert.equal(parseModelCatalogRepresentation(null), "legacy");
});
test("validates stored indexes and drops publication metadata", () => {
assert.deepEqual(
parseModelCatalogIndex({
...index,
catalogs: index.catalogs.map((catalog) => ({ ...catalog, sourceCommit: "abc", modelCount: 1 })),
}),
index,
);
assert.throws(() => parseModelCatalogIndex({ ...index, schemaVersion: 2 }), /index is invalid/);
assert.throws(() => parseModelCatalogIndex({ ...index, defaultRevision: `sha256-${"c".repeat(64)}` }), /invalid/);
assert.throws(
() => parseModelCatalogIndex({ ...index, catalogs: [{ minimumPiVersion: "latest", revision: legacyRevision }] }),
/invalid/,
);
});