import { describe, expect, test } from "vitest"; import { createBuiltinProviderProfileResolver } from "../src/agents/provider-profiles.js"; describe("trusted provider profiles", () => { test("keeps Tinker endpoint and credential selection on the trusted host", () => { const resolver = createBuiltinProviderProfileResolver({ THOUGHTSTREAM_TINKER_ALLOWED_MODELS: "custom/checkpoint", THOUGHTSTREAM_TINKER_ESCALATION_MODEL: "openai/gpt-oss-120b", }); expect(resolver.resolve("tinker-default", "custom/checkpoint")).toMatchObject({ provider: "tinker", baseUrl: "https://tinker.thinkingmachines.dev/services/tinker-prod/oai/api/v1", route: "/chat/completions", apiKeyEnv: "TINKER_API_KEY", imageInputModels: new Set(["thinkingmachines/Inkling", "thinkingmachines/Inkling-Small"]), jsonObjectResponseFormat: false, jsonSchemaResponseFormat: false, }); expect(resolver.resolve("tinker-default", "openai/gpt-oss-120b")).toMatchObject({ provider: "tinker", apiKeyEnv: "TINKER_API_KEY", }); expect(resolver.resolve("tinker-default", "thinkingmachines/Inkling-Small")).toMatchObject({ provider: "tinker", apiKeyEnv: "TINKER_API_KEY", }); expect(() => resolver.resolve("tinker-default", "not-allowlisted")).toThrow("not allowlisted"); }); test("requires explicit trusted-host configuration for OpenAI-compatible providers", () => { const resolver = createBuiltinProviderProfileResolver({ THOUGHTSTREAM_MODEL_BASE_URL: "https://models.example.test/v1", THOUGHTSTREAM_MODEL_ALLOWED_MODELS: "small,large", THOUGHTSTREAM_MODEL_IMAGE_MODELS: "large", }); expect(resolver.resolve("openai-compatible-default", "small")).toMatchObject({ provider: "openai-compatible", baseUrl: "https://models.example.test/v1", apiKeyEnv: "THOUGHTSTREAM_MODEL_API_KEY", imageInputModels: new Set(["large"]), }); expect(() => createBuiltinProviderProfileResolver({ THOUGHTSTREAM_MODEL_BASE_URL: "http://models.example.test/v1", THOUGHTSTREAM_MODEL_ALLOWED_MODELS: "small", }).resolve("openai-compatible-default", "small")).toThrow("must use HTTPS"); }); test("keeps the JSON-enforcing OpenAI profile fixed and narrow", () => { const resolver = createBuiltinProviderProfileResolver({}); expect(resolver.resolve("openai-json-default", "gpt-4.1-mini")).toMatchObject({ provider: "openai-compatible", baseUrl: "https://api.openai.com/v1", route: "/chat/completions", apiKeyEnv: "OPENAI_API_KEY", allowedModels: new Set(["gpt-4.1-mini"]), jsonObjectResponseFormat: false, jsonSchemaResponseFormat: true, }); expect(() => resolver.resolve("openai-json-default", "gpt-4.1")).toThrow("not allowlisted"); }); test("keeps non-allowlisted image model values out of profile errors", () => { const privateModel = "tinker://SYNTHETIC_PRIVATE_IMAGE_FIXTURE"; try { createBuiltinProviderProfileResolver({ THOUGHTSTREAM_MODEL_BASE_URL: "https://models.example.test/v1", THOUGHTSTREAM_MODEL_ALLOWED_MODELS: "small", THOUGHTSTREAM_MODEL_IMAGE_MODELS: privateModel, }).resolve("openai-compatible-default", "small"); throw new Error("Expected image-model profile rejection"); } catch (error) { expect(String(error)).toContain("marks a non-allowlisted model as image-capable"); expect(String(error)).not.toContain(privateModel); } }); });