mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-06 01:30:08 +00:00
refactor(ai): share the Vertex OAuth route setup (#61160)
This commit is contained in:
parent
5d24e0dc5b
commit
ff5be41bf7
5 changed files with 108 additions and 158 deletions
|
|
@ -2,7 +2,7 @@ import type { ProviderPackage } from "../provider-package.js"
|
|||
import { OpenAIChat } from "../protocols/openai-chat.js"
|
||||
import { Route, type RouteDefaultsInput } from "../route/client.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { ProviderConfigurationError, ProviderID, type ModelID } from "../schema/index.js"
|
||||
import { ProviderID, type ModelID } from "../schema/index.js"
|
||||
import { GoogleVertexShared } from "./google-vertex-shared.js"
|
||||
import type { OpenAIProviderOptionsInput } from "./openai-options.js"
|
||||
|
||||
|
|
@ -36,29 +36,14 @@ const route = Route.make({
|
|||
|
||||
export const routes = [route]
|
||||
|
||||
const configuredRoute = (input: Config) => {
|
||||
if ("apiKey" in input && input.apiKey !== undefined)
|
||||
throw new ProviderConfigurationError({ provider: id, message: "Google Vertex Chat does not support API keys" })
|
||||
const {
|
||||
accessToken: _accessToken,
|
||||
auth: _auth,
|
||||
baseURL,
|
||||
location: inputLocation,
|
||||
project: inputProject,
|
||||
...rest
|
||||
} = input
|
||||
const location = GoogleVertexShared.location(inputLocation)
|
||||
const project = GoogleVertexShared.project(inputProject)
|
||||
return route.with({
|
||||
...rest,
|
||||
endpoint: {
|
||||
baseURL:
|
||||
baseURL ??
|
||||
`https://aiplatform.googleapis.com/v1/projects/${GoogleVertexShared.requireProject(project)}/locations/${location}/endpoints/openapi`,
|
||||
},
|
||||
auth: GoogleVertexShared.oauth(input, project),
|
||||
})
|
||||
}
|
||||
const configuredRoute = (input: Config) =>
|
||||
GoogleVertexShared.oauthRoute(
|
||||
route,
|
||||
"Chat",
|
||||
input,
|
||||
(project, location) =>
|
||||
`https://aiplatform.googleapis.com/v1/projects/${project}/locations/${location}/endpoints/openapi`,
|
||||
)
|
||||
|
||||
export const configure = (input: Config = {}) => {
|
||||
const route = configuredRoute(input)
|
||||
|
|
@ -74,19 +59,5 @@ export const provider = {
|
|||
configure,
|
||||
}
|
||||
|
||||
export const model: ProviderPackage.Model<Settings, OpenAIProviderOptionsInput> = (
|
||||
modelID,
|
||||
{ accessToken, apiKey, baseURL, body, headers, location, project, ...providerOptions }: Settings = {},
|
||||
) => {
|
||||
if (apiKey !== undefined)
|
||||
throw new ProviderConfigurationError({ provider: id, message: "Google Vertex Chat does not support API keys" })
|
||||
return configure({
|
||||
accessToken,
|
||||
baseURL,
|
||||
headers,
|
||||
http: body === undefined ? undefined : { body },
|
||||
location,
|
||||
project,
|
||||
providerOptions,
|
||||
}).model(modelID)
|
||||
}
|
||||
export const model: ProviderPackage.Model<Settings, OpenAIProviderOptionsInput> = (modelID, settings = {}) =>
|
||||
configure(GoogleVertexShared.oauthSettings<OpenAIProviderOptionsInput>("Chat", settings)).model(modelID)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { Auth } from "../route/auth.js"
|
|||
import { Route, type RouteDefaultsInput } from "../route/client.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
import { ProviderConfigurationError, ProviderID, type ModelID } from "../schema/index.js"
|
||||
import { ProviderID, type ModelID } from "../schema/index.js"
|
||||
import { GoogleVertexShared } from "./google-vertex-shared.js"
|
||||
|
||||
export type AnthropicOptionsInput = AnthropicMessages.OptionsInput
|
||||
|
|
@ -66,29 +66,14 @@ const route = Route.make({
|
|||
|
||||
export const routes = [route]
|
||||
|
||||
const configuredRoute = (input: Config) => {
|
||||
if ("apiKey" in input && input.apiKey !== undefined)
|
||||
throw new ProviderConfigurationError({ provider: id, message: "Google Vertex Messages does not support API keys" })
|
||||
const {
|
||||
accessToken: _accessToken,
|
||||
auth: _auth,
|
||||
baseURL,
|
||||
location: inputLocation,
|
||||
project: inputProject,
|
||||
...rest
|
||||
} = input
|
||||
const location = GoogleVertexShared.location(inputLocation)
|
||||
const project = GoogleVertexShared.project(inputProject)
|
||||
return route.with({
|
||||
...rest,
|
||||
endpoint: {
|
||||
baseURL:
|
||||
baseURL ??
|
||||
`https://${GoogleVertexShared.host(location)}/v1/projects/${GoogleVertexShared.requireProject(project)}/locations/${location}/publishers/anthropic/models`,
|
||||
},
|
||||
auth: GoogleVertexShared.oauth(input, project),
|
||||
})
|
||||
}
|
||||
const configuredRoute = (input: Config) =>
|
||||
GoogleVertexShared.oauthRoute(
|
||||
route,
|
||||
"Messages",
|
||||
input,
|
||||
(project, location) =>
|
||||
`https://${GoogleVertexShared.host(location)}/v1/projects/${project}/locations/${location}/publishers/anthropic/models`,
|
||||
)
|
||||
|
||||
export const configure = (input: Config = {}) => {
|
||||
const route = configuredRoute(input)
|
||||
|
|
@ -106,17 +91,8 @@ export const provider = {
|
|||
|
||||
export const model: ProviderPackage.Model<Settings, AnthropicMessages.ProviderOptionsInput> = (
|
||||
modelID,
|
||||
{ accessToken, apiKey, baseURL, body, headers, location, project, ...providerOptions }: Settings = {},
|
||||
) => {
|
||||
if (apiKey !== undefined)
|
||||
throw new ProviderConfigurationError({ provider: id, message: "Google Vertex Messages does not support API keys" })
|
||||
return configure({
|
||||
accessToken,
|
||||
baseURL,
|
||||
headers,
|
||||
http: body === undefined ? undefined : { body },
|
||||
location,
|
||||
project,
|
||||
providerOptions,
|
||||
}).model(modelID)
|
||||
}
|
||||
settings = {},
|
||||
) =>
|
||||
configure(GoogleVertexShared.oauthSettings<AnthropicMessages.ProviderOptionsInput>("Messages", settings)).model(
|
||||
modelID,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { Route, type RouteDefaultsInput } from "../route/client.js"
|
|||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
import { HttpTransport } from "../route/transport/index.js"
|
||||
import { ProviderConfigurationError, ProviderID, type ModelID } from "../schema/index.js"
|
||||
import { ProviderID, type ModelID } from "../schema/index.js"
|
||||
import { GoogleVertexShared } from "./google-vertex-shared.js"
|
||||
|
||||
export const id = ProviderID.make("google-vertex")
|
||||
|
|
@ -52,29 +52,14 @@ const route = Route.make({
|
|||
|
||||
export const routes = [route]
|
||||
|
||||
const configuredRoute = (input: Config) => {
|
||||
if ("apiKey" in input && input.apiKey !== undefined)
|
||||
throw new ProviderConfigurationError({ provider: id, message: "Google Vertex Mistral does not support API keys" })
|
||||
const {
|
||||
accessToken: _accessToken,
|
||||
auth: _auth,
|
||||
baseURL,
|
||||
location: inputLocation,
|
||||
project: inputProject,
|
||||
...rest
|
||||
} = input
|
||||
const location = GoogleVertexShared.location(inputLocation)
|
||||
const project = GoogleVertexShared.project(inputProject)
|
||||
return route.with({
|
||||
...rest,
|
||||
endpoint: {
|
||||
baseURL:
|
||||
baseURL ??
|
||||
`https://${GoogleVertexShared.host(location)}/v1/projects/${GoogleVertexShared.requireProject(project)}/locations/${location}/publishers/mistralai/models`,
|
||||
},
|
||||
auth: GoogleVertexShared.oauth(input, project),
|
||||
})
|
||||
}
|
||||
const configuredRoute = (input: Config) =>
|
||||
GoogleVertexShared.oauthRoute(
|
||||
route,
|
||||
"Mistral",
|
||||
input,
|
||||
(project, location) =>
|
||||
`https://${GoogleVertexShared.host(location)}/v1/projects/${project}/locations/${location}/publishers/mistralai/models`,
|
||||
)
|
||||
|
||||
export const configure = (input: Config = {}) => {
|
||||
const route = configuredRoute(input)
|
||||
|
|
@ -90,19 +75,5 @@ export const provider = {
|
|||
configure,
|
||||
}
|
||||
|
||||
export const model: ProviderPackage.Model<Settings, MistralChat.ProviderOptionsInput> = (
|
||||
modelID,
|
||||
{ accessToken, apiKey, baseURL, body, headers, location, project, ...providerOptions }: Settings = {},
|
||||
) => {
|
||||
if (apiKey !== undefined)
|
||||
throw new ProviderConfigurationError({ provider: id, message: "Google Vertex Mistral does not support API keys" })
|
||||
return configure({
|
||||
accessToken,
|
||||
baseURL,
|
||||
headers,
|
||||
http: body === undefined ? undefined : { body },
|
||||
location,
|
||||
project,
|
||||
providerOptions,
|
||||
}).model(modelID)
|
||||
}
|
||||
export const model: ProviderPackage.Model<Settings, MistralChat.ProviderOptionsInput> = (modelID, settings = {}) =>
|
||||
configure(GoogleVertexShared.oauthSettings<MistralChat.ProviderOptionsInput>("Mistral", settings)).model(modelID)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import type { ProviderPackage } from "../provider-package.js"
|
|||
import { OpenResponses } from "../protocols/open-responses.js"
|
||||
import { Route, type RouteDefaultsInput } from "../route/client.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { ProviderConfigurationError, ProviderID, type ModelID } from "../schema/index.js"
|
||||
import { ProviderID, type ModelID } from "../schema/index.js"
|
||||
import { GoogleVertexShared } from "./google-vertex-shared.js"
|
||||
import type { OpenResponsesProviderOptionsInput } from "./open-responses-options.js"
|
||||
|
||||
|
|
@ -37,29 +37,14 @@ const route = Route.make({
|
|||
|
||||
export const routes = [route]
|
||||
|
||||
const configuredRoute = (input: Config) => {
|
||||
if ("apiKey" in input && input.apiKey !== undefined)
|
||||
throw new ProviderConfigurationError({ provider: id, message: "Google Vertex Responses does not support API keys" })
|
||||
const {
|
||||
accessToken: _accessToken,
|
||||
auth: _auth,
|
||||
baseURL,
|
||||
location: inputLocation,
|
||||
project: inputProject,
|
||||
...rest
|
||||
} = input
|
||||
const location = GoogleVertexShared.location(inputLocation)
|
||||
const project = GoogleVertexShared.project(inputProject)
|
||||
return route.with({
|
||||
...rest,
|
||||
endpoint: {
|
||||
baseURL:
|
||||
baseURL ??
|
||||
`https://aiplatform.googleapis.com/v1/projects/${GoogleVertexShared.requireProject(project)}/locations/${location}/endpoints/openapi`,
|
||||
},
|
||||
auth: GoogleVertexShared.oauth(input, project),
|
||||
})
|
||||
}
|
||||
const configuredRoute = (input: Config) =>
|
||||
GoogleVertexShared.oauthRoute(
|
||||
route,
|
||||
"Responses",
|
||||
input,
|
||||
(project, location) =>
|
||||
`https://aiplatform.googleapis.com/v1/projects/${project}/locations/${location}/endpoints/openapi`,
|
||||
)
|
||||
|
||||
export const configure = (input: Config = {}) => {
|
||||
const route = configuredRoute(input)
|
||||
|
|
@ -75,19 +60,5 @@ export const provider = {
|
|||
configure,
|
||||
}
|
||||
|
||||
export const model: ProviderPackage.Model<Settings, OpenResponsesProviderOptionsInput> = (
|
||||
modelID,
|
||||
{ accessToken, apiKey, baseURL, body, headers, location, project, ...providerOptions }: Settings = {},
|
||||
) => {
|
||||
if (apiKey !== undefined)
|
||||
throw new ProviderConfigurationError({ provider: id, message: "Google Vertex Responses does not support API keys" })
|
||||
return configure({
|
||||
accessToken,
|
||||
baseURL,
|
||||
headers,
|
||||
http: body === undefined ? undefined : { body },
|
||||
location,
|
||||
project,
|
||||
providerOptions,
|
||||
}).model(modelID)
|
||||
}
|
||||
export const model: ProviderPackage.Model<Settings, OpenResponsesProviderOptionsInput> = (modelID, settings = {}) =>
|
||||
configure(GoogleVertexShared.oauthSettings<OpenResponsesProviderOptionsInput>("Responses", settings)).model(modelID)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import type { AnyAuthClient, GoogleAuthOptions } from "google-auth-library"
|
||||
import { Effect, Redacted } from "effect"
|
||||
import type { ProviderPackage } from "../provider-package.js"
|
||||
import { Auth, MissingCredentialError } from "../route/auth.js"
|
||||
import type { CompactionOperations, Route, RouteDefaultsInput } from "../route/client.js"
|
||||
import { ProviderConfigurationError, ProviderID } from "../schema/index.js"
|
||||
|
||||
const SCOPE = "https://www.googleapis.com/auth/cloud-platform"
|
||||
|
|
@ -112,4 +114,63 @@ export const oauth = (input: OAuthOptions, project?: string) => {
|
|||
return adc(project)
|
||||
}
|
||||
|
||||
export const oauthRoute = <Body, Prepared, Compact extends CompactionOperations | undefined>(
|
||||
route: Route<Body, Prepared, Compact>,
|
||||
label: string,
|
||||
input: RouteDefaultsInput &
|
||||
OAuthOptions & { readonly baseURL?: string; readonly location?: string; readonly project?: string },
|
||||
url: (project: string, location: string) => string,
|
||||
) => {
|
||||
if ("apiKey" in input && input.apiKey !== undefined)
|
||||
throw new ProviderConfigurationError({ provider: id, message: `Google Vertex ${label} does not support API keys` })
|
||||
const {
|
||||
accessToken: _accessToken,
|
||||
auth: _auth,
|
||||
baseURL,
|
||||
location: inputLocation,
|
||||
project: inputProject,
|
||||
...rest
|
||||
} = input
|
||||
const resolvedLocation = location(inputLocation)
|
||||
const resolvedProject = project(inputProject)
|
||||
return route.with({
|
||||
...rest,
|
||||
endpoint: { baseURL: baseURL ?? url(requireProject(resolvedProject), resolvedLocation) },
|
||||
auth: oauth(input, resolvedProject),
|
||||
})
|
||||
}
|
||||
|
||||
export const oauthSettings = <Options>(
|
||||
label: string,
|
||||
{
|
||||
accessToken,
|
||||
apiKey,
|
||||
baseURL,
|
||||
body,
|
||||
headers,
|
||||
location,
|
||||
project,
|
||||
...providerOptions
|
||||
}: ProviderPackage.Settings &
|
||||
Options & {
|
||||
readonly accessToken?: string
|
||||
readonly apiKey?: never
|
||||
readonly baseURL?: string
|
||||
readonly location?: string
|
||||
readonly project?: string
|
||||
},
|
||||
) => {
|
||||
if (apiKey !== undefined)
|
||||
throw new ProviderConfigurationError({ provider: id, message: `Google Vertex ${label} does not support API keys` })
|
||||
return {
|
||||
accessToken,
|
||||
baseURL,
|
||||
headers,
|
||||
http: body === undefined ? undefined : { body },
|
||||
location,
|
||||
project,
|
||||
providerOptions,
|
||||
}
|
||||
}
|
||||
|
||||
export * as GoogleVertexShared from "./google-vertex-shared.js"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue