Saltar al contenido principal

Chat embebido (prueba de concepto)

Tipo: Prueba de concepto — widget de chat externo embebido en el tema Ubicación: theme/cdigital/templates/theme_boost/footer.mustache, theme/cdigital/templates/frontpage.mustache, theme/cdigital/templates/head.mustache, theme/cdigital/templates/theme_boost/head.mustache Alcance: 3 — Agente IA (exploración exploratoria, independiente de la capa de datos formal) Estado: Prueba de concepto — con incidencia abierta

Propósito

Validar de forma temprana la experiencia de un asistente conversacional flotante para el estudiante, como antesala visual del tutor de IA del Alcance 3. El widget no está conectado a la capa de datos del campus (local_pccntr8203403_dashboard) ni a ningún endpoint propio de Moodle: apunta a un workflow externo de n8n.

La interfaz definitiva del asistente es el Drawer IA — elemento Aside - NavigationDrawer (AI Assistant Chat Panel) del diseño en Figma; este widget @n8n/chat es solo una exploración previa de esa experiencia.

Implementación actual

El tema theme_cdigital carga el paquete @n8n/chat directamente desde un CDN (cdn.jsdelivr.net) en todas las páginas:

  • templates/head.mustache y templates/theme_boost/head.mustache enlazan la hoja de estilos @n8n/chat/dist/style.css.
  • templates/theme_boost/footer.mustache (override del footer de Boost, presente en todo layout que extienda theme_boost/footer, incluido mydashboard) y templates/frontpage.mustache incluyen un <script type="module"> que importa @n8n/chat/dist/chat.bundle.es.js y llama a createChat() con un webhookUrl que apunta a una instancia de n8n alojada en Azure Container Apps.

Por estar en el footer compartido, el widget aparece en cualquier página que use el layout estándar del tema, incluida el Área personal (/my/).

Incidencia conocida: conflicto con RequireJS

El bundle @n8n/chat/dist/chat.bundle.es.js incluye, entre sus dependencias internas, un wrapper UMD que detecta typeof define === 'function' && define.amd. Como Moodle expone globalmente el define de RequireJS, ese wrapper se autorregistra como módulo AMD anónimo al ejecutarse el <script type="module">.

RequireJS intercepta esa llamada a define() fuera de su flujo normal de carga de módulos (no la asocia a ningún require([...]) pendiente) y lanza en consola:

Uncaught (in promise) Error: Mismatched anonymous define() module: function() { ... }

El cuerpo de la función reportada en el error corresponde a un parser de srcset empaquetado dentro de @n8n/chat, no a código de Moodle ni del tema. El error se reproduce de forma consistente en cualquier página (incluida /my/) tras una purga de cachés, por lo que no se trata de un problema de caché sino del propio script.

Impacto

  • Ruido en la consola del navegador en todas las páginas del sitio.
  • Riesgo de que el wrapper UMD interfiera con la cola de carga de módulos AMD de Moodle/Boost en escenarios menos predecibles (orden de carga, módulos lazy).

Posibles correcciones (sin aplicar todavía)

  • Aislar el import() del bundle ocultando temporalmente window.define mientras se ejecuta (patrón común para integrar librerías UMD en páginas con AMD global).
  • Cargar el widget dentro de un <iframe> con su propio contexto global, sin RequireJS.
  • Auto-alojar una build del bundle sin la detección UMD/AMD, o usar la variante "vanilla" del paquete pensada para <script> clásico.

Relación con el Alcance 3

Este POC es independiente de la arquitectura decidida en ADR-001 (funciones externas de Web Services sobre local_pccntr8203403_dashboard). Antes de avanzar como desarrollo formal del Alcance 3 debe decidirse si el asistente conversacional:

  • se conecta a la capa de datos propia del campus en lugar de (o además de) el webhook externo de n8n, y
  • se resuelve la incidencia de RequireJS descrita arriba, o se reemplaza por una implementación que no choque con el AMD global de Moodle.

Mientras tanto, permanece como prueba de concepto y no como funcionalidad soportada.