chore(vendor): import pi 1.3.0
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree. git-subtree-dir: third_party/pi git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { parseOpenRouterImageModels } from "../scripts/generate-image-models.ts";
|
||||
import { buildOpenRouterCatalog, type OpenRouterModelListItem } from "../scripts/openrouter-catalog.ts";
|
||||
|
||||
const validImageModel = {
|
||||
const imageOnly: OpenRouterModelListItem = {
|
||||
id: "example/image-model",
|
||||
name: "Example Image Model",
|
||||
architecture: {
|
||||
@@ -14,34 +14,86 @@ const validImageModel = {
|
||||
},
|
||||
};
|
||||
|
||||
describe("OpenRouter image model parsing", () => {
|
||||
it.each([{}, { data: [] }, { data: "invalid" }])("rejects a missing or empty strict catalog", (payload) => {
|
||||
expect(() => parseOpenRouterImageModels(payload, true)).toThrow("missing or empty image model list");
|
||||
});
|
||||
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,
|
||||
};
|
||||
|
||||
it("rejects a strict catalog with no usable image models", () => {
|
||||
expect(() =>
|
||||
parseOpenRouterImageModels(
|
||||
{
|
||||
data: [
|
||||
{
|
||||
...validImageModel,
|
||||
architecture: { input_modalities: ["text"], output_modalities: ["text"] },
|
||||
},
|
||||
],
|
||||
},
|
||||
true,
|
||||
),
|
||||
).toThrow("no usable image models");
|
||||
});
|
||||
const chatOnly: OpenRouterModelListItem = {
|
||||
id: "example/chat",
|
||||
name: "Example Chat",
|
||||
supported_parameters: ["tools"],
|
||||
architecture: { modality: "text->text", output_modalities: ["text"] },
|
||||
};
|
||||
|
||||
it("parses a non-empty image model catalog", () => {
|
||||
expect(parseOpenRouterImageModels({ data: [validImageModel] }, true)).toEqual([
|
||||
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,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user