v3.10.0 — server-side PDF + auto --ctx-size + per-model handler architecture Minor release. Three coupled features for llamacpp / Surya OCR 2: 1. Per-model handler architecture — wrapper-side plugin point that lets one model declare custom request-level orchestration (handlers/__init__.py + base.py). Future GGUFs that don't opt in keep the default one-shot proxy behaviour. 2. Surya PDF handler (handlers/surya.py) — detects PDF input (data URL or http URL with application/pdf Content-Type), rasterizes each page server-side via poppler-utils, loops the chat completion per page, and stitches the per-page responses keyed by Surya's prompt mode (page → <div data-page="N">, layout/table → "page": N JSON field, block OCR rejected). Per-request dpi_rescale_to knob (default 96 cap, -1 for native, hard cap 600). Failure-isolated (page_errors array) + x_surya_pages / x_surya_mode response fields. 3. Auto --ctx-size resolver — model entries can pass "auto" instead of an integer to --ctx-size. The supervisor probes free VRAM/RAM at every spawn, computes available KV budget from per- token cost, caps at the model's trained max_ctx_size, floors at LLAMACPP_WRAP_CTX_FLOOR. Surya now picks 262144 (the full 256K trained context) on the live stack — verified live. Tests: 12 → 23 cases. 11 new test functions. Surya gets 5 new PDF cases per variant + 1 auto-ctx case per variant. New fixture tests/.fixtures/doc-multipage.pdf (3 pages). 6/6 CUDA cases verified green. Docs: docs/services/llamacpp.md grew "PDF input — server-side handling" and "Auto-sizing --ctx-size to available memory" sections. README + .env.example updated. See CHANGELOG.md for the full breakdown.