From 234e5c3957f6e07d8c7a65df72070f43c6760023 Mon Sep 17 00:00:00 2001 From: zgc37359-lang Date: Thu, 2 Apr 2026 19:24:54 +0800 Subject: [PATCH 1/2] fix: correct token estimation to prevent agent hang Token estimation was incorrectly counting content blocks: - For text blocks: was encoding entire JSON structure instead of just text - For thinking blocks: was double-counting (once in content, once in field) This caused massive overestimation of token counts, triggering summarization too frequently. Agent would get stuck in a loop between adding files and summarization, never completing tasks. Fixes MiniMax-AI/Mini-Agent#65 --- mini_agent/agent.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/mini_agent/agent.py b/mini_agent/agent.py index b7d7feab..a383879b 100644 --- a/mini_agent/agent.py +++ b/mini_agent/agent.py @@ -141,10 +141,19 @@ def _estimate_tokens(self) -> int: elif isinstance(msg.content, list): for block in msg.content: if isinstance(block, dict): - # Convert dict to string for calculation - total_tokens += len(encoding.encode(str(block))) - - # Count thinking + # Extract actual text content from content blocks + # to avoid over-estimating token count + block_type = block.get("type", "") + if block_type == "text" and "text" in block: + total_tokens += len(encoding.encode(block["text"])) + elif block_type == "thinking" and "thinking" in block: + # Thinking blocks are counted separately below + pass + else: + # For other block types (tool_use, etc.), encode the whole block + total_tokens += len(encoding.encode(str(block))) + + # Count thinking (only from field, not from content blocks to avoid double-counting) if msg.thinking: total_tokens += len(encoding.encode(msg.thinking)) @@ -166,7 +175,14 @@ def _estimate_tokens_fallback(self) -> int: elif isinstance(msg.content, list): for block in msg.content: if isinstance(block, dict): - total_chars += len(str(block)) + block_type = block.get("type", "") + if block_type == "text" and "text" in block: + total_chars += len(block["text"]) + elif block_type == "thinking" and "thinking" in block: + # Thinking blocks are counted separately below + pass + else: + total_chars += len(str(block)) if msg.thinking: total_chars += len(msg.thinking) From 201b2274b87376cd0a35c571a2af827a154bcadb Mon Sep 17 00:00:00 2001 From: zgc37359-lang Date: Thu, 2 Apr 2026 19:40:55 +0800 Subject: [PATCH 2/2] fix: handle None content when agent completes without text When agent completes a task without tool_calls but also without text content (e.g., only thinking), return thinking or empty string instead of None. --- mini_agent/agent.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mini_agent/agent.py b/mini_agent/agent.py index a383879b..1cf26e04 100644 --- a/mini_agent/agent.py +++ b/mini_agent/agent.py @@ -434,7 +434,8 @@ async def run(self, cancel_event: Optional[asyncio.Event] = None) -> str: step_elapsed = perf_counter() - step_start_time total_elapsed = perf_counter() - run_start_time print(f"\n{Colors.DIM}⏱️ Step {step + 1} completed in {step_elapsed:.2f}s (total: {total_elapsed:.2f}s){Colors.RESET}") - return response.content + # Return content or thinking or empty string if neither exists + return response.content if response.content else (response.thinking if response.thinking else "") # Check for cancellation before executing tools if self._check_cancelled():