Repository navigation
[Bug]: Vision sidecar never triggers for NVIDIA NIM text-only models (registry nvidia entry missing noVisionModels) #956
Description
Client or integration
Codex App (also reproducible via Direct HTTP/API client)
Area
Proxy and routing · Catalog / models · Provider adapter
Summary
The built-in nvidia provider entry in src/providers/registry.ts does not declare noVisionModels, so the vision sidecar is never activated for NVIDIA NIM text-only models (e.g. deepseek-ai/deepseek-v4-flash, nvidia/nemotron-3-ultra-550b-a55b, z-ai/glm-5.2, minimaxai/minimax-m3, moonshotai/kimi-k2.6). Users must manually add noVisionModels to the provider entry in ~/.opencodex/config.json as a workaround.
Expected: a text-only NIM model receives an image attachment and the proxy describes it through the vision sidecar before calling the upstream.
Actual: planVisionSidecar returns undefined (the model is not in provider.noVisionModels), so raw image parts are either forwarded to the text-only upstream or the catalog advertises the model as text-only and the app blocks the attachment.
Reproduction
- Install
@bitkyc08/opencodex2.10.0 and start the proxy (ocx start). - Add a provider entry for NVIDIA NIM in
~/.opencodex/config.jsonwith only the documented fields (an empty or absentnoVisionModelsmatches the registry default, which has nonoVisionModelsfornvidia):{ "providers": { "nvidia": { "adapter": "openai-chat", "baseUrl": "https://integrate.api.nvidia.com/v1", "authMode": "key", "apiKey": "nvapi-<redacted>" } } } - Query the routed model list and confirm the model has no image modality:
GET /api/models → nvidia/deepseek-ai/deepseek-v4-flash inputModalities: absent - Send a request that carries an image to the text-only model, e.g. via the Codex App (attach a screenshot) or directly:
POST /v1/responses { "model": "nvidia/deepseek-ai/deepseek-v4-flash", "input": [ { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": "data:image/png;base64,..." } } ] } ] } - Observe: no
[vision]sidecar call happens (nothing in the logs); the image either 400s at the upstream or is stripped/blocked. - Workaround: set
noVisionModels: ["deepseek-ai/deepseek-v4-flash"]on the provider entry and restart. Now/api/modelsadvertisesinputModalities: ["text","image"]and the sidecar describes the image successfully (verified end-to-end withdescribeImagereturning a description via the OpenAI forward sidecar).
Version
2.10.0 (npm @bitkyc08/opencodex); Codex runtime 0.146.0
Operating system
Windows 11 (current), America/Fortaleza timezone
Provider and model
nvidia / deepseek-ai/deepseek-v4-flash (also affects nvidia/nvidia/nemotron-3-ultra-550b-a55b, z-ai/glm-5.2, minimaxai/minimax-m3, moonshotai/kimi-k2.6)
Logs or error output
No [vision] log lines are emitted for these models. The model rows in GET /api/models carry no inputModalities. With the workaround applied, the sidecar path works and returns descriptions.
Redacted configuration
{
"providers": {
"nvidia": {
"adapter": "openai-chat",
"baseUrl": "https://integrate.api.nvidia.com/v1",
"authMode": "key",
"apiKey": "nvapi-<redacted>"
}
},
"visionSidecar": {
"backend": "openai",
"model": "gpt-5.6-luna"
}
}How the vision sidecar is gated
planVisionSidecar in src/vision/index.ts returns a plan only when the routed model is listed in provider.noVisionModels:
if (!modelInList(provider.noVisionModels, modelId)) return undefined;
if (!messagesHaveImage(parsed)) return undefined;The registry nvidia entry (src/providers/registry.ts, around line 1079) sets noReasoningModels / preserveReasoningContentModels for the Kimi family but no noVisionModels:
{
id: "nvidia", label: "NVIDIA NIM", baseUrl: "https://integrate.api.nvidia.com/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://build.nvidia.com",
freeTier: true,
parallelToolCalls: false,
noReasoningModels: NVIDIA_NIM_KIMI_MODELS,
modelReasoningEfforts: Object.fromEntries(NVIDIA_NIM_KIMI_MODELS.map(id => [id, []])),
preserveReasoningContentModels: NVIDIA_NIM_KIMI_THINKING_MODELS,
note: "Free tier on NVIDIA NIM — API key still required (get a free key at build.nvidia.com).",
},Other registry entries covering the same text-only model families do declare it, e.g. ollama-cloud lists deepseek-v4-pro, deepseek-v4-flash, nemotron-3-ultra, glm-5.2, etc., and alibaba-intl lists deepseek-v4-pro/flash, glm-5.2, MiniMax-M2.5.
The NIM /v1/models endpoint does not expose input_modalities, so the registry is the only source of truth for capability classification.
Impact
For every text-only NIM model without noVisionModels:
- The proxy forwards raw image parts to a text-only upstream (which rejects them with a 400 or silently ignores them), or
- The Codex catalog advertises the model as text-only (no
input_modalities: ["image"]), so the Codex app blocks image attachments client-side before the sidecar ever runs.
Confirmed against 2.10.0: all 101 discovered nvidia/* rows in /api/models carry no inputModalities, and the 4 enabled text-only models (deepseek-ai/deepseek-v4-flash, minimaxai/minimax-m3, nvidia/nemotron-3-ultra-550b-a55b, z-ai/glm-5.2) never produce a vision plan.
Suggested fix
Add noVisionModels to the registry nvidia entry for the known text-only NIM model families (deepseek-v4-flash/pro, glm-5.x, nemotron-3-ultra/super, minimax-m3, kimi-k2.x, qwen, etc.), matching how ollama-cloud / alibaba-intl classify the same families. Vision-capable NIM models (e.g. meta-llama-3.2-11b-vision-instruct, nvidia/nemotron-nano-vl-8b-v1) must stay out of the list.
Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Activity
github-actions commentedon Aug 3, 2026
Automated translation bookkeeping — detected language: unknown.
github-actions commentedon Aug 3, 2026
Issue reopened
The report now contains the information required by the automated check. Thanks for updating it.
Ingwannu commentedon Aug 4, 2026
Maintainer triage: confirmed. The built-in
nvidiaregistry entry currently provides neithernoVisionModelsnor explicit native image modalities, so the sidecar cannot activate for verified text-only NIM models and native vision models are not advertised correctly.The prepared fix is commit
f557f917in stacked PR #980. It deliberately does not copy the broad suggested list: NVIDIA documents Kimi K2.6 as accepting text, image, and video, while Nemotron 3 Ultra and DeepSeek V4 Flash are text-only. The patch therefore maintains separate verified text-only and native-vision sets and leaves unverified IDs unclassified instead of guessing.Primary evidence:
I reran the focused suites on the stacked head: all 23 NVIDIA tests passed, including both no-intercept guards for native vision models and sidecar activation for text-only models. #980 is stacked on #973 and is not merged into
devyet, so this issue remains open until both layers land.lidge-jun commentedon Aug 4, 2026
Fixed by #980, merged into
devas7343f0ba5.The
nvidiaregistry entry now classifies vision capability, so the sidecar activates for text-only NIM models and the catalog advertises image input for them. Every model named in this report is covered:deepseek-ai/deepseek-v4-flashnoVisionModels— sidecar describes the imagenvidia/nemotron-3-ultra-550b-a55bnoVisionModelsz-ai/glm-5.2noVisionModelsminimaxai/minimax-m3modelInputModalities— natively vision-capablemoonshotai/kimi-k2.6modelInputModalities— natively vision-capableA correction to the report. minimax-m3 and kimi-k2.6 are documented by NVIDIA as accepting image input natively (kimi-k2.6 even ships a hosted
image_urlexample). Listing them as text-only would have been a silent defect in the other direction: the proxy would replace an image the model could read with another model's text description — no error, worse answers, extra cost. They are handled by advertising their real modalities instead. Four more ids from the same family had the same problem:moonshotai/kimi-k2.5,stepfun-ai/step-3.7-flash,thinkingmachines/inkling,mistralai/mistral-medium-3.5-128b.Bounded scope — what this does not fix. Only ids verified against NVIDIA per-model documentation are classified: 26 text-only and 16 vision-capable, audited on 2026-08-04 (
devlog/_plan/260804_stack7_service_vision/011_nim_id_audit.md). A NIM model released after that date is still unclassified and will still show this bug until someone adds it.That is deliberate rather than an oversight. NIM's
/v1/modelspublishes no modality metadata, andshouldExposeRoutedModelfilters only media-generation names — so embeddings, rerankers, guards and OCR endpoints reach the same code path as chat models. An unknown id carries no signal separating a text-only chat model from an embedding endpoint, and defaulting unknown ids in either direction would have been a claim the data does not support (two such designs were tried and falsified during review).The config-only workaround in this report still works for any unclassified model, and a PR adding a verified id is welcome.
Closing. Reopen if a model on the verified list still misbehaves.
docs(devlog): plan stack layer 7 — NIM vision classification and serv…
docs(devlog): fold five audit blockers into the stack 7 plan
docs(devlog): a sixth false positive changes the method, not the design
docs(devlog): audit every id in lidge-jun#964's list — 26 ship, 6 rev…
fix(providers): classify NVIDIA NIM vision capability (lidge-jun#956)
docs(devlog): plan stack layer 7 — NIM vision classification and serv…
docs(devlog): fold five audit blockers into the stack 7 plan
docs(devlog): a sixth false positive changes the method, not the design
docs(devlog): audit every id in lidge-jun#964's list — 26 ship, 6 rev…
fix(providers): classify NVIDIA NIM vision capability (lidge-jun#956)