package llm import ( "strings" "testing" ) // The model picker offers whatever /v1/models returns, which is dated ids and // context-window variants. Those are the same model at the same price, so // pricing has to look past the decoration rather than report "unknown". func TestCostPricesDecoratedModelIDs(t *testing.T) { u := Usage{InputTokens: 1_000_000} base, ok := u.Cost("claude-sonnet-5") if !ok { t.Fatal("the bare id is not priced") } for _, id := range []string{ "claude-sonnet-5-20250930", "claude-sonnet-5[1m]", "claude-sonnet-5-latest", } { got, ok := u.Cost(id) if !ok { t.Errorf("Cost(%q) reported no price", id) continue } if got != base { t.Errorf("Cost(%q) = %v, want the same %v as the bare id", id, got, base) } } // A model nobody has priced still reports nothing rather than guessing. if _, ok := u.Cost("some-gateway/mystery-model"); ok { t.Error("an unknown model was given a price") } if _, ok := u.Cost("claude-something-9-20990101"); ok { t.Error("an unknown Claude model was given a price") } } // The wizard's fallback list has to stand on its own: everything in it priced, // the default present, and the same order every time. func TestPricedModelsIsAUsableFallback(t *testing.T) { got := PricedModels() if len(got) != len(prices) { t.Fatalf("PricedModels returned %d of %d priced models", len(got), len(prices)) } var hasDefault bool for _, id := range got { if id == DefaultModel { hasDefault = true } if _, ok := PriceOf(id); !ok { t.Errorf("%s is offered but cannot be priced", id) } } if !hasDefault { t.Errorf("the fallback omits the default model %s", DefaultModel) } if first := got[0]; !strings.HasPrefix(first, "claude-opus") { t.Errorf("the list opens on %s, want the flagship family first", first) } // Map iteration is random, so an unsorted implementation passes once in a // while and fails in front of a user. for i := 0; i < 20; i++ { if again := PricedModels(); strings.Join(again, ",") != strings.Join(got, ",") { t.Fatalf("the order is not stable:\n%v\n%v", got, again) } } }