Skip to content

Commit 2ba2945

Browse files
committed
fix(providers): kimi_coding rejects custom temperature, skip sending
Upstream returns HTTP 400 `invalid temperature: only 1 is allowed for this model` for every model on the kimi_coding endpoint. Treat it like the o1/o3/o4 / gpt-5-mini family — omit `temperature` from the request body so the server applies its mandatory default. Two new tests: - kimi_coding strips temperature even when ChatRequest.Options sets it - other providers still receive the override (negative control)
1 parent 4eeb984 commit 2ba2945

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

internal/providers/openai_extra_headers_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,40 @@ func TestOpenAIProvider_ExtraHeaders_NoOpWhenEmpty(t *testing.T) {
8888
t.Errorf("ExtraHeaders after empty calls = %v, want nil", got)
8989
}
9090
}
91+
92+
// TestKimiCoding_TemperatureSkipped reproduces the upstream rejection
93+
// `invalid temperature: only 1 is allowed for this model`. When the provider
94+
// is kimi_coding, the request body must omit temperature entirely so the
95+
// upstream applies its mandatory default.
96+
func TestKimiCoding_TemperatureSkipped(t *testing.T) {
97+
p := NewOpenAIProvider("kimi-coding", "sk-fake", "https://api.kimi.com/coding/v1", "kimi-k2-turbo-preview").
98+
WithProviderType("kimi_coding")
99+
100+
body := p.buildRequestBody("kimi-k2-turbo-preview", ChatRequest{
101+
Messages: []Message{{Role: "user", Content: "hi"}},
102+
Options: map[string]any{OptTemperature: 0.7},
103+
}, true)
104+
105+
if _, present := body["temperature"]; present {
106+
t.Errorf("temperature must not be sent to kimi_coding; got body[temperature]=%v", body["temperature"])
107+
}
108+
}
109+
110+
// TestKimiCoding_TemperatureSentForOtherProviders is the negative control —
111+
// without provider_type=kimi_coding, a temperature option still flows through.
112+
func TestKimiCoding_TemperatureSentForOtherProviders(t *testing.T) {
113+
p := NewOpenAIProvider("openai", "sk-fake", "https://api.openai.com/v1", "gpt-4o-mini")
114+
115+
body := p.buildRequestBody("gpt-4o-mini", ChatRequest{
116+
Messages: []Message{{Role: "user", Content: "hi"}},
117+
Options: map[string]any{OptTemperature: 0.7},
118+
}, true)
119+
120+
got, ok := body["temperature"]
121+
if !ok {
122+
t.Fatal("temperature must be sent for non-kimi providers")
123+
}
124+
if got != 0.7 {
125+
t.Errorf("temperature = %v, want 0.7", got)
126+
}
127+
}

internal/providers/openai_request.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ func (p *OpenAIProvider) buildRequestBody(model string, req ChatRequest, stream
184184
// Note: gpt-5.X flagship models (gpt-5.1, gpt-5.4, gpt-5.5) DO support temperature;
185185
// only the mini/nano reasoning variants reject it.
186186
skipTemp := strings.HasPrefix(capabilityModel, "gpt-5-mini") || strings.HasPrefix(capabilityModel, "gpt-5-nano") || strings.HasPrefix(capabilityModel, "o1") || strings.HasPrefix(capabilityModel, "o3") || strings.HasPrefix(capabilityModel, "o4")
187+
// Kimi Coding rejects any temperature override — `invalid temperature: only
188+
// 1 is allowed for this model`. Skip sending so the upstream applies its
189+
// own default (1). Matches the model-locked behavior of o1/o3/o4.
190+
if p.providerType == "kimi_coding" {
191+
skipTemp = true
192+
}
187193
if !skipTemp {
188194
body["temperature"] = v
189195
}

0 commit comments

Comments
 (0)