import { describe, expect, it } from "bun:test"; import { checkOpencodeModels } from "../../.opencode/model-check.js"; import { assertModelCheckPassed, type ModelCheckInput } from "../../src/runtime/model-check.js"; const targets: ModelCheckInput = { models: [ { id: "custom/alias", provider_id: "custom", model_id: "alias", wire_id: "org/model", requires_tools: true }, { id: "custom/typo", provider_id: "custom", model_id: "typo", wire_id: "does-not-exist", requires_tools: true }, ] }; describe("OpenCode model validation", () => { it("rejects a manually registered invalid name and validates the actual upstream alias", async () => { const originalFetch = globalThis.fetch; let queries = 0; globalThis.fetch = (async (input: unknown, init: RequestInit) => { queries++; expect(String(input)).toBe("https://example.com/v1/models"); expect(new Headers(init.headers).get("Authorization")).toBe("Bearer TEST_ONLY_SECRET"); expect(init.redirect).toBe("error"); return Response.json({ data: [{ id: "org/model" }] }); }) as typeof fetch; try { const report = await checkOpencodeModels({ model: { list: async () => ({ data: targets.models.map((model) => ({ id: model.model_id, modelID: model.wire_id, providerID: "custom", enabled: true, capabilities: { tools: true } })) }) }, provider: { get: async () => ({ data: { package: "@opencode/ai/providers/openai-compatible", settings: { baseURL: "https://example.com/v1", apiKey: "TEST_ONLY_SECRET" } } }) }, } as never, targets, new AbortController().signal); expect(report.models.map((model) => model.status)).toEqual(["valid", "not_advertised"]); expect(queries).toBe(1); expect(() => assertModelCheckPassed(report)).toThrow("custom/typo: not_advertised"); expect(JSON.stringify(report)).not.toContain("TEST_ONLY_SECRET"); expect(JSON.stringify(report)).not.toContain("example.com"); } finally { globalThis.fetch = originalFetch; } }); it("reports unavailable, non-tool and mismatched native models", async () => { const originalFetch = globalThis.fetch; globalThis.fetch = (async () => Response.json({ data: [{ id: "org/model" }, { id: "does-not-exist" }] })) as unknown as typeof fetch; try { for (const [native, expected] of [ [undefined, "not_registered"], [{ enabled: false, modelID: "org/model", capabilities: { tools: true } }, "not_enabled"], [{ enabled: true, modelID: "org/model", capabilities: { tools: false } }, "no_tools"], [{ enabled: true, modelID: "different", capabilities: { tools: true } }, "wire_id_mismatch"], ] as const) { const report = await checkOpencodeModels({ model: { list: async () => ({ data: native ? [{ id: "alias", providerID: "custom", ...native }] : [] }) }, provider: { get: async () => ({ data: { package: "@opencode/ai/providers/openai-compatible", settings: { baseURL: "https://example.com/v1", apiKey: "TEST_ONLY_SECRET" } } }) }, } as never, { models: [targets.models[0]!] }, new AbortController().signal); expect(report.models[0]!.status).toBe(expected); expect(() => assertModelCheckPassed(report)).toThrow(); } } finally { globalThis.fetch = originalFetch; } }); it("fails closed on auth, empty/invalid inventory and cancellation without exposing upstream errors", async () => { const originalFetch = globalThis.fetch; const context = { model: { list: async () => ({ data: [{ id: "alias", modelID: "org/model", providerID: "custom", enabled: true, capabilities: { tools: true } }] }) }, provider: { get: async () => ({ data: { package: "@opencode/ai/providers/openai-compatible", settings: { baseURL: "https://example.com/v1", apiKey: "TEST_ONLY_SECRET" } } }) }, } as never; try { for (const response of [Response.json({ secret: "TEST_ONLY_SECRET" }, { status: 401 }), Response.json({ data: [] }), Response.json({ data: [{ wrong: true }] })]) { globalThis.fetch = (async () => response) as unknown as typeof fetch; const report = await checkOpencodeModels(context, { models: [targets.models[0]!] }, new AbortController().signal); expect(() => assertModelCheckPassed(report)).toThrow(); expect(JSON.stringify(report)).not.toContain("TEST_ONLY_SECRET"); } globalThis.fetch = (async (_input: unknown, init: RequestInit) => { init.signal!.throwIfAborted(); throw new Error("should not query"); }) as unknown as typeof fetch; const controller = new AbortController(); controller.abort(); const report = await checkOpencodeModels(context, { models: [targets.models[0]!] }, controller.signal); expect(report.providers[0]!.status).toBe("catalog_unavailable"); } finally { globalThis.fetch = originalFetch; } }); });