mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-21 22:23:29 +00:00
fix(core): make Google Vertex models work with ADC credentials (#43077)
Signed-off-by: Major Hayden <major@mhtx.net>
This commit is contained in:
parent
d5e83fefda
commit
5c8d46ab4b
6 changed files with 127 additions and 2 deletions
|
|
@ -55,8 +55,13 @@ export const ModelsDevPlugin = define({
|
|||
})
|
||||
|
||||
function environmentNames(provider: ModelsDev.Snapshot) {
|
||||
if (provider.info.id !== Provider.ID.azure) return [...provider.environment]
|
||||
return [...provider.environment.filter((name) => name.endsWith("_API_KEY")), "AZURE_COGNITIVE_SERVICES_API_KEY"]
|
||||
if (provider.info.id === Provider.ID.azure)
|
||||
return [...provider.environment.filter((name) => name.endsWith("_API_KEY")), "AZURE_COGNITIVE_SERVICES_API_KEY"]
|
||||
// models.dev advertises project, location, and the ADC credentials file path for
|
||||
// Vertex. Those configure Google auth rather than carrying a key, so only the
|
||||
// Express Mode key may become a credential; GoogleVertexPlugin handles activation.
|
||||
if (provider.info.id === Provider.ID.googleVertex) return ["GOOGLE_VERTEX_API_KEY"]
|
||||
return [...provider.environment]
|
||||
}
|
||||
|
||||
function snapshots(data: readonly ModelsDev.Snapshot[]) {
|
||||
|
|
|
|||
|
|
@ -71,6 +71,9 @@ export const GoogleVertexPlugin = define({
|
|||
const project = resolveProject(item.provider.settings ?? {})
|
||||
const location = String(resolveLocation(item.provider.settings ?? {}))
|
||||
evt.provider.update(item.provider.id, (provider) => {
|
||||
// Vertex authenticates through ADC rather than a key credential, so a
|
||||
// resolvable project is what makes the provider usable.
|
||||
if (project && provider.activation === "auto") provider.activation = "enabled"
|
||||
provider.settings = {
|
||||
...provider.settings,
|
||||
...(project ? { project } : {}),
|
||||
|
|
|
|||
|
|
@ -48,6 +48,17 @@ const builtins = new Map<string, () => Promise<unknown>>([
|
|||
["@opencode-ai/ai/providers/azure/chat", () => import("@opencode-ai/ai/providers/azure/chat")],
|
||||
["@opencode-ai/ai/providers/azure/responses", () => import("@opencode-ai/ai/providers/azure/responses")],
|
||||
["@opencode-ai/ai/providers/google", () => import("@opencode-ai/ai/providers/google")],
|
||||
["@opencode-ai/ai/providers/google-vertex", () => import("@opencode-ai/ai/providers/google-vertex")],
|
||||
["@opencode-ai/ai/providers/google-vertex/gemini", () => import("@opencode-ai/ai/providers/google-vertex/gemini")],
|
||||
["@opencode-ai/ai/providers/google-vertex/chat", () => import("@opencode-ai/ai/providers/google-vertex/chat")],
|
||||
[
|
||||
"@opencode-ai/ai/providers/google-vertex/responses",
|
||||
() => import("@opencode-ai/ai/providers/google-vertex/responses"),
|
||||
],
|
||||
[
|
||||
"@opencode-ai/ai/providers/google-vertex/messages",
|
||||
() => import("@opencode-ai/ai/providers/google-vertex/messages"),
|
||||
],
|
||||
["@opencode-ai/ai/providers/openai", () => import("@opencode-ai/ai/providers/openai")],
|
||||
["@opencode-ai/ai/providers/openai/chat", () => import("@opencode-ai/ai/providers/openai/chat")],
|
||||
["@opencode-ai/ai/providers/openai/responses", () => import("@opencode-ai/ai/providers/openai/responses")],
|
||||
|
|
|
|||
|
|
@ -426,6 +426,46 @@ describe("ModelsDevPlugin", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
it.effect("advertises only key-bearing Google Vertex environment variables", () =>
|
||||
Effect.gen(function* () {
|
||||
const integrations = yield* Integration.Service
|
||||
const catalog = yield* Catalog.Service
|
||||
|
||||
yield* ModelsDevPlugin.effect(
|
||||
host({
|
||||
catalog: catalogHost(catalog),
|
||||
integration: integrationHost(integrations),
|
||||
}),
|
||||
).pipe(
|
||||
Effect.provideService(
|
||||
ModelsDev.Service,
|
||||
ModelsDev.Service.of({
|
||||
get: () =>
|
||||
Effect.succeed([
|
||||
{
|
||||
info: {
|
||||
id: Provider.ID.make("google-vertex"),
|
||||
name: "Google Vertex",
|
||||
activation: "auto",
|
||||
package: Provider.aisdk("@ai-sdk/google-vertex"),
|
||||
},
|
||||
environment: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_LOCATION", "GOOGLE_APPLICATION_CREDENTIALS"],
|
||||
models: [],
|
||||
},
|
||||
] satisfies readonly ModelsDev.Snapshot[]),
|
||||
refresh: () => Effect.void,
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
// Vertex authenticates through ADC; project, location, and the credentials
|
||||
// file path are configuration, not API keys.
|
||||
expect(yield* integrations.get(Integration.ID.make("google-vertex"))).toMatchObject({
|
||||
methods: [{ type: "key" }, { type: "env", names: ["GOOGLE_VERTEX_API_KEY"] }],
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("converts reasoning options into settings variants", () =>
|
||||
Effect.gen(function* () {
|
||||
const catalog = yield* Catalog.Service
|
||||
|
|
|
|||
|
|
@ -141,6 +141,52 @@ describe("GoogleVertexPlugin", () => {
|
|||
),
|
||||
)
|
||||
|
||||
it.effect("enables the provider when a project resolves and leaves it automatic otherwise", () =>
|
||||
withEnv(
|
||||
{
|
||||
GOOGLE_VERTEX_PROJECT: undefined,
|
||||
GOOGLE_CLOUD_PROJECT: undefined,
|
||||
GCP_PROJECT: undefined,
|
||||
GCLOUD_PROJECT: undefined,
|
||||
},
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const catalog = yield* Catalog.Service
|
||||
yield* catalog.transform((catalog) =>
|
||||
catalog.provider.update(Provider.ID.make("google-vertex"), (provider) => {
|
||||
provider.package = Provider.aisdk("@ai-sdk/google-vertex")
|
||||
}),
|
||||
)
|
||||
yield* addPlugin()
|
||||
|
||||
expect(required(yield* catalog.provider.get(Provider.ID.make("google-vertex"))).activation).toBe("auto")
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
it.effect("enables the provider when a project resolves from env", () =>
|
||||
withEnv(
|
||||
{
|
||||
GOOGLE_VERTEX_PROJECT: undefined,
|
||||
GOOGLE_CLOUD_PROJECT: "adc-project",
|
||||
GCP_PROJECT: undefined,
|
||||
GCLOUD_PROJECT: undefined,
|
||||
},
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const catalog = yield* Catalog.Service
|
||||
yield* catalog.transform((catalog) =>
|
||||
catalog.provider.update(Provider.ID.make("google-vertex"), (provider) => {
|
||||
provider.package = Provider.aisdk("@ai-sdk/google-vertex")
|
||||
}),
|
||||
)
|
||||
yield* addPlugin()
|
||||
|
||||
expect(required(yield* catalog.provider.get(Provider.ID.make("google-vertex"))).activation).toBe("enabled")
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
it.effect("resolves the advertised GOOGLE_VERTEX_PROJECT env for provider updates and SDKs", () =>
|
||||
withEnv(
|
||||
{
|
||||
|
|
|
|||
20
packages/core/test/provider.test.ts
Normal file
20
packages/core/test/provider.test.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { describe, expect, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { Provider } from "@opencode-ai/core/provider"
|
||||
|
||||
describe("Provider", () => {
|
||||
test("loads Vertex native provider entrypoints", async () => {
|
||||
const packages = [
|
||||
"@opencode-ai/ai/providers/google-vertex",
|
||||
"@opencode-ai/ai/providers/google-vertex/gemini",
|
||||
"@opencode-ai/ai/providers/google-vertex/chat",
|
||||
"@opencode-ai/ai/providers/google-vertex/responses",
|
||||
"@opencode-ai/ai/providers/google-vertex/messages",
|
||||
]
|
||||
|
||||
for (const specifier of packages) {
|
||||
const loaded = await Effect.runPromise(Provider.loadPackage(specifier))
|
||||
expect(loaded.model).toBeFunction()
|
||||
}
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue