diff --git a/agent/prompt_builder.py b/agent/prompt_builder.py index 2a2ebafa09..771f946bf6 100644 --- a/agent/prompt_builder.py +++ b/agent/prompt_builder.py @@ -1422,10 +1422,11 @@ def _build_skills_system_prompt_inner( def _truncate_content( content: str, filename: str, max_chars: Optional[int] = None, context_length: Optional[int] = None, - read_path: Optional[str] = None, + read_path: Optional[str] = None, queue_warning: bool = True, ) -> str: """Head/tail truncation with a marker in the middle; ``read_path`` (default ``filename``) is what the - agent is told to ``read_file`` to recover the full content.""" + agent is told to ``read_file`` to recover the full content. ``queue_warning`` controls whether startup + context-file callers surface the truncation through the chat warning queue.""" if max_chars is None: max_chars = _get_context_file_max_chars(context_length) if len(content) <= max_chars: @@ -1435,9 +1436,10 @@ def _truncate_content( f"trim the file, pin a larger context_file_max_chars, or use a larger-context model!" ) logger.warning(msg) - if (warnings := _truncation_warnings.get()) is None: - _truncation_warnings.set(warnings := []) - warnings.append(msg) + if queue_warning: + if (warnings := _truncation_warnings.get()) is None: + _truncation_warnings.set(warnings := []) + warnings.append(msg) head_chars = int(max_chars * CONTEXT_TRUNCATE_HEAD_RATIO) tail_chars = int(max_chars * CONTEXT_TRUNCATE_TAIL_RATIO) marker = ( diff --git a/agent/subdirectory_hints.py b/agent/subdirectory_hints.py index cfd47d54d7..d1ad92c05b 100644 --- a/agent/subdirectory_hints.py +++ b/agent/subdirectory_hints.py @@ -214,7 +214,9 @@ class SubdirectoryHintTracker: # Same security scan as startup context loading. content = _scan_context_content(content, filename) rel_path = self._display_path(hint_path) - content = _truncate_content(content, filename, max_chars=_MAX_HINT_CHARS, read_path=rel_path) + content = _truncate_content( + content, filename, max_chars=_MAX_HINT_CHARS, read_path=rel_path, queue_warning=False, + ) logger.debug("Loaded subdirectory hints from %s: %s", directory, [rel_path]) return f"[Subdirectory context discovered: {rel_path}]\n{content}" # first match wins per directory except Exception as exc: diff --git a/tests/agent/test_subdirectory_hints.py b/tests/agent/test_subdirectory_hints.py index 1751318d73..3214b23236 100644 --- a/tests/agent/test_subdirectory_hints.py +++ b/tests/agent/test_subdirectory_hints.py @@ -7,6 +7,7 @@ from pathlib import Path from unittest.mock import patch from agent.search_policy import SEARCH_PRUNE_DIR_NAMES +from agent.prompt_builder import drain_truncation_warnings from agent.subdirectory_hints import SubdirectoryHintTracker @@ -135,6 +136,22 @@ class TestSubdirectoryHintTracker: assert len(result) < len(body) assert any("TRUNCATED" in r.message and "AGENTS.md" in r.message for r in caplog.records) + def test_truncation_of_large_hints_does_not_queue_context_file_warning(self, tmp_path): + """Hint previews retain their marker without surfacing a startup-context warning in chat (#111772).""" + from agent import subdirectory_hints as sh + + drain_truncation_warnings() + sub = tmp_path / "bigdir" + sub.mkdir() + (sub / "AGENTS.md").write_text("x" * (sh._MAX_HINT_CHARS + 1), encoding="utf-8") + + tracker = SubdirectoryHintTracker(working_dir=str(tmp_path)) + result = tracker.check_tool_call("read_file", {"path": str(sub / "file.py")}) + + assert result is not None + assert "truncated AGENTS.md" in result + assert drain_truncation_warnings() == [] + def test_area_file_under_ceiling_is_delivered_whole(self, tmp_path): """An area AGENTS.md sized like ours (well under the ceiling) arrives intact — no marker.""" sub = tmp_path / "gateway"