refactor(ai): separate Vertex API routes (#37275)

This commit is contained in:
Shoubhit Dash 2026-07-16 17:17:15 +05:30 committed by GitHub
commit 282f3f7eb2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 120 additions and 126 deletions

View file

@ -1,42 +0,0 @@
import { Effect, Schema, Struct } from "effect"
import { AnthropicMessages } from "./anthropic-messages"
import { Auth } from "../route/auth"
import { Route } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { Framing } from "../route/framing"
import { Protocol } from "../route/protocol"
const VERSION = "vertex-2023-10-16" as const
export const GoogleVertexAnthropicBody = Schema.Struct({
...Struct.omit(AnthropicMessages.AnthropicMessagesBody.fields, ["model"]),
anthropic_version: Schema.Literal(VERSION),
})
export type GoogleVertexAnthropicBody = Schema.Schema.Type<typeof GoogleVertexAnthropicBody>
export const protocol = Protocol.make({
id: "google-vertex-anthropic",
body: {
schema: GoogleVertexAnthropicBody,
from: (request) =>
AnthropicMessages.protocol.body.from(request).pipe(
Effect.map((body) => ({
...Struct.omit(body, ["model"]),
anthropic_version: VERSION,
})),
),
},
stream: AnthropicMessages.protocol.stream,
})
export const route = Route.make({
id: "google-vertex-anthropic",
provider: "google-vertex-anthropic",
providerMetadataKey: "anthropic",
protocol,
endpoint: Endpoint.path(({ request }) => `/${request.model.id}:streamRawPredict`),
auth: Auth.none,
framing: Framing.sse,
})
export * as GoogleVertexAnthropic from "./google-vertex-anthropic"

View file

@ -1,20 +0,0 @@
import { Gemini } from "./gemini"
import { Auth } from "../route/auth"
import { Route } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { Framing } from "../route/framing"
export const route = Route.make({
id: "google-vertex-gemini",
provider: "google-vertex",
providerMetadataKey: "google",
protocol: Gemini.protocol,
endpoint: Endpoint.path(({ request }) => {
const model = String(request.model.id)
return `/${model.startsWith("endpoints/") ? model : `models/${model}`}:streamGenerateContent?alt=sse`
}),
auth: Auth.none,
framing: Framing.sse,
})
export * as GoogleVertexGemini from "./google-vertex-gemini"

View file

@ -1,6 +1,4 @@
export * as AnthropicMessages from "./anthropic-messages"
export * as GoogleVertexAnthropic from "./google-vertex-anthropic"
export * as GoogleVertexGemini from "./google-vertex-gemini"
export * as BedrockConverse from "./bedrock-converse"
export * as Gemini from "./gemini"
export * as OpenAIChat from "./openai-chat"

View file

@ -1,9 +1,17 @@
import { Effect, Schema, Struct } from "effect"
import type { ProviderPackage } from "../provider-package"
import { GoogleVertexAnthropic } from "../protocols/google-vertex-anthropic"
import type { RouteDefaultsInput } from "../route/client"
import { AnthropicMessages } from "../protocols/anthropic-messages"
import { Auth } from "../route/auth"
import { Route, type RouteDefaultsInput } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { Framing } from "../route/framing"
import { Protocol } from "../route/protocol"
import { ProviderID, type ModelID, type ProviderOptions } from "../schema"
import { GoogleVertexShared } from "./google-vertex-shared"
const VERSION = "vertex-2023-10-16" as const
// models.dev uses this provider id even though the API contract is Anthropic Messages.
export const id = ProviderID.make("google-vertex-anthropic")
export type Config = RouteDefaultsInput &
@ -22,11 +30,37 @@ export interface Settings extends ProviderPackage.Settings {
readonly providerOptions?: ProviderOptions
}
export const routes = [GoogleVertexAnthropic.route]
const route = Route.make({
id: "google-vertex-messages",
provider: id,
providerMetadataKey: "anthropic",
protocol: Protocol.make({
id: AnthropicMessages.protocol.id,
body: {
schema: Schema.Struct({
...Struct.omit(AnthropicMessages.AnthropicMessagesBody.fields, ["model"]),
anthropic_version: Schema.Literal(VERSION),
}),
from: (request) =>
AnthropicMessages.protocol.body.from(request).pipe(
Effect.map((body) => ({
...Struct.omit(body, ["model"]),
anthropic_version: VERSION,
})),
),
},
stream: AnthropicMessages.protocol.stream,
}),
endpoint: Endpoint.path(({ request }) => `/${request.model.id}:streamRawPredict`),
auth: Auth.none,
framing: Framing.sse,
})
export const routes = [route]
const configuredRoute = (input: Config) => {
if ("apiKey" in input && input.apiKey !== undefined)
throw new Error("Google Vertex Anthropic does not support API keys")
throw new Error("Google Vertex Messages does not support API keys")
const {
accessToken: _accessToken,
auth: _auth,
@ -37,7 +71,7 @@ const configuredRoute = (input: Config) => {
} = input
const location = GoogleVertexShared.location(inputLocation, "global")
const project = GoogleVertexShared.project(inputProject)
return GoogleVertexAnthropic.route.with({
return route.with({
...rest,
endpoint: {
baseURL:
@ -63,7 +97,7 @@ export const provider = {
}
export const model: ProviderPackage.Definition<Settings>["model"] = (modelID, settings) => {
if (settings.apiKey !== undefined) throw new Error("Google Vertex Anthropic does not support API keys")
if (settings.apiKey !== undefined) throw new Error("Google Vertex Messages does not support API keys")
return configure({
accessToken: settings.accessToken,
baseURL: settings.baseURL,

View file

@ -1,7 +1,9 @@
import type { ProviderPackage } from "../provider-package"
import { GoogleVertexGemini } from "../protocols/google-vertex-gemini"
import { Gemini } from "../protocols/gemini"
import { Auth } from "../route/auth"
import type { RouteDefaultsInput } from "../route/client"
import { Route, type RouteDefaultsInput } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { Framing } from "../route/framing"
import { ProviderID, type ModelID, type ProviderOptions } from "../schema"
import { GoogleVertexShared } from "./google-vertex-shared"
@ -25,7 +27,20 @@ export type Settings = ProviderPackage.Settings &
readonly providerOptions?: ProviderOptions
}
export const routes = [GoogleVertexGemini.route]
const route = Route.make({
id: "google-vertex-gemini",
provider: id,
providerMetadataKey: "google",
protocol: Gemini.protocol,
endpoint: Endpoint.path(({ request }) => {
const model = String(request.model.id)
return `/${model.startsWith("endpoints/") ? model : `models/${model}`}:streamGenerateContent?alt=sse`
}),
auth: Auth.none,
framing: Framing.sse,
})
export const routes = [route]
const configuredRoute = (input: Config, modelID: string | ModelID) => {
const {
@ -48,7 +63,7 @@ const configuredRoute = (input: Config, modelID: string | ModelID) => {
(apiKey
? "https://aiplatform.googleapis.com/v1/publishers/google"
: `https://${GoogleVertexShared.host(location)}/v1beta1/projects/${GoogleVertexShared.requireProject(project)}/locations/${location}${endpointModel ? "" : "/publishers/google"}`)
return GoogleVertexGemini.route.with({
return route.with({
...rest,
endpoint: { baseURL: endpoint },
auth: apiKey === undefined ? GoogleVertexShared.oauth(input, project) : Auth.header("x-goog-api-key", apiKey),

View file

@ -1,2 +0,0 @@
export { model } from "../google-vertex-anthropic"
export type { Settings } from "../google-vertex-anthropic"

View file

@ -0,0 +1,2 @@
export { model } from "../google-vertex"
export type { Settings } from "../google-vertex"

View file

@ -0,0 +1,2 @@
export { model } from "../google-vertex-messages"
export type { Settings } from "../google-vertex-messages"

View file

@ -7,7 +7,7 @@ export { CloudflareAIGateway, CloudflareWorkersAI } from "./cloudflare"
export * as GitHubCopilot from "./github-copilot"
export * as Google from "./google"
export * as GoogleVertex from "./google-vertex"
export * as GoogleVertexAnthropic from "./google-vertex-anthropic"
export * as GoogleVertexMessages from "./google-vertex-messages"
export * as OpenAI from "./openai"
export * as OpenAICompatible from "./openai-compatible"
export * as OpenAICompatibleResponses from "./openai-compatible-responses"