Resumen de Cambios Implementados
Backend v1.2.1
Mejoras en gestión de API keys multi-proveedor:
Nuevo endpoint /api/ai/api-keys: Retorna todas las API keys guardadas por proveedor (enmascaradas para seguridad)
Formato: {"openai": {"has_key": true, "masked_key": "sk-proj...xyz", "is_active": false}}
Solo administradores pueden acceder
Endpoint /api/ai/configuration mejorado:
Ahora preserva API keys existentes cuando se cambia de proveedor
Si ya existe configuración para un proveedor, solo actualiza el modelo y activa ese proveedor
Solo requiere API key nueva si no existe configuración previa para ese proveedor
Validación: no acepta API keys vacías para nuevos proveedores
Persistencia de configuraciones:
Cada proveedor (OpenAI, Anthropic, Gemini) mantiene su registro en la base de datos
Solo uno tiene is_active=True a la vez
Al cambiar de proveedor, se desactiva el anterior pero NO se elimina
Frontend v1.2.6
UX mejorada para configuración de IA:
Indicadores visuales en botones de proveedor:
Badge "✓ ACTIVO" en verde para el proveedor actualmente activo
Badge "Configurado" en gris para proveedores con API key guardada pero inactivos
Sin badges para proveedores no configurados
Selector de modelos inteligente:
Solo muestra modelo seleccionado si el proveedor está activo
Al hacer click en un proveedor inactivo, NO se pre-selecciona ningún modelo
Solo al GUARDAR se activa el proveedor con el modelo seleccionado
Input de API key con contexto:
Muestra key enmascarada si ya existe: ✓ Ya tienes una API key guardada: sk-proj...xyz
Permite dejar vacío para mantener la key actual
Solo requiere key nueva si el proveedor no tiene una guardada
Flujo de trabajo mejorado:
Click en proveedor → Cambia tab de formulario
Si ya tiene key guardada → Se muestra enmascarada, puede mantenerla
Seleccionar modelo → Click en "Guardar Configuración"
Solo entonces se ACTIVA ese proveedor y modelo
Beneficios
No re-ingresar API keys: Al cambiar entre proveedores, las keys se preservan
Claridad visual: Solo el proveedor activo muestra badge verde y modelo seleccionado
Seguridad: API keys enmascaradas en la UI (sk-proj...xyz)
Flexibilidad: Configurar los 3 proveedores y cambiar entre ellos sin perder configuración
Versiones actualizadas:
Backend: 1.2.0 → 1.2.1
Frontend: 1.2.5 → 1.2.6
Service Worker: cache v1.2.6
This commit is contained in:
@@ -276,7 +276,7 @@ def extract_pdf_text_smart(pdf_content: bytes, max_chars: int = None) -> dict:
|
||||
}
|
||||
|
||||
|
||||
BACKEND_VERSION = "1.2.0"
|
||||
BACKEND_VERSION = "1.2.1"
|
||||
app = FastAPI(title="Checklist Inteligente API", version=BACKEND_VERSION)
|
||||
|
||||
# S3/MinIO configuration
|
||||
@@ -2782,20 +2782,50 @@ def get_ai_configuration(
|
||||
return config
|
||||
|
||||
|
||||
@app.get("/api/ai/api-keys")
|
||||
def get_all_api_keys(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: models.User = Depends(get_current_user)
|
||||
):
|
||||
"""Obtener todas las API keys guardadas (sin mostrar las keys completas)"""
|
||||
if current_user.role != "admin":
|
||||
raise HTTPException(status_code=403, detail="Solo administradores pueden ver API keys")
|
||||
|
||||
configs = db.query(models.AIConfiguration).all()
|
||||
|
||||
result = {}
|
||||
for config in configs:
|
||||
# Solo devolver si tiene API key guardada (enmascarada)
|
||||
if config.api_key:
|
||||
masked_key = config.api_key[:8] + "..." + config.api_key[-4:] if len(config.api_key) > 12 else "***"
|
||||
result[config.provider] = {
|
||||
"has_key": True,
|
||||
"masked_key": masked_key,
|
||||
"is_active": config.is_active
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@app.post("/api/ai/configuration", response_model=schemas.AIConfiguration)
|
||||
def create_ai_configuration(
|
||||
config: schemas.AIConfigurationCreate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: models.User = Depends(get_current_user)
|
||||
):
|
||||
"""Crear o actualizar configuración de IA"""
|
||||
"""Crear o actualizar configuración de IA - ACTIVA el proveedor seleccionado"""
|
||||
if current_user.role != "admin":
|
||||
raise HTTPException(status_code=403, detail="Solo administradores pueden configurar IA")
|
||||
|
||||
# Desactivar configuraciones anteriores
|
||||
# Desactivar TODAS las configuraciones
|
||||
db.query(models.AIConfiguration).update({"is_active": False})
|
||||
|
||||
# Determinar modelo por defecto según el proveedor si no se especifica
|
||||
# Buscar si ya existe configuración para este proveedor
|
||||
existing_config = db.query(models.AIConfiguration).filter(
|
||||
models.AIConfiguration.provider == config.provider
|
||||
).first()
|
||||
|
||||
# Determinar modelo por defecto si no se especifica
|
||||
model_name = config.model_name
|
||||
if not model_name:
|
||||
if config.provider == "openai":
|
||||
@@ -2807,19 +2837,31 @@ def create_ai_configuration(
|
||||
else:
|
||||
model_name = "default"
|
||||
|
||||
# Crear nueva configuración
|
||||
new_config = models.AIConfiguration(
|
||||
provider=config.provider,
|
||||
api_key=config.api_key,
|
||||
model_name=model_name,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
db.add(new_config)
|
||||
db.commit()
|
||||
db.refresh(new_config)
|
||||
|
||||
return new_config
|
||||
if existing_config:
|
||||
# Actualizar configuración existente
|
||||
# Solo actualizar API key si se proporciona una nueva (no vacía)
|
||||
if config.api_key and config.api_key.strip():
|
||||
existing_config.api_key = config.api_key
|
||||
existing_config.model_name = model_name
|
||||
existing_config.is_active = True # Activar este proveedor
|
||||
db.commit()
|
||||
db.refresh(existing_config)
|
||||
return existing_config
|
||||
else:
|
||||
# Crear nueva configuración (requiere API key)
|
||||
if not config.api_key or not config.api_key.strip():
|
||||
raise HTTPException(status_code=400, detail="API key es requerida para nuevo proveedor")
|
||||
|
||||
new_config = models.AIConfiguration(
|
||||
provider=config.provider,
|
||||
api_key=config.api_key,
|
||||
model_name=model_name,
|
||||
is_active=True # Activar este proveedor
|
||||
)
|
||||
db.add(new_config)
|
||||
db.commit()
|
||||
db.refresh(new_config)
|
||||
return new_config
|
||||
|
||||
|
||||
@app.put("/api/ai/configuration/{config_id}", response_model=schemas.AIConfiguration)
|
||||
|
||||
Reference in New Issue
Block a user