fix: recover reasoning-only compact summaries instead of failing with EmptyResponse#220
Open
minhtq1234 wants to merge 1 commit into
Open
Conversation
… EmptyResponse Reasoning models (e.g. MiniMax M2.5) served via OpenAI-compatible endpoints may emit the entire compact summary as reasoning_content, which the provider maps to LlmEvent::ThinkingDelta. The compact stream collector discarded thinking deltas, so the collected text was empty and /compact and autocompact failed with "Empty response from LLM" even though the model produced a full summary. ThinkingConfig::Disabled does not prevent this: not every provider honors it. Collect thinking deltas alongside text and fall back to the reasoning content when the model produced no plain text. format_compact_summary already degrades gracefully when no <summary> tag is present. Truly empty responses still fail with EmptyResponse.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Running
/compact(and autocompact) fails withCompact failed: Empty response from LLMwhen the conversation model is a reasoning model served via an OpenAI‑compatible endpoint. Observed in AionUi with MiniMax M2.5 (customprovider): the model generates for ~17s, then the turn ends withevent_type="Error" text_len=0.Root cause
thinking: ThinkingConfig::Disabled(crates/aion-agent/src/compact/auto.rs), but the OpenAI projector only acts onThinkingConfig::Enabled(crates/aion-providers/src/projector.rs), so "disabled" never reaches the wire — reasoning models reason anyway.reasoning_contentdeltas toLlmEvent::ThinkingDelta(crates/aion-providers/src/openai.rs).collect_stream_textincompact/auto.rsaccumulated onlyTextDeltaand discarded thinking deltas. A model that emits its whole summary as reasoning yields an empty string →CompactError::EmptyResponse, even though a complete summary was produced (output budget is not the issue —COMPACT_MAX_OUTPUT_TOKENSis 20k).Fix
collect_stream_textnow accumulates thinking deltas alongside text and falls back to the reasoning content when the model produced no plain text.format_compact_summaryalready degrades gracefully when<summary>tags are absent, so the recovered content flows through the existing parsing unchanged.Behavior is otherwise preserved:
EmptyResponse.Donecan now salvage reasoning-only output; if nothing was received it still fails withEmptyResponseas before.Testing
reasoning_only_response_is_recovered(ThinkingDelta-only stream → compaction succeeds, summary contains the recovered content, failure counter untouched).empty_response_failsstill passes (truly empty stream →EmptyResponse).cargo test -p aion-agent— all tests pass.cargo fmt --all -- --checkandcargo clippy -p aion-agent -- -D warnings— clean.Repro context
AionUi desktop → aionrs conversation → MiniMax M2.5 (
customOpenAI-compatible provider) →/compact→Compact failed: Empty response from LLM. With this change the reasoning-only summary is recovered and compaction completes.