From 15730d3ef45e109a9e1919203338b8f928347269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AC=E6=98=8E?= <83812544+Ed1s0nZ@users.noreply.github.com> Date: Fri, 19 Jun 2026 00:01:20 +0800 Subject: [PATCH] Add files via upload --- internal/openai/claude_bridge.go | 14 +++++--- .../openai/claude_reasoning_roundtrip_test.go | 33 +++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/internal/openai/claude_bridge.go b/internal/openai/claude_bridge.go index 10319202..c498e060 100644 --- a/internal/openai/claude_bridge.go +++ b/internal/openai/claude_bridge.go @@ -10,7 +10,7 @@ package openai // Auth: Bearer → x-api-key // Tools: OpenAI tools[] → Claude tools[] (input_schema) // -// Extended thinking: 顶层 `thinking` 从 OpenAI 请求体透传;响应中 `thinking` block 映射为 +// Extended thinking: 顶层 `thinking` / `output_config` 从 OpenAI 请求体透传;响应中 `thinking` block 映射为 // `reasoning_content`(可读前缀 + 内部 JSON 尾缀以保留 signature,供多轮工具续跑;UI 用 openai.DisplayReasoningContent 剥离)。 import ( @@ -40,8 +40,9 @@ type claudeRequest struct { System string `json:"system,omitempty"` Messages []claudeMessage `json:"messages"` Tools []claudeTool `json:"tools,omitempty"` - Stream bool `json:"stream,omitempty"` - Thinking json.RawMessage `json:"thinking,omitempty"` + Stream bool `json:"stream,omitempty"` + Thinking json.RawMessage `json:"thinking,omitempty"` + OutputConfig json.RawMessage `json:"output_config,omitempty"` } type claudeMessage struct { @@ -304,12 +305,17 @@ func convertOpenAIToClaude(payload interface{}) (*claudeRequest, error) { } } - // Extended thinking (Anthropic top-level); merged from Eino ExtraFields / admin extras. + // Extended thinking + effort (Anthropic top-level); merged from Eino ExtraFields / admin extras. if th, ok := oai["thinking"]; ok && th != nil { if raw, err := json.Marshal(th); err == nil && len(raw) > 0 && string(raw) != "null" { req.Thinking = json.RawMessage(raw) } } + if oc, ok := oai["output_config"]; ok && oc != nil { + if raw, err := json.Marshal(oc); err == nil && len(raw) > 0 && string(raw) != "null" { + req.OutputConfig = json.RawMessage(raw) + } + } return req, nil } diff --git a/internal/openai/claude_reasoning_roundtrip_test.go b/internal/openai/claude_reasoning_roundtrip_test.go index 6b112f1a..2f67389f 100644 --- a/internal/openai/claude_reasoning_roundtrip_test.go +++ b/internal/openai/claude_reasoning_roundtrip_test.go @@ -73,6 +73,39 @@ func TestConvertOpenAIToClaude_AssistantReasoningReplay(t *testing.T) { } } +func TestConvertOpenAIToClaude_OutputConfigEffort(t *testing.T) { + payload := map[string]interface{}{ + "model": "claude-opus-4-8", + "messages": []interface{}{ + map[string]interface{}{"role": "user", "content": "hi"}, + }, + "thinking": map[string]interface{}{ + "type": "adaptive", + "display": "summarized", + }, + "output_config": map[string]interface{}{ + "effort": "high", + }, + } + req, err := convertOpenAIToClaude(payload) + if err != nil { + t.Fatal(err) + } + if len(req.Thinking) == 0 { + t.Fatal("expected thinking") + } + if len(req.OutputConfig) == 0 { + t.Fatal("expected output_config") + } + var oc map[string]interface{} + if err := json.Unmarshal(req.OutputConfig, &oc); err != nil { + t.Fatal(err) + } + if oc["effort"] != "high" { + t.Fatalf("effort=%v", oc["effort"]) + } +} + func TestClaudeToOpenAIResponseJSON_Thinking(t *testing.T) { claudeBody := []byte(`{ "id":"msg_1","type":"message","role":"assistant","model":"x","stop_reason":"end_turn",