mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
This builds the model catalog from per-provider definitions and models.dev v2 data. It eplacer `generate-models.ts` with one `defineProvider()` file per built-in provider, shared model-family rules (Claude, GPT, DeepSeek, Kimi, Google), and source adapters. models.dev is read through its v2 API. Outputs and CLI flags are unchanged.
100 lines
3.5 KiB
TypeScript
100 lines
3.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { buildOpenRouterCatalog, type OpenRouterModelListItem } from "../catalog/sources/openrouter.ts";
|
|
|
|
const imageOnly: OpenRouterModelListItem = {
|
|
id: "example/image-model",
|
|
name: "Example Image Model",
|
|
architecture: {
|
|
input_modalities: ["text", "image"],
|
|
output_modalities: ["image"],
|
|
},
|
|
pricing: {
|
|
prompt: "0.000001",
|
|
completion: "0.000002",
|
|
},
|
|
};
|
|
|
|
const chatWithImages: OpenRouterModelListItem = {
|
|
id: "example/multimodal",
|
|
name: "Example Multimodal",
|
|
supported_parameters: ["tools"],
|
|
architecture: {
|
|
modality: "text+image->text+image",
|
|
input_modalities: ["text", "image"],
|
|
output_modalities: ["text", "image"],
|
|
},
|
|
context_length: 32000,
|
|
};
|
|
|
|
const chatOnly: OpenRouterModelListItem = {
|
|
id: "example/chat",
|
|
name: "Example Chat",
|
|
supported_parameters: ["tools"],
|
|
architecture: { modality: "text->text", output_modalities: ["text"] },
|
|
};
|
|
|
|
const decisionModel: OpenRouterModelListItem = {
|
|
id: "typesafe/jev-1.13",
|
|
name: "TypeSafe: Jev 1.13",
|
|
supported_parameters: [],
|
|
architecture: { modality: "text->decisions", input_modalities: ["text"], output_modalities: ["decisions"] },
|
|
pricing: { prompt: "0.000000042", completion: "0" },
|
|
context_length: 32000,
|
|
top_provider: { context_length: 32000, max_completion_tokens: 28800 },
|
|
};
|
|
|
|
describe("OpenRouter catalog parsing", () => {
|
|
it("emits image-only models from the image listing as image models", () => {
|
|
const catalog = buildOpenRouterCatalog([], [imageOnly], []);
|
|
expect(catalog.chat).toEqual([]);
|
|
expect(catalog.images).toEqual([
|
|
expect.objectContaining({
|
|
type: "image",
|
|
id: "example/image-model",
|
|
api: "openrouter-images",
|
|
input: ["text", "image"],
|
|
output: ["image"],
|
|
cost: expect.objectContaining({ input: 1, output: 2 }),
|
|
}),
|
|
]);
|
|
});
|
|
|
|
it("emits separate chat and image entries for an id that supports both operations", () => {
|
|
const catalog = buildOpenRouterCatalog([chatWithImages, chatOnly], [chatWithImages, imageOnly], []);
|
|
expect(catalog.chat.map((model) => model.id)).toEqual(["example/multimodal", "example/chat"]);
|
|
expect(catalog.chat.map((model) => model.type)).toEqual(["chat", "chat"]);
|
|
expect(catalog.images.map((model) => model.id)).toEqual(["example/multimodal", "example/image-model"]);
|
|
expect(catalog.images.every((model) => model.type === "image")).toBe(true);
|
|
expect(catalog.images.map((model) => model.output)).toEqual([["text", "image"], ["image"]]);
|
|
});
|
|
|
|
it("ignores listed models that neither support tools nor emit images", () => {
|
|
const catalog = buildOpenRouterCatalog(
|
|
[{ ...chatOnly, supported_parameters: [] }],
|
|
[{ ...imageOnly, architecture: { output_modalities: ["text"] } }],
|
|
[{ ...decisionModel, architecture: { output_modalities: ["text"] } }],
|
|
);
|
|
expect(catalog.chat).toEqual([]);
|
|
expect(catalog.images).toEqual([]);
|
|
expect(catalog.classifiers).toEqual([]);
|
|
});
|
|
|
|
it("emits decision models as System One classifier models", () => {
|
|
const catalog = buildOpenRouterCatalog([], [], [decisionModel, decisionModel]);
|
|
expect(catalog.chat).toEqual([]);
|
|
expect(catalog.classifiers).toEqual([
|
|
{
|
|
type: "classifier",
|
|
id: "typesafe/jev-1.13",
|
|
name: "TypeSafe: Jev 1.13",
|
|
api: "typesafe-system-one",
|
|
provider: "openrouter",
|
|
baseUrl: "https://openrouter.ai/api/v1",
|
|
input: ["text"],
|
|
cost: { input: 0.042, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
contextWindow: 32000,
|
|
compat: { imageInput: "state-image-urls", sendImageOptInHeader: false },
|
|
},
|
|
]);
|
|
});
|
|
});
|