mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-01 00:27:35 +02:00
69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
package openai
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"cyberstrike-ai/internal/config"
|
|
)
|
|
|
|
// reasoningToolChoiceCompatRoundTripper strips thinking/reasoning fields from
|
|
// chat/completions requests that force tool_choice, which some gateways reject
|
|
// when thinking mode is enabled on the same request.
|
|
type reasoningToolChoiceCompatRoundTripper struct {
|
|
base http.RoundTripper
|
|
cfg *config.OpenAIConfig
|
|
}
|
|
|
|
func (rt *reasoningToolChoiceCompatRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
if rt == nil || rt.base == nil || req == nil || req.Body == nil {
|
|
if rt != nil && rt.base != nil {
|
|
return rt.base.RoundTrip(req)
|
|
}
|
|
return http.DefaultTransport.RoundTrip(req)
|
|
}
|
|
if req.Method != http.MethodPost || !strings.HasSuffix(req.URL.Path, "/chat/completions") {
|
|
return rt.base.RoundTrip(req)
|
|
}
|
|
|
|
body, err := io.ReadAll(req.Body)
|
|
_ = req.Body.Close()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
patched := body
|
|
var perr error
|
|
if isDeepSeekToolChoiceCompatProfile(rt.cfg) {
|
|
patched, perr = StripToolChoiceForThinkingMode(body)
|
|
} else {
|
|
patched, perr = StripReasoningIfForcedToolChoice(body)
|
|
}
|
|
if perr != nil {
|
|
patched = body
|
|
}
|
|
req.Body = io.NopCloser(bytes.NewReader(patched))
|
|
req.ContentLength = int64(len(patched))
|
|
req.Header.Set("Content-Length", strconv.Itoa(len(patched)))
|
|
return rt.base.RoundTrip(req)
|
|
}
|
|
|
|
func isDeepSeekToolChoiceCompatProfile(cfg *config.OpenAIConfig) bool {
|
|
if cfg == nil {
|
|
return false
|
|
}
|
|
profile := strings.ToLower(strings.TrimSpace(cfg.Reasoning.ProfileEffective()))
|
|
if profile == "deepseek" || profile == "deepseek_compat" {
|
|
return true
|
|
}
|
|
if profile != "" && profile != "auto" {
|
|
return false
|
|
}
|
|
baseURL := strings.ToLower(cfg.BaseURL)
|
|
model := strings.ToLower(cfg.Model)
|
|
return strings.Contains(baseURL, "deepseek") || strings.Contains(model, "deepseek")
|
|
}
|