Agent host Claude harness: toSdkModelId turns claude-fable-5-1[1m] into claude-fable-5 (native "Fable" row runs Fable 5 instead of 5.1)
- Dominant language
- TypeScript
- Stars
- 193k
- Forks
- 42.4k
- PR merge metrics
- PR metrics pending
Description
Does this issue occur when all extensions are disabled?: Yes (the bug is in the server-side agent host, `src/vs/platform/agentHost/node/claude/claudeModelId.ts`; no extension is involved)
- VS Code Version: 1.137.0-insider, commit de8cc55dae905582f191fdcfb6dff8c811a743c4 (2026-09-04), agent host reached via `code-insiders agent host --tunnel`
- OS Version: agent host on Ubuntu 24.04.4 LTS x64; client via insiders.vscode.dev
- Claude Agent SDK bundled by the agent host: 0.3.258 (Claude Code CLI 2.1.258)
## Summary
When the Claude Code CLI on the machine is configured with a model that has a **minor version and the `[1m]` context suffix** (e.g. `"model": "claude-fable-5-1[1m]"` in `~/.claude/settings.json`), the native (BYO-Anthropic) "Fable" row in the Claude harness model picker silently runs on **Claude Fable 5** instead of **Claude Fable 5.1**. The same happens for `claude-opus-4-8[1m]` → `claude-opus-4`.
The cause is `toSdkModelId()` / `tryParseClaudeModelId()` in `claudeModelId.ts`. The ids in the native list come from `Query.supportedModels()` and are already SDK-format (the code comment in `fromSdkModelInfo` says "`toSdkModelId` is identity at this seam"), but the parser does not know the `[1m]` suffix form that Claude Code uses, so it is not an identity:
- Pattern 1 (`^claude-(\w+)-(\d+)-(\d+)(?:-(.+))?$`) fails on `claude-fable-5-1[1m]` because `[1m]` follows the minor version without a dash.
- Pattern 4 (`^claude-(\w+)-(\d+)(?:-(.+))?$`) then matches with `major=5` and `mod="1[1m]"`. The minor version is swallowed into the modifier, `extractValidSuffix('fable', '1[1m]')` returns `''`, and the result is `claude-fable-5`.
Ids without a minor version (`claude-opus-5[1m]`, `claude-sonnet-5[1m]`) fall through all patterns and pass through unchanged, so those work by accident.
## Steps to Reproduce
1. On a Linux machine, set `"model": "claude-fable-5-1[1m]"` in `~/.claude/settings.json` and provide a Claude subscription token (`CLAUDE_CODE_OAUTH_TOKEN`) so the native Anthropic transport is set up.
2. Run `code-insiders agent host --tunnel`, open the Agents view, start a Claude harness session and select the **"Fable"** row under the native Anthropic models (not the Copilot-billed "Claude Fable 5.1").
3. Ask "What model are you?".
**Expected:** the session runs on `claude-fable-5-1`.
**Actual:** the session runs on `claude-fable-5`. The Claude Code transcript (`~/.claude/projects//.jsonl`) shows every assistant message with `"model":"claude-fable-5"`, and the model replies that it is Fable 5. The AHP log confirms the picker sent `"model":{"id":"@provider=anthropic:claude-fable-5-1%5B1m%5D"}` and the session snapshot recorded `"model":"claude-fable-5"`.
Running the bundled CLI directly with the same id works, which isolates the agent host:
```
$ .../claude-agent-sdk-linux-x64/claude -p --model 'claude-fable-5-1[1m]' --output-format json 'hi'
# modelUsage keys: claude-fable-5-1
```
## Minimal repro of the parser (evaluated against the shipped `agentHostMain.js` normalizer)
```
claude-fable-5-1[1m] => claude-fable-5 (wrong; expected claude-fable-5-1 or unchanged)
claude-fable-5-1 => claude-fable-5-1
claude-opus-4-8[1m] => claude-opus-4 (wrong)
claude-opus-5[1m] => claude-opus-5[1m] (passes through)
claude-sonnet-5[1m] => claude-sonnet-5[1m] (passes through)
```
## Suggested fix
Treat a trailing `[...]` as a modifier before pattern matching (Claude Code's own model-id regex accepts `(?:\[[12]m\])?$`), or skip `toSdkModelId` entirely for ids that came from `supportedModels()` on the native transport, since they are already SDK-canonical. A test case for `claude-fable-5-1[1m]` in `claudeModelId.test.ts` would catch this; the existing 1m tests only cover the `-1m` dash form.
Workaround: remove `[1m]` from the configured model (Fable 5.1 has a native 1M window, so nothing is lost there), then restart the agent host.
Possibly related: #334017 reports "Fable one is 5" in the Claude harness without a cause.
Contributor guide
Assessment
This issue has not been assessed yet.