Python 88.3%
TypeScript 7.6%
Shell 4.1%
1"""Vision / documents / citations smoke tests on Haiku 4.5: 1x1 PNG, invalid image bytes, text document with2citations (char_location), search_result citation, generated 1-page PDF (page_location), count_tokens for an image.3≈$0.004 per run.4"""5from __future__ import annotations67import base648import struct9import zlib1011import pytest121314def tiny_png_b64() -> str:15 def chunk(t: bytes, d: bytes) -> bytes:16 return struct.pack(">I", len(d)) + t + d + struct.pack(">I", zlib.crc32(t + d) & 0xFFFFFFFF)17 png = (b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", 1, 1, 8, 2, 0, 0, 0))18 + chunk(b"IDAT", zlib.compress(b"\x00\xff\x00\x00")) + chunk(b"IEND", b""))19 return base64.b64encode(png).decode()202122def tiny_pdf_b64(text: str) -> str:23 stream = f"BT /F1 18 Tf 40 750 Td ({text}) Tj ET".encode()24 objs = [b"<< /Type /Catalog /Pages 2 0 R >>", b"<< /Type /Pages /Kids [3 0 R] /Count 1 >>",25 b"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >>",26 b"<< /Length %d >>\nstream\n" % len(stream) + stream + b"\nendstream", b"<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>"]27 out, offs = b"%PDF-1.4\n", []28 for i, o in enumerate(objs, 1):29 offs.append(len(out)); out += f"{i} 0 obj\n".encode() + o + b"\nendobj\n"30 xref = len(out)31 out += f"xref\n0 {len(objs)+1}\n0000000000 65535 f \n".encode() + b"".join(f"{o:010d} 00000 n \n".encode() for o in offs)32 out += f"trailer\n<< /Size {len(objs)+1} /Root 1 0 R >>\nstartxref\n{xref}\n%%EOF\n".encode()33 return base64.b64encode(out).decode()343536Q = {"type": "text", "text": "What color is grass? Answer in one sentence and cite."}373839def _msg(model: str, content: list, max_tokens: int = 60) -> dict:40 return {"model": model, "max_tokens": max_tokens, "messages": [{"role": "user", "content": content}]}414243def _first_citation(body: dict) -> dict:44 for b in body["content"]:45 if b["type"] == "text" and b.get("citations"):46 return b["citations"][0]47 raise AssertionError(f"no citation in {body['content']}")484950def test_base64_image_and_token_count(anthropic, models):51 img = {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": tiny_png_b64()}}52 st, body, _ = anthropic("POST", "/v1/messages", _msg(models["anthropic"], [img, {"type": "text", "text": "What color is this pixel? One word."}], 10),53 est_cost_usd=0.00005, note="test_vision 1x1 png")54 assert st == 200 and "red" in body["content"][0]["text"].lower()55 st, cnt, _ = anthropic("POST", "/v1/messages/count_tokens", {"model": models["anthropic"], "messages": [{"role": "user", "content": [img, {"type": "text", "text": "Describe."}]}]},56 note="test_vision count_tokens image")57 assert st == 200 and 5 < cnt["input_tokens"] < 100585960def test_invalid_image_bytes_400(anthropic, models):61 bad = {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": base64.b64encode(b"notapng").decode()}}62 st, body, _ = anthropic("POST", "/v1/messages", _msg(models["anthropic"], [bad, {"type": "text", "text": "Describe."}], 10), note="test_vision invalid image")63 assert st == 400 and "image" in body["error"]["message"].lower()646566def test_text_document_char_location_citation(anthropic, models):67 doc = {"type": "document", "source": {"type": "text", "media_type": "text/plain", "data": "The sky is blue. Grass is green."}, "title": "Colors", "citations": {"enabled": True}}68 st, body, _ = anthropic("POST", "/v1/messages", _msg(models["anthropic"], [doc, Q]), est_cost_usd=0.0007, note="test_vision citations text")69 assert st == 200, body70 c = _first_citation(body)71 assert c["type"] == "char_location" and "green" in c["cited_text"].lower() and c["end_char_index"] > c["start_char_index"]727374def test_search_result_citation(anthropic, models):75 sr = {"type": "search_result", "source": "kb://colors/1", "title": "Color facts",76 "content": [{"type": "text", "text": "The sky is blue."}, {"type": "text", "text": "Grass is green."}], "citations": {"enabled": True}}77 st, body, _ = anthropic("POST", "/v1/messages", _msg(models["anthropic"], [sr, Q]), est_cost_usd=0.0007, note="test_vision citations search_result")78 assert st == 200, body79 c = _first_citation(body)80 assert c["type"] == "search_result_location" and c["source"] == "kb://colors/1" and c["search_result_index"] == 0818283def test_pdf_page_location_citation(anthropic, models):84 pdf = {"type": "document", "source": {"type": "base64", "media_type": "application/pdf", "data": tiny_pdf_b64("The sky is blue. Grass is green.")},85 "title": "Colors PDF", "citations": {"enabled": True}}86 st, body, _ = anthropic("POST", "/v1/messages", _msg(models["anthropic"], [pdf, Q]), est_cost_usd=0.0025, note="test_vision citations pdf")87 assert st == 200, body88 c = _first_citation(body)89 assert c["type"] == "page_location" and c["start_page_number"] == 1 and c["end_page_number"] == 2909192def test_mixed_citation_settings_400(anthropic, models):93 on = {"type": "document", "source": {"type": "text", "media_type": "text/plain", "data": "A."}, "citations": {"enabled": True}}94 off = {"type": "document", "source": {"type": "text", "media_type": "text/plain", "data": "B."}, "citations": {"enabled": False}}95 st, body, _ = anthropic("POST", "/v1/messages", _msg(models["anthropic"], [on, off, Q], 10), note="test_vision mixed citations")96 assert st == 400 and "itations" in body["error"]["message"]97