mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-07-10 01:29:17 +00:00
* fix(web-shell): encode vision model selection & polish picker Address Wenshao's review comments on #6209: [Critical] Encode vision model selection before persisting - handleVisionModelSelect now strips ACP (authType) suffix and stores as authType:modelId format expected by core's resolveVisionModelSelection() - Without this, picker selections silently fail to resolve when the same model ID appears on multiple providers [Suggestion] Add currentVisionModel derivation - Mirror currentVoiceModel pattern so the picker highlights the active vision model instead of falling back to the main model [Suggestion] Extract MODE_TITLE_KEY record for exhaustive dispatch - Replace duplicated 4-way ternary in App.tsx dialog title with a single Record<ModelDialogMode, string> lookup - Replace if/else if/else onSelect chain with a handlers record that would fail at compile time if a new mode is added without a handler [Suggestion] Add settings.label/description.visionModel i18n keys - Add to both EN and ZH locales so Chinese users see proper labels in the Settings dialog Files changed: - App.tsx: encoding fix, currentVisionModel, MODE_TITLE_KEY, handlers record - i18n.tsx: visionModel label + description (EN + ZH) * fix(web-shell): encode vision model selection & polish picker Address Wenshao's review comments on #6209: [Critical] Encode vision model selection before persisting - handleVisionModelSelect now strips ACP (authType) suffix and stores as authType:modelId format expected by core's resolveVisionModelSelection() - Without this, picker selections silently fail to resolve when the same model ID appears on multiple providers [Suggestion] Add currentVisionModel derivation - Mirror currentVoiceModel pattern so the picker highlights the active vision model instead of falling back to the main model [Suggestion] Extract MODE_TITLE_KEY record for exhaustive dispatch - Replace duplicated 4-way ternary in App.tsx dialog title with a single Record<ModelDialogMode, string> lookup - Replace if/else if/else onSelect chain with a handlers record that would fail at compile time if a new mode is added without a handler [Suggestion] Add settings.label/description.visionModel i18n keys - Add to both EN and ZH locales so Chinese users see proper labels in the Settings dialog Files changed: - App.tsx: encoding fix, currentVisionModel, MODE_TITLE_KEY, handlers record - i18n.tsx: visionModel label + description (EN + ZH) * fix(web-shell): address review comments for vision model picker encoding - Extract encodeVisionModelForSetting / decodeVisionModelForPicker into shared utils/modelEncoding.ts so they can be tested in isolation - Add 17 unit tests covering ACP encoding, colon-bearing IDs, empty parens passthrough, and round-trip identity - Memoize modelHandlers record with useMemo to avoid re-allocation on every model picker click - Replace dead fallback (?? 'main') — the outer modelDialogMode guard already ensures non-null, so use an explicit if-guard instead * test(web-shell): add edge-case tests for model encoding functions - Add passthrough tests for already-encoded colon format - Add malformed input tests (bare authType, unclosed paren, double-parens) - Add leadin-colon malformed input test for decode - Add empty string passthrough test - 23 encoding tests passing (up from 17), full suite: 735 passing * fix: PR #6236 follow-up — vision model encoding + fast model highlight - decodeVisionModelForPicker: strip \0baseUrl suffix before decoding to ACP - Remove dead encodeFastModelForSetting (fast picker strips ACP suffix before handler) - Add currentFastModel derivation + 'fast' branch to currentModelId ternary - Fix misleading voice handler comment (bare IDs, not ACP) - Replace unnecessary useMemo on modelHandlers with plain object Co-authored-by: atlarix-agent <agent@atlarix.dev> --------- Co-authored-by: Qwen3.6 Plus agent <agent@atlarix.dev>
33 lines
1.4 KiB
TypeScript
33 lines
1.4 KiB
TypeScript
/**
|
|
* Encodes a model ID from ACP format (modelId(authType)) to storage format
|
|
* (authType:modelId). Core's resolveVisionModelSelection() expects this format.
|
|
* If the input is not in ACP format, returns it unchanged.
|
|
*/
|
|
export function encodeVisionModelForSetting(modelId: string): string {
|
|
const match = modelId.match(/^(.+)\(([^()]+)\)$/);
|
|
return match ? `${match[2]}:${match[1]}` : modelId;
|
|
}
|
|
|
|
export function extractBareModelId(modelId: string): string {
|
|
const match = modelId.match(/^(.+)\(([^()]+)\)$/);
|
|
return match ? match[1] : modelId;
|
|
}
|
|
|
|
/**
|
|
* Decodes a stored model ID from authType:modelId format back to ACP format
|
|
* (modelId(authType)). Used for picker comparison where model IDs are in ACP
|
|
* format. Splits on the first colon — safe for colon-bearing model IDs
|
|
* (e.g., 'openai:gpt-4o:online' → 'gpt-4o:online(openai)').
|
|
* If the input has no colon, returns it unchanged.
|
|
*/
|
|
export function decodeVisionModelForPicker(storedValue: string): string {
|
|
// CLI stores custom-endpoint vision models as authType:modelId\0baseUrl.
|
|
// Strip the \0 suffix before decoding to ACP format.
|
|
const nullIdx = storedValue.indexOf('\0');
|
|
const selector = nullIdx >= 0 ? storedValue.slice(0, nullIdx) : storedValue;
|
|
const colonIdx = selector.indexOf(':');
|
|
if (colonIdx > 0) {
|
|
return `${selector.slice(colonIdx + 1)}(${selector.slice(0, colonIdx)})`;
|
|
}
|
|
return selector;
|
|
}
|