Tags

Tags give the ability to mark specific points in history as being important
  • v3.14.3

    v3.14.3 — sync tests/ to v3.14.2 provider audit
    
    Pure tests/ patch. No prod code, no API, no docs/, no compose, no
    litellm config.
    
    The v3.14.2 release removed sunset-flagged Groq / Cerebras /
    OpenRouter aliases and added new free-tier candidates, but the
    shell test suite (tests/test_*.sh) still referenced the dead
    aliases. This patch syncs them.
    
    tests/test_litellm.sh — EXPECTED_MODELS array:
      - removed: groq-llama-3.1-8b, groq-llama-3.3-70b,
                 groq-llama-4-scout, groq-kimi-k2, groq-qwen3-32b,
                 cerebras-qwen3-235b, cerebras-llama-3.1-8b,
                 or-minimax-m2.5.
      - added:   groq-qwen3.6-27b, groq-gpt-oss-safeguard-20b,
                 or-nemotron-ultra-550b, or-nemotron-nano-9b,
                 or-nemotron-nano-30b.
    
    Inline POST swaps in test_integration.sh, test_piston.sh,
    test_proxq.sh, test_security.sh, test_telethon.sh — all
    deprecated model names → their recommended replacements.
    
    shellcheck clean on all six. Patch bump.
  • v3.14.2

    v3.14.2 — pibox v0.11.2 + provider audit
    
    Two-commit release:
      - 66b7d3b: CHANGELOG entry + docker-compose.yml (pibox image tag
        v0.11.1→v0.11.2, LIBRECHAT_TITLE_MODEL default, PIBOX_ZAI_DEBUG
        env wire). Landed under a stale "v3.14.1" commit message; this
        tag annotation is the canonical record of what shipped.
      - HEAD:   provider yaml audits (Groq, Cerebras, OpenRouter),
        fallbacks.json purge, doc sync (providers.md, services/librechat.md,
        services/browser.md, README.md, .env.example, .gitignore).
    
    PIBOX v0.11.1 → v0.11.2 (tracks aicodebox v0.10.0):
      - Schema-mode retries on /openai/v1/chat/completions no longer
        replay the full original prompt. Base allocates ephemeral
        /tmp/aicodebox/<uuid>/ workspace (mode 0o700, cleaned in
        finally) and session-continues the retry conversation with
        minimal corrective prompt (error + directive + schema, ~1.5k
        tokens). 100k-token request needing 3 retries: 400k → ~105k
        input tokens.
      - PiAdapter contract unchanged. /run callers unchanged. Wire
        shape on /openai/v1/chat/completions unchanged.
    
    PROVIDER AUDIT — REMOVED (dead / sunset-flagged):
      Groq:    groq-llama-3.1-8b, groq-llama-3.3-70b, groq-llama-4-scout,
               groq-qwen3-32b, groq-kimi-k2
      Cerebras: cerebras-qwen3-235b, cerebras-llama-3.1-8b
      OpenRouter: or-minimax-m2.5
    
    PROVIDER AUDIT — RENAMED model fields:
      groq-compound:      groq/compound-beta → groq/compound
      groq-compound-mini: groq/compound-beta-mini → groq/compound-mini
    
    PROVIDER AUDIT — ADDED:
      groq-qwen3.6-27b, groq-gpt-oss-safeguard-20b,
      or-nemotron-ultra-550b, or-nemotron-nano-9b, or-nemotron-nano-30b
    
    CONFIG HYGIENE:
      fallbacks.json: 106 → 98 chains (purged refs to removed aliases).
      LIBRECHAT_TITLE_MODEL default: groq-llama-3.3-70b → groq-gpt-oss-120b.
    
    HEADS-UP: psyb0t/pibox:v0.11.2 + psyb0t/aicodebox:v0.10.0 may not
    be on Docker Hub at this tag's cut moment.
  • v3.14.1

    v3.14.1 — bump pibox v0.11.0 → v0.11.1
    
    Patch release. Tracks aicodebox v0.9.1. Single upstream bug fix
    for the schema-mode retry helper used by /pibox-zai/openai/v1/
    chat/completions:
    
      - Each retry now re-states the original task in the retry
        body (sectioned: Original task / previous invalid response
        / parse-validation error / required schema). Pre-fix the
        retry prompt only had bad-output + error + schema; for
        schemas that need task context (enum picks, allowed-values
        lists, domain identifiers) the retry agent had ~zero chance
        of correcting.
    
    PiAdapter contract unchanged. Wire shape unchanged. aigate-side:
    image-tag bump only. test_pibox.sh 7/7 green.
    
    Heads-up: psyb0t/pibox:v0.11.1 + psyb0t/aicodebox:v0.9.1 may
    not be on Docker Hub at this tag's cut moment.
  • v3.14.0

    v3.14.0 — new service flickies (video toolkit)
    
    Minor release. Adds the video sibling of audiolla (audio) and
    talkies (speech).
    
    flickies surface:
      - Lipsync: latentsync-1.5 (Apache-2.0, CUDA-only, default on
        CUDA) + wav2lip / wav2lip-gan (LRS2 non-commercial — gated on
        FLICKIES_ENABLE_NONCOMMERCIAL=1).
      - Face restore: gfpgan v1.4 (Apache-2.0, CUDA-only). Chains
        after Wav2Lip or stand-alone.
      - ffmpeg ops (CPU): trim, concat, transcode (incl. gif + fps +
        codec change), scale, mux_audio, extract_audio,
        thumbnail_grid.
      - Info: ffprobe metadata.
      - 11 MCP tools per variant. Aggregated /mcp/ exposes 22 tools
        (flickies-* + flickies_cuda-*).
      - Same JSON-body + output_path xor output_url contract as
        audiolla.
    
    Pinned at psyb0t/flickies:v0.2.0 (CPU) and
    psyb0t/flickies:v0.2.0-cuda.
    
    Wire-up mirrors audiolla: FLICKIES=1 / FLICKIES_CUDA=1 profile
    flags, /flickies/ + /flickies-cuda/ nginx routes, rate-limit zones,
    MCP fragments, env passthrough on litellm.
    
    Other ASCII-diagram fix: README routing diagram MCP-servers block
    now lists "piston (via mcp_tools)" pointing at the execute_code
    tool — piston doesn't run its own MCP, the wrapper lives inside
    mcp_tools, the diagram now reflects that.
    
    Verified: both containers healthy on v0.2.0; tests/test_flickies.sh
    8/8 pass; aggregated /mcp/ surfaces all 22 flickies tools.
    
    Heads-up: psyb0t/flickies:v0.2.0 + :v0.2.0-cuda may not be on
    Docker Hub at this tag's cut moment.
  • v3.13.0

    v3.13.0 — fix sd.cpp image-gen flakiness via resource_manager pre-warm
    
    Minor release. Eliminates the "/v1/images/generations returns HTTP
    200 with empty data" failure mode on local-sdcpp-{cuda,cpu}-*
    routes.
    
    Root cause: sd.cpp's TryLockModel 503s during model load (5-20 s)
    -> LiteLLM router num_retries=3 retries internally + walks
    fallback chain (4-5 entries per model) -> one external call
    generates 15-30 backend hits, all 503 -> LiteLLM image-gen
    fallback exhaustion returns HTTP 200 + empty data (upstream bug).
    
    Fix: resource_manager.py async_pre_call_hook now issues an
    explicit blocking POST /sdcpp/v1/load?model=<key> for cuda-img /
    cpu-img requests, immediately after the existing competing-group
    unload. By the time LiteLLM dispatches the actual image-gen call,
    sdcpp is fully warm and attempt 1 succeeds. Pre-load failures are
    logged rather than raised.
    
    Other model groups (chat / embed / talkies / vllm / llamacpp /
    predictalot) are UNCHANGED — the pre-warm step only fires for the
    sd.cpp groups.
    
    Verified: 5/5 sequential cold/warm/swap calls across sd-turbo /
    sdxl-turbo / sdxl-lightning return valid b64 PNG data. No new
    config knobs. No new env vars. No new endpoints.
    
    Doc sync: docs/resource-management.md + README.md both updated to
    describe the new pre-warm step.
    
    Known residual: 5+ concurrent calls against different models can
    still flake (LiteLLM router internal parallel retry bypasses the
    proxy hook). Beyond realistic ~1-2 req/min ad-hoc workload.
  • v3.12.6

    v3.12.6 — bump pibox v0.10.0 → v0.11.0
    
    Patch release. Tracks aicodebox v0.9.0. New OpenAI-standard
    response_format body field on /pibox-zai/openai/v1/chat/completions
    — stock OAI SDKs (LangChain, openai-python, LlamaIndex) can now
    drive schema enforcement without the proprietary
    x-aicodebox-json-schema header.
    
    Body field types:
      - text         → no schema (default)
      - json_object  → permissive {"type":"object"} constraint
      - json_schema  → response_format.json_schema.schema (OpenAI
                       structured-outputs shape)
    
    Body wins on conflict; header still supported as fallback.
    
    Breaking: response_format={"type":"json_object"} now returns 200
    with schema-validated JSON content (was 400). Callers using the
    400 as control-flow signal must update.
    
    aigate-side: image-tag bump only. PiAdapter zero code changes —
    v0.9.0 was route-only. test_pibox.sh 7/7 green.
    
    Heads-up: psyb0t/pibox:v0.11.0 + psyb0t/aicodebox:v0.9.0 may not
    be on Docker Hub yet at the moment this tag is cut.
  • v3.12.5

    v3.12.5 — bump pibox v0.9.0 → v0.10.0
    
    Patch release. Tracks aicodebox v0.8.3 base. Two aicodebox patches
    pulled in (v0.8.2 reconstruction-grade logging on schema-mode path;
    v0.8.3 single-source versioning fix). PiAdapter own logging brought
    from zero to spec. PiAdapter functional contract unchanged — no
    wire-level changes.
    
    aigate-side:
      - docker-compose.yml — pibox image tag bump.
      - tests/test_pibox.sh:test_pibox_zai_chat — swapped test model
        from glm-4.5-air to glm-4.7. z.ai's glm-4.5-air returns empty
        content ~80% on the echo prompt (smallest-model weakness, not
        a pibox bug; surfaced by v0.10.0's new parse_output text_len=0
        logging). glm-4.7 reliable.
    
    Live: pibox-zai healthy on v0.10.0; test suite 7/7 green in
    isolation. Heads-up: psyb0t/pibox:v0.10.0 + psyb0t/aicodebox:v0.8.3
    may not be on Docker Hub yet.
  • v3.12.4

    v3.12.4 — bump pibox v0.8.0 → v0.9.0
    
    Patch release. Tracks aicodebox v0.8.1 base. Three surface changes
    propagated through /pibox-zai/:
    
      - /pibox-zai/openai/v1/chat/completions x-aicodebox-json-schema
        header actually validates now (v0.7.0 plumbed it but never read
        result.parsed). Success -> canonical JSON content; exhaustion
        -> 422; agent crash -> 500; stream+schema -> 400.
      - Per-attempt breakdown on /pibox-zai/run (.attempts) and OAI
        envelope (.aicodebox_attempts). Top-level .usage summed across
        attempts so per-token billing reflects every retry.
      - Breaking: /pibox-zai/openai/v1/models entries now carry
        owned_by="aicodebox" instead of owned_by="pi" (aicodebox v0.8.x
        renamed the field). Filter callers must migrate.
    
    Base pinned via digest psyb0t/aicodebox:v0.8.1@sha256:3a234d49…
    upstream.
    
    aigate-side: image-tag bump + one test rewrite for the owned_by
    rename. test_pibox.sh 7/7 green; aigate-pibox-zai-1 healthy on
    v0.9.0.
  • v3.12.3

    v3.12.3 — bump audiolla v1.0.7 → v1.0.10
    
    Patch release. Bundles three upstream bug-fix patches (v1.0.8 /
    v1.0.9 / v1.0.10). No API removals; every change is additive,
    strict-superset, or a fix that was previously silently broken.
    
      - v1.0.8: UVR /v1/audio/restore/uvr-* and noise-reduce/uvr-denoise
        actually work now (3-layer config bug — audio-separator
        output_dir snapshotted at load_model time + wrong-namespace
        stem filter + near-silent dropper masking the symptom). Plus
        /v1/audio/remix TypeError fix (missing stems arg).
      - v1.0.9: /v1/audio/remix single-stem-solo (stem_mix gain-
        filtering down to one input) no longer fails with "requires
        at least 2 inputs".
      - v1.0.10: /v1/audio/visualize/video/volume ffmpeg arg style fix;
        /v1/audio/metadata write mode persists when output_path/url
        supplied (additive); /v1/catalog paths corrected
        (/v1/audio/batch -> /v1/batch, /v1/audio/diarize -> /v1/audio/
        diarize/{engine}).
    
    aigate-side: image-tag bump only. test_audiolla.sh stays as-is
    (suite does not exercise any of the changed endpoints); 14/14 green
    on v1.0.10. Both containers healthy.
    
    Heads-up: psyb0t/audiolla:v1.0.10 and :v1.0.10-cuda may not yet be
    published on Docker Hub at this tag's cut moment.
  • v3.12.2

    v3.12.2 — bump audiolla v1.0.6 → v1.0.7
    
    Patch release. Upstream UX + bug-fix tag — no API contract removed.
    
      - Field-name aliases on /v1/audio/{fade,eq,similar}.
      - /v1/audio/master mode optional (auto-detected from request).
      - POST /v1/presets/{name} + POST /v1/pipeline migrated from
        Form/File to JSON body. New PresetRunRequest / PipelineRunRequest
        schemas; pipeline steps now typed list[{op, params?}].
      - Global JSON 500 envelope (uncaught exceptions now return JSON
        instead of plain text).
      - /v1/audio/remix accepts linear-gain shorthand.
      - UVR phantom-output diagnostic improved.
    
    aigate-side: image-tag bump only. test_audiolla.sh 14/14 green
    (suite does not exercise any of the changed endpoints).
  • v3.12.1

    v3.12.1 — bump audiolla v1.0.5 → v1.0.6 (upstream bug fixes)
    
    Patch release. Two upstream bug fixes:
    
      - /v1/audio/info now surfaces real ffprobe stderr (was masked by
        -v quiet).
      - /v1/audio/trim end_sec optional; omitting trims to source end.
    
    No aigate-side code, config, or behavior changes beyond the image
    tag. Both containers healthy on v1.0.6; test_audiolla.sh 14/14
    green.
  • v3.12.0

    v3.12.0 — predictalot v0.2.1 → v1.0.1 + merged talkies voices endpoint
    
    Minor release. Two unrelated streams bundled.
    
    PREDICTALOT v0.2.1 → v1.0.1
      - BREAKING (direct REST callers only): FM forecast / ensemble /
        models endpoints move from /v1/<type>/… to /v1/timeseries/<type>/….
        No upstream redirect compat layer. MCP tool names unchanged so MCP
        callers are unaffected.
      - New sibling family /v1/tabular/* — 9 supervised backends (lightgbm,
        xgboost, hist-gbt, random-forest, logistic, mlp, svm-rbf, knn,
        naive-bayes) × 3 modes (direction, value, quantile) + 3 meta-
        learners (calibrated, stacking, diversified). REST-only in v1.0.x
        (not MCP-wrapped upstream).
      - FM per-call escape hatches: ForecastConfig.extra + ensemble
        memberOverrides.
      - v1.0.1 itself is a docs-only patch over v1.0.0 (no source changes,
        no behavior change — upstream restructured the README into
        docs/{timeseries,tabular,mcp,configuration,architecture,accuracy,
        errors}.md). Our doc links repointed at the new tree.
    
    MERGED /v1/audio/voices ENDPOINT
      - mcp aggregates talkies CPU + CUDA voice catalogs (130 voices with
        both enabled) and annotates each voice with the LiteLLM model
        alias(es) so callers go straight from voice pick to /v1/audio/
        speech without a second lookup. Tolerates either upstream being
        unconfigured or unreachable.
      - Nginx gains a `location = /v1/audio/voices` block proxying to
        mcp:8000 before the LiteLLM catch-all (LiteLLM doesn't route this
        non-OpenAI-standard endpoint).
      - proxq pathFilter narrowed from `^/v1/audio` to the three explicit
        inference paths so the listing endpoint isn't accidentally queued
        under /q/.
    
    Live-verified: 16/16 predictalot tests green; old /v1/<type>/ paths
    404, new /v1/timeseries/<type>/ paths 200; tabular surface reachable
    at /v1/tabular/backends; merged voices endpoint returns 130 voices.
    
    Full per-file breakdown in CHANGELOG.md.
  • v3.11.2

    v3.11.2 -- README routing-diagram catch-up to v3.11.1
    
    Patch release. Docs-only. Three more gaps in the ASCII routing
    diagram noticed after v3.11.1:
    
      - /piston/ added to the nginx routes block.
      - execute_code added to mcp_tools in the MCP servers block
        (it was introduced in v3.11.0 but the diagram still only
        showed the original three tools).
      - llama.cpp CPU + CUDA added to the LiteLLM providers block
        (LLAMACPP=1 / LLAMACPP_CUDA=1 serve GGUF + vision-VLM
        weights incl. Surya OCR 2 but were never listed in the
        providers diagram).
    
    No code, config, or behavior changes.
  • v3.11.1

    v3.11.1 — README catch-up for v3.11.0 piston ship
    
    Patch release. Docs-only. Three stale spots in README missed during
    the v3.11.0 ship:
    
      - Tools and capabilities bullet list now includes piston
        (Sandboxed code execution — nsjail isolation, Python+Node
        default, PISTON_LANGUAGES extensible, REST + MCP).
      - Services table piston row: dead piston-pull sidecar reference
        removed; default langs corrected to Python+Node; pre-bake-at-
        build-time + aigate-internal-only network model documented;
        Authorization-header-strip detail added.
      - Security section: "All containers no-new-privileges" qualified
        for the two genuine carve-outs (piston privileged for nsjail,
        tailscale NET_ADMIN for tun) — matching the already-correct
        Network-isolation section lower in the README.
    
    No code, config, or behavior changes.
  • v3.11.0

    v3.11.0 — new service piston + whole-package security pass
    
    Minor release. Adds engineer-man/piston as a new aigate service
    (sandboxed multi-language code execution; nsjail-based per-execution
    isolation; pre-bake architecture for runtime no-outbound), plus the
    fallout from a full brutal-review pass across every line of code,
    every doc, every config.
    
    PISTON
      - 50+ languages available; default pre-bake is python + node only.
      - Pre-baked at image build time -> runtime container lives on
        aigate-internal ONLY (no outbound).
      - privileged:true is what piston needs to set up nsjail; the
        sandbox is the nsjail subprocess (own user ns, chroot, seccomp,
        cgroups). For aigate's threat model (trusted operator +
        bearer-auth-gated endpoint + sandboxed code from LLM agents)
        this is acceptable.
      - /piston/ nginx gate with `Bearer ${AIGATE_TOKEN}`; client
        Authorization header stripped before proxy hop.
      - MCP tool `mcp_tools-execute_code` exposed via the existing /mcp/
        aggregator.
    
    SECURITY HARDENING
      - SSRF guard on llamacpp image_url fetches (both default path +
        Surya PDF path). Blocks RFC1918 / loopback / link-local /
        multicast / reserved hosts. Live-verified.
      - no-new-privileges:true added to claudebox, pibox-zai, ollama,
        ollama-cuda. README claim qualified for the two genuine
        carve-outs (piston needs privileged for nsjail; tailscale needs
        NET_ADMIN).
      - resource_manager: try/except BaseException wrapping the unload
        phase releases the semaphore on cancel; talkies CPU+CUDA unload
        lists synced to provider YAML (CPU 4->6, CUDA 8->14) so previously
        un-evicted models actually free memory under contention.
    
    BUG FIXES
      - litellm/config/fallbacks.json: 20+ dead local-speaches-* / 4 dead
        local-qwen3-cuda-tts entries rewritten to live talkies slugs.
      - mcp/server.py: search_web num_results capped at 100;
        execute_code description no longer lies about installed
        runtimes.
    
    DOCS
      - README Piper/Speaches drift cleaned (5 places).
      - new docs/services/piston.md.
      - 7 broken relative links in docs/services/* repaired.
      - docs/services-reference.md + docs/usage.md deleted (stale
        redirect stubs from v3.10.0).
      - docs/services/resource-management.md moved out of services/
        (it's cross-cutting LiteLLM callback logic, not a service).
    
    TESTS
      - tests/test_piston.sh: 8 cases including
        test_piston_e2e_groq_drives_execute_code which exercises the
        full agentic loop (Groq llama-3.3-70b -> tool_call -> MCP ->
        piston nsjail -> SHA-256 verified byte-for-byte). All green.
    
    Full per-file breakdown in CHANGELOG.md.
  • v3.10.0

    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.
  • v3.9.2

    v3.9.2 — docs reorg: per-service pages under docs/services/
    
    Patch release. Pure documentation restructure — no production code
    changes.
    
    The two monolithic doc files were growing unmanageable:
      docs/services-reference.md  ~960 lines / 18 service sections
      docs/usage.md               ~780 lines / 15 task-keyed sections
    
    Both have been split. Every service now has ONE file under
    docs/services/<name>.md containing both the deep reference (endpoints,
    models, config, internals) and the curl recipes / usage examples.
    
    18 new per-service files + 2 new index pages (docs/README.md +
    docs/services/README.md). Old files now redirect to the new structure.
    README + docs/providers.md links migrated to the new paths.
    
    See CHANGELOG.md for the full mapping of old section → new file.
  • v3.9.1

    v3.9.1 — Surya OCR 2 follow-up: layout + table-rec tests + DPI fix + usage docs
    
    Patch release. No production code changes — the llamacpp/ wrapper,
    model registries, compose services, LiteLLM provider configs, and
    resource_manager wiring are byte-identical to v3.9.0.
    
    Tests: 8 → 12 cases. New `layout` + `table_rec` test functions per
    variant now exercise the two Surya prompt modes v3.9.0 shipped support
    for but did not test. _llamacpp_ocr_call grew a task=block|page|
    layout|table_rec dispatcher that selects the right verbatim Surya
    training-time prompt per task.
    
    New fixture: tests/.fixtures/table.pdf (A4, 3×3 bordered table).
    
    PDF rasterization DPI dropped from 200 to 96 — Surya's training-time
    default. ~4× CPU encode speedup with no accuracy loss on the synthetic
    fixtures (200 DPI inflates prompt-token count quadratically).
    
    Docs: full Surya usage section across README + docs/services-
    reference.md + docs/usage.md + docs/providers.md. Documents all 4
    trained-in prompts verbatim, per-hardware throughput tables, the
    wrapper's http:// → data: URL rewrite, DPI sweet spot, and "which
    slug should I pick" workload picker.
    
    See CHANGELOG.md for the full breakdown.
  • v3.9.0

    v3.9.0 — new service llamacpp / llamacpp-cuda (Surya OCR 2)
    
    Minor release. Adds a second on-prem VLM serving lane to aigate — a
    supervised `llama-server` wrapper that mirrors the vllm-wrap lifecycle
    surface (/v1/chat/completions, /api/ps, DELETE /api/ps/{model_id},
    POST /unload) but serves GGUF weights and supports vision models via
    mmproj. Why this exists: vllm-CPU's vision-VLM support is weak, and
    even on GPU the upstream-blessed inference target for Surya is GGUF.
    llama.cpp does Qwen3-VL-class document models cleanly on both CPU
    and GPU.
    
    First model shipped: Surya OCR 2 (datalab-to/surya-ocr-2-gguf), a
    ~650M-param document VLM that does OCR / layout / table-recognition
    through one model — behaviour switches on the prompt (training-time
    contracts, see CHANGELOG for the exact strings).
    
    Pieces:
      - llamacpp + llamacpp-cuda wrapper services (~750 LOC Python,
        mirrors vllm-wrap 1-for-1). Base images pinned by sha256 digest.
      - llamacpp-pull sidecar — reads both models.{cpu,cuda}.json,
        huggingface-cli download --local-dir, exits 0. Wrapper depends_on
        completion, runs HF_HUB_OFFLINE=1.
      - HTTP-URL → data-URL rewriting in the proxy so OpenAI's
        `image_url.url: https://...` works transparently (llama-server's
        mtmd doesn't fetch URLs natively).
      - LiteLLM provider entries + new resource_manager groups
        (cpu-llamacpp / cuda-llamacpp) so sibling eviction now covers
        llamacpp under contention with ollama / sdcpp / talkies / vllm.
      - tests/test_llamacpp.sh — 8 cases (4 per variant) verifying
        models-list + captcha OCR (data: URL) + PDF OCR (full page) +
        captcha OCR via hybrids3 presigned URL. All 8 pass end-to-end
        through LiteLLM → wrapper → llama-server → GGUF VLM.
    
    Two new fixtures committed:
      tests/.fixtures/captcha.png  (18 KB, contains "AIGATE2026")
      tests/.fixtures/doc.pdf      (1 KB, two lines of known prose)
    
    See CHANGELOG.md for the full file-by-file breakdown.
  • v3.8.1

    v3.8.1 — docs-only sync for v3.8.0
    
    README + docs/*.md + .env.example catch up to the talkies v0.9.0
    model set (6 CPU models / 14 CUDA models). No behaviour change, no
    image-pin change, no LiteLLM config change — the actual upgrade
    shipped in v3.8.0.
    
    Updated files:
      - README.md (services overview table — talkies CPU + CUDA rows)
      - docs/providers.md (talkies CPU + CUDA model tables)
      - docs/services-reference.md (talkies model bullet list + Qwen3-TTS
        family sub-section documenting mode-implicit voice / instructions
        semantics, PCM streaming, sampling controls)
      - docs/usage.md (transcription + speech examples + model bullets)
      - docs/testing.md (model-count assertion line)
      - .env.example (TALKIES / TALKIES_CUDA doc comments +
        TALKIES_QWEN3_STREAM_CHUNK_SIZE knob)
    
    See CHANGELOG.md for the full per-file breakdown.