Mapped GPT models were rejected by Codex clients with "model does not
support image inputs". Two root causes:
- Catalog entries for native-Responses/Anthropic providers cloned a
template whose input_modalities defaulted to ["text"], so every mapped
model was advertised text-only. model_catalog_json replaces Codex's
built-in model table wholesale, and both the TUI and the IDE extension
block images pre-send when the current model is found without "image".
- Editing the current Codex provider during proxy takeover only refreshed
the DB backup, so removing the mapping left a stale model_catalog_json
pointer (and its text-only catalog file) active in live config.
Changes:
- New shared model_capabilities module: explicit row declaration first,
then a confirmed text-only registry (exact tail match only — prefix
matching removed, variants enumerated so future -vl/-vision models fail
open), everything else unknown.
- Catalog generation writes input_modalities from that inference for all
tool profiles: unknown models fail open to ["text","image"]; only
confirmed text-only models are advertised as ["text"], giving users a
clear client-side prompt instead of silent image stripping.
- Live catalog reverse-import collapses modalities that match current
inference, so registry corrections are not frozen into hidden row
overrides and the rectifier's heuristic opt-out keeps working.
- Saving the current Codex provider while takeover owns live now
re-projects the live config (mirrors the hot-switch path), so mapping
edits and removals take effect immediately.
- Media rectifier delegates to the shared module; its preflight toggle is
documented (4 locales) as proxy-request-only, never affecting catalog
capability declarations.
Fixes#5025. The rectifier's media fallback missed Volcano Coding Plan's
GLM 5.2 on both paths:
- Preventive: known_text_only_model had glm-5.1 but not glm-5.2, so image
blocks were forwarded verbatim. Added glm-5.2 as an exact tail match
(not a prefix, to avoid stripping images from a future glm-5.2v
multimodal variant following Zhipu's 4v/5v naming).
- Reactive: the upstream error "Model only support text input" never
mentions image/media, so the mentions_image gate rejected it before
hints ran; and the existing "only supports text" hint misses the
gateway's missing third-person "s". Added a self-evident phrase list
("only support text" / "only supports text") that asserts a modality
rejection on its own and bypasses the image-mention gate.
Includes regression tests using the verbatim #5025 error body and the
glm-5.2[1M] mapped-model form, plus a glm-5.2v negative assertion.
* Update Longcat presets to LongCat-2.0
* fix(proxy): classify LongCat-2.0 as text-only for media sanitizer
The Longcat presets now use LongCat-2.0, but the known_text_only_model
allowlist still only matched the retired longcat-flash-chat tail. Without
this, images pasted into a text-only LongCat-2.0 session are forwarded
upstream instead of being replaced with the unsupported-image marker,
causing a hard rejection. Add longcat-2.0 (keeping the retired name for
saved configs) and a regression test.
---------
Co-authored-by: chengzifeng <chengzifeng@meituan.com>
Co-authored-by: Jason <farion1231@gmail.com>
Codex /responses requests routed to text-only OpenAI-chat upstreams
(e.g. DeepSeek deepseek-v4-flash) failed with HTTP 400 "unknown variant
image_url" when images were sent: the responses->chat conversion turns
input_image items into image_url blocks the model rejects. The media
rectifier previously covered only the Claude adapter, so neither the
proactive strip nor the reactive retry fired for Codex.
- media_retry_should_trigger: accept "Codex" adapter, not just "Claude"
- contains_image_blocks / replace_images: also scan responses `input`
(input_image) in addition to chat `messages`
- is_image_block_type: match image | image_url | input_image
- is_unsupported_image_error: add "unknown variant" hint for the
deserialize error
- forward(): proactively run apply_media_prevention for Codex after the
responses->chat conversion
Proactively strips images for known text-only models (heuristic on by
default) and reactively retries with images replaced on upstream
image-unsupported errors. Adds tests for chat image_url, codex
input_image, the reactive trigger, and the deserialize error match.
Replace unsupported Anthropic image blocks with an [Unsupported Image] marker when routed models are text-only or upstream rejects image input.
Add rectifier settings for media fallback and heuristic model detection, wire the controls into the settings UI, and cover the sanitizer and forwarder gates with regression tests.