refactor(agui): redesign event dispatching with strategy pattern and deferred queue#1341
refactor(agui): redesign event dispatching with strategy pattern and deferred queue#1341jujn wants to merge 22 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refactors the AG-UI adapter’s streaming event conversion to use a strategy-based dispatch model with a dedicated StreamContext that supports deferred “end” events, and extends the core message model with a CustomBlock to enable emitting AG-UI CUSTOM events.
Changes:
- Refactors
AguiAgentAdapterto dispatchContentBlockconversion viaBlockEventConverterstrategies and manage lifecycle/end-event ordering viaStreamContext. - Adds block converters for text, thinking/reasoning, tool use/results, and custom blocks under
adapter.strategy. - Introduces
CustomBlockas a newContentBlocksubtype and wires it into Jackson polymorphic serialization; updates AG-UI adapter tests for revised lifecycle behavior.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| agentscope-extensions/agentscope-extensions-agui/src/main/java/io/agentscope/core/agui/adapter/AguiAgentAdapter.java | Refactors the adapter to strategy-based block conversion and deferred end-event flushing. |
| agentscope-extensions/agentscope-extensions-agui/src/main/java/io/agentscope/core/agui/adapter/StreamContext.java | Adds a context object to track active lifecycles and queue/flush deferred end events. |
| agentscope-extensions/agentscope-extensions-agui/src/main/java/io/agentscope/core/agui/adapter/strategy/BlockEventConverter.java | Introduces the strategy interface for block→event conversion. |
| agentscope-extensions/agentscope-extensions-agui/src/main/java/io/agentscope/core/agui/adapter/strategy/TextBlockConverter.java | Implements text block conversion with lifecycle tracking and deferred end events. |
| agentscope-extensions/agentscope-extensions-agui/src/main/java/io/agentscope/core/agui/adapter/strategy/ThinkingBlockConverter.java | Implements reasoning conversion (when enabled) with lifecycle tracking and deferred end events. |
| agentscope-extensions/agentscope-extensions-agui/src/main/java/io/agentscope/core/agui/adapter/strategy/ToolUseBlockConverter.java | Implements tool call start/args conversion and interrupts active text/reasoning lifecycles. |
| agentscope-extensions/agentscope-extensions-agui/src/main/java/io/agentscope/core/agui/adapter/strategy/ToolResultBlockConverter.java | Implements tool result conversion and ensures tool call closure semantics. |
| agentscope-extensions/agentscope-extensions-agui/src/main/java/io/agentscope/core/agui/adapter/strategy/CustomBlockConverter.java | Implements CustomBlock→AG-UI CUSTOM event emission. |
| agentscope-extensions/agentscope-extensions-agui/src/test/java/io/agentscope/core/agui/adapter/AguiAgentAdapterTest.java | Updates test expectations for the new lifecycle/event ordering behavior. |
| agentscope-core/src/main/java/io/agentscope/core/message/CustomBlock.java | Adds a new ContentBlock subtype for custom extension payloads. |
| agentscope-core/src/main/java/io/agentscope/core/message/ContentBlock.java | Registers CustomBlock in the sealed hierarchy and Jackson subtype mapping. |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
|
@LearningGp |
|
For PRs related to ag-ui, please cc @chickenlj for a high-level review to avoid potential conflicts and misalignment. |
AgentScopeJavaBot
left a comment
There was a problem hiding this comment.
🤖 AI Review
This PR delivers a well-architected refactoring of the AG-UI adapter, replacing a monolithic if-else chain with a clean strategy pattern (BlockEventConverter) and introducing a StreamContext with deferred-end-event queue to resolve lifecycle ordering issues (#1382). The per-subscription state isolation via StreamContext is a significant improvement over the old instance-field approach, making the adapter safe for concurrent/retry subscriptions. Test coverage is strong with 30+ test methods including state-leak and custom-converter-override tests. The Spring Boot integration correctly wires custom converter beans via ObjectProvider. A few defensive-programming gaps and missing direct tests for StreamContext prevent a clean approval.
AgentScopeJavaBot
left a comment
There was a problem hiding this comment.
All blocking review comments have been addressed. 3 non-blocking suggestion(s) (minor/nit) remain open and may be addressed in a follow-up.
Description:
Closes #1347, #1382
This PR implements the architectural refactoring proposed in #1347, bringing a strategy-based dispatcher to the AG-UI adapter and enabling pluggable custom converters. Additionally, it fixes the lifecycle mismatch bug mentioned in #1382.
Code Changes & Architecture
AguiAgentAdapter: Replaced the massiveif-elseblock with aBlockEventConverterstrategy interface. The adapter now acts as a clean router (dispatching based on Block class).StreamContext: Replaced the heavySet-based state tracking with a lightweight context. It uses a Deferred Queue mechanism (delayingEndevents until termination or interruption), resolving lifecycle mismatch bugs.BlockEventConverterImplementations: Logic forTextBlock,ThinkingBlock,ToolUseBlock, andToolResultBlockare now beautifully isolated in their own classes.customConverters: To support future broader customization needs without modifying the core framework, we introduced new configuration mechanisms:AguiAdapterConfig): AddedcustomConvertersto allow developers to register their ownBlockEventConverterimplementations.agui-spring-boot-starter): ModifiedAgentscopeAguiMvcAutoConfigurationandAgentscopeAguiWebFluxAutoConfigurationby utilizingObjectProvider<BlockEventConverter<?>>. This allows the framework to automatically collect any custom converter beans defined in the Spring context (e.g., using@Component), transforming the adapter into a highly extensible microkernel architecture.测试脚本及日志.zip