Repository navigation
feat(core): resolve model modalities from API metadata #8529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 32 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
bd509d1
feat(core): resolve model modalities from API metadata
DragonnZhang 189a24f
fix(core): make model modality loading resilient
DragonnZhang e90c964
fix(core): resolve model modality aliases
DragonnZhang 8be61ff
fix(core): harden model modality resolution
DragonnZhang 6dbf124
fix(core): use catalog for regional modalities
DragonnZhang 0eb16b3
fix(serve): respect runtime env isolation
DragonnZhang b3cef00
fix(core): resolve Idealab aliases by model family
DragonnZhang 9051fa6
refactor(core): resolve auth modalities from catalog
DragonnZhang cf71c84
fix(core): resolve Alibaba proxy modalities by family
DragonnZhang d41e366
fix(core): reuse original provider metadata across gateways
DragonnZhang 08065db
test(core): align legacy modality precedence
DragonnZhang 707e61d
fix(core): preserve explicit legacy modalities
DragonnZhang 8c44f2a
fix(core): harden model metadata catalog loading
DragonnZhang 4b05798
Merge main into dragon/model-modality-api
DragonnZhang 508d28d
fix: preserve model modality metadata
DragonnZhang f373e3c
fix: address model modality review findings
DragonnZhang c4b850f
Merge remote-tracking branch 'origin/main' into dragon/model-modality…
DragonnZhang 09bf0cf
fix model metadata provider resolution
DragonnZhang 444faf6
test(config): isolate OpenAI environment
DragonnZhang 40090b9
test(core): strengthen modality catalog coverage
DragonnZhang e958967
fix(models): avoid proxy refresh thrashing
DragonnZhang 384aef3
fix(core): bound catalog proxy refresh handoffs
DragonnZhang 2609ac3
style(core): preserve catalog test formatting
DragonnZhang 37f2894
fix(core): preserve provider endpoint isolation
DragonnZhang b12cd11
chore: merge origin/main into dragon/model-modality-api
qwen-code-dev-bot 997ce58
fix(models): preserve env-sourced endpoint modalities
DragonnZhang 73f9709
fix(models): bound failed catalog refreshes
DragonnZhang 4f12d61
chore: merge origin/main into dragon/model-modality-api
qwen-code-dev-bot 614d330
fix(models): resolve modalities against runtime endpoint
DragonnZhang aeb4c42
fix(models): preserve endpoint-resolved modalities
DragonnZhang 7c3860d
fix(core): preserve catalog provider identity
DragonnZhang 0682ac3
fix(models): close four review-suggestion gaps in catalog loader
DragonnZhang 9c8bed2
fix(models): close three critical review findings
DragonnZhang 238db3d
Merge remote-tracking branch 'origin/main' into pr8529-fix
DragonnZhang bba7c72
test(cli): document the serve catalog test-runner env exception
DragonnZhang dce920e
fix(core): resolve OpenRouter :batch variants and freeze the serve te…
DragonnZhang d383328
fix(cli): gate the catalog test-runner check on the process-launch env
DragonnZhang fc4e178
Merge remote-tracking branch 'origin/main' into fix-pr8529
DragonnZhang 07b7ef0
fix(core): preserve session endpoint and catalog modalities across sa…
DragonnZhang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| # API-backed model modalities | ||
|
|
||
| ## Problem | ||
|
|
||
| Qwen Code currently derives missing input modalities from model-id regular | ||
| expressions. That works for known model families, but new models and provider | ||
| aliases remain text-only until the table is updated manually. | ||
|
|
||
| ## Design | ||
|
|
||
| Ship a compact snapshot containing only provider identity and input modalities, | ||
| generated from models.dev with `npm run generate:model-modalities`. Load it | ||
| during CLI configuration and cache the full live catalog at | ||
| `~/.qwen/models-dev.json`. | ||
|
|
||
| A valid disk cache is used immediately. When no cache exists, startup uses the | ||
| built-in snapshot immediately. Network access is always a background refresh, | ||
| so a cold start never waits for models.dev. The default loader refreshes stale | ||
| data after one hour and continues refreshing hourly while the process remains | ||
| alive. Refresh failures are non-fatal and retain the last usable disk cache or | ||
| built-in snapshot. | ||
|
|
||
| A successful refresh replaces the process-wide current catalog. Configurations | ||
| created after that point use the new metadata, including later sessions in a | ||
| long-running daemon. Existing sessions retain the catalog they were created | ||
| with so their capabilities do not change midway through a conversation. | ||
|
|
||
| Model modality resolution uses this precedence: | ||
|
|
||
| 1. Explicit `generationConfig.modalities` from settings or a provider entry. | ||
| 2. Exact model metadata from the models.dev provider catalog. | ||
| 3. The existing model-id heuristic. | ||
| 4. Text-only for an unknown model. | ||
|
|
||
| Model-id rules, including MiniMax M3 defaults, are fallback behavior only and | ||
| never override an explicit user value. | ||
|
|
||
| Built-in `/auth` templates omit modalities and let the catalog resolve them. | ||
| Modalities selected explicitly in the advanced setup flow continue to take | ||
| precedence. Existing saved configurations are not migrated or rewritten. | ||
| Their modalities remain explicit and take precedence over catalog metadata. | ||
|
|
||
| Provider identity is resolved from the configured provider when possible and | ||
| otherwise from its endpoint or credential environment key. The catalog lookup | ||
| is exact and case-insensitive; it does not guess across similarly named models. | ||
| An SDK protocol such as `openai` is not treated as provider identity when an | ||
| unknown custom endpoint or credential key is present. | ||
|
|
||
| Exact provider endpoints take precedence over local provider aliases so the | ||
| China and international Alibaba catalogs remain distinct. A missing endpoint | ||
| uses the local provider's default region, while an endpoint that models.dev | ||
| does not list falls back to the model-id heuristic instead of borrowing another | ||
| region's metadata. Idealab's `Qwen*-DogFooding` models and its listed | ||
| `bailian/` aliases resolve by model family to the corresponding Alibaba China, | ||
| DeepSeek, Moonshot, or MiniMax model IDs. | ||
|
|
||
| Every resolved provider first uses its exact catalog entry. When that catalog | ||
| does not list a recognized DeepSeek, Kimi, MiniMax, or GLM model, lookup falls | ||
| back to the model family's original provider catalog. This applies to Alibaba | ||
| and other gateways, while exact metadata from the current provider always | ||
| takes precedence. Lookup never scans arbitrary providers for the first matching | ||
| model ID; unrecognized families remain on the local fallback path. | ||
|
|
||
| OpenRouter model variants first use an exact catalog entry. When models.dev | ||
| does not list the variant, the recognized OpenRouter suffixes `:free`, | ||
| `:extended`, `:thinking`, `:online`, `:nitro`, `:floor`, and `:exacto` fall | ||
| back to the base model. Unknown suffixes remain unmatched. | ||
|
|
||
| The loaded catalog is passed to `ModelsConfig` and `ModelRegistry`. This covers | ||
| initial resolution, provider-backed models installed through `/auth`, manually | ||
| edited model providers, runtime model switches, and model-provider hot reloads | ||
| without persisting remotely supplied metadata into user settings. | ||
| The daemon workspace-provider status path uses the same catalog so model lists | ||
| shown before a session starts match the configuration used by live sessions. | ||
|
|
||
| ## Boundaries | ||
|
|
||
| - This change reads input modalities only. It does not import pricing, token | ||
| limits, reasoning flags, or the remote model list. | ||
| - It does not call provider-specific `/models` endpoints because their schemas | ||
| are not portable. Those endpoints can be added later as a higher-priority | ||
| source without changing the catalog interface. | ||
| - Unit tests disable the automatic network load and exercise the loader with | ||
| injected cache paths and fetch functions. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
packages/cli/src/serve/server/auth-provider-helpers.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| /** | ||
| * @license | ||
| * Copyright 2026 Qwen Team | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import { describe, expect, it } from 'vitest'; | ||
| import { buildAuthProviderCatalog } from './auth-provider-helpers.js'; | ||
|
|
||
| describe('buildAuthProviderCatalog', () => { | ||
| it('exposes preset modalities to daemon clients', () => { | ||
| const catalog = buildAuthProviderCatalog('/workspace'); | ||
| const minimax = catalog.providers.find( | ||
| (provider) => provider.id === 'minimax', | ||
| ); | ||
|
|
||
| expect( | ||
| minimax?.models?.find((model) => model.id === 'MiniMax-M3')?.modalities, | ||
| ).toEqual({ image: true, video: true }); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.