fix: Message.ReasoningContent/Reasoning 改为 *string,修复空思考内容在请求转发时被静默丢弃的问题

问题:
在非 passThrough 模式下,客户端发送的 reasoning_content: "" 经过
Go struct 反序列化再序列化后,因 string + omitempty 无法区分空串和
字段缺失,导致空的思考内容被静默丢弃。

根因:
dto.Message.ReasoningContent 和 Message.Reasoning 使用 string(非指针)
加 omitempty,违反 AGENTS.md Rule 6(可选标量字段必须用指针类型)。

修复:
1. Message.ReasoningContent/Reasoning 类型从 string 改为 *string
   - nil = 字段缺失 → JSON 省略
   - &"" = 显式空串 → JSON 保留 reasoning_content: ""
2. 新增 Message.GetReasoningContent() 辅助方法
3. 更新所有读写处:relay-openai, relay-claude, relay-gemini, ollama
4. 新增测试覆盖空串保留、字段省略、getter 回退逻辑
This commit is contained in:
heimoshuiyu
2026-04-29 13:43:26 +08:00
committed by Calcium-Ion
parent 22ae14f0d7
commit 8ca103342d
6 changed files with 123 additions and 7 deletions
+12 -2
View File
@@ -279,8 +279,8 @@ type Message struct {
Content any `json:"content"`
Name *string `json:"name,omitempty"`
Prefix *bool `json:"prefix,omitempty"`
ReasoningContent string `json:"reasoning_content,omitempty"`
Reasoning string `json:"reasoning,omitempty"`
ReasoningContent *string `json:"reasoning_content,omitempty"`
Reasoning *string `json:"reasoning,omitempty"`
ToolCalls json.RawMessage `json:"tool_calls,omitempty"`
ToolCallId string `json:"tool_call_id,omitempty"`
parsedContent []MediaContent
@@ -431,6 +431,16 @@ const (
//ContentTypeAudioUrl = "audio_url"
)
func (m *Message) GetReasoningContent() string {
if m.ReasoningContent == nil && m.Reasoning == nil {
return ""
}
if m.ReasoningContent != nil {
return *m.ReasoningContent
}
return *m.Reasoning
}
func (m *Message) GetPrefix() bool {
if m.Prefix == nil {
return false