fix(agents): add google/google-vertex forward-compat for gemini-3.1 fallback models#36173
fix(agents): add google/google-vertex forward-compat for gemini-3.1 fallback models#36173Sid-Qin wants to merge 1 commit intoopenclaw:mainfrom
Conversation
…odels Gemini 3.1 series models (gemini-3.1-pro-preview, gemini-3.1-flash-preview, gemini-3.1-flash-lite-preview) work as primary models but fail with "Unknown model" when used in fallbacks. The existing forward-compat resolver only handled google-gemini-cli provider, not google/google-vertex. Add resolveGoogleGenai31ForwardCompatModel that clones the nearest gemini-3 template or synthesizes a model definition when no template exists in the registry. Closes openclaw#36111 Made-with: Cursor
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟡 Credential/endpoint confusion: google-vertex routed through google-generative-ai forward-compat fallback without Vertex endpoint constraints
Description
This creates a risky provider/api mismatch:
Impact (security/privacy):
Vulnerable code: const GOOGLE_GENAI_ELIGIBLE_PROVIDERS = new Set(["google", "google-vertex"]);
...
return normalizeModelCompat({
id: trimmed,
name: trimmed,
api: "google-generative-ai",
provider: normalizedProvider,
...
});RecommendationAvoid routing Safer options:
const GOOGLE_GENAI_ELIGIBLE_PROVIDERS = new Set(["google"]);
if (normalizedProvider === "google-vertex") {
const cloned = cloneFirstTemplateModel({ ... });
return cloned; // no synthetic fallback for vertex
}
Analyzed PR: #36173 at commit Last updated on: 2026-03-05T14:09:26Z |
Greptile SummaryThis PR extends the existing forward-compat model resolution to cover the Key issues:
Confidence Score: 3/5
Last reviewed commit: c96535e |
| return normalizeModelCompat({ | ||
| id: trimmed, | ||
| name: trimmed, | ||
| api: "google-generative-ai", | ||
| provider: normalizedProvider, | ||
| reasoning: true, | ||
| input: ["text", "image"], | ||
| cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, | ||
| contextWindow: DEFAULT_CONTEXT_TOKENS, | ||
| maxTokens: DEFAULT_CONTEXT_TOKENS, | ||
| } as Model<Api>); |
There was a problem hiding this comment.
Wrong API type hardcoded for google-vertex synthetic fallback
The synthetic fallback path always sets api: "google-generative-ai", which is the correct adapter for the google provider (Google AI Studio) but incorrect for google-vertex. Vertex AI uses a different endpoint and authentication scheme — routing it through the google-generative-ai adapter will cause authentication failures or wrong-endpoint errors at runtime.
This synthetic path is only hit when no template exists in the registry for the given provider (e.g. google-vertex has no gemini-3-flash-preview entry). For google-vertex users in that situation, the resolved model will silently point at the wrong API.
The fix should branch on normalizedProvider:
const api =
normalizedProvider === "google-vertex" ? "google-vertex-ai" : "google-generative-ai";
return normalizeModelCompat({
id: trimmed,
name: trimmed,
api,
provider: normalizedProvider,
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: DEFAULT_CONTEXT_TOKENS,
maxTokens: DEFAULT_CONTEXT_TOKENS,
} as Model<Api>);(Replace "google-vertex-ai" with whatever string the rest of the codebase uses for the Vertex AI adapter.)
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/model-forward-compat.ts
Line: 205-215
Comment:
**Wrong API type hardcoded for `google-vertex` synthetic fallback**
The synthetic fallback path always sets `api: "google-generative-ai"`, which is the correct adapter for the `google` provider (Google AI Studio) but incorrect for `google-vertex`. Vertex AI uses a different endpoint and authentication scheme — routing it through the `google-generative-ai` adapter will cause authentication failures or wrong-endpoint errors at runtime.
This synthetic path is only hit when no template exists in the registry for the given provider (e.g. `google-vertex` has no `gemini-3-flash-preview` entry). For `google-vertex` users in that situation, the resolved model will silently point at the wrong API.
The fix should branch on `normalizedProvider`:
```typescript
const api =
normalizedProvider === "google-vertex" ? "google-vertex-ai" : "google-generative-ai";
return normalizeModelCompat({
id: trimmed,
name: trimmed,
api,
provider: normalizedProvider,
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: DEFAULT_CONTEXT_TOKENS,
maxTokens: DEFAULT_CONTEXT_TOKENS,
} as Model<Api>);
```
(Replace `"google-vertex-ai"` with whatever string the rest of the codebase uses for the Vertex AI adapter.)
How can I resolve this? If you propose a fix, please make it concise.| it("resolves google-vertex gemini-3.1 models via the same forward-compat path", () => { | ||
| const result = resolveModel("google-vertex", "gemini-3.1-flash-preview", "/tmp/agent"); | ||
| expect(result.error).toBeUndefined(); | ||
| expect(result.model).toMatchObject({ | ||
| id: "gemini-3.1-flash-preview", | ||
| provider: "google-vertex", | ||
| reasoning: true, | ||
| }); | ||
| }); |
There was a problem hiding this comment.
api field not asserted for google-vertex synthetic path
This test exercises the no-template synthetic fallback for google-vertex (no mock is set up, so discoverModels returns null and the fallback triggers). However, it doesn't assert api, so it would pass even though the synthetic model currently receives the wrong api: "google-generative-ai" value.
Adding an api assertion here would have caught the bug described above and would lock in the correct adapter going forward:
expect(result.model).toMatchObject({
id: "gemini-3.1-flash-preview",
provider: "google-vertex",
api: "google-vertex-ai", // or the correct vertex adapter string
reasoning: true,
});Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/model.forward-compat.test.ts
Line: 144-152
Comment:
**`api` field not asserted for `google-vertex` synthetic path**
This test exercises the no-template synthetic fallback for `google-vertex` (no mock is set up, so `discoverModels` returns `null` and the fallback triggers). However, it doesn't assert `api`, so it would pass even though the synthetic model currently receives the wrong `api: "google-generative-ai"` value.
Adding an `api` assertion here would have caught the bug described above and would lock in the correct adapter going forward:
```typescript
expect(result.model).toMatchObject({
id: "gemini-3.1-flash-preview",
provider: "google-vertex",
api: "google-vertex-ai", // or the correct vertex adapter string
reasoning: true,
});
```
How can I resolve this? If you propose a fix, please make it concise.
Summary
gemini-3.1-pro-preview,gemini-3.1-flash-preview,gemini-3.1-flash-lite-preview) work correctly as the primary model but throwFailoverError: Unknown modelwhen used in thefallbacksarray. The forward-compat resolver only coveredgoogle-gemini-cliprovider, notgoogleorgoogle-vertex.resolveGoogleGenai31ForwardCompatModelthat handlesgoogleandgoogle-vertexproviders by cloning the nearestgemini-3-pro-preview/gemini-3-flash-previewtemplate or synthesizing a model definition when no template exists.google-gemini-cliforward-compat path is untouched. No changes to primary model resolution, provider config, or API routing.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
Gemini 3.1 models (
google/gemini-3.1-pro-preview,google/gemini-3.1-flash-preview,google/gemini-3.1-flash-lite-preview) now resolve correctly when used in thefallbacksarray, instead of throwingFailoverError: Unknown model.Security Impact (required)
Repro + Verification
Environment
Steps
google/gemini-3.1-flash-lite-previewto thefallbacksarray in agent configExpected
Actual
FailoverError: Unknown model: google/gemini-3.1-flash-lite-previewEvidence
7 new vitest unit tests covering:
google/gemini-3.1-pro-previewwith templategoogle/gemini-3.1-flash-previewwith templategoogle/gemini-3.1-flash-lite-previewwith templategoogle-vertexprovider resolutionHuman Verification (required)
Compatibility / Migration
Failure Recovery (if this breaks)
src/agents/model-forward-compat.tsRisks and Mitigations