Merge pull request #7607 from ResidualBlood/fix/antigravity-malformed-function-call-retry

fix(antigravity): trigger failover retry on empty stream caused by MALFORMED_FUNCTION_CALL
This commit is contained in:
Wesley Liddick
2026-09-28 10:50:53 +08:00
committed by GitHub
2 changed files with 17 additions and 11 deletions
@@ -40,6 +40,7 @@ type StreamingProcessor struct {
outputTokens int
cacheReadTokens int
imageOutputTokens int
hasContent bool
}
// NewStreamingProcessor 创建流式响应处理器
@@ -175,6 +176,11 @@ func (p *StreamingProcessor) MessageStartSent() bool {
return p.messageStartSent
}
// HasContent reports whether any substantive text, thinking, or tool calls were emitted.
func (p *StreamingProcessor) HasContent() bool {
return p.hasContent
}
// emitMessageStart 发送 message_start 事件
func (p *StreamingProcessor) emitMessageStart(v1Resp *V1InternalResponse) []byte {
if p.messageStartSent {
@@ -296,6 +302,7 @@ func (p *StreamingProcessor) processThinking(text, signature string) []byte {
}
if text != "" {
p.hasContent = true
_, _ = result.Write(p.emitDelta("thinking_delta", map[string]any{
"thinking": text,
}))
@@ -350,6 +357,7 @@ func (p *StreamingProcessor) processText(text, signature string) []byte {
}))
}
p.hasContent = true
_, _ = result.Write(p.emitDelta("text_delta", map[string]any{
"text": text,
}))
@@ -362,6 +370,7 @@ func (p *StreamingProcessor) processFunctionCall(fc *GeminiFunctionCall, signatu
var result bytes.Buffer
p.usedTool = true
p.hasContent = true
toolID := fc.ID
if toolID == "" {
@@ -141,15 +141,18 @@ func (s *antigravityCompatStreamSession) consume(line string) {
}
func (s *antigravityCompatStreamSession) hasMeaningfulData() bool {
return s.meaningfulData
return s.meaningfulData || s.processor.HasContent()
}
func (s *antigravityCompatStreamSession) finish() *antigravityStreamResult {
func (s *antigravityCompatStreamSession) finish() (*antigravityStreamResult, error) {
finalEvents, usage := s.processor.Finish()
mergeAntigravityCompatUsage(s.usage, usage)
s.consumeClaudeEvents(finalEvents)
if !s.hasMeaningfulData() && !s.writer.Disconnected() {
return nil, antigravityCompatEmptyStreamError()
}
s.adapter.Finalize(s.writer)
return s.result(s.writer.Disconnected())
return s.result(s.writer.Disconnected()), nil
}
func (s *antigravityCompatStreamSession) collectResult(clientDisconnect bool) *antigravityStreamResult {
@@ -220,24 +223,18 @@ func isMeaningfulAntigravityCompatEvent(event *apicompat.AnthropicStreamEvent) b
if event == nil {
return false
}
if event.Type == "message_stop" {
return true
}
if event.ContentBlock != nil {
block := event.ContentBlock
return block.Type == "tool_use" ||
block.Text != "" ||
block.Thinking != "" ||
block.Signature != "" ||
block.Source != nil
}
if event.Delta != nil {
delta := event.Delta
return delta.Text != "" ||
delta.PartialJSON != "" ||
delta.Thinking != "" ||
delta.Signature != "" ||
delta.StopReason != ""
delta.Thinking != ""
}
return false
}
@@ -295,7 +292,7 @@ func (s *AntigravityGatewayService) handleAntigravityCompatStream(
if !session.hasMeaningfulData() && !writer.Disconnected() {
return nil, antigravityCompatEmptyStreamError()
}
return session.finish(), nil
return session.finish()
}
if event.err != nil {
return s.handleAntigravityCompatReadError(c, session, event.err, maxLineSize, prefix)