diff --git a/agent/context_compressor.py b/agent/context_compressor.py index 5c0e0edf4573d..e91b24c2f9aeb 100644 --- a/agent/context_compressor.py +++ b/agent/context_compressor.py @@ -102,22 +102,24 @@ def _generate_summary(self, turns_to_summarize: List[Dict[str, Any]]) -> Optiona parts.append(f"[{role.upper()}]: {content}") content_to_summarize = "\n\n".join(parts) - prompt = f"""Summarize these conversation turns concisely. This summary will replace these turns in the conversation history. - -Write from a neutral perspective describing: -1. What actions were taken (tool calls, searches, file operations) -2. Key information or results obtained -3. Important decisions or findings -4. Relevant data, file names, or outputs - -Keep factual and informative. Target ~{self.summary_target_tokens} tokens. - ---- -TURNS TO SUMMARIZE: -{content_to_summarize} ---- - -Write only the summary, starting with "[CONTEXT SUMMARY]:" prefix.""" + prompt = ( + "You are performing a CONTEXT CHECKPOINT COMPACTION. Create a handoff " + "summary for the AI assistant that will resume this conversation.\n\n" + "Include:\n" + "- Current progress and key decisions made\n" + "- Important context, constraints, or user preferences discovered\n" + "- What remains to be done (clear next steps)\n" + "- Any critical data: file paths, variable names, URLs, error messages, " + "or code snippets needed to continue\n" + "- Tool calls made and their key results\n\n" + "Be concise, structured, and focused on helping the assistant seamlessly " + "continue the work without re-doing what's already been done.\n\n" + f"Target roughly {self.summary_target_tokens} tokens.\n\n" + "---\n" + f"TURNS TO SUMMARIZE:\n{content_to_summarize}\n" + "---\n\n" + 'Write only the summary, starting with "[CONTEXT SUMMARY]:" prefix.' + ) # Use the centralized LLM router — handles provider resolution, # auth, and fallback internally. diff --git a/tests/agent/test_context_compressor.py b/tests/agent/test_context_compressor.py index dac64aaf6ddf1..58b7b977f2cd9 100644 --- a/tests/agent/test_context_compressor.py +++ b/tests/agent/test_context_compressor.py @@ -153,6 +153,33 @@ def test_none_content_in_system_message_compress(self): assert len(result) < len(msgs) +class TestSummaryPrompt: + def test_generate_summary_uses_handoff_compaction_prompt(self): + mock_response = MagicMock() + mock_response.choices = [MagicMock()] + mock_response.choices[0].message.content = "[CONTEXT SUMMARY]: compacted" + + with patch("agent.context_compressor.get_model_context_length", return_value=100000): + c = ContextCompressor(model="test", quiet_mode=True, summary_target_tokens=1234) + + messages = [ + {"role": "user", "content": "Investigate the failing test"}, + {"role": "assistant", "content": "I'll inspect the traceback."}, + ] + + with patch("agent.context_compressor.call_llm", return_value=mock_response) as mock_call_llm: + c._generate_summary(messages) + + prompt = mock_call_llm.call_args.kwargs["messages"][0]["content"] + assert "CONTEXT CHECKPOINT COMPACTION" in prompt + assert "Current progress and key decisions made" in prompt + assert "Important context, constraints, or user preferences discovered" in prompt + assert "What remains to be done (clear next steps)" in prompt + assert "Tool calls made and their key results" in prompt + assert "Target roughly 1234 tokens." in prompt + assert 'Write only the summary, starting with "[CONTEXT SUMMARY]:" prefix.' in prompt + + class TestNonStringContent: """Regression: content as dict (e.g., llama.cpp tool calls) must not crash."""