Repository navigation
[Bug]: GitHub Copilot provider: all models report text-only input — image attachments blocked #2941
Description
Client or integration
Codex App
Area
Catalog / models
Summary
When using the github-copilot provider, every modeli s cataloged with inputModalities: ["text"], which makes Codex block image attachments with "This model does not support image inputs." This affects all 32+ vision-capable models (Claude Opus/Sonnet, GPT-4o/4.1/5.x, Gemini, Grok, etc.).
Expected: models that support vision should be cataloged with ["text", "image"] so users can attach images.
Root cause
Three compounding gaps in the github-copilot provider:
1. Copilot API uses a non-standard capabilities structure
GitHub Copilot's /models endpoint reports vision support in a nested format that OpenCodex does not parse:
{
"id": "claude-opus-4.6",
"capabilities": {
"supports": { "vision": true },
"limits": { "vision": { "max_prompt_images": 20 } }
}
}OpenCodex's modelInputModalities() function (in provider-fetch.ts) checks:
item.input_modalities/item.modalities— Copilot does not have these fieldscapabilityRecord?.vision— butcapabilityRecordisplainRecord(item.capabilities)which yields{ supports: {...}, limits: {...} }, so.visionisundefined(it is nested under.supports)capabilitiesarray frommodelCapabilities()— iteratescapabilityFieldslooking forvalue === true, butsupportsis an object nottrue
Result: every path returns undefined, the fallback chain lands on ["text"], and Codex blocks images.
2. No modelInputModalities in the registry entry
The github-copilot entry in src/providers/registry.ts (line 2694) has no modelInputModalities field. Other major providers include one as a cold-start seed.
3. Not in PROVIDER_ALIASES
github-copilot is absent from PROVIDER_ALIASES in src/generated/model-metadata.ts. Providers like openrouter are aliased, so their models can fall back to the metadata database. Without an alias, this fallback is also dead.
Reproduction
- Install OpenCodex 2.33.0 and log in via the
github-copilotprovider - Select any vision-capable model (e.g. claude-opus-4.6, gpt-4o, gpt-5.4)
- Try to attach/paste an image in the Codex App
- Codex blocks it with: "This model does not support image inputs"
- Compare: switch to the same model via openrouter provider — images work fine
Proposed fix
parse the nested Copilot structure
In modelInputModalities() in provider-fetch.ts, add a check for the nested capabilities.supports.vision structure:
const supports = plainRecord(capabilityRecord?.supports);
if (supports?.vision === true) return ["text", "image"];This would automatically handle all current and future Copilot models.
or the eaiser way is to just
Add modelInputModalities to the github-copilot registry entry.
Version
2.33.0
OS
macOS 26.2 (arm64)
Provider and model
github-copilot / claude-opus-4.6 (affects all 32 vision-capable models on the Copilot API)
Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Activity
Ingwannu commentedon Aug 29, 2026
Confirmed on current
devat3a9835ca91d34affe97a4028b616d33e86d09d5b.The report is valid:
catalogHintsFromModelsApiItem()reads directcapabilities.vision, but Copilot publishes the signal ascapabilities.supports.vision. The nested object is not converted into the flat capability list, so discovery contributes no image modality and the routed catalog falls back to text-only.I am preparing the narrow fix in the shared live-discovery parser:
supports.vision: trueas["text", "image"];supports.vision: falseas["text"];I will not add a blanket Copilot registry seed or provider alias: the live per-model capability is the more precise source and avoids incorrectly marking text-only Copilot models as vision-capable. I will link the implementation PR here after focused validation.
DamnUi commentedon Aug 29, 2026
Ignore the pr pelase
lidge-jun commentedon Aug 29, 2026
리뷰 · 우선순위 73 / 80
이 이슈는 지금
devHEAD3a9835ca9(#2933) 에서도 그대로인 GitHub Copilot 카탈로그 구멍이다. Codex 앱에서github-copilot모델을 고르면, 그림이 되는 모델까지 전부inputModalities: ["text"]로 적히고, 이미지를 붙이면 "This model does not support image inputs" 로 막힌다. 작성자는 Claude Opus/Sonnet, GPT-4o/4.1/5.x, Gemini, Grok 같은 32개 이상 그림 모델이 같이 죽는다고 했다. 같은 모델을 openrouter 로 고르면 그림이 된다. 미리보기 배포는 계획에 없고, types.ts/config.ts 분할과도 안 겹친다. 독립 버그픽스다.지금 HEAD 가 그림을 못 읽는 이유는 세 겹이다. 첫째, Copilot
/models는capabilities.supports.vision을 쓴다.src/codex/catalog/provider-fetch.ts의modelInputModalities()(1063-1108행) 는plainRecord(item.capabilities)?.vision만 본다. 객체는{ supports, limits }이라.vision은 없다.modelCapabilities()도 값이true인 칸만 이름 목록에 넣어서,supports객체는 목록에vision을 안 남긴다. 힌트가 비면src/codex/catalog/parsing.ts457-468행ensureStrictCatalogFields가["text"]를 채운다. 둘째, 레지스트리github-copilot항목(src/providers/registry.ts2790행)에modelInputModalities씨앗이 없다. 산 신호가 죽으면 차가운 시작도 글자만이다. 셋째,github-copilot은PROVIDER_ALIASES에도 없어서 메타데이터 데이터베이스 폴백도 안 탄다. 메인테이너가 같은 SHA 에서 이 보고가 맞다고 확인했다.고치는 바른 길은 산 발견 파서에 겹친 신호를 넣는 것이다.
supports.vision === true면["text", "image"]이고,=== false면["text"]이고, 이상한 값은 그림을 켜면 안 된다. 레지스트리에 그림 씨앗을 통째로 심거나 별칭을 넣으면, Copilot 이 글자만이라고 한 15개 모델까지 그림으로 보일 수 있다. 메인테이너가 그 두 갈래를 안 하겠다고 한 이유가 그것이다. 작성자가 연 #2942 는 참 갈래만 넣었고, 거짓 갈래와 테스트가 없으며, 갈래가main이라 이미 닫혔다. 그 PR로 이 이슈를 닫으면 안 된다.테스트 자리는 이미 있다.
tests/catalog-input-modality-enum.test.ts가catalogHintsFromModelsApiItem을 부르고,tests/catalog-llamacpp-capabilities.test.ts가 같은 함수로 llama.cppmultimodal(#1797) 을 잠근다. Copilot 모양 세 줄(true / false / 이상한 값)을 거기에 넣으면 hygiene 도 통과한다.limits.vision.max_prompt_images는 이번 첨부를 켜는 신호와 다른 칸이다. 이번 이슈는 모달리티 오탐이다.경로
src/codex/catalog/provider-fetch.tsmodelInputModalities- 겹친supports.vision을 안 본다. 산 발견이 그림을 못 남기는 바로 그 줄이다.경로
src/codex/catalog/provider-fetch.tsmodelCapabilities- 겹친 객체를 평평한 이름 목록으로 안 펼친다. 첨부는 모달리티가 막으므로 1차 고침은 모달리티만으로도 된다. 능력 목록은 후속이다.경로
src/providers/registry.tsgithub-copilot-modelInputModalities씨앗이 없다. 산 신호가 죽은 지금, 차가운 시작도 글자만이다. 씨앗을 통째로 심으면 글자만 모델이 그림으로 보인다. 넣지 않는 편이 맞다.경로
src/codex/catalog/parsing.ts457-468 - 힌트가 비면["text"]로 채운다. 빈 목록보다 낫다. 이 기본값을 바꾸면 다른 제공자까지 흔들린다. 고칠 곳은 여기가 아니다.경로/심볼 - #2942 - 참 갈래만 있는 닫힌 초안이다. 이 이슈를 그 PR로 닫지 마세요.
메인테이너의 판단이 필요한 지점
modelCapabilities()펼치기를 같은 PR에 넣을지, 모달리티 다음에 둘지너의 추천
열린 채로 두고, 메인테이너가 준비 중인
dev위 구현을 받으세요. 참/거짓/이상한 값 세 갈래와catalogHintsFromModelsApiItem회귀를 같이 넣어야 한다. #2942 는 다시 열지 마세요. 레지스트리 씨앗과 별칭은 넣지 마세요. types/config 분할과 무관하니 close-don't-rebase 대상이 아니다. 구현이dev에 들어가면 이 이슈를 그 PR로 닫으면 된다.이 댓글은 grok-bot이 작성했습니다
Ingwannu commentedon Aug 29, 2026
The fix is now available in #2943 at exact head
2fe8c89dd41d83dc34edbd90b06ddff83483ff1b.Focused discovery coverage passes: 31 tests / 180 expectations. The PR is intentionally not merged yet: cross-platform CI is running and, because I authored it, project policy requires approval from another maintainer. @lidge-jun has been requested for review.
Ingwannu commentedon Aug 29, 2026
Update: #2943 was rebased after #2863 advanced
devand touched the shared catalog file. The current exact head isb2cb71b992d893fe1a955d3096a03c06ce4e038a; the focused discovery suite passes again at 31 tests / 182 expectations. The force-push was limited to the PR branch, so review and CI correctly restarted for the new head.lidge-jun commentedon Aug 29, 2026
Fixed on
devas3700526489645f65f7bf162fd4ffa81e610fa3f1(#2943). Vision-capablegithub-copilotmodels will be cataloged with["text", "image"]and accept image attachments after the next catalog sync.Your diagnosis was right on all three points, and the first one is what got fixed.
modelInputModalities()now reads the nestedcapabilities.supports.visionboolean, so every current and future Copilot model that reports vision gets image input without anyone maintaining a list. An explicit nestedfalseis honoured as a real text-only denial rather than falling through.Two notes on the parts of your proposal we did not take, since you clearly thought about them.
The registry seed — your "easier way" — we skipped.
modelInputModalitiesis a per-model map, so a seed means asserting a model-by-model list. Nobody here has an audited one, and writing it from the 32 names in your report would duplicate a remote catalog that changes without us and go stale silently. Parsing what Copilot reports is authoritative per model. A selective seed for verified ids is still legitimate as cold-start protection if someone can audit the list — that stays open.PROVIDER_ALIASESwe did not touch, because it turned out not to be needed. That path exists to fall back to the bundled metadata database when a provider reports nothing useful; here Copilot does report the capability, we just were not reading it. Fixing the parse makes the fallback unnecessary rather than dead.One detail from your payload that shaped the implementation:
capabilitiescarries a secondvisionkey underlimitsholdingmax_prompt_images. Any fix that searched the capabilities object loosely for a vision-ish key would have found that record — truthy, and meaningless as a capability signal. Including it in your report is what made the exact-path read obviously correct, so thank you for pasting the whole shape rather than a summary.On #2942: it was closed only because it targeted
maininstead ofdev— the branch gate is automatic and not a judgement on the change. The parse that shipped is essentially yours. If you open another PR, targetdevand it will go through normal review.A follow-up in #2944 adds regression coverage for the precedence rule, the
limits.visionsibling, and malformed capability shapes.