add default providers and support overrides

This commit is contained in:
miloschwartz
2026-07-31 15:55:10 -04:00
parent f1a2da277e
commit 1333c8e841
6 changed files with 96 additions and 30 deletions
@@ -16,7 +16,7 @@ import {
aiBudgetUnitSchema,
aiProviderTypeSchema,
refineBudgetFields,
refineCustomProviderFields
refineProviderUpstreamFields
} from "@server/routers/aiProvider/validation";
const paramsSchema = z.strictObject({
@@ -36,7 +36,7 @@ const bodySchema = z
enabled: z.boolean().optional()
})
.superRefine((data, ctx) => {
refineCustomProviderFields(data, ctx);
refineProviderUpstreamFields(data, ctx);
refineBudgetFields(data, ctx);
});
+20 -13
View File
@@ -12,13 +12,17 @@ import { encrypt } from "@server/lib/crypto";
import config from "@server/lib/config";
import type { CreateOrEditAiProviderResponse } from "@server/routers/aiProvider/types";
import { toPublicAiProvider } from "@server/routers/aiProvider/types";
import type { AiProviderType } from "@server/lib/aiProviderDefaults";
import {
aiAuthTypeSchema,
aiBudgetUnitSchema,
aiProviderTypeSchema,
refineBudgetFields,
refineCustomProviderFields
refineProviderUpstreamFields
} from "@server/routers/aiProvider/validation";
import {
providerRequiresUpstreamUrl,
type AiProviderType
} from "@server/lib/aiProviderDefaults";
const paramsSchema = z.strictObject({
orgId: z.string().nonempty(),
@@ -115,26 +119,29 @@ export async function updateAiProvider(
}
const providerType = existing.type as AiProviderType;
const nextUpstreamUrl =
body.upstreamUrl !== undefined
? body.upstreamUrl
: existing.upstreamUrl;
const nextAuthType =
body.authType !== undefined ? body.authType : existing.authType;
if (providerType === "custom") {
const nextUpstreamUrl =
body.upstreamUrl !== undefined
? body.upstreamUrl
: existing.upstreamUrl;
const nextAuthType =
body.authType !== undefined ? body.authType : existing.authType;
if (
providerRequiresUpstreamUrl(providerType) ||
body.upstreamUrl !== undefined ||
body.authType !== undefined
) {
const validation = z
.object({
type: z.literal("custom"),
type: aiProviderTypeSchema,
upstreamUrl: z.string().nullable().optional(),
authType: aiAuthTypeSchema.nullable().optional()
})
.superRefine((data, ctx) =>
refineCustomProviderFields(data, ctx)
refineProviderUpstreamFields(data, ctx)
)
.safeParse({
type: "custom",
type: providerType,
upstreamUrl: nextUpstreamUrl,
authType: nextAuthType
});
+13 -11
View File
@@ -1,13 +1,19 @@
import { z } from "zod";
import type {
AiBudgetUnit,
AiProviderType
import {
providerRequiresUpstreamUrl,
type AiBudgetUnit,
type AiProviderType
} from "@server/lib/aiProviderDefaults";
export const aiProviderTypeSchema = z.enum([
"openai",
"anthropic",
"googleGemini",
"vertexAi",
"bedrock",
"microsoftFoundry",
"openRouter",
"vercelAiGateway",
"custom"
]);
@@ -36,7 +42,7 @@ export function refineBudgetFields(
}
}
export function refineCustomProviderFields(
export function refineProviderUpstreamFields(
data: {
type: AiProviderType;
upstreamUrl?: string | null;
@@ -44,19 +50,15 @@ export function refineCustomProviderFields(
},
ctx: z.RefinementCtx
) {
if (data.type !== "custom") {
return;
}
if (!data.upstreamUrl) {
if (providerRequiresUpstreamUrl(data.type) && !data.upstreamUrl) {
ctx.addIssue({
code: "custom",
message: "upstreamUrl is required for custom providers",
message: `upstreamUrl is required for ${data.type} providers`,
path: ["upstreamUrl"]
});
}
if (!data.authType) {
if (data.type === "custom" && !data.authType) {
ctx.addIssue({
code: "custom",
message: "authType is required for custom providers",