Repository navigation
Conversation
There was a problem hiding this comment.
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="astrbot/core/agent/context/manager.py" line_range="114-118" />
<code_context>
"""
logger.debug("Compress triggered, starting compression...")
- messages = await self.compressor(messages)
+ try:
+ messages = await self.compressor(messages)
+ except Exception as e:
+ raise ContextCompressionError(
+ f"Context compression failed: {e}",
+ messages=messages,
+ token_count=prev_tokens,
+ ) from e
</code_context>
<issue_to_address>
**Original conversation history is lost**
When a custom compressor mutates its input list in place and then raises, `_run_compression()` stores the same mutated `messages` list in `ContextCompressionError`, so the runner uses altered history instead of the pre-compression context and the caller loses history.
Preserve a copy of the messages before calling the compressor and store that copy in `ContextCompressionError` if compression fails.
</issue_to_address>
### Comment 2
<location path="astrbot/core/agent/runners/tool_loop_agent_runner.py" line_range="842-847" />
<code_context>
+ # Keep the count from before compression; a fresh local estimate may
+ # undercount the unchanged history and conceal a context overflow.
+ if max_tokens > 0 and e.token_count > max_tokens:
+ self._transition_state(AgentState.ERROR)
+ self.stats.end_time = time.time()
+ raise RuntimeError(
+ f"Context compression failed and the context exceeds the model's "
+ f"maximum context length ({e.token_count} > {max_tokens} tokens): {e}"
+ ) from e
+ logger.warning(
+ f"{e}. Attempting the uncompressed request "
</code_context>
<issue_to_address>
**Overflow leaves no final response**
When a caller relies on the runner’s final response after `run_agent()` handles a context-overflow exception, the overflow branch raises without assigning `self.final_llm_resp`, unlike the runner’s ordinary provider-error path. Callers that inspect `get_final_llm_resp()` after `run_agent()` handles the exception receive `None` instead of the terminal error response, so they cannot recognize or process the failure through the runner result.
Store the overflow error as the runner’s final response before raising, or route it through the runner’s normal error-response finalization path.
</issue_to_address>Sourcery assessment
Approval pending. 2 findings to address first.
Blocking findings: astrbot/core/agent/context/manager.py:118, astrbot/core/agent/runners/tool_loop_agent_runner.py:847
| messages = await self.compressor(messages) | ||
| except Exception as e: | ||
| raise ContextCompressionError( | ||
| f"Context compression failed: {e}", | ||
| messages=messages, |
There was a problem hiding this comment.
🟡 Medium · Original conversation history is lost
When a custom compressor mutates its input list in place and then raises, _run_compression() stores the same mutated messages list in ContextCompressionError, so the runner uses altered history instead of the pre-compression context and the caller loses history.
Preserve a copy of the messages before calling the compressor and store that copy in ContextCompressionError if compression fails.
Prompt for AI agents
In `astrbot/core/agent/context/manager.py` at lines 114-118:
**Original conversation history is lost**
When a custom compressor mutates its input list in place and then raises, `_run_compression()` stores the same mutated `messages` list in `ContextCompressionError`, so the runner uses altered history instead of the pre-compression context and the caller loses history.
Preserve a copy of the messages before calling the compressor and store that copy in `ContextCompressionError` if compression fails.| self._transition_state(AgentState.ERROR) | ||
| self.stats.end_time = time.time() | ||
| raise RuntimeError( | ||
| f"Context compression failed and the context exceeds the model's " | ||
| f"maximum context length ({e.token_count} > {max_tokens} tokens): {e}" | ||
| ) from e |
There was a problem hiding this comment.
🟡 Medium · Overflow leaves no final response
When a caller relies on the runner’s final response after run_agent() handles a context-overflow exception, the overflow branch raises without assigning self.final_llm_resp, unlike the runner’s ordinary provider-error path. Callers that inspect get_final_llm_resp() after run_agent() handles the exception receive None instead of the terminal error response, so they cannot recognize or process the failure through the runner result.
Store the overflow error as the runner’s final response before raising, or route it through the runner’s normal error-response finalization path.
Prompt for AI agents
In `astrbot/core/agent/runners/tool_loop_agent_runner.py` at lines 842-847:
**Overflow leaves no final response**
When a caller relies on the runner’s final response after `run_agent()` handles a context-overflow exception, the overflow branch raises without assigning `self.final_llm_resp`, unlike the runner’s ordinary provider-error path. Callers that inspect `get_final_llm_resp()` after `run_agent()` handles the exception receive `None` instead of the terminal error response, so they cannot recognize or process the failure through the runner result.
Store the overflow error as the runner’s final response before raising, or route it through the runner’s normal error-response finalization path.
When a summary request fails, AstrBot currently returns the unchanged history and recounts it with a local estimate. A lower estimate can then be reported as successful compression, as in #10551. Compression failure should instead reach the runner, which decides whether to attempt the original request.
Modifications
ContextCompressionErrorthrough the context manager with the pre-compression messages and token count. Failed summaries no longer trigger automatic history truncation or a successful-compression log.max_context_tokens. Otherwise, log the failure and attempt the uncompressed request. The 82% compression threshold remains separate from the 100% context-limit check.run_agent()handler catches the overflow exception and invokeson_agent_done.Related to #10551. This changes failure handling, not token estimation: the issue's last reported total of 1,043,200 is below its configured limit of 1,048,576, so it still permits a request attempt. New content or estimation error can cause the upstream model to reject that attempt. Successful compression retains the existing post-compression trimming behavior.
Screenshots or Test Results
Validated against
masterat776793b82:The warning is the existing
audioopdeprecation warning. The test run reused the local development environment with the latest master's declared OpenTelemetry dependencies installed in a temporary directory.Checklist
Summary by Sourcery
Propagate context compression failures to the runner so it can safely decide whether to retry with the original context or stop on provider-limit overflow.
Bug Fixes:
Enhancements:
Documentation:
Tests: