Skip to content

fix(openai): drop non-chunk summary event message to avoid content duplication#2367

Merged
jujn merged 2 commits into
agentscope-ai:mainfrom
Buktal:fix/openai-summary-event-dedup
Jul 24, 2026
Merged

fix(openai): drop non-chunk summary event message to avoid content duplication#2367
jujn merged 2 commits into
agentscope-ai:mainfrom
Buktal:fix/openai-summary-event-dedup

Conversation

@Buktal

@Buktal Buktal commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

AgentScope-Java Version

2.0.1-SNAPSHOT

Description

Fixes #2366.

Some OpenAI-compatible providers (confirmed with MiniMax-M3) terminate a streaming response with an extra non-chunk chat.completion summary event whose message restates the full message (reasoning text + complete tool-call arguments) that the incremental delta chunks already delivered.

OpenAIResponse.isChunk() returns false for this summary, so OpenAIResponseParser.parseResponse routes it to parseCompletionResponse, extracting the full message into ContentBlocks identical to what the deltas already produced. ReasoningContext then accumulates them on top of the existing content:

  • reasoning_content is doubled (delta-accumulated full text + summary full text)
  • tool_call.arguments are concatenated into {...}{...} (invalid JSON), which survives loose JSON validation, is sent back on the next round, and the model rejects it (returns empty choices:[]), halting the agent.

Changes

OpenAIClient.stream(): after the error check and before emitting, if the response is not a chunk (i.e. a summary event), clear its choice.message while keeping the choice (so finish_reason is preserved) and usage (real token counts only appear in the summary event). Provider-agnostic, lives at the protocol-normalization layer alongside the existing [DONE] filtering and error detection.

How to test

Regression test MinimaxDoubledSummaryReplayTest replays a 6-event SSE trace captured from a real MiniMax-M3 stream (5 incremental chat.completion.chunk deltas + 1 non-chunk chat.completion summary) through the real OpenAIClient.stream() (driven by a stub HttpTransport), then feeds the parsed OpenAIResponses through OpenAIResponseParser and ReasoningContext:

  1. summaryEventMessageClearedByTransportLayer — asserts the summary event's choice.message is cleared while finish_reason is preserved (the fix point).
  2. reasoningAndToolArgsNotDoubled — asserts accumulated reasoning contains Let me start by loading once (not twice) and tool args contain AIHOT_marketplace once (not {...}{...}).

Both tests fail without the fix (message non-null; reasoning/args counted twice) and pass with it.

Checklist

  • Code has been formatted with mvn spotless:apply
  • All tests are passing (mvn test)
  • Javadoc comments are complete and follow project conventions
  • Related documentation has been updated (e.g. links, examples, etc.)
  • Code is ready for review

…plication

Some OpenAI-compatible providers (e.g. MiniMax-M3) emit an extra non-chunk
chat.completion summary event at the end of a stream whose message restates
the entire message. The incremental deltas already accumulated the full
content, so accumulating the summary message again doubles reasoning_content
and concatenates tool_call arguments into {...}{...} (invalid JSON), which
the model rejects on the next round and halts the agent.

Strip the summary event's message at the transport layer in
OpenAIClient.stream(), keeping the choice (finish_reason) and usage (real
token counts only appear in the summary). Provider-agnostic, alongside the
existing [DONE] filtering.

Closes agentscope-ai#2366
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...entscope/extensions/model/openai/OpenAIClient.java 85.71% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@Buktal

Buktal commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

@jujn
jujn merged commit 1a1d359 into agentscope-ai:main Jul 24, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Streaming: non-chunk chat.completion summary event (MiniMax-M3) doubles accumulated content, halting the agent

2 participants