fix(opencode): clarify vertex anthropic authentication

This commit is contained in:
Aiden Cline
2026-05-27 23:57:28 -05:00
parent e5cf3ad3c2
commit 01635b20ee
5 changed files with 64 additions and 4 deletions
@@ -460,6 +460,13 @@ export const ProvidersLoginCommand = effectCmd({
)
}
if (provider === "google-vertex") {
yield* Prompt.log.info(
"Note: this API key cannot be used with Anthropic models.\n" +
"Use `gcloud auth application-default login` or set `GOOGLE_APPLICATION_CREDENTIALS`.",
)
}
if (provider === "opencode") {
yield* Prompt.log.info("Create an api key at https://opencode.ai/auth")
}
@@ -384,6 +384,15 @@ function ApiMethod(props: ApiMethodProps) {
</text>
</box>
),
"google-vertex": (
<box gap={1}>
<text fg={theme.warning}>Note: this API key cannot be used with Anthropic models.</text>
<text fg={theme.textMuted}>
Use <span style={{ fg: theme.text }}>gcloud auth application-default login</span> or set
GOOGLE_APPLICATION_CREDENTIALS.
</text>
</box>
),
}[props.providerID] ?? undefined
}
onConfirm={async (value) => {
+16 -3
View File
@@ -1095,8 +1095,9 @@ export function latest(msgs: WithParts[]) {
export function fromError(
e: unknown,
ctx: { providerID: ProviderID; aborted?: boolean },
ctx: { model: Provider.Model; aborted?: boolean } | { providerID: ProviderID; aborted?: boolean },
): NonNullable<Assistant["error"]> {
const providerID = "model" in ctx ? ctx.model.providerID : ctx.providerID
switch (true) {
case e instanceof DOMException && e.name === "AbortError":
return new AbortedError(
@@ -1110,11 +1111,23 @@ export function fromError(
case LoadAPIKeyError.isInstance(e):
return new AuthError(
{
providerID: ctx.providerID,
providerID,
message: e.message,
},
{ cause: e },
).toObject()
case e instanceof Error &&
"model" in ctx &&
ctx.model.api.npm === "@ai-sdk/google-vertex/anthropic" &&
e.message.includes("Could not load the default credentials"):
return new AuthError(
{
providerID,
message:
"Anthropic models on Google Vertex require Google Cloud credentials. Use `gcloud auth application-default login` or set `GOOGLE_APPLICATION_CREDENTIALS`.",
},
{ cause: e },
).toObject()
case (e as SystemError)?.code === "ECONNRESET":
return new APIError(
{
@@ -1157,7 +1170,7 @@ export function fromError(
).toObject()
case APICallError.isInstance(e):
const parsed = ProviderError.parseAPICallError({
providerID: ctx.providerID,
providerID,
error: e,
})
if (parsed.type === "context_overflow") {
+1 -1
View File
@@ -124,7 +124,7 @@ export const layer = Layer.effect(
const parse = (e: unknown) =>
MessageV2.fromError(e, {
providerID: input.model.providerID,
model: input.model,
aborted,
})
@@ -1509,6 +1509,37 @@ describe("session.message-v2.fromError", () => {
})
})
test("explains ADC requirements when Vertex Anthropic credentials are missing", () => {
const vertexAnthropicModel = {
...model,
providerID: ProviderID.googleVertex,
api: { ...model.api, npm: "@ai-sdk/google-vertex/anthropic" },
}
const result = MessageV2.fromError(
new Error(
"Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.",
),
{ model: vertexAnthropicModel },
)
expect(result).toStrictEqual({
name: "ProviderAuthError",
data: {
providerID: "google-vertex",
message:
"Anthropic models on Google Vertex require Google Cloud credentials. Use `gcloud auth application-default login` or set `GOOGLE_APPLICATION_CREDENTIALS`.",
},
})
})
test("does not present Anthropic ADC guidance for Gemini Vertex credentials errors", () => {
const result = MessageV2.fromError(new Error("Could not load the default credentials."), {
model: { ...model, providerID: ProviderID.googleVertex, api: { ...model.api, npm: "@ai-sdk/google-vertex" } },
})
expect(result.name).toBe("UnknownError")
})
test("serializes tagged errors with their message", () => {
const result = MessageV2.fromError(new Question.RejectedError(), { providerID })