返回 DeepSeek-Reasonix
provider_presets_scnet_test.go
根目录 / internal / config / provider_presets_scnet_test.go
1 package config
2
3 import (
4 "reflect"
5 "testing"
6 )
7
8 func TestCuratedProviderPresetsSCNetUsesOfficialBaseURLs(t *testing.T) {
9 wantModels := []string{
10 "GLM-5.2",
11 "GLM-5",
12 "GLM-5.1",
13 "Kimi-K3",
14 "Kimi-K2.7-Code",
15 "Kimi-K2.6",
16 "Kimi-K2.5",
17 "DeepSeek-V4-Flash",
18 "DeepSeek-V3.2",
19 "MiniMax-M3",
20 "MiniMax-M2.7",
21 "MiniMax-M2.5",
22 "MiMo-V2.5-Pro",
23 }
24 wantVisionModels := []string{"Kimi-K2.6", "Kimi-K2.5"}
25 tests := []struct {
26 id string
27 kind string
28 baseURL string
29 modelsURL string
30 models []string
31 visionModels []string
32 authHeader bool
33 }{
34 {
35 id: "scnet",
36 kind: "openai",
37 baseURL: "https://api.scnet.cn/api/llm/v1",
38 modelsURL: "https://api.scnet.cn/api/llm/v1/models",
39 models: wantModels,
40 visionModels: wantVisionModels,
41 },
42 {
43 id: "scnet-anthropic",
44 kind: "anthropic",
45 baseURL: "https://api.scnet.cn/api/llm/anthropic",
46 models: wantModels,
47 visionModels: wantVisionModels,
48 authHeader: true,
49 },
50 }
51 for _, tt := range tests {
52 t.Run(tt.id, func(t *testing.T) {
53 preset, ok := CuratedProviderPreset(tt.id)
54 if !ok {
55 t.Fatalf("missing preset %q", tt.id)
56 }
57 if preset.KeyEnv != "SCNET_API_KEY" {
58 t.Fatalf("preset %q key_env = %q, want SCNET_API_KEY", tt.id, preset.KeyEnv)
59 }
60 if len(preset.Entries) != 1 {
61 t.Fatalf("preset %q has %d entries, want 1", tt.id, len(preset.Entries))
62 }
63 entry := preset.Entries[0]
64 if entry.Kind != tt.kind {
65 t.Fatalf("preset %q kind = %q, want %q", tt.id, entry.Kind, tt.kind)
66 }
67 if entry.BaseURL != tt.baseURL {
68 t.Fatalf("preset %q base_url = %q, want %q", tt.id, entry.BaseURL, tt.baseURL)
69 }
70 if entry.ModelsURL != tt.modelsURL {
71 t.Fatalf("preset %q models_url = %q, want %q", tt.id, entry.ModelsURL, tt.modelsURL)
72 }
73 if entry.AuthHeader != tt.authHeader {
74 t.Fatalf("preset %q auth_header = %t, want %t", tt.id, entry.AuthHeader, tt.authHeader)
75 }
76 if !reflect.DeepEqual(entry.Models, tt.models) {
77 t.Fatalf("preset %q models = %q, want %q", tt.id, entry.Models, tt.models)
78 }
79 if !reflect.DeepEqual(entry.VisionModels, tt.visionModels) {
80 t.Fatalf("preset %q vision_models = %q, want %q", tt.id, entry.VisionModels, tt.visionModels)
81 }
82 if entry.DefaultModel() != "MiniMax-M2.5" {
83 t.Fatalf("preset %q default = %q, want MiniMax-M2.5", tt.id, entry.DefaultModel())
84 }
85 if tt.kind == "anthropic" && entry.Thinking != "" {
86 t.Fatalf("preset %q thinking = %q, want omitted", tt.id, entry.Thinking)
87 }
88 var cfg Config
89 if err := cfg.UpsertProvider(entry); err != nil {
90 t.Fatalf("preset %q entry failed validation: %v", tt.id, err)
91 }
92 })
93 }
94 }
95
96 func TestCuratedProviderPresetSCNetAppliesPerModelCapabilities(t *testing.T) {
97 preset, ok := CuratedProviderPreset("scnet")
98 if !ok || len(preset.Entries) != 1 {
99 t.Fatalf("SCNet preset = %+v", preset)
100 }
101 var cfg Config
102 if err := cfg.UpsertProvider(preset.Entries[0]); err != nil {
103 t.Fatalf("UpsertProvider: %v", err)
104 }
105
106 deepseek, ok := cfg.ResolveModel("scnet/DeepSeek-V4-Flash")
107 if !ok {
108 t.Fatal("ResolveModel(scnet/DeepSeek-V4-Flash) failed")
109 }
110 if got := ReasoningProtocolForEntry(deepseek); got != ReasoningProtocolOpenAI {
111 t.Fatalf("DeepSeek-V4-Flash reasoning protocol = %q, want %q", got, ReasoningProtocolOpenAI)
112 }
113 if !reflect.DeepEqual(deepseek.SupportedEfforts, []string{"high", "max"}) || deepseek.DefaultEffort != "high" {
114 t.Fatalf("DeepSeek-V4-Flash efforts = %v/%q, want [high max]/high", deepseek.SupportedEfforts, deepseek.DefaultEffort)
115 }
116
117 vision, ok := cfg.ResolveModel("scnet/Kimi-K2.5")
118 if !ok || !EffectiveVision(vision) {
119 t.Fatalf("Kimi-K2.5 vision capability = %t, found=%t", EffectiveVision(vision), ok)
120 }
121 textOnly, ok := cfg.ResolveModel("scnet/MiniMax-M2.5")
122 if !ok || EffectiveVision(textOnly) {
123 t.Fatalf("MiniMax-M2.5 vision capability = %t, found=%t", EffectiveVision(textOnly), ok)
124 }
125 }
126
126 lines GO