using ClaudeDo.Data.Models; namespace ClaudeDo.Data.Tests; public class ModelRegistryTests { [Theory] [InlineData("sonnet", "sonnet")] [InlineData("OPUS", "opus")] [InlineData(" haiku ", "haiku")] public void NormalizeAlias_canonicalizes_known_aliases(string input, string expected) { Assert.Equal(expected, ModelRegistry.NormalizeAlias(input)); } [Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] public void NormalizeAlias_blank_means_inherit(string? input) { Assert.Null(ModelRegistry.NormalizeAlias(input)); } [Fact] public void NormalizeAlias_unknown_throws() { Assert.Throws(() => ModelRegistry.NormalizeAlias("gpt4")); } [Fact] public void ByCostAscending_is_haiku_sonnet_opus_fable() { Assert.Equal(new[] { "haiku", "sonnet", "opus", "fable" }, ModelRegistry.ByCostAscending); } [Theory] [InlineData("sonnet", "sonnet")] [InlineData("OPUS", "opus")] [InlineData(" haiku ", "haiku")] [InlineData("claude-sonnet-4-6", "sonnet")] [InlineData("claude-opus-4-6", "opus")] [InlineData("claude-haiku-4-5-20251001", "haiku")] [InlineData("us.anthropic.claude-sonnet-4-6-v1:0", "sonnet")] public void TryNormalizeAlias_matches_aliases_and_full_model_ids(string input, string expected) { Assert.Equal(expected, ModelRegistry.TryNormalizeAlias(input)); } [Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] [InlineData("gpt-4")] [InlineData("some-future-model")] public void TryNormalizeAlias_never_throws_and_returns_null_when_unrecognized(string? input) { Assert.Null(ModelRegistry.TryNormalizeAlias(input)); } [Fact] public void List_handler_role_aliases_are_valid_and_split_cost_by_role() { // Triage and Merge get the wide-context, expensive role; Wait just queues and blocks, // so it stays on the cheaper model. Assert.Equal("opus", ModelRegistry.NormalizeAlias(ModelRegistry.HandlerTriageAlias)); Assert.Equal("sonnet", ModelRegistry.NormalizeAlias(ModelRegistry.HandlerWaitAlias)); Assert.Equal("opus", ModelRegistry.NormalizeAlias(ModelRegistry.HandlerMergeAlias)); } }