Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/roadmap_v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ issue is not yet placed. Keyed record: update in place, never append.
| [#652](https://github.com/mudler/vllm.cpp/issues/652) | — | `model-matrix.md` prose counters drifted: LTX-2.5 reached the rows and the CI-enforced rollup but none of the five sentences that count them | bug |
| [#659](https://github.com/mudler/vllm.cpp/issues/659) | — | LTX-2.5 device select adopts M3a's platform seam but not its companion capability guard: `ltx2_video.cpp` asks `CurrentPlatform().device_type()` and `TryGetBackend(...)` but never `supports_model_architecture`, so a PARTIAL backend (Metal 15/75 ops, Tenstorrent) is handed a queue and dies in a kernel bind where it used to be refused BY NAME (found while reviewing #553 for landing) | bug |
| [#660](https://github.com/mudler/vllm.cpp/issues/660) | — | `check-device-leakage`'s `kcuda` bucket is the token grep `\bkCUDA\b`, so `minimax_h3_video.cpp:221-226`'s `static_cast<vt::DeviceType>(device)` hardcodes CUDA as enum value 1 and counts as 0. Gate strength plus an enum-ordering hazard; the H3 video lane should ask the same seam `ltx2_video.cpp` now does (found while reviewing #553) | bug |
| [#664](https://github.com/mudler/vllm.cpp/issues/664) | — | **FIXED 2026-08-13, `row/FIX-WINDOWS-POSIX-VIDEO-ENGINE`.** `windows-msvc-cpu` / `windows-msvc-vulkan` were RED on EVERY open PR (9 sampled across 5 unrelated lanes) from ONE file: `video_engine.cpp` reached Windows with `<sys/stat.h>`, `::stat` and `S_ISDIR` (landed `cefacd2d0`), which `check-windows-portability.py:1675-1688` flags under `full_source_posix` — every scanned source, not only the platform-boundary set. `main` was never a denominator because the Windows jobs are PR-only and `skipped` on push (#584). Repaired at the SOURCE, not the checker: `IsDir`/`Exists` now take the `std::error_code` <filesystem> overloads through a file-local `NativePath`, which preserves `::stat`'s return-false-for-an-uninspectable-path behaviour that the THROWING overloads would have turned into a `filesystem_error` escaping a registry query | bug |
| [#608](https://github.com/mudler/vllm.cpp/issues/608) | `TOOLS-PARSER-BREADTH` | **W0 (record backfill) landed 2026-08-13; row `INVENTORIED` → `PARTIAL`, 41 shipped names / 37 families recorded.** Re-derived from the two REGISTRIES rather than from recipe usage: **five** `--tool-call-parser` names are upstream-only at the pin — `openai`, `inkling`, `minimax_m3` (W1, recipe demand) and `cohere_command3`, `cohere_command4` (W2, ZERO recipe uses, so usage-driven audits miss them). **Only `inkling` is PORTABLE from vLLM source**: `minimax_m3` is backed by the Rust crate, `openai` is a declared Harmony stub that raises on both methods, and both Cohere names are shims over the out-of-tree `cohere_melody` package, so W1/W2 each owe a recorded decision before code rather than a text port. `nemotron_json`, `kimi_k3` and `ling3` are in NEITHER registry and arrive with the pin advance, not here. W3 ports upstream's shared `ToolParserTestConfig` harness. The earlier "six missing" framing was usage-derived: it listed `nemotron_json` as portable (it is not registered at the pin) and missed both Cohere entries | feature |
| [#647](https://github.com/mudler/vllm.cpp/issues/647) | — | Oracle policy had no fallback and no pin concept: five upstreams beyond vLLM are already compared against (vLLM-Omni, SGLang, llama.cpp, `transformers`, tt-forge) with their pins scattered across individual specs or absent entirely. AGENTS.md now admits a named secondary oracle where vLLM implements nothing, `.agents/oracles/<id>.md` pins each one file-per-oracle, and `check-oracle-pins.py` enforces both directions. The gateability debts for `sglang`, `diffusers` and `tt-forge` stay open on this issue | feature |
| [#672](https://github.com/mudler/vllm.cpp/issues/672) | `MODEL-MUSIC-minimax-music3-mini-max-music3-for-conditional-generation` | MiniMax-Music3: port the text-to-music lane — ~8.6B Qwen3 global LLM (our LANDED architecture at vocab 200000) + 8-codebook RVQ depth decoder + 2.4B fp32 flow-matching DiT + DAC Flow-VAE. Our first music-generating model, and the first row whose primary oracle is not vLLM: absent from the pin, from vLLM `main` and from `vllm-omni`, so it gates against the OPEN diffusers PR #14456 with SGLang-Omni as the e2e cross-check, under the fallback rule added in #647 | feature |
Expand Down
42 changes: 36 additions & 6 deletions src/vllm/multimodal/video_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
#include <cassert>
#include <cstdio>
#include <exception>
#include <filesystem>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <system_error>
#include <utility>
#include <vector>

#include <sys/stat.h>

#include <nlohmann/json.hpp>

#include "vllm/entrypoints/openai/video_api.h"
Expand Down Expand Up @@ -54,14 +54,44 @@ std::vector<VideoFamilyRegistration>& RegistryStorage() {
// detector may claim a checkpoint and exactly one entry may carry a name.
const std::vector<VideoFamilyRegistration>& OrderedRegistry() { return RegistryStorage(); }

// A caller's UTF-8 path as a native filesystem path. Byte-for-byte the spelling
// in v1/kv_offload/fs_io.cpp:31, and the same job the loader lane's Utf8Path
// does (gguf_reader.cpp:22, safetensors_reader.cpp:29) — no shared helper
// exists to call, because each is file-local to its own TU. The u8string step
// is not decoration: on Windows a narrow std::string handed to
// std::filesystem::path is interpreted in the ACTIVE CODE PAGE, so every
// non-ASCII checkpoint path silently resolves to the wrong file (or to none).
// Saying char8_t makes the UTF-8 explicit and the conversion to UTF-16 exact.
std::filesystem::path NativePath(const std::string& utf8) {
#if defined(_WIN32)
const std::u8string value(reinterpret_cast<const char8_t*>(utf8.data()), utf8.size());
return std::filesystem::path(value);
#else
return std::filesystem::path(utf8);
#endif
}

// BOTH probes take the std::error_code overloads, and that is load-bearing
// rather than stylistic. The `::stat` calls these replaced reported an
// uninspectable path — ENAMETOOLONG, ELOOP, EACCES on a parent — by returning
// -1, which arrived here as a plain `false` and became the registry's ordinary
// "no such file or directory" refusal. The THROWING
// std::filesystem::exists(p) / is_directory(p) overloads raise
// filesystem_error for exactly those cases instead, which would escape
// ReadVideoCheckpointTensorNames — whose header contract is to return false
// with *why set — and, through DescribeCheckpoint, escape LoadVideoEngine in
// place of the refusal that names the registered families. Returning false on
// error keeps the POSIX behaviour these calls had. Issue #664.
bool IsDir(const std::string& path) {
struct stat st {};
return ::stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
std::error_code error;
const bool result = std::filesystem::is_directory(NativePath(path), error);
return !error && result;
}

bool Exists(const std::string& path) {
struct stat st {};
return ::stat(path.c_str(), &st) == 0;
std::error_code error;
const bool result = std::filesystem::exists(NativePath(path), error);
return !error && result;
}

std::string StripTrailingSlash(const std::string& dir) {
Expand Down
46 changes: 46 additions & 0 deletions tests/vllm/multimodal/test_video_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,52 @@ TEST_CASE("video engine registry: an unrecognizable checkpoint refuses instead o
}
}

// A path the OS cannot inspect AT ALL — one 300-character component, which is
// ENAMETOOLONG rather than ENOENT. This is the case that separates a REFUSAL
// from a THROW, and it is why the registry's existence probes must use the
// std::error_code overloads of <filesystem>:
//
// ::stat(path, &st) -> -1, so the probe returned false
// std::filesystem::exists(p, ec) -> false, ec = "File name too long"
// std::filesystem::exists(p) [throwing] -> THROWS filesystem_error
//
// The header's contract for ReadVideoCheckpointTensorNames is "returns false
// with *why holding the reason when the artifact cannot be enumerated"
// (include/vllm/multimodal/video_engine.h). A throwing overload silently trades
// that documented refusal for an exception escaping a registry query, and no
// token- or golden-based gate would ever see it, because every checkpoint those
// gates hand over is perfectly stattable. Issue #664.
TEST_CASE("video engine registry: an UNINSPECTABLE path refuses, and never throws") {
SeamWorkspace ws;
const std::string unstattable = ws.root + "/" + std::string(300, 'x');

std::vector<std::string> names{"stale"};
std::string why;
bool enumerated = true;
REQUIRE_NOTHROW(enumerated = vllm::multimodal::ReadVideoCheckpointTensorNames(
unstattable, &names, &why));
CHECK_FALSE(enumerated);
CHECK(names.empty());
CHECK(why == "no such file or directory");

// ...and the same path through the seam ends in the registry's OWN refusal,
// which names the registered families. std::filesystem::filesystem_error
// derives from std::runtime_error, so CHECK_THROWS_AS(std::runtime_error)
// would NOT tell the two apart — the message is what discriminates them, and
// a filesystem_error's what() knows nothing about video families.
vllm::multimodal::VideoModelParams mp = FixtureParams(ws.fixture);
mp.dit_path = unstattable;
try {
(void)vllm::multimodal::LoadVideoEngine(mp);
FAIL("an uninspectable dit_path must be refused, not detected around");
} catch (const std::exception& e) {
const std::string msg = e.what();
INFO(msg);
CHECK(msg.find("minimax-h3") != std::string::npos);
CHECK(msg.find("no such file or directory") != std::string::npos);
}
}

// ─── extras carry the family-specific knob, in BOTH directions ──────────────
TEST_CASE("video engine seam: H3's partition rides in extras and still guards") {
SeamWorkspace ws;
Expand Down
Loading