|
| 1 | +import { describe, expect, test } from "bun:test"; |
| 2 | +import { filterCatalogVisibleModels, type CatalogModel } from "../src/codex-catalog"; |
| 3 | +import type { OcxConfig, OcxProviderConfig } from "../src/types"; |
| 4 | + |
| 5 | +function m(provider: string, id: string): CatalogModel { |
| 6 | + return { provider, id, owned_by: provider }; |
| 7 | +} |
| 8 | + |
| 9 | +function cfg(providers: Record<string, Partial<OcxProviderConfig>>, disabledModels?: string[]): Pick<OcxConfig, "disabledModels" | "providers"> { |
| 10 | + const full: Record<string, OcxProviderConfig> = {}; |
| 11 | + for (const [name, p] of Object.entries(providers)) full[name] = { adapter: "openai-chat", baseUrl: "https://x", ...p }; |
| 12 | + return { providers: full, ...(disabledModels ? { disabledModels } : {}) }; |
| 13 | +} |
| 14 | + |
| 15 | +describe("filterCatalogVisibleModels — per-provider allowlist", () => { |
| 16 | + const models = [m("proxy", "a"), m("proxy", "b"), m("proxy", "c"), m("openai", "gpt-5.5")]; |
| 17 | + |
| 18 | + test("no selectedModels → all models pass", () => { |
| 19 | + const out = filterCatalogVisibleModels(models, cfg({ proxy: {}, openai: {} })); |
| 20 | + expect(out.map(x => x.id).sort()).toEqual(["a", "b", "c", "gpt-5.5"]); |
| 21 | + }); |
| 22 | + |
| 23 | + test("empty selectedModels array → treated as all", () => { |
| 24 | + const out = filterCatalogVisibleModels(models, cfg({ proxy: { selectedModels: [] }, openai: {} })); |
| 25 | + expect(out.map(x => x.id).sort()).toEqual(["a", "b", "c", "gpt-5.5"]); |
| 26 | + }); |
| 27 | + |
| 28 | + test("non-empty allowlist keeps only listed ids for that provider, others untouched", () => { |
| 29 | + const out = filterCatalogVisibleModels(models, cfg({ proxy: { selectedModels: ["a", "c"] }, openai: {} })); |
| 30 | + expect(out.map(x => `${x.provider}/${x.id}`).sort()).toEqual(["openai/gpt-5.5", "proxy/a", "proxy/c"]); |
| 31 | + }); |
| 32 | + |
| 33 | + test("allowlist is per-provider — an id present under another provider is not leaked", () => { |
| 34 | + const withDup = [...models, m("openai", "a")]; |
| 35 | + const out = filterCatalogVisibleModels(withDup, cfg({ proxy: { selectedModels: ["a"] }, openai: {} })); |
| 36 | + expect(out.map(x => `${x.provider}/${x.id}`).sort()).toEqual(["openai/a", "openai/gpt-5.5", "proxy/a"]); |
| 37 | + }); |
| 38 | + |
| 39 | + test("disabledModels blocklist still applies alongside the allowlist", () => { |
| 40 | + const out = filterCatalogVisibleModels(models, cfg({ proxy: { selectedModels: ["a", "b"] }, openai: {} }, ["proxy/b"])); |
| 41 | + expect(out.map(x => `${x.provider}/${x.id}`).sort()).toEqual(["openai/gpt-5.5", "proxy/a"]); |
| 42 | + }); |
| 43 | + |
| 44 | + test("large list collapses to the few selected (the issue #52 shape)", () => { |
| 45 | + const big = Array.from({ length: 2000 }, (_, i) => m("proxy", `model-${i}`)); |
| 46 | + const out = filterCatalogVisibleModels(big, cfg({ proxy: { selectedModels: ["model-7", "model-1999"] } })); |
| 47 | + expect(out.map(x => x.id).sort()).toEqual(["model-1999", "model-7"]); |
| 48 | + }); |
| 49 | +}); |
0 commit comments