| 1 | package config |
| 2 | |
| 3 | import "testing" |
| 4 | |
| 5 | func TestTokenRhythmPresetMatchesPublicAPIIntegration(t *testing.T) { |
| 6 | preset, ok := CuratedProviderPreset("token-rhythm") |
| 7 | if !ok || len(preset.Entries) != 1 { |
| 8 | t.Fatalf("Token Rhythm preset = %+v, want one entry", preset) |
| 9 | } |
| 10 | if preset.Label != "Token Rhythm" || preset.KeyEnv != "TOKEN_RHYTHM_API_KEY" { |
| 11 | t.Fatalf("Token Rhythm identity = label %q key %q", preset.Label, preset.KeyEnv) |
| 12 | } |
| 13 | entry := preset.Entries[0] |
| 14 | if entry.Kind != "openai" || entry.BaseURL != "https://tokenrhythm.studio/v1" || entry.ModelsURL != "https://tokenrhythm.studio/v1/models" { |
| 15 | t.Fatalf("Token Rhythm endpoint mismatch: %+v", entry) |
| 16 | } |
| 17 | if entry.DefaultModel() != "deepseek-v4-flash" || !entry.HasModel("qwen3.8-max") || entry.HasModel("qwen-image-2.0") { |
| 18 | t.Fatalf("Token Rhythm chat catalog mismatch: models=%v default=%q", entry.Models, entry.DefaultModel()) |
| 19 | } |
| 20 | |
| 21 | var cfg Config |
| 22 | if err := cfg.UpsertProvider(entry); err != nil { |
| 23 | t.Fatalf("upsert Token Rhythm preset: %v", err) |
| 24 | } |
| 25 | deepseek, ok := cfg.ResolveModel("token-rhythm/deepseek-v4-flash") |
| 26 | if !ok || deepseek.ContextWindow != 1_000_000 || ReasoningProtocolForEntry(deepseek) != ReasoningProtocolDeepSeek { |
| 27 | t.Fatalf("Token Rhythm DeepSeek capability mismatch: %+v", deepseek) |
| 28 | } |
| 29 | shortFlash, ok := cfg.ResolveModel("token-rhythm/deepseek-flash") |
| 30 | if !ok || ReasoningProtocolForEntry(shortFlash) != ReasoningProtocolDeepSeek { |
| 31 | t.Fatalf("Token Rhythm DeepSeek short alias capability mismatch: %+v", shortFlash) |
| 32 | } |
| 33 | shortFlashCap := EffortCapabilityForEntry(shortFlash) |
| 34 | if !shortFlashCap.Supported || shortFlashCap.Default != "high" || !stringSlicesEqual(shortFlashCap.Levels, []string{"auto", "disabled", "low", "high", "max"}) { |
| 35 | t.Fatalf("Token Rhythm DeepSeek short alias effort mismatch: %+v", shortFlashCap) |
| 36 | } |
| 37 | kimi, ok := cfg.ResolveModel("token-rhythm/kimi-k2.7-code") |
| 38 | if !ok || kimi.ContextWindow != 256_000 || !EffectiveVision(kimi) { |
| 39 | t.Fatalf("Token Rhythm Kimi capability mismatch: %+v", kimi) |
| 40 | } |
| 41 | glm, ok := cfg.ResolveModel("token-rhythm/glm-5.1") |
| 42 | if !ok || glm.ContextWindow != 200_000 || EffectiveVision(glm) || ReasoningProtocolForEntry(glm) != ReasoningProtocolGLM { |
| 43 | t.Fatalf("Token Rhythm GLM capability mismatch: %+v", glm) |
| 44 | } |
| 45 | glmCap := EffortCapabilityForEntry(glm) |
| 46 | if !glmCap.Supported || glmCap.Default != "enabled" || !stringSlicesEqual(glmCap.Levels, []string{"auto", "enabled", "disabled"}) { |
| 47 | t.Fatalf("Token Rhythm GLM effort mismatch: %+v", glmCap) |
| 48 | } |
| 49 | flash0731, ok := cfg.ResolveModel("token-rhythm/deepseek-v4-flash-0731") |
| 50 | if !ok || ReasoningProtocolForEntry(flash0731) != ReasoningProtocolDeepSeek { |
| 51 | t.Fatalf("Token Rhythm DeepSeek 0731 protocol mismatch: %+v", flash0731) |
| 52 | } |
| 53 | flashCap := EffortCapabilityForEntry(flash0731) |
| 54 | if !flashCap.Supported || flashCap.Default != "high" || !stringSlicesEqual(flashCap.Levels, []string{"auto", "disabled", "low", "high", "max"}) { |
| 55 | t.Fatalf("Token Rhythm DeepSeek 0731 effort mismatch: %+v", flashCap) |
| 56 | } |
| 57 | } |
| 58 |