feat(event): emit COMPACTION_START/END events from CompactionMiddleware#1962
feat(event): emit COMPACTION_START/END events from CompactionMiddleware#1962Buktal wants to merge 11 commits into
Conversation
When context compaction is triggered, CompactionMiddleware now emits COMPACTION_START before the summarization LLM call and COMPACTION_END after reasoning completes, allowing frontends to display progress instead of appearing frozen. Events carry token statistics so callers can show meaningful progress information. Closes agentscope-ai#1905
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
…ent and CompactionMiddleware - CompactionEventRoundTrip in AgentEventStreamTest: JSON serialization/deserialization round-trip via Jackson polymorphism for both compaction event types; field values and type discriminator are verified - CompactionMiddlewareTest: covers the four execution paths — no compaction (passthrough), compaction triggered (START/END wrap next flux), non-ReActAgent short-circuit, and compaction error fallback
Previously COMPACTION_START was emitted inside flatMapMany after the compactIfNeeded Mono completed, causing the frontend to appear stuck during the actual compaction wait period. Now the middleware performs a lightweight threshold pre-check and emits COMPACTION_START immediately before the compaction Mono subscribes. COMPACTION_END fires right after compaction completes, before reasoning output begins. All paths (success, skip, error) properly close the START/END pair so the frontend never hangs in loading state.
The test asserted inner events appeared between START and END, but the actual middleware contract is START → END → inner (compaction finishes before reasoning begins). Also improved the error-path test to use a low threshold config that actually enters the compaction branch, ensuring the START/END pairing contract is verified on error recovery.
Tests that call agent.call() without closing the agent leave background resources (session writers, task repositories) running, causing JUnit @tempdir cleanup to fail with DirectoryNotEmptyException. Wrap agent construction in try-with-resources to ensure proper shutdown before temp directory deletion.
jujn
left a comment
There was a problem hiding this comment.
Additionally, it is suggested to narrow down the PR description from "Fixes1905" to partial fixes (including only COMPACTION-START/END events)
Move onErrorResume before flatMapMany so it only catches errors from compactIfNeeded(), not from downstream next.apply() execution. This prevents duplicate model/tool execution and misleading compaction end events when downstream reasoning fails after a successful compaction.
|
This PR has conflicts with the git fetch origin
git checkout feat/compaction-events
git rebase origin/main
# resolve conflicts, then:
git push --force-with-leaseThis is a one-time reminder. Feel free to @mention me for a re-review after conflicts are resolved. Automated notification by github-manager-bot |
AgentScopeJavaBot
left a comment
There was a problem hiding this comment.
🤖 AI Review
Adds COMPACTION_START/END events from CompactionMiddleware. Good observability addition. Design concerns: START fires speculatively (ambiguous cancel), triggerThreshold misleading for message-count triggers, estimatedTokensSaved could be negative.
(inline comments could not be attached — line numbers fell outside PR hunks. See archived report.)
…t semantics Address PR review feedback on the COMPACTION_START/END events: * Split ConversationCompactor into probe() + execute(): probe runs the non-LLM truncate/prune passes and locates a safe cutoff without side effects, returning a sealed CompactionDecision (Proceed | Skip). CompactionMiddleware now emits COMPACTION_START only when compaction will actually run, eliminating the speculative-start / synthetic-end pair emitted when internal skip paths were hit. compactIfNeeded() is kept as a convenience wrapper for existing callers. * CompactionStartEvent gains a TriggerReason enum (TOKEN_THRESHOLD / MESSAGE_THRESHOLD), thresholdValue, and messageCount so consumers can interpret the fired dimension. Legacy `triggerThreshold` JSON is still accepted via @JsonAlias; getTriggerThreshold() is @deprecated. * CompactionEndEvent gains an Outcome enum (COMPACTED / FAILED) plus beforeTokens / afterTokens observations. getEstimatedTokensSaved() is retained as a @deprecated derived accessor; it may be negative when the preserved tail outweighs the removed prefix — documented, not masked. Tests updated to cover the new fields, the legacy JSON alias round-trip, and the FAILED outcome on the compaction error path. No behaviour change in the happy path; skip paths now produce no compaction events at all.
# Conflicts: # agentscope-core/src/main/java/io/agentscope/core/event/AgentEvent.java # agentscope-core/src/main/java/io/agentscope/core/event/AgentEventType.java
|
@oss-maintainer Conflicts resolved. Thanks! |


AgentScope-Java Version
2.0.0-SNAPSHOT
Description
Fixes #1905.
Background: When
CompactionMiddlewaretriggers context compaction (a summarization LLM call), the frontend receives no events during this period and appears frozen.Changes:
COMPACTION_STARTandCOMPACTION_ENDtoAgentEventTypeCompactionStartEvent(carriesestimatedTokens,triggerThreshold) andCompactionEndEvent(carriesoriginalMessageCount,compactedMessageCount,estimatedTokensSaved)AgentEvent@JsonSubTypesCompactionMiddleware.onReasoning()wraps the reasoning stream withCOMPACTION_START→ stream →COMPACTION_ENDwhen compaction is actually triggered (events are not emitted when the token threshold is not reached)Testing: Full build passes (
mvn clean install). The events fire only when compaction triggers, consistent with the existing event model (e.g.MODEL_CALL_START/END).Checklist
mvn spotless:applymvn test)