litellm/tests
Rick 71e508b65d
feat(minimax): add MiniMax-H3 and H3-Max video generation via /v1/videos (#43705)
* feat(minimax): add MiniMax-H3 and H3-Max video generation via /v1/videos

MinimaxVideoConfig maps litellm's OpenAI Videos API onto MiniMax's V2 task
API. Create, status, list, content and delete hit /v2/video_generation and
/v2/query/video_generation. Remix is not exposed: MiniMax's
/v2/video_regeneration only upscales a finished 768P task to 2K and ignores any
prompt, so it raises instead of returning a video that silently drops the edit

OpenAI params translate to MiniMax's contract: seconds becomes duration, size
reduces via gcd to a valid ratio, and text-to-video requests default to ratio
16:9, resolution 768P and duration 5 when unset. input_reference becomes a
first_frame content item, base64 encoded into a data URI for file inputs, and
multimodal reference media passes through a content array in extra_body. Caller
content is validated strictly as image, video or audio items, and the scanned
prompt is always the one text item sent, so text can't reach MiniMax past the
guardrails; anything else in content returns a 400. api_base
shares MINIMAX_API_BASE with the chat config (a trailing /v1 or /v2 is stripped
because the video API carries its own version). The list endpoint pages by
number with no cursor or sort, so after and an ascending order are rejected
with a 400 rather than ignored, and page_num passes through extra_query. Responses
validate into frozen pydantic models at the boundary, video ids are
provider-encoded so status and content route back to MiniMax, and create
reports duration_seconds and video_resolution in usage for cost tracking

End-to-end tests drive the real avideo_generation() entrypoint through an httpx
MockTransport and assert on the encoded request body, which is what catches a
mapper that drops input_reference before the request is built

Both model_prices maps gain minimax/MiniMax-H3 and minimax/MiniMax-H3-Max,
priced per output second by resolution tier from MiniMax's pay-as-you-go list
(H3 $0.08 at 768P and $0.13 at 2K, H3-Max $0.05 at 480P and $0.08 at 768P).
MiniMax also bills input images beyond a per-model free allowance (5 for H3, 2
for H3-Max), so each entry carries input_cost_per_image and
provider_specific_entry.minimax_free_input_images, and the create response
reports the full charge as provider_reported_cost_usd. Reference video input is
rejected with a 400, because MiniMax bills its duration only after the create
call that litellm bills

Co-authored-by: AaronHowell <237895480@qq.com>

* fix(minimax): fail closed on invalid video params and malformed task responses

Addresses review on #43705:

- A create, status or delete response without a task id (or a task) is a
  502 instead of a queued object with an empty id
- An unmapped task status is a 502 instead of defaulting to queued
- seconds/duration must be a positive whole number and size a positive
  WIDTHxHEIGHT or W:H, otherwise 400; a 0x0 size no longer divides by zero
  and an unparseable duration no longer falls back to the billed default
- characters and image are rejected with UnsupportedParamsError unless
  drop_params is set, instead of being dropped silently
- Downloading a task that is not ready or failed is a 400 that keeps its
  message through the handler, instead of a ValueError surfaced as a
  retried 500
- The video download goes through safe_get / async_safe_get

Co-authored-by: AaronHowell <237895480@qq.com>

* test(minimax): cover the video download path and invalid-param branches

The download now goes through safe_get, so the happy path and the
finished-task-without-a-url branch are asserted, alongside the non-object
parameters rejection and the remix response stub.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>

* fix(minimax): return 400 for video remix and clear new lint gate counts

* fix(minimax): send file-tuple images and keep input_reference next to content media

* fix(minimax): answer 404 when an H3 video is downloaded before it finishes

A download that lands while the task is still queued or running answered 400. That is a
client error, which was the intent, but 404 is what the OpenAI videos API documents for
content that is not ready, and it is the status the sibling DashScope and Volcengine
video paths now answer, so a client polling all three reads one shape

A failed task keeps its 400, since that is not a timing mistake the caller can retry
away. The download test drives avideo_content and asserts the caller sees NotFoundError
rather than an internal server error

* fix(minimax): answer 400 for unsupported video params, early downloads and unknown ids

A create param MiniMax cannot honor (seed, n, quality and the like) was dropped
without a word. It now answers 400 unless drop_params is on, like other providers

A download before the video is ready and a status call for an unknown task id
now answer 400. The router cools a deployment down on a 404 and retries a 5xx,
and neither is a deployment fault. DashScope on main answers 400 for the same case

Input images past the free allowance are now billed through the shared video cost
path, so a deployment with custom pricing bills them too. Status usage no longer
carries MiniMax's token counts, list sets has_more to false since MiniMax pages by
number, and the price map stops listing video as an input modality

* fix(minimax): keep the polled video id, honor deployment drop settings, and match chat's key order

Status re-encodes the id with the polled id's model when MiniMax omits it, drop_params and
additional_drop_params never reach MiniMax and listed keys are dropped, MINIMAX_API_KEY wins over
litellm.api_key, create sets created_at, and a content variant other than the video answers 400

* fix(minimax): list a task without a model under the routed group

MiniMax leaves `model` off some listed tasks. The caller polls the ids a list hands back, and the
proxy resolves a poll by the model in the id, so an id encoded with an empty model no longer routes
back to the deployment that served the task. Fall back to the group the router was asked for.

* fix(minimax): honor deployment drop keys inside parameters and bill images at the map rate when a deployment prices only seconds

A field the deployment lists in additional_drop_params no longer reaches MiniMax when it arrives inside parameters, and a deployment that sets only its per-second price now bills reference images past the free allowance at the cost map's per-image rate instead of $0

* fix(minimax): keep deployment-dropped fields out of the body when they arrive through extra_body

* fix(minimax): answer 400 for a video resolution with no price unless drop_params is on

* fix(minimax): send the default resolution when a deployment drops resolution

---------

Co-authored-by: AaronHowell <237895480@qq.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Happy <yesreply@happy.engineering>
Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-10-15 05:48:36 -07:00
..
_support fix(params): validate stream_chunk_size once, before any provider call (#43222) 2026-09-26 23:01:20 +00:00
base_sdk_tests test: move packaging and install checks off CircleCI build_and_test (#45757) 2026-10-10 09:33:51 -07:00
benchmarks refactor: expose core private helpers under public names (#44871) 2026-10-07 00:05:27 +00:00
code_coverage_tests feat(ui): filter active and paused model deployments (#43710) 2026-10-14 23:19:59 -07:00
documentation_tests fix(proxy): let configured pass-through endpoints outrank built-in provider prefix routes (#44133) 2026-10-10 12:26:17 -07:00
e2e test(ci): pin xai reported-cost split and coordinator-held Prisma lock timeout (#46645) 2026-10-15 04:08:56 -07:00
e2e_harness test(e2e): rename load to perf and consolidate the opt-in into E2E_PERF_TESTS (#46077) 2026-10-12 13:54:03 -07:00
fixtures test: migrate tests/llm_translation into unit, integration and e2e tiers (#45759) 2026-10-11 07:58:53 +00:00
harness_e2e feat: add litellm.agent() to run claude code, codex, opencode and deep agents through the ai gateway (#43885) 2026-10-01 22:27:49 +00:00
integration fix: preserve explicit provider for async image, audio, and realtime routes (#36346) 2026-10-15 05:21:43 -07:00
rust-python-harness docs(agents): ban semicolons and colons in human-facing text (#45684) 2026-10-09 16:36:32 -07:00
test_litellm_rust refactor(rust-bridge): return an unstarted Execution from native entrypoints and drive it in Python (#46299) 2026-10-14 17:50:44 -07:00
typing fix: support OpenAI SDK 3 while retaining SDK 2 compatibility (#44927) 2026-10-09 19:45:50 -07:00
unit feat(minimax): add MiniMax-H3 and H3-Max video generation via /v1/videos (#43705) 2026-10-15 05:48:36 -07:00
windows_tests test: move packaging and install checks off CircleCI build_and_test (#45757) 2026-10-10 09:33:51 -07:00
__init__.py refactor: expose core private helpers under public names (#44871) 2026-10-07 00:05:27 +00:00
_fake_openai_endpoint_server.py
_flush_vcr_cache.py
_live_test_helpers.py
_master_key.py fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
_openai_record_replay_proxy.py
_process_helpers.py test: count a zombie grandchild as gone in the migrate deploy timeout test (#42570) 2026-09-22 14:59:26 -07:00
_vcr_conftest_common.py test: migrate tests/llm_translation into unit, integration and e2e tiers (#45759) 2026-10-11 07:58:53 +00:00
_vcr_redis_persister.py
_wait_helpers.py
_ws_vcr.py
AGENTS.md docs(agents): ban semicolons and colons in human-facing text (#45684) 2026-10-09 16:36:32 -07:00
capturing_transport.py test(vcr): guard leaked cassette patches and make injected-transport embedding tests immune (#42542) 2026-09-22 14:20:18 -07:00
eval_swe_bench.py
fake_openai_endpoint.py
gettysburg.wav
large_text.py
openai_batch_completions.jsonl
pyrightconfig.json
README.MD test: finish the non-proxy half of tests/test_litellm (#43281) 2026-09-25 22:43:41 -07:00
test_logging.conf
test_rust_python_harness.py test: move 76 live top-level tests to offline unit and integration coverage (#45352) 2026-10-08 10:33:35 -07:00
VCR_TESTING.md test: migrate tests/llm_translation into unit, integration and e2e tiers (#45759) 2026-10-11 07:58:53 +00:00
white_100x100.png test: stop CI tests from downloading tokenizer files and images (#43257) 2026-09-25 19:27:48 -07:00

In total litellm runs 1000+ tests

[02/20/2025] Update:

To make it easier to contribute and map what behavior is tested,

we've started mapping the litellm directory in tests/unit

This folder can only run mock tests.