Skip to content
This repository was archived by the owner on Jun 1, 2026. It is now read-only.

Commit 839c863

Browse files
fix(openai-compat): preserve legacy thinking passthrough
1 parent 6fa038a commit 839c863

4 files changed

Lines changed: 103 additions & 6 deletions

File tree

config.example.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ nonstream-keepalive-interval: 0
248248
# models: # The models supported by the provider.
249249
# - name: "moonshotai/kimi-k2:free" # The actual model name.
250250
# alias: "kimi-k2" # The alias used in the API.
251-
# thinking: # optional: omit to default to levels ["low","medium","high"]
251+
# thinking: # optional: omit to preserve legacy passthrough (no advertised thinking support)
252252
# levels: ["low", "medium", "high"]
253253
# # You may repeat the same alias to build an internal model pool.
254254
# # The client still sees only one alias in the model list.

internal/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ type OpenAICompatibilityModel struct {
551551
Alias string `yaml:"alias" json:"alias"`
552552

553553
// Thinking configures the thinking/reasoning capability for this model.
554-
// If nil, the model defaults to level-based reasoning with levels ["low", "medium", "high"].
554+
// If nil, the model keeps legacy passthrough behavior and does not advertise managed thinking support.
555555
Thinking *registry.ThinkingSupport `yaml:"thinking,omitempty" json:"thinking,omitempty"`
556556
}
557557

sdk/cliproxy/service.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,17 +2136,15 @@ func (s *Service) registerModelsForAuth(a *coreauth.Auth) {
21362136
modelID = m.Name
21372137
}
21382138
thinking := m.Thinking
2139-
if thinking == nil {
2140-
thinking = &registry.ThinkingSupport{Levels: []string{"low", "medium", "high"}}
2141-
}
2139+
userDefined := thinking == nil
21422140
ms = append(ms, &ModelInfo{
21432141
ID: modelID,
21442142
Object: "model",
21452143
Created: time.Now().Unix(),
21462144
OwnedBy: compat.Name,
21472145
Type: "openai-compatibility",
21482146
DisplayName: modelID,
2149-
UserDefined: false,
2147+
UserDefined: userDefined,
21502148
Thinking: thinking,
21512149
})
21522150
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package cliproxy
2+
3+
import (
4+
"testing"
5+
6+
"github.com/router-for-me/CLIProxyAPI/v6/internal/registry"
7+
coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth"
8+
"github.com/router-for-me/CLIProxyAPI/v6/sdk/config"
9+
)
10+
11+
func TestRegisterModelsForAuth_OpenAICompatibility_DefaultThinkingPreservesLegacyPassthrough(t *testing.T) {
12+
modelID := "compat-default-" + t.Name()
13+
authID := "auth-" + t.Name()
14+
service := &Service{
15+
cfg: &config.Config{
16+
OpenAICompatibility: []config.OpenAICompatibility{{
17+
Name: "compat-default",
18+
Models: []config.OpenAICompatibilityModel{{
19+
Name: "upstream-default",
20+
Alias: modelID,
21+
}},
22+
}},
23+
},
24+
}
25+
auth := &coreauth.Auth{
26+
ID: authID,
27+
Provider: "openai-compatibility",
28+
Status: coreauth.StatusActive,
29+
Attributes: map[string]string{
30+
"compat_name": "compat-default",
31+
},
32+
}
33+
34+
reg := GlobalModelRegistry()
35+
reg.UnregisterClient(auth.ID)
36+
t.Cleanup(func() {
37+
reg.UnregisterClient(auth.ID)
38+
})
39+
40+
service.registerModelsForAuth(auth)
41+
42+
got := registry.LookupModelInfo(modelID, "compat-default")
43+
if got == nil {
44+
t.Fatalf("expected model %q to be registered", modelID)
45+
}
46+
if !got.UserDefined {
47+
t.Fatalf("expected model %q to remain user-defined when thinking is omitted", modelID)
48+
}
49+
if got.Thinking != nil {
50+
t.Fatalf("expected model %q to keep nil thinking support when omitted, got %+v", modelID, got.Thinking)
51+
}
52+
}
53+
54+
func TestRegisterModelsForAuth_OpenAICompatibility_ExplicitThinkingEnablesManagedSupport(t *testing.T) {
55+
modelID := "compat-thinking-" + t.Name()
56+
authID := "auth-" + t.Name()
57+
service := &Service{
58+
cfg: &config.Config{
59+
OpenAICompatibility: []config.OpenAICompatibility{{
60+
Name: "compat-thinking",
61+
Models: []config.OpenAICompatibilityModel{{
62+
Name: "upstream-thinking",
63+
Alias: modelID,
64+
Thinking: &registry.ThinkingSupport{Levels: []string{"low", "medium", "high"}},
65+
}},
66+
}},
67+
},
68+
}
69+
auth := &coreauth.Auth{
70+
ID: authID,
71+
Provider: "openai-compatibility",
72+
Status: coreauth.StatusActive,
73+
Attributes: map[string]string{
74+
"compat_name": "compat-thinking",
75+
},
76+
}
77+
78+
reg := GlobalModelRegistry()
79+
reg.UnregisterClient(auth.ID)
80+
t.Cleanup(func() {
81+
reg.UnregisterClient(auth.ID)
82+
})
83+
84+
service.registerModelsForAuth(auth)
85+
86+
got := registry.LookupModelInfo(modelID, "compat-thinking")
87+
if got == nil {
88+
t.Fatalf("expected model %q to be registered", modelID)
89+
}
90+
if got.UserDefined {
91+
t.Fatalf("expected model %q to use managed thinking when explicitly configured", modelID)
92+
}
93+
if got.Thinking == nil {
94+
t.Fatalf("expected model %q to expose configured thinking support", modelID)
95+
}
96+
if len(got.Thinking.Levels) != 3 || got.Thinking.Levels[0] != "low" || got.Thinking.Levels[1] != "medium" || got.Thinking.Levels[2] != "high" {
97+
t.Fatalf("unexpected thinking levels: %+v", got.Thinking)
98+
}
99+
}

0 commit comments

Comments
 (0)