← Back to PRs

#20049: fix(model-selection): resolve short-name alias keys correctly

by widingmarcus-cyber open 2026-02-18 13:08 View on GitHub →
agents size: S trusted-contributor
## 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