Skip to content

refactor(agui): redesign event dispatching with strategy pattern and deferred queue#1341

Open
jujn wants to merge 22 commits into
agentscope-ai:mainfrom
jujn:refactor/agui
Open

refactor(agui): redesign event dispatching with strategy pattern and deferred queue#1341
jujn wants to merge 22 commits into
agentscope-ai:mainfrom
jujn:refactor/agui

Conversation

@jujn

@jujn jujn commented May 5, 2026

Copy link
Copy Markdown
Contributor

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

  1. Refactored AguiAgentAdapter: Replaced the massive if-else block with a BlockEventConverter strategy interface. The adapter now acts as a clean router (dispatching based on Block class).
  2. Introduced StreamContext: Replaced the heavy Set-based state tracking with a lightweight context. It uses a Deferred Queue mechanism (delaying End events until termination or interruption), resolving lifecycle mismatch bugs.
  3. Added BlockEventConverter Implementations: Logic for TextBlock, ThinkingBlock, ToolUseBlock, and ToolResultBlock are now beautifully isolated in their own classes.
  4. Introduced Pluggable customConverters: To support future broader customization needs without modifying the core framework, we introduced new configuration mechanisms:
    • Core Config (AguiAdapterConfig): Added customConverters to allow developers to register their own BlockEventConverter implementations.
    • Spring Boot Auto-Configuration (agui-spring-boot-starter): Modified AgentscopeAguiMvcAutoConfiguration and AgentscopeAguiWebFluxAutoConfiguration by utilizing ObjectProvider<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.
  5. Updated Tests: For AguiAgentAdapterTest.java, all existing unit tests pass smoothly(just modified one), proving backward compatibility. And added new tests to cover the remaining newly added code.

[📝 Multi-Model Log Comparison]

To ensure that the refactored AguiAgentAdapter behaves consistently and correctly across different LLMs, I evaluated the AG-UI event outputs before and after the refactoring by running 12 test cases(See the attachment agui_test.js) across each of the 5 different models (qwen3.5-plus, gpt-5.2, kimi-k2.6, MiniMax-M2.5, deepseek-v4-pro, glm-5).

Testing context: The tests were conducted using agentscope-examples/integration/agui with reasoning events enabled. (Test scripts and full logs are attached).
Result: After a rigorous dual review by human and AI, no issues have been found so far post-refactoring.

Appendix: AG-UI Log Review Criteria
The logs were meticulously audited against the following standards:

  1. Lifecycle Completeness: Ensure the complete lifecycle (start, content, end) for reasoning events, tool call events, and text events (tool calls also include a result event). The messageId or toolCallId must remain exactly consistent throughout each lifecycle.
  2. Strict Event Ordering: Ensure events follow a rigorous sequence (e.g., a reasoning event must fully end before a text event starts; a reasoning event must fully end before a tool event starts).
  3. No Duplicate Events: Check for redundant start or end events within each test case (e.g., no multiple reasoning start/end events sharing the identical messageId).
  4. Content Integrity: Verify that concatenated content events form a complete message without any truncation or interruption.
  5. Focus: Note that the "before" logs may contain pre-existing framework bugs. The primary focus of this audit is verifying the absolute correctness of the "after" logs (post-refactoring).

测试脚本及日志.zip

@jujn jujn requested review from a team and Copilot May 5, 2026 14:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 AguiAgentAdapter to dispatch ContentBlock conversion via BlockEventConverter strategies and manage lifecycle/end-event ordering via StreamContext.
  • Adds block converters for text, thinking/reasoning, tool use/results, and custom blocks under adapter.strategy.
  • Introduces CustomBlock as a new ContentBlock subtype 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.

@jujn jujn marked this pull request as draft May 17, 2026 13:14
@jujn jujn marked this pull request as ready for review May 20, 2026 15:59
@jujn

jujn commented May 27, 2026

Copy link
Copy Markdown
Contributor Author

@LearningGp
Could you please prioritize reviewing this PR when you have time? This is very important for the future maintainability and extensibility of the ag-ui module. Thanks very mach.

@LearningGp

Copy link
Copy Markdown
Member

For PRs related to ag-ui, please cc @chickenlj for a high-level review to avoid potential conflicts and misalignment.

@jujn jujn force-pushed the refactor/agui branch from f1aa28d to 97c19d8 Compare June 6, 2026 14:18

@AgentScopeJavaBot AgentScopeJavaBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 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 AgentScopeJavaBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All blocking review comments have been addressed. 3 non-blocking suggestion(s) (minor/nit) remain open and may be addressed in a follow-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ext/integration External protocols & middleware integrations area/ext/spring-boot Spring Boot starters enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: refactor ag-ui adapter

4 participants