fix(chat): detect CONTINUATION conversation history headers - #460
fix(chat): detect CONTINUATION conversation history headers#460syf2211 wants to merge 3 commits into
Conversation
SimpleTool only checked for the legacy "=== CONVERSATION HISTORY ===" sentinel, so server-injected "(CONTINUATION)" headers were missed and history was rebuilt twice on continuation requests. Add has_embedded_conversation_history() and use it when deciding whether to reuse pre-embedded history. Fixes BeehiveInnovations#459
There was a problem hiding this comment.
Code Review
This pull request introduces the has_embedded_conversation_history helper function to check if a prompt contains server-built conversation history, replacing a hardcoded string check in tools/simple/base.py and adding corresponding integration tests. The review feedback suggests making this helper function more robust by handling None or non-string inputs gracefully and adding tests for these edge cases.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| def has_embedded_conversation_history(prompt: str) -> bool: | ||
| """Return True when a prompt already contains server-built conversation history.""" | ||
| return ( | ||
| "=== CONVERSATION HISTORY" in prompt | ||
| and "=== END CONVERSATION HISTORY ===" in prompt | ||
| ) |
There was a problem hiding this comment.
The function has_embedded_conversation_history assumes that prompt is always a valid string. However, if prompt is None or of another non-string type (which can happen if a tool's request prompt is optional or unset), performing 'in prompt' operations will raise a TypeError at runtime.
To enforce defensive programming and prevent potential crashes, we should add a type and null check at the beginning of the function.
| def has_embedded_conversation_history(prompt: str) -> bool: | |
| """Return True when a prompt already contains server-built conversation history.""" | |
| return ( | |
| "=== CONVERSATION HISTORY" in prompt | |
| and "=== END CONVERSATION HISTORY ===" in prompt | |
| ) | |
| def has_embedded_conversation_history(prompt: Optional[str]) -> bool: | |
| """Return True when a prompt already contains server-built conversation history.""" | |
| if not prompt or not isinstance(prompt, str): | |
| return False | |
| return ( | |
| "=== CONVERSATION HISTORY" in prompt | |
| and "=== END CONVERSATION HISTORY ===" in prompt | |
| ) |
| def test_has_embedded_conversation_history_rejects_plain_prompt(): | ||
| assert has_embedded_conversation_history("continue the discussion") is False |
There was a problem hiding this comment.
It is a good practice to add test cases for edge cases such as None or non-string inputs to verify that has_embedded_conversation_history handles them gracefully without raising exceptions.
| def test_has_embedded_conversation_history_rejects_plain_prompt(): | |
| assert has_embedded_conversation_history("continue the discussion") is False | |
| def test_has_embedded_conversation_history_rejects_plain_prompt(): | |
| assert has_embedded_conversation_history("continue the discussion") is False | |
| assert has_embedded_conversation_history(None) is False |
- Update test_continuation_with_huge_conversation_history to use server-style CONTINUATION headers including END marker - Run black on conversation_memory.py for CI lint compliance
Reformat 10 test files that failed black --check in CI.
Summary
Fix duplicate conversation history reconstruction when the server injects a
(CONTINUATION)header during chat continuations.Motivation
server.pyembeds history usingbuild_conversation_history(), which emits:SimpleToolonly checked for the exact legacy sentinel=== CONVERSATION HISTORY ===, so continuation prompts with the server header were treated as missing history. The tool then rebuilt the thread again, duplicating context and inflating prompt size.Fixes #459
Changes
has_embedded_conversation_history()inutils/conversation_memory.pytools/simple/base.pywhen deciding whether to reuse pre-embedded historyTests
Result: 4 passed
Notes
=== CONVERSATION HISTORY) and end marker (=== END CONVERSATION HISTORY ===) to avoid false positives.