Resumen
Al pulsar el botón Guardar en Configuración de Proveedor (Local Provider y Vercel Gateway), los modelos previamente seleccionados desaparecen del selector del chat. No es solo una percepción de UX — el bug es reproducible en código: el handler dispara un re-sync que, ante un fetch vacío o fallido, sobrescribe provider.models con un array vacío.
Reproducción (Local Provider)
- Abrir Configuración de Proveedor → Local Provider.
- Configurar URL Base (ej.
http://localhost:11434 con Ollama corriendo). Pulsar Descubrir Modelos.
- En Modelos Disponibles, marcar algún modelo (ej.
qwen3:6). La selección se autoguarda correctamente (selectedModelIds y model.isSelected se actualizan).
- Escribir una API Key (opcional) en el campo correspondiente.
- Pulsar el botón Guardar.
- Ir al chat → el apartado de modelos locales no aparece / el modelo seleccionado se ha perdido.
Mismo patrón ocurre en Vercel Gateway tras pulsar Guardar.
Causa raíz
1) handleSave dispara un re-sync inmediato tras guardar credenciales:
src/renderer/pages/ModelPage/ProviderConfigs.tsx:117-123 (GatewayConfig):
const handleSave = async () => {
await updateProvider(provider.id, { apiKey, baseUrl });
if (apiKey) {
syncProviderModels(provider.id); // ← re-fetch tras guardar
}
};
src/renderer/pages/ModelPage/ProviderConfigs.tsx:189-197 (LocalConfig):
const handleSave = async () => {
await updateProvider(provider.id, {
baseUrl,
apiKey: apiKey.trim() || undefined,
});
if (baseUrl) {
syncProviderModels(provider.id); // ← re-fetch tras guardar
}
};
2) El re-sync sobrescribe provider.models sin proteger contra fetch vacío:
src/renderer/services/modelService.ts:748-770:
// Update provider models: combine synced models with user-defined models
provider.models = [...models, ...userDefinedModels]; // ← línea 750: reemplazo incondicional
// Only update selectedModelIds if we actually got new models from sync
// This prevents losing saved selections when sync fails or returns empty
if (models.length > 0) {
provider.selectedModelIds = provider.models.filter(m => m.isSelected).map(m => m.id);
this.syncedProvidersInSession.add(provider.id);
}
else if (userDefinedModels.length > 0) {
// ...preserva selectedModelIds...
}
// If sync returned empty and no user-defined, preserve existing selectedModelIds
// (don't clear them - they'll be restored when sync succeeds later)
El comentario indica intención de "preservar selecciones" cuando el sync falla, y la lógica protege selectedModelIds. Pero la línea 750 ya ejecutó provider.models = [] antes de ese chequeo, por lo que el array de modelos disponibles queda vacío.
3) _saveProviders luego persiste el array vacío:
src/renderer/services/modelService.ts:815-837 filtra provider.models por selectedIdSet, y como provider.models ya está vacío, persiste models: [] en ui-preferences.json. El selector del chat lee provider.models, por lo que el usuario no ve ningún modelo.
Casos en que el fetch devuelve vacío / falla
- Local provider con Ollama/LM Studio cuando se añade una API Key que el endpoint no espera (algunos devuelven 401, otros responden vacío).
- Endpoint local momentáneamente no disponible cuando se pulsa Guardar.
- Cualquier error transitorio de red en Vercel Gateway.
En todos estos casos el comportamiento esperado sería mantener el estado anterior, no vaciar provider.models.
Reportes de usuarios
"Recién me descargue la nueva versión, pero veo que no me guarda el modelo local cuando lo configuro, me reconoce los modelos, selecciono el que quiero pero no guarda esa información, y al ir al chat no me aparecen el apartado de modelos locales."
"Ahhh, ya vi el error, que cuando le doy a guardar me quita el modelo que tenía seleccionado."
Propuestas de fix
Por orden de preferencia:
-
(Preferida) Eliminar el re-sync automático tras guardar credenciales. El usuario ya dispone del botón Descubrir Modelos / Sync explícito. Guardar credenciales no debería tener efectos colaterales sobre la lista de modelos.
-
Si se mantiene el auto-sync, proteger provider.models en modelService.ts:750:
// Solo reemplazar si el fetch devolvió modelos
if (models.length > 0) {
provider.models = [...models, ...userDefinedModels];
} else if (userDefinedModels.length > 0) {
// Mantener los modelos no-userDefined existentes y refrescar los user-defined
const nonUserDefined = provider.models.filter(m => !m.userDefined);
provider.models = [...nonUserDefined, ...userDefinedModels];
}
// si ambos están vacíos: no tocar provider.models
-
Surface del error: cuando el fetch post-Guardar falla, mostrar un toast/alert explícito ("No se pudieron sincronizar modelos: [razón]. Tu selección anterior se mantiene.") en lugar de fallar silenciosamente.
-
(UX, complementaria) Renombrar el botón a algo más específico — Guardar credenciales o Guardar API Key — para reforzar que su scope es solo URL/API Key. Añadir hint sobre que la selección de modelos se autoguarda.
Criterios de aceptación
Archivos involucrados
src/renderer/pages/ModelPage/ProviderConfigs.tsx — handlers handleSave (líneas 117-123, 189-197).
src/renderer/services/modelService.ts — _doSyncProviderModels (línea 750), _saveProviders (líneas 795-872).
src/renderer/stores/modelStore.ts — toggleModelSelection, syncProviderModels.
Versión objetivo
v1.8.3
Resumen
Al pulsar el botón Guardar en Configuración de Proveedor (Local Provider y Vercel Gateway), los modelos previamente seleccionados desaparecen del selector del chat. No es solo una percepción de UX — el bug es reproducible en código: el handler dispara un re-sync que, ante un fetch vacío o fallido, sobrescribe
provider.modelscon un array vacío.Reproducción (Local Provider)
http://localhost:11434con Ollama corriendo). Pulsar Descubrir Modelos.qwen3:6). La selección se autoguarda correctamente (selectedModelIdsymodel.isSelectedse actualizan).Mismo patrón ocurre en Vercel Gateway tras pulsar Guardar.
Causa raíz
1)
handleSavedispara un re-sync inmediato tras guardar credenciales:src/renderer/pages/ModelPage/ProviderConfigs.tsx:117-123(GatewayConfig):src/renderer/pages/ModelPage/ProviderConfigs.tsx:189-197(LocalConfig):2) El re-sync sobrescribe
provider.modelssin proteger contra fetch vacío:src/renderer/services/modelService.ts:748-770:El comentario indica intención de "preservar selecciones" cuando el sync falla, y la lógica protege
selectedModelIds. Pero la línea 750 ya ejecutóprovider.models = []antes de ese chequeo, por lo que el array de modelos disponibles queda vacío.3)
_saveProvidersluego persiste el array vacío:src/renderer/services/modelService.ts:815-837filtraprovider.modelsporselectedIdSet, y comoprovider.modelsya está vacío, persistemodels: []enui-preferences.json. El selector del chat leeprovider.models, por lo que el usuario no ve ningún modelo.Casos en que el fetch devuelve vacío / falla
En todos estos casos el comportamiento esperado sería mantener el estado anterior, no vaciar
provider.models.Reportes de usuarios
Propuestas de fix
Por orden de preferencia:
(Preferida) Eliminar el re-sync automático tras guardar credenciales. El usuario ya dispone del botón Descubrir Modelos / Sync explícito. Guardar credenciales no debería tener efectos colaterales sobre la lista de modelos.
Si se mantiene el auto-sync, proteger
provider.modelsenmodelService.ts:750:Surface del error: cuando el fetch post-Guardar falla, mostrar un toast/alert explícito ("No se pudieron sincronizar modelos: [razón]. Tu selección anterior se mantiene.") en lugar de fallar silenciosamente.
(UX, complementaria) Renombrar el botón a algo más específico —
Guardar credencialesoGuardar API Key— para reforzar que su scope es solo URL/API Key. Añadir hint sobre que la selección de modelos se autoguarda.Criterios de aceptación
provider.modelsy en el selector del chat.Archivos involucrados
src/renderer/pages/ModelPage/ProviderConfigs.tsx— handlershandleSave(líneas 117-123, 189-197).src/renderer/services/modelService.ts—_doSyncProviderModels(línea 750),_saveProviders(líneas 795-872).src/renderer/stores/modelStore.ts—toggleModelSelection,syncProviderModels.Versión objetivo
v1.8.3