Commit cac3cb0
authored
🤖 feat: add google:gemini-3-flash-preview model (#1216)
Add `google:gemini-3-flash-preview` as a known model with Flash-specific
thinking levels.
### Changes
- Add `GEMINI_3_FLASH` to `knownModels.ts` with alias `gemini-3-flash`
- Update thinking policy: Flash supports `off/low/medium/high` (vs Pro's
`low/high`)
- Update `providerOptions.ts` to pass `medium` directly for Flash (Pro
maps `medium` → `high`)
- Refresh `models.json` from LiteLLM (includes gemini-3-flash-preview
pricing)
- Fix `modelStats.ts` type to allow `null` for `max_output_tokens`
(LiteLLM compat)
---
<details>
<summary>📋 Implementation Plan</summary>
# Plan: Add `google:gemini-3-flash-preview` to Known Models
## Summary
Add a new Google Gemini 3 Flash Preview model entry and update thinking
policy to reflect Flash-specific thinking levels.
**Estimated LoC change:** +25 lines (production code only, excluding
auto-fetched JSON)
## Changes
### 1. Add model definition to `src/common/constants/knownModels.ts`
Insert a new `GEMINI_3_FLASH` entry after the existing `GEMINI_3_PRO`
definition:
```typescript
GEMINI_3_FLASH: {
provider: "google",
providerModelId: "gemini-3-flash-preview",
aliases: ["gemini-3-flash"],
tokenizerOverride: "google/gemini-2.5-pro",
},
```
<details>
<summary>Why these values?</summary>
- **provider:** `"google"` — matches the existing Gemini model pattern
- **providerModelId:** `"gemini-3-flash-preview"` — the exact model ID
requested
- **aliases:** `["gemini-3-flash"]` — convenient shorthand without
`-preview` suffix
- **tokenizerOverride:** `"google/gemini-2.5-pro"` — reuses the same
tokenizer as `GEMINI_3_PRO` since `ai-tokenizer` likely doesn't have
gemini-3 specific tokenizers yet
- **warm:** Not set (defaults to false) — flash models are typically
secondary, not preloaded
</details>
### 2. Update thinking policy in `src/browser/utils/thinking/policy.ts`
Per [Google's Gemini 3
docs](https://ai.google.dev/gemini-api/docs/gemini-3#rest), thinking
levels differ between Pro and Flash:
| Model | Thinking Levels |
|-------|-----------------|
| Gemini 3 Pro | `low`, `high` |
| Gemini 3 Flash | `minimal`, `low`, `medium`, `high` |
**Note:** Google's `minimal` maps to mux's `off` (no/minimal thinking).
Update the `gemini-3` check in `getThinkingPolicyForModel()` to
differentiate Flash from Pro:
```typescript
// Gemini 3 Flash supports 4 levels: off (minimal), low, medium, high
if (withoutProviderNamespace.includes("gemini-3-flash")) {
return ["off", "low", "medium", "high"];
}
// Gemini 3 Pro only supports "low" and "high" reasoning levels
if (withoutProviderNamespace.includes("gemini-3")) {
return ["low", "high"];
}
```
The Flash check must come **before** the generic `gemini-3` check since
Flash contains `gemini-3` as a substring.
### 3. Refresh `src/common/utils/tokens/models.json` from LiteLLM
LiteLLM already includes `gemini-3-flash-preview`. Just run the existing
update script:
```bash
bun scripts/update_models.ts
```
This fetches the latest model data from [LiteLLM's
model_prices_and_context_window.json](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json).
### 4. Update `src/common/utils/ai/providerOptions.ts` for
Flash-specific thinking levels
Current code treats all `gemini-3` models the same, mapping `medium` →
`high`. But Flash actually supports `medium` natively:
| Model | Google API levels |
|-------|-------------------|
| Gemini 3 Pro | `low`, `high` |
| Gemini 3 Flash | `minimal`, `low`, `medium`, `high` |
Update the Google provider options to differentiate Flash from Pro:
```typescript
if (isGemini3) {
const isFlash = modelString.includes("gemini-3-flash");
if (isFlash) {
// Flash supports: minimal (maps to off), low, medium, high
// When off, we don't set thinkingConfig at all (API defaults to minimal)
thinkingConfig.thinkingLevel =
effectiveThinking === "xhigh" ? "high" : effectiveThinking;
} else {
// Pro only supports: low, high - map medium/xhigh to high
thinkingConfig.thinkingLevel =
effectiveThinking === "medium" || effectiveThinking === "xhigh"
? "high"
: effectiveThinking;
}
}
```
### 5. Update tests in `src/browser/utils/thinking/policy.test.ts`
Add test case for the new Flash model:
```typescript
expect(getThinkingPolicyForModel("google:gemini-3-flash-preview")).toEqual([
"off", "low", "medium", "high"
]);
```
## Systems That Work Automatically
| System | Reason |
|--------|--------|
| **Model display** | Generic Gemini parsing in `modelDisplay.ts` will
format as "Gemini 3 Flash Preview" |
| **Tokenizer** | Override specified; falls back to gemini-2.5-pro
tokenizer |
## Verification
After implementation:
1. `make typecheck` — ensures type correctness
2. `bun test src/browser/utils/thinking/policy.test.ts` — verify
thinking policy
3. Verify model appears in `KNOWN_MODEL_OPTIONS` export
</details>
---
_Generated with `mux` • Model: `anthropic:claude-opus-4-5` • Thinking:
`high`_
Signed-off-by: Thomas Kosiewski <tk@coder.com>1 parent f51ad35 commit cac3cb0
File tree
7 files changed
+1074
-107
lines changed- docs
- src
- browser/utils/thinking
- common
- constants
- utils
- ai
- tokens
7 files changed
+1074
-107
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
159 | 159 | | |
160 | 160 | | |
161 | 161 | | |
162 | | - | |
| 162 | + | |
163 | 163 | | |
164 | 164 | | |
165 | 165 | | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
166 | 175 | | |
167 | 176 | | |
168 | 177 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
66 | 66 | | |
67 | 67 | | |
68 | 68 | | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
69 | 74 | | |
70 | 75 | | |
71 | 76 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
83 | 83 | | |
84 | 84 | | |
85 | 85 | | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
86 | 92 | | |
87 | 93 | | |
88 | 94 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
264 | 264 | | |
265 | 265 | | |
266 | 266 | | |
267 | | - | |
268 | | - | |
269 | | - | |
270 | | - | |
271 | | - | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
272 | 279 | | |
273 | 280 | | |
274 | 281 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
15 | | - | |
16 | | - | |
| 15 | + | |
| 16 | + | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| |||
0 commit comments