"""WebFetch must never post raw binary into the model's context. The field bug: fetching a PDF handed the model megabytes of `%PDF-1.5` gibberish, which cost real money, told it nothing, and pushed real content out of the window. Same class for images and any other binary body. """ import pytest import backend.apps.agents.tools.fetch.wayback as WB from backend.apps.agents.tools.fetch.page_text import ( MAX_PDF_PAGES, body_to_text, extract_pdf_text, looks_like_pdf, ) from backend.apps.agents.tools.browser_http import HttpReply from backend.apps.agents.tools.fetch.wayback import fetch_wayback, snapshot_date def p_minimal_pdf(text: str = "Hello from a real PDF") -> bytes: """A genuine 600-byte one-page PDF with a real font resource and xref table.""" stream = f"BT /F1 18 Tf 20 100 Td ({text}) Tj ET".encode() objects = [ b"<< /Type /Catalog /Pages 2 0 R >>", b"<< /Type /Pages /Kids [3 0 R] /Count 1 >>", b"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] /Contents 4 0 R " b"/Resources << /Font << /F1 5 0 R >> >> >>", b"<< /Length " + str(len(stream)).encode() + b" >>\nstream\n" + stream + b"\nendstream", b"<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>", ] out = bytearray(b"%PDF-1.4\n") offsets = [] for i, body in enumerate(objects, start=1): offsets.append(len(out)) out += f"{i} 0 obj\n".encode() + body + b"\nendobj\n" xref = len(out) out += f"xref\n0 {len(objects) + 1}\n".encode() + b"0000000000 65535 f \n" for offset in offsets: out += f"{offset:010d} 00000 n \n".encode() out += f"trailer\n<< /Size {len(objects) + 1} /Root 1 0 R >>\nstartxref\n{xref}\n%%EOF\n".encode() return bytes(out) # ------------------------------------------------------------------ PDF def test_pdf_is_detected_by_magic_bytes_not_just_the_header(): # Servers mislabel PDFs as text/html constantly. assert looks_like_pdf("text/html", b"%PDF-1.7\n...") is True assert looks_like_pdf("application/pdf", b"") is True assert looks_like_pdf("text/html", b"") is False def test_a_real_pdf_yields_its_text_not_its_bytes(): raw = p_minimal_pdf("Attention Is All You Need") out = body_to_text("application/pdf", raw, raw.decode("latin-1")) assert out.kind == "pdf" assert "Attention Is All You Need" in out.text assert "%PDF" not in out.text def test_a_pdf_with_no_text_layer_says_so_instead_of_dumping_it(): fake = b"%PDF-1.4\n" + b"\x00\x01\x02" * 500 out = body_to_text("application/pdf", fake, "ignored") assert out.kind == "pdf_unreadable" assert "no extractable text layer" in out.text assert "\x00" not in out.text def test_extract_returns_none_rather_than_raising_on_garbage(): assert extract_pdf_text(b"not a pdf at all") is None def test_page_cap_is_bounded(): assert 0 < MAX_PDF_PAGES <= 500 # ------------------------------------------------------------------ other binaries def test_an_image_is_refused_with_a_description_not_its_bytes(): png = b"\x89PNG\r\n\x1a\n" + bytes(range(256)) * 40 out = body_to_text("image/png", png, png.decode("latin-1")) assert out.kind == "binary" assert "image/png" in out.text assert "\x89PNG" not in out.text assert len(out.text) < 400 def test_json_and_plain_text_still_pass_through_verbatim(): payload = '{"stars": 68000, "name": "cpython"}' out = body_to_text("application/json", payload.encode(), payload) assert out.kind == "text" assert out.text == payload def test_mislabelled_text_is_still_treated_as_text(): # application/octet-stream on a plain-text file is common; the bytes get the final say. payload = "name,value\nalpha,1\nbeta,2\n" out = body_to_text("application/octet-stream", payload.encode(), payload) assert out.kind == "text" assert out.text == payload # ------------------------------------------------------------------ wayback def p_wayback_reply(monkeypatch, status: int, text: str, url: str): async def p_req(target, **kw): return HttpReply(status=status, text=text, content=text.encode(), content_type="text/html", url=url) monkeypatch.setattr(WB, "browser_request", p_req) P_ARCHIVED = "