Novedades · Changelog

Cada semana, un poco mejor.

Mejoramos GarBotGPT casi a diario. Estas son las novedades más recientes: nuevas herramientas, mejoras de velocidad y arreglos, contadas en claro.

  1. v8.77.0

    🛠 Tab Herramientas: +10 tools que faltaban (video gen/analysis, OCR, slides, quiz, etc.)

    Tab Herramientas tenía solo 13 cards pero el código real soporta 23. Añadidas: Generar Video (Runway/Sora/Veo), Analizar Video, OCR documentos, Generar Presentación, Mapa Mental, Crear Quiz, Reproductor música, App Builder, Imagen→Código, Resumir YouTube. Mismo grid bonito, mismas bulk actions.

    Nuevo

    • 🎬 video_generation (Runway, Sora, Veo, Luma)
    • 🎞 video_analysis (transcript Whisper + 6 frames + resumen vision)
    • 📷 ocr_mode (Tesseract.js — fotos, escaneos, tickets)
    • 🖼 slides_generation (.pptx con maquetación automática)
    • 🧠 mind_map (Mermaid mindmap inline)
    • 📝 quiz_generation (cuestionarios con explicación)
    • 🎵 music_player (reproductor cinemático embebido)
    • 🚀 app_builder (mini-apps HTML como artifact)
    • 📸 image_to_code (screenshot → React + Tailwind)
    • 📺 youtube_summary (URL → transcript + resumen + capítulos)
    • 🛡 toolMap en /api/chat actualizado con las 23 tools para enforcement server-side

    Seguridad

    • 🆕 ALL_TOOL_IDS y TOOL_LABELS en UserRoleManagement actualizados (modal permisos por user incluye las nuevas)
  2. v8.76.0

    🌐 Landing actualizada con features reales (artifacts · agentes · self-hosting · status)

    Bento grid de la landing extendido con todo lo añadido v8.70-v8.75: Artifacts tipo Canvas, Document Generation Card, Agentes autónomos con scheduler, Roles+permisos granulares, Mis Archivos, análisis vídeo/OCR, self-hosting completo (Supabase + NAS) y status page propio. Stats actualizados a 20+ modelos, 13 tools, 8 OAuth.

    Nuevo

    • 📊 Stats: 15+ → 20+ modelos, 14 → 13 tools (real count), 6 → 8 OAuth providers, +"Self-hosting disponible"
    • 🖼 Imports añadidos: Activity, HardDrive, Server, Shield (lucide-react)

    Mejorado

    • 🎨 Descripciones actualizadas: "13 tools en vivo", "20+ modelos", "OAuth Google/Microsoft/Spotify/GitHub/Monday — la IA actúa por ti"
    • 🌈 Nueva paleta indigo para BentoCard

    Seguridad

    • 🆕 Cards bento añadidas: Artifacts (Canvas), Generación de documentos, Agentes autónomos, Roles y permisos, Mis archivos, Self-hosting completo, Status page propio
  3. v8.75.0

    📄 DocumentGenerationCard — card desde el inicio (como ImageGenerationCard)

    Cuando activas generación de docx/pdf/xlsx/pptx, ya no ves todo el texto markdown seguido del archivo al final. Ahora aparece una card con animación desde el inicio del request, frases rotativas de progreso, y al terminar muestra el archivo final con botones Descargar / Abrir. El texto markdown queda oculto (el contenido está dentro del archivo descargable).

    Nuevo

    • 🆕 Tipos según formato: docx=azul, pdf=rosa, xlsx=verde, pptx=naranja, html=violeta, json=amber
    • 📡 MessageBubble intercepta el evento en el stream y actualiza el store
    • 💾 meta_json.generated_document persistido en el message para que la card se re-renderice al recargar conversation
    • 🙈 Cuando hay generatedDocMeta, displayContent se sobrescribe a un mensaje corto ("Aquí tienes tu X 👇") — el texto markdown completo NO se muestra (está dentro del archivo)

    Mejorado

    • 🆕 Store ui: DocumentGenerationRun + setDocumentGenerationRun + clearDocumentGenerationRun
    • 🎨 ChatArea muestra DocumentGenerationCard efímera durante el run, MessageBubble la persistente al recargar

    Arreglado

    • 🆕 Componente DocumentGenerationCard con states running/ready/error, frases rotativas, progress bar
    • 🛰 SSE event document_generation_event (running al inicio + ready/error al final) inyectado en /api/chat
  4. v8.74.0

    🔧 5 fixes: voz · banner · preview pptx · títulos IA · enforcement cuota/tools

    Lote de hotfixes: arregla modo voz roto (modelo deprecated), banner que se solapaba con el header, preview de pptx con UI clara, títulos de documentos generados con IA en vez del prompt literal, y enforcement server-side de cuota mensual de tokens y tools deshabilitadas.

    Nuevo

    • 📢 Banner: ahora se renderiza ENCIMA del header (era debajo y se solapaba con el selector de modelo)
    • 📊 Preview pptx/zip/binarios: card centrada con icono, info del archivo, botón Descargar prominente y Abrir en nueva pestaña
    • 🤖 Títulos de documentos generados con IA: nueva función generateSmartDocumentTitle() en document-export.ts (gpt-4o-mini, response_format json_object). Ej: "hazme presentación michael jackson" → título "Michael Jackson: Rey del Pop" + slug "michael-jackson-rey-del-pop"
    • 🛡 Enforcement server-side: /api/chat valida quotaProfile, bloquea suspended/pending con 423, devuelve 429 si supera monthly_token_limit del mes, fuerza false en tool flags que el user tiene en disabled_tools
    • 🆕 lib/server/quota.ts: helpers getUserMonthlyTokenUsage(), checkUserQuota(), userCanUseToolServer(), userCanUseModelServer()

    Arreglado

    • 🎙 Modo voz: modelo pinned a gpt-4o-mini-realtime-preview-2024-12-17, voice "marin" → "alloy", mejor reporting de error OpenAI
  5. v8.73.0

    🛠 Tab Roles+Permisos en admin · Tab Tools reescrito · Mis Archivos página propia

    Tres tabs nuevas/reescritas en panel admin y la página dedicada Mis Archivos en el menú de usuario. Roles y Permisos consolida la gestión completa del sistema RBAC nuevo (cambio de rol, suspensión con razón/fecha, permisos por feature, dominios permitidos, audit log global). Tools reescrito desde cero con grid visual y bulk actions. Mis Archivos da al usuario página propia para ver/descargar/renombrar/eliminar/reintentar sus archivos.

    Nuevo

    • 🔁 Tab admin "Herramientas" reescrita completa — grid de 13 tools con bulk actions (bloquear/desbloquear para todos)
    • 🆕 Endpoint GET /api/admin/tools con resumen + lista users bloqueados por tool
    • 🆕 Endpoint POST /api/admin/tools/[id]/bulk action=block_all|unblock_all
    • 📂 Página /my-files con filtros (todos/indexados/procesando/fallidos), búsqueda, polling auto
    • 🔧 Endpoints: GET /api/files (lista), DELETE /api/files/[id], PATCH /api/files/[id] (rename)
    • Links "Mis archivos" + "Admin" en ambos menús del sidebar (collapsed y full)
    • Signup totalmente abierto: cualquier email no listado → role=user automático (confirmado en v8.72.0)

    Seguridad

    • 🆕 Tab admin "Roles y Permisos" — sub-tabs Usuarios / Dominios permitidos / Audit log global
    • 🆕 Modales: cambiar rol, suspender (con razón y fecha hasta), permisos por feature (tools/models/cuota), audit log
  6. v8.72.0

    ⚡ Performance: Vercel→Frankfurt + polling reducido + índices + signup abierto

    Optimización de latencia tras migrar Supabase a self-hosted en NAS (Madrid). Vercel ahora despliega en Frankfurt (fra1) para estar cerca del NAS. Polling de presencia reducido 50%. Cache HTTP en /api/tools/permissions. Índices estratégicos en mensajes/conversations/token_usage. Signup ahora abierto: cualquier email se da de alta como user (los dominios listados siguen forzando rol específico).

    Nuevo

    • use-user-activity: heartbeat 30s→60s, check 15s→30s, idle 2min→3min, gap 8s→15s (-50% requests)
    • 🗂 Migración 088: índices en conversations(user_id, updated_at), messages(conv, created), token_usage(user, created), status_checks(service, checked), user_activity_sessions(user, last)
    • 🧹 VACUUM ANALYZE en messages/message_versions/token_usage/conversations/user_activity_sessions
    • 🌐 Signup abierto: trigger handle_new_user_with_domain_check ahora asigna user por defecto (no pending) para dominios no listados

    Mejorado

    • 🌍 Vercel region → fra1 (Frankfurt) — reduce latencia Vercel↔NAS de ~150ms a ~30ms
    • 🔍 Diagnóstico: DB es minúscula (1.5MB tabla más grande), problema era latencia red US↔EU + cold starts Vercel

    Seguridad

    • 💾 /api/tools/permissions: Cache-Control private max-age=60 (era no-cache)
  7. v8.71.0

    🔐 Roles v2 — audit log + dominios + permisos por feature + middleware admin

    Sobre el sistema simple v8.70.0 (profiles.role admin|user), añadimos: rol pending, auto-aprobación por dominio email, audit log trazable, permisos por user (disabled_tools, disabled_models, monthly_token_limit), middleware que bloquea /admin/* a no-admins y a usuarios suspendidos o pending.

    Nuevo

    • 🆕 Rol pending para usuarios cuyo email no está en la lista blanca de dominios
    • 🌐 Tabla allowed_email_domains: signup auto-asigna role (o pending) según el dominio
    • 🛡 Middleware bloquea /admin/* y /api/admin/* si role!=admin; bloquea todo para suspended/pending
    • 🔧 verifyAdmin() ahora también valida suspended y devuelve profile completo
    • 🆕 verifyActiveUser() helper para endpoints no-admin
    • 🆕 Endpoints: GET /api/admin/users/[id]/audit, GET/POST/PATCH/DELETE /api/admin/email-domains
    • 🆕 PATCH /api/admin/users acepta disabled_tools/disabled_models/monthly_token_limit y registra audit
    • 🧹 getUserModelAccessScope respeta disabled_models (lista negra)
    • Migración 087 aplicada en NAS + cloud, seed gesem.es y garbotgpt.com como dominios permitidos

    Seguridad

    • 📝 Tabla role_audit_log + función log_role_action: trazabilidad de cambios de rol/suspensión/permisos
    • 🛠 Permisos por feature en profiles: disabled_tools[], disabled_models[], monthly_token_limit
    • 🧹 /api/tools/permissions respeta disabled_tools del profile del user
  8. v8.70.0

    🔐 Sistema de roles simplificado — fuente única profiles.role

    Eliminado por completo el RBAC granular (roles, user_roles, role_permissions) que coexistía sin sincronización con profiles.role y generaba huecos de seguridad. Ahora la única fuente de verdad es profiles.role enum (admin | user). Admin tiene acceso total; user accede a todo excepto el panel admin.

    Nuevo

    • 🚮 Borrados 4 endpoints /api/admin/roles/* + componente RolesManagement.tsx
    • 🧹 model-configs.ts: simplificado getUserModelAccessScope (admin = todo, user = todo)
    • 🧹 /api/admin/users/create: dejó de insertar en user_roles, sólo profiles.role
    • 🛡️ Restaurado CHECK constraint en profiles.role (sólo admin o user) + default user
    • Migración 086_drop_rbac_system aplicada en NAS + cloud

    Seguridad

    • 🚮 Borradas 3 tablas (roles, user_roles, role_permissions) + 2 funciones PG (user_has_permission, get_user_accessible_resources)
    • 🚮 Quitada tab "Roles y Permisos" del panel admin (AdminPageClient + ModernAdminPageClient + ModernAdminLayout)
    • 🧹 /api/tools/permissions: ahora cualquier user autenticado ve todas las tools
  9. v8.69.1

    🩺 Status page: arreglados falsos positivos de Supabase Auth/Storage + threshold web

    Los checks de Supabase Auth y Storage estaban marcados como caídos siendo falsos positivos (faltaba el header apikey en el ping). El cron ahora lo inyecta automáticamente para URLs *.supabase.co, Storage usa /storage/v1/version (público) y el threshold de la app web sube a 3000ms degraded / 10000ms down para no penalizar cold-starts de Vercel.

    Nuevo

    • 🔑 Cron auto-inyecta header apikey + Authorization Bearer para URLs *.supabase.co usando NEXT_PUBLIC_SUPABASE_ANON_KEY
    • 🛠 Supabase Storage URL: /storage/v1/bucket → /storage/v1/version (público, sin auth)
    • 🛠 Supabase Auth expected_status: [200] → [200, 401] (defensivo si la anon key no está en env)
    • Web app threshold: degraded 1500ms → 3000ms, down 5000ms → 10000ms (Vercel cold start típico)
    • 🧹 Migration 085 auto-resuelve los incidents falsos abiertos sobre estos 3 servicios
  10. v8.69.0

    🤖 Sistema de Agentes — refactor completo (planner + toolchain real)

    Reescritura completa del executor de agentes: planner con JSON validado, toolchain real (web_search + browse_url + db_query), límites de pasos y timeout configurables, traza estructurada por step, y summarizer dinámico sin hardcoding.

    Nuevo

    • 🚮 Quitado prompt hardcoded "FC Barcelona" del summarizer — ahora 100% genérico basado en agent.goal
    • 🛡️ Plan JSON validado con schema + fallback a single-step summary si falla el planner
    • ⏱️ max_steps (default 10, hard cap 25) y step_timeout_ms (default 20s) configurables vía agent.config_json
    • 🚫 code_interpreter explícito como "no soportado en serverless" en vez de stub silencioso
    • 🤖 Summarizer dinámico — instruido por agent.goal + step.text, formato pedido por el usuario (tabla/lista/JSON/informe)
    • 🛡️ db_query con lista blanca de tablas + force-filter user_id (incluso con service role) — nunca puede leer otros usuarios

    Mejorado

    • JSON mode en OpenAI planner para garantizar parseo limpio

    Arreglado

    • Try/catch por step — un fallo en un paso no aborta toda la ejecución, continúa
    • 📋 Trace estructurado (acción, ms, ok/error, preview) guardado en agent_executions.result como <details> colapsable

    Seguridad

    • 🔧 Tools reales en agentes: web_search (Tavily), browse_url (HTML fetch+strip), db_query (SELECT con safelist + RLS por user_id)
  11. v8.68.1

    🐛 Hotfix: build Vercel fallaba por className multi-línea en RewriteMenu

    Turbopack no parseaba el className multi-línea del dropdown combinado con <style jsx global>. Colapsado a una sola línea.

    Nuevo

    • Collapsed className del dropdown a una sola línea — mismas clases, mismo render

    Arreglado

    • 🐛 Turbopack (Next.js 16.1.6) no parseaba className multi-línea junto con <style jsx global>
  12. v8.68.0

    🐛 Fix: header "Reescribir para…" mostraba barra rara

    Bug visual reportado por el usuario: el header del dropdown "Reescribir para…" se veía mal — aparecía como una barra vertical extraña al lado del texto, parecía que faltaba la primera letra. Causa: el emoji ✨ (U+2728 SPARKLES) combinado con CSS `uppercase` + `tracking-wider` + `text-[10px]` se renderizaba con un glifo "compacto" raro en algunos sistemas/fuentes, parecido a una barra. Fix: reemplazar el emoji por un icono Lucide `<Sparkles>` que se renderiza limpio en todos los sistemas (es SVG, no depende de fuente emoji). De paso aplicado el styling premium de los otros dropdowns (rounded-[18px] + liquid glass + sombra multicapa + items con rounded interno + animación cubic-bezier de Apple).

    Nuevo

    • rounded-[18px] (antes rounded-xl) + sombra multicapa con highlight superior
    • Items con mx-1.5 + rounded-[10px] hover + active:scale-[0.98] (consistente con sidebar)
    • Animación 160ms cubic-bezier(0.22,0.9,0.24,1) (antes 150ms ease-out)

    Mejorado

    • Dropdown rediseñado con liquid glass (backdrop-blur-2xl saturate-150)
    • 🎨 Dark mode con bg-zinc-900/85 + border-white/[0.08]
    • 🎨 Hover violet (bg-violet-50/80 light, bg-violet-500/15 dark)

    Arreglado

    • 🐛 Emoji ✨ + uppercase + tracking-wider se renderizaba como barra rara — reemplazado por <Sparkles> Lucide
  13. v8.67.0

    🔔 Notificaciones browser para assignments + coalescer polling de colaboración

    Doble entrega que activa la dimensión "real" de la colaboración. (1) Notificaciones del navegador cuando alguien te asigna un mensaje en un chat compartido. Nuevo listener AssignmentNotificationsListener montado en ChatShell que se suscribe via Realtime a conversation_message_assignments filtrado por tu user_id. Muestra notificación con nombre del asignador + preview del mensaje + nota; click navega al chat. Anti-doble-notif y skip si ya estás en el chat. (2) Coalescer polling: el hook useConversationCollaboration polleaba /collaboration cada 2.5s para detectar cambios en presence/live_runs/read_receipts. Migración 084 añade esas tablas al supabase_realtime publication; ahora el hook se suscribe via postgres_changes con debounce 250ms y dispara refresh inmediato. Polling de safety net subido a 30s (antes 2.5s) — reduce ~80% queries DB sin perder responsividad.

    Nuevo

    • 🔔 Nuevo: AssignmentNotificationsListener (Realtime + browser notification)
    • 🔔 Notif body con preview del mensaje (120 chars) + nota del asignador
    • 🔔 Click en notificación → router.push(/chat/[id]) + window.focus
    • 🛡️ Anti-doble-notif por ID + skip si ya estás viendo el chat
    • 🛡️ Skip self-assignments (assigned_by === assigned_to)
    • 📡 Migración 084: presence, read_receipts, live_runs, assignments, reactions al supabase_realtime publication
    • 📉 ~80% menos queries DB sobre /collaboration (antes 2.5s → ahora 30s con realtime push)

    Mejorado

    • useConversationCollaboration: suscripción Realtime + debounce 250ms + polling fallback 30s

    Arreglado

    • 🔄 Tras CHANNEL_ERROR/TIMED_OUT/CLOSED log warning y polling sigue como safety net
  14. v8.66.0

    🎵 Spotify Now Playing en Welcome + 5 fixes chats compartidos

    Doble entrega. (1) El indicador de Spotify "lo que estás escuchando ahora" que estaba en el menú de usuario del Header se extiende a la página Welcome con un look más visual (cover 64px con glow verde pulsante, barras EQ animadas, barra de progreso live mm:ss). Hook reutilizable `useSpotifyNowPlaying` consolida la lógica antes duplicada en Header y MobileHeader. (2) Sistema de chats compartidos: migración 083 consolida `shared_chats` (existía en prod pero no en repo — bomba de relojería); ParticipantsList.tsx muerto eliminado; beacon DELETE de presence con `keepalive: true` al cerrar pestaña; MessageReactions enchufadas al MessageBubble en chats compartidos (componente que existía pero estaba huérfano).

    Nuevo

    • 🎵 Hook reutilizable src/hooks/use-spotify-now-playing.ts (consolida Header + MobileHeader)
    • 🎵 SpotifyNowPlayingCard: cover 64px con glow verde pulsante + 5 barras EQ + progreso live + tiempo mm:ss
    • 🎵 Integrado en WelcomeScreen (solo aparece si hay música sonando, sin ser intrusivo)
    • 🧹 ParticipantsList.tsx eliminado (componente huérfano con TODO "en desarrollo")
    • 🔌 fetch DELETE con keepalive:true en pagehide/beforeunload → presence se limpia incluso si cierras pestaña

    Mejorado

    • Tick local de 1s en SpotifyNowPlayingCard actualiza la barra de progreso entre polls (sin extra API calls)

    Seguridad

    • 🛡️ Migración 083: shared_chats con RLS public SELECT + owner write (era ghost table sin migration)
    • 😀 MessageReactions enchufadas al MessageBubble (chats compartidos con write permission)
  15. v8.65.0

    📁 Menú de opciones en cada carpeta del sidebar

    Cada carpeta del sidebar ahora tiene un botón de 3-puntos (visible on-hover) que abre un menú dropdown con todas las operaciones comunes: Abrir espacio, Nuevo chat aquí, Renombrar, Marcar/Quitar favorita, Configurar carpeta (abre FolderSettingsModal), Eliminar (con confirm dialog rojo). Antes había que ir a Settings de la carpeta para hacer cualquier cosa, ahora 1 click. El menú reutiliza el mismo estilo premium del dropdown de chats (rounded-[18px] + liquid glass + sombra multicapa). Renombrar es inline: pulsas Renombrar y el nombre se convierte en input editable. Doble-click sobre el nombre también activa renombrar.

    Nuevo

    • 📁 Botón MoreHorizontal (3-puntos) on-hover en cada FolderBlock
    • 📁 6 acciones: Abrir espacio · Nuevo chat aquí · Renombrar · Marcar favorita · Configurar · Eliminar
    • 📁 Dropdown con rounded-[18px] + glass + animación 160ms cubic-bezier (igual que ChatRow)
    • 📁 Renombrar inline: input editable con auto-select on focus + Escape cancela
    • 📁 Double-click en el nombre activa renombrar (atajo)
    • 📁 Indicator estrella amber junto al contador cuando is_favorite
    • 🛡️ Eliminar pide confirmación con ConfirmDialog rojo (los chats NO se eliminan, solo se sacan)
    • ⚙️ Configurar abre FolderSettingsModal (lazy-loaded con dynamic import)

    Seguridad

    • 🛡️ Todas las operaciones via supabase client con RLS (no necesita endpoint custom)
  16. v8.64.0

    📂 Pipeline de documentos: 11 mejoras (Paquete A+B)

    Re-trabajo a fondo del sistema de análisis de documentos al subir. 11 mejoras de impacto real, varias arreglan bugs serios. (1) Embeddings con batching REAL: antes mandaba 1 texto por HTTP request, ahora envía hasta 100 por request → ingest de PDF de 200 chunks pasa de 200 round-trips a 2 (~50× más rápido + más barato). (2) Retry con jitter exponencial (antes lineal sin jitter → thundering herd). (3) Skip re-ingest si content_hash unchanged (antes pagaba embeddings duplicados). (4) Atomic chunk replacement: nuevos antes de borrar viejos (antes DELETE→INSERT, fallo a mitad dejaba orphan failed sin chunks). (5) LLM analysis skip si hash unchanged. (6) Branch image/* en extractor con OCR automático (antes "Unsupported file type" → failed). (7) Whitelist ingestable unificada cliente/server (antes el cliente skipea xlsx/pptx/odt/etc.). (8) Server-side auto-ingest usando flag SERVER_AUTO_RAG_INGEST_ON_UPLOAD que estaba declarado pero sin usar. (9) FileLibrary: polling status cada 3s mientras procesa. (10) FileLibrary: tooltip de ingest_error + retry button rojo. (11) FileLibrary: upload via /api/files/upload (antes bypassaba MIME validation + size cap).

    Nuevo

    • 🛡️ #3 Skip re-ingest si full_content_hash === previousHash (ahorra dinero)
    • 🛡️ #7 Atomic chunk replacement: INSERT nuevos → DELETE viejos por ID (no más orphan failed)
    • 🛡️ #18 LLM analysis skip si hash no cambió
    • 📸 #4 Imágenes con OCR automático (tesseract.js, antes throw Unsupported)
    • 🔗 #6 isIngestableFile() unificado en cliente y servidor
    • 🚀 #17 SERVER_AUTO_RAG_INGEST_ON_UPLOAD activa ingest en fire-and-forget tras upload
    • 👁️ #9 FileLibrary: polling 3s mientras queued/processing → badge live

    Mejorado

    • #1 Embeddings batch real: 100 textos/request en vez de 1 (10-100× menos latencia/coste)
    • #15 Backoff exponencial con jitter (Math.pow(2,attempt) + Math.random()×0.3)

    Arreglado

    • 🚨 #10 FileLibrary: tooltip negro con ingest_error + AlertCircle + retry button rojo si failed

    Seguridad

    • 🔒 #12 FileLibrary: upload via /api/files/upload (no más bypass de MIME/size/sanitización)

    Bugs reales arreglados

    • Embeddings: 200 requests serializados por 200 chunks → 2 batched requests
    • OCR de imágenes ahora funciona (antes failed)
    • Re-ingest no paga embeddings ni LLM analysis si el archivo no cambió
    • Fallo de embeddings a mitad ya NO deja el archivo con 0 chunks
    • FileLibrary subía bypassando MIME validation y 30MB cap (vector de abuso)

    UX mejorada

    • Status badge actualiza solo cada 3s mientras procesa
    • Loader2 amber junto al badge cuando processing
    • Tooltip negro con detalle de error si failed
    • Botón retry rojo si failed (en vez del verde de "ingest new")
  17. v8.63.0

    ✨ Mensajes de estado IA con vida: icono por tool + rotación + shimmer

    Tres mejoras premium al indicador "Pensando..." que aparece mientras la IA contesta en chats compartidos. (1) Icono específico por tool: Search para web, Database para SQL, Sparkles para imagen, Telescope para deep research, FileSpreadsheet para Excel, Youtube, ScanText para OCR, etc. (antes era el mismo Loader2 spinner genérico para todo). (2) Rotación automática entre 3 variantes de texto cada 2.4s: ej. para web "Buscando en la web..." → "Revisando fuentes recientes..." → "Contrastando resultados..." (las variantes ya existían en i18n pero nunca se usaban). (3) Shimmer animado sobre el texto (gradient sweep violeta + blanco translúcido en el medio que viaja de izquierda a derecha) — sensación de "trabajando" en vez de "congelado". El backend ahora persiste live_tool en meta_json (key estable) y el frontend hace todo lo demás: rotación local, mapeo a icono, shimmer.

    Nuevo

    • Nuevo componente: src/components/chat/LiveAssistantStatus.tsx (autocontenido, 11 tools mapeados)
    • Backend: live_tool key estable persistido en meta_json
    • 11 iconos Lucide específicos: Brain (thinking), Search (web), Database (SQL), Network (red), Sparkles (imagen), FileText (doc), FileSpreadsheet (xlsx), Youtube (yt), ScanText (OCR), Telescope (deep research), PenLine (streaming)
    • Rotación variantes cada 2400ms (no rota durante streaming ni done)
    • Crossfade del texto al rotar: fade-in + blur(2px)→0 en 320ms con cubic-bezier(0.22,0.9,0.24,1)
    • Shimmer gradient: currentColor → blanco 95% → currentColor; 250% size; 2.6s linear infinite
    • Icono con micro-pulso (scale 1→1.08→1, 1.8s) + halo Loader2 translúcido detrás
    • prefers-reduced-motion respetado: animaciones off, color sólido

    Mejorado

    • 🎨 Dark mode: card violet con bg gradient oscuro + sombra negra
  18. v8.62.2

    🎤 Renombrar GIA-Voz → GarBotGPT-Voz

    Renombrado el modelo de conversación por voz de "GIA-Voz" a "GarBotGPT-Voz" para alinearlo con la marca de la app. Cambiado en UI (SettingsModal: ajuste de voz; UserTokenUsage admin: tarjeta de voz + lista actividad reciente; VoiceConversationModal: model field de cada mensaje + nombre del speaker), en API (transcribe: vocabulario del prompt de Whisper) y en DB (model_configs.display_name vía migración 082). De paso arreglado un bug pre-existente en VoiceConversationModal: el lookup hacía .eq("is_active", true) pero esa columna no existe (es is_visible) → el lookup siempre devolvía null y el system_prompt del admin nunca se aplicaba. Ahora sí.

    Nuevo

    • 🎤 SettingsModal: "Elige la voz que usará GarBotGPT-Voz"
    • 🎤 UserTokenUsage (admin): tarjeta "GarBotGPT-Voz (Realtime)" + actividad reciente
    • 🎤 VoiceConversationModal: model field, speaker name y comentarios renombrados
    • 🎤 Whisper transcribe: vocabulario actualizado
    • 🎤 Migración 082: UPDATE display_name + INSERT entrada si no existía
    • 🗂️ Changelog histórico NO se toca — mantiene mentions originales de "GIA-Voz" como referencia histórica

    Arreglado

    • 🐛 Fix bug pre-existente: .eq("is_active") → .eq("is_visible") (columna correcta)
  19. v8.62.1

    🔧 Hotfix: cron de Vercel rompía el build (Hobby limit)

    El vercel.json que añadí en v8.61.0 para el status-checks cron usaba schedule */2 * * * * (cada 2 min). Vercel Hobby plan SOLO permite cron diario, así que cualquier expresión más frecuente hace fallar el build durante la validación de manifiesto — por eso v8.61.0 y v8.62.0 nunca llegaron a Vercel a pesar de estar pushed a GitHub. Fix: vacío el vercel.json y muevo el cron a GitHub Actions (.github/workflows/status-checks-cron.yml) que pinguea /api/cron/status-checks cada 5 minutos. GitHub Actions cron es gratis y suficiente para status monitoring. Frecuencia ligeramente más baja (5min vs 2min) pero igual funcional.

    Nuevo

    • 🔧 vercel.json crons removido (causaba "Hobby accounts limited to once-per-day cron")
    • 🔧 .github/workflows/status-checks-cron.yml: cron 5min con curl al endpoint
    • 🔧 Usa secret CRON_SECRET y opcional STATUS_ENDPOINT desde GitHub Actions secrets
    • 🔧 concurrency group evita ejecuciones solapadas
    • 🔧 timeout 5min + curl con max-time 90s

    Mejorado

    • 🔧 workflow_dispatch permite trigger manual desde la UI de GitHub
  20. v8.62.0

    ✨ Sidebar premium + reconexión robusta con mala conexión

    Dos mejoras: (1) estética del sidebar y sus menús dropdown, (2) reconexión automática del sistema de "en línea" cuando hay mala conexión. Los menús del sidebar (3-puntos por chat y el del perfil) ahora tienen rounded-[18px] con liquid glass real (backdrop-blur-2xl + saturación), sombras multicapa con highlight superior, items con rounded interno + active:scale + transición suave. El sidebar refinado: items rounded-[10px] con inset shadow sutil en el activo, hover con shadow inset, kbd más cuidado. La parte 2 arregla un bug serio: con mala conexión móvil/wifi pobre, las suscripciones Realtime quedaban en CHANNEL_ERROR sin recuperarse y los pings de actividad se perdían silenciosamente — el usuario aparecía offline en 5min sin recovery. Ahora hay reconexión exponencial (1s, 2s, 4s, 8s, 16s, 30s), retry/backoff en pings HTTP, listener window.online que fuerza refresh inmediato al recuperar conectividad, focus listener para refrescar al volver al tab, y un realtimeStatus en el contexto para futuras UI de degradación.

    Nuevo

    • Dropdown 3-puntos: rounded-[18px] + liquid glass (backdrop-blur-2xl saturate-150)
    • Sombras multicapa con highlight superior + inset border
    • Items del dropdown con mx-1.5 + rounded-[10px] hover + active:scale-[0.98]
    • ChatRow rounded-[10px] con inset shadow en activo
    • New chat + Buscar con hover inset shadow + active scale
    • 🔄 Reconexión exponencial Realtime: 1s/2s/4s/8s/16s/30s
    • 🔄 Retry con backoff en pings HTTP (1s, 3s, 8s) — antes .catch silenciaba todo
    • 🔄 window.addEventListener("online") fuerza refresh + reconnect inmediato
    • 🔄 focus listener refresca statuses al volver al tab
    • 🔄 Tras SUBSCRIBED tras reconectar, refresh para no perder eventos del intervalo offline
    • 🔄 navigator.onLine check: no insistir con retries si no hay red, esperamos al evento online

    Mejorado

    • Menu perfil del sidebar: mismo tratamiento glass
    • 🆕 ActivityContext expone realtimeStatus (connected/connecting/disconnected) para UI futura

    Arreglado

    • 🔄 ChannelView con manejo de CHANNEL_ERROR/TIMED_OUT/CLOSED + refresh on online
  21. v8.61.0

    📡 Status page real estilo Supabase

    Nuevo sistema completo de status page público y monitoring activo. Página /status pública (no requiere login) con liquid glass + uptime 90 días en barras estilo Supabase + incidents activos y resueltos. Cron en Vercel cada 2 minutos pinguea 12 servicios: web app, Supabase REST/Auth/Storage, Tika, OpenAI/Anthropic/Gemini, OAuth providers (Google/Microsoft/Spotify/GitHub). Estado por servicio: operational/degraded/down según thresholds de latencia. Auto-incident creation cuando un servicio está down 5 checks consecutivos. Auto-resolve cuando vuelve a operational 3 checks. Admin UI en /admin/status para gestionar incidents manualmente. Banner global en la app cuando hay incident activo.

    Nuevo

    • 📡 12 servicios sembrados (infraestructura, AI models, OAuth)
    • 📡 Cron Vercel /api/cron/status-checks cada 2 min con auto-incident creation/resolution
    • 📡 /status público con liquid glass, uptime 90 días en barras tipo Supabase, gráfico de incidents con timeline
    • 📡 /admin/status para crear/editar/resolver incidents manualmente
    • 📡 Banner global en ChatShell cuando hay incident activo (dismissable por user, recordado en localStorage)
    • 📡 API pública GET /api/status devuelve JSON con global_status, services, incidents
    • 📡 /api/health para auto-monitoring de la propia app

    Seguridad

    • 📡 Migración 081: tablas status_services, status_checks, incidents, incident_updates con RLS público SELECT
  22. v8.60.1

    🔧 Hotfix: build de Vercel petaba por ffmpeg

    El build de Vercel en v8.60.0 falló: Turbopack no podía analizar los require() dinámicos de @ffmpeg-installer/ffmpeg (el paquete resuelve el binario por OS a runtime con paths computados, no estáticos). Fix: marcar @ffmpeg-installer/* y fluent-ffmpeg como serverExternalPackages en next.config.ts para que el bundler los deje pasar y se carguen via require() nativo en Node.

    Nuevo

    • 🔧 next.config.ts: serverExternalPackages incluye @ffmpeg-installer/* y fluent-ffmpeg
    • 🔧 Patrón estándar para paquetes con require() dinámico OS-specific
    • 🔧 Análisis de vídeo v8.60.0 ahora compila y funciona en Vercel
  23. v8.60.0

    🎬 Análisis de vídeo (multimodal in)

    La IA ahora puede ENTENDER vídeos subidos (antes solo generaba). Sube un mp4/mov de hasta 30MB y 5min — el backend extrae 6 keyframes evenly-spaced con ffmpeg, transcribe el audio con Whisper (con timestamps por segmento), describe cada frame con gpt-4o-mini visión usando el transcript como contexto, y genera un resumen + 3-5 key moments con timestamps. Todo se inyecta como contexto en el system prompt para que el AI pueda responder cualquier pregunta sobre el vídeo (reuniones grabadas, tutoriales, vídeos de clientes, screencast de bugs). Auto-detección: con solo subir un vídeo se dispara el análisis, sin toggle nuevo.

    Nuevo

    • 🎬 Nuevo helper: src/lib/server/chat/tools/video-analysis.ts
    • 🎬 Endpoint dedicado: POST /api/video/analyze (file_id → análisis JSON)
    • 🎬 Bundlea @ffmpeg-installer/ffmpeg + fluent-ffmpeg (binarios para Linux serverless)
    • 🎬 Pipeline: descarga storage → audio mp3 → Whisper verbose_json → 6 frames JPG → gpt-4o-mini vision → resumen+moments
    • 🎬 Integrado en /api/chat: auto-detecta video/* mime en attachments y activa el análisis
    • 🎬 maxDuration 300s para procesar vídeos cortos sincrónicamente (Vercel Pro)
    • 🎬 Resultado se inyecta como contexto en system prompt + se guarda en meta_json.video_analyses
    • 🎬 Límites: 30MB / 5min / 6 frames / 2 vídeos por turno
  24. v8.59.2

    💾 Rescate de mensajes del asistente "desaparecidos"

    Bug: en chats dentro de carpetas (y otros casos), el usuario veía la respuesta del AI durante el streaming pero a los pocos segundos desaparecía. Causa: el INSERT del mensaje del asistente al final del streaming fallaba o se interrumpía (timeout, error de DB, cliente desconectado antes del INSERT), y aunque el cliente tenía el contenido en memoria, al refrescar o cambiar de chat se perdía porque el mensaje optimista solo vive en estado de React. Verificado en DB del usuario: conversación con user_msg pero asst_count=0 a pesar de respuesta vista. Fix: nuevo endpoint /api/messages/save-assistant-recovery que persiste el contenido huérfano cuando el INSERT principal falló. El frontend lo llama automáticamente cuando, tras 3 reintentos de loadMessages, no aparece el assistant en DB. Anti-duplicado: si el INSERT del stream sí persistió tarde, el endpoint detecta el contenido similar y skipea.

    Nuevo

    • 💾 Nuevo endpoint: /api/messages/save-assistant-recovery
    • 💾 Anti-duplicado: chequea assistants de los últimos 5min con mismo prefijo de contenido
    • 💾 Frontend (ChatInput.tsx) llama al recovery cuando el optimistic_local fallback se activa
    • 💾 Mensaje rescatado se marca con meta.recovery_insert para debugging
    • 🔍 Causa raíz: el optimistic_local solo vivía en estado de React, no persistía en DB
  25. v8.59.1

    🪞 /ios V11 iteración: más transparente + bordes con refracción visible

    Feedback: V11 quedaba demasiado gris/lechoso y no se veía cómo el cristal deformaba el fondo en los bordes. Dos bugs identificados y arreglados: (1) la recombinación de canales RGB usaba feComposite arithmetic (suma) que sobre-saturaba a gris/blanco — cambiado a feBlend mode="screen" que recombina correctamente sin engrisar. (2) Defaults demasiado tímidos en refracción y demasiado generosos en tint/highlights blancos — rebalanceados.

    Nuevo

    • 📐 scaleRatio 0.7 → 1.2 (refracción claramente visible en bordes)
    • 📐 glassThickness 6 → 12 (más profundidad de deformación)
    • 📐 bezelWidth 16 → 26 (zona de refracción más ancha)
    • 🪟 tintOpacity 0.10 → 0.03 (3% en vez de 10% — casi transparente)
    • 🪟 inner-shadow alpha 0.55 → 0.28 (menos blanqueo interno)
    • 🪟 top-highlight de 55% a 28% en el bezel superior
    • 🪟 pointer-specular opacity 0.85 → 0.7 + hot-spot 0.42 → 0.25
    • 🪟 backdrop background 0.02 → 0 (sin velo)
    • 🌈 aberrationStrength 0.015 → 0.018 (cromática un pelín más visible)

    Arreglado

    • 🐛 Fix crítico SVG: feComposite arithmetic → feBlend mode="screen" (no más saturación a gris)
  26. v8.59.0

    🪞 /ios v11: réplica fiel del Liquid Glass de Apple iOS 26

    Tras analizar la documentación de Apple, los repos open-source de referencia (liquid-glass-main, conor.fyi/liquid-glass-reference, nikdelvin/liquid-glass) y vídeos de WWDC 2025, añado la versión 11 del showcase /ios — la más fiel al cristal real de Apple. Mejoras concretas sobre V9/V10: aberración cromática real (3 displacement maps con IORs distintos por canal R/G/B), specular reactivo al puntero (la luz viaja siguiendo el cursor), press con bounce spring (scale 0.96 + cubic-bezier con overshoot), touch ripple (destello blanco desde el punto de click expandiéndose en 640ms), top edge highlight (luz cayendo desde arriba en el bezel, no en el centro). Defaults Apple-like: refracción mucho más sutil (scaleRatio 0.7, blur 0.6, glassThickness 6, bezelWidth 16) en vez de los V9/V10 exagerados.

    Nuevo

    • 🌈 Aberración cromática: SVG con 3 feDisplacementMap por canal RGB, IORs 1.515/1.500/1.485
    • 💡 Specular reactivo: radial-gradient hot-spot + halo amplio que siguen --v11-px/--v11-py via pointermove
    • 🎯 Press bounce: cubic-bezier(0.34, 1.56, 0.64, 1) — overshoot al soltar como SwiftUI .interactive()
    • 💫 Touch ripple: span expandiéndose scale(1→70) en 640ms con mix-blend-mode screen
    • Top edge highlight: linear-gradient(180deg, white 55% → transparent 30%) en el bezel superior
    • 📐 Defaults sutiles vs exagerados: scaleRatio 0.7 (era 1.0), blur 0.6 (era 1.5), glassThickness 6 (era 12)
    • 🏗️ Estructura por capas: backdrop → tint → pointer-specular → top-highlight → ripples → content
    • prefers-reduced-motion: ripple a 50ms y sin transform transitions
  27. v8.58.1

    🐛 Hotfix: "No se pudieron cargar los miembros" en Compartir carpeta

    Las policies RLS que añadí en la migración 078 sobre folder_shares hacían recursión infinita (un EXISTS sub-select sobre folder_shares dentro de la propia policy de folder_shares → Postgres lanza "infinite recursion detected in policy"). El usuario veía el toast "No se pudieron cargar los miembros" al abrir la tab de Compartir en FolderSettingsModal. Fix: usar la función SECURITY DEFINER folder_shared_role (bypasea RLS internamente) para chequear el rol admin en vez del sub-select recursivo. La migración 078 del repo ya está corregida para deploys desde cero, y la 080 arregla entornos donde la 078 antigua ya se aplicó.

    Nuevo

    • 🛡️ Migración 080 aplicada en producción (project GEIA / iuuuhhrwbteerxecxhlu)

    Arreglado

    • 🐛 Causa: EXISTS sub-select sobre folder_shares dentro de policy de folder_shares
    • 🔧 Fix: usar folder_shared_role() SECURITY DEFINER (no recursivo)
    • 📁 Migración 078 actualizada en el repo para que deploys desde cero no caigan en el bug
  28. v8.58.0

    📁 Sistema de carpetas: gran auditoría y arreglos

    Auditoría completa al sistema de carpetas con varios bugs serios resueltos y mejoras de UX. Lo más importante: las "columnas fantasma" (accent_color, is_favorite, parent_folder_id, banner_url, smart_filters_json, tablas folder_shares y folder_templates) ahora tienen migración SQL real (078) — antes existían solo en la base de datos creada a mano y cualquier deploy nuevo habría petado. Las carpetas compartidas ahora funcionan end-to-end (antes la UI permitía compartir pero el backend ignoraba al invitado). Las queries de contexto de carpeta van en paralelo. El inventario de archivos cap por tokens, no por filas. Modelo por defecto por carpeta. Toggle para aislar conocimientos. Multi-select + bulk move. Endpoint de búsqueda cross-folder.

    Nuevo

    • 🤝 Carpetas compartidas funcionan de verdad: instrucciones, memorias y archivos llegan al invitado
    • 🧠 Modelo por defecto por carpeta (default_model_slug) con picker en settings
    • ✂️ Dedup de archivos entre carpeta-RAG y knowledge-RAG (no más chunks duplicados)
    • 📐 Inventario de archivos: cap por tokens (~3500), no por filas — antes podía empujar fuera el contexto
    • 🌳 Carpetas anidadas: el sidebar ya tenía render-tree pero faltaba la columna parent_folder_id en la migración
    • 🔍 Endpoint /api/folders/search: busca carpetas, chats y archivos a través de TODAS las carpetas (propias + compartidas)
    • Multi-select + bulk move en FolderWelcomeScreen — botón "Seleccionar" + bar flotante "Mover a…"
    • 🗒️ Auto-cap de folder_memories: cuando una carpeta pasa de 80 memorias activas, las 20 más antiguas se desactivan (no se borran)

    Mejorado

    • 4 queries de contexto de carpeta paralelizadas (Promise.all, ahorra 60-150ms/mensaje)

    Seguridad

    • 🛡️ Migración 078: columnas fantasma + folder_shares + folder_templates + RLS completas
    • 🔒 Toggle inherit_model_knowledge para aislar carpetas del modelo global
  29. v8.57.0

    🧠 Conocimientos: clasificador LLM de intent (sin palabras clave)

    Mejora encima de v8.56.0. Antes el detector de "el usuario pide listar archivos" funcionaba con regex (lista cerrada de palabras: archivos, documentos, pdf, nóminas, facturas, etc.). Frágil con frases idiomáticas raras, otros idiomas o tipos de documento nuevos. Ahora hay un mini-LLM clasificador (gpt-4o-mini) paralelo al de Spotify intent: cuando la conversación tiene colección de conocimientos vinculada y el regex no matcheó, llama al LLM para decidir entre "list" (inyectar inventario) y "search" (búsqueda semántica). Coste despreciable (~$0.00005/llamada) y el regex sigue como fast path: el 80% de mensajes ni lo tocan. Cache 5 min en memoria por mensaje normalizado.

    Nuevo

    • 🧠 Nuevo helper: src/lib/server/chat/helpers/knowledge-intent-llm.ts
    • 🧠 gpt-4o-mini, timeout 4s, response_format JSON, temperature 0
    • 🧠 Gate doble: solo se llama si hay colección vinculada Y el regex no matcheó
    • 🧠 Soporta español, catalán e inglés de forma nativa
    • 🧠 Fallback silencioso a regex si el LLM falla/timeoutea

    Mejorado

    • 🧠 Cache 5 min en memoria (max 500 entradas, LRU básico)
  30. v8.56.0

    📚 Conocimientos: ahora enumera TODOS los archivos de la colección

    Bug: con una colección de conocimientos de 16 nóminas vinculada a una carpeta, al pedir "dime todas mis nóminas" solo aparecían 9 de 16 documentos. Causa: la búsqueda vectorial usaba p_match_count=8 (fallback 10) y la deduplicación de chunks→archivos ocurría DESPUÉS del límite, así que 16 PDFs casi idénticos colapsaban a ~9 docs únicos. Fix triple: (1) regex de "intent listar" ampliado para detectar nóminas/facturas/recibos/sueldos/contratos/etc., (2) cuando se detecta intent de listado y la conversación tiene colección de conocimientos, se inyecta el inventario COMPLETO de archivos en el system prompt (paralelo al patrón que ya teníamos para archivos de carpeta), (3) p_match_count escalado dinámicamente al nº de archivos (16 archivos → 32/48 en vez de 8/10).

    Nuevo

    • 📚 Regex ampliado: nóminas/facturas/recibos/sueldos/contratos/albaranes/tickets
    • 📚 Inventario completo de la colección inyectado como fuente autorizada cuando se pide listar/contar/enumerar
    • 📚 match_count dinámico: min(40, files×2) primario · min(48, files×3) fallback
    • 📚 Preview de primer chunk por archivo para que el modelo distinga cada nómina

    Arreglado

    • 📚 Bug resuelto: ahora salen los 16 archivos en lugar de 9 al listar nóminas

1118 versiones publicadas · página 31 de 38. Míralo dentro de la app.