#20049: fix(model-selection): resolve short-name alias keys correctly
agents
size: S
trusted-contributor
Cluster:
Model Alias Fixes
## Summary
Fixes #20042 — `/model flash` (and all short-name aliases) resolve to `anthropic/flash` instead of the configured target model.
## Root Cause
`buildModelAliasIndex` assumed config keys were always full model paths (`"anthropic/claude-3-5-sonnet": { alias: "fast" }`). When users configure the opposite style — short name as key, full path as alias — the map was keyed by the full model path instead of the short name:
```js
// Before (broken for Style B)
const parsed = parseModelRef(keyRaw, defaultProvider); // "flash" → anthropic/flash
const aliasKey = normalizeAliasKey(alias); // "google/gemini-2.5-flash"
byAlias.set(aliasKey, { alias, ref: parsed }); // lookup by "flash" → miss
```
## Fix
Detect which value is the short name and which is the full path by checking for a `/` separator. Both config styles now work:
- **Style A** (existing): `{ "anthropic/claude-3-5-sonnet": { alias: "fast" } }`
- **Style B** (broken until now): `{ "flash": { alias: "google/gemini-2.5-flash" } }`
The heuristic:
- Key has `/`, alias doesn't → Style A (key=model path, alias=short name)
- Key has no `/`, alias does → Style B (key=short name, alias=model path)
- Ambiguous → falls back to legacy behavior (Style A)
## Test
Added regression test covering Style B config with 3 aliases (flash/sonnet/opus) + end-to-end resolution via `resolveModelRefFromString`. All 14 tests pass (13 existing + 1 new).
## Changes
- `src/agents/model-selection.ts` — bidirectional alias detection in `buildModelAliasIndex`
- `src/agents/model-selection.e2e.test.ts` — regression test for #20042
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes alias resolution in `buildModelAliasIndex` so that "Style B" configs — where the config key is a short name and the alias value is a full model path (e.g., `"flash": { alias: "google/gemini-2.5-flash" }`) — resolve correctly instead of defaulting to `anthropic/flash`.
The approach uses a `/` slash heuristic to detect which value is the short name vs. full path, which is reasonable. However, there are two issues:
- **Allowlist functions not updated**: `buildConfiguredAllowlistKeys` and `buildAllowedModelSet` also iterate over config keys using `parseModelRef(key, defaultProvider)` directly. With Style B configs, these produce incorrect allowlist entries (e.g., `"anthropic/flash"` instead of `"google/gemini-2.5-flash"`), which will cause the resolved model to be rejected as "not allowed" in `resolveAllowedModelRef` and model fallback paths.
- **`alias` field semantics changed for Style A**: The `alias` field in `byAlias` now stores the full model path instead of the short name. For existing Style A configs, this causes duplicate information in model switch event messages (e.g., `"Model switched to anthropic/claude-3-5-sonnet (anthropic/claude-3-5-sonnet)."` instead of `"Model switched to fast (anthropic/claude-3-5-sonnet)."`).
<h3>Confidence Score: 2/5</h3>
- This PR has logic issues that will cause Style B models to fail allowlist checks and regress Style A display messages — should not be merged as-is.
- Score of 2 because: (1) the core alias resolution fix is correct, but (2) two related functions (buildConfiguredAllowlistKeys, buildAllowedModelSet) are not updated for Style B, meaning resolved models will be rejected as "not allowed" in production paths, and (3) the alias field semantics change for Style A configs causes a visible regression in model switch event messages.
- src/agents/model-selection.ts — buildConfiguredAllowlistKeys (line 129-146) and buildAllowedModelSet (line 332-347) need the same bidirectional detection logic applied to buildModelAliasIndex.
<sub>Last reviewed commit: f65bd7e</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#20080: fix: resolve model aliases correctly when keyed by short name
by kamal-ayman · 2026-02-18
87.7%
#9905: fix: require provider prefix for models set without alias (#5790)
by petter-b · 2026-02-05
77.4%
#19927: fix(agents): replace hardcoded Anthropic model IDs with pattern mat...
by Milofax · 2026-02-18
77.1%
#16104: fix: implement model aliases for /model command
by MisterGuy420 · 2026-02-14
76.1%
#11198: fix(models): strip @profile suffix from model selection
by mcaxtr · 2026-02-07
75.8%
#17560: fix: Anthropic Prompt Caching Not Working - Missing cache_control H...
by MisterGuy420 · 2026-02-15
75.0%
#16838: fix: include configured fallbacks in model allowlist
by taw0002 · 2026-02-15
71.9%
#11349: fix(agents): do not filter fallback models by models allowlist
by liuxiaopai-ai · 2026-02-07
71.3%
#19533: fix: allow forward-compat models in buildAllowedModelSet
by Anthony-g-dev · 2026-02-17
71.2%
#20185: fix(model): recognize default/reset/clear keywords to clear session...
by yxshee · 2026-02-18
71.1%