diff --git a/server/internal/proxy/convert/stream.go b/server/internal/proxy/convert/stream.go index 77a779e..7630af1 100644 --- a/server/internal/proxy/convert/stream.go +++ b/server/internal/proxy/convert/stream.go @@ -412,9 +412,10 @@ func (t *responsesToChat) line(line []byte) []byte { type chatToResponses struct { sseState - model string - usage any - done bool + model string + usage any + finishSeen bool + done bool } func newChatToResponses() *chatToResponses { return &chatToResponses{} } @@ -425,6 +426,7 @@ func (t *chatToResponses) line(line []byte) []byte { return nil } if done { + // 流结束兜底:finish 后 usage 未随块到达时在此补发 completed if !t.done { t.done = true return eventLine("response.completed", map[string]any{ @@ -453,6 +455,9 @@ func (t *chatToResponses) line(line []byte) []byte { finish, _ = c0["finish_reason"].(string) } } + if finish != "" { + t.finishSeen = true + } var out [][]byte if role, _ := delta["role"].(string); role == "assistant" { out = append(out, eventLine("response.created", map[string]any{ @@ -465,7 +470,8 @@ func (t *chatToResponses) line(line []byte) []byte { "type": "response.output_text.delta", "delta": content, "item_id": "msg_1", "output_index": 0, "content_index": 0, })) } - if finish != "" && !t.done { + // 上游 usage 块(choices 为空)通常晚于 finish_reason:此时再发 completed,携带 usage + if _, hasUsage := m["usage"]; hasUsage && t.finishSeen && !t.done { t.done = true out = append(out, eventLine("response.completed", map[string]any{ "type": "response.completed",