Skip to content

feat(google): add Google Vertex AI provider with ADC auth and global endpoint routing#60860

Open
PewterZz wants to merge 12 commits into
openclaw:mainfrom
PewterZz:feat/google-vertex-provider
Open

feat(google): add Google Vertex AI provider with ADC auth and global endpoint routing#60860
PewterZz wants to merge 12 commits into
openclaw:mainfrom
PewterZz:feat/google-vertex-provider

Conversation

@PewterZz

@PewterZz PewterZz commented Apr 4, 2026

Copy link
Copy Markdown

Summary

  • Registers a new google-vertex provider in the Google plugin that routes to aiplatform.googleapis.com using Application Default Credentials (ADC), separate from the existing google-gemini-cli OAuth path
  • Adds vertex-region.ts for region/project/baseUrl resolution (env vars + ADC file fallback), with global location producing the unprefixed aiplatform.googleapis.com endpoint
  • Adds vertex-provider-catalog.ts with the Gemini 3.x model catalog for Vertex AI
  • Updates the Google transport stream to detect Vertex endpoints and construct the correct project/location URL path (/v1/projects/{project}/locations/{location}/publishers/google/models/{model}:streamGenerateContent)
  • Exchanges ADC refresh token for a Bearer token at request time, handling the pi-ai "<authenticated>" sentinel that was previously sent as a literal API key causing 401s
  • Captures thought_signature from Gemini 3 thinking-mode tool call responses so multi-turn conversations replay correctly (fixes 400 INVALID_ARGUMENT on second turn)
  • Adds GCP_VERTEX_GOOGLE_CREDENTIALS_MARKER sentinel and registers google-vertex in openclaw.plugin.json

Closes #49039
Closes #56253
Closes #58775
Closes #60736

Test plan

  • pnpm test extensions/google/vertex-region.test.ts — 20 cases, all pass
  • pnpm test extensions/google/vertex-provider-catalog.test.ts — 7 cases, all pass
  • pnpm test src/infra/gemini-auth.test.ts — 5 cases, all pass
  • Live: google-vertex/gemini-3-flash-preview with GOOGLE_CLOUD_LOCATION=global and GOOGLE_CLOUD_PROJECT set — correct Vertex URL, Bearer auth, successful response

@PewterZz PewterZz requested a review from a team as a code owner April 4, 2026 12:47
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: L labels Apr 4, 2026
@greptile-apps

greptile-apps Bot commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a google-vertex provider to the Google plugin, routing to aiplatform.googleapis.com via Application Default Credentials (ADC), with separate region/project resolution, a Gemini 3.x model catalog, Vertex URL path construction, and thought_signature capture for multi-turn tool call replay.

  • P1: src/agents/model-auth-env.ts gates google-vertex on hasAnthropicVertexAvailableAuth, which returns true when ANTHROPIC_VERTEX_USE_GCP_METADATA=1 even without an ADC file. This causes the sentinel to be issued when no real token can be fetched, producing a silent auth failure at request time. The check should mirror hasGoogleVertexAvailableAuth (ADC file readable only), not the Anthropic-specific function.

Confidence Score: 4/5

Safe to merge after fixing the wrong auth-presence predicate in model-auth-env.ts; all other concerns are minor.

One P1 defect: google-vertex availability is gated by the Anthropic Vertex auth check (ANTHROPIC_VERTEX_USE_GCP_METADATA=1 without an ADC file returns the sentinel but fails at token-fetch time). The rest of the implementation — Vertex URL routing, ADC token exchange, thought_signature capture, provider registration — looks correct.

src/agents/model-auth-env.ts — wrong auth-presence function used for google-vertex

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/model-auth-env.ts
Line: 45-46

Comment:
**Wrong auth-presence check for `google-vertex`**

`hasAnthropicVertexAvailableAuth` is imported from `anthropic-vertex-auth-presence.ts` and returns `true` when `ANTHROPIC_VERTEX_USE_GCP_METADATA=1` *even with no ADC file on disk*. If a user sets that env var (for their Anthropic Vertex setup) but has no `application_default_credentials.json`, this block returns the `GCP_VERTEX_GOOGLE_CREDENTIALS_MARKER` sentinel — but `resolveGoogleVertexAccessToken` in `google-vertex-adc.ts` then reads the ADC file, gets `null`, and the request fails at runtime with no helpful error.

The equivalent check for Google's ADC presence is `hasGoogleVertexAvailableAuth` (already exported from `extensions/google/vertex-region.ts`), but since that lives in the extension package it can't be imported here directly. The same gating logic that the extension's catalog uses (`canReadAdc`) should be replicated in core — similar to how `canReadAnthropicVertexAdc` is defined locally in `anthropic-vertex-auth-presence.ts`. A minimal fix is to inline an ADC-file-readable check here, or add a dedicated `hasGoogleVertexAdcAvailableAuth` helper in a new `google-vertex-auth-presence.ts` alongside its Anthropic sibling.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/agents/google-vertex-adc.ts
Line: 81-98

Comment:
**Service-account ADC type silently falls through**

Only `authorized_user` credentials are exchanged for a token; all other ADC types (most commonly `service_account` JSON key files) reach the final `return null` with no diagnostic. Production GCP workloads typically use service-account keys, so this creates a confusing silent failure. Consider throwing or logging a clear message when the ADC file is present but its `type` is unhandled, so users aren't left wondering why auth is failing.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/google/vertex-provider-catalog.ts
Line: 13

Comment:
**Duplicated marker constant**

`GCP_VERTEX_GOOGLE_CREDENTIALS_MARKER` is defined as a private constant in both this file and `vertex-region.ts` (and exported from `src/agents/model-auth-markers.ts`). Within the extension package, `vertex-provider-catalog.ts` could import it from `./vertex-region.js` if it were exported there, avoiding silent value drift if the marker is ever renamed.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "feat(google): add Google Vertex AI provi..." | Re-trigger Greptile

Re-review progress:

Comment thread src/agents/model-auth-env.ts Outdated
Comment on lines +45 to +46
if (hasAnthropicVertexAvailableAuth(env)) {
return { apiKey: GCP_VERTEX_GOOGLE_CREDENTIALS_MARKER, source: "gcloud adc" };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Wrong auth-presence check for google-vertex

hasAnthropicVertexAvailableAuth is imported from anthropic-vertex-auth-presence.ts and returns true when ANTHROPIC_VERTEX_USE_GCP_METADATA=1 even with no ADC file on disk. If a user sets that env var (for their Anthropic Vertex setup) but has no application_default_credentials.json, this block returns the GCP_VERTEX_GOOGLE_CREDENTIALS_MARKER sentinel — but resolveGoogleVertexAccessToken in google-vertex-adc.ts then reads the ADC file, gets null, and the request fails at runtime with no helpful error.

The equivalent check for Google's ADC presence is hasGoogleVertexAvailableAuth (already exported from extensions/google/vertex-region.ts), but since that lives in the extension package it can't be imported here directly. The same gating logic that the extension's catalog uses (canReadAdc) should be replicated in core — similar to how canReadAnthropicVertexAdc is defined locally in anthropic-vertex-auth-presence.ts. A minimal fix is to inline an ADC-file-readable check here, or add a dedicated hasGoogleVertexAdcAvailableAuth helper in a new google-vertex-auth-presence.ts alongside its Anthropic sibling.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/model-auth-env.ts
Line: 45-46

Comment:
**Wrong auth-presence check for `google-vertex`**

`hasAnthropicVertexAvailableAuth` is imported from `anthropic-vertex-auth-presence.ts` and returns `true` when `ANTHROPIC_VERTEX_USE_GCP_METADATA=1` *even with no ADC file on disk*. If a user sets that env var (for their Anthropic Vertex setup) but has no `application_default_credentials.json`, this block returns the `GCP_VERTEX_GOOGLE_CREDENTIALS_MARKER` sentinel — but `resolveGoogleVertexAccessToken` in `google-vertex-adc.ts` then reads the ADC file, gets `null`, and the request fails at runtime with no helpful error.

The equivalent check for Google's ADC presence is `hasGoogleVertexAvailableAuth` (already exported from `extensions/google/vertex-region.ts`), but since that lives in the extension package it can't be imported here directly. The same gating logic that the extension's catalog uses (`canReadAdc`) should be replicated in core — similar to how `canReadAnthropicVertexAdc` is defined locally in `anthropic-vertex-auth-presence.ts`. A minimal fix is to inline an ADC-file-readable check here, or add a dedicated `hasGoogleVertexAdcAvailableAuth` helper in a new `google-vertex-auth-presence.ts` alongside its Anthropic sibling.

How can I resolve this? If you propose a fix, please make it concise.

Comment thread src/agents/google-vertex-adc.ts Outdated
Comment on lines +81 to +98
adc.project_id ||
undefined;

if (adc.type === "authorized_user") {
const result = await refreshAuthorizedUserToken(adc as AdcAuthorizedUser);
cachedToken = {
accessToken: result.access_token,
projectId,
expiresAt: Date.now() + result.expires_in * 1000,
};
return cachedToken;
}

return null;
}

export function clearGoogleVertexTokenCache(): void {
cachedToken = null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Service-account ADC type silently falls through

Only authorized_user credentials are exchanged for a token; all other ADC types (most commonly service_account JSON key files) reach the final return null with no diagnostic. Production GCP workloads typically use service-account keys, so this creates a confusing silent failure. Consider throwing or logging a clear message when the ADC file is present but its type is unhandled, so users aren't left wondering why auth is failing.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/google-vertex-adc.ts
Line: 81-98

Comment:
**Service-account ADC type silently falls through**

Only `authorized_user` credentials are exchanged for a token; all other ADC types (most commonly `service_account` JSON key files) reach the final `return null` with no diagnostic. Production GCP workloads typically use service-account keys, so this creates a confusing silent failure. Consider throwing or logging a clear message when the ADC file is present but its `type` is unhandled, so users aren't left wondering why auth is failing.

How can I resolve this? If you propose a fix, please make it concise.


export const GOOGLE_VERTEX_DEFAULT_MODEL_ID = "gemini-3.1-pro-preview";
const GOOGLE_VERTEX_DEFAULT_CONTEXT_WINDOW = 1_000_000;
const GCP_VERTEX_GOOGLE_CREDENTIALS_MARKER = "gcp-vertex-google-credentials";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Duplicated marker constant

GCP_VERTEX_GOOGLE_CREDENTIALS_MARKER is defined as a private constant in both this file and vertex-region.ts (and exported from src/agents/model-auth-markers.ts). Within the extension package, vertex-provider-catalog.ts could import it from ./vertex-region.js if it were exported there, avoiding silent value drift if the marker is ever renamed.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/google/vertex-provider-catalog.ts
Line: 13

Comment:
**Duplicated marker constant**

`GCP_VERTEX_GOOGLE_CREDENTIALS_MARKER` is defined as a private constant in both this file and `vertex-region.ts` (and exported from `src/agents/model-auth-markers.ts`). Within the extension package, `vertex-provider-catalog.ts` could import it from `./vertex-region.js` if it were exported there, avoiding silent value drift if the marker is ever renamed.

How can I resolve this? If you propose a fix, please make it concise.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ebab852f19

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/google-vertex-adc.ts Outdated
Comment on lines +84 to +88
if (adc.type === "authorized_user") {
const result = await refreshAuthorizedUserToken(adc as AdcAuthorizedUser);
cachedToken = {
accessToken: result.access_token,
projectId,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Support non-user ADC credentials for Vertex auth

The new Vertex token resolver only exchanges tokens when the ADC file is type: "authorized_user"; all other ADC types fall through with no token. In environments that use service-account ADC (GOOGLE_APPLICATION_CREDENTIALS in CI/GKE/Cloud Run), this makes runtime auth unresolved and requests end up unauthenticated (or sent with the marker as an API key), causing Vertex calls to fail consistently. Please add token minting for service-account/metadata ADC or refuse to advertise Vertex auth when the ADC type is unsupported.

Useful? React with 👍 / 👎.

Comment thread src/agents/model-auth-env.ts Outdated
Comment on lines +45 to +46
if (hasAnthropicVertexAvailableAuth(env)) {
return { apiKey: GCP_VERTEX_GOOGLE_CREDENTIALS_MARKER, source: "gcloud adc" };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate google-vertex env auth with the correct capability check

The google-vertex branch uses hasAnthropicVertexAvailableAuth, which can return true via Anthropic-specific metadata opt-in even when Google Vertex cannot actually resolve a token in this implementation. That emits the gcp-vertex-google-credentials marker and leads to failed runtime auth for google-vertex configs without readable Google ADC credentials. This should use a Google-specific availability predicate that matches what the Google resolver can truly handle.

Useful? React with 👍 / 👎.

Comment on lines +108 to +110
return {
...implicit,
...existing,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recompute Vertex location when baseUrl is overridden

Merging implicit and configured provider settings allows existing.baseUrl to override the implicit endpoint, but the region/header state is not recomputed from that effective URL. As a result, users who set models.providers.google-vertex.baseUrl to another region can still send /locations/us-central1/... paths, which causes Vertex INVALID_ARGUMENT request routing failures. The merge should derive location from the final base URL (or synchronize headers accordingly).

Useful? React with 👍 / 👎.

@PewterZz PewterZz force-pushed the feat/google-vertex-provider branch from ebab852 to 72aece9 Compare April 4, 2026 12:52

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e0c16151e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/google-transport-stream.ts Outdated
Comment on lines +202 to +206
const origin = baseUrl.replace(/\/+$/, "");
const modelPath = modelId.startsWith("publishers/")
? modelId
: `publishers/google/models/${modelId}`;
return `${origin}/v1/projects/${projectId}/locations/${location}/${modelPath}:streamGenerateContent?alt=sse`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip path from Vertex baseUrl before composing request URL

This URL builder uses the full configured baseUrl as the prefix and then appends /v1/projects/..., so a valid override like https://us-central1-aiplatform.googleapis.com/v1 produces .../v1/v1/projects/... and Vertex requests fail. This commit newly supports google-vertex baseUrl overrides, so users who copy a /v1 endpoint form will get hard request failures until the builder normalizes to URL origin (or strips an existing /v1) before appending the path.

Useful? React with 👍 / 👎.

Comment on lines +116 to +119
if (params.model.provider === "google-vertex") {
const boundaryAwareStreamFn = createBoundaryAwareStreamFnForModel(params.model);
if (boundaryAwareStreamFn) {
return boundaryAwareStreamFn;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve explicit session streamFn for google-vertex models

This new provider-specific branch returns a boundary-aware stream function before the existing custom-stream fallback, so any explicitly supplied currentStreamFn is ignored whenever model.provider === "google-vertex". That is a behavior regression for integrations that attach custom stream wrappers (for telemetry, retries, policy checks, etc.), because those wrappers now silently stop running for Vertex models.

Useful? React with 👍 / 👎.

@PewterZz PewterZz force-pushed the feat/google-vertex-provider branch from f89cdae to e47140a Compare April 4, 2026 13:43

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39e250c4ea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/google-transport-stream.ts Outdated
Comment on lines +203 to +205
const modelPath = modelId.startsWith("publishers/")
? modelId
: `publishers/google/models/${modelId}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve prequalified Vertex model IDs in request paths

The Vertex URL builder always prefixes non-publishers/ model IDs with publishers/google/models/, so inputs like models/gemini-2.5-pro or tunedModels/... become invalid paths such as .../publishers/google/models/models/.... This causes Vertex requests to fail for model ID formats that are already accepted in the non-Vertex Google path logic, so the builder should treat already-qualified IDs as complete instead of blindly prefixing.

Useful? React with 👍 / 👎.

Comment thread src/agents/google-vertex-adc.ts Outdated
Comment on lines +80 to +81
("quota_project_id" in adc ? adc.quota_project_id : undefined) ||
adc.project_id ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prefer ADC project_id over quota_project_id for routing

This resolves the ADC project as quota_project_id before project_id, which conflicts with the implicit provider project resolution (in extensions/google/vertex-region.ts) that prefers project_id first. Because request URL construction prioritizes the token-derived project, ADC files containing both fields can route calls to the quota/billing project instead of the intended Vertex project, leading to avoidable permission or not-found failures.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a98d4fd690

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/google-transport-stream.ts Outdated
Comment on lines +229 to +230
const normalizedBaseUrl = normalizeGoogleApiBaseUrl(model.baseUrl);
return `${normalizedBaseUrl}/${resolveGoogleModelPath(model.id)}:streamGenerateContent?alt=sse`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail fast when Vertex project ID is unavailable

When baseUrl is a Vertex endpoint but no project id can be resolved (no GOOGLE_CLOUD_PROJECT, no provider header, and no ADC-derived project), this code falls back to the generic Gemini URL shape (.../models/...) on the Vertex host instead of returning a clear configuration error. That request shape is invalid for Vertex and will fail at runtime with a confusing API error, so users with ADC credentials lacking project metadata get broken requests rather than actionable guidance.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9a4d659ee6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/google-transport-stream.ts Outdated
Comment on lines +666 to +670
const location =
model.headers?.["x-openclaw-vertex-location"] ||
process.env.GOOGLE_CLOUD_LOCATION ||
"us-central1";
return JSON.stringify({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Let Vertex request URL infer location from endpoint

When ADC is used, this helper always injects a location field and defaults it to "us-central1"; later buildGoogleRequestUrl prioritizes that value over the endpoint-derived region. In configs that point baseUrl at another Vertex region (or the global host) without explicitly setting x-openclaw-vertex-location, requests are routed to /locations/us-central1/... on the wrong endpoint and fail with Vertex routing/INVALID_ARGUMENT errors. Leave location unset unless it is explicitly known so URL construction can fall back to the base URL region.

Useful? React with 👍 / 👎.

@PewterZz PewterZz force-pushed the feat/google-vertex-provider branch from 9a4d659 to 36f9839 Compare April 10, 2026 17:17

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f72b5396c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread extensions/google/index.ts Outdated
normalizeModelId: ({ modelId }) => normalizeGoogleModelId(modelId),
resolveDynamicModel: (ctx) =>
resolveGoogle31ForwardCompatModel({ providerId: "google-vertex", ctx }),
...GOOGLE_GEMINI_PROVIDER_HOOKS_WITH_TOOL_COMPAT,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Import Vertex hook bundle before provider registration

This spread references GOOGLE_GEMINI_PROVIDER_HOOKS_WITH_TOOL_COMPAT, but that identifier is never defined or imported in this module. When register(api) runs, evaluating this object literal throws a ReferenceError, which aborts Google plugin registration and prevents the new Vertex provider from being registered at runtime. Please import the hook bundle (and the other newly referenced helpers below) before constructing this provider object.

Useful? React with 👍 / 👎.

@PewterZz PewterZz force-pushed the feat/google-vertex-provider branch from 0f72b53 to d4f4595 Compare April 10, 2026 19:17

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d4f4595451

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread extensions/google/index.ts Outdated
@@ -115,5 +133,73 @@ export default definePluginEntry({
api.registerMusicGenerationProvider(buildGoogleMusicGenerationProvider());
api.registerVideoGenerationProvider(buildGoogleVideoGenerationProvider());
api.registerWebSearchProvider(createGeminiWebSearchProvider());
api.registerProvider({
id: "google-vertex",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prefer exact provider ownership for google-vertex hooks

Registering a real google-vertex provider here collides with the existing google hook alias (hookAliases: ["google-vertex"] in extensions/google/provider-registration.ts), and runtime hook resolution uses first-match semantics (resolveProviderRuntimePlugin(...).find(matchesProviderId)). In that ordering, google can claim google-vertex first, so this provider's custom hooks (especially formatApiKey and refreshOAuth) are skipped; in auth-profile flows that means the raw OAuth access token is used instead of the JSON Bearer payload expected by parseGeminiAuth, leading to malformed Vertex auth. Ensure exact provider-id matches win (or remove the legacy alias) when google-vertex is registered.

Useful? React with 👍 / 👎.

@clawsweeper

clawsweeper Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 11, 2026, 1:08 AM ET / 05:08 UTC.

Summary
Review failed before ClawSweeper could summarize the requested change.

PR surface: Source +661, Tests +289. Total +950 across 29 files.

Reproducibility: unclear. The review failed before ClawSweeper could establish a reproduction path.

Review metrics: none identified.

Merge readiness
Overall: 🌊 off-meta tidepool
Proof: 🌊 off-meta tidepool
Patch quality: 🌊 off-meta tidepool
Result: rating does not apply to this item.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • [P1] No close action taken because the review did not complete.

Maintainer options:

  1. Decide the mitigation before merge
    Retry the Codex review after fixing the execution failure.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] Review did not complete, so no work-lane recommendation was made.
Review details

Best possible solution:

Retry the Codex review after fixing the execution failure.

Do we have a high-confidence way to reproduce the issue?

Unclear. The review failed before ClawSweeper could establish a reproduction path.

Is this the best way to solve the issue?

Unclear. Retry the review first so ClawSweeper can evaluate the actual issue and fix direction.

AGENTS.md: unclear because the file could not be read completely.

Codex review notes: model internal, reasoning high; reviewed against 418d7e1e83c5.

Label changes

Label changes:

  • remove P2: Current review triage priority is none.
  • remove merge-risk: 🚨 compatibility: Current PR review selected no merge-risk labels.
  • remove merge-risk: 🚨 auth-provider: Current PR review selected no merge-risk labels.
  • remove merge-risk: 🚨 security-boundary: Current PR review selected no merge-risk labels.

Label justifications:

  • rating: 🌊 off-meta tidepool: Overall readiness is 🌊 off-meta tidepool; proof is 🌊 off-meta tidepool and patch quality is 🌊 off-meta tidepool.
Evidence reviewed

PR surface:

Source +661, Tests +289. Total +950 across 29 files.

View PR surface stats
Area Files Added Removed Net
Source 21 1158 497 +661
Tests 8 395 106 +289
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 29 1553 603 +950

What I checked:

  • failure reason: codex execution failed.
  • codex failure detail: Codex review failed for this PR with exit 1.

Likely related people:

  • unknown: Codex failed before it could trace repository history. (role: review did not complete; confidence: low)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

PewterZz added 5 commits May 2, 2026 04:24
… routing

Registers a new google-vertex provider in the Google plugin that routes to
aiplatform.googleapis.com using Application Default Credentials (ADC). The
existing GCP_VERTEX_CREDENTIALS_MARKER and main's google-vertex auth-presence
check in src/agents/model-auth-env.ts are reused; no new core marker or
hard-coded provider branch is added.

Provider follows the anthropic-vertex pattern with resolveSyntheticAuth(),
manifest-declared nonSecretAuthMarkers, and an implicit catalog from
buildGoogleVertexProvider(). hookAliases:[google-vertex] is removed from
the Google AI Studio provider so the new provider's hooks own google-vertex
configs.

ADC token exchange supports both authorized_user (gcloud login) and
service_account (CI/CD JSON keys) types; unsupported ADC types throw a clear
error rather than silently falling through.

Vertex URL builder strips trailing /v1 from custom baseUrls, preserves
already-qualified model paths (publishers/.../, tunedModels/, projects/),
infers the location from the configured baseUrl when set, and fails fast
when no project ID is resolvable.

Closes openclaw#49039
Closes openclaw#56253
Closes openclaw#58775
Closes openclaw#60736
Adds vertex-adc.test.ts with coverage for: missing ADC file, authorized_user
refresh, service_account JWT-bearer minting, unsupported ADC type rejection,
token endpoint error surfacing, in-memory cache reuse, and env project
override over the ADC project_id.
…ovider

# Conflicts:
#	extensions/google/transport-stream.test.ts
#	extensions/google/transport-stream.ts
@openclaw-barnacle openclaw-barnacle Bot added channel: whatsapp-web Channel integration: whatsapp-web agents Agent runtime and tooling extensions: oc-path extensions: google labels May 14, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the channel: whatsapp-web Channel integration: whatsapp-web label May 15, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels May 19, 2026
@clawsweeper

clawsweeper Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat.

Where did the egg go?
  • The egg game starts only after the PR passes the real-behavior proof check.
  • Before that, no creature or rarity is rolled. The treat waits for real proof.
  • This is still just collectible flavor: proof affects review readiness, not creature quality.

@wiselancer

Copy link
Copy Markdown

Adding production evidence — running OpenClaw 2026.5.18 on Hetzner Coolify, routing Gemini 3.5 Flash via Vertex AI on a third-party GCP project (reseller billing). Posted longer reproduction details over on #83971.

Specifically validating two things this PR touches:

1. global region routing. Gemini 3.5 Flash (shipped 2026-05-19) is not yet GA in us-central1 — only global works. My deployment uses GOOGLE_CLOUD_LOCATION=global and hits https://aiplatform.googleapis.com/v1/projects/{project}/locations/global/publishers/google/models/gemini-3.5-flash:streamGenerateContent. Confirms the "global produces the unprefixed aiplatform.googleapis.com endpoint" behavior in vertex-region.ts is exactly what's needed for day-1 model GA gaps.

2. ADC bearer exchange. I'm currently using authorized_user ADC (via ~/.config/gcloud/application_default_credentials.json with quota_project_id set, copied onto the container). This PR's Bearer exchange at request time + handling of "<authenticated>" sentinel matches the auth-profile sentinel pattern I had to hand-craft to get past the "No API key found for provider 'google'" runtime error.

Session JSONL after my hack-workaround:

{"role":"assistant","api":"google-vertex","provider":"google",
 "model":"gemini-3.5-flash","stopReason":"stop",
 "responseId":"8xAOaqW7H4nItfAP-uanuAE", ...}

Multi-turn works. thought_signature capture in this PR would address the second-turn 400 I haven't hit yet but would expect on longer sessions.

Happy to test the official build end-to-end against a real third-party GCP billing account once a maintainer-buildable tag exists. The reseller-billing angle is a useful real-world stress test for quota_project_id propagation.

@wiselancer

Copy link
Copy Markdown

Bundled the full reproduction (env vars, ADC setup, auth-profiles.json sentinel, patch scripts, session-log proof) into a gist for anyone else hitting this in the meantime:

https://gist.github.com/wiselancer/edcb1d8b766518ecb9849287d5fc2e36

Will delete it / replace with a "use the official path" note once this PR (or #60860) lands.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. label May 21, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Jun 10, 2026
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 10, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling extensions: google extensions: oc-path merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. size: XL triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

2 participants