El fix anterior de Gemini (22efb9c) solo tocó providerDefaultURL, que usan
el chat/embeddings/whisper reales. TestAiConfigHandler (el botón "Probar
conexión" del panel de AI Config) tenía una tercera copia independiente del
mismo mapeo, sin caso para Gemini ni Deepseek — por eso el chat ya
funcionaba con Gemini pero la prueba de conexión seguía fallando.
Se exporta providerDefaultURL a services.ProviderDefaultURL y el controller
la reusa, en vez de mantener una copia más que se desactualiza cada vez que
se agrega un proveedor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Multi-tenant dentro de soft_usite, reutilizando la infraestructura ya
existente (AiConfig, motor de function-calling del agente de Telegram)
en vez de un servicio nuevo aparte:
- UmindTenant: sitio/cliente con dominios permitidos, config de IA para
el chat y personalidad/tono.
- Ingesta: crawler simple (mismo dominio, N páginas) + chunking +
embeddings (config global con módulo "umind_embeddings", pensada
para OpenAI ya que Claude no ofrece embeddings) guardados como JSON,
con búsqueda por similitud coseno en memoria (sin pgvector todavía).
- Agente acotado: única herramienta buscar_conocimiento, sin acceso a
nada interno — si no encuentra la respuesta, lo dice en vez de
inventar.
- Widget público (/widget/umind.js + /widget/:site_key/*), autenticado
por site_key + validación de dominio (Origin/Referer), no por
secreto, ya que la key viaja en el HTML público del sitio instalado.
- Panel /app/umind: tenants, estado de ingesta, historial de
conversaciones por sesión.