fix(agents): Gemini 3.1 models not recognized with 'google' provider alias#36160
fix(agents): Gemini 3.1 models not recognized with 'google' provider alias#36160xinhuagu wants to merge 1 commit intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes Gemini 3.1 models not being recognized when specified with the
Confidence Score: 4/5
Last reviewed commit: 26aa88a |
| it("builds a forward-compat fallback for google/gemini-3.1-flash-lite-preview", () => { | ||
| mockGoogleGeminiCliFlashTemplateModel(); | ||
| const result = resolveModel("google", "gemini-3.1-flash-lite-preview", "/tmp/agent"); | ||
| expect(result.error).toBeUndefined(); | ||
| expect(result.model).toBeDefined(); | ||
| expect(result.model).toMatchObject({ | ||
| id: "gemini-3.1-flash-lite-preview", | ||
| name: "gemini-3.1-flash-lite-preview", | ||
| reasoning: true, | ||
| }); | ||
| }); | ||
|
|
||
| it("builds a forward-compat fallback for google/gemini-3.1-pro-preview", () => { | ||
| mockGoogleGeminiCliProTemplateModel(); | ||
| const result = resolveModel("google", "gemini-3.1-pro-preview", "/tmp/agent"); | ||
| expect(result.error).toBeUndefined(); | ||
| expect(result.model).toBeDefined(); | ||
| expect(result.model).toMatchObject({ | ||
| id: "gemini-3.1-pro-preview", | ||
| name: "gemini-3.1-pro-preview", | ||
| reasoning: true, | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Missing provider assertion in new tests
The two new tests don't assert that the returned model's provider field is "google". The PR description explicitly states that "the cloned model preserves the caller's original provider ID" — this is the key behavioral change introduced here. Without asserting provider: "google", a future accidental removal of provider: normalized from the patch object in model-forward-compat.ts would not be caught by these tests.
The provider field matters at runtime because it drives auth lookup and API key resolution (getApiKeyForModel uses model.provider). If provider were to silently revert to "google-gemini-cli", users who have credentials stored under "google" could face auth failures.
Suggested fix for both tests:
| it("builds a forward-compat fallback for google/gemini-3.1-flash-lite-preview", () => { | |
| mockGoogleGeminiCliFlashTemplateModel(); | |
| const result = resolveModel("google", "gemini-3.1-flash-lite-preview", "/tmp/agent"); | |
| expect(result.error).toBeUndefined(); | |
| expect(result.model).toBeDefined(); | |
| expect(result.model).toMatchObject({ | |
| id: "gemini-3.1-flash-lite-preview", | |
| name: "gemini-3.1-flash-lite-preview", | |
| reasoning: true, | |
| }); | |
| }); | |
| it("builds a forward-compat fallback for google/gemini-3.1-pro-preview", () => { | |
| mockGoogleGeminiCliProTemplateModel(); | |
| const result = resolveModel("google", "gemini-3.1-pro-preview", "/tmp/agent"); | |
| expect(result.error).toBeUndefined(); | |
| expect(result.model).toBeDefined(); | |
| expect(result.model).toMatchObject({ | |
| id: "gemini-3.1-pro-preview", | |
| name: "gemini-3.1-pro-preview", | |
| reasoning: true, | |
| }); | |
| }); | |
| it("builds a forward-compat fallback for google/gemini-3.1-flash-lite-preview", () => { | |
| mockGoogleGeminiCliFlashTemplateModel(); | |
| const result = resolveModel("google", "gemini-3.1-flash-lite-preview", "/tmp/agent"); | |
| expect(result.error).toBeUndefined(); | |
| expect(result.model).toBeDefined(); | |
| expect(result.model).toMatchObject({ | |
| id: "gemini-3.1-flash-lite-preview", | |
| name: "gemini-3.1-flash-lite-preview", | |
| reasoning: true, | |
| provider: "google", | |
| }); | |
| }); | |
| it("builds a forward-compat fallback for google/gemini-3.1-pro-preview", () => { | |
| mockGoogleGeminiCliProTemplateModel(); | |
| const result = resolveModel("google", "gemini-3.1-pro-preview", "/tmp/agent"); | |
| expect(result.error).toBeUndefined(); | |
| expect(result.model).toBeDefined(); | |
| expect(result.model).toMatchObject({ | |
| id: "gemini-3.1-pro-preview", | |
| name: "gemini-3.1-pro-preview", | |
| reasoning: true, | |
| provider: "google", | |
| }); | |
| }); |
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: 90-112
Comment:
**Missing `provider` assertion in new tests**
The two new tests don't assert that the returned model's `provider` field is `"google"`. The PR description explicitly states that "the cloned model preserves the caller's original provider ID" — this is the key behavioral change introduced here. Without asserting `provider: "google"`, a future accidental removal of `provider: normalized` from the `patch` object in `model-forward-compat.ts` would not be caught by these tests.
The `provider` field matters at runtime because it drives auth lookup and API key resolution (`getApiKeyForModel` uses `model.provider`). If `provider` were to silently revert to `"google-gemini-cli"`, users who have credentials stored under `"google"` could face auth failures.
Suggested fix for both tests:
```suggestion
it("builds a forward-compat fallback for google/gemini-3.1-flash-lite-preview", () => {
mockGoogleGeminiCliFlashTemplateModel();
const result = resolveModel("google", "gemini-3.1-flash-lite-preview", "/tmp/agent");
expect(result.error).toBeUndefined();
expect(result.model).toBeDefined();
expect(result.model).toMatchObject({
id: "gemini-3.1-flash-lite-preview",
name: "gemini-3.1-flash-lite-preview",
reasoning: true,
provider: "google",
});
});
it("builds a forward-compat fallback for google/gemini-3.1-pro-preview", () => {
mockGoogleGeminiCliProTemplateModel();
const result = resolveModel("google", "gemini-3.1-pro-preview", "/tmp/agent");
expect(result.error).toBeUndefined();
expect(result.model).toBeDefined();
expect(result.model).toMatchObject({
id: "gemini-3.1-pro-preview",
name: "gemini-3.1-pro-preview",
reasoning: true,
provider: "google",
});
});
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 26aa88af82
ℹ️ 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".
src/agents/model-forward-compat.ts
Outdated
| templateIds: [...templateIds], | ||
| modelRegistry, | ||
| patch: { reasoning: true }, | ||
| patch: { reasoning: true, provider: normalized }, |
There was a problem hiding this comment.
Keep Gemini CLI schema sanitization active for google alias
Setting the cloned forward-compat model to provider: normalized makes google/gemini-3.1-* models carry provider google even though they still use the google-gemini-cli API template, and that bypasses the Google CLI tool-schema cleanup path because sanitizeToolsForGoogle only runs when provider is google-gemini-cli (src/agents/pi-embedded-runner/google.ts:248, called from src/agents/pi-embedded-runner/run/attempt.ts:797 and src/agents/pi-embedded-runner/compact.ts:390). In runs that use tools with unsupported schema keywords, this causes request failures that did not occur for the google-gemini-cli/... path.
Useful? React with 👍 / 👎.
26aa88a to
1f90eae
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1f90eae854
ℹ️ 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".
src/agents/model-forward-compat.ts
Outdated
| templateIds: [...templateIds], | ||
| modelRegistry, | ||
| patch: { reasoning: true }, | ||
| patch: { reasoning: true, provider: normalized }, |
There was a problem hiding this comment.
Preserve gemini-cli auth provider for cloned 3.1 models
Overriding the cloned model to provider: normalized makes google/gemini-3.1-* forward-compat models report provider: "google" while still inheriting the google-gemini-cli transport fields from the template, and auth lookup is keyed by model.provider (src/agents/model-auth.ts, via getApiKeyForModel). In setups that only have google-gemini-cli OAuth profiles (the normal Cloud Code Assist path), these alias models now fail credential resolution because the runner looks for google credentials instead of google-gemini-cli.
Useful? React with 👍 / 👎.
1f90eae to
73315fc
Compare
… fallback resolveGoogleGeminiCli31ForwardCompatModel only matched provider 'google-gemini-cli', silently rejecting the common 'google' alias. Users specifying 'google/gemini-3.1-flash-lite-preview' or 'google/gemini-3.1-pro-preview' got unknown-model errors or silent fallback to the default provider. Accept both 'google' and 'google-gemini-cli' as valid providers, searching templates under 'google-gemini-cli' (where they are registered) while preserving the caller's provider ID. Fixes openclaw#36111 Fixes openclaw#36134
73315fc to
bdee4a7
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bdee4a74a7
ℹ️ 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".
| if (normalized !== "google-gemini-cli" && normalized !== "google") { | ||
| return undefined; | ||
| } | ||
| // Templates are registered under "google-gemini-cli" in the model registry, | ||
| // so always search there regardless of which alias the user specified. | ||
| const templateProvider = "google-gemini-cli"; |
There was a problem hiding this comment.
Keep google provider on google forward-compat fallback
Accepting google in this guard now routes google/gemini-3.1-* through a google-gemini-cli template, so resolveModel returns early from forward-compat instead of using the configured models.providers.google fallback path; the resulting model carries Cloud Code Assist transport/auth metadata (model.provider is used by getApiKeyForModel), which breaks environments that only have Google API-key auth (GEMINI_API_KEY or providers.google.apiKey) and no google-gemini-cli credentials. This regression is triggered when a gemini-cli template is available in the registry.
Useful? React with 👍 / 👎.
|
Closing — same fix as #36145 and several others. 14 competing PRs for the same change, no point keeping this open. |
Fixes #36111
Fixes #36134
Root Cause
resolveGoogleGeminiCli31ForwardCompatModelonly acceptedgoogle-gemini-clias the provider ID. Users specifyinggoogle/gemini-3.1-flash-lite-preview(using the commongooglealias) hit the provider guard and got either:Unknown modelerrors when used in fallback chains ([Bug]: Gemini 3.1 series models not recognized in fallback routing #36111)modelApplied: true([Bug]: sessions_spawn silently falls back to Anthropic (set fallback model) when targeting Google Gemini models on spawned subagent tasks. #36134)Fix
Accept both
googleandgoogle-gemini-clias valid providers. Templates are always searched undergoogle-gemini-cli(where they are registered in the model registry), but the cloned model preserves the caller's original provider ID.Changes
src/agents/model-forward-compat.ts: widen provider check, usetemplateProviderfor registry lookupgoogle/gemini-3.1-flash-lite-previewandgoogle/gemini-3.1-pro-preview