From 1e9532040f53d74cd9bff7da8f6e2805adde99bd Mon Sep 17 00:00:00 2001 From: rastinder Date: Thu, 28 May 2026 22:08:47 -0400 Subject: [PATCH] fix(compaction): filter empty text parts to avoid API 400 Context compaction fails with Moonshot API error 'text content is empty' when historical messages contain empty or whitespace-only TextParts. This applies the same defensive guard already used for tool messages (#1663) to the compaction path: 1. Filter out TextParts with empty/whitespace-only text when building the compaction prompt. 2. Skip compaction entirely if no meaningful text remains, falling back to preserving the full context. Fixes: context compaction crash during 'kimi export' --- src/kimi_cli/soul/compaction.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/kimi_cli/soul/compaction.py b/src/kimi_cli/soul/compaction.py index 7db37d5d8..7307a8114 100644 --- a/src/kimi_cli/soul/compaction.py +++ b/src/kimi_cli/soul/compaction.py @@ -175,7 +175,8 @@ def prepare( TextPart(text=f"## Message {i + 1}\nRole: {msg.role}\nContent:\n") ) compact_message.content.extend( - part for part in msg.content if isinstance(part, TextPart) + part for part in msg.content + if isinstance(part, TextPart) and part.text.strip() ) prompt_text = "\n" + prompts.COMPACT if custom_instruction: @@ -186,4 +187,11 @@ def prepare( f"{custom_instruction}" ) compact_message.content.append(TextPart(text=prompt_text)) + # Defensive: if after filtering there are no non-empty text parts besides + # headers and the prompt, skip compaction to avoid API 400 "text content is empty". + if not any( + isinstance(p, TextPart) and p.text.strip() + for p in compact_message.content + ): + return self.PrepareResult(compact_message=None, to_preserve=messages) return self.PrepareResult(compact_message=compact_message, to_preserve=to_preserve)