| 1 | package openai |
| 2 | |
| 3 | import ( |
| 4 | "strings" |
| 5 | |
| 6 | "reasonix/internal/provider" |
| 7 | ) |
| 8 | |
| 9 | func hasReasoningOrToolCall(m provider.Message) bool { |
| 10 | return len(m.ToolCalls) > 0 || m.ReasoningContent != "" |
| 11 | } |
| 12 | |
| 13 | // RequiresAssistantReasoningReplay keeps provider-issued reasoning replayable |
| 14 | // on every DeepSeek-style assistant turn that carries it. Tool turns remain |
| 15 | // required even when reasoning was lost because the wire accepts an empty key. |
| 16 | func (c *client) RequiresAssistantReasoningReplay(m provider.Message) bool { |
| 17 | if c == nil { |
| 18 | return false |
| 19 | } |
| 20 | if c.kimiK3 { |
| 21 | return true |
| 22 | } |
| 23 | if c.zhipu { |
| 24 | return strings.TrimSpace(m.ReasoningContent) != "" |
| 25 | } |
| 26 | if c.deepseek { |
| 27 | return strings.TrimSpace(m.ReasoningContent) != "" || |
| 28 | (len(m.ToolCalls) > 0 && c.RequiresToolCallReasoning()) |
| 29 | } |
| 30 | if c.RequiresToolCallReasoning() { |
| 31 | return len(m.ToolCalls) > 0 || strings.TrimSpace(m.ReasoningContent) != "" |
| 32 | } |
| 33 | return false |
| 34 | } |
| 35 |