feat(media): forward video input_type + Solana image quality (1.7.0)#24
Merged
Merged
Conversation
added 4 commits
July 15, 2026 16:37
Both params are accepted by the gateway today but had no way through the SDK, so callers could not reach them — and blockrun-litellm#18 tried to forward them anyway, producing a TypeError against every published release. input_type (VideoClient.generate + SolanaLLMClient.video, sync and async): declares the intended seed mode. The gateway infers the mode from the seed fields and 400s — before charging — when the declared value disagrees. That converts an expensive silent failure into an error: a dropped image_url otherwise yields a text-to-video clip the caller still pays for. quality (SolanaLLMClient.image/image_edit, sync and async): low/medium/high/ auto latency-vs-fidelity for openai/gpt-image-*. Solana only, deliberately. The Base gateway defines no such field and zod strips unknown keys, so a quality sent to Base would be silently dropped — ImageClient already rejects it on purpose (test_image_parameter_validation) and keeps doing so. Validation lives in validation.py alongside the other validate_* helpers and covers spelling only. Whether a declared mode matches the seed fields, and which models accept quality, stay the gateway's call — it already answers both before billing, so a second copy here would only drift. The enums are verified equal to the gateway zod enums on both chains. Reference-to-video (reference_videos/reference_audios) is deliberately NOT added: both gateways gate it behind R2V_ENABLED, which is unset on blockrun-sol and "false" on blockrun-web, so every call returns 503 until that flips.
From review of #24: - Replace test_async_video_exposes_input_type, which only checked the signature and would have passed if the param were accepted then never forwarded — the one regression worth catching. The async paths now assert the forwarded JSON body, matching the sync coverage, and cover async image quality (previously untested on all four methods). - Call validate_image_quality unconditionally, as validate_video_input_type already is; the validator no-ops on None, so the guard was redundant. - Make _build_video_body's input_type required like its siblings. Every param being explicit is exactly how the builder prevents the drift it exists for. - Point the Base ImageClient TypeError at the Solana client when quality is the offending kwarg, so the error names where the param does exist. - Document input_type and Solana quality in the README. input_type earns the worked example: its value is the 400 you get instead of a text-to-video clip you paid for. - Backfill CHANGELOG 1.5.0/1.5.1/1.6.0/1.6.1 (dates from PyPI) and add 1.7.0. The file claimed "all notable changes" but stopped at 1.4.7.
VickyXAI
pushed a commit
to BlockRunAI/blockrun-litellm
that referenced
this pull request
Jul 15, 2026
BlockRunAI/blockrun-llm#24 shipped the two params this branch originally tried to forward, so they can now go back — pointing at a real SDK surface rather than a gap. input_type (/v1/videos/generations, both chains): declared seed mode, cross checked by the gateway against the seed fields and rejected 400-unbilled on disagreement. quality (/v1/images/{generations,edits}): Solana only. The Base gateway has no quality field and strips unknown keys, so routing it there would silently drop it and the caller would never learn their latency knob did nothing. The adapter refuses on the Base branch and _media_endpoint turns that into a 400 naming the constraint — verified end-to-end through the real proxy, not a 500. Floors go to blockrun-llm>=1.7.0, base and [solana]. The base floor moves this time, unlike the Solana-only re-signing bump reverted earlier in this branch: input_type is genuinely a Base concern, and VideoClient.generate has a closed signature, so an older core raises TypeError the first time anyone sends it. reference_videos/reference_audios stay out. Both gateways gate them behind R2V_ENABLED — unset on blockrun-sol, "false" on blockrun-web — so every call 503s until that flips. The contract test now also pins the Base-rejects-quality asymmetry, so a future SDK adding quality to ImageClient fails here loudly instead of leaving the adapter's Base guard silently stale. Verified against the real SDK 1.7.0 with only HTTP stubbed: input_type reaches the video body, quality reaches /v1/images/generations and image2image.
VickyXAI
pushed a commit
to BlockRunAI/blockrun-litellm
that referenced
this pull request
Jul 16, 2026
…m 1.7.0 (0.7.0) (#18) Adds OpenAI-compatible image editing plus the two media params that are real as of blockrun-llm 1.7.0 (BlockRunAI/blockrun-llm#24). - Image editing: POST /v1/images/edits (alias /v1/images/image2image) — JSON data URIs or multipart image/image[], multi-image fusion, mask. Adds python-multipart to the proxy extra. - input_type on /v1/videos/generations, both chains: declares the seed mode; the gateway rejects 400-unbilled when it disagrees with the seed fields, so a dropped image_url becomes an error rather than a text-to-video clip you paid for. - quality on the image endpoints — Solana only. Base has no quality field and strips unknown keys, so the adapter 400s rather than let it be silently dropped (the SDK would otherwise raise TypeError → 500). - Floors → blockrun-llm>=1.7.0, base and [solana]. The base floor moves because input_type is a genuine Base concern (VideoClient.generate has a closed signature). Dropped from the original revision: reference_videos/reference_audios. Both gateways gate them behind R2V_ENABLED (unset on blockrun-sol, "false" on blockrun-web), so every call would 503. Review fixes: the contract test was vacuous for the Base image surface (_accepted() returns None for **kwargs, so the assertions never ran) — Base params are now probed by calling with the transport stubbed, mutation-verified. Also fixed a real billing bug where a prompt sent as a multipart file part was billed as a Python repr, added JSON image/mask type guards, and capped multipart uploads (12MB → 413, 16 parts → 400). 228 passed, 1 skipped. Verified end-to-end against the real SDK 1.7.0 with only HTTP stubbed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the two media params the gateway already accepts but the SDK had no way to send. Companion to BlockRunAI/blockrun-litellm#18, which tried to forward them through a gap that did not exist in any release.
Why
blockrun-litellm#18 forwarded four params —
quality,reference_videos,reference_audios,input_type— that are in no blockrun-llm release, including 1.6.1. The SDK clients have closed signatures, andImageClient.generate/editexplicitly raise on unknown kwargs, so each was a runtimeTypeErroron the first real call. Its test suite fakes the clients with**kwargs, which swallowed every invented param — 96 green tests over a surface that could not work.Checking each against the gateway rather than assuming split them three ways:
input_typequalityopenai/gpt-image-*)reference_videos/reference_audiosR2V_ENABLED="false"→ 503R2V_ENABLEDunset → 503What's in it
input_typeonVideoClient.generateandSolanaLLMClient.video(sync + async). Declares the intended seed mode; the gateway infers the mode from the seed fields and 400s — before charging — on disagreement. That turns an expensive silent failure into a loud one: a droppedimage_urlotherwise yields a text-to-video clip you still pay for.qualityonSolanaLLMClient.image/image_edit(sync + async) —low/medium/high/auto,openai/gpt-image-*. Solana only, deliberately: the Base gateway defines no such field and zod strips unknown keys, so aqualitysent to Base would be silently dropped.ImageClientalready rejects it on purpose (test_image_parameter_validation.test_generate_rejects_quality_parameter) and continues to.Not added: reference-to-video. Both gateways gate
reference_videos/reference_audiosbehindR2V_ENABLED(unset onblockrun-solin both regions,"false"onblockrun-web), returning "reference-to-video is being finalized and will be enabled shortly." Adding it now ships a guaranteed 503 — the same mistake one layer down. It slots in cleanly once the flag flips.Design notes
Validation sits in
validation.pybeside the othervalidate_*helpers (as #23 did) and checks spelling only. Whether a declared mode matches the seed fields, and which models takequality, stay the gateway's call — it already answers both before billing, so a second copy here would only drift.input_typeflows through the existing shared_build_video_body, so sync and async cannot diverge.Verification
input_typebody line fails the new tests, so they aren't vacuous.input_type(text, image, first_last_frame, reference),quality(low, medium, high, auto).