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.31.1

    🐛 Fix subida de archivos con acentos/apóstrofes ("Invalid key")

    Supabase Storage rechazaba uploads cuyos nombres contenían acentos (è/é/í/ñ), apóstrofes tipográficas, espacios o paréntesis con error "Invalid key". sanitizeFilename ahora normaliza NFD, elimina marcas combinantes (diacríticos) y fuerza el set [A-Za-z0-9._-], preservando legibilidad.

    Nuevo

    • 🔤 Acentos eliminados (NFD + strip combining marks): Estratègies → Estrategies
    • ✂️ Caracteres no permitidos → "_" (apóstrofes, paréntesis, espacios)
    • 📏 Cap a 180 caracteres con extensión preservada
    • 🧹 Colapso de "_" repetidos y trim de bordes
    • 🔄 Misma función compartida en client (WelcomeScreen, ChatInput indirecto) y server (/api/files/upload, /api/projects/.../replace)
    • 🗑️ Eliminado duplicado de sanitizeFilename en upload/route.ts

    src/lib/file-utils.ts

    • sanitizeFilename ahora separa stem/extension, normaliza NFD, strip /[\u0300-\u036f]/ (diacríticos).
    • Sustituye /[^A-Za-z0-9._-]+/ → "_" en stem y extension por separado.
    • Colapsa "_+" y recorta "._-" de bordes.
    • Cap a 180 chars preservando la extensión en minúsculas.

    src/app/api/files/upload/route.ts

    • Eliminado sanitizeFilename local que solo escapaba <>:"/\|?* y control chars.
    • Importa el shared util de @/lib/file-utils.
  2. v8.31.0

    ✨ Welcome enriquecido + rebrand GIA → GarBotGPT

    WelcomeScreen ahora muestra 7 toggles de herramientas en móvil (web, deep, red, doc, imagen, BD, excel) en lugar de 4, con badge contador de herramientas activas y filtrado por permisos del admin. Rebrand completo: todas las menciones de "GIA" se han renombrado a "GarBotGPT" (124 reemplazos en 52 archivos), preservando los IDs de modelo GIA-5.2 etc.

    Nuevo

    • 📱 Mobile quick actions ampliadas: 4 → 7 toggles (añadidos imagen, BD, excel)
    • 🔢 Badge contador de herramientas activas en la sección quick actions
    • 🏷️ Rebrand GIA → GarBotGPT en 52 archivos (traducciones, auth, chat, mobile, sidebar, settings…)
    • 🧠 Preservados los identificadores de modelo (GIA-5.2, GIA-5.2-mini) vía regex con look-ahead
    • Typecheck verde

    Seguridad

    • 🔒 Acciones se filtran por toolPermissions del admin (antes el estado se cargaba pero no se usaba)

    WelcomeScreen.tsx

    • Importados Database, ImageIcon, Sheet de lucide-react.
    • mobileQuickActions ahora incluye image (rosa), db (violeta), sheet (teal) además de los 4 originales.
    • Filtrado .filter() por toolPermissions[key] para respetar configuración admin.
    • activeToolsCount renderizado como badge verde junto al título "Quick actions".

    Rebrand masivo

    • Script regex \bGIA\b(?![-A-Za-z0-9]) → "GarBotGPT".
    • 124 reemplazos en 52 archivos.
    • src/lib/changelog.ts excluido (historia preservada).
    • Identificadores de modelo (GIA-5.2 etc.) intactos por look-ahead.
  3. v8.23.0

    🎆 Petardos del Barça + modal infinito + banner abajo

    Sistema de cohetes/petardos que suben desde abajo y explotan en lluvia de chispas. El modal de celebración ya NO se cierra solo — espera a que el usuario clique fuera de la tarjeta. Banner residual movido a la esquina inferior derecha. Burst de confeti programado cada 4.5s mientras dure el modal.

    Nuevo

    • 🚀 Cohetes/petardos que salen disparados desde el suelo hacia arriba
    • 💥 Cada cohete explota en 36-52 chispas radiales heredando su color
    • Trail de 12 puntos con fade-out por cada cohete
    • 🌧️ Lanzamiento cada 280-420ms (con 45% de doble lanzamiento)
    • 🚫 Modal SIN auto-cierre — usuario controla cuándo cerrar
    • 🎉 Burst extra programado cada 4.5s para celebración infinita
    • 👇 Banner residual movido de top-right a bottom-right

    Mejorado

    • 🎨 Cabeza brillante del cohete con shadow blur 14px

    Fireworks engine

    • Nuevo tipo Rocket con x/y/vx/vy/color/trail/exploded.
    • createRocket() spawns a posición x random 10%-90%, vy -11 a -16 (sube fuerte).
    • Gravedad 0.18 px/frame² aplicada → decelera la subida hasta vy >= -0.5.
    • Al peak (vy >= -0.5 o y < 18% altura) → explosión: 36-52 partículas radiales con createParticle(originX, originY, intensity 1.3).
    • Color de explosión: 70% del color del cohete, 30% de la paleta general.
    • Trail: array de últimas 12 posiciones con alpha decay 0.85 por frame.
    • Cabeza del cohete: círculo blanco interior + círculo de color exterior + shadowBlur 14 px.

    UX cambios

    • closeModal() ya NO se llama por timer. Solo al click en overlay.
    • Banner residual bajado a bottom: 20px, right: 20px (móvil 12/12).
    • Slide animation invertida: ahora entra desde abajo.
    • Tip del modal actualizado: "Toca fuera de la tarjeta para cerrar".
    • Burst extra cada 4.5s mantiene la fiesta viva.
  4. v8.22.0

    🏆 Celebració Barça · EPIC EDITION (escudo real + audio + cinema)

    Rediseño total de la celebración: escudo oficial FCB descargado de Wikipedia, intento de autoplay de "Viva la Vida" con fallback a botón dorado, 4 fases cinemáticas con flash blanco inicial, spotlights conicos rotando, senyera ondulando en BG, 30 estrellas titilando, halo dorado pulsante alrededor del escudo, título letra-por-letra con rotación 3D, count-up de 4 stats reales (28 Ligas · 5 Champions · 32 Copas · 14 Supercopas), confeti masivo con 4 formas (rect/círculo/estrella/triángulo) + multi-burst, glow rays + shimmer animation.

    Nuevo

    • Escudo OFICIAL FC Barcelona (descargado de Wikipedia Commons)
    • 🎵 Audio "Viva la Vida" con autoplay + fallback button dorado si bloqueado
    • 🎬 4 fases: flash blanco → spotlights → escudo emergiendo → título + stats
    • 🌟 Halo dorado pulsante alrededor del escudo (radial gradient + blur)
    • 🔤 Título "ÉS CAMPIONS!" letra-por-letra con rotación 3D y blur entrance
    • 📊 4 stats reales con count-up animado (28/5/32/14)
    • 🎭 Spotlights conicos rotando (4 capas, sentidos opuestos, mix-blend screen)
    • 🟡 🔴 Senyera (bandera catalana) ondulando en BG con skewY -12°
    • 30 estrellas titilando + shimmer en partículas confeti
    • 🎉 Confeti masivo con 4 formas (rect/círculo/estrella/triángulo)
    • 💥 2 bursts de confeti programados (600ms y 2800ms)
    • ⏱️ Auto-cierre a 9.5s + banner residual pulsante

    Recursos

    • public/celebrations/barca-crest.svg (14KB, oficial Wikipedia)
    • public/celebrations/viva-la-vida.mp3 (placeholder — el usuario debe subir el MP3)

    Componente

    • src/components/celebration/BarcaChampions.tsx (~700 líneas).
    • Phases: hidden → opening (flash) → modal → banner.
    • Audio loop, volume 0.7. Detecta bloqueo de autoplay y muestra botón "Activa la música".
    • Burst confetti triggers via state increment (Reactive useEffect).
    • StatCounter con useCountUp hook (easeOutCubic, 1400ms).
    • 12 @keyframes animations distintos.
  5. v8.21.0

    🏆 Celebració FC Barcelona campió de Liga (temporal)

    Componente temporal que celebra el título de Liga del FC Barcelona. Al cargar la app aparece un modal con confeti, escudo FCB animado y el lema "ÉS CAMPIONS!". Después queda un banner pequeño top-right que persiste durante la sesión. Auto-desactiva el 15 de junio de 2026.

    Nuevo

    • 🎉 Modal full-screen con backdrop blaugrana + confeti continuo (canvas)
    • Escudo FCB dibujado en SVG desde cero (cruz Sant Jordi + senyera + bandas blaugrana + balón)
    • Título "ÉS CAMPIONS!" con gradient blanco→dorado y shine animation
    • 🏵️ Tres estrellas doradas parpadeantes + badge "🏆 Campeones de La Liga 2025-26"
    • 📌 Banner persistente top-right con pulse cada 3s, cierre 24h via localStorage
    • Auto-expiración: desaparece después del 2026-06-15

    Componente

    • `src/components/celebration/BarcaChampions.tsx` (~580 líneas).
    • Canvas-based confetti: 600 partículas máx, paleta blaugrana + dorado (#004D98, #A50044, #EDBB00, blanco), burst inicial desde 5 puntos.
    • Modal con animaciones: crest-spin-in (540°), title-in (scale + blur), star-twinkle, shine cruzando la card cada 3.5s.
    • Banner pill con pulse y borde dorado.
    • Configurable via STARTS_AT / EXPIRES_AT constants.
    • Persistencia: localStorage 'barca-champions-celebration-v1' (seenModal + dismissed timestamp).

    Montaje

    • Importado y renderizado en `src/app/layout.tsx` dentro de ActivityProvider.
    • Se carga en TODAS las páginas de la app.
    • Para apagar: cambiar `EXPIRES_AT` a una fecha pasada en BarcaChampions.tsx.
  6. v8.20.0

    Refactor v8.20 — Helpers de research/web/YouTube extraídos (-829 líneas)

    El módulo más grande del Bloque A: 40+ helpers de search, ranking, deep research, image collection, YouTube, concurrency y rerank parsing se mueven a `src/lib/server/chat/helpers/research-helpers.ts` (~960 líneas). DI eliminada en 2 tools (web-search y youtube).

    Nuevo

    • 🔍 40+ helpers extraídos a research-helpers.ts (~960 líneas)
    • 📊 Source scoring: authority, freshness, coverage, dedupe, rankWebSources
    • 🧠 Deep-research intent parsing: detectIntentHints, sanitizePlan, buildFallbacks
    • 🖼️ Image collection cross-source con scoring lexical + URL + size
    • 🎬 YouTube: metadata, transcript (XML + JSON3), captionTracks parsing
    • 🧪 parseRerankScores con fallback a regex si JSON está roto
    • DI eliminada en web-search.ts y youtube.ts

    Mejorado

    • runWithConcurrency<T,R> shared utility

    Nuevo módulo

    • `src/lib/server/chat/helpers/research-helpers.ts` con 6 tipos públicos + 40 funciones.
    • Tipos: ResearchMode, RankedWebSource, DeepResearchPlan, DeepResearchCacheEntry, DeepResearchImage, DeepResearchImageCandidate.
    • URL/text utils: canonicalizeUrl, tokenize, jaccardSimilarity, uniqueStrings.
    • Source scoring: scoreSourceAuthority/Freshness/Coverage, removeDuplicateSources, rankWebSources.
    • Deep-research: buildFocusedResearchQuery, detectDeepResearchIntentHints, sanitizeDeepResearchPlan, buildGenericDeepResearchFallbackQueries.
    • HTML/Images: extractImageCandidatesFromHtml, fetchHtmlWithTimeout, collectDeepResearchImages.
    • YouTube: extractYouTubeVideoIds, fetchYouTubeMetadata, fetchYouTubeTranscript, decodeHtmlEntities.
    • parseRerankScores: parser robusto para output JSON del LLM rerank.

    Tools afectados

    • tools/web-search.ts: rankWebSources + collectDeepResearchImages inyectados → imports directos.
    • tools/youtube.ts: 4 helpers DI eliminados. YoutubeToolContext queda en 1 campo (antes 5).
    • route.ts: 9829 → 9001 líneas (-828).
  7. v8.19.0

    Refactor v8.19 — Helpers de Gmail/Outlook extraídos (-652 líneas)

    Helpers compartidos por Gmail tool y Microsoft tool salen al módulo `gmail-helpers.ts` (~600 líneas con 14 públicos + 11 privados). DI eliminada en 2 tools.

    Nuevo

    • 📧 30+ helpers de email a gmail-helpers.ts
    • 🔧 Regex EMAIL_ADDRESS_RE y GMAIL_SEND_CONFIRMATION_RE como exports
    • ✍️ Parseo intent + edición + AI draft generation centralizados
    • 🌐 fetchGmailMessages + sendGmailMessage (con buildGmailRawMessage MIME)
    • 🗂️ buildMicrosoftDriveQuery + buildMicrosoftDriveBlock (OneDrive)
    • DI eliminada en gmail.ts (17 → 0 DI) y microsoft.ts (14 → 0 DI)

    Mejorado

    • 🎨 HTML templates: wantsHtmlEmail + buildEmailHtmlTemplate

    Nuevo módulo

    • `src/lib/server/chat/helpers/gmail-helpers.ts` (~600 líneas).
    • Públicos: parseGmailSendIntent, parseGmailSendIntentFromHistory, mergeGmailDraft, applyGmailDraftEditsFromPrompt, generateGmailDraftIfNeeded, computeGmailMissingFields, isConfirmationOnlyMessage, wantsHtmlEmail, buildEmailHtmlTemplate, extractGmailSenderName, buildGmailSearchQuery, buildGmailMessagesGroupedBlock, fetchGmailMessages, sendGmailMessage, buildMicrosoftDriveQuery, buildMicrosoftDriveBlock.
    • Internos: decodeMailtoParam, extractLabeledLineValue, cleanParsedGmailBody, parseGmailDraftFromAssistantText, escapeHtml, normalizeInstructionText, isInstructionalEmailSubject/Body, parseGeneratedDraftJson, stripHtmlToText, buildGmailRawMessage, formatGmailDayHeader, formatGmailHour.

    Tools afectados

    • tools/gmail.ts: GmailToolContext 17 → 6 campos.
    • tools/microsoft.ts: MicrosoftToolContext 14 → 7 campos.
    • route.ts: 10481 → 9829 líneas (-652).
  8. v8.18.0

    Refactor v8.18 — Helpers de Google AdSense extraídos (-343 líneas)

    15+ helpers de parseo y formateo de Google AdSense salen al módulo `adsense-helpers.ts`. DI eliminada en AdSense tool.

    Nuevo

    • 📈 4 tipos públicos + 14 funciones de scoring/formateo a helpers
    • 🔧 parseAdSenseDateRange, parseAdSenseDimensions, parseAdSenseMetrics, wantsAdSenseTodayVsYesterdayComparison
    • DI eliminada en google-adsense.ts (13 → 0 DI)

    Mejorado

    • 🎨 buildAdSenseMetricPayloads, buildAdSenseComparisonPayloads, buildAdSenseRowsTable, buildAdSenseAccountsBlock

    Nuevo módulo

    • `src/lib/server/chat/helpers/adsense-helpers.ts` (~360 líneas).
    • Tipos: AdSenseDateRangeSelection, AdSenseMetricKind, AdSenseMetricPayload, AdSenseComparisonMetricPayload.
    • Internos: adsenseDateParts, ADSENSE_METRIC_LABELS, formatAdSenseHeaderLabel, getAdSenseCells/MetricKind/NumericValue/MetricHeaders/MetricEntries/MetricEntryByName, pickAdSenseMetricRow, formatAdSenseMetricValue/DeltaValue.

    Tools afectados

    • tools/google-adsense.ts: AdSenseToolContext 13 → 3 campos.
    • route.ts: 10824 → 10481 líneas (-343).
  9. v8.17.0

    Refactor v8.17 — Helpers de Spotify extraídos (-314 líneas)

    Helpers de Spotify (intent parsing + API calls) salen al módulo `spotify-helpers.ts`. DI eliminada en Spotify tool.

    Nuevo

    • 🎵 8 helpers de Spotify a spotify-helpers.ts
    • 🔄 Retry on 429 con Retry-After header
    • 🎤 deriveSpotifyPlaylistNameFromPrompt + deriveSpotifySearchIntent
    • 📡 searchSpotifyTracks (con paginación), fetchSpotifyPlaylists, fetchSpotifyPlaylistTrackPreview
    • DI eliminada en spotify.ts (11 → 0 DI)

    Nuevo módulo

    • `src/lib/server/chat/helpers/spotify-helpers.ts` (~330 líneas).
    • Tipos públicos: SpotifyTrackDigest, SpotifyPlaylistDigest.
    • Internos: delay, getRetryDelayFromHeaders, normalizePlaylistName, stripCountExpression, fallbackPlaylistName, parseSpotifyTrackItem, asObj.

    Tools afectados

    • tools/spotify.ts: SpotifyToolContext 11 → 5 campos.
    • route.ts: 11138 → 10824 líneas (-314).
  10. v8.16.0

    Refactor v8.16 — Helpers de documento extraídos (-150 líneas)

    Primer paso del Bloque A. Helpers puros de manipulación de strings, parseo JSON, detección de tipo de archivo, parseo de números con formato europeo/americano y QuickChart URLs salen al módulo `document-helpers.ts`.

    Nuevo

    • 🧱 10+ helpers puros a document-helpers.ts
    • 🔤 normalizeForKey, sanitizeMarkdownCell, parseJsonContent
    • 📁 SPREADSHEET_EXTENSIONS + isSpreadsheetAttachment + extractFileExtension
    • 🔢 parseRequestedCount, toNumericValue (europeo/americano), buildQuickChartUrl
    • 📄 GeneratedDocumentExt + inferDocumentOutputFormat

    Nuevo módulo

    • `src/lib/server/chat/helpers/document-helpers.ts` (~210 líneas).
    • Funciones puras sin red, sin DB, sin estado. Manipulación de strings, detección de tipos de archivo, parseo robusto.
    • normalizeForKey usado en 20+ sitios de route.ts queda compartido.

    route.ts cambios

    • Helpers eliminados de route.ts y reemplazados por import statement.
    • route.ts: 11288 → 11138 líneas (-150).
  11. v8.15.0

    GarMusic Cinema — reproductor totalmente nuevo con waveform y color dinámico

    Rediseño completo desde cero con concepto editorial-cinematográfico. El album art es el héroe, el color del player se extrae del propio cover en tiempo real, la barra de progreso es un waveform de 56 barras que representa la "huella" musical de cada pista, y todo flota sobre un mesh gradient animado que también usa el color del cover.

    Nuevo

    • 🌊 Waveform de 56 barras como barra de progreso — pintada con el accent en la parte reproducida
    • 🎬 Mesh gradient animado en backdrop usando el color extraído
    • 🪟 Parallax 3D en cover (perspective 1100px, max 8°), con glow follower del ratón
    • 📰 Tipografía editorial: serif italic para labels + sans con tracking negativo en titles
    • Grain texture SVG sutil overlay (4% opacity, blend overlay)
    • 🌫️ Cover con vignette + shine + breathing animation cuando suena
    • 🔮 Botón Play con glow pulsante en accent color cuando hay reproducción
    • ⏱️ Modo fullscreen cinematográfico con cover gigante y vignette radial

    Mejorado

    • 🎨 Color de acento DINÁMICO extraído del album cover (con fallback hash si CORS bloquea)
    • Las 4 barras alrededor del playhead bouncean para simular reactivity audio (sin Web Audio API)

    Detalles únicos

    • Waveform deterministico por track (hash FNV-1a + senos mezclados) → cada canción tiene su huella única.
    • Click en cualquier punto del waveform = seek directo.
    • Stripe vertical de color en la fila de la playlist que está sonando.
    • Cover con animación "breath" sutil (scale 1 ↔ 1.02) cuando suena.
    • Color de acento se aplica vía CSS variable y atraviesa todo el componente (waveform, accent buttons, glows, focus states, fill volumen).

    Sin cambios

    • Audio engine, crossfade, shuffle, repeat, mute, volumen.
    • Persistencia localStorage (key con sufijo v2 para no chocar con la versión anterior).
    • Atajos teclado: Space, ←, →, Esc.
    • Búsqueda y drag & drop en la playlist.
    • Detección automática por flag music_player o URLs .mp3.
  12. v8.14.0

    Music Player — rediseño completo estética premium (Apple Music / Tidal)

    El reproductor GarMusic se rediseña desde cero con estética minimalista premium inspirada en Apple Music y Tidal. Fuera los gradientes saturados, el disco que gira, las ondas concéntricas y las pills de colores. En su lugar: el album cover domina la composición y su versión ampliada + desenfocada da el color al bloque entero (igual que en Spotify Now Playing). Tipografía SF Pro con jerarquía clara, controles minimalistas con SVG vectoriales, progreso ultrafino con thumb que aparece en hover, playlist tipo Spotify Desktop con número de pista que se transforma en ▶ al hover y en equalizer cuando suena.

    Nuevo

    • 🖼️ El cover ampliado y desenfocado pinta el bloque (sin gradientes hardcoded)
    • Glassmorphism real: vidrio negro 35% sobre el backdrop borroso
    • 🎯 Controles SVG vectoriales nítidos en cualquier resolución
    • 🎵 Playlist estilo Spotify Desktop: número → ▶ on hover → equalizer cuando suena
    • 📐 Tipografía SF Pro Display + tabular nums para tiempos
    • 🌫️ Progress thin (4px) que crece a 6px on hover, thumb aparece on hover
    • ⏯️ Botón Play prominente en blanco con sombra cinematográfica
    • 🖥️ Modo fullscreen renovado (cover grande + título + artist)
    • typecheck verde, build verde

    Mejorado

    • 🎨 Rediseño completo: minimalista, premium, Apple Music style

    Comportamiento conservado

    • Mismo audio engine: load/play/pause/seek/crossfade
    • Misma persistencia localStorage por player_id
    • Mismos atajos teclado (Space, ←, →, Esc)
    • Misma búsqueda + drag & drop en la playlist
    • Mismo shuffle, repeat, mute, volumen, crossfade configurable

    Lo que cambia

    • Layout: cover + info + controles arriba; playlist a la derecha (desktop) o debajo (mobile).
    • Header con marca G, eq animado cuando suena, label "Reproductor del chat".
    • Iconos lucide/feather en SVG en lugar de caracteres unicode.
    • Footer minimalista con greeting y stats de sesión.
    • Sin temas de color hardcoded — el color sale del album cover.
  13. v8.13.0

    Music Player tool — reproductor GarMusic Nova en el chat

    Nueva tool: cuando se activa el botón "Reproductor de música" en el menú del chat (icono 🎵), o cuando el mensaje contiene URLs `.mp3`, la respuesta del asistente embebe un reproductor completo: portada con parallax 3D, playlist con búsqueda y drag&drop, controles play/prev/next/shuffle/repeat/mute, crossfade configurable, modo Now Playing en pantalla completa, atajos teclado, persistencia (índice + tiempo escuchado) en localStorage. Adaptado del plugin Open WebUI a React/TypeScript con styled-jsx para no chocar con Tailwind.

    Nuevo

    • 🎵 Tool Music Player con reproductor completo dentro de la burbuja del asistente
    • 🪩 Parallax 3D en portada · disco animado · ondas cuando suena
    • 🎶 Playlist con búsqueda + drag & drop · persistencia localStorage
    • ⏯️ Crossfade configurable (0–3s) · shuffle · repeat · atajos teclado
    • 🔗 Auto-detecta URLs .mp3 en el mensaje y crea playlist con ellas
    • 🚀 Llama al asistente con `music_player: true` desde el toggle del menú

    Mejorado

    • 🎨 8 temas (purple_dream, ocean_blue, sunset_orange, forest_green, rose_gold, midnight_dark, candy_pink, cyber_neon)

    Backend

    • `src/lib/server/chat/tools/music.ts` — runMusicTool({inputText, explicitlyEnabled}) → { systemPromptAddition, musicPlayerMeta }.
    • Detección: flag `music_player: true` en el body o regex `\.mp3` en el inputText.
    • Devuelve `meta_json.music_player` con playlist + greeting + theme + crossfade_ms + source.
    • Playlist por defecto con 25 canciones GarMusic. Si hay URLs .mp3 en el mensaje, las usa en lugar de la default.

    Frontend

    • `src/components/chat/MusicPlayer.tsx` — componente self-contained con audio, playlist, parallax, mini-bar de estado.
    • styled-jsx para CSS scoped (no choca con Tailwind global).
    • Persistencia: índice de pista + tiempo escuchado + canciones reproducidas por player_id (= message.id).
    • Cleanup completo del audio + listeners en unmount.
    • Botón toggle 🎵 en el menú de tools (mobile + desktop).
    • MessageBubble detecta `meta_json.music_player` y renderiza el componente.
  14. v8.12.0

    Refactor v8.12 — System prompt builders extraídos a módulo puro

    Cinco fragmentos del system prompt salen de route.ts a un único módulo de funciones puras: `src/lib/server/chat/prompt-builders.ts`. Los fragmentos: recuerdos del usuario, instrucciones del Code Interpreter, contexto del proyecto (instrucciones + memorias + inventario), contexto de carpeta (instrucciones + memorias + inventario), y plantilla de generación de documento (xlsx/json/markdown). Sin DI — todo son funciones que toman datos y devuelven string.

    Nuevo

    • 🧱 5 system prompt builders → prompt-builders.ts
    • 🧮 67 líneas inline reemplazadas por 5 llamadas (1 línea cada una)
    • 🪶 Funciones puras — sin red, sin BD, sin mutación
    • typecheck verde, build verde

    Seguridad

    • 🔒 Comportamiento idéntico — mismos textos exactos para cada caso

    Nuevo módulo

    • `src/lib/server/chat/prompt-builders.ts` (~110 líneas).
    • Exporta: buildUserMemoriesPrompt, buildCodeInterpreterPrompt, buildProjectContextPrompt, buildFolderContextPrompt, buildDocumentGenerationPrompt.
    • Cada función devuelve "" si no aplica el contexto, o el fragmento concatenado con \n\n al sistema.

    route.ts cambios

    • userMemories: 3 → 1 línea.
    • Code Interpreter: 21 → 2 líneas (con comentario).
    • Proyecto context: 11 → 1 línea.
    • Folder context: 13 → 1 línea.
    • Document generation: 19 → 1 línea.
    • Total: 67 → 6 líneas en route.ts.

    Próximos releases

    • v8.13 — DeepResearch (~320 líneas, ALTO RIESGO).
    • v8.14 — NetworkDriveRag (~1.800 líneas).
    • v8.15 — Streaming progressive REAL (refactor SSE).
  15. v8.11.0

    Refactor v8.11 — Spreadsheet analysis tool extraído

    El bloque Spreadsheet analysis (118 líneas: lectura xlsx con SheetJS, cálculo de stats numéricos por columna, detección de eje categórico para chart, generación de URLs QuickChart) sale a `src/lib/server/chat/tools/spreadsheet.ts`. Mantiene los límites originales: 3 archivos máx, 3 hojas por archivo, 1200 filas muestreadas, 40 columnas máx, 4 charts.

    Nuevo

    • 📊 Spreadsheet analysis (118 líneas) → tools/spreadsheet.ts
    • 🧬 2 helpers DI (toNumericValue, buildQuickChartUrl)
    • typecheck verde, build verde

    Seguridad

    • 🔒 Comportamiento idéntico — mismos thresholds para columnas numéricas/categóricas

    Nuevo módulo

    • `src/lib/server/chat/tools/spreadsheet.ts` (~190 líneas) — runSpreadsheetTool(ctx) → { systemPromptAddition, spreadsheetChartImages, status }.
    • Importa xlsx dinámicamente (igual que antes) y descarga del bucket user-files via serviceClient inyectado.
    • Status: ok | error | skipped (skipped si no hay attachments).

    Próximos releases

    • v8.12 — DeepResearch (~320 líneas, ALTO RIESGO).
    • v8.13 — NetworkDriveRag (~1.800 líneas).
    • v8.14 — Streaming progressive REAL.
  16. v8.10.0

    Refactor v8.10 — YouTube summary tool extraído

    El bloque YouTube summary (50 líneas: descarga metadata + transcript de hasta 2 vídeos en paralelo, fallback a búsqueda web si la transcripción es pobre, construcción del [RESUMEN DE YOUTUBE] block del system prompt) sale a `src/lib/server/chat/tools/youtube.ts`. Status enum ok|error|skipped.

    Nuevo

    • 🎬 YouTube summary (50 líneas) → tools/youtube.ts
    • 🧬 4 helpers DI (runWithConcurrency, fetchYouTubeMetadata, fetchYouTubeTranscript, searchWeb)
    • typecheck verde, build verde

    Seguridad

    • 🔒 Comportamiento idéntico — slice 12000 chars de transcript, slice 320 de fallback sources

    Nuevo módulo

    • `src/lib/server/chat/tools/youtube.ts` (~135 líneas) — runYoutubeTool(ctx) → { systemPromptAddition, youtubeSummaries, status }.
    • Mantiene los límites originales: 2 vídeos máx en paralelo, transcript a 12000 chars, 5 fuentes de fallback si transcript < 120 chars.
    • Corre antes del tool-timeline en route.ts (no llama recordTool).

    Próximos releases

    • v8.11 — Spreadsheet analysis (~140 líneas, lectura xlsx + tablas + chart candidates).
    • v8.12 — DeepResearch (~320 líneas, ALTO RIESGO).
    • v8.13 — NetworkDriveRag (~1.800 líneas).
  17. v8.9.0

    Refactor v8.9 — OCR tool extraído (gpt-4o-mini visión + factura)

    Continúa el strangler-pattern. El bloque OCR (72 líneas: llamada a gpt-4o-mini visión, parseo JSON con summary + full_text + document_type + language + confidence + invoice_fields, construcción del bloque [OCR ADJUNTOS] del system prompt) se mueve a `src/lib/server/chat/tools/ocr.ts`. Status enum: ok | error | skipped. Si OCR falla no bloquea la respuesta del modelo principal.

    Nuevo

    • 👁️ OCR (72 líneas) → tools/ocr.ts
    • 📦 12 líneas en route.ts en lugar de 72
    • typecheck verde, build verde

    Seguridad

    • 🔒 Comportamiento idéntico — mismo prompt JSON + mismas heurísticas

    Nuevo módulo

    • `src/lib/server/chat/tools/ocr.ts` (~150 líneas) — runOcrTool(ctx) → { systemPromptAddition, ocrOutput, status }.
    • Status: ok | error | skipped (skipped si no hay imágenes o no hay API key).
    • parseJsonContent inyectado vía DI; el resto (URL, modelo, prompts) viven en el módulo.

    Próximos releases

    • v8.10 — DeepResearch (~320 líneas) — ALTO RIESGO: muta webSources/rankedWebSources + cache global.
    • v8.11 — NetworkDriveRag (~1.800 líneas con ~30 helpers internos).
    • v8.12 — Streaming progressive REAL.
    • v8.13 — Provider streams a `streaming/{openai,anthropic,google}.ts`.
  18. v8.8.0

    Refactor v8.8 — Google AdSense + Google Analytics extraídos (en paralelo)

    Continúa el strangler-pattern. Dos bloques grandes salen del monolito en una sola release: Google AdSense (172 líneas — modo summary y modo comparison hoy-vs-ayer, con métricas + dimensiones + report meta para cards) y Google Analytics GA4 (99 líneas — modo summary y modo comparison con previousDateRanges, breakdown por dimensiones). Ambos a `src/lib/server/chat/tools/google-{adsense,analytics}.ts`. Se enchufan al multi-tool parallel: AdSense + Analytics + web/db/spotify/gmail/microsoft pueden correr a la vez.

    Nuevo

    • 📈 Google AdSense (172 líneas) → tools/google-adsense.ts
    • 📊 Google Analytics GA4 (99 líneas) → tools/google-analytics.ts
    • 🧬 AdSense: 10 helpers DI · Analytics: 0 DI (todo viene de google-analytics-intent.ts)
    • typecheck verde, build verde

    Mejorado

    • Ambos en multi-tool parallel — corren con web/db/spotify/gmail/microsoft

    Seguridad

    • 🔒 Comportamiento idéntico — mismos systemPrompts y reportMetas

    Nuevos módulos

    • `src/lib/server/chat/tools/google-adsense.ts` (~250 líneas) — runAdSenseTool(ctx) → { systemPromptAddition, adsenseReportMeta, status }.
    • `src/lib/server/chat/tools/google-analytics.ts` (~170 líneas) — runGoogleAnalyticsTool(ctx) → { systemPromptAddition, googleAnalyticsReportMeta, status }.
    • AdSense maneja modo summary (con dateRange + dimensions + rowsTable) y modo comparison hoy-vs-ayer (Promise.all por cuenta).
    • Analytics maneja modo summary (con dimensions + breakdown rows) y modo comparison (con previousDateRanges).

    route.ts cambios

    • `adsensePromise` y `googleAnalyticsPromise` se lanzan junto al resto de promises del multi-tool parallel.
    • AdSense: bloque de 172 líneas reemplazado por 9 líneas de await + recordTool.
    • Analytics: bloque de 99 líneas reemplazado por 9 líneas de await + recordTool.
    • Reduce ~250 líneas netas en el monolito.

    Próximos releases

    • v8.9 — Calendar + Drive + Monday + Github + restantes integraciones (~700 líneas).
    • v8.10 — NetworkDriveRag (~1800 líneas con ~30 helpers internos).
    • v8.11 — DeepResearch (~400 líneas).
    • v8.12 — Streaming progressive REAL (refactor SSE).
  19. v8.7.0

    Refactor v8.7 — Microsoft 365 (Outlook + OneDrive) extraído + en paralelo

    Continúa el strangler-pattern del monolito. El bloque Microsoft 365 (156 líneas: lectura Outlook con focused/sender/email filters, envío Outlook con borrador + confirmación + fallback mailto, lectura de OneDrive con search) se mueve a `src/lib/server/chat/tools/microsoft.ts`. Se enchufa al multi-tool parallel: si el usuario activa Microsoft + otra integración, ahora corren en paralelo. Comparte 11 helpers de redacción de correo con Gmail (parseGmailSendIntent, generateGmailDraftIfNeeded, etc.) — siguen en route.ts y se inyectan vía DI.

    Nuevo

    • 📨 Bloque Microsoft 365 (156 líneas) extraído a tools/microsoft.ts
    • 🧬 19 helpers inyectados vía DI (11 compartidos con Gmail + Drive helpers + parseRequestedCount + extractGmailSenderName)
    • typecheck verde, build verde

    Mejorado

    • Microsoft 365 también va en paralelo con web/db/spotify/gmail

    Seguridad

    • 🔒 Comportamiento idéntico — mismo orden de aplicación al systemPrompt

    Nuevo módulo

    • `src/lib/server/chat/tools/microsoft.ts` (~250 líneas) — runMicrosoftTool(ctx) → { systemPromptAddition, status, durationMs }
    • Maneja los 3 modos: mail read (Outlook con filter focused/sender/email), mail send (con confirmación + mailto fallback), drive read (OneDrive search).
    • fetchMicrosoftMessages, sendMicrosoftMail y fetchMicrosoftDriveFiles ya estaban en `@/lib/microsoft-graph` — se importan directos.

    route.ts cambios

    • `microsoftPromise` se lanza junto a webSearchPromise/dbQueryPromise/spotifyPromise/gmailPromise.
    • Bloque inline (try/catch + 156 líneas) reemplazado por 7 líneas: `await microsoftPromise` + recordTool().
    • Helpers compartidos con Gmail siguen en route.ts. Se podrán mover a un módulo `mail-helpers` cuando ambos estén estables.

    Próximos releases

    • v8.8 — AdSense + Google Analytics (~340 líneas, con report metas).
    • v8.9 — Calendar + Drive + Monday + Github + restantes.
    • v8.10 — NetworkDriveRag (~1800 líneas con ~30 helpers).
    • v8.11 — DeepResearch (~400 líneas).
  20. v8.6.0

    Refactor v8.6 — Gmail tool extraído a su módulo (en paralelo con web/db/spotify)

    Continúa el strangler-pattern del monolito api/chat/route.ts: el bloque Gmail (122 líneas, lectura de bandeja + envío con borrador + fallback mailto) se mueve a `src/lib/server/chat/tools/gmail.ts` con el mismo patrón de Dependency Injection que web/db/spotify. Al extraerlo se enchufa al multi-tool parallel: cuando el usuario activa Gmail + otra tool, ahora corren en paralelo. Los helpers internos (parseGmailSendIntent, fetchGmailMessages, sendGmailMessage, etc.) siguen en route.ts y se inyectan vía context — Microsoft 365 también los usa, así que se extraerán cuando ese bloque también salga.

    Nuevo

    • 📧 Bloque Gmail (122 líneas) extraído a tools/gmail.ts
    • 🧬 17 helpers inyectados vía DI (regex EMAIL_ADDRESS_RE + parseRequestedCount + parseGmailSendIntent + fetchGmailMessages + sendGmailMessage + …)
    • typecheck verde, build verde

    Mejorado

    • Gmail también va en paralelo con web_search + db_query + spotify

    Seguridad

    • 🔒 Comportamiento idéntico — mismo orden de aplicación al systemPrompt

    Nuevo módulo

    • `src/lib/server/chat/tools/gmail.ts` (~210 líneas) — runGmailTool(ctx) → { systemPromptAddition, status, durationMs }
    • GmailToolContext con 17 helpers inyectados vía DI (ningún helper se mueve todavía).
    • Maneja capacidad real, lectura de bandeja con filtro Gmail q=, envío con borrador + confirmación, fallback mailto si no hay token.

    route.ts cambios

    • `gmailPromise` se lanza junto a webSearchPromise/dbQueryPromise/spotifyPromise en el bloque MULTI-TOOL PARALLEL.
    • Bloque inline (try/catch + 122 líneas) reemplazado por 7 líneas: `await gmailPromise` + recordTool().
    • Helpers internos (parseGmailSendIntent, etc.) siguen en route.ts hasta que Microsoft 365 también se extraiga.

    Próximos releases

    • v8.7 — Microsoft 365 (Outlook + OneDrive) ~580 líneas. Comparte helpers Gmail.
    • v8.8 — AdSense + Google Analytics + Calendar + Drive + Monday + Github (~700 líneas).
    • v8.9 — NetworkDriveRag (~1800 líneas con ~30 helpers internos).
    • v8.10 — DeepResearch (~400 líneas).
  21. v8.5.0

    Multi-tool parallel REAL — web_search + db_query + spotify corren simultáneamente

    Hito importante del refactor v8.x: ahora cuando el usuario activa múltiples tools, web_search + db_query + spotify NO esperan unos a otros — corren con Promise.all() y el tiempo total es max(web, db, spotify) en lugar de sum(). Beneficio típico: respuestas con tools 2-3× más rápidas. Implementado lanzando las promises temprano (justo después de calcular los inputs) y haciendo `await thePromise` en cada call site original — el orden de aplicación al systemPrompt se mantiene exacto.

    Nuevo

    • ⏱️ Tiempo total: max(web=5s, db=2s, spotify=1s) = 5s en lugar de 8s
    • 🛠️ typecheck verde, build verde

    Mejorado

    • web_search + db_query + spotify ahora corren EN PARALELO
    • Sin cambios de comportamiento — solo optimización de timing

    Seguridad

    • 🔒 Orden del systemPrompt preservado (mismo orden de aplicación)

    route.ts cambios

    • Justo después de las var declarations (línea ~9156), lanzar las 3 promises:
    • - webSearchPromise = effectiveWebSearch ? runWebSearchTool(...) : null
    • - dbQueryPromise = effectiveDbQuery ? runDbQueryTool(...) : null
    • - spotifyPromise = effectiveSpotify ? runSpotifyTool(...) : null
    • En cada call site original, hacer `await thePromise` en lugar de `await runXTool(...)`.
    • Orden de aplicación al systemPrompt: web → db → spotify (igual que antes).

    Próximos parallels

    • rag_search no se paraleliza aún porque está mucho antes en el flow (línea 7000) — en v8.6 mover su call al mismo punto.
    • Integraciones gmail/microsoft/etc están entre medio y no extraídas — quedan secuenciales por ahora.
    • Cuando todos los tools estén extraídos (v8.10+), un Promise.allSettled global puede paralelizar TODO.
  22. v8.4.0

    Refactor: Spotify tool extraído del monolito (cambio de plan)

    Continúa el refactor v8.x. NetworkDriveRag y DeepResearch resultaron ser MUCHO más grandes (1800 y 400+ líneas con 30+ helpers locales) — extraerlos limpiamente requiere reorganizar también esos helpers, lo que es trabajo de varias releases. Pivotamos a integraciones más self-contained: Spotify (~100 líneas) extraído a `lib/server/chat/tools/spotify.ts` con dependency injection. typecheck verde, comportamiento idéntico.

    Nuevo

    • 🎵 Nueva función pura: runSpotifyTool(ctx) → SpotifyToolResult
    • 🔌 5 helpers inyectados (fetchSpotifyPlaylists, searchSpotifyTracks, etc.)
    • ✂️ route.ts pierde ~100 líneas de spotify inline
    • ⏸️ networkDriveRag (1800 líneas) y deepResearch (400+ líneas) deferred — requieren extracción de helpers locales primero

    tools/spotify.ts

    • runSpotifyTool(ctx) maneja read + create con permisos scope-based.
    • Tipos SpotifyTrackDigest y SpotifyPlaylistDigest en módulo (compat con los del route.ts).
    • Errores: 429 (rate limit) tratado distinto que el resto.
    • spotifyPlaylistsMeta + spotifyPlaylistPreviewMeta devueltos para el caller.

    Próximo plan

    • v8.5.0: Multi-tool parallel REAL — wrapping web_search + rag + db_query + spotify (4 tools ya extraídos) en Promise.allSettled.
    • v8.6.0+: Resto de integraciones (gmail, drive, calendar, microsoft, monday, github) — se irán extrayendo cuando los helpers estén disponibles.
    • NetworkDriveRag y DeepResearch: extraer en releases dedicadas (v8.10+) tras mover helpers locales.
  23. v8.3.0

    Refactor: db_query extraído del monolito

    Continúa el refactor v8.x. El bloque MÁS COMPLEJO del chat route (db_query, ~245 líneas con SQL gen via gpt-4o-mini, fallback automático a SELECT * FROM tabla, schema inventario, telemetría) ahora vive en `lib/server/chat/tools/db-query.ts` con `runDbQueryTool(ctx) → result`. Helpers (selectDbConnectionForPrompt, sanitizeMarkdownCell, wantsDbSchemaListing, etc.) siguen en route.ts y se inyectan vía context. typecheck verde, build verde, comportamiento idéntico.

    Nuevo

    • 🧱 Nueva función pura: runDbQueryTool(ctx) → DbQueryToolResult
    • 🔌 12 helpers inyectados vía context (decryptSecret, sanitizeMarkdownCell, etc.)
    • ✂️ route.ts pierde ~245 líneas (12.276 → 12.021)
    • 📦 ChatDbConnection type movido a tools/types.ts (compartido)
    • typecheck verde, build verde, comportamiento intacto

    tools/db-query.ts (~340 líneas)

    • Status enum extendido: ok | error | no_connection | no_schema
    • runTablePreviewFallback como helper interno cerrado.
    • Imports limpios desde @/lib/db-runtime y @/lib/secret-store.
    • Tipos del context usan typeof de las funciones reales para evitar incompatibilidades de unions estrictas.

    route.ts

    • Block legacy de 245 líneas eliminado completamente.
    • Reemplazado por llamada a runDbQueryTool con 12 helpers como dependencies.
    • recordTool sigue marcando con tool name "db_query".

    Próxima release

    • v8.4.0: runNetworkDriveRag (~200 líneas) — similar al RAG pero contra network_drives + network_files.
  24. v8.2.0

    Refactor: rag_search extraído del monolito

    Continúa el refactor v8.x. El bloque inline de 75 líneas del RAG (project scope, match_file_chunks + fallback threshold + file_contents persistidos + citation tracking) ahora vive en `lib/server/chat/tools/rag-search.ts` con `runRagSearchTool(ctx) → result`. tool-timeline movido al inicio del handler para estar en scope de todos los tools. typecheck verde, build verde.

    Nuevo

    • 🧱 Nueva función pura: runRagSearchTool(ctx) → RagSearchToolResult
    • 🔄 fetchChunks helper con threshold inicial 0.62 + fallback 0.48 (idéntico al inline)
    • 🎯 Soporta scope por projectId Y por fileIds (preparado para folder/attachments en futuras releases)
    • 📦 Citation tracking estricto preservado
    • ✂️ route.ts pierde 75 líneas (12.276 → 12.201)
    • tool-timeline movido al inicio del handler (antes estaba después del bloque RAG)

    tools/rag-search.ts

    • RagSearchToolContext: serviceClient, queryEmbedding, ragMode, citeMode, projectId, fileIds[].
    • RagSearchToolResult: systemPromptAddition, sources[], chunks[], status, detail, durationMs.
    • fetchChunks(): primary threshold 0.62 → fallback 0.48 (mismo comportamiento).
    • STRICT_PROMPT_PREFIX, ASSISTED_PROMPT_PREFIX, CITATION_TRACKING_BLOCK extraídos como constantes.
    • Manejo de no_results vs error vs ok como status enum.
    • Filtrado por fileIds opcional para scope folder/attachments.

    route.ts

    • Block inline RAG-project reemplazado por llamada a runRagSearchTool.
    • _toolTimeline + recordTool movidos al inicio del handler (antes del primer tool block).
    • recordTool ahora marca el RAG con tool name "rag_project" (preparado para "rag_folder" después).

    Verificación

    • npm run typecheck → 0 errors
    • npm run build → completo, todas las rutas compiladas

    Próxima release

    • v8.3.0: runDbQuery + helpers (~250 líneas, más complejo: tiene fallback automático, schema inventario, gen SQL con gpt-4o-mini, telemetría).
  25. v8.1.0

    Refactor: web_search extraído del monolito chat route

    Continúa el refactor v8.x. El bloque inline de 80 líneas de web_search ahora vive en `lib/server/chat/tools/web-search.ts` con interfaz pura `runWebSearchTool(ctx) → result`. Los helpers (rankWebSources, collectDeepResearchImages) siguen en route.ts y se inyectan vía context — esto permite extraer la orquestación sin romper nada (otras 500 líneas de helpers se moverán en v8.x posteriores). Sin cambios funcionales, typecheck verde, build verde, comportamiento idéntico.

    Nuevo

    • 🧱 Nueva función pura: runWebSearchTool(ctx) → WebSearchToolResult
    • 🔌 Dependency injection para los helpers (rankWebSources + collectDeepResearchImages)
    • 📦 Nuevo módulo: src/lib/server/chat/tools/web-search.ts (~190 líneas)
    • 📘 Nuevo módulo: src/lib/server/chat/tools/types.ts (tipos compartidos)
    • ✂️ route.ts pierde 80 líneas inline (12.356 → 12.276)
    • typecheck verde, build verde, sin cambios de comportamiento

    Nuevo módulo tools/web-search.ts

    • WebSearchToolContext interface con rawInput, effectiveQuery, deepResearch, researchMode + helpers inyectados.
    • WebSearchToolResult interface con systemPromptAddition, webAnswerSummary, webSources, rankedWebSources, webSearchImages, durationMs, status, detail.
    • Lógica idéntica al inline original: search → enrich (si deep) → rank → format prompt → collect images.
    • Manejo de errores: try/catch interno + return {status:"error", detail}.

    route.ts cambios

    • Import: runWebSearchTool desde el nuevo módulo.
    • Block inline reemplazado por llamada a runWebSearchTool con dependencies inyectadas.
    • Variables externas (webAnswerSummary, webSources, rankedWebSources, webSearchImages, systemPrompt) actualizadas con el resultado.
    • recordTool sigue funcionando sin cambios.

    Verificación

    • npm run typecheck → 0 errors
    • npm run lint → 0 errors en mis archivos nuevos (los 132 errores existentes son de archivos no tocados)
    • npm run build → completo sin errores, todas las rutas compiladas

    Próxima release

    • v8.2.0: runRagSearch (file_chunks + match_file_chunks). Más complejo: ~300 líneas con vector search + sources push.
  26. v8.0.0

    Refactor del chat route — fundación para sacar el monolito de 12k líneas

    src/app/api/chat/route.ts tiene 12.356 líneas: 14 tool blocks, RAG, memorias, live runs, persistencia, providers... todo en un solo archivo. Esto bloquea multi-tool parallel real, streaming progressive y tests E2E. v8.0.0 establece la fundación: estructura `src/lib/server/chat/tools/`, README con roadmap completo de extracción tool-por-tool, y primera pieza extraída como prueba del patrón (`tool-timeline.ts`). Las siguientes 11 releases (v8.1 → v8.11) sacan tools una a una con tests, hasta llegar a multi-tool parallel REAL en v8.8 y streaming progressive en v8.9.

    Nuevo

    • 🏗️ Bump a v8.x.0 marca el inicio del refactor mayor del chat route.
    • 📁 Estructura nueva: src/lib/server/chat/tools/ con README arquitectónico.
    • 🧱 Primera extracción: createToolTimeline() ahora vive en tool-timeline.ts (era inline en route.ts).
    • 📋 Roadmap claro de 11 releases siguientes con scope concreto y líneas estimadas.
    • Sin cambios funcionales — el comportamiento del chat es idéntico.
    • Sin cambios de schema.
    • 🎯 Próxima release (v8.1): runWebSearch + helpers (rankWebSources, collectDeepResearchImages) — ~200 líneas extraídas.

    Estructura nueva

    • src/lib/server/chat/README.md actualizado con estado actual + roadmap completo + patrón de extracción.
    • src/lib/server/chat/tools/tool-timeline.ts — createToolTimeline() factory con métodos start/done/record/entries/toSseEvent.
    • Patrón documentado: cada tool exporta una función pura runXTool(ctx) → result que devuelve systemPromptAddition + sources + metadata.
    • Convenciones documentadas: no mutar arrays compartidos, errores con status flag, LLM intermedio recibe apiKey por context.

    route.ts (cambios mínimos)

    • Importa createToolTimeline desde el nuevo módulo.
    • recordTool() ahora delega a la instancia del timeline.
    • toolTimelineEvent generado vía _toolTimeline.toSseEvent() (sin lógica inline).
    • Sin cambios de comportamiento — typecheck verde.

    Roadmap

    • v8.1.0 → runWebSearch (-200 líneas)
    • v8.2.0 → runRagSearch (-300)
    • v8.3.0 → runDbQuery (-250)
    • v8.4.0 → runNetworkDriveRag (-200)
    • v8.5.0 → runDeepResearch (-400)
    • v8.6.0 → 7 tools de integraciones gmail/drive/calendar/spotify/microsoft/monday/github (-800)
    • v8.7.0 → runDocumentGeneration + runSpreadsheetAnalysis + runCodeInterpreter (-300)
    • v8.8.0 → Multi-tool parallel REAL con Promise.allSettled
    • v8.9.0 → Streaming progressive con SSE events conforme cada tool termina
    • v8.10.0 → Provider streams a streaming/{openai,anthropic,google}.ts
    • v8.11.0 → Memory hierarchy + system prompt builders a módulos propios
  27. v7.42.0

    UI agentes IA del canal + Tool timeline visible durante respuesta

    Cierre de los items pendientes de v7.41. Modal completo de gestión de agentes IA del canal accesible desde un botón "Agentes" en el header (gradient violet→fuchsia). Permite a los admins añadir modelos con trigger configurable (mention/keyword/always), keywords, display name, system prompt y cooldown. Y nuevo evento SSE `tool_timeline_event` que el chat route emite con los timings de cada tool ejecutado (web_search, db_query) — el cliente lo pinta como pill flotante junto al token meter durante el streaming: "🌐 Web 2.1s · 🗃️ DB 0.8s · total 2.9s". El multi-tool parallel real (Promise.all del chat route) sigue deferred — requiere tests E2E antes de tocar el path más crítico de la app.

    Nuevo

    • 🤖 Modal de agentes IA del canal (botón "Agentes" gradient en header).
    • ⏯️ Toggle on/off por agente sin tener que borrarlo.
    • 🗑️ Quitar agente con confirmación.
    • 📊 Tool timeline pill durante streaming: muestra qué tools se ejecutaron y cuánto tardaron.
    • 🌐 Iconos por tool: web_search (Globe azul), db_query (Database emerald), rag (BookOpen violet), network_drive (HardDrive amber).
    • ⏱️ Total acumulado al final de la pill ("total 2.9s").

    Mejorado

    • 🎯 UI completo: select modelo + tabs trigger (Mención/Keyword/Siempre) + keywords + display name + system prompt + cooldown.

    Arreglado

    • 🔴 Tools que fallaron salen en rose con icono de error.

    ChannelAgentsModal.tsx (nuevo)

    • Portal modal con backdrop blur + max 2xl.
    • Header con badge "AGENTES IA" + #channel-name + descripción.
    • Lista de agents con avatar bot + display name + trigger badge color-coded + keywords + system prompt preview.
    • Toggle On/Off por agente (PATCH enabled).
    • Botón eliminar (DELETE) con confirm().
    • Form de añadir colapsable: select modelo + segmented tabs trigger + keywords (CSV) + display name + cooldown number + system prompt textarea.
    • Disabled inputs si no es admin.

    ChannelView.tsx — botón Agentes

    • Nuevo botón gradient violet→fuchsia con icono Sparkles + label "Agentes" en el header.
    • showAgentsModal state que abre/cierra el modal.
    • isAdmin pasado al modal vía myChannelRole === "admin".

    chat/route.ts — SSE tool_timeline_event

    • Variable toolTimeline acumula entries {tool, ms, status, detail} durante la fase de tools.
    • Función helper recordTool(tool, startedAt, status, detail).
    • Tracking en web_search y db_query (try → ok, catch → error).
    • Emisión: data: {"type":"tool_timeline_event","data":{"tools":[...]}} antes de imageGenerationStreamEvent.
    • cleanAssistantStreamContent ahora también filtra tool_timeline_event.

    ChatInput.tsx — handler del evento

    • Parser detecta eventData.type === "tool_timeline_event".
    • window.dispatchEvent('chat-tool-timeline', {conversationId, tools}).
    • continue para no añadir al fullContent.

    ToolTimelinePill.tsx + ChatArea.tsx

    • Componente nuevo con iconos por tool, color por estado, fmtMs(ms) helper, total acumulado.
    • ChatArea escucha custom event 'chat-tool-timeline', filtra por conversationId, guarda en state.
    • Reset state al cambiar de conversación.
    • Render junto al TokenContextMeter en el header del streaming.

    Pendiente realmente difícil (deferred a v7.43+)

    • Multi-tool parallel TRUE: refactor del chat route para que web_search + RAG + db_query corran con Promise.allSettled. Requiere extraer ~400 líneas inline a funciones puras + tests E2E del path completo (chat con cada tool y combinaciones) antes de tocar.
    • Streaming progressive REAL: convertir todo el chat route a SSE desde el inicio (no solo después de los tools). Otra ronda de refactor profundo.
  28. v7.41.0

    AI permanente en canales — agente vive en el canal con triggers configurables

    Implementada la mejora #6 pendiente de v7.40.0: ahora puedes asignar un modelo IA a un canal con tres modos de activación (mention/keyword/always) + cooldown anti-loop + system prompt personalizado para darle personalidad. Antes la IA solo respondía cuando la mencionabas explícitamente con @. Multi-tool parallel y streaming progressive de tools quedan deferred a v7.42 porque requieren refactor profundo (>400 líneas) del chat route que no es seguro hacer en una sola pasada.

    Nuevo

    • 🤖 Modelos IA viven en canales con trigger configurable.
    • 🎯 3 modos de trigger: `mention` (@ explícito), `keyword` (palabras clave), `always` (responde a todo).
    • ⏱️ Cooldown configurable (default 5s) para evitar bucles cuando trigger=always.
    • 👤 Display name custom — el agente puede llamarse "ResearchBot" en lugar del nombre del modelo.
    • 🛡️ Tabla channel_agent_last_reply para implementar cooldown sin race conditions.

    Mejorado

    • 🎨 System prompt personalizado por canal — dale personalidad/foco al agente.

    Seguridad

    • 🔒 RLS: solo admins del canal pueden asignar/quitar agentes. Cualquier miembro los ve.

    Schema (Supabase)

    • Tabla channel_agents (channel_id, agent_id, model_config_id, trigger_mode, trigger_keywords, display_name, system_prompt, cooldown_seconds, enabled).
    • CHECK constraint trigger_mode IN (mention, keyword, always).
    • CHECK constraint: agent_id O model_config_id deben estar set.
    • UNIQUE(channel_id, agent_id) y UNIQUE(channel_id, model_config_id).
    • Indice partial idx_channel_agents_channel WHERE enabled=true.
    • Tabla channel_agent_last_reply (channel_agent_id PK, last_reply_at) para cooldown.
    • Trigger touch_updated_at automático.
    • 4 policies RLS (SELECT cualquier miembro, INSERT/UPDATE/DELETE solo admin).

    API endpoints nuevos

    • GET /api/channels/[id]/agents — lista agents activos con info del modelo enriched.
    • POST /api/channels/[id]/agents — asigna modelo/agent al canal con trigger config.
    • PATCH /api/channels/[id]/agents/[agentId] — actualiza trigger_mode, keywords, system_prompt, etc.
    • DELETE /api/channels/[id]/agents/[agentId] — quita el agent del canal.

    Auto-trigger en POST /api/channels/[id]/messages

    • 1) Mantiene flujo legacy: si hay @mention explícita, el modelo responde igual que antes.
    • 2) Si NO hubo mention, comprueba channel_agents activos con trigger evaluation:
    • - always → triggered=true
    • - keyword → triggered=alguna keyword aparece en lower-case
    • - mention → ya cubierto por el flujo legacy
    • 3) Cooldown check: si han pasado <cooldown_seconds desde last_reply_at, skip.
    • 4) Resuelve ResolvedModel completo via resolveModelByConfigId() (helper nuevo).
    • 5) Pasa extraSystemPrompt del agent a generateChannelModelReply para personality.
    • 6) Marca last_reply_at vía upsert en channel_agent_last_reply.
    • 7) attachments_json del mensaje incluye {kind: "agent_trigger", reason} para debug.

    Pendiente para v7.42

    • UI admin para asignar agentes desde la página del canal (usar API REST que ya existe).
    • Multi-tool parallel: web_search + RAG + db_query con Promise.all en chat/route.ts (~400 líneas refactor).
    • Streaming progresivo: emitir SSE events tool_start/tool_chunk/tool_done conforme llegan resultados de cada tool.
  29. v7.40.0

    IA: 9 mejoras (auto-routing, hybrid RAG, self-RAG, memory hierarchy, citations, auto-debug, token live)

    Paquete grande de mejoras en el sistema de IA: medidor de tokens y context window en vivo durante streaming; detector de formato que añade lenguaje a bloques de código sin language; endpoint de auto-debug que analiza por qué falló una respuesta y propone arreglos (gpt-4o-mini); citation tracking estricto en RAG con formato [N] y verificación; detector de tipo de tarea (code/reasoning/creative/simple/general) extendiendo el auto-router existente; nuevo endpoint /api/memory/hierarchy que consolida memorias proyecto > carpeta > conversación con deduplicación; nuevo endpoint /api/rag/should-search (Self-RAG) que decide si la query necesita RAG/web/db antes de gastar tokens; función SQL match_file_chunks_hybrid que combina vector + tsvector con pesos 70/30. Quedan pendientes (refactor profundo del chat route): multi-tool en paralelo, streaming progresivo y AI permanente en canales.

    Nuevo

    • 📊 TokenContextMeter: tokens en vivo + barra de context window con color (verde/amber/rojo) + coste USD acumulado.
    • 🔧 enhanceMarkdownContent: detecta SQL/JS/TS/Python/JSON/Bash/YAML/CSS/HTML en bloques sin lenguaje declarado.
    • 📚 Citation tracking estricto: cada claim factual con [N] obligatorio, "no inventes citas", "di cuando no tengas info".
    • 🧠 detectTaskType: clasifica input como code/reasoning/creative/simple/general usando ~15 patrones regex.
    • 🪜 Memory hierarchy: GET /api/memory/hierarchy consolida user+project+folder+conversation memories con dedup heurístico y orden por especificidad.
    • 🤔 Self-RAG: POST /api/rag/should-search decide si necesita RAG/web/db con heurística + gpt-4o-mini fallback. Conservador por defecto.
    • 🔍 Hybrid search: nueva función SQL match_file_chunks_hybrid (vector 70% + ts_rank_cd 30%) con normalización por subset, top-50 vector pre-filter, tsvector index GIN.

    Arreglado

    • 🐞 AutoDebugCard: tras thumbs-down, gpt-4o-mini analiza qué falló y sugiere fixes (cambiar modelo, añadir contexto, activar tool, replantear).

    UI nueva

    • src/components/chat/TokenContextMeter.tsx — pill flotante con tokens, context%, $ coste.
    • src/components/chat/AutoDebugCard.tsx — card rose con sugerencias de fix tras thumbs-down.
    • src/lib/format-detector.ts — detectCodeLanguage(), looksLikeTable(), enhanceMarkdownContent(), detectDates().
    • ChatArea.tsx — meter visible debajo del nombre del modelo durante streaming.
    • MessageBubble.tsx — botón "🐞 Auto-debug" tras thumbs-down + render con enhanceMarkdownContent.

    API endpoints nuevos

    • POST /api/debug/analyze — analiza un message_id y devuelve {diagnosis, suggestions[]}.
    • GET /api/memory/hierarchy?folder_id=&project_id=&conversation_id= — devuelve memories consolidadas con scope+pinned+counts.
    • POST /api/rag/should-search — clasificador self-RAG, devuelve {should_rag, should_web, should_db, reason, confidence}.

    Backend mejoras

    • auto-router.ts: detectTaskType() y TASK_PREFERRED_FAMILY map (code → codex/sonnet, reasoning → o1/opus, creative → 4o/sonnet).
    • chat/route.ts: cite_mode prompt reescrito a citation tracking estricto con [N] obligatorio y "no inventes".
    • chat/route.ts: detectTaskType() invocado en auto-route para enriquecer el system prompt (futuro).

    Database

    • file_chunks: nueva columna content_tsv tsvector GENERATED ALWAYS AS (to_tsvector(spanish, content)) STORED.
    • Index GIN idx_file_chunks_content_tsv.
    • Función match_file_chunks_hybrid(user_id, query_text, query_embedding, match_count, file_ids) → top-K combinando vector + keyword.
    • Pre-filter de 50 candidatos por vector + normalización Z-score por subset + score 0.7*vec + 0.3*kw.

    Pendiente (refactor profundo)

    • Multi-tool en paralelo: requiere refactor del chat route para que web_search + RAG + DB corran con Promise.all en lugar de await secuencial.
    • Streaming progresivo: enviar resultados parciales de tools como SSE events conforme llegan.
    • AI permanente en canales: feature aparte que merece su propio análisis. La tabla agents y agent_executions ya existen.
  30. v7.39.0

    Carpetas: anidación, compartir, plantillas y banner — UI completa

    Cierre de la línea de carpetas avanzadas iniciada en v7.37/v7.38. Ahora todas las funciones que tenían el schema listo en DB tienen UI funcional: árbol jerárquico de carpetas en el sidebar, modal de invitar usuarios con roles (viewer/editor/admin), galería de plantillas en el modal de crear carpeta, "Guardar como plantilla" desde Settings, banner image (URL) y picker de carpeta padre. Smart filters se queda para más adelante (necesita un editor de query JSON).

    Nuevo

    • 🪺 Sidebar renderiza carpetas anidadas como árbol con indentación + línea punteada lateral.
    • 🔗 Tab "Compartir" en Settings con búsqueda por email + roles + cambiar/quitar acceso.
    • 💾 Botón "Guardar como plantilla" en tab Organización (con flag pública/privada).
    • 🖼️ Campo "Banner image URL" con preview live.
    • 🌲 Picker de carpeta padre (anidación).
    • 📊 use_count se incrementa cuando alguien usa una plantilla.

    Mejorado

    • 📦 Galería de plantillas en CreateFolderModal con preview y aplicación instantánea.

    API endpoints nuevos

    • GET / POST / PATCH /api/folder-templates — list (own + public), create, increment use_count.
    • DELETE / PATCH /api/folder-templates/:id — solo owner via RLS.
    • GET / POST /api/folders/:id/shares — list (con profiles join) e invite por email/user_id.
    • PATCH / DELETE /api/folders/:id/shares/:shareId — cambiar rol o quitar acceso.
    • Validación de permisos: owner + admins de la carpeta pueden invitar/eliminar; el invitado puede salirse.

    CreateFolderModal — Plantillas

    • Carga GET /api/folder-templates al abrir.
    • Sección colapsable "Empezar desde una plantilla" con grid 2 columnas.
    • Cada tarjeta muestra icono+color, nombre, descripción, badge "Pública", use_count y count tools.
    • Click → applyTemplate() rellena icon/accent/instructions automáticamente.
    • Pill superior con nombre de plantilla aplicada + X para quitarla.
    • Al crear, se incrementa use_count vía PATCH.

    FolderSettingsModal — 2 tabs nuevas

    • Tab "Compartir": email input + role select + invite button (gradient violet→fuchsia).
    • Lista de personas con avatar, nombre, fecha invitación, role select (viewer/editor/admin), botón quitar.
    • Tab "Organización": banner URL con preview + parent folder picker + sección "Guardar como plantilla".
    • Save as template: name + description + toggle pública/privada.

    FolderSettingsModal — saveFolder

    • Persiste banner_url y parent_folder_id junto con los demás campos.

    Sidebar — árbol jerárquico

    • Agrupa folders por parent_folder_id en una map.
    • Renderiza root folders primero. Cada nivel tiene paddingLeft proporcional (max 3 niveles).
    • Borde lateral punteado para indicar la jerarquía visual.
    • Recursive renderWithChildren() ilimitado en profundidad.

    Pendiente

    • 🧠 Smart filters: editor visual de filtros JSON. Schema (smart_filters_json) listo en DB.
    • 🖼️ Banner upload: actualmente solo URL. Falta integración con Storage para upload.
    • 🤖 Auto-classify: sugerir carpeta para chat nuevo basado en primer mensaje.

1036 versiones publicadas · página 32 de 35. Míralo dentro de la app.