diff --git a/packages/proxy/schema/index.test.ts b/packages/proxy/schema/index.test.ts index 38636068..c5a5f193 100644 --- a/packages/proxy/schema/index.test.ts +++ b/packages/proxy/schema/index.test.ts @@ -331,4 +331,29 @@ describe("APISecretSchema compatibility", () => { }); expect(result.success).toBe(false); }); + + it("preserves passthrough behavior for legacy Ollama api_base values", () => { + const cases: Array<{ name: string; api_base: unknown }> = [ + { name: "invalid url string", api_base: "not a url" }, + { name: "bare hostname", api_base: "localhost" }, + { name: "number", api_base: 12345 }, + { name: "boolean", api_base: true }, + { name: "object", api_base: { nested: 1 } }, + ]; + + for (const { name, api_base } of cases) { + const parsed = APISecretSchema.parse({ + secret: "ollama-secret", + type: "ollama", + metadata: { api_base }, + }); + if (parsed.type !== "ollama") { + throw new Error(`Expected ollama secret for case '${name}'`); + } + expect( + parsed.metadata?.api_base, + `case '${name}' should coerce to undefined to preserve runtime fallback`, + ).toBeUndefined(); + } + }); }); diff --git a/packages/proxy/schema/secrets.ts b/packages/proxy/schema/secrets.ts index a3dd180d..89f76d33 100644 --- a/packages/proxy/schema/secrets.ts +++ b/packages/proxy/schema/secrets.ts @@ -129,6 +129,15 @@ export const MistralMetadataSchema = BaseMetadataSchema.merge( }), ).passthrough(); +export const OllamaMetadataSchema = BaseMetadataSchema.merge( + z.object({ + api_base: z + .union([z.string().url(), z.string().length(0)]) + .nullish() + .catch(undefined), + }), +).passthrough(); + export const BraintrustMetadataSchema = BaseMetadataSchema.merge( z.object({ api_base: z.union([z.string().url(), z.string().length(0)]).nullish(), @@ -155,7 +164,6 @@ export const APISecretSchema = z.union([ "replicate", "together", "baseten", - "ollama", "groq", "lepton", "fireworks", @@ -208,6 +216,12 @@ export const APISecretSchema = z.union([ metadata: MistralMetadataSchema.nullish(), }), ).passthrough(), + APISecretBaseSchema.merge( + z.object({ + type: z.literal("ollama"), + metadata: OllamaMetadataSchema.nullish(), + }), + ).passthrough(), ]); export type APISecret = z.infer;