set provider default capabilities

This commit is contained in:
miloschwartz
2026-08-07 12:25:29 -04:00
parent d699455b38
commit 297cb9c8f2
4 changed files with 51 additions and 56 deletions
-37
View File
@@ -1,5 +1,4 @@
import type { Request } from "express"; import type { Request } from "express";
import type { AiProviderType } from "@server/lib/aiProviderDefaults";
export const AI_CAPABILITIES = [ export const AI_CAPABILITIES = [
"openai_chat", "openai_chat",
@@ -188,20 +187,6 @@ export const AI_CAPABILITY_DEFS: Record<AiCapability, AiCapabilityDefinition> =
} }
}; };
export const AI_PROVIDER_CAPABILITY_DEFAULTS: Record<
Exclude<AiProviderType, "custom">,
readonly AiCapability[]
> = {
openai: ["openai_chat"],
anthropic: ["anthropic_messages"],
googleGemini: ["gemini_generate_content"],
vertexAi: ["google_generate_content"],
bedrock: ["bedrock_converse"],
microsoftFoundry: ["openai_chat"],
openRouter: ["openai_chat"],
vercelAiGateway: ["openai_chat"]
};
export function isAiCapability(value: unknown): value is AiCapability { export function isAiCapability(value: unknown): value is AiCapability {
return ( return (
typeof value === "string" && typeof value === "string" &&
@@ -256,25 +241,3 @@ export function providerHasCapability(
: capabilities; : capabilities;
return list.includes(capability); return list.includes(capability);
} }
export function resolveCapabilitiesForCreate(input: {
type: AiProviderType;
capabilities?: AiCapability[] | null;
}): AiCapability[] {
if (input.capabilities != null) {
return parseCapabilities(input.capabilities);
}
if (input.type === "custom") {
return [];
}
return [...AI_PROVIDER_CAPABILITY_DEFAULTS[input.type]];
}
export function defaultsForProviderType(
type: AiProviderType
): readonly AiCapability[] {
if (type === "custom") {
return [];
}
return AI_PROVIDER_CAPABILITY_DEFAULTS[type];
}
+43 -8
View File
@@ -1,4 +1,8 @@
import { decrypt, encrypt } from "@server/lib/crypto"; import { decrypt, encrypt } from "@server/lib/crypto";
import {
parseCapabilities,
type AiCapability
} from "@server/lib/aiCapabilities";
export type AiProviderType = export type AiProviderType =
| "openai" | "openai"
@@ -28,6 +32,7 @@ export type AiProviderRoutingMode = "url" | "target";
type AiProviderDefaults = { type AiProviderDefaults = {
upstreamUrl: string | null; upstreamUrl: string | null;
authType: AiProviderAuthType; authType: AiProviderAuthType;
capabilities: readonly AiCapability[];
}; };
export const AI_PROVIDER_DEFAULTS: Record< export const AI_PROVIDER_DEFAULTS: Record<
@@ -36,35 +41,43 @@ export const AI_PROVIDER_DEFAULTS: Record<
> = { > = {
openai: { openai: {
upstreamUrl: "https://api.openai.com/v1", upstreamUrl: "https://api.openai.com/v1",
authType: "bearer" authType: "bearer",
capabilities: ["openai_chat", "openai_responses"]
}, },
anthropic: { anthropic: {
upstreamUrl: "https://api.anthropic.com", upstreamUrl: "https://api.anthropic.com",
authType: "x-api-key" authType: "x-api-key",
capabilities: ["anthropic_messages"]
}, },
googleGemini: { googleGemini: {
upstreamUrl: "https://generativelanguage.googleapis.com", upstreamUrl: "https://generativelanguage.googleapis.com",
authType: "x-goog-api-key" authType: "x-goog-api-key",
capabilities: ["gemini_generate_content"]
}, },
vertexAi: { vertexAi: {
upstreamUrl: null, upstreamUrl: null,
authType: "bearer" authType: "bearer",
capabilities: ["google_generate_content", "google_raw_predict"]
}, },
bedrock: { bedrock: {
upstreamUrl: "https://bedrock-runtime.us-east-1.amazonaws.com", upstreamUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
authType: "bearer" authType: "bearer",
capabilities: ["bedrock_converse"]
}, },
microsoftFoundry: { microsoftFoundry: {
upstreamUrl: null, upstreamUrl: null,
authType: "bearer" authType: "bearer",
capabilities: ["openai_chat", "openai_responses", "anthropic_messages"]
}, },
openRouter: { openRouter: {
upstreamUrl: "https://openrouter.ai/api/v1", upstreamUrl: "https://openrouter.ai/api/v1",
authType: "bearer" authType: "bearer",
capabilities: ["openai_chat"]
}, },
vercelAiGateway: { vercelAiGateway: {
upstreamUrl: "https://ai-gateway.vercel.sh/v1", upstreamUrl: "https://ai-gateway.vercel.sh/v1",
authType: "bearer" authType: "bearer",
capabilities: ["openai_chat", "openai_responses"]
} }
}; };
@@ -225,3 +238,25 @@ export function applyAiProviderAuthHeaders(
break; break;
} }
} }
export function resolveCapabilitiesForCreate(input: {
type: AiProviderType;
capabilities?: AiCapability[] | null;
}): AiCapability[] {
if (input.capabilities != null) {
return parseCapabilities(input.capabilities);
}
if (input.type === "custom") {
return [];
}
return [...AI_PROVIDER_DEFAULTS[input.type].capabilities];
}
export function defaultsForProviderType(
type: AiProviderType
): readonly AiCapability[] {
if (type === "custom") {
return [];
}
return AI_PROVIDER_DEFAULTS[type].capabilities;
}
@@ -9,7 +9,11 @@ import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { encrypt } from "@server/lib/crypto"; import { encrypt } from "@server/lib/crypto";
import config from "@server/lib/config"; import config from "@server/lib/config";
import { resolveAiProviderCreateFields } from "@server/lib/aiProviderDefaults"; import {
resolveAiProviderCreateFields,
resolveCapabilitiesForCreate,
serializeAiProviderHeaders
} from "@server/lib/aiProviderDefaults";
import type { CreateOrEditAiProviderResponse } from "@server/routers/aiProvider/types"; import type { CreateOrEditAiProviderResponse } from "@server/routers/aiProvider/types";
import { toPublicAiProvider } from "@server/routers/aiProvider/types"; import { toPublicAiProvider } from "@server/routers/aiProvider/types";
import { import {
@@ -20,11 +24,7 @@ import {
aiRoutingModeSchema, aiRoutingModeSchema,
refineProviderUpstreamFields refineProviderUpstreamFields
} from "@server/routers/aiProvider/validation"; } from "@server/routers/aiProvider/validation";
import { serializeAiProviderHeaders } from "@server/lib/aiProviderDefaults"; import { serializeCapabilities } from "@server/lib/aiCapabilities";
import {
resolveCapabilitiesForCreate,
serializeCapabilities
} from "@server/lib/aiCapabilities";
const paramsSchema = z.strictObject({ const paramsSchema = z.strictObject({
orgId: z.string().nonempty() orgId: z.string().nonempty()
+2 -5
View File
@@ -3,15 +3,12 @@ import {
AI_PROVIDER_AUTH_TYPES, AI_PROVIDER_AUTH_TYPES,
AI_PROVIDER_DEFAULTS, AI_PROVIDER_DEFAULTS,
authTypeRequiresApiKey, authTypeRequiresApiKey,
defaultsForProviderType,
providerRequiresUpstreamUrl, providerRequiresUpstreamUrl,
type AiProviderAuthType, type AiProviderAuthType,
type AiProviderType type AiProviderType
} from "@server/lib/aiProviderDefaults"; } from "@server/lib/aiProviderDefaults";
import { import { AI_CAPABILITIES, type AiCapability } from "@server/lib/aiCapabilities";
AI_CAPABILITIES,
defaultsForProviderType,
type AiCapability
} from "@server/lib/aiCapabilities";
type TranslateFn = (key: string) => string; type TranslateFn = (key: string) => string;