Fix empty content deltas and leaked section markers in streaming

Tool parser:
- Case 3/4: return None instead of DeltaMessage(content='') when
  inside an open tool section with no parseable content yet.
  Empty-string content deltas pollute the response and break the
  content=null vs content='' contract with non-streaming.

Reasoning parser:
- Suppress tool-calls section markers from content forwarding.
  The tool parser detects them via current_text re-parsing; forwarding
  them as content causes double-handling.
- Already-past-reasoning path: strip section markers from content
  for the same reason.
This commit is contained in:
2026-04-14 06:46:19 +00:00
parent fcf8fd134e
commit a404735b2d
2 changed files with 19 additions and 9 deletions

View File

@@ -249,6 +249,13 @@ class KimiK2ReasoningParser(ReasoningParser):
if self.is_reasoning_end(previous_token_ids):
# Strip any residual think tags that might appear in content
cleaned = self._strip_think_tags(delta_text)
if not cleaned:
return None
# If tool-calls section markers are present, suppress them
# from content — the tool parser handles them via current_text
# re-parsing and does not need them forwarded as content.
for variant in self._tool_section_start_variants:
cleaned = cleaned.replace(variant, "")
return DeltaMessage(content=cleaned) if cleaned else None
# ── Check for </think> in this delta ──
@@ -270,15 +277,13 @@ class KimiK2ReasoningParser(ReasoningParser):
tool_idx = self._find_tool_section_start(delta_text)
if tool_idx != -1:
reasoning = self._strip_think_tags(delta_text[:tool_idx])
# Forward the tool section marker as content so the tool
# parser can detect it.
content = delta_text[tool_idx:]
# Do NOT forward the tool section marker as content. The
# tool parser detects it via current_text re-parsing on its
# own. Forwarding it causes double-handling and empty content
# deltas.
kwargs = {}
if reasoning:
kwargs["reasoning"] = reasoning
if content:
kwargs["content"] = content
return DeltaMessage(**kwargs) if kwargs else None
# ── Still in reasoning — strip <think> tag if present ──