Skip to content

Commit 03902e6

Browse files
committed
Detect free models that became paid
1 parent f2ac9db commit 03902e6

2 files changed

Lines changed: 40 additions & 2 deletions

File tree

internal/adminapi/adminapi_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,26 @@ func TestTGAdminModelCheckRejectsPaidModel(t *testing.T) {
383383
}
384384
}
385385

386+
func TestFailedModelCheckBlocksFreeModelsThatBecamePaid(t *testing.T) {
387+
cases := []string{
388+
"api error (HTTP 404): This model is unavailable for free. The paid version is available now - use this slug instead: minimax/minimax-m2.5",
389+
"api error (HTTP 404): Hy3 preview is no longer available as a free model. It has transitioned to a paid model.",
390+
}
391+
for _, message := range cases {
392+
status := failedModelCheck(message, 23)
393+
if status.Status != "free_blocked" {
394+
t.Fatalf("status = %s, want free_blocked for %q", status.Status, message)
395+
}
396+
}
397+
}
398+
399+
func TestFailedModelCheckKeepsTransientFailuresDegraded(t *testing.T) {
400+
status := failedModelCheck("api error (HTTP 500): upstream temporarily unavailable", 91)
401+
if status.Status != "free_degraded" {
402+
t.Fatalf("status = %s, want free_degraded", status.Status)
403+
}
404+
}
405+
386406
func TestFreeModelCheckCandidatesSkipFreshChecks(t *testing.T) {
387407
s, _ := newTGModelTestServer(t)
388408
fresh := time.Now().Add(-time.Hour).Format(time.RFC3339)

internal/adminapi/model_checks.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,7 @@ func (s *Server) probeModel(ctx context.Context, providerType, modelID string, c
188188

189189
func failedModelCheck(message string, latencyMS int64) modelCheckStatus {
190190
status := "free_degraded"
191-
lower := strings.ToLower(message)
192-
if strings.Contains(lower, "429") || strings.Contains(lower, "rate") || strings.Contains(lower, "quota") {
191+
if isBlockedModelCheckError(message) {
193192
status = "free_blocked"
194193
}
195194
return modelCheckStatus{
@@ -200,6 +199,25 @@ func failedModelCheck(message string, latencyMS int64) modelCheckStatus {
200199
}
201200
}
202201

202+
func isBlockedModelCheckError(message string) bool {
203+
lower := strings.ToLower(message)
204+
for _, needle := range []string{
205+
"429",
206+
"rate",
207+
"quota",
208+
"no longer available as a free model",
209+
"unavailable for free",
210+
"paid version is available",
211+
"transitioned to a paid model",
212+
"has become paid",
213+
} {
214+
if strings.Contains(lower, needle) {
215+
return true
216+
}
217+
}
218+
return false
219+
}
220+
203221
func (s *Server) startModelCheckScheduler() {
204222
if s.settings == nil || s.capStore == nil || s.cfgRef == nil {
205223
return

0 commit comments

Comments
 (0)