mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-15 07:30:53 +02:00
Add files via upload
This commit is contained in:
+106
-6
@@ -36,7 +36,7 @@ func ApplyPlanExecutePlannerModelConfig(cfg *einoopenai.ChatModelConfig, oa *con
|
||||
}
|
||||
mergeExtraRequestFields(cfg, oa.Reasoning.ExtraRequestFields)
|
||||
clearReasoningFromChatModelConfig(cfg)
|
||||
if resolveWireProfile(oa, &oa.Reasoning) == wireDeepseek {
|
||||
if resolveWireProfile(oa, &oa.Reasoning) == wireDeepseek || oa.IsDeepSeekEndpointOrModel() {
|
||||
// DeepSeek enables thinking by default, so omission would not actually
|
||||
// disable it for the planner's forced tool-choice requests.
|
||||
applyThinkingDisabled(cfg)
|
||||
@@ -88,8 +88,9 @@ func ApplyToEinoChatModelConfig(cfg *einoopenai.ChatModelConfig, oa *config.Open
|
||||
clearReasoningFromChatModelConfig(cfg)
|
||||
// Strict OpenAI endpoints reject unknown `thinking` fields, whereas the
|
||||
// DeepSeek API enables thinking by default and requires an explicit
|
||||
// thinking.type=disabled switch. Keep that wire difference profile-scoped.
|
||||
if resolveWireProfile(oa, sr) == wireDeepseek {
|
||||
// thinking.type=disabled switch. Detect the actual DeepSeek target even
|
||||
// when the configured reasoning profile was left as openai_compat.
|
||||
if resolveWireProfile(oa, sr) == wireDeepseek || oa.IsDeepSeekEndpointOrModel() {
|
||||
applyThinkingDisabled(cfg)
|
||||
}
|
||||
return
|
||||
@@ -118,6 +119,107 @@ func ApplyToEinoChatModelConfig(cfg *einoopenai.ChatModelConfig, oa *config.Open
|
||||
}
|
||||
}
|
||||
|
||||
// AgenticOpenAIExtraFields returns reasoning-related request fields for
|
||||
// agenticopenai.ChatConfig. The agentic chat backend currently exposes provider
|
||||
// extensions through ExtraFields instead of typed ReasoningEffort fields.
|
||||
func AgenticOpenAIExtraFields(oa *config.OpenAIConfig, client *ClientIntent) map[string]any {
|
||||
if oa == nil {
|
||||
return nil
|
||||
}
|
||||
sr := &oa.Reasoning
|
||||
allowClient := sr.AllowClientReasoningEffective()
|
||||
mode := effectiveMode(sr, client, allowClient)
|
||||
fields := cloneExtraRequestFields(sr.ExtraRequestFields)
|
||||
if mode == "off" {
|
||||
clearReasoningExtraFields(fields)
|
||||
if resolveWireProfile(oa, sr) == wireDeepseek || oa.IsDeepSeekEndpointOrModel() {
|
||||
if fields == nil {
|
||||
fields = make(map[string]any)
|
||||
}
|
||||
fields["thinking"] = map[string]any{"type": "disabled"}
|
||||
}
|
||||
return fields
|
||||
}
|
||||
if strings.EqualFold(strings.TrimSpace(oa.Provider), "claude") ||
|
||||
strings.EqualFold(strings.TrimSpace(oa.Provider), "anthropic") {
|
||||
return fields
|
||||
}
|
||||
effort := effectiveEffort(sr, client, allowClient)
|
||||
switch resolveWireProfile(oa, sr) {
|
||||
case wireDeepseek:
|
||||
if mode == "auto" || mode == "on" {
|
||||
if fields == nil {
|
||||
fields = make(map[string]any)
|
||||
}
|
||||
fields["thinking"] = map[string]any{"type": "enabled"}
|
||||
}
|
||||
if effort != "" {
|
||||
if fields == nil {
|
||||
fields = make(map[string]any)
|
||||
}
|
||||
fields["reasoning_effort"] = effortStringForAPI(effort)
|
||||
}
|
||||
case wireOutputConfig:
|
||||
e := effort
|
||||
if mode == "on" && e == "" {
|
||||
e = "high"
|
||||
}
|
||||
if e != "" {
|
||||
if fields == nil {
|
||||
fields = make(map[string]any)
|
||||
}
|
||||
fields["output_config"] = map[string]any{"effort": effortStringForAPI(e)}
|
||||
}
|
||||
default:
|
||||
e := effort
|
||||
if mode == "on" && e == "" {
|
||||
e = "medium"
|
||||
}
|
||||
if e != "" {
|
||||
if fields == nil {
|
||||
fields = make(map[string]any)
|
||||
}
|
||||
fields["reasoning_effort"] = effortStringForAPI(e)
|
||||
}
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
// AgenticOpenAIPlannerExtraFields mirrors ApplyPlanExecutePlannerModelConfig for
|
||||
// agenticopenai.ChatConfig: keep admin extras, strip reasoning controls, and
|
||||
// explicitly disable DeepSeek thinking where omission would still think.
|
||||
func AgenticOpenAIPlannerExtraFields(oa *config.OpenAIConfig) map[string]any {
|
||||
if oa == nil {
|
||||
return nil
|
||||
}
|
||||
fields := cloneExtraRequestFields(oa.Reasoning.ExtraRequestFields)
|
||||
clearReasoningExtraFields(fields)
|
||||
if resolveWireProfile(oa, &oa.Reasoning) == wireDeepseek || oa.IsDeepSeekEndpointOrModel() {
|
||||
if fields == nil {
|
||||
fields = make(map[string]any)
|
||||
}
|
||||
fields["thinking"] = map[string]any{"type": "disabled"}
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
func cloneExtraRequestFields(fields map[string]interface{}) map[string]any {
|
||||
if len(fields) == 0 {
|
||||
return nil
|
||||
}
|
||||
out := make(map[string]any, len(fields))
|
||||
for k, v := range fields {
|
||||
out[k] = v
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func clearReasoningExtraFields(fields map[string]any) {
|
||||
for _, key := range []string{"thinking", "reasoning_effort", "output_config", "reasoning"} {
|
||||
delete(fields, key)
|
||||
}
|
||||
}
|
||||
|
||||
// applyClaudeExtendedThinking sets Anthropic Messages API fields per official guidance:
|
||||
// - Adaptive models (4.6+): thinking.type=adaptive; output_config.effort only when user sets effort (API default is high).
|
||||
// - Sonnet 3.7: thinking.type=enabled + budget_tokens=10000 (doc example); effort is not mapped — use extra_request_fields for custom budget.
|
||||
@@ -240,9 +342,7 @@ func resolveWireProfile(oa *config.OpenAIConfig, sr *config.OpenAIReasoningConfi
|
||||
case "deepseek", "deepseek_compat":
|
||||
return wireDeepseek
|
||||
case "auto", "":
|
||||
bu := strings.ToLower(oa.BaseURL)
|
||||
mo := strings.ToLower(oa.Model)
|
||||
if strings.Contains(bu, "deepseek") || strings.Contains(mo, "deepseek") {
|
||||
if oa.IsDeepSeekEndpointOrModel() {
|
||||
return wireDeepseek
|
||||
}
|
||||
return wireOpenAI
|
||||
|
||||
@@ -69,6 +69,104 @@ func TestApplyOpenAICompat_xhighExtraField(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgenticOpenAIExtraFields_openAICompatReasoningEffort(t *testing.T) {
|
||||
oa := &config.OpenAIConfig{
|
||||
Reasoning: config.OpenAIReasoningConfig{
|
||||
Profile: "openai_compat",
|
||||
Mode: "on",
|
||||
Effort: "high",
|
||||
ExtraRequestFields: map[string]interface{}{
|
||||
"vendor_option": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
got := AgenticOpenAIExtraFields(oa, nil)
|
||||
if got["reasoning_effort"] != "high" {
|
||||
t.Fatalf("reasoning_effort=%#v, want high in %#v", got["reasoning_effort"], got)
|
||||
}
|
||||
if got["vendor_option"] != true {
|
||||
t.Fatalf("vendor option not preserved: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgenticOpenAIExtraFields_reasoningOffPreservesUnrelatedFields(t *testing.T) {
|
||||
oa := &config.OpenAIConfig{
|
||||
Model: "gpt-4o-mini",
|
||||
Reasoning: config.OpenAIReasoningConfig{
|
||||
Profile: "openai_compat",
|
||||
Mode: "off",
|
||||
Effort: "high",
|
||||
ExtraRequestFields: map[string]interface{}{
|
||||
"reasoning_effort": "high",
|
||||
"thinking": map[string]any{"type": "enabled"},
|
||||
"vendor_option": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
got := AgenticOpenAIExtraFields(oa, nil)
|
||||
for _, key := range reasoningPayloadKeysForTest {
|
||||
if _, ok := got[key]; ok {
|
||||
t.Fatalf("agentic fields unexpectedly contain %q: %#v", key, got)
|
||||
}
|
||||
}
|
||||
if got["vendor_option"] != true {
|
||||
t.Fatalf("vendor option not preserved: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgenticOpenAIPlannerExtraFields_deepseekDisablesThinking(t *testing.T) {
|
||||
oa := &config.OpenAIConfig{
|
||||
BaseURL: "https://api.deepseek.com",
|
||||
Model: "deepseek-chat",
|
||||
Reasoning: config.OpenAIReasoningConfig{
|
||||
Profile: "auto",
|
||||
Mode: "on",
|
||||
ExtraRequestFields: map[string]interface{}{
|
||||
"reasoning_effort": "high",
|
||||
"vendor_option": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
got := AgenticOpenAIPlannerExtraFields(oa)
|
||||
if got["reasoning_effort"] != nil {
|
||||
t.Fatalf("planner should strip reasoning_effort: %#v", got)
|
||||
}
|
||||
thinking, ok := got["thinking"].(map[string]any)
|
||||
if !ok || thinking["type"] != "disabled" {
|
||||
t.Fatalf("expected deepseek thinking disabled, got %#v", got)
|
||||
}
|
||||
if got["vendor_option"] != true {
|
||||
t.Fatalf("vendor option not preserved: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgenticOpenAIPlannerExtraFields_deepseekEndpointWinsOverOpenAIProfile(t *testing.T) {
|
||||
oa := &config.OpenAIConfig{
|
||||
BaseURL: "https://api.deepseek.com/v1",
|
||||
Model: "deepseek-v4-flash",
|
||||
Reasoning: config.OpenAIReasoningConfig{
|
||||
Profile: "openai_compat",
|
||||
Mode: "on",
|
||||
Effort: "high",
|
||||
ExtraRequestFields: map[string]interface{}{
|
||||
"reasoning_effort": "high",
|
||||
"vendor_option": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
got := AgenticOpenAIPlannerExtraFields(oa)
|
||||
if _, ok := got["reasoning_effort"]; ok {
|
||||
t.Fatalf("planner should strip reasoning_effort: %#v", got)
|
||||
}
|
||||
thinking, ok := got["thinking"].(map[string]any)
|
||||
if !ok || thinking["type"] != "disabled" {
|
||||
t.Fatalf("expected deepseek thinking disabled despite openai_compat profile, got %#v", got)
|
||||
}
|
||||
if got["vendor_option"] != true {
|
||||
t.Fatalf("vendor option not preserved: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyPlanExecutePlannerModelConfig_stripsReasoningWhenGlobalOn(t *testing.T) {
|
||||
cfg := &einoopenai.ChatModelConfig{ExtraFields: map[string]any{
|
||||
"thinking": map[string]any{"type": "enabled"},
|
||||
@@ -91,6 +189,37 @@ func TestApplyPlanExecutePlannerModelConfig_stripsReasoningWhenGlobalOn(t *testi
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyPlanExecutePlannerModelConfig_deepseekEndpointWinsOverOpenAIProfile(t *testing.T) {
|
||||
cfg := &einoopenai.ChatModelConfig{ExtraFields: map[string]any{
|
||||
"thinking": map[string]any{"type": "enabled"},
|
||||
"reasoning_effort": "high",
|
||||
"vendor_option": true,
|
||||
}}
|
||||
oa := &config.OpenAIConfig{
|
||||
BaseURL: "https://api.deepseek.com/v1",
|
||||
Model: "deepseek-v4-flash",
|
||||
Reasoning: config.OpenAIReasoningConfig{
|
||||
Profile: "openai_compat",
|
||||
Mode: "on",
|
||||
Effort: "high",
|
||||
},
|
||||
}
|
||||
ApplyPlanExecutePlannerModelConfig(cfg, oa)
|
||||
if cfg.ReasoningEffort != "" {
|
||||
t.Fatalf("expected ReasoningEffort omitted, got %q", cfg.ReasoningEffort)
|
||||
}
|
||||
if _, ok := cfg.ExtraFields["reasoning_effort"]; ok {
|
||||
t.Fatalf("expected reasoning_effort omitted, got %#v", cfg.ExtraFields)
|
||||
}
|
||||
thinking, ok := cfg.ExtraFields["thinking"].(map[string]any)
|
||||
if !ok || thinking["type"] != "disabled" {
|
||||
t.Fatalf("expected deepseek thinking disabled despite openai_compat profile, got %#v", cfg.ExtraFields)
|
||||
}
|
||||
if cfg.ExtraFields["vendor_option"] != true {
|
||||
t.Fatalf("expected unrelated extra field preserved, got %#v", cfg.ExtraFields)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyReasoningOff_omitsAllReasoningFields(t *testing.T) {
|
||||
cfg := &einoopenai.ChatModelConfig{ExtraFields: map[string]any{
|
||||
"thinking": map[string]any{"type": "enabled"},
|
||||
@@ -127,7 +256,7 @@ func TestApplyReasoningOff_clientOverrideOmit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestApplyReasoningOff_deepseekExplicitlyDisablesDefaultThinking(t *testing.T) {
|
||||
for _, profile := range []string{"deepseek_compat", "auto"} {
|
||||
for _, profile := range []string{"deepseek_compat", "auto", "openai_compat"} {
|
||||
t.Run(profile, func(t *testing.T) {
|
||||
cfg := &einoopenai.ChatModelConfig{ExtraFields: map[string]any{
|
||||
"reasoning_effort": "high",
|
||||
|
||||
Reference in New Issue
Block a user