feat(agui): support tool execution progress and fix stream delta loss#1240
feat(agui): support tool execution progress and fix stream delta loss#1240jujn wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR enhances the AG-UI adapter’s streaming behavior by (1) optionally surfacing tool-execution progress in real time and (2) preventing “tail-end” deltas from being dropped when the terminating (isLast=true) packet still carries content.
Changes:
- Added
enableToolProgressStreamtoAguiAdapterConfigand wired it intoStreamOptions.includeActingChunk. - Updated
AguiAgentAdapter.convertEvent()to emit text/tool-args deltas even whenevent.isLast()is true, then close lifecycles afterward to avoid tail-data loss. - Added tests covering last-packet content preservation and tool progress streaming scenarios.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| agentscope-extensions/agentscope-extensions-agui/src/main/java/io/agentscope/core/agui/adapter/AguiAgentAdapter.java | Adds acting-chunk option plumbing; adjusts last-event handling; introduces tool-progress-to-reasoning mapping. |
| agentscope-extensions/agentscope-extensions-agui/src/main/java/io/agentscope/core/agui/adapter/AguiAdapterConfig.java | Adds new config flag and builder method for enabling tool progress stream. |
| agentscope-extensions/agentscope-extensions-agui/src/test/java/io/agentscope/core/agui/adapter/AguiAgentAdapterTest.java | Adds/updates tests for tail-end preservation and tool progress streaming behavior. |
| // Start message if not started | ||
| if (!state.hasStartedMessage(messageId)) { | ||
| events.add( | ||
| new AguiEvent.TextMessageStart( | ||
| state.threadId, state.runId, messageId, "assistant")); | ||
| state.startMessage(messageId); | ||
| } | ||
|
|
||
| if (!event.isLast()) { | ||
| // In incremental mode, text is already the delta | ||
| events.add( | ||
| new AguiEvent.TextMessageContent( | ||
| state.threadId, state.runId, messageId, text)); | ||
| } else { | ||
| // End message if this is the last event | ||
| if (!state.hasEndedMessage(messageId)) { | ||
| events.add( | ||
| new AguiEvent.TextMessageEnd( | ||
| state.threadId, state.runId, messageId)); | ||
| state.endMessage(messageId); | ||
| } | ||
| } | ||
| events.add( | ||
| new AguiEvent.TextMessageContent( | ||
| state.threadId, state.runId, messageId, text)); |
There was a problem hiding this comment.
Text deltas are now always emitted even when event.isLast() is true. If a TextMessageEnd was already emitted earlier for the same messageId (e.g., because a ToolUseBlock ended the active text message), this can result in TextMessageContent being sent after TextMessageEnd with no subsequent restart/end, which is an invalid lifecycle for many consumers. Consider suppressing content emission for ended messages, or introducing a continuation strategy (e.g., generate a new messageId for post-tool text) so that content is never emitted after an end event.
There was a problem hiding this comment.
Perhaps we can use the idea of ag-ui-4j to introduce an event stream and subscriber distribution pattern, abstracting events into explicit lifecycle callbacks. Thus eliminating the fragile isLast() guess. I will study it later and create a new PR to refactor it.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |

Description
Close #1222
This PR introduces support for real-time tool execution progress and addresses the streaming data loss edge cases.
Key Changes
Support Tool Progress Stream: - Added
enableToolProgressStreaminAguiAdapterConfig.!event.isLast()) intoReasoningMessageevents to display real-time progress on the frontend without modifying the AG-UI protocol.Fix Tail-End Data Loss:
isLasttermination logic from the data extraction process inconvertEvent().Checklist
Please check the following items before code is ready to be reviewed.
mvn spotless:applymvn test)