fix(apicompat): preserve empty streaming thinking blocks

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
nanobabanan 2026-05-18 15:10:35 +08:00
parent f5bd25bea0
commit e9a25e7b92
2 changed files with 26 additions and 0 deletions

View File

@ -744,6 +744,10 @@ func TestStreamingReasoning(t *testing.T) {
assert.Equal(t, "content_block_start", events[0].Type)
assert.Equal(t, "thinking", events[0].ContentBlock.Type)
sse, err := ResponsesAnthropicEventToSSE(events[0])
require.NoError(t, err)
assert.Contains(t, sse, `"content_block":{"thinking":"","type":"thinking"}`)
// reasoning text delta
events = ResponsesEventToAnthropicEvents(&ResponsesStreamEvent{
Type: "response.reasoning_summary_text.delta",

View File

@ -75,6 +75,28 @@ type AnthropicContentBlock struct {
IsError bool `json:"is_error,omitempty"`
}
func (b AnthropicContentBlock) MarshalJSON() ([]byte, error) {
type anthropicContentBlock AnthropicContentBlock
base := struct {
anthropicContentBlock
}{anthropicContentBlock: anthropicContentBlock(b)}
switch b.Type {
case "text":
return json.Marshal(struct {
Text string `json:"text"`
anthropicContentBlock
}{Text: b.Text, anthropicContentBlock: anthropicContentBlock(b)})
case "thinking":
return json.Marshal(struct {
Thinking string `json:"thinking"`
anthropicContentBlock
}{Thinking: b.Thinking, anthropicContentBlock: anthropicContentBlock(b)})
default:
return json.Marshal(base)
}
}
// AnthropicImageSource describes the source data for an image content block.
type AnthropicImageSource struct {
Type string `json:"type"` // "base64"