Repository navigation
[Bug]: deepseek-flash accepts native image input on Chat and Responses, but the registry still routes it through the vision sidecar #4436
Description
Client or integration
Direct HTTP/API client
Area
Provider adapter
Summary
deepseek-flash (DeepSeek V4.1-Flash) accepts native image input on both /chat/completions and /responses, but the built-in DeepSeek entry still classifies it as text-only via noVisionModels. Attached images are therefore pre-described by the vision sidecar instead of being sent upstream, and the catalog only advertises image input because of that sidecar path. Expected: deepseek-flash should be treated as a native vision model and images should go upstream unchanged.
Reproduction
- Send
POST https://api.deepseek.com/responseswith modeldeepseek-flash, a 16×16 solid red PNG as aninput_imagedata URL,reasoning.effort = "none",max_output_tokens: 300,stream: false→ HTTP 200, output textRed. - Repeat with a 32×32 image whose left half is green and right half is blue, asking "This image has two solid colored halves. Name both colors in left-to-right order." → HTTP 200, output text
green, blue. - Repeat the same two-tone image on
POST https://api.deepseek.com/chat/completionswith animage_urlcontent part → HTTP 200, answergreen, blue. - Control: point
input_image.image_urlathttps://example.invalid/missing.pngonPOST /responses→ HTTP 400,input[0].image[0]: Failed to download image from https://example.invalid/missing.png.
Request shape used in steps 1–3:
{
"model": "deepseek-flash",
"input": [{
"role": "user",
"content": [
{ "type": "input_text", "text": "This image has two solid colored halves. Name both colors in left-to-right order." },
{ "type": "input_image", "image_url": "data:image/png;base64,<32x32 left-green/right-blue>" }
]
}],
"reasoning": { "effort": "none" },
"max_output_tokens": 300,
"stream": false
}Step 4 is decisive: the server actually downloads and decodes the image, so input_image is not replaced with placeholder text.
The same probe with deepseek-v4-flash-vision-exp (the id the docs still point at) returns "model": "deepseek-flash" in the response body — the retired id is routed to V4.1-Flash — and answers the two-tone image correctly as well.
Version
2.52.0
Operating system
macOS (Apple Silicon)
Provider and model
deepseek / deepseek-flash
Logs or error output
POST /responses model=deepseek-flash image=16x16 solid red -> 200 "Red"
POST /responses model=deepseek-flash image=32x32 two-tone -> 200 "green, blue"
POST /chat/completions model=deepseek-flash image=32x32 two-tone -> 200 "green, blue"
POST /responses model=deepseek-flash image=https://example.invalid/missing.png
-> 400 input[0].image[0]: Failed to download image from https://example.invalid/missing.png
Redacted configuration
Registry default being overridden by the stale classification, src/providers/registry.ts (DeepSeek first-party entry):
// Issue #88: every DeepSeek API model is text-only input (no image support upstream) — the
// vision sidecar describes attached images for them, and the catalog advertises image input
// on their behalf.
noVisionModels: ["deepseek-chat", "deepseek-reasoner", ...DEEPSEEK_NATIVE_THINKING_MODELS],DEEPSEEK_NATIVE_THINKING_MODELS is ["deepseek-flash", "deepseek-v4-flash"], so deepseek-flash is classified as text-only. The list predates the V4.1 transition; #4282 moved deepseek-flash into it.
Suggested change:
- Drop
deepseek-flashfrom the DeepSeek entry'snoVisionModels(keepdeepseek-chat,deepseek-reasoner, anddeepseek-v4-flashuntil that alias is probed too). - Add the positive declaration, following the existing vision-preview pattern:
modelInputModalities: { "deepseek-flash": ["text", "image"] }. - Note for the changelog: this cannot be fixed from user config.
router.tsunions the registry list with the saved list, so entries can be added but never removed at the config level.
Stale upstream docs, for reference:
- Responses API reference still lists
modelas[deepseek-v4-flash, deepseek-v4-pro]and claimsinput_imageparts "are replaced with a placeholder text". - Vision guide still says only
deepseek-v4-flash-vision-expaccepts images and other models return 400.
Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Activity
github-actions commentedon Sep 12, 2026
Issue reopened
The report now contains the information required by the automated check. Thanks for updating it.
lidge-jun commentedon Sep 12, 2026
리뷰 · 우선순위 66 / 80
설명
이 이슈는 DeepSeek 기본 모델
deepseek-flash(V4.1-Flash)가 이미 네이티브 이미지 입력을 받는데, OpenCodex 레지스트리는 아직도 “텍스트만 보는 모델”로 분류해서 비전 사이드카로 이미지를 먼저 설명하게 만든다는 버그다. 보고자는api.deepseek.com에 직접 붙여서 확인했다./responses에 16×16 빨간 PNG와 32×32 초록/파랑 반반 PNG를input_image로 넣으면 200으로 색깔을 맞히고,/chat/completions의image_url파트도 같다. 가짜 URL을 주면 400과 함께 “이미지를 못 내려받았다”고 나와서, 서버가 진짜로 이미지를 다운로드·디코딩한다는 증거까지 있다. 예전 실험 iddeepseek-v4-flash-vision-exp로 보내도 응답model이deepseek-flash로 오고 같은 답이 나온다. 즉 비전 프리뷰가 Flash로 흡수된 뒤인데, 우리 쪽 분류만 예전 Issue #88 시절(“DeepSeek API는 전부 텍스트만”)에 멈춰 있다.지금
devHEAD(dcd13b435, package2.53.0)의src/providers/registry.tsDeepSeek first-party 엔트리를 보면 말이 맞다.DEEPSEEK_NATIVE_THINKING_MODELS는["deepseek-flash", "deepseek-v4-flash"]이고,noVisionModels는["deepseek-chat", "deepseek-reasoner", ...DEEPSEEK_NATIVE_THINKING_MODELS]라서 기본 모델 flash가 사이드카 소비자로 들어간다. 반대로 양수 선언modelInputModalities는 아직도 실험 id만{ [DEEPSEEK_VISION_PREVIEW_MODEL]: ["text", "image"] }다.src/vision/eligibility.ts의isModelVisionSidecarConsumer는noVisionModels멤버면 곧바로 true라서, 이미지가 붙은 요청은src/vision/plan.ts경로로 먼저 설명되고 본 모델에는 텍스트만 간다. 카탈로그가 image를 광고하는 것도 사이드카 소비자용 힌트(applyProviderConfigHints계열) 때문이지, native vision으로 광고하는 게 아니다.설정으로 못 고친다는 점도 현재 코드와 같다.
src/router.ts의mergeStringArray는 레지스트리 seed와 사용자 배열을 합집합(Set union) 한다. 그래서 사용자가noVisionModels에서deepseek-flash를 빼도 레지스트리 값이 다시 붙는다. 양수modelInputModalities만 넣어도, eligibility는noVisionModels를 먼저 보기 때문에 사이드카가 계속 탄다. 고치려면 레지스트리에서 flash를noVisionModels에서 빼고(또는 thinking 상수에서 비전 예외를 분리하고),modelInputModalities["deepseek-flash"] = ["text", "image"]를 넣는 코드 변경이 필요하다.deepseek-v4-flash호환 별칭과 Zen 게이트웨이의deepseek-v4.1-flash(DEEPSEEK_GATEWAY_THINKING_MODELS→ opencode-zennoVisionModels)는 이번 프로브 범위 밖이면 일단 사이드카에 남겨 두고, first-party flash만 먼저 고치는 편이 안전하다.지금
dev방향(Muse device OAuth, Devin WS/effort, quota-avoid, credits #4432)과 파일은registry.ts/router.ts/vision/*로 겹치지만, DeepSeek 기본 모델의 이미지 품질·지연·비용을 바로 깎는 provider 버그라 우선순위는 중상이다. types/config 분할에 잡아먹힐 큰 PR이 아니라, 레지스트리 한 줄·양수 modality·짧은 회귀 테스트로 끝낼 수 있는 독립 픽스다. 업스트림 문서(Responses가 placeholder로 바꾼다, vision-exp만 이미지가 된다)는 보고자 말대로 낡았고, live probe가 문서를 이긴다.경로
src/providers/registry.tsDeepSeeknoVisionModels(대략 2217–2220행) /DEEPSEEK_NATIVE_THINKING_MODELS(679행) - Issue #88 주석과 함께 flash·v4-flash가 사이드카 소비자로 묶여 있다. V4.1 전환 후 flash만 native vision으로 빼야 한다.경로
src/providers/registry.tsmodelInputModalities(2147행) /DEEPSEEK_VISION_PREVIEW_MODEL(687행) - 실험 id만["text","image"]다. flash에 같은 양수 선언을 추가하지 않으면 카탈로그·capability 체인이 native vision으로 안 읽힌다.경로
src/vision/eligibility.tsisModelVisionSidecarConsumer-noVisionModels가 modality보다 우선한다. flash를 리스트에서 빼지 않으면 modality만 고쳐도 사이드카가 남는다.경로
src/router.tsmergeStringArray(161–167행) - 사용자 config로 레지스트리noVisionModels항목을 제거할 수 없다. 수정은 레지스트리 쪽이어야 한다.경로
src/providers/registry.tsopencode-zennoVisionModels+DEEPSEEK_GATEWAY_THINKING_MODELS- Zen의deepseek-v4.1-flash도 같은 계열로 사이드카에 들어가 있다. first-party와 같은지 별도 프로브가 필요하다.심볼
deepseek-v4-flash(호환 별칭) - 보고자 제안대로 이번엔 사이드카에 남겨 두고, flash와 동일하게 라우팅되는지 확인한 뒤에야noVisionModels에서 빼는 편이 안전하다.메인테이너의 판단이 필요한 지점
deepseek-flash만 고칠지, 같은 날deepseek-v4-flash별칭과 Zendeepseek-v4.1-flash까지 한 PR에 묶을지.DEEPSEEK_VISION_PREVIEW_MODEL행을 유지할지(별칭으로 flash에 붙음), 카탈로그에서 내려 “flash가 vision”으로만 남길지.너의 추천
열린 버그로 두고
bug/provider를 유지한다. 작성자 제안대로 레지스트리에서deepseek-flash만noVisionModels에서 제거하고modelInputModalities["deepseek-flash"] = ["text", "image"]를 넣은 짧은 PR을 받는다.deepseek-chat/deepseek-reasoner/deepseek-v4-flash는 프로브 전까지 사이드카에 남긴다.isModelVisionSidecarConsumer가 false가 되고 이미지가 그대로 upstream으로 가는지, 카탈로그가 sidecar 광고가 아니라 native image로 읽히는지 단위 테스트로 잠근다. Zendeepseek-v4.1-flash는 follow-up 이슈/체크리스트로 분리해도 된다. types/config 분할에 무효화될 변경이 아니므로 닫지 말고, 현재 Muse/Devin/quota 기차와 파일 충돌만 피하면 독립으로 머지 가능하다.2.52.0사용자에게는dev/2.53.0HEAD에도 같은 분류가 남아 있다고 안내하면 된다.이 댓글은 grok-bot이 작성했습니다
test(routing): accept native-vision DeepSeek Flash in inherited regis…
Merge pull request #4500 from lidge-jun/codex/260913-i3-carry-4467-de…
lidge-jun commentedon Sep 13, 2026
Fixed on dev. deepseek-flash is now treated as native multimodal rather than being routed through the vision sidecar, landed via #4500 (merge commit 94063d0, verified as an ancestor of origin/dev).
Your own pull request #4467 is what landed; the carry preserves your authorship with a Co-authored-by trailer in the landed commit.
Cross-platform CI run 34751593123 concluded success on the exact merged head. Closing manually because this merges into dev rather than the default branch.
fix(provider): treat deepseek-flash as native multimodal
docs(devlog): correct wave 2 after the dispatch-time ownership re-check
fix(provider): treat deepseek-flash as native multimodal
test(routing): accept native-vision DeepSeek Flash in inherited regis…
Merge pull request lidge-jun#4500 from lidge-jun/codex/260913-i3-carr…
docs(devlog): correct wave 2 after the dispatch-time ownership re-check