Skip to content

feat(provider): discriminate provider behaviour by npm where unique#28536

Draft
andrewesweet wants to merge 3 commits into
anomalyco:devfrom
andrewesweet:feat/npm-keyed-provider-loader
Draft

feat(provider): discriminate provider behaviour by npm where unique#28536
andrewesweet wants to merge 3 commits into
anomalyco:devfrom
andrewesweet:feat/npm-keyed-provider-loader

Conversation

@andrewesweet
Copy link
Copy Markdown

@andrewesweet andrewesweet commented May 20, 2026

Issue for this PR

Closes #28524

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Declaring a second Vertex AI provider entry under a custom ID (say google-vertex-eu for the eu multi-region) silently skips the Vertex loader today. The resulting SDK has no ADC credentials and requests fail with Model not found. The custom-loader iteration in packages/opencode/src/provider/provider.ts walks Object.entries(custom(dep)), keyed by exact provider ID, so anything that isn't a canonical loader name is dropped.

This PR walks the merged provider database instead. Each entry resolves to a loader by exact-ID match (canonical behaviour, untouched) or by unique-npm match. When the npm is shared (the @ai-sdk/openai-compatible family of seven loaders, plus the @ai-sdk/azure pair), the resolver returns undefined and the entry falls through to the generic SDK path. That keeps the change narrow. Explicit aliasing inside those shared-npm groups is a separate problem; #28489 attacks one slice of it with an auth_provider config field.

I also moved the literal model.providerID === "X" discriminations in provider.ts, transform.ts, and agent.ts to model.api.npm === NPM.X wherever the canonical loader uniquely owns its npm. Sites inside the openai-compatible family stay ID-keyed; npm can't discriminate among them. A new packages/opencode/src/provider/npm.ts holds the npm constants so a typo at a call site is a compile error.

Drive-by: the google-vertex-anthropic loader was reading project and location from env vars only and silently ignoring provider.options. Fixed to mirror google-vertex (config first, env fallback). Regression test included.

How did you verify your code works?

Seven new tests in packages/opencode/test/provider/provider.test.ts cover the alias path, canonical-entry regression, ambiguous-npm fallthrough for the azure pair and the openai-compatible family, the google-vertex-anthropic config gap, and the migrated Bedrock cross-region small-model picker.

bun test test/provider/ test/agent/   # 390 pass, 0 fail
bun run typecheck                     # clean

Manual, with the config below in opencode.json and Google ADC set up (gcloud auth application-default login):

opencode run --model google-vertex/gemini-2.5-pro --log-level DEBUG "ping"
opencode run --model google-vertex-eu/gemini-3.5-flash --log-level DEBUG "ping"

Both succeed. Debug logs show each request hitting its configured regional endpoint with an Authorization: Bearer … header from ADC.

Example

{
  "provider": {
    "google-vertex": {
      "options": { "project": "P", "location": "europe-west4" },
      "models": { "gemini-2.5-pro": {} }
    },
    "google-vertex-eu": {
      "npm": "@ai-sdk/google-vertex",
      "options": { "project": "P", "location": "eu" },
      "models": { "gemini-3.5-flash": {} }
    }
  }
}

Screenshots / recordings

N/A — backend/provider logic change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Switch the custom-loader iteration to walk merged provider entries and
resolve loaders by exact ID match or unique-npm fallback. A user-defined
provider entry with `npm: "@ai-sdk/google-vertex"` (and any other
unique-npm provider) now inherits the canonical loader's setup,
enabling multi-region Vertex AI in one session.

Migrate behavioural literal-ID checks in provider.ts, transform.ts, and
agent.ts to `model.api.npm === NPM.X` wherever the canonical loader's
npm value is unique. ID-keyed checks stay in place for the
`@ai-sdk/openai-compatible` family (7 loaders share that npm) and the
azure pair (`azure` plus `azure-cognitive-services`).

Add `packages/opencode/src/provider/npm.ts` with named constants so the
migrated equality checks live in one place and typos become compile
errors.

Fix `google-vertex-anthropic` loader to honour
`provider.options.project` and `provider.options.location` from config,
aligning it with the `google-vertex` loader (drive-by, two-line change).

Refs anomalyco#28524

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label May 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search, I found one potentially related PR:

Related PR:

The searches returned PR #28536 (the current PR) multiple times, and one other related PR (#28489) that deals with provider aliasing. The other results are unrelated feature additions.

No direct duplicate PRs found for this specific feature of discriminating provider behavior by unique npm values.

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label May 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

andrewesweet and others added 2 commits May 20, 2026 23:17
- Drop top-of-file comment block on `src/provider/npm.ts`.
- Tighten the comments inside `resolveLoader` in `src/provider/provider.ts`
  so they stop reading like AI section headers.
- Restore `[].includes()` form for the Anthropic/Vertex-Anthropic check at
  `src/provider/transform.ts:211`, using `[NPM.ANTHROPIC,
  NPM.GOOGLE_VERTEX_ANTHROPIC] as string[]` so the `as const` tuple widens
  enough for `.includes` to accept `model.api.npm`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A future reader of the file can't know what "before" refers to.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vertex AI provider can't run two regions in the same session

1 participant