Skip to content

fix(chat): detect CONTINUATION conversation history headers - #460

Open
syf2211 wants to merge 3 commits into
BeehiveInnovations:mainfrom
syf2211:fix/continuation-history-detection
Open

fix(chat): detect CONTINUATION conversation history headers#460
syf2211 wants to merge 3 commits into
BeehiveInnovations:mainfrom
syf2211:fix/continuation-history-detection

Conversation

@syf2211

@syf2211 syf2211 commented Jun 29, 2026

Copy link
Copy Markdown

Summary

Fix duplicate conversation history reconstruction when the server injects a (CONTINUATION) header during chat continuations.

Motivation

server.py embeds history using build_conversation_history(), which emits:

=== CONVERSATION HISTORY (CONTINUATION) ===

SimpleTool only 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

  • Add has_embedded_conversation_history() in utils/conversation_memory.py
  • Use the helper in tools/simple/base.py when deciding whether to reuse pre-embedded history
  • Add regression tests for continuation and legacy header formats

Tests

pytest tests/test_conversation_continuation_integration.py -q

Result: 4 passed

Notes

  • Detection requires both the start prefix (=== CONVERSATION HISTORY) and end marker (=== END CONVERSATION HISTORY ===) to avoid false positives.
  • No runtime behavior change for in-process continuation paths that legitimately need reconstruction.

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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread utils/conversation_memory.py Outdated
Comment on lines +638 to +643
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
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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
)

Comment on lines +36 to +37
def test_has_embedded_conversation_history_rejects_plain_prompt():
assert has_embedded_conversation_history("continue the discussion") is False

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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

syf2211 added 2 commits June 29, 2026 22:03
- 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: chat continuation history is rebuilt twice when server injects CONTINUATION header

1 participant