import { describe, expect, test } from 'bun:test'; import { listClaudeCodeModels } from './list-models'; /** * The Claude tier list, and the one property the rest of the system depends on: the id survives the split. * * `claude-manager` derives what it hands the SDK with `params.model?.split('/')[1]`, so a bracketed alias * only works if the id has exactly one `/` and the brackets come through untouched. That is easy to break * by "tidying" an id into `claude-code/opus/1m` or url-encoding the brackets, and it would fail as the * harness silently running the wrong model rather than as an error — the same class of silent mismatch the * mid-conversation switch work existed to remove. */ const ids = () => listClaudeCodeModels().map((m) => m.id); describe('claude-code tiers', () => { test('every alias the installed CLI accepts is offered', () => { // Read out of the CLI binary rather than recalled — see the note in list-models.ts. `mythos` is // deliberately excluded (Project Glasswing only), so its absence is part of the claim. expect(ids()).toEqual([ 'claude-code/fable', 'claude-code/fable[1m]', 'claude-code/opus', 'claude-code/opus[1m]', 'claude-code/opusplan', 'claude-code/opusplan[1m]', 'claude-code/sonnet', 'claude-code/sonnet[1m]', 'claude-code/haiku', ]); }); test('the alias survives `split("/")[1]` with its brackets intact', () => { for (const id of ids()) { const parts = id.split('/'); expect(parts).toHaveLength(2); expect(parts[1]).not.toContain('%'); } expect('claude-code/opus[1m]'.split('/')[1]).toBe('opus[1m]'); }); test('a 1M variant declares a 1M window, and nothing else does', () => { for (const model of listClaudeCodeModels()) { expect(model.contextWindow).toBe(model.id.endsWith('[1m]') ? 1_000_000 : 200_000); } }); test('every tier is routed to the Claude sidecar', () => { // `isClaudeModel` is a `startsWith` on the harness prefix; an id that misses it silently dispatches to // OpenCode, which is the wrong-harness bug the model-switch guard refuses at runtime. for (const id of ids()) expect(id.startsWith('claude-code')).toBe(true); }); });