wu-framework 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wu-framework.cjs.js","sources":["../src/core/wu-logger.js","../src/core/wu-loader.js","../src/core/wu-style-bridge.js","../src/core/wu-proxy-sandbox.js","../src/core/wu-snapshot-sandbox.js","../src/core/wu-sandbox.js","../src/core/wu-manifest.js","../src/core/wu-store.js","../src/core/wu-app.js","../src/core/wu-cache.js","../src/core/wu-event-bus.js","../src/core/wu-performance.js","../src/core/wu-plugin.js","../src/core/wu-strategies.js","../src/core/wu-error-boundary.js","../src/core/wu-hooks.js","../src/core/wu-html-parser.js","../src/core/wu-script-executor.js","../src/core/wu-iframe-sandbox.js","../src/core/wu-prefetch.js","../src/core/wu-overrides.js","../src/core/wu-core.js","../src/ai/wu-ai-provider.js","../src/ai/wu-ai-permissions.js","../src/ai/wu-ai-schema.js","../src/ai/wu-ai-context.js","../src/ai/wu-ai-actions.js","../src/ai/wu-ai-conversation.js","../src/ai/wu-ai-triggers.js","../src/ai/wu-ai-agent.js","../src/ai/wu-ai-browser-primitives.js","../src/ai/wu-ai-orchestrate.js","../src/ai/wu-ai-browser.js","../src/ai/wu-ai.js","../src/core/wu-mcp-bridge.js","../src/index.js"],"sourcesContent":["/**\r\n * 📝 WU-LOGGER: Sistema de logging inteligente para entornos\r\n * Controla los logs automáticamente según el entorno\r\n */\r\n\r\nexport class WuLogger {\r\n constructor() {\r\n // Detectar entorno automáticamente\r\n this.isDevelopment = this.detectEnvironment();\r\n // En desarrollo: warn (menos ruido), en producción: error\r\n this.logLevel = this.isDevelopment ? 'warn' : 'error';\r\n\r\n this.levels = {\r\n debug: 0,\r\n info: 1,\r\n warn: 2,\r\n error: 3,\r\n silent: 4\r\n };\r\n }\r\n\r\n /**\r\n * Detectar si estamos en desarrollo\r\n */\r\n detectEnvironment() {\r\n // 1. Explicit flag takes priority\r\n if (typeof window !== 'undefined' && window.WU_DEBUG === true) return true;\r\n if (typeof window !== 'undefined' && window.WU_DEBUG === false) return false;\r\n\r\n // 2. NODE_ENV check (works in bundlers and Node)\r\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return false;\r\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development') return true;\r\n\r\n // 3. Browser heuristics (only if window exists)\r\n if (typeof window !== 'undefined' && window.location) {\r\n const hostname = window.location.hostname;\r\n if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]') return true;\r\n\r\n // URL param override\r\n try {\r\n if (new URLSearchParams(window.location.search).has('wu-debug')) return true;\r\n } catch {}\r\n }\r\n\r\n // 4. Default: assume production\r\n return false;\r\n }\r\n\r\n /**\r\n * Configurar nivel de logging\r\n */\r\n setLevel(level) {\r\n this.logLevel = level;\r\n return this;\r\n }\r\n\r\n /**\r\n * Habilitar/deshabilitar development mode\r\n */\r\n setDevelopment(isDev) {\r\n this.isDevelopment = isDev;\r\n this.logLevel = isDev ? 'debug' : 'error';\r\n return this;\r\n }\r\n\r\n /**\r\n * Verificar si debemos mostrar el log\r\n */\r\n shouldLog(level) {\r\n return this.levels[level] >= this.levels[this.logLevel];\r\n }\r\n\r\n /**\r\n * Logging methods\r\n */\r\n debug(...args) {\r\n if (this.shouldLog('debug')) {\r\n console.log(...args);\r\n }\r\n }\r\n\r\n info(...args) {\r\n if (this.shouldLog('info')) {\r\n console.info(...args);\r\n }\r\n }\r\n\r\n warn(...args) {\r\n if (this.shouldLog('warn')) {\r\n console.warn(...args);\r\n }\r\n }\r\n\r\n error(...args) {\r\n if (this.shouldLog('error')) {\r\n console.error(...args);\r\n }\r\n }\r\n\r\n /**\r\n * Logging con contexto Wu\r\n */\r\n wu(level, ...args) {\r\n if (this.shouldLog(level)) {\r\n const method = level === 'debug' ? 'log' : level;\r\n console[method]('[Wu]', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * Helper methods específicos para Wu\r\n */\r\n wuDebug(...args) { this.wu('debug', ...args); }\r\n wuInfo(...args) { this.wu('info', ...args); }\r\n wuWarn(...args) { this.wu('warn', ...args); }\r\n wuError(...args) { this.wu('error', ...args); }\r\n}\r\n\r\n// Singleton instance\r\nexport const logger = new WuLogger();\r\n\r\n// Helper para compatibilidad con logs existentes\r\nexport const wuLog = {\r\n debug: (...args) => logger.wuDebug(...args),\r\n info: (...args) => logger.wuInfo(...args),\r\n warn: (...args) => logger.wuWarn(...args),\r\n error: (...args) => logger.wuError(...args)\r\n};\r\n\r\n/**\r\n * 🔇 Silenciar todos los logs de Wu Framework\r\n * Útil en producción para eliminar todo el ruido\r\n */\r\nexport function silenceAllLogs() {\r\n logger.setLevel('silent');\r\n}\r\n\r\n/**\r\n * 🔊 Restaurar logs (nivel debug)\r\n */\r\nexport function enableAllLogs() {\r\n logger.setLevel('debug');\r\n}","/**\r\n * WU-LOADER: SISTEMA DE CARGA DINAMICA UNIVERSAL\r\n * Carga aplicaciones y componentes sin depender del framework\r\n *\r\n * Cache strategy: LRU with TTL eviction.\r\n * Entries track lastAccess time. When the cache reaches maxCacheSize,\r\n * the least recently accessed entry is evicted. Entries older than\r\n * cacheTTL are treated as stale and removed on access or eviction.\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\n/**\r\n * @typedef {Object} WuLoaderOptions\r\n * @property {number} [maxCacheSize=50] - Maximum cache entries\r\n * @property {number} [cacheTTL=1800000] - Cache TTL in ms (default 30min)\r\n */\r\n\r\n/**\r\n * @typedef {Object} WuLoaderStats\r\n * @property {number} cached - Number of cached entries\r\n * @property {number} loading - Number of in-flight loads\r\n * @property {number} maxCacheSize - Max cache size setting\r\n * @property {number} cacheTTL - Cache TTL setting\r\n * @property {string[]} cacheKeys - Cached URL keys\r\n */\r\n\r\nexport class WuLoader {\r\n /**\r\n * @param {Object} options\r\n * @param {number} [options.maxCacheSize=50] - Maximum number of entries in the cache\r\n * @param {number} [options.cacheTTL=1800000] - Time-to-live for cache entries in ms (default 30 minutes)\r\n */\r\n constructor(options = {}) {\r\n this.maxCacheSize = options.maxCacheSize ?? 50;\r\n this.cacheTTL = options.cacheTTL ?? 1800000;\r\n this.cache = new Map();\r\n this.loadingPromises = new Map();\r\n\r\n logger.debug('[WuLoader] Dynamic loader initialized');\r\n }\r\n\r\n /**\r\n * Read from cache with TTL validation and LRU access tracking.\r\n * Returns undefined if the entry does not exist or has expired.\r\n * @param {string} key\r\n * @returns {string|undefined}\r\n */\r\n _cacheGet(key) {\r\n if (!this.cache.has(key)) {\r\n return undefined;\r\n }\r\n\r\n const entry = this.cache.get(key);\r\n const now = Date.now();\r\n\r\n if (now - entry.timestamp > this.cacheTTL) {\r\n this.cache.delete(key);\r\n logger.debug(`[WuLoader] Cache expired for: ${key}`);\r\n return undefined;\r\n }\r\n\r\n // Promote: delete and re-insert so iteration order reflects recency.\r\n // Map iteration order in JS follows insertion order, so the oldest\r\n // inserted entry is always first -- exactly what we need for LRU eviction.\r\n this.cache.delete(key);\r\n entry.lastAccess = now;\r\n this.cache.set(key, entry);\r\n\r\n return entry.code;\r\n }\r\n\r\n /**\r\n * Write to cache. Evicts stale and LRU entries before inserting.\r\n * @param {string} key\r\n * @param {string} code\r\n */\r\n _cacheSet(key, code) {\r\n // If the key already exists, remove it first so re-insertion\r\n // moves it to the end (most-recently-used position).\r\n if (this.cache.has(key)) {\r\n this.cache.delete(key);\r\n }\r\n\r\n this._evictIfNeeded();\r\n\r\n const now = Date.now();\r\n this.cache.set(key, {\r\n code,\r\n timestamp: now,\r\n lastAccess: now\r\n });\r\n }\r\n\r\n /**\r\n * Evict entries until cache is below maxCacheSize.\r\n *\r\n * Two-pass strategy:\r\n * 1. Remove all expired entries (TTL exceeded).\r\n * 2. If still at capacity, remove the least recently accessed entry.\r\n * Because Map preserves insertion order and _cacheGet promotes on\r\n * access, the first key from the iterator is always the LRU entry.\r\n */\r\n _evictIfNeeded() {\r\n const now = Date.now();\r\n\r\n // Pass 1: purge expired entries\r\n for (const [key, entry] of this.cache) {\r\n if (now - entry.timestamp > this.cacheTTL) {\r\n this.cache.delete(key);\r\n logger.debug(`[WuLoader] Evicted expired entry: ${key}`);\r\n }\r\n }\r\n\r\n // Pass 2: evict LRU entries until we are under the limit\r\n while (this.cache.size >= this.maxCacheSize) {\r\n // Map.keys().next() gives us the oldest-inserted key (LRU)\r\n const oldestKey = this.cache.keys().next().value;\r\n this.cache.delete(oldestKey);\r\n logger.debug(`[WuLoader] Evicted LRU entry: ${oldestKey}`);\r\n }\r\n }\r\n\r\n /**\r\n * Cargar aplicacion completa\r\n * @param {string} appUrl - URL base de la aplicacion\r\n * @param {Object} manifest - Manifest de la aplicacion\r\n * @returns {string} Codigo JavaScript de la aplicacion\r\n */\r\n async loadApp(appUrl, manifest) {\r\n // Sentinel gate: block code loading for unverified clients\r\n await this._ensureSentinelVerified();\r\n\r\n const entryFile = manifest?.entry || 'index.js';\r\n const fullUrl = `${appUrl}/${entryFile}`;\r\n\r\n logger.debug(`[WuLoader] Loading app from: ${fullUrl}`);\r\n\r\n try {\r\n // Check cache with TTL and LRU tracking\r\n const cached = this._cacheGet(fullUrl);\r\n if (cached !== undefined) {\r\n logger.debug(`[WuLoader] Cache hit for: ${fullUrl}`);\r\n return cached;\r\n }\r\n\r\n // Check if already loading\r\n if (this.loadingPromises.has(fullUrl)) {\r\n logger.debug(`[WuLoader] Loading in progress for: ${fullUrl}`);\r\n return await this.loadingPromises.get(fullUrl);\r\n }\r\n\r\n // Create loading promise\r\n const loadingPromise = this.fetchCode(fullUrl);\r\n this.loadingPromises.set(fullUrl, loadingPromise);\r\n\r\n const code = await loadingPromise;\r\n\r\n // Clean up loading promise and cache result\r\n this.loadingPromises.delete(fullUrl);\r\n this._cacheSet(fullUrl, code);\r\n\r\n logger.debug(`[WuLoader] App loaded successfully: ${fullUrl}`);\r\n return code;\r\n\r\n } catch (error) {\r\n this.loadingPromises.delete(fullUrl);\r\n console.error(`[WuLoader] Failed to load app: ${fullUrl}`, error);\r\n throw new Error(`Failed to load app from ${fullUrl}: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Cargar componente especifico\r\n * @param {string} appUrl - URL base de la aplicacion\r\n * @param {string} componentPath - Ruta del componente\r\n * @returns {Function} Funcion del componente\r\n */\r\n async loadComponent(appUrl, componentPath) {\r\n // Sentinel gate\r\n await this._ensureSentinelVerified();\r\n\r\n // Normalizar ruta del componente\r\n let normalizedPath = componentPath;\r\n if (normalizedPath.startsWith('./')) {\r\n normalizedPath = normalizedPath.substring(2);\r\n }\r\n if (!normalizedPath.endsWith('.js') && !normalizedPath.endsWith('.jsx')) {\r\n normalizedPath += '.js';\r\n }\r\n\r\n const fullUrl = `${appUrl}/${normalizedPath}`;\r\n\r\n logger.debug(`[WuLoader] Loading component from: ${fullUrl}`);\r\n\r\n try {\r\n // Cargar codigo del componente\r\n const code = await this.loadCode(fullUrl);\r\n\r\n // Crear funcion que retorna el componente\r\n const componentFunction = new Function('require', 'module', 'exports', `\r\n ${code}\r\n return typeof module.exports === 'function' ? module.exports :\r\n typeof module.exports === 'object' && module.exports.default ? module.exports.default :\r\n exports.default || exports;\r\n `);\r\n\r\n // Ejecutar y obtener el componente\r\n const fakeModule = { exports: {} };\r\n const fakeRequire = (name) => {\r\n logger.warn(`[WuLoader] Component ${componentPath} requires ${name} - not supported yet`);\r\n return {};\r\n };\r\n\r\n const component = componentFunction(fakeRequire, fakeModule, fakeModule.exports);\r\n\r\n logger.debug(`[WuLoader] Component loaded: ${componentPath}`);\r\n return component;\r\n\r\n } catch (error) {\r\n console.error(`[WuLoader] Failed to load component: ${componentPath}`, error);\r\n throw new Error(`Failed to load component ${componentPath}: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Cargar codigo con cache\r\n * @param {string} url - URL del archivo\r\n * @returns {string} Codigo JavaScript\r\n */\r\n async loadCode(url) {\r\n // Check cache with TTL and LRU tracking\r\n const cached = this._cacheGet(url);\r\n if (cached !== undefined) {\r\n return cached;\r\n }\r\n\r\n // Check if already loading\r\n if (this.loadingPromises.has(url)) {\r\n return await this.loadingPromises.get(url);\r\n }\r\n\r\n // Create loading promise\r\n const loadingPromise = this.fetchCode(url);\r\n this.loadingPromises.set(url, loadingPromise);\r\n\r\n try {\r\n const code = await loadingPromise;\r\n this.loadingPromises.delete(url);\r\n this._cacheSet(url, code);\r\n return code;\r\n } catch (error) {\r\n this.loadingPromises.delete(url);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Realizar fetch del codigo\r\n * @param {string} url - URL del archivo\r\n * @returns {string} Codigo JavaScript\r\n */\r\n async fetchCode(url) {\r\n const response = await fetch(url, {\r\n cache: 'no-cache',\r\n headers: {\r\n 'Accept': 'application/javascript, text/javascript, */*'\r\n }\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n\r\n const code = await response.text();\r\n\r\n if (!code.trim()) {\r\n throw new Error('Empty response');\r\n }\r\n\r\n return code;\r\n }\r\n\r\n /**\r\n * Precargar aplicaciones\r\n * @param {Array} appConfigs - Configuraciones de aplicaciones\r\n */\r\n async preload(appConfigs) {\r\n logger.debug(`[WuLoader] Preloading ${appConfigs.length} apps...`);\r\n\r\n const preloadPromises = appConfigs.map(async (config) => {\r\n try {\r\n await this.loadApp(config.url, config.manifest);\r\n logger.debug(`[WuLoader] Preloaded: ${config.name}`);\r\n } catch (error) {\r\n logger.warn(`[WuLoader] Failed to preload ${config.name}:`, error.message);\r\n }\r\n });\r\n\r\n await Promise.allSettled(preloadPromises);\r\n logger.debug(`[WuLoader] Preload completed`);\r\n }\r\n\r\n /**\r\n * Verificar si una URL esta disponible\r\n * @param {string} url - URL a verificar\r\n * @returns {boolean} True si esta disponible\r\n */\r\n async isAvailable(url) {\r\n try {\r\n const response = await fetch(url, { method: 'HEAD' });\r\n return response.ok;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Resolver dependencias de imports\r\n * @param {Array} imports - Lista de imports del manifest\r\n * @param {Map} availableApps - Apps disponibles\r\n */\r\n async resolveDependencies(imports, availableApps) {\r\n const resolved = new Map();\r\n\r\n for (const importPath of imports || []) {\r\n const [appName, componentName] = importPath.split('.');\r\n\r\n if (!appName || !componentName) {\r\n logger.warn(`[WuLoader] Invalid import format: ${importPath}`);\r\n continue;\r\n }\r\n\r\n const app = availableApps.get(appName);\r\n if (!app) {\r\n logger.warn(`[WuLoader] Import app not found: ${appName}`);\r\n continue;\r\n }\r\n\r\n const manifest = app.manifest;\r\n const exportPath = manifest?.wu?.exports?.[componentName];\r\n\r\n if (!exportPath) {\r\n logger.warn(`[WuLoader] Export not found: ${importPath}`);\r\n continue;\r\n }\r\n\r\n try {\r\n const component = await this.loadComponent(app.url, exportPath);\r\n resolved.set(importPath, component);\r\n logger.debug(`[WuLoader] Resolved dependency: ${importPath}`);\r\n } catch (error) {\r\n console.error(`[WuLoader] Failed to resolve: ${importPath}`, error);\r\n }\r\n }\r\n\r\n return resolved;\r\n }\r\n\r\n /**\r\n * Limpiar cache\r\n * @param {string} pattern - Patron opcional para limpiar URLs especificas\r\n */\r\n clearCache(pattern) {\r\n if (pattern) {\r\n const regex = new RegExp(pattern);\r\n for (const [url] of this.cache) {\r\n if (regex.test(url)) {\r\n this.cache.delete(url);\r\n logger.debug(`[WuLoader] Cleared cache for: ${url}`);\r\n }\r\n }\r\n } else {\r\n this.cache.clear();\r\n logger.debug(`[WuLoader] Cache cleared completely`);\r\n }\r\n }\r\n\r\n /**\r\n * Obtener estadisticas del loader\r\n */\r\n getStats() {\r\n return {\r\n cached: this.cache.size,\r\n maxCacheSize: this.maxCacheSize,\r\n cacheTTL: this.cacheTTL,\r\n loading: this.loadingPromises.size,\r\n cacheKeys: Array.from(this.cache.keys())\r\n };\r\n }\r\n\r\n // ── Sentinel Gate ─────────────────────────────────────────────────\r\n // Blocks code loading until the client is verified as human.\r\n // Scrapers that execute JS but don't pass proof-of-work get nothing.\r\n\r\n async _ensureSentinelVerified() {\r\n // Skip in development / localhost (sentinel is for production)\r\n if (typeof window === 'undefined') return;\r\n const host = window.location?.hostname || '';\r\n if (host === 'localhost' || host === '127.0.0.1' || host === '0.0.0.0') return;\r\n\r\n // If sentinel is not loaded, allow (backwards compat — site doesn't use sentinel)\r\n if (!window.__wu_sentinel) return;\r\n\r\n // Already verified? Proceed.\r\n if (window.__wu_sentinel.isVerified()) return;\r\n\r\n // Wait for sentinel verification (max 10 seconds)\r\n await new Promise((resolve, reject) => {\r\n // Check if verified during wait\r\n if (window.__wu_sentinel.isVerified()) {\r\n resolve();\r\n return;\r\n }\r\n\r\n const timeout = setTimeout(() => {\r\n cleanup();\r\n reject(new Error('[WuLoader] Sentinel verification timeout — content blocked'));\r\n }, 10000);\r\n\r\n const onVerified = () => {\r\n cleanup();\r\n resolve();\r\n };\r\n\r\n function cleanup() {\r\n clearTimeout(timeout);\r\n window.removeEventListener('wu:sentinel:verified', onVerified);\r\n }\r\n\r\n window.addEventListener('wu:sentinel:verified', onVerified);\r\n\r\n // Check periodically in case event was missed\r\n const check = setInterval(() => {\r\n if (window.__wu_sentinel.isVerified()) {\r\n clearInterval(check);\r\n cleanup();\r\n resolve();\r\n }\r\n }, 100);\r\n\r\n // Clean up interval on timeout too\r\n const origCleanup = cleanup;\r\n cleanup = function() {\r\n clearInterval(check);\r\n origCleanup();\r\n };\r\n });\r\n }\r\n}\r\n","/**\r\n * 🎨 WU-STYLE-BRIDGE: SHADOW DOM STYLE SHARING SYSTEM\r\n *\r\n * Comparte automáticamente estilos de node_modules entre padre e hijos Shadow DOM\r\n * Soluciona el problema de aislamiento CSS en microfrontends\r\n *\r\n * MODOS DE INYECCIÓN DE ESTILOS:\r\n * ================================\r\n *\r\n * 1. \"shared\" (default):\r\n * - Inyecta TODOS los estilos del documento padre en el Shadow DOM\r\n * - Incluye: librerías (Element Plus, Vue Flow), estilos globales, etc.\r\n * - Ideal para: Apps que necesitan compartir un design system común\r\n * - Riesgo de colisiones: ALTO\r\n *\r\n * 2. \"isolated\":\r\n * - NO inyecta estilos externos\r\n * - Usa el encapsulamiento NATIVO del Shadow DOM\r\n * - La app debe incluir sus propios estilos (CSS-in-JS, scoped styles, etc.)\r\n * - Ideal para: Apps con estilos completamente independientes\r\n * - Riesgo de colisiones: NINGUNO\r\n *\r\n * 3. \"fully-isolated\":\r\n * - Inyecta SOLO los estilos propios de la micro-app específica\r\n * - Detecta estilos por patrón: packages/appName/src/\r\n * - Usa MutationObserver para HMR de Vite\r\n * - Ideal para: Apps que necesitan sus estilos pero no los globales\r\n * - Riesgo de colisiones: NINGUNO\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuStyleBridge {\r\n constructor() {\r\n this.styleObserver = null;\r\n this.fullyIsolatedApps = new Map(); // Mapa de appName -> appUrl para apps con fully-isolated\r\n this.config = {\r\n // Librerías que se deben compartir automáticamente\r\n autoShareLibraries: [\r\n 'element-plus',\r\n 'vue-flow',\r\n '@vue-flow',\r\n 'vueuse',\r\n '@vueuse',\r\n 'normalize.css',\r\n 'reset.css'\r\n ],\r\n // Patrones de URLs a compartir\r\n sharePatterns: [\r\n /\\/node_modules\\//,\r\n /\\/@vite\\/client/,\r\n /\\/dist\\/index\\.css$/,\r\n /\\/dist\\/style\\.css$/\r\n ],\r\n // Modo de compartición\r\n mode: 'auto', // 'auto' | 'manual' | 'all'\r\n // Caché de estilos\r\n cacheEnabled: true\r\n };\r\n\r\n logger.debug('[WuStyleBridge] 🎨 Style sharing system initialized');\r\n }\r\n\r\n /**\r\n * 🛡️ REGISTRAR APP FULLY-ISOLATED: Registra una app con fully-isolated para filtrar sus estilos\r\n * @param {string} appName - Nombre de la app\r\n * @param {string} appUrl - URL base de la app\r\n */\r\n registerFullyIsolatedApp(appName, appUrl) {\r\n this.fullyIsolatedApps.set(appName, appUrl);\r\n logger.debug(`[WuStyleBridge] 🛡️ Registered fully-isolated app: ${appName} (${appUrl})`);\r\n }\r\n\r\n /**\r\n * 🔍 VERIFICAR SI ESTILO ES DE APP FULLY-ISOLATED: Verifica si un estilo proviene de una app con fully-isolated\r\n * @param {string|Object|HTMLElement} styleUrlOrElement - URL del estilo, objeto de estilo, o elemento DOM\r\n * @returns {boolean}\r\n */\r\n isStyleFromFullyIsolatedApp(styleUrlOrElement) {\r\n let url = '';\r\n \r\n // Si es un string, usar directamente\r\n if (typeof styleUrlOrElement === 'string') {\r\n url = styleUrlOrElement;\r\n }\r\n // Si es un elemento DOM (HTMLElement) - verificar si tiene getAttribute (método común de elementos DOM)\r\n else if (styleUrlOrElement && typeof styleUrlOrElement.getAttribute === 'function') {\r\n // Obtener data-vite-dev-id o href del elemento\r\n url = styleUrlOrElement.getAttribute('data-vite-dev-id') || styleUrlOrElement.href || '';\r\n }\r\n // Si es un objeto con propiedades\r\n else if (styleUrlOrElement) {\r\n if (styleUrlOrElement.href) {\r\n url = styleUrlOrElement.href;\r\n } else if (styleUrlOrElement.viteId) {\r\n url = styleUrlOrElement.viteId;\r\n } else if (styleUrlOrElement.element) {\r\n if (typeof styleUrlOrElement.element.getAttribute === 'function') {\r\n url = styleUrlOrElement.element.getAttribute('data-vite-dev-id') || styleUrlOrElement.element.href || '';\r\n } else if (styleUrlOrElement.element.href) {\r\n url = styleUrlOrElement.element.href;\r\n }\r\n }\r\n }\r\n\r\n if (!url || url.trim() === '') return false;\r\n\r\n // Normalizar la URL para comparación (convertir backslashes a forward slashes)\r\n const normalizedUrl = url.replace(/\\\\/g, '/').toLowerCase();\r\n\r\n // Verificar si la URL pertenece a alguna app con fully-isolated\r\n for (const [appName, appUrl] of this.fullyIsolatedApps.entries()) {\r\n const normalizedAppUrl = appUrl.replace(/\\\\/g, '/').toLowerCase();\r\n const normalizedAppName = appName.toLowerCase();\r\n \r\n // Verificar si la URL contiene la URL base de la app (ej: http://localhost:4001)\r\n if (normalizedAppUrl && normalizedUrl.includes(normalizedAppUrl)) {\r\n return true;\r\n }\r\n \r\n // Verificar si la URL contiene rutas del app en el sistema de archivos\r\n // Ej: C:/Users/.../header/src/... o /header/src/...\r\n // Patrón: cualquier ruta que contenga /header/ o \\header\\\r\n const appPathPattern = new RegExp(`[/\\\\\\\\]${normalizedAppName}[/\\\\\\\\]`, 'i');\r\n if (appPathPattern.test(normalizedUrl)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * 🔍 DETECTAR ESTILOS: Escanea todos los estilos del documento\r\n * @returns {Array} Lista de estilos detectados (filtrados para excluir apps con fully-isolated)\r\n */\r\n detectDocumentStyles() {\r\n const styles = [];\r\n\r\n // 1. Detectar TODOS los <link> tags de CSS\r\n const linkTags = document.querySelectorAll('link[rel=\"stylesheet\"]');\r\n linkTags.forEach((link) => {\r\n // Filtrar estilos de apps con fully-isolated\r\n if (this.isStyleFromFullyIsolatedApp(link)) {\r\n return;\r\n }\r\n\r\n styles.push({\r\n type: 'link',\r\n href: link.href,\r\n element: link,\r\n library: this.extractLibraryName(link.href)\r\n });\r\n });\r\n\r\n // 2. Detectar TODOS los <style> tags (incluyendo Vue scoped styles)\r\n const styleTags = document.querySelectorAll('style');\r\n styleTags.forEach((style, index) => {\r\n // Excluir solo estilos ya compartidos por wu-framework\r\n if (style.getAttribute('data-wu-shared') === 'true') {\r\n return;\r\n }\r\n\r\n const viteId = style.getAttribute('data-vite-dev-id');\r\n const content = style.textContent;\r\n\r\n // Filtrar estilos de apps con fully-isolated (después de obtener viteId para mejor detección)\r\n if (this.isStyleFromFullyIsolatedApp(style) || (viteId && this.isStyleFromFullyIsolatedApp(viteId))) {\r\n logger.debug(`[WuStyleBridge] 🛡️ Filtered out style from fully-isolated app: ${viteId || 'unknown'}`);\r\n return;\r\n }\r\n\r\n // Incluir todos los estilos con contenido\r\n if (content && content.trim().length > 0) {\r\n styles.push({\r\n type: 'inline',\r\n content,\r\n element: style,\r\n viteId,\r\n library: this.extractLibraryName(viteId || ''),\r\n index\r\n });\r\n }\r\n });\r\n\r\n // 3. Detectar Constructable Stylesheets (si están disponibles)\r\n if (document.adoptedStyleSheets && document.adoptedStyleSheets.length > 0) {\r\n document.adoptedStyleSheets.forEach((sheet, index) => {\r\n styles.push({\r\n type: 'adoptedStyleSheet',\r\n sheet,\r\n index\r\n });\r\n });\r\n }\r\n\r\n logger.debug(`[WuStyleBridge] 🔍 Detected ${styles.length} shareable styles`);\r\n return styles;\r\n }\r\n\r\n /**\r\n * 🎯 VERIFICAR SI SE DEBE COMPARTIR: Filtra estilos según configuración\r\n * @param {string} urlOrId - URL o ID del estilo\r\n * @returns {boolean}\r\n */\r\n shouldShareStyle(urlOrId) {\r\n if (!urlOrId) return false;\r\n\r\n // Modo 'all' - compartir todo\r\n if (this.config.mode === 'all') return true;\r\n\r\n // Verificar patrones configurados\r\n for (const pattern of this.config.sharePatterns) {\r\n if (pattern.test(urlOrId)) return true;\r\n }\r\n\r\n // Verificar librerías específicas\r\n for (const lib of this.config.autoShareLibraries) {\r\n if (urlOrId.includes(lib)) return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * 📦 EXTRAER NOMBRE DE LIBRERÍA: Obtiene el nombre de la librería desde la URL\r\n * @param {string} url - URL del estilo\r\n * @returns {string|null}\r\n */\r\n extractLibraryName(url) {\r\n if (!url) return null;\r\n\r\n // Extraer de node_modules\r\n const nodeModulesMatch = url.match(/\\/node_modules\\/(@?[^/]+\\/[^/]+|@?[^/]+)/);\r\n if (nodeModulesMatch) return nodeModulesMatch[1];\r\n\r\n // Extraer de vite dev id\r\n const viteMatch = url.match(/\\/node_modules\\/(.+?)\\/.*?\\.css/);\r\n if (viteMatch) return viteMatch[1];\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * 🌉 INYECTAR ESTILOS EN SHADOW DOM: Clona estilos al Shadow DOM\r\n * @param {ShadowRoot} shadowRoot - Shadow DOM donde inyectar\r\n * @param {string} appName - Nombre de la app\r\n * @param {string} styleMode - Modo de estilos: 'shared', 'isolated', 'fully-isolated'\r\n * @returns {Promise<number>}\r\n */\r\n async injectStylesIntoShadow(shadowRoot, appName, styleMode) {\r\n if (!shadowRoot) {\r\n logger.warn('[WuStyleBridge] ⚠️ No shadow root provided');\r\n return 0;\r\n }\r\n\r\n // 🛡️ MODO FULLY-ISOLATED: No inyectar ningún estilo compartido\r\n // Los estilos propios se manejan en wu-sandbox.js con injectOwnStylesToShadow\r\n if (styleMode === 'fully-isolated') {\r\n logger.debug(`[WuStyleBridge] 🛡️ Style mode \"fully-isolated\" for ${appName}, skipping shared style injection`);\r\n return 0;\r\n }\r\n\r\n // 🔒 MODO ISOLATED: No inyectar estilos externos - usar encapsulamiento nativo de Shadow DOM\r\n // La app debe manejar sus propios estilos (CSS-in-JS, scoped styles, imports directos)\r\n if (styleMode === 'isolated') {\r\n logger.debug(`[WuStyleBridge] 🔒 Style mode \"isolated\" for ${appName}, using native Shadow DOM encapsulation (no external styles)`);\r\n return 0;\r\n }\r\n\r\n // 🌐 MODO SHARED (default): Inyectar todos los estilos compartidos del documento\r\n logger.debug(`[WuStyleBridge] 🌐 Style mode \"shared\" for ${appName}, injecting all shared styles...`);\r\n\r\n // Detectar estilos del documento\r\n const styles = this.detectDocumentStyles();\r\n let injectedCount = 0;\r\n\r\n // Inyectar cada estilo\r\n for (const style of styles) {\r\n try {\r\n switch (style.type) {\r\n case 'link':\r\n await this.injectLinkStyle(shadowRoot, style);\r\n injectedCount++;\r\n break;\r\n\r\n case 'inline':\r\n this.injectInlineStyle(shadowRoot, style);\r\n injectedCount++;\r\n break;\r\n\r\n case 'adoptedStyleSheet':\r\n this.injectAdoptedStyleSheet(shadowRoot, style);\r\n injectedCount++;\r\n break;\r\n }\r\n } catch (error) {\r\n logger.warn(`[WuStyleBridge] ⚠️ Failed to inject style:`, error);\r\n }\r\n }\r\n\r\n logger.debug(`[WuStyleBridge] ✅ Injected ${injectedCount} shared styles into ${appName}`);\r\n return injectedCount;\r\n }\r\n\r\n /**\r\n * 🔗 INYECTAR LINK STYLE: Clona <link> tag al Shadow DOM\r\n * @param {ShadowRoot} shadowRoot\r\n * @param {Object} style\r\n */\r\n async injectLinkStyle(shadowRoot, style) {\r\n // Verificar si ya existe\r\n const existing = shadowRoot.querySelector(`link[href=\"${style.href}\"]`);\r\n if (existing) {\r\n logger.debug(`[WuStyleBridge] ⏭️ Style already exists: ${style.library || style.href}`);\r\n return;\r\n }\r\n\r\n // Clonar link tag\r\n const link = document.createElement('link');\r\n link.rel = 'stylesheet';\r\n link.href = style.href;\r\n link.setAttribute('data-wu-shared', 'true');\r\n link.setAttribute('data-wu-library', style.library || 'unknown');\r\n\r\n // Insertar al principio del shadow root (antes de otros estilos)\r\n shadowRoot.insertBefore(link, shadowRoot.firstChild);\r\n\r\n logger.debug(`[WuStyleBridge] 🔗 Injected link: ${style.library || style.href}`);\r\n }\r\n\r\n /**\r\n * 📝 INYECTAR INLINE STYLE: Clona <style> tag al Shadow DOM\r\n * @param {ShadowRoot} shadowRoot\r\n * @param {Object} style\r\n */\r\n injectInlineStyle(shadowRoot, style) {\r\n // Verificar si ya existe\r\n const viteId = style.viteId;\r\n if (viteId) {\r\n const existing = shadowRoot.querySelector(`style[data-wu-vite-id=\"${viteId}\"]`);\r\n if (existing) {\r\n logger.debug(`[WuStyleBridge] ⏭️ Inline style already exists: ${viteId}`);\r\n return;\r\n }\r\n }\r\n\r\n // Crear nuevo style tag\r\n const styleTag = document.createElement('style');\r\n styleTag.textContent = style.content;\r\n styleTag.setAttribute('data-wu-shared', 'true');\r\n styleTag.setAttribute('data-wu-library', style.library || 'unknown');\r\n if (viteId) {\r\n styleTag.setAttribute('data-wu-vite-id', viteId);\r\n }\r\n\r\n // Insertar al principio del shadow root\r\n shadowRoot.insertBefore(styleTag, shadowRoot.firstChild);\r\n\r\n logger.debug(`[WuStyleBridge] 📝 Injected inline style: ${style.library || viteId}`);\r\n }\r\n\r\n /**\r\n * 📋 INYECTAR ADOPTED STYLESHEET: Comparte stylesheet constructable\r\n * @param {ShadowRoot} shadowRoot\r\n * @param {Object} style\r\n */\r\n injectAdoptedStyleSheet(shadowRoot, style) {\r\n try {\r\n // Agregar stylesheet al array de adopted stylesheets\r\n if (!shadowRoot.adoptedStyleSheets) {\r\n shadowRoot.adoptedStyleSheets = [];\r\n }\r\n\r\n // Verificar si ya existe\r\n if (shadowRoot.adoptedStyleSheets.includes(style.sheet)) {\r\n logger.debug(`[WuStyleBridge] ⏭️ Adopted stylesheet already exists`);\r\n return;\r\n }\r\n\r\n shadowRoot.adoptedStyleSheets = [\r\n ...shadowRoot.adoptedStyleSheets,\r\n style.sheet\r\n ];\r\n\r\n logger.debug(`[WuStyleBridge] 📋 Injected adopted stylesheet`);\r\n } catch (error) {\r\n logger.warn(`[WuStyleBridge] ⚠️ Failed to inject adopted stylesheet:`, error);\r\n }\r\n }\r\n\r\n /**\r\n * 🔄 OBSERVAR CAMBIOS: Monitorea nuevos estilos en el documento\r\n * @param {Function} callback - Callback cuando se detectan cambios\r\n */\r\n observeStyleChanges(callback) {\r\n // Limpiar observer anterior si existe\r\n if (this.styleObserver) {\r\n this.styleObserver.disconnect();\r\n }\r\n\r\n // Crear MutationObserver para detectar nuevos estilos\r\n this.styleObserver = new MutationObserver((mutations) => {\r\n let hasStyleChanges = false;\r\n\r\n for (const mutation of mutations) {\r\n if (mutation.type === 'childList') {\r\n // Verificar si se agregaron <link> o <style> tags\r\n const addedNodes = Array.from(mutation.addedNodes);\r\n const hasNewStyles = addedNodes.some(node =>\r\n node.tagName === 'LINK' || node.tagName === 'STYLE'\r\n );\r\n\r\n if (hasNewStyles) {\r\n hasStyleChanges = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (hasStyleChanges && callback) {\r\n logger.debug('[WuStyleBridge] 🔄 Style changes detected');\r\n callback();\r\n }\r\n });\r\n\r\n // Observar <head> para cambios en estilos\r\n this.styleObserver.observe(document.head, {\r\n childList: true,\r\n subtree: true\r\n });\r\n\r\n logger.debug('[WuStyleBridge] 👀 Observing style changes');\r\n }\r\n\r\n /**\r\n * ⚙️ CONFIGURAR: Actualiza la configuración\r\n * @param {Object} config - Nueva configuración\r\n */\r\n configure(config) {\r\n this.config = {\r\n ...this.config,\r\n ...config\r\n };\r\n\r\n logger.debug('[WuStyleBridge] ⚙️ Configuration updated:', this.config);\r\n }\r\n\r\n /**\r\n * 🧹 LIMPIAR: Detiene la observación\r\n */\r\n cleanup() {\r\n if (this.styleObserver) {\r\n this.styleObserver.disconnect();\r\n this.styleObserver = null;\r\n }\r\n\r\n logger.debug('[WuStyleBridge] 🧹 StyleBridge cleaned up');\r\n }\r\n\r\n /**\r\n * 📊 OBTENER ESTADÍSTICAS: Información sobre estilos compartidos\r\n * @returns {Object}\r\n */\r\n getStats() {\r\n const styles = this.detectDocumentStyles();\r\n\r\n return {\r\n totalStyles: styles.length,\r\n linkStyles: styles.filter(s => s.type === 'link').length,\r\n inlineStyles: styles.filter(s => s.type === 'inline').length,\r\n adoptedStyleSheets: styles.filter(s => s.type === 'adoptedStyleSheet').length,\r\n libraries: [...new Set(styles.map(s => s.library).filter(Boolean))],\r\n config: this.config\r\n };\r\n }\r\n}\r\n","/**\r\n * WU-PROXY-SANDBOX: Hardened JavaScript Isolation\r\n *\r\n * ES6 Proxy-based sandbox with side-effect tracking:\r\n * - Timer hijacking (setTimeout, setInterval, requestAnimationFrame)\r\n * - Event listener tracking (window + document addEventListener)\r\n * - DOM scoping (querySelector/querySelectorAll → shadow root)\r\n * - Storage scoping (localStorage/sessionStorage → prefixed keys)\r\n *\r\n * All tracked side effects are automatically cleaned up on deactivate().\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuProxySandbox {\r\n constructor(appName, options = {}) {\r\n this.appName = appName;\r\n this.options = options;\r\n this.proxy = null;\r\n this.fakeWindow = Object.create(null);\r\n this.active = false;\r\n this.modifiedKeys = new Set();\r\n\r\n // --- Side-effect tracking ---\r\n this._timers = new Set();\r\n this._intervals = new Set();\r\n this._rafs = new Set();\r\n this._eventListeners = []; // [{target, event, handler, options}]\r\n\r\n // --- DOM & Storage scoping ---\r\n this._container = null;\r\n this._shadowRoot = null;\r\n this._scopedDocument = null;\r\n this._scopedLocalStorage = null;\r\n this._scopedSessionStorage = null;\r\n\r\n // --- Window patching state ---\r\n this._patched = false;\r\n this._originals = null;\r\n }\r\n\r\n /**\r\n * Set the DOM scope for this sandbox.\r\n * Must be called before activate() for DOM scoping to work.\r\n * @param {HTMLElement} container - App container element\r\n * @param {ShadowRoot} shadowRoot - Shadow root containing the container\r\n */\r\n setContainer(container, shadowRoot) {\r\n this._container = container;\r\n this._shadowRoot = shadowRoot;\r\n }\r\n\r\n /**\r\n * Activate the sandbox. Creates the Proxy and starts tracking.\r\n * @returns {Proxy} The sandboxed window proxy\r\n */\r\n activate() {\r\n if (this.active) return this.proxy;\r\n\r\n const self = this;\r\n\r\n this.proxy = new Proxy(window, {\r\n get(target, prop) {\r\n // 1. App's own isolated globals\r\n if (prop in self.fakeWindow) {\r\n return self.fakeWindow[prop];\r\n }\r\n\r\n // 2. Intercepted APIs\r\n const intercepted = self._intercept(prop, target);\r\n if (intercepted !== undefined) {\r\n return intercepted;\r\n }\r\n\r\n // 3. Real window value with correct binding\r\n const value = target[prop];\r\n if (typeof value === 'function' && !self._isConstructor(value)) {\r\n return value.bind(target);\r\n }\r\n return value;\r\n },\r\n\r\n set(target, prop, value) {\r\n self.fakeWindow[prop] = value;\r\n self.modifiedKeys.add(prop);\r\n return true;\r\n },\r\n\r\n has(target, prop) {\r\n return prop in self.fakeWindow || prop in target;\r\n },\r\n\r\n deleteProperty(target, prop) {\r\n if (prop in self.fakeWindow) {\r\n delete self.fakeWindow[prop];\r\n self.modifiedKeys.delete(prop);\r\n return true;\r\n }\r\n return false;\r\n }\r\n });\r\n\r\n this.active = true;\r\n logger.wuDebug(`[ProxySandbox] Activated for ${this.appName}`);\r\n return this.proxy;\r\n }\r\n\r\n /**\r\n * Deactivate the sandbox. Cleans up ALL tracked side effects.\r\n */\r\n deactivate() {\r\n if (!this.active) return;\r\n\r\n // Unpatch window if patched\r\n this.unpatchWindow();\r\n\r\n // --- Clean timers ---\r\n for (const id of this._timers) {\r\n try { clearTimeout(id); } catch {}\r\n }\r\n for (const id of this._intervals) {\r\n try { clearInterval(id); } catch {}\r\n }\r\n for (const id of this._rafs) {\r\n try { cancelAnimationFrame(id); } catch {}\r\n }\r\n\r\n const timerCount = this._timers.size + this._intervals.size + this._rafs.size;\r\n this._timers.clear();\r\n this._intervals.clear();\r\n this._rafs.clear();\r\n\r\n // --- Clean event listeners ---\r\n const listenerCount = this._eventListeners.length;\r\n for (const { target, event, handler, options } of this._eventListeners) {\r\n try { target.removeEventListener(event, handler, options); } catch {}\r\n }\r\n this._eventListeners = [];\r\n\r\n // --- Clean namespace ---\r\n this.fakeWindow = Object.create(null);\r\n this.modifiedKeys.clear();\r\n this._scopedDocument = null;\r\n this._scopedLocalStorage = null;\r\n this._scopedSessionStorage = null;\r\n this.proxy = null;\r\n this.active = false;\r\n\r\n if (timerCount > 0 || listenerCount > 0) {\r\n logger.wuDebug(\r\n `[ProxySandbox] ${this.appName} cleanup: ${timerCount} timers, ${listenerCount} listeners`\r\n );\r\n }\r\n logger.wuDebug(`[ProxySandbox] Deactivated for ${this.appName}`);\r\n }\r\n\r\n // ================================================================\r\n // WINDOW PATCHING - patches real window APIs during module loading\r\n // ================================================================\r\n\r\n /**\r\n * Patch real window APIs to track side effects from global code.\r\n * Call before loading app module, unpatch after.\r\n *\r\n * IMPORTANT: Uses closure over originals so patched functions remain\r\n * valid even after unpatchWindow() — prevents crashes when frameworks\r\n * (React 19, etc.) cache references to patched setTimeout during import.\r\n */\r\n patchWindow() {\r\n if (this._patched) return;\r\n\r\n const self = this;\r\n\r\n // Capture originals in a local closure that survives unpatch\r\n const originals = {\r\n setTimeout: window.setTimeout,\r\n clearTimeout: window.clearTimeout,\r\n setInterval: window.setInterval,\r\n clearInterval: window.clearInterval,\r\n requestAnimationFrame: window.requestAnimationFrame,\r\n cancelAnimationFrame: window.cancelAnimationFrame,\r\n addEventListener: window.addEventListener,\r\n removeEventListener: window.removeEventListener\r\n };\r\n\r\n // Store reference (used by unpatchWindow to restore)\r\n this._originals = originals;\r\n\r\n // Patch timers — closure captures `originals`, not `self._originals`\r\n window.setTimeout = function(fn, delay, ...args) {\r\n const id = originals.setTimeout.call(window, fn, delay, ...args);\r\n if (self._patched) self._timers.add(id);\r\n return id;\r\n };\r\n window.clearTimeout = function(id) {\r\n self._timers.delete(id);\r\n return originals.clearTimeout.call(window, id);\r\n };\r\n window.setInterval = function(fn, delay, ...args) {\r\n const id = originals.setInterval.call(window, fn, delay, ...args);\r\n if (self._patched) self._intervals.add(id);\r\n return id;\r\n };\r\n window.clearInterval = function(id) {\r\n self._intervals.delete(id);\r\n return originals.clearInterval.call(window, id);\r\n };\r\n window.requestAnimationFrame = function(fn) {\r\n const id = originals.requestAnimationFrame.call(window, fn);\r\n if (self._patched) self._rafs.add(id);\r\n return id;\r\n };\r\n window.cancelAnimationFrame = function(id) {\r\n self._rafs.delete(id);\r\n return originals.cancelAnimationFrame.call(window, id);\r\n };\r\n\r\n // Patch event listeners\r\n window.addEventListener = function(event, handler, options) {\r\n if (self._patched) self._eventListeners.push({ target: window, event, handler, options });\r\n return originals.addEventListener.call(window, event, handler, options);\r\n };\r\n window.removeEventListener = function(event, handler, options) {\r\n self._eventListeners = self._eventListeners.filter(\r\n l => !(l.target === window && l.event === event && l.handler === handler)\r\n );\r\n return originals.removeEventListener.call(window, event, handler, options);\r\n };\r\n\r\n this._patched = true;\r\n logger.wuDebug(`[ProxySandbox] Window patched for ${this.appName}`);\r\n }\r\n\r\n /**\r\n * Restore original window APIs.\r\n * Safe: patched functions still work via closure even after restore.\r\n */\r\n unpatchWindow() {\r\n if (!this._patched || !this._originals) return;\r\n\r\n window.setTimeout = this._originals.setTimeout;\r\n window.clearTimeout = this._originals.clearTimeout;\r\n window.setInterval = this._originals.setInterval;\r\n window.clearInterval = this._originals.clearInterval;\r\n window.requestAnimationFrame = this._originals.requestAnimationFrame;\r\n window.cancelAnimationFrame = this._originals.cancelAnimationFrame;\r\n window.addEventListener = this._originals.addEventListener;\r\n window.removeEventListener = this._originals.removeEventListener;\r\n\r\n // NOTE: Do NOT null _originals — patched closures may still reference\r\n // the sandbox instance (e.g. React scheduler caches setTimeout).\r\n // The closure uses `originals` (local const), not `this._originals`.\r\n this._patched = false;\r\n logger.wuDebug(`[ProxySandbox] Window unpatched for ${this.appName}`);\r\n }\r\n\r\n // ================================================================\r\n // PROXY INTERCEPTS - for code running through the proxy\r\n // ================================================================\r\n\r\n /**\r\n * Intercept property access on the proxy.\r\n * Returns wrapped API or undefined to fall through.\r\n */\r\n _intercept(prop, target) {\r\n const self = this;\r\n\r\n switch (prop) {\r\n // --- Timer hijacking ---\r\n case 'setTimeout':\r\n return function(fn, delay, ...args) {\r\n const id = target.setTimeout(fn, delay, ...args);\r\n self._timers.add(id);\r\n return id;\r\n };\r\n case 'clearTimeout':\r\n return function(id) {\r\n self._timers.delete(id);\r\n target.clearTimeout(id);\r\n };\r\n case 'setInterval':\r\n return function(fn, delay, ...args) {\r\n const id = target.setInterval(fn, delay, ...args);\r\n self._intervals.add(id);\r\n return id;\r\n };\r\n case 'clearInterval':\r\n return function(id) {\r\n self._intervals.delete(id);\r\n target.clearInterval(id);\r\n };\r\n case 'requestAnimationFrame':\r\n return function(fn) {\r\n const id = target.requestAnimationFrame(fn);\r\n self._rafs.add(id);\r\n return id;\r\n };\r\n case 'cancelAnimationFrame':\r\n return function(id) {\r\n self._rafs.delete(id);\r\n target.cancelAnimationFrame(id);\r\n };\r\n\r\n // --- Event listener tracking ---\r\n case 'addEventListener':\r\n return function(event, handler, options) {\r\n self._eventListeners.push({ target, event, handler, options });\r\n target.addEventListener(event, handler, options);\r\n };\r\n case 'removeEventListener':\r\n return function(event, handler, options) {\r\n self._eventListeners = self._eventListeners.filter(\r\n l => !(l.target === target && l.event === event && l.handler === handler)\r\n );\r\n target.removeEventListener(event, handler, options);\r\n };\r\n\r\n // --- DOM scoping ---\r\n case 'document':\r\n return this._getScopedDocument();\r\n\r\n // --- Storage scoping ---\r\n case 'localStorage':\r\n return this._getScopedStorage('local');\r\n case 'sessionStorage':\r\n return this._getScopedStorage('session');\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n // ================================================================\r\n // DOM SCOPING - querySelector searches inside shadow root\r\n // ================================================================\r\n\r\n _getScopedDocument() {\r\n if (this._scopedDocument) return this._scopedDocument;\r\n\r\n const root = this._shadowRoot || this._container;\r\n if (!root) return document; // No container set, pass through\r\n\r\n const self = this;\r\n\r\n this._scopedDocument = new Proxy(document, {\r\n get(target, prop) {\r\n switch (prop) {\r\n case 'querySelector':\r\n return (selector) => root.querySelector(selector);\r\n case 'querySelectorAll':\r\n return (selector) => root.querySelectorAll(selector);\r\n case 'getElementById':\r\n return (id) => root.querySelector(`#${CSS.escape(id)}`);\r\n case 'getElementsByClassName':\r\n return (className) => root.querySelectorAll(`.${CSS.escape(className)}`);\r\n case 'getElementsByTagName':\r\n return (tag) => root.querySelectorAll(tag);\r\n\r\n // Track document event listeners too\r\n case 'addEventListener':\r\n return function(event, handler, options) {\r\n self._eventListeners.push({ target, event, handler, options });\r\n target.addEventListener(event, handler, options);\r\n };\r\n case 'removeEventListener':\r\n return function(event, handler, options) {\r\n self._eventListeners = self._eventListeners.filter(\r\n l => !(l.target === target && l.event === event && l.handler === handler)\r\n );\r\n target.removeEventListener(event, handler, options);\r\n };\r\n\r\n // createElement, createTextNode, etc. - pass through\r\n default: {\r\n const value = target[prop];\r\n if (typeof value === 'function') {\r\n return value.bind(target);\r\n }\r\n return value;\r\n }\r\n }\r\n }\r\n });\r\n\r\n return this._scopedDocument;\r\n }\r\n\r\n // ================================================================\r\n // STORAGE SCOPING - localStorage/sessionStorage with app prefix\r\n // ================================================================\r\n\r\n _getScopedStorage(type) {\r\n const cacheKey = type === 'local' ? '_scopedLocalStorage' : '_scopedSessionStorage';\r\n if (this[cacheKey]) return this[cacheKey];\r\n\r\n const realStorage = type === 'local' ? window.localStorage : window.sessionStorage;\r\n if (!realStorage) return realStorage;\r\n\r\n const prefix = `wu_${this.appName}_`;\r\n\r\n this[cacheKey] = {\r\n getItem(key) {\r\n return realStorage.getItem(prefix + key);\r\n },\r\n setItem(key, value) {\r\n realStorage.setItem(prefix + key, String(value));\r\n },\r\n removeItem(key) {\r\n realStorage.removeItem(prefix + key);\r\n },\r\n clear() {\r\n // Only clear this app's keys\r\n const toRemove = [];\r\n for (let i = 0; i < realStorage.length; i++) {\r\n const k = realStorage.key(i);\r\n if (k && k.startsWith(prefix)) toRemove.push(k);\r\n }\r\n toRemove.forEach(k => realStorage.removeItem(k));\r\n },\r\n key(index) {\r\n let count = 0;\r\n for (let i = 0; i < realStorage.length; i++) {\r\n const k = realStorage.key(i);\r\n if (k && k.startsWith(prefix)) {\r\n if (count === index) return k.slice(prefix.length);\r\n count++;\r\n }\r\n }\r\n return null;\r\n },\r\n get length() {\r\n let count = 0;\r\n for (let i = 0; i < realStorage.length; i++) {\r\n if (realStorage.key(i)?.startsWith(prefix)) count++;\r\n }\r\n return count;\r\n }\r\n };\r\n\r\n return this[cacheKey];\r\n }\r\n\r\n // ================================================================\r\n // UTILITIES\r\n // ================================================================\r\n\r\n _isConstructor(fn) {\r\n try {\r\n return fn.prototype && fn.prototype.constructor === fn;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n getProxy() {\r\n return this.active ? this.proxy : null;\r\n }\r\n\r\n isActive() {\r\n return this.active;\r\n }\r\n\r\n getStats() {\r\n return {\r\n appName: this.appName,\r\n active: this.active,\r\n patched: this._patched,\r\n modifiedKeys: Array.from(this.modifiedKeys),\r\n isolatedPropsCount: Object.keys(this.fakeWindow).length,\r\n trackedTimers: this._timers.size,\r\n trackedIntervals: this._intervals.size,\r\n trackedRAFs: this._rafs.size,\r\n trackedEventListeners: this._eventListeners.length,\r\n hasContainer: !!this._container,\r\n hasShadowRoot: !!this._shadowRoot\r\n };\r\n }\r\n}\r\n","/**\r\n * WU-SNAPSHOT-SANDBOX: JavaScript Isolation via Snapshots\r\n * Fallback for browsers without Proxy support.\r\n *\r\n * Takes a snapshot of window state before mount,\r\n * restores original state on deactivate.\r\n * Also tracks timers and event listeners for cleanup.\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuSnapshotSandbox {\r\n constructor(appName) {\r\n this.appName = appName;\r\n this.proxy = window;\r\n this.snapshot = new Map();\r\n this.modifiedKeys = new Set();\r\n this.active = false;\r\n\r\n // Side-effect tracking (same as ProxySandbox)\r\n this._timers = new Set();\r\n this._intervals = new Set();\r\n this._rafs = new Set();\r\n this._eventListeners = [];\r\n\r\n // Window patching state\r\n this._patched = false;\r\n this._originals = null;\r\n }\r\n\r\n /**\r\n * Activate sandbox - capture window snapshot and start tracking.\r\n */\r\n activate() {\r\n if (this.active) return this.proxy;\r\n\r\n this.snapshot.clear();\r\n this.modifiedKeys.clear();\r\n\r\n // Capture current window state\r\n for (const key in window) {\r\n try {\r\n this.snapshot.set(key, window[key]);\r\n } catch {\r\n // Some properties may be inaccessible\r\n }\r\n }\r\n\r\n this.active = true;\r\n logger.wuDebug(`[SnapshotSandbox] Activated for ${this.appName} (${this.snapshot.size} props)`);\r\n return this.proxy;\r\n }\r\n\r\n /**\r\n * Deactivate sandbox - restore snapshot AND clean side effects.\r\n */\r\n deactivate() {\r\n if (!this.active) return;\r\n\r\n // Unpatch window if patched\r\n this.unpatchWindow();\r\n\r\n // --- Clean tracked timers ---\r\n for (const id of this._timers) {\r\n try { clearTimeout(id); } catch {}\r\n }\r\n for (const id of this._intervals) {\r\n try { clearInterval(id); } catch {}\r\n }\r\n for (const id of this._rafs) {\r\n try { cancelAnimationFrame(id); } catch {}\r\n }\r\n\r\n const timerCount = this._timers.size + this._intervals.size + this._rafs.size;\r\n this._timers.clear();\r\n this._intervals.clear();\r\n this._rafs.clear();\r\n\r\n // --- Clean tracked event listeners ---\r\n const listenerCount = this._eventListeners.length;\r\n for (const { target, event, handler, options } of this._eventListeners) {\r\n try { target.removeEventListener(event, handler, options); } catch {}\r\n }\r\n this._eventListeners = [];\r\n\r\n // --- Restore window snapshot ---\r\n let restoredCount = 0;\r\n let deletedCount = 0;\r\n\r\n for (const key in window) {\r\n try {\r\n const currentValue = window[key];\r\n const originalValue = this.snapshot.get(key);\r\n\r\n if (currentValue !== originalValue) {\r\n if (this.snapshot.has(key)) {\r\n window[key] = originalValue;\r\n restoredCount++;\r\n } else {\r\n try {\r\n delete window[key];\r\n deletedCount++;\r\n } catch {}\r\n }\r\n }\r\n } catch {}\r\n }\r\n\r\n this.snapshot.clear();\r\n this.modifiedKeys.clear();\r\n this.active = false;\r\n\r\n if (timerCount > 0 || listenerCount > 0) {\r\n logger.wuDebug(\r\n `[SnapshotSandbox] ${this.appName} cleanup: ${timerCount} timers, ${listenerCount} listeners, ${restoredCount} restored, ${deletedCount} deleted`\r\n );\r\n }\r\n logger.wuDebug(`[SnapshotSandbox] Deactivated for ${this.appName}`);\r\n }\r\n\r\n // ================================================================\r\n // WINDOW PATCHING - same interface as ProxySandbox\r\n // ================================================================\r\n\r\n patchWindow() {\r\n if (this._patched) return;\r\n\r\n const self = this;\r\n\r\n // Capture in local closure — survives unpatch safely\r\n const originals = {\r\n setTimeout: window.setTimeout,\r\n clearTimeout: window.clearTimeout,\r\n setInterval: window.setInterval,\r\n clearInterval: window.clearInterval,\r\n requestAnimationFrame: window.requestAnimationFrame,\r\n cancelAnimationFrame: window.cancelAnimationFrame,\r\n addEventListener: window.addEventListener,\r\n removeEventListener: window.removeEventListener\r\n };\r\n\r\n this._originals = originals;\r\n\r\n window.setTimeout = function(fn, delay, ...args) {\r\n const id = originals.setTimeout.call(window, fn, delay, ...args);\r\n if (self._patched) self._timers.add(id);\r\n return id;\r\n };\r\n window.clearTimeout = function(id) {\r\n self._timers.delete(id);\r\n return originals.clearTimeout.call(window, id);\r\n };\r\n window.setInterval = function(fn, delay, ...args) {\r\n const id = originals.setInterval.call(window, fn, delay, ...args);\r\n if (self._patched) self._intervals.add(id);\r\n return id;\r\n };\r\n window.clearInterval = function(id) {\r\n self._intervals.delete(id);\r\n return originals.clearInterval.call(window, id);\r\n };\r\n window.requestAnimationFrame = function(fn) {\r\n const id = originals.requestAnimationFrame.call(window, fn);\r\n if (self._patched) self._rafs.add(id);\r\n return id;\r\n };\r\n window.cancelAnimationFrame = function(id) {\r\n self._rafs.delete(id);\r\n return originals.cancelAnimationFrame.call(window, id);\r\n };\r\n\r\n window.addEventListener = function(event, handler, options) {\r\n if (self._patched) self._eventListeners.push({ target: window, event, handler, options });\r\n return originals.addEventListener.call(window, event, handler, options);\r\n };\r\n window.removeEventListener = function(event, handler, options) {\r\n self._eventListeners = self._eventListeners.filter(\r\n l => !(l.target === window && l.event === event && l.handler === handler)\r\n );\r\n return originals.removeEventListener.call(window, event, handler, options);\r\n };\r\n\r\n this._patched = true;\r\n logger.wuDebug(`[SnapshotSandbox] Window patched for ${this.appName}`);\r\n }\r\n\r\n unpatchWindow() {\r\n if (!this._patched || !this._originals) return;\r\n\r\n window.setTimeout = this._originals.setTimeout;\r\n window.clearTimeout = this._originals.clearTimeout;\r\n window.setInterval = this._originals.setInterval;\r\n window.clearInterval = this._originals.clearInterval;\r\n window.requestAnimationFrame = this._originals.requestAnimationFrame;\r\n window.cancelAnimationFrame = this._originals.cancelAnimationFrame;\r\n window.addEventListener = this._originals.addEventListener;\r\n window.removeEventListener = this._originals.removeEventListener;\r\n\r\n this._patched = false;\r\n logger.wuDebug(`[SnapshotSandbox] Window unpatched for ${this.appName}`);\r\n }\r\n\r\n // ================================================================\r\n // UTILITIES\r\n // ================================================================\r\n\r\n getProxy() {\r\n return this.active ? this.proxy : null;\r\n }\r\n\r\n isActive() {\r\n return this.active;\r\n }\r\n\r\n getStats() {\r\n return {\r\n appName: this.appName,\r\n active: this.active,\r\n patched: this._patched,\r\n snapshotSize: this.snapshot.size,\r\n trackedTimers: this._timers.size,\r\n trackedIntervals: this._intervals.size,\r\n trackedRAFs: this._rafs.size,\r\n trackedEventListeners: this._eventListeners.length\r\n };\r\n }\r\n}\r\n","/**\r\n * 🛡️ WU-SANDBOX: ADVANCED ISOLATION SYSTEM\r\n * Shadow DOM + Proxy Sandbox + Script Execution + HTML Parsing\r\n * Combina lo mejor de video-code con Shadow DOM nativo\r\n */\r\n\r\nimport { WuStyleBridge } from './wu-style-bridge.js';\r\nimport { WuProxySandbox } from './wu-proxy-sandbox.js';\r\nimport { WuSnapshotSandbox } from './wu-snapshot-sandbox.js';\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuSandbox {\r\n constructor() {\r\n // Registros existentes\r\n this.sandboxes = new Map();\r\n this.styleBridge = new WuStyleBridge();\r\n\r\n // 🚀 NUEVOS SISTEMAS INTEGRADOS\r\n this.jsSandboxes = new Map(); // ProxySandbox o SnapshotSandbox por app\r\n this.sandboxStrategy = this.detectSandboxStrategy();\r\n\r\n logger.wuDebug(`Advanced isolation system initialized (strategy: ${this.sandboxStrategy})`);\r\n }\r\n\r\n /**\r\n * Detectar estrategia de sandbox óptima\r\n * @returns {'proxy' | 'snapshot'} Estrategia a usar\r\n */\r\n detectSandboxStrategy() {\r\n // Verificar si Proxy está disponible\r\n if (typeof Proxy !== 'undefined') {\r\n try {\r\n // Test básico de Proxy\r\n const testProxy = new Proxy({}, {\r\n get(target, prop) { return target[prop]; }\r\n });\r\n testProxy.test = 'value';\r\n\r\n logger.wuDebug('Proxy available - using ProxySandbox strategy');\r\n return 'proxy';\r\n } catch (error) {\r\n logger.wuWarn('Proxy not working - falling back to SnapshotSandbox');\r\n return 'snapshot';\r\n }\r\n }\r\n\r\n logger.wuWarn('Proxy not available - using SnapshotSandbox strategy');\r\n return 'snapshot';\r\n }\r\n\r\n /**\r\n * 🔧 SMART SANDBOX: Advanced Shadow DOM creation with error recovery\r\n * @param {string} appName - Nombre de la aplicación\r\n * @param {HTMLElement} hostContainer - Contenedor host\r\n * @param {Object} options - Opciones adicionales (styleMode, manifest, etc.)\r\n * @returns {Object} Sandbox con shadow root y container\r\n */\r\n create(appName, hostContainer, options = {}) {\r\n logger.wuDebug(`Creating sandbox for: ${appName}`);\r\n\r\n try {\r\n // 🔧 SHADOW DOM VERIFICATION\r\n if (!hostContainer.attachShadow) {\r\n throw new Error('Shadow DOM not supported in this browser');\r\n }\r\n\r\n // 🛠️ SMART CLEANUP: Handle existing shadow roots\r\n let shadowRoot;\r\n if (hostContainer.shadowRoot) {\r\n logger.wuDebug(`Existing shadow root detected for ${appName}, performing cleanup...`);\r\n\r\n // Clear existing shadow root content\r\n hostContainer.shadowRoot.innerHTML = '';\r\n shadowRoot = hostContainer.shadowRoot;\r\n\r\n logger.wuDebug(`Existing shadow root cleaned and reused for ${appName}`);\r\n } else {\r\n // Create new Shadow DOM\r\n shadowRoot = hostContainer.attachShadow({\r\n mode: 'open',\r\n delegatesFocus: true\r\n });\r\n\r\n logger.wuDebug(`New shadow root created for ${appName}`);\r\n }\r\n\r\n // 🎯 Create app container with advanced features\r\n const appContainer = document.createElement('div');\r\n appContainer.id = `wu-app-${appName}`;\r\n appContainer.className = 'wu-app-root';\r\n appContainer.setAttribute('data-wu-enhanced', 'true');\r\n appContainer.setAttribute('data-wu-timestamp', Date.now().toString());\r\n\r\n // 🎨 Enhanced base styles with advanced properties\r\n const baseStyles = document.createElement('style');\r\n baseStyles.textContent = this.generateSandboxStyles(appName);\r\n\r\n // 🌟 Assemble enhanced Shadow DOM\r\n shadowRoot.appendChild(baseStyles);\r\n shadowRoot.appendChild(appContainer);\r\n\r\n // Create JS Sandbox with container reference for DOM/storage scoping\r\n const jsSandbox = this.createAdvancedJSSandbox(appName);\r\n if (jsSandbox.setContainer) {\r\n jsSandbox.setContainer(appContainer, shadowRoot);\r\n }\r\n const jsProxy = jsSandbox.activate();\r\n\r\n // Verificar styleMode del manifest antes de inyectar estilos\r\n const styleMode = options.styleMode || options.manifest?.styleMode;\r\n\r\n const sandbox = {\r\n appName,\r\n shadowRoot,\r\n container: appContainer,\r\n hostContainer,\r\n jsSandbox, // NUEVO: ProxySandbox o SnapshotSandbox\r\n jsProxy, // NUEVO: Proxy para ejecutar scripts\r\n styles: baseStyles,\r\n styleMode, // Guardar styleMode para uso futuro\r\n manifest: options.manifest, // Guardar manifest completo\r\n created: Date.now(),\r\n sandbox_state: 'stable',\r\n recovery_count: 0\r\n };\r\n\r\n // 🎨 INJECT STYLES: Comportamiento según styleMode\r\n // - \"shared\": Inyecta todos los estilos del documento padre\r\n // - \"isolated\": NO inyecta estilos externos (encapsulamiento nativo Shadow DOM)\r\n // - \"fully-isolated\": Inyecta SOLO estilos propios de la app\r\n\r\n if (styleMode === 'isolated') {\r\n // 🔒 MODO ISOLATED: Encapsulamiento nativo del Shadow DOM\r\n // No se inyectan estilos externos - la app debe manejar sus propios estilos\r\n logger.wuDebug(`Style mode \"isolated\" for ${appName}, using native Shadow DOM encapsulation`);\r\n sandbox.stylesReady = Promise.resolve(0);\r\n // No configurar observer de estilos - la app es responsable de sus propios estilos\r\n\r\n } else if (styleMode === 'fully-isolated') {\r\n logger.wuDebug(`Style mode \"fully-isolated\" detected for ${appName}, using enhanced style injection`);\r\n // Registrar esta app como fully-isolated en el style bridge para filtrar sus estilos\r\n const appUrl = options.appUrl || (options.manifest?.name ? `/${options.manifest.name}/` : `/${appName}/`);\r\n this.styleBridge.registerFullyIsolatedApp(appName, appUrl);\r\n\r\n // Guardar appUrl en sandbox para uso en reinjectStyles\r\n sandbox.appUrl = appUrl;\r\n\r\n // Para fully-isolated, inyectar SOLO los estilos propios de la app en su Shadow DOM\r\n // Guardamos referencia a this para usar en el observer\r\n const self = this;\r\n\r\n sandbox.stylesReady = new Promise((resolve) => {\r\n let resolved = false;\r\n\r\n const tryInject = async () => {\r\n const count = await self.injectOwnStylesToShadow(shadowRoot, appName, appUrl);\r\n\r\n if (count > 0) {\r\n logger.wuDebug(`Injected ${count} own styles for ${appName} (fully-isolated)`);\r\n if (!resolved) {\r\n resolved = true;\r\n resolve(count);\r\n }\r\n }\r\n\r\n return count;\r\n };\r\n\r\n // Usar MutationObserver PERSISTENTE para detectar cuando se inyectan estilos del app\r\n logger.wuDebug(`Setting up style observer for ${appName} (fully-isolated)`);\r\n const observer = new MutationObserver((mutations) => {\r\n let newStyleCount = 0;\r\n for (const m of mutations) {\r\n if (m.type === 'childList') {\r\n for (const n of m.addedNodes) {\r\n if (n.nodeName === 'STYLE' || n.nodeName === 'LINK') {\r\n newStyleCount++;\r\n const viteId = n.getAttribute ? n.getAttribute('data-vite-dev-id') : null;\r\n if (viteId && viteId.toLowerCase().includes(appName.toLowerCase())) {\r\n logger.wuDebug(`New ${appName} style detected: ${viteId.split('/').pop()}`);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n if (newStyleCount > 0) {\r\n logger.wuDebug(`${newStyleCount} new styles detected in head, checking for ${appName}...`);\r\n tryInject();\r\n }\r\n });\r\n\r\n // Observar cambios en el head DE FORMA PERSISTENTE\r\n observer.observe(document.head, {\r\n childList: true,\r\n subtree: true\r\n });\r\n\r\n // Guardar referencia al observer para poder desconectarlo cuando se desmonte la app\r\n sandbox.styleObserver = observer;\r\n\r\n // Intento inicial con pequeño delay para que Vite procese los imports\r\n setTimeout(async () => {\r\n const count = await tryInject();\r\n // Si después de 3 segundos no hay estilos, usar fallback\r\n if (!resolved) {\r\n setTimeout(() => {\r\n if (!resolved) {\r\n logger.wuWarn(`No own styles found for ${appName} after timeout, using FALLBACK`);\r\n const fallbackCount = self.injectAllStylesToShadow(shadowRoot, appName);\r\n logger.wuDebug(`FALLBACK: Injected ${fallbackCount} styles for ${appName}`);\r\n resolved = true;\r\n resolve(fallbackCount);\r\n }\r\n }, 3000);\r\n }\r\n }, 50);\r\n });\r\n } else {\r\n // 🌐 MODO SHARED (default): Inyectar todos los estilos compartidos del documento\r\n logger.wuDebug(`Style mode \"shared\" for ${appName}, injecting all shared styles...`);\r\n sandbox.stylesReady = this.styleBridge.injectStylesIntoShadow(shadowRoot, appName, styleMode).then(count => {\r\n logger.wuDebug(`Shared ${count} styles with ${appName}`);\r\n\r\n // 🔄 Observar cambios dinámicos de estilos (HMR de Vite)\r\n this.styleBridge.observeStyleChanges(() => {\r\n logger.wuDebug(`Reinjecting styles for ${appName} due to changes`);\r\n this.styleBridge.injectStylesIntoShadow(shadowRoot, appName, styleMode).catch(err => {\r\n logger.wuWarn(`Failed to reinject styles: ${err}`);\r\n });\r\n });\r\n\r\n return count;\r\n }).catch(error => {\r\n logger.wuWarn(`Failed to inject styles: ${error}`);\r\n return 0;\r\n });\r\n }\r\n\r\n // 📊 Register in sandbox registry\r\n this.sandboxes.set(appName, sandbox);\r\n\r\n logger.wuDebug(`Enhanced sandbox created for ${appName}`);\r\n return sandbox;\r\n\r\n } catch (error) {\r\n logger.wuError(`Failed to create sandbox for ${appName}: ${error}`);\r\n\r\n // 🔧 FALLBACK RECOVERY: Create fallback sandbox when Shadow DOM fails\r\n if (error.message.includes('Shadow root cannot be created')) {\r\n return this.createFallbackSandbox(appName, hostContainer);\r\n }\r\n\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * 🔧 FALLBACK SANDBOX: Create fallback container when Shadow DOM is not available\r\n */\r\n createFallbackSandbox(appName, hostContainer) {\r\n logger.wuDebug(`Creating fallback sandbox for ${appName}...`);\r\n\r\n try {\r\n // 🛠️ Complete shadow DOM reset\r\n if (hostContainer.shadowRoot) {\r\n hostContainer.shadowRoot.innerHTML = '';\r\n }\r\n\r\n // 🌟 Create minimal container without shadow DOM if necessary\r\n const fallbackContainer = document.createElement('div');\r\n fallbackContainer.id = `wu-app-${appName}`;\r\n fallbackContainer.className = 'wu-app-root wu-fallback';\r\n fallbackContainer.style.cssText = `\r\n width: 100%;\r\n height: 100%;\r\n isolation: isolate;\r\n contain: layout style paint;\r\n `;\r\n\r\n // 🧹 Clear host container\r\n hostContainer.innerHTML = '';\r\n hostContainer.appendChild(fallbackContainer);\r\n\r\n const healedSandbox = {\r\n appName,\r\n shadowRoot: null, // No shadow DOM in fallback mode\r\n container: fallbackContainer,\r\n hostContainer,\r\n styles: null,\r\n created: Date.now(),\r\n sandbox_state: 'fallback_mode',\r\n recovery_count: 1,\r\n fallback_mode: true\r\n };\r\n\r\n this.sandboxes.set(appName, healedSandbox);\r\n\r\n logger.wuDebug(`Fallback sandbox created successfully for ${appName}`);\r\n return healedSandbox;\r\n\r\n } catch (healingError) {\r\n logger.wuError(`Fallback sandbox creation failed: ${healingError}`);\r\n throw healingError;\r\n }\r\n }\r\n\r\n /**\r\n * 🎨 SANDBOX STYLES: Generate CSS styles for Shadow DOM isolation\r\n */\r\n generateSandboxStyles(appName) {\r\n return `\r\n /* Wu Framework - Shadow DOM Isolation Styles */\r\n :host {\r\n display: block;\r\n width: 100%;\r\n height: 100%;\r\n box-sizing: border-box;\r\n contain: layout style paint;\r\n --wu-sandbox-active: true;\r\n --wu-isolation-state: stable;\r\n }\r\n\r\n .wu-app-root {\r\n width: 100%;\r\n height: 100%;\r\n box-sizing: border-box;\r\n isolation: isolate;\r\n position: relative;\r\n overflow: hidden;\r\n }\r\n\r\n /* Loading animation for sandbox initialization */\r\n .wu-app-root[data-wu-loading=\"true\"] {\r\n background: linear-gradient(45deg,\r\n rgba(74, 144, 226, 0.1) 0%,\r\n rgba(80, 227, 194, 0.1) 100%);\r\n animation: sandboxPulse 2s ease-in-out infinite;\r\n }\r\n\r\n @keyframes sandboxPulse {\r\n 0%, 100% { opacity: 0.8; }\r\n 50% { opacity: 1; }\r\n }\r\n\r\n /* CSS reset for shadow DOM stability */\r\n * {\r\n box-sizing: border-box;\r\n }\r\n\r\n /* CSS custom properties for sandbox */\r\n :host {\r\n --wu-app-name: \"${appName}\";\r\n --wu-isolation: true;\r\n --wu-creation-timestamp: ${Date.now()};\r\n }\r\n\r\n /* 🛡️ Debug mode enhancements */\r\n :host([wu-debug]) {\r\n border: 2px dashed #4a90e2;\r\n background: rgba(74, 144, 226, 0.05);\r\n box-shadow: 0 0 10px rgba(74, 144, 226, 0.3);\r\n }\r\n\r\n :host([wu-debug])::before {\r\n content: \"Wu Framework: \" attr(wu-app);\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n background: linear-gradient(45deg, #4a90e2, #50e3c2);\r\n color: white;\r\n padding: 4px 8px;\r\n font-size: 11px;\r\n font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;\r\n z-index: 10000;\r\n border-radius: 0 0 4px 0;\r\n font-weight: 600;\r\n }\r\n\r\n /* Sandbox state indicators */\r\n :host([data-sandbox-state=\"stable\"]) {\r\n --wu-isolation-state: stable;\r\n }\r\n\r\n :host([data-sandbox-state=\"healing\"]) {\r\n --wu-dimensional-stability: healing;\r\n animation: sandboxHealing 1s ease-in-out infinite;\r\n }\r\n\r\n @keyframes sandboxHealing {\r\n 0%, 100% { filter: hue-rotate(0deg); }\r\n 50% { filter: hue-rotate(180deg); }\r\n }\r\n `;\r\n }\r\n\r\n /**\r\n * 🛡️ Crear JS Sandbox avanzado (ProxySandbox o SnapshotSandbox)\r\n * @param {string} appName - Nombre de la app\r\n * @returns {WuProxySandbox|WuSnapshotSandbox} Sandbox JS\r\n */\r\n createAdvancedJSSandbox(appName) {\r\n let jsSandbox;\r\n\r\n if (this.sandboxStrategy === 'proxy') {\r\n jsSandbox = new WuProxySandbox(appName);\r\n logger.wuDebug(`Created ProxySandbox for ${appName}`);\r\n } else {\r\n jsSandbox = new WuSnapshotSandbox(appName);\r\n logger.wuDebug(`Created SnapshotSandbox for ${appName}`);\r\n }\r\n\r\n // Registrar sandbox\r\n this.jsSandboxes.set(appName, jsSandbox);\r\n\r\n return jsSandbox;\r\n }\r\n\r\n /**\r\n * Agregar estilos personalizados al sandbox\r\n * @param {string} appName - Nombre de la aplicación\r\n * @param {string} css - CSS a agregar\r\n */\r\n addStyles(appName, css) {\r\n const sandbox = this.sandboxes.get(appName);\r\n if (!sandbox) {\r\n logger.wuWarn(`Sandbox not found for: ${appName}`);\r\n return;\r\n }\r\n\r\n const styleElement = document.createElement('style');\r\n styleElement.textContent = css;\r\n styleElement.setAttribute('wu-custom-styles', '');\r\n\r\n sandbox.shadowRoot.appendChild(styleElement);\r\n logger.wuDebug(`Custom styles added to ${appName}`);\r\n }\r\n\r\n /**\r\n * Cargar estilos externos en el sandbox\r\n * @param {string} appName - Nombre de la aplicación\r\n * @param {string} href - URL del CSS\r\n */\r\n loadExternalStyles(appName, href) {\r\n const sandbox = this.sandboxes.get(appName);\r\n if (!sandbox) {\r\n logger.wuWarn(`Sandbox not found for: ${appName}`);\r\n return;\r\n }\r\n\r\n const linkElement = document.createElement('link');\r\n linkElement.rel = 'stylesheet';\r\n linkElement.href = href;\r\n linkElement.setAttribute('wu-external-styles', '');\r\n\r\n sandbox.shadowRoot.appendChild(linkElement);\r\n logger.wuDebug(`External styles loaded in ${appName}: ${href}`);\r\n }\r\n\r\n /**\r\n * Establecer modo debug para un sandbox\r\n * @param {string} appName - Nombre de la aplicación\r\n * @param {boolean} enabled - Activar/desactivar debug\r\n */\r\n setDebugMode(appName, enabled = true) {\r\n const sandbox = this.sandboxes.get(appName);\r\n if (!sandbox) {\r\n logger.wuWarn(`Sandbox not found for: ${appName}`);\r\n return;\r\n }\r\n\r\n if (enabled) {\r\n sandbox.hostContainer.setAttribute('wu-debug', '');\r\n sandbox.hostContainer.setAttribute('wu-app', appName);\r\n } else {\r\n sandbox.hostContainer.removeAttribute('wu-debug');\r\n sandbox.hostContainer.removeAttribute('wu-app');\r\n }\r\n\r\n logger.wuDebug(`Debug mode ${enabled ? 'enabled' : 'disabled'} for ${appName}`);\r\n }\r\n\r\n /**\r\n * Limpiar y destruir sandbox\r\n * @param {Object} sandbox - Sandbox a limpiar\r\n */\r\n cleanup(sandbox) {\r\n if (!sandbox) return;\r\n\r\n const { appName, shadowRoot, hostContainer, jsSandbox } = sandbox;\r\n\r\n logger.wuDebug(`Cleaning up sandbox for: ${appName}`);\r\n\r\n try {\r\n // 🛡️ NUEVO: Desactivar JS Sandbox\r\n if (jsSandbox && jsSandbox.isActive()) {\r\n jsSandbox.deactivate();\r\n logger.wuDebug(`JS Sandbox deactivated for ${appName}`);\r\n }\r\n\r\n // Limpiar eventos y observers\r\n this.cleanupEventListeners(sandbox);\r\n\r\n // Limpiar contenido del Shadow DOM\r\n if (shadowRoot) {\r\n shadowRoot.innerHTML = '';\r\n }\r\n\r\n // Remover atributos del host\r\n if (hostContainer) {\r\n hostContainer.removeAttribute('wu-debug');\r\n hostContainer.removeAttribute('wu-app');\r\n hostContainer.removeAttribute('wu-no-scroll');\r\n }\r\n\r\n // Remover del registro\r\n this.sandboxes.delete(appName);\r\n this.jsSandboxes.delete(appName);\r\n\r\n logger.wuDebug(`Sandbox cleaned up: ${appName}`);\r\n\r\n } catch (error) {\r\n logger.wuError(`Error cleaning up sandbox ${appName}: ${error}`);\r\n }\r\n }\r\n\r\n /**\r\n * Limpiar event listeners del sandbox\r\n * @param {Object} sandbox - Sandbox a limpiar\r\n */\r\n cleanupEventListeners(sandbox) {\r\n // Remover todos los event listeners del Shadow DOM\r\n const { shadowRoot } = sandbox;\r\n if (!shadowRoot) return;\r\n\r\n // Clonar nodos para remover todos los event listeners\r\n const elements = shadowRoot.querySelectorAll('*');\r\n elements.forEach(element => {\r\n if (element.cloneNode) {\r\n const clone = element.cloneNode(true);\r\n element.parentNode?.replaceChild(clone, element);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Obtener información de un sandbox\r\n * @param {string} appName - Nombre de la aplicación\r\n * @returns {Object} Información del sandbox\r\n */\r\n getSandboxInfo(appName) {\r\n const sandbox = this.sandboxes.get(appName);\r\n if (!sandbox) return null;\r\n\r\n return {\r\n appName: sandbox.appName,\r\n created: sandbox.created,\r\n hasContainer: !!sandbox.container,\r\n hasShadowRoot: !!sandbox.shadowRoot,\r\n elementCount: sandbox.shadowRoot?.children?.length || 0,\r\n uptime: Date.now() - sandbox.created\r\n };\r\n }\r\n\r\n /**\r\n * Obtener estadísticas de todos los sandboxes\r\n */\r\n getStats() {\r\n return {\r\n strategy: this.sandboxStrategy,\r\n total: this.sandboxes.size,\r\n sandboxes: Array.from(this.sandboxes.keys()),\r\n jsSandboxes: Array.from(this.jsSandboxes.keys()),\r\n details: Array.from(this.sandboxes.entries()).map(([name, sandbox]) => ({\r\n name,\r\n uptime: Date.now() - sandbox.created,\r\n elements: sandbox.shadowRoot?.children?.length || 0,\r\n hasJsSandbox: !!sandbox.jsSandbox,\r\n jsSandboxActive: sandbox.jsSandbox?.isActive() || false\r\n }))\r\n };\r\n }\r\n\r\n /**\r\n * Limpiar todos los sandboxes\r\n */\r\n cleanupAll() {\r\n logger.wuDebug(`Cleaning up all ${this.sandboxes.size} sandboxes...`);\r\n\r\n for (const [appName, sandbox] of this.sandboxes) {\r\n this.cleanup(sandbox);\r\n }\r\n\r\n // Limpiar StyleBridge\r\n if (this.styleBridge) {\r\n this.styleBridge.cleanup();\r\n }\r\n\r\n logger.wuDebug('All sandboxes cleaned up');\r\n }\r\n\r\n /**\r\n * 🎨 CONFIGURAR STYLE BRIDGE: Configura el sistema de compartición de estilos\r\n * @param {Object} config - Configuración del StyleBridge\r\n */\r\n configureStyleSharing(config) {\r\n if (this.styleBridge) {\r\n this.styleBridge.configure(config);\r\n logger.wuDebug('StyleBridge configured');\r\n }\r\n }\r\n\r\n /**\r\n * 📊 OBTENER ESTADÍSTICAS DE ESTILOS: Info sobre estilos compartidos\r\n * @returns {Object}\r\n */\r\n getStyleStats() {\r\n return this.styleBridge ? this.styleBridge.getStats() : null;\r\n }\r\n\r\n /**\r\n * 🔄 RE-INYECTAR ESTILOS: Vuelve a inyectar estilos en un sandbox\r\n * @param {string} appName - Nombre de la aplicación\r\n */\r\n async reinjectStyles(appName) {\r\n const sandbox = this.sandboxes.get(appName);\r\n if (!sandbox || !sandbox.shadowRoot) {\r\n logger.wuWarn(`Cannot reinject styles for ${appName}`);\r\n return;\r\n }\r\n\r\n const styleMode = sandbox.styleMode;\r\n\r\n // 🔒 MODO ISOLATED: No reinyectar estilos - la app maneja sus propios estilos\r\n if (styleMode === 'isolated') {\r\n logger.wuDebug(`Skipping reinject for ${appName} (isolated mode - app manages own styles)`);\r\n return;\r\n }\r\n\r\n // 🛡️ MODO FULLY-ISOLATED: Reinyectar SOLO estilos propios\r\n if (styleMode === 'fully-isolated') {\r\n logger.wuDebug(`Reinjecting OWN styles for ${appName} (fully-isolated)...`);\r\n const appUrl = sandbox.appUrl || sandbox.manifest?.name ? `/${sandbox.manifest.name}/` : `/${appName}/`;\r\n const count = await this.injectOwnStylesToShadow(sandbox.shadowRoot, appName, appUrl);\r\n logger.wuDebug(`Reinjected ${count} own styles for ${appName}`);\r\n return;\r\n }\r\n\r\n // 🌐 MODO SHARED: Reinyectar todos los estilos compartidos\r\n logger.wuDebug(`Reinjecting shared styles for ${appName}...`);\r\n const count = await this.styleBridge.injectStylesIntoShadow(\r\n sandbox.shadowRoot,\r\n appName,\r\n styleMode\r\n );\r\n logger.wuDebug(`Reinjected ${count} shared styles`);\r\n }\r\n\r\n /**\r\n * 🎨 INYECTAR ESTILOS PROPIOS: Inyecta SOLO los estilos propios de una app en su Shadow DOM\r\n * Usado para apps en modo fully-isolated\r\n * @param {ShadowRoot} shadowRoot - Shadow DOM donde inyectar\r\n * @param {string} appName - Nombre de la app\r\n * @param {string} appUrl - URL base de la app\r\n * @returns {Promise<number>} Número de estilos inyectados\r\n */\r\n async injectOwnStylesToShadow(shadowRoot, appName, appUrl) {\r\n if (!shadowRoot) return 0;\r\n\r\n let injectedCount = 0;\r\n\r\n // Buscar TODOS los estilos en el head\r\n const allStyles = document.querySelectorAll('style');\r\n const normalizedAppName = appName.toLowerCase();\r\n\r\n // Patrones para detectar estilos de esta app (Windows y Unix paths)\r\n // IMPORTANTE: Debe coincidir SOLO con packages/appName/ al inicio del path del paquete\r\n // NO debe coincidir con packages/shell/src/components/learning/ (eso es del shell)\r\n const appPatterns = [\r\n // Patrón específico: packages/learning/src o packages\\learning\\src\r\n // El src/ es clave para asegurar que es el MFE, no un subdirectorio de otro package\r\n new RegExp(`packages[/\\\\\\\\]${normalizedAppName}[/\\\\\\\\]src[/\\\\\\\\]`, 'i')\r\n ];\r\n\r\n logger.wuDebug(`Searching own styles for ${appName}, found ${allStyles.length} style tags in head`);\r\n\r\n // Log para debug: mostrar estilos que contienen el nombre de la app\r\n let matchingCount = 0;\r\n for (const s of allStyles) {\r\n const vid = s.getAttribute('data-vite-dev-id') || '';\r\n if (vid.toLowerCase().includes(normalizedAppName)) {\r\n matchingCount++;\r\n }\r\n }\r\n if (matchingCount > 0) {\r\n logger.wuDebug(`Found ${matchingCount} styles potentially matching ${appName}`);\r\n }\r\n\r\n for (const style of allStyles) {\r\n // NO saltar basándose en data-wu-injected del head - eso se pone en los clones del shadow DOM\r\n\r\n const viteId = style.getAttribute('data-vite-dev-id') || '';\r\n const normalizedViteId = viteId.replace(/\\\\/g, '/').toLowerCase();\r\n\r\n // Verificar si el estilo pertenece a esta app\r\n let belongsToApp = false;\r\n\r\n // 1. Por data-vite-dev-id (la forma más confiable)\r\n if (viteId) {\r\n // Revisar si el path contiene packages/appName/\r\n for (const pattern of appPatterns) {\r\n if (pattern instanceof RegExp) {\r\n if (pattern.test(viteId)) {\r\n belongsToApp = true;\r\n break;\r\n }\r\n } else {\r\n if (normalizedViteId.includes(pattern.toLowerCase())) {\r\n belongsToApp = true;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (belongsToApp) {\r\n // Verificar si ya existe en el Shadow DOM\r\n const existingStyle = shadowRoot.querySelector(`style[data-vite-dev-id=\"${viteId}\"]`);\r\n\r\n if (!existingStyle) {\r\n const clonedStyle = style.cloneNode(true);\r\n clonedStyle.setAttribute('data-wu-injected', 'true');\r\n shadowRoot.insertBefore(clonedStyle, shadowRoot.firstChild);\r\n injectedCount++;\r\n const styleName = viteId.substring(viteId.lastIndexOf('/') + 1) || viteId.substring(viteId.lastIndexOf('\\\\') + 1);\r\n logger.wuDebug(`Injected own style for ${appName}: ${styleName}`);\r\n }\r\n }\r\n }\r\n\r\n logger.wuDebug(`Total own styles injected for ${appName}: ${injectedCount}`);\r\n return injectedCount;\r\n }\r\n\r\n /**\r\n * 🎨 FALLBACK: Inyectar estilos que contengan el nombre de la app\r\n * Usado como último recurso cuando no se encuentran los estilos con el patrón exacto\r\n * @param {ShadowRoot} shadowRoot - Shadow DOM donde inyectar\r\n * @param {string} appName - Nombre de la app (para logging)\r\n * @returns {number} Número de estilos inyectados\r\n */\r\n injectAllStylesToShadow(shadowRoot, appName) {\r\n if (!shadowRoot) return 0;\r\n\r\n let injectedCount = 0;\r\n const normalizedAppName = appName.toLowerCase();\r\n\r\n // Inyectar estilos que contengan el nombre de la app en su vite-id\r\n const allStyles = document.querySelectorAll('style');\r\n for (const style of allStyles) {\r\n const viteId = style.getAttribute('data-vite-dev-id') || '';\r\n\r\n // Solo inyectar si contiene el nombre de la app\r\n if (!viteId.toLowerCase().includes(normalizedAppName)) continue;\r\n\r\n // Verificar si ya existe en el shadow DOM\r\n if (shadowRoot.querySelector(`style[data-vite-dev-id=\"${viteId}\"]`)) continue;\r\n\r\n const clonedStyle = style.cloneNode(true);\r\n clonedStyle.setAttribute('data-wu-fallback', 'true');\r\n shadowRoot.insertBefore(clonedStyle, shadowRoot.firstChild);\r\n injectedCount++;\r\n const styleName = viteId.split('/').pop() || viteId.split('\\\\').pop();\r\n logger.wuDebug(`FALLBACK injected: ${styleName}`);\r\n }\r\n\r\n logger.wuDebug(`FALLBACK: Total ${injectedCount} styles injected for ${appName}`);\r\n return injectedCount;\r\n }\r\n}\r\n","/**\r\n * 📋 WU-MANIFEST: SECURE MANIFEST SYSTEM\r\n * Validación estricta de wu.json para seguridad\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuManifest {\r\n constructor() {\r\n this.cache = new Map();\r\n this.schemas = new Map();\r\n\r\n // 🔐 Configuración de seguridad\r\n this.security = {\r\n maxManifestSize: 100 * 1024, // 100KB máximo\r\n maxNameLength: 50,\r\n maxEntryLength: 200,\r\n maxExports: 100,\r\n maxImports: 50,\r\n maxRoutes: 100,\r\n // Patrones peligrosos en paths\r\n dangerousPatterns: [\r\n /\\.\\./, // Path traversal\r\n /^\\/etc\\//, // System paths\r\n /^\\/proc\\//,\r\n /^file:\\/\\//, // File protocol\r\n /javascript:/i, // JS injection\r\n /data:/i, // Data URLs\r\n /<script/i, // Script tags\r\n /on\\w+\\s*=/i // Event handlers\r\n ],\r\n // Dominios bloqueados\r\n blockedDomains: [\r\n 'evil.com',\r\n 'malware.com'\r\n ]\r\n };\r\n\r\n this.defineSchema();\r\n }\r\n\r\n /**\r\n * Definir schema de validación para wu.json\r\n */\r\n defineSchema() {\r\n this.schemas.set('wu.json', {\r\n required: ['name', 'entry'],\r\n optional: ['wu'],\r\n wu: {\r\n optional: ['exports', 'imports', 'routes', 'permissions'],\r\n exports: 'object',\r\n imports: 'array',\r\n routes: 'array',\r\n permissions: 'array'\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Cargar manifest desde URL\r\n * @param {string} appUrl - URL base de la aplicación\r\n * @returns {Object} Manifest parseado y validado\r\n */\r\n async load(appUrl) {\r\n const manifestUrl = `${appUrl}/wu.json`;\r\n\r\n logger.debug(`[WuManifest] 📥 Loading manifest: ${manifestUrl}`);\r\n\r\n try {\r\n // Verificar cache\r\n if (this.cache.has(manifestUrl)) {\r\n logger.debug(`[WuManifest] ⚡ Cache hit: ${manifestUrl}`);\r\n return this.cache.get(manifestUrl);\r\n }\r\n\r\n // Cargar manifest\r\n const response = await fetch(manifestUrl, {\r\n cache: 'no-cache',\r\n headers: {\r\n 'Accept': 'application/json'\r\n }\r\n });\r\n\r\n if (!response.ok) {\r\n // Si no hay manifest, crear uno básico\r\n if (response.status === 404) {\r\n logger.debug(`[WuManifest] 📄 No manifest found, creating default for: ${appUrl}`);\r\n return this.createDefaultManifest(appUrl);\r\n }\r\n\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n\r\n const manifestText = await response.text();\r\n\r\n // 🔐 Validar tamaño del manifest\r\n if (manifestText.length > this.security.maxManifestSize) {\r\n throw new Error(`Manifest too large (${manifestText.length} bytes, max ${this.security.maxManifestSize})`);\r\n }\r\n\r\n // 🔐 Intentar parsear JSON de forma segura\r\n let manifest;\r\n try {\r\n manifest = JSON.parse(manifestText);\r\n } catch (parseError) {\r\n throw new Error(`Invalid JSON in manifest: ${parseError.message}`);\r\n }\r\n\r\n // Validar manifest\r\n const validatedManifest = this.validate(manifest);\r\n\r\n // Cachear resultado\r\n this.cache.set(manifestUrl, validatedManifest);\r\n\r\n logger.debug(`[WuManifest] ✅ Manifest loaded: ${manifest.name}`);\r\n return validatedManifest;\r\n\r\n } catch (error) {\r\n console.error(`[WuManifest] ❌ Failed to load manifest: ${manifestUrl}`, error);\r\n\r\n // En caso de error, intentar crear manifest por defecto\r\n try {\r\n return this.createDefaultManifest(appUrl);\r\n } catch (defaultError) {\r\n throw new Error(`Failed to load manifest from ${manifestUrl}: ${error.message}`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Crear manifest por defecto cuando no existe wu.json\r\n * @param {string} appUrl - URL de la aplicación\r\n * @returns {Object} Manifest por defecto\r\n */\r\n createDefaultManifest(appUrl) {\r\n // Extraer nombre de la app de la URL\r\n const appName = this.extractAppNameFromUrl(appUrl);\r\n\r\n const defaultManifest = {\r\n name: appName,\r\n entry: 'index.js',\r\n wu: {\r\n exports: {},\r\n imports: [],\r\n routes: [],\r\n permissions: []\r\n }\r\n };\r\n\r\n logger.debug(`[WuManifest] 🔧 Created default manifest for: ${appName}`);\r\n return defaultManifest;\r\n }\r\n\r\n /**\r\n * Extraer nombre de app desde URL\r\n * @param {string} url - URL de la aplicación\r\n * @returns {string} Nombre de la aplicación\r\n */\r\n extractAppNameFromUrl(url) {\r\n try {\r\n const urlObj = new URL(url);\r\n const pathSegments = urlObj.pathname.split('/').filter(Boolean);\r\n\r\n // Usar el último segmento como nombre de la app\r\n return pathSegments[pathSegments.length - 1] || 'unknown-app';\r\n } catch {\r\n // Si no es una URL válida, usar como está\r\n return url.replace(/[^a-zA-Z0-9-]/g, '') || 'unknown-app';\r\n }\r\n }\r\n\r\n /**\r\n * 🔐 SANITIZE STRING: Limpiar string de caracteres peligrosos\r\n */\r\n _sanitizeString(str) {\r\n if (typeof str !== 'string') return '';\r\n return str\r\n .replace(/[<>'\"]/g, '') // Remove HTML chars\r\n .replace(/[\\x00-\\x1F\\x7F]/g, '') // Remove control chars\r\n .trim();\r\n }\r\n\r\n /**\r\n * 🔐 CHECK DANGEROUS PATTERNS: Verificar patrones peligrosos\r\n */\r\n _hasDangerousPatterns(str) {\r\n if (typeof str !== 'string') return false;\r\n return this.security.dangerousPatterns.some(pattern => pattern.test(str));\r\n }\r\n\r\n /**\r\n * 🔐 VALIDATE URL: Verificar que URL es segura\r\n */\r\n _isUrlSafe(url) {\r\n if (typeof url !== 'string') return false;\r\n\r\n // Verificar patrones peligrosos\r\n if (this._hasDangerousPatterns(url)) {\r\n return false;\r\n }\r\n\r\n // Verificar dominios bloqueados\r\n try {\r\n const urlObj = new URL(url, 'http://localhost');\r\n if (this.security.blockedDomains.some(d => urlObj.hostname.includes(d))) {\r\n return false;\r\n }\r\n } catch {\r\n // Si no es URL válida, verificar como path\r\n if (this._hasDangerousPatterns(url)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Validar manifest contra schema con validación de seguridad\r\n * @param {Object} manifest - Manifest a validar\r\n * @returns {Object} Manifest validado\r\n */\r\n validate(manifest) {\r\n const schema = this.schemas.get('wu.json');\r\n\r\n // 🔐 Verificar que manifest es un objeto\r\n if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest)) {\r\n throw new Error('Manifest must be a valid object');\r\n }\r\n\r\n // Verificar campos requeridos\r\n for (const field of schema.required) {\r\n if (!manifest[field]) {\r\n throw new Error(`Required field missing: ${field}`);\r\n }\r\n }\r\n\r\n // 🔐 Validar nombre\r\n if (typeof manifest.name !== 'string') {\r\n throw new Error('name must be a string');\r\n }\r\n if (manifest.name.length > this.security.maxNameLength) {\r\n throw new Error(`name too long (max ${this.security.maxNameLength} chars)`);\r\n }\r\n if (this._hasDangerousPatterns(manifest.name)) {\r\n throw new Error('name contains dangerous patterns');\r\n }\r\n\r\n // 🔐 Validar entry\r\n if (typeof manifest.entry !== 'string') {\r\n throw new Error('entry must be a string');\r\n }\r\n if (manifest.entry.length > this.security.maxEntryLength) {\r\n throw new Error(`entry too long (max ${this.security.maxEntryLength} chars)`);\r\n }\r\n if (!this._isUrlSafe(manifest.entry)) {\r\n throw new Error('entry contains dangerous patterns');\r\n }\r\n\r\n // Verificar tipos en sección wu\r\n if (manifest.wu) {\r\n const wu = manifest.wu;\r\n\r\n if (wu.exports && typeof wu.exports !== 'object') {\r\n throw new Error('wu.exports must be an object');\r\n }\r\n\r\n // 🔐 Validar límites de exports\r\n if (wu.exports && Object.keys(wu.exports).length > this.security.maxExports) {\r\n throw new Error(`Too many exports (max ${this.security.maxExports})`);\r\n }\r\n\r\n // 🔐 Validar cada export path\r\n if (wu.exports) {\r\n for (const [key, path] of Object.entries(wu.exports)) {\r\n if (!this._isUrlSafe(path)) {\r\n throw new Error(`Dangerous export path: ${key}`);\r\n }\r\n }\r\n }\r\n\r\n if (wu.imports && !Array.isArray(wu.imports)) {\r\n throw new Error('wu.imports must be an array');\r\n }\r\n\r\n // 🔐 Validar límites de imports\r\n if (wu.imports && wu.imports.length > this.security.maxImports) {\r\n throw new Error(`Too many imports (max ${this.security.maxImports})`);\r\n }\r\n\r\n if (wu.routes && !Array.isArray(wu.routes)) {\r\n throw new Error('wu.routes must be an array');\r\n }\r\n\r\n // 🔐 Validar límites de routes\r\n if (wu.routes && wu.routes.length > this.security.maxRoutes) {\r\n throw new Error(`Too many routes (max ${this.security.maxRoutes})`);\r\n }\r\n\r\n if (wu.permissions && !Array.isArray(wu.permissions)) {\r\n throw new Error('wu.permissions must be an array');\r\n }\r\n }\r\n\r\n // Validate optional fields\r\n if (manifest.styleMode !== undefined) {\r\n const validModes = ['shared', 'isolated', 'fully-isolated'];\r\n if (!validModes.includes(manifest.styleMode)) {\r\n logger.warn(`[WuManifest] Invalid styleMode \"${manifest.styleMode}\", defaulting to \"shared\". Valid: ${validModes.join(', ')}`);\r\n manifest.styleMode = 'shared';\r\n }\r\n }\r\n\r\n if (manifest.version !== undefined && typeof manifest.version !== 'string') {\r\n logger.warn('[WuManifest] version must be a string, ignoring');\r\n delete manifest.version;\r\n }\r\n\r\n if (manifest.folder !== undefined) {\r\n if (typeof manifest.folder !== 'string') {\r\n logger.warn('[WuManifest] folder must be a string, ignoring');\r\n delete manifest.folder;\r\n } else if (this._hasDangerousPatterns(manifest.folder)) {\r\n throw new Error('folder contains dangerous patterns');\r\n }\r\n }\r\n\r\n // Normalizar y limpiar manifest\r\n return this.normalize(manifest);\r\n }\r\n\r\n /**\r\n * Normalizar manifest\r\n * @param {Object} manifest - Manifest a normalizar\r\n * @returns {Object} Manifest normalizado\r\n */\r\n normalize(manifest) {\r\n const normalized = {\r\n name: manifest.name.trim(),\r\n entry: this.normalizeEntry(manifest.entry),\r\n wu: {\r\n exports: manifest.wu?.exports || {},\r\n imports: manifest.wu?.imports || [],\r\n routes: manifest.wu?.routes || [],\r\n permissions: manifest.wu?.permissions || []\r\n }\r\n };\r\n\r\n // Preservar campos opcionales del manifest (styleMode, version, folder, etc.)\r\n if (manifest.styleMode) {\r\n normalized.styleMode = manifest.styleMode;\r\n }\r\n if (manifest.version) {\r\n normalized.version = manifest.version;\r\n }\r\n if (manifest.folder) {\r\n normalized.folder = manifest.folder;\r\n }\r\n\r\n // Normalizar exports\r\n if (normalized.wu.exports) {\r\n const normalizedExports = {};\r\n for (const [key, path] of Object.entries(normalized.wu.exports)) {\r\n normalizedExports[key] = this.normalizeComponentPath(path);\r\n }\r\n normalized.wu.exports = normalizedExports;\r\n }\r\n\r\n // Validar imports\r\n normalized.wu.imports = normalized.wu.imports.filter(imp => {\r\n if (typeof imp !== 'string' || !imp.includes('.')) {\r\n logger.warn(`[WuManifest] Invalid import format: ${imp}`);\r\n return false;\r\n }\r\n return true;\r\n });\r\n\r\n return normalized;\r\n }\r\n\r\n /**\r\n * Normalizar entry path\r\n * @param {string} entry - Entry path\r\n * @returns {string} Entry normalizado\r\n */\r\n normalizeEntry(entry) {\r\n if (!entry) return 'index.js';\r\n\r\n let normalized = entry.trim();\r\n\r\n // Remover ./ inicial si está presente\r\n if (normalized.startsWith('./')) {\r\n normalized = normalized.substring(2);\r\n }\r\n\r\n // Agregar extensión si no la tiene\r\n if (!normalized.includes('.')) {\r\n normalized += '.js';\r\n }\r\n\r\n return normalized;\r\n }\r\n\r\n /**\r\n * Normalizar path de componente\r\n * @param {string} path - Path del componente\r\n * @returns {string} Path normalizado\r\n */\r\n normalizeComponentPath(path) {\r\n if (!path) return '';\r\n\r\n let normalized = path.trim();\r\n\r\n // Remover ./ inicial si está presente\r\n if (normalized.startsWith('./')) {\r\n normalized = normalized.substring(2);\r\n }\r\n\r\n // Agregar extensión si no la tiene\r\n if (!normalized.includes('.')) {\r\n normalized += '.js';\r\n }\r\n\r\n return normalized;\r\n }\r\n\r\n /**\r\n * Validar dependencias de imports\r\n * @param {Array} imports - Lista de imports\r\n * @param {Map} availableApps - Apps disponibles\r\n * @returns {Object} Resultado de validación\r\n */\r\n validateDependencies(imports, availableApps) {\r\n const result = {\r\n valid: [],\r\n invalid: [],\r\n missing: []\r\n };\r\n\r\n for (const importPath of imports) {\r\n const [appName, componentName] = importPath.split('.');\r\n\r\n if (!appName || !componentName) {\r\n result.invalid.push({\r\n import: importPath,\r\n reason: 'Invalid format. Use \"app.component\"'\r\n });\r\n continue;\r\n }\r\n\r\n const app = availableApps.get(appName);\r\n if (!app) {\r\n result.missing.push({\r\n import: importPath,\r\n app: appName,\r\n reason: 'App not registered'\r\n });\r\n continue;\r\n }\r\n\r\n const manifest = app.manifest;\r\n const exportExists = manifest?.wu?.exports?.[componentName];\r\n\r\n if (!exportExists) {\r\n result.invalid.push({\r\n import: importPath,\r\n reason: `Component ${componentName} not exported by ${appName}`\r\n });\r\n continue;\r\n }\r\n\r\n result.valid.push({\r\n import: importPath,\r\n app: appName,\r\n component: componentName,\r\n path: exportExists\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Crear manifest programáticamente\r\n * @param {string} name - Nombre de la app\r\n * @param {Object} config - Configuración\r\n * @returns {Object} Manifest creado\r\n */\r\n create(name, config = {}) {\r\n const manifest = {\r\n name: name,\r\n entry: config.entry || 'index.js',\r\n wu: {\r\n exports: config.exports || {},\r\n imports: config.imports || [],\r\n routes: config.routes || [],\r\n permissions: config.permissions || []\r\n }\r\n };\r\n\r\n return this.normalize(manifest);\r\n }\r\n\r\n /**\r\n * Limpiar cache de manifests\r\n * @param {string} pattern - Patrón opcional para limpiar URLs específicas\r\n */\r\n clearCache(pattern) {\r\n if (pattern) {\r\n const regex = new RegExp(pattern);\r\n for (const [url] of this.cache) {\r\n if (regex.test(url)) {\r\n this.cache.delete(url);\r\n logger.debug(`[WuManifest] 🗑️ Cleared cache for: ${url}`);\r\n }\r\n }\r\n } else {\r\n this.cache.clear();\r\n logger.debug(`[WuManifest] 🗑️ Manifest cache cleared completely`);\r\n }\r\n }\r\n\r\n /**\r\n * Obtener estadísticas del sistema de manifests\r\n */\r\n getStats() {\r\n return {\r\n cached: this.cache.size,\r\n schemas: this.schemas.size,\r\n cacheKeys: Array.from(this.cache.keys())\r\n };\r\n }\r\n}","/**\r\n * 🚀 WU-STORE: Ultra-High Performance State Management\r\n *\r\n * Basado en patrones de Disruptor y Vert.x\r\n * - Ring Buffer para zero-allocation\r\n * - Lock-free operations\r\n * - Event Bus para pub/sub\r\n * - API minimalista: get(), set(), on()\r\n */\r\n\r\n/**\r\n * @typedef {Object} WuStoreMetrics\r\n * @property {number} reads - Total read operations\r\n * @property {number} writes - Total write operations\r\n * @property {number} notifications - Total notifications sent\r\n * @property {number} bufferUtilization - Ring buffer utilization (0-1)\r\n * @property {number} listenerCount - Active listener count\r\n */\r\n\r\nexport class WuStore {\r\n constructor(bufferSize = 256) {\r\n // Ring Buffer configuration\r\n this.bufferSize = this.nextPowerOfTwo(bufferSize);\r\n this.mask = this.bufferSize - 1;\r\n this.buffer = new Array(this.bufferSize);\r\n this.cursor = 0;\r\n\r\n // State storage\r\n this.state = {};\r\n\r\n // Event listeners map: path -> Set of callbacks\r\n this.listeners = new Map();\r\n\r\n // Pattern listeners for wildcards\r\n this.patternListeners = new Map();\r\n\r\n // Performance metrics\r\n this.metrics = {\r\n reads: 0,\r\n writes: 0,\r\n notifications: 0\r\n };\r\n\r\n // Initialize ring buffer slots\r\n for (let i = 0; i < this.bufferSize; i++) {\r\n this.buffer[i] = { path: null, value: null, timestamp: 0 };\r\n }\r\n\r\n // No global pollution - proper library architecture\r\n }\r\n\r\n /**\r\n * Get value from store\r\n * @param {string} path - Dot notation path (e.g., 'user.name')\r\n * @returns {*} Value at path or entire state if no path\r\n */\r\n get(path) {\r\n this.metrics.reads++;\r\n\r\n if (!path) return this.state;\r\n\r\n // Fast path resolution with reduce\r\n return path.split('.').reduce((obj, key) => obj?.[key], this.state);\r\n }\r\n\r\n /**\r\n * Set value in store with Ring Buffer\r\n * @param {string} path - Dot notation path\r\n * @param {*} value - Value to set\r\n * @returns {number} Sequence number\r\n */\r\n set(path, value) {\r\n this.metrics.writes++;\r\n\r\n // Write to ring buffer (lock-free, wraps at buffer boundary)\r\n const sequence = this.cursor;\r\n this.cursor = (this.cursor + 1) % (this.bufferSize * this.bufferSize);\r\n const index = sequence & this.mask;\r\n\r\n // Reuse buffer slot (zero allocation)\r\n const event = this.buffer[index];\r\n event.path = path;\r\n event.value = value;\r\n event.timestamp = performance.now();\r\n\r\n // Update state synchronously\r\n this.updateState(path, value);\r\n\r\n // Schedule async notifications (non-blocking)\r\n queueMicrotask(() => {\r\n this.notify(path, value);\r\n this.notifyPatterns(path, value);\r\n });\r\n\r\n return sequence;\r\n }\r\n\r\n /**\r\n * Subscribe to state changes\r\n * @param {string} pattern - Path or pattern (supports * wildcard)\r\n * @param {Function} callback - Callback function\r\n * @returns {Function} Unsubscribe function\r\n */\r\n on(pattern, callback) {\r\n // Check if pattern contains wildcards\r\n if (pattern.includes('*')) {\r\n // Pattern subscription\r\n if (!this.patternListeners.has(pattern)) {\r\n this.patternListeners.set(pattern, new Set());\r\n }\r\n this.patternListeners.get(pattern).add(callback);\r\n\r\n // Return unsubscribe function\r\n return () => {\r\n const listeners = this.patternListeners.get(pattern);\r\n if (listeners) {\r\n listeners.delete(callback);\r\n if (listeners.size === 0) {\r\n this.patternListeners.delete(pattern);\r\n }\r\n }\r\n };\r\n } else {\r\n // Direct path subscription\r\n if (!this.listeners.has(pattern)) {\r\n this.listeners.set(pattern, new Set());\r\n }\r\n this.listeners.get(pattern).add(callback);\r\n\r\n // Return unsubscribe function\r\n return () => {\r\n const listeners = this.listeners.get(pattern);\r\n if (listeners) {\r\n listeners.delete(callback);\r\n if (listeners.size === 0) {\r\n this.listeners.delete(pattern);\r\n }\r\n }\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Batch set multiple values\r\n * @param {Object} updates - Object with path:value pairs\r\n */\r\n batch(updates) {\r\n const sequences = [];\r\n\r\n for (const [path, value] of Object.entries(updates)) {\r\n sequences.push(this.set(path, value));\r\n }\r\n\r\n return sequences;\r\n }\r\n\r\n /**\r\n * Get current metrics\r\n * @returns {Object} Performance metrics\r\n */\r\n getMetrics() {\r\n return {\r\n ...this.metrics,\r\n bufferUtilization: Math.min(1, this.cursor / this.bufferSize),\r\n listenerCount: this.listeners.size + this.patternListeners.size\r\n };\r\n }\r\n\r\n // Private methods\r\n\r\n nextPowerOfTwo(n) {\r\n return Math.pow(2, Math.ceil(Math.log2(n)));\r\n }\r\n\r\n updateState(path, value) {\r\n if (!path) {\r\n this.state = value;\r\n return;\r\n }\r\n\r\n const keys = path.split('.');\r\n const last = keys.pop();\r\n\r\n // Create nested structure if needed\r\n let target = this.state;\r\n for (const key of keys) {\r\n if (!(key in target) || typeof target[key] !== 'object') {\r\n target[key] = {};\r\n }\r\n target = target[key];\r\n }\r\n\r\n target[last] = value;\r\n }\r\n\r\n notify(path, value) {\r\n this.metrics.notifications++;\r\n\r\n // Notify exact path listeners\r\n const exactListeners = this.listeners.get(path);\r\n if (exactListeners) {\r\n exactListeners.forEach(callback => {\r\n try {\r\n callback(value, path);\r\n } catch (error) {\r\n console.error('[WuStore] Listener error:', error);\r\n }\r\n });\r\n }\r\n\r\n // Notify parent path listeners\r\n const parts = path.split('.');\r\n for (let i = parts.length - 1; i > 0; i--) {\r\n const parentPath = parts.slice(0, i).join('.');\r\n const parentListeners = this.listeners.get(parentPath);\r\n if (parentListeners) {\r\n const parentValue = this.get(parentPath);\r\n parentListeners.forEach(callback => {\r\n try {\r\n callback(parentValue, parentPath);\r\n } catch (error) {\r\n console.error('[WuStore] Parent listener error:', error);\r\n }\r\n });\r\n }\r\n }\r\n }\r\n\r\n notifyPatterns(path, value) {\r\n // Check all pattern listeners\r\n for (const [pattern, listeners] of this.patternListeners) {\r\n if (this.matchesPattern(path, pattern)) {\r\n listeners.forEach(callback => {\r\n try {\r\n callback({ path, value });\r\n } catch (error) {\r\n console.error('[WuStore] Pattern listener error:', error);\r\n }\r\n });\r\n }\r\n }\r\n }\r\n\r\n matchesPattern(path, pattern) {\r\n // Convert pattern to regex\r\n // user.* matches user.name, user.email, etc.\r\n // *.name matches user.name, post.name, etc.\r\n // * matches everything\r\n\r\n if (pattern === '*') return true;\r\n\r\n const regexPattern = pattern\r\n .split('.')\r\n .map(part => part === '*' ? '[^.]+' : part.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\r\n .join('\\\\.');\r\n\r\n const regex = new RegExp(`^${regexPattern}$`);\r\n return regex.test(path);\r\n }\r\n\r\n /**\r\n * Clear all state and listeners\r\n */\r\n clear() {\r\n this.state = {};\r\n this.listeners.clear();\r\n this.patternListeners.clear();\r\n this.cursor = 0;\r\n\r\n // Clear buffer\r\n for (let i = 0; i < this.bufferSize; i++) {\r\n this.buffer[i].path = null;\r\n this.buffer[i].value = null;\r\n this.buffer[i].timestamp = 0;\r\n }\r\n }\r\n\r\n /**\r\n * Get recent events from ring buffer\r\n * @param {number} count - Number of recent events\r\n * @returns {Array} Recent events\r\n */\r\n getRecentEvents(count = 10) {\r\n const events = [];\r\n const start = Math.max(0, this.cursor - count);\r\n\r\n for (let i = start; i < this.cursor && events.length < count; i++) {\r\n const index = i & this.mask;\r\n const event = this.buffer[index];\r\n if (event.path) {\r\n events.push({\r\n path: event.path,\r\n value: event.value,\r\n timestamp: event.timestamp\r\n });\r\n }\r\n }\r\n\r\n return events.reverse();\r\n }\r\n}\r\n\r\n// Create singleton instance\r\nconst store = new WuStore();\r\n\r\n// Export both class and instance\r\nexport default store;\r\n","/**\r\n * 🎯 WU-APP: SIMPLIFIED API WRAPPER\r\n *\r\n * Wrapper simple para uso declarativo de microfrontends\r\n * Mantiene todo el core de wu-framework pero simplifica el uso\r\n */\r\nimport { logger } from './wu-logger.js';\r\n\r\n\r\nexport class WuApp {\r\n /**\r\n * @param {string} name - Nombre de la app\r\n * @param {Object} config - Configuración de la app\r\n * @param {string} config.url - URL donde está corriendo la app\r\n * @param {string} [config.container] - Selector del contenedor (opcional)\r\n * @param {Object} wu - Instancia de WuCore\r\n */\r\n constructor(name, config, wu) {\r\n this.name = name\r\n this.url = config.url\r\n this.container = config.container\r\n this.keepAlive = config.keepAlive || false\r\n this._wu = wu\r\n this._mounted = false\r\n this._autoInit = config.autoInit !== false // Default true\r\n\r\n // Auto-register app in wu-framework\r\n if (this._autoInit) {\r\n this._registerApp()\r\n }\r\n }\r\n\r\n /**\r\n * Registrar app en wu-framework\r\n * @private\r\n */\r\n _registerApp() {\r\n if (!this._wu.apps.has(this.name)) {\r\n this._wu.apps.set(this.name, {\r\n name: this.name,\r\n url: this.url,\r\n keepAlive: this.keepAlive,\r\n status: 'registered'\r\n })\r\n logger.debug(`📦 App registered: ${this.name} at ${this.url}`)\r\n }\r\n }\r\n\r\n /**\r\n * Montar la app en el contenedor\r\n * @param {string} [container] - Selector del contenedor (opcional, usa config.container si no se pasa)\r\n * @returns {Promise<void>}\r\n */\r\n async mount(container) {\r\n const targetContainer = container || this.container\r\n\r\n if (!targetContainer) {\r\n throw new Error(`Container not specified for app: ${this.name}`)\r\n }\r\n\r\n // Asegurar que wu-framework está inicializado\r\n if (!this._wu.isInitialized) {\r\n await this._wu.init({\r\n apps: [{ name: this.name, url: this.url }]\r\n })\r\n }\r\n\r\n // Montar usando wu-framework core\r\n await this._wu.mount(this.name, targetContainer)\r\n this._mounted = true\r\n\r\n return this\r\n }\r\n\r\n /**\r\n * Desmontar la app.\r\n * If keepAlive is configured, hides instead of destroying.\r\n *\r\n * @param {Object} [options] - { keepAlive, force }\r\n * @returns {Promise<WuApp>}\r\n */\r\n async unmount(options = {}) {\r\n if (!this._mounted && !this._wu.isHidden(this.name)) {\r\n logger.warn(`⚠️ App ${this.name} is not mounted`)\r\n return this\r\n }\r\n\r\n await this._wu.unmount(this.name, options)\r\n this._mounted = !this._wu.isHidden(this.name)\r\n\r\n return this\r\n }\r\n\r\n /**\r\n * Hide the app (keep-alive). Preserves all state for instant re-show.\r\n * @returns {Promise<WuApp>}\r\n */\r\n async hide() {\r\n if (!this._mounted) {\r\n logger.warn(`⚠️ App ${this.name} is not mounted`)\r\n return this\r\n }\r\n\r\n await this._wu.hide(this.name)\r\n this._mounted = false\r\n return this\r\n }\r\n\r\n /**\r\n * Show a hidden (keep-alive) app instantly.\r\n * @returns {Promise<WuApp>}\r\n */\r\n async show() {\r\n if (!this._wu.isHidden(this.name)) {\r\n logger.warn(`⚠️ App ${this.name} is not in keep-alive state`)\r\n return this\r\n }\r\n\r\n await this._wu.show(this.name)\r\n this._mounted = true\r\n return this\r\n }\r\n\r\n /**\r\n * Remontar la app (útil para recargas)\r\n * @param {string} [container] - Selector del contenedor\r\n * @returns {Promise<void>}\r\n */\r\n async remount(container) {\r\n await this.unmount({ force: true })\r\n await this.mount(container)\r\n return this\r\n }\r\n\r\n /**\r\n * Verificar si la app está montada\r\n * @returns {boolean}\r\n */\r\n get isMounted() {\r\n return this._mounted && this._wu.mounted?.has(this.name)\r\n }\r\n\r\n /**\r\n * Check if the app is in keep-alive (hidden) state\r\n * @returns {boolean}\r\n */\r\n get isHidden() {\r\n return this._wu.isHidden(this.name)\r\n }\r\n\r\n /**\r\n * Obtener información de la app\r\n * @returns {Object}\r\n */\r\n get info() {\r\n return {\r\n name: this.name,\r\n url: this.url,\r\n container: this.container,\r\n mounted: this.isMounted,\r\n status: this._wu.apps.get(this.name)?.status || 'unknown'\r\n }\r\n }\r\n\r\n /**\r\n * Recargar la app (limpiar cache y remontar)\r\n * @returns {Promise<void>}\r\n */\r\n async reload() {\r\n logger.debug(`🔄 Reloading app: ${this.name}`)\r\n\r\n await this.unmount()\r\n\r\n // Limpiar caches\r\n if (this._wu.loader?.clearCache) {\r\n this._wu.loader.clearCache(this.name)\r\n }\r\n if (this._wu.manifest?.clearCache) {\r\n this._wu.manifest.clearCache(this.name)\r\n }\r\n\r\n await this.mount()\r\n logger.debug(`✅ App reloaded: ${this.name}`)\r\n\r\n return this\r\n }\r\n\r\n /**\r\n * Verificar el estado de la app\r\n * @returns {Object}\r\n */\r\n async verify() {\r\n const container = document.querySelector(this.container)\r\n const hasShadowDOM = container?.shadowRoot !== null\r\n const hasContent = (container?.shadowRoot?.children?.length || 0) > 0\r\n\r\n return {\r\n name: this.name,\r\n mounted: this.isMounted,\r\n container: {\r\n found: !!container,\r\n selector: this.container,\r\n hasShadowDOM,\r\n hasContent\r\n },\r\n wu: {\r\n registered: this._wu.apps.has(this.name),\r\n mountedInWu: this._wu.mounted?.has(this.name)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Shorthand para mount\r\n */\r\n async start(container) {\r\n return await this.mount(container)\r\n }\r\n\r\n /**\r\n * Shorthand para unmount\r\n */\r\n async stop() {\r\n return await this.unmount()\r\n }\r\n\r\n /**\r\n * Destruir la app completamente\r\n */\r\n async destroy() {\r\n await this.unmount({ force: true })\r\n this._wu.apps.delete(this.name)\r\n this._mounted = false\r\n logger.debug(`🗑️ App destroyed: ${this.name}`)\r\n }\r\n}\r\n","/**\r\n * 💾 WU-CACHE: SECURE INTERNAL CACHING\r\n *\r\n * Sistema de caché INTERNO con rate limiting\r\n * - Rate limiting para prevenir abuso\r\n * - Cache persistente y en memoria\r\n * - TTL y LRU eviction\r\n *\r\n * ⚠️ USO INTERNO: No exponer en API pública\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuCache {\r\n constructor(options = {}) {\r\n this.config = {\r\n maxSize: options.maxSize || 50, // MB\r\n maxItems: options.maxItems || 100,\r\n defaultTTL: options.defaultTTL || 3600000, // 1 hour\r\n persistent: options.persistent !== false,\r\n storage: options.storage || 'memory'\r\n };\r\n\r\n // 🔐 Rate limiting configuration\r\n this.rateLimiting = {\r\n enabled: options.rateLimiting !== false,\r\n maxOpsPerSecond: options.maxOpsPerSecond || 100,\r\n windowMs: 1000, // 1 second window\r\n cooldownMs: options.cooldownMs || 5000, // 5 second cooldown after limit\r\n operations: [],\r\n inCooldown: false,\r\n cooldownUntil: 0\r\n };\r\n\r\n // Rate limit notification flag (log only once per cooldown)\r\n this._rateLimitNotified = false;\r\n\r\n // Memory cache\r\n this.memoryCache = new Map();\r\n\r\n // LRU tracking\r\n this.accessOrder = new Map();\r\n\r\n // Statistics\r\n this.stats = {\r\n hits: 0,\r\n misses: 0,\r\n sets: 0,\r\n evictions: 0,\r\n size: 0,\r\n rateLimited: 0 // 🔐 Contador de operaciones rechazadas\r\n };\r\n }\r\n\r\n /**\r\n * 🔐 CHECK RATE LIMIT: Verificar si la operación está permitida\r\n * @returns {boolean} true si la operación está permitida\r\n */\r\n _checkRateLimit() {\r\n if (!this.rateLimiting.enabled) return true;\r\n\r\n const now = Date.now();\r\n\r\n // Verificar si estamos en cooldown\r\n if (this.rateLimiting.inCooldown) {\r\n if (now < this.rateLimiting.cooldownUntil) {\r\n this.stats.rateLimited++;\r\n return false;\r\n }\r\n // Cooldown terminado\r\n this.rateLimiting.inCooldown = false;\r\n this._rateLimitNotified = false;\r\n this.rateLimiting.operations = [];\r\n }\r\n\r\n // Limpiar operaciones antiguas (fuera de la ventana)\r\n const windowStart = now - this.rateLimiting.windowMs;\r\n this.rateLimiting.operations = this.rateLimiting.operations.filter(\r\n ts => ts > windowStart\r\n );\r\n\r\n // Verificar límite\r\n if (this.rateLimiting.operations.length >= this.rateLimiting.maxOpsPerSecond) {\r\n // Activar cooldown\r\n this.rateLimiting.inCooldown = true;\r\n this.rateLimiting.cooldownUntil = now + this.rateLimiting.cooldownMs;\r\n this.stats.rateLimited++;\r\n logger.warn(`[WuCache] 🚫 Rate limit exceeded. Cooldown for ${this.rateLimiting.cooldownMs}ms`);\r\n return false;\r\n }\r\n\r\n // Registrar operación\r\n this.rateLimiting.operations.push(now);\r\n return true;\r\n }\r\n\r\n /**\r\n * Handle rate-limited operations: log once per cooldown, return diagnostic object\r\n * @param {string} operation - The operation that was rate limited ('get' or 'set')\r\n * @param {string} key - The cache key that was rejected\r\n * @returns {{ rateLimited: true, operation: string, key: string }}\r\n */\r\n _onRateLimited(operation, key) {\r\n if (!this._rateLimitNotified) {\r\n const cooldownRemaining = Math.max(0, this.rateLimiting.cooldownUntil - Date.now());\r\n logger.warn(`[WuCache] Rate limited: ${operation} for key \"${key}\" rejected. ${cooldownRemaining}ms remaining in cooldown.`);\r\n this._rateLimitNotified = true;\r\n }\r\n return { rateLimited: true, operation, key };\r\n }\r\n\r\n /**\r\n * GET RATE LIMIT STATUS\r\n */\r\n getRateLimitStatus() {\r\n const now = Date.now();\r\n return {\r\n enabled: this.rateLimiting.enabled,\r\n inCooldown: this.rateLimiting.inCooldown,\r\n cooldownRemaining: this.rateLimiting.inCooldown\r\n ? Math.max(0, this.rateLimiting.cooldownUntil - now)\r\n : 0,\r\n currentOps: this.rateLimiting.operations.length,\r\n maxOps: this.rateLimiting.maxOpsPerSecond,\r\n rateLimited: this.stats.rateLimited\r\n };\r\n }\r\n\r\n /**\r\n * 🔍 GET: Obtener valor del cache\r\n * @param {string} key - Clave\r\n * @returns {*} Valor cacheado o null\r\n */\r\n get(key) {\r\n // 🔐 Check rate limit\r\n if (!this._checkRateLimit()) {\r\n this._onRateLimited('get', key);\r\n return null;\r\n }\r\n\r\n // 1. Buscar en memoria\r\n if (this.memoryCache.has(key)) {\r\n const entry = this.memoryCache.get(key);\r\n\r\n // Verificar TTL\r\n if (this.isExpired(entry)) {\r\n this.delete(key);\r\n this.stats.misses++;\r\n return null;\r\n }\r\n\r\n // Actualizar acceso (LRU)\r\n this.accessOrder.set(key, Date.now());\r\n this.stats.hits++;\r\n\r\n return entry.value;\r\n }\r\n\r\n // 2. Buscar en storage persistente\r\n if (this.config.persistent) {\r\n const stored = this.getFromStorage(key);\r\n if (stored) {\r\n // Restaurar a memoria\r\n this.memoryCache.set(key, stored);\r\n this.accessOrder.set(key, Date.now());\r\n this.stats.hits++;\r\n return stored.value;\r\n }\r\n }\r\n\r\n this.stats.misses++;\r\n return null;\r\n }\r\n\r\n /**\r\n * 💾 SET: Guardar valor en cache\r\n * @param {string} key - Clave\r\n * @param {*} value - Valor\r\n * @param {number} ttl - Time to live (ms)\r\n * @returns {boolean}\r\n */\r\n set(key, value, ttl) {\r\n // 🔐 Check rate limit\r\n if (!this._checkRateLimit()) {\r\n this._onRateLimited('set', key);\r\n return false;\r\n }\r\n\r\n try {\r\n const entry = {\r\n key,\r\n value,\r\n timestamp: Date.now(),\r\n ttl: ttl || this.config.defaultTTL,\r\n size: this.estimateSize(value)\r\n };\r\n\r\n // Verificar si necesitamos hacer espacio\r\n const hasSpace = this.ensureSpace(entry.size);\r\n if (hasSpace === false) {\r\n logger.warn(`[WuCache] ⚠️ Cannot cache item: ${key} (too large)`);\r\n return false;\r\n }\r\n\r\n // Guardar en memoria\r\n this.memoryCache.set(key, entry);\r\n this.accessOrder.set(key, Date.now());\r\n\r\n // Guardar en storage persistente\r\n if (this.config.persistent) {\r\n this.saveToStorage(key, entry);\r\n }\r\n\r\n this.stats.sets++;\r\n this.stats.size += entry.size;\r\n\r\n return true;\r\n } catch (error) {\r\n logger.warn('[WuCache] ⚠️ Failed to set cache:', error);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * 🗑️ DELETE: Eliminar del cache\r\n * @param {string} key - Clave\r\n */\r\n delete(key) {\r\n const entry = this.memoryCache.get(key);\r\n if (entry) {\r\n this.stats.size -= entry.size;\r\n }\r\n\r\n this.memoryCache.delete(key);\r\n this.accessOrder.delete(key);\r\n\r\n if (this.config.persistent) {\r\n this.deleteFromStorage(key);\r\n }\r\n }\r\n\r\n /**\r\n * 🧹 CLEAR: Limpiar todo el cache\r\n */\r\n clear() {\r\n this.memoryCache.clear();\r\n this.accessOrder.clear();\r\n this.stats.size = 0;\r\n\r\n if (this.config.persistent) {\r\n this.clearStorage();\r\n }\r\n\r\n logger.debug('[WuCache] 🧹 Cache cleared');\r\n }\r\n\r\n /**\r\n * ⏰ IS EXPIRED: Verificar si entrada expiró\r\n * @param {Object} entry - Entrada del cache\r\n * @returns {boolean}\r\n */\r\n isExpired(entry) {\r\n if (!entry.ttl) return false;\r\n return Date.now() - entry.timestamp > entry.ttl;\r\n }\r\n\r\n /**\r\n * 📏 ESTIMATE SIZE: Estimar tamaño de un valor\r\n * @param {*} value - Valor\r\n * @returns {number} Tamaño en bytes\r\n */\r\n estimateSize(value) {\r\n if (typeof value === 'string') {\r\n return value.length * 2; // UTF-16\r\n }\r\n\r\n if (typeof value === 'object') {\r\n try {\r\n return JSON.stringify(value).length * 2;\r\n } catch {\r\n return 1000; // Estimación por defecto\r\n }\r\n }\r\n\r\n return 100; // Tamaño por defecto para primitivos\r\n }\r\n\r\n /**\r\n * 🎯 ENSURE SPACE: Asegurar espacio en cache (LRU eviction)\r\n * @param {number} neededSize - Tamaño necesario\r\n */\r\n ensureSpace(neededSize) {\r\n const maxSizeBytes = this.config.maxSize * 1024 * 1024;\r\n\r\n // 🛡️ FIX: Validar que el item no sea más grande que el máximo permitido\r\n if (neededSize > maxSizeBytes) {\r\n logger.warn(`[WuCache] ⚠️ Item size (${neededSize}) exceeds max cache size (${maxSizeBytes}). Skipping.`);\r\n return false;\r\n }\r\n\r\n // 🛡️ FIX: Límite de iteraciones para evitar loop infinito\r\n const maxIterations = this.config.maxItems + 10;\r\n let iterations = 0;\r\n\r\n // Verificar si necesitamos limpiar\r\n while ((this.stats.size + neededSize > maxSizeBytes ||\r\n this.memoryCache.size >= this.config.maxItems) &&\r\n iterations < maxIterations) {\r\n\r\n iterations++;\r\n\r\n // 🛡️ FIX: Si el cache está vacío pero aún no hay espacio, salir\r\n if (this.memoryCache.size === 0) {\r\n logger.warn('[WuCache] ⚠️ Cache empty but still no space. Breaking loop.');\r\n break;\r\n }\r\n\r\n // Encontrar entrada menos recientemente usada (LRU)\r\n let oldestKey = null;\r\n let oldestTime = Infinity;\r\n\r\n for (const [key, time] of this.accessOrder) {\r\n if (time < oldestTime) {\r\n oldestTime = time;\r\n oldestKey = key;\r\n }\r\n }\r\n\r\n if (oldestKey) {\r\n logger.debug(`[WuCache] 🗑️ Evicting LRU entry: ${oldestKey}`);\r\n this.delete(oldestKey);\r\n this.stats.evictions++;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n // 🛡️ FIX: Log si alcanzamos el límite de iteraciones\r\n if (iterations >= maxIterations) {\r\n console.error(`[WuCache] 🚨 Max eviction iterations reached (${maxIterations}). Possible infinite loop prevented.`);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * 💽 GET FROM STORAGE: Obtener del storage persistente\r\n * @param {string} key - Clave\r\n * @returns {Object|null}\r\n */\r\n getFromStorage(key) {\r\n try {\r\n const storage = this.getStorage();\r\n const stored = storage.getItem(`wu_cache_${key}`);\r\n\r\n if (stored) {\r\n return JSON.parse(stored);\r\n }\r\n } catch (error) {\r\n logger.warn('[WuCache] ⚠️ Failed to get from storage:', error);\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * 💾 SAVE TO STORAGE: Guardar en storage persistente\r\n * @param {string} key - Clave\r\n * @param {Object} entry - Entrada\r\n */\r\n saveToStorage(key, entry) {\r\n const storage = this.getStorage();\r\n try {\r\n storage.setItem(`wu_cache_${key}`, JSON.stringify(entry));\r\n } catch (error) {\r\n // Storage lleno, limpiar entradas antiguas\r\n logger.warn('[WuCache] ⚠️ Storage full, cleaning old entries');\r\n this.cleanOldStorageEntries();\r\n\r\n try {\r\n storage.setItem(`wu_cache_${key}`, JSON.stringify(entry));\r\n } catch {\r\n logger.warn('[WuCache] ⚠️ Failed to save to storage after cleanup');\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 🗑️ DELETE FROM STORAGE: Eliminar del storage\r\n * @param {string} key - Clave\r\n */\r\n deleteFromStorage(key) {\r\n try {\r\n const storage = this.getStorage();\r\n storage.removeItem(`wu_cache_${key}`);\r\n } catch (error) {\r\n logger.warn('[WuCache] ⚠️ Failed to delete from storage:', error);\r\n }\r\n }\r\n\r\n /**\r\n * 🧹 CLEAR STORAGE: Limpiar storage\r\n */\r\n clearStorage() {\r\n try {\r\n const storage = this.getStorage();\r\n const keys = Object.keys(storage);\r\n\r\n keys.forEach(key => {\r\n if (key.startsWith('wu_cache_')) {\r\n storage.removeItem(key);\r\n }\r\n });\r\n } catch (error) {\r\n logger.warn('[WuCache] ⚠️ Failed to clear storage:', error);\r\n }\r\n }\r\n\r\n /**\r\n * 🧹 CLEAN OLD STORAGE ENTRIES: Limpiar entradas antiguas del storage\r\n */\r\n cleanOldStorageEntries() {\r\n try {\r\n const storage = this.getStorage();\r\n const keys = Object.keys(storage);\r\n const entries = [];\r\n\r\n // Recopilar todas las entradas con timestamp\r\n keys.forEach(key => {\r\n if (key.startsWith('wu_cache_')) {\r\n try {\r\n const entry = JSON.parse(storage.getItem(key));\r\n entries.push({ key, timestamp: entry.timestamp });\r\n } catch {}\r\n }\r\n });\r\n\r\n // Ordenar por timestamp (más antiguas primero)\r\n entries.sort((a, b) => a.timestamp - b.timestamp);\r\n\r\n // Eliminar 25% de entradas más antiguas\r\n const toRemove = Math.ceil(entries.length * 0.25);\r\n for (let i = 0; i < toRemove; i++) {\r\n storage.removeItem(entries[i].key);\r\n }\r\n\r\n logger.debug(`[WuCache] 🧹 Cleaned ${toRemove} old storage entries`);\r\n } catch (error) {\r\n logger.warn('[WuCache] ⚠️ Failed to clean old storage entries:', error);\r\n }\r\n }\r\n\r\n /**\r\n * 💽 GET STORAGE: Obtener instancia de storage\r\n * @returns {Storage}\r\n */\r\n getStorage() {\r\n if (this.config.storage === 'localStorage') {\r\n return window.localStorage;\r\n } else if (this.config.storage === 'sessionStorage') {\r\n return window.sessionStorage;\r\n }\r\n // Fallback a memoria\r\n return {\r\n getItem: () => null,\r\n setItem: () => {},\r\n removeItem: () => {},\r\n clear: () => {}\r\n };\r\n }\r\n\r\n /**\r\n * 📊 GET STATS: Obtener estadísticas del cache\r\n * @returns {Object}\r\n */\r\n getStats() {\r\n const hitRate = this.stats.hits + this.stats.misses > 0\r\n ? (this.stats.hits / (this.stats.hits + this.stats.misses) * 100).toFixed(2)\r\n : 0;\r\n\r\n return {\r\n ...this.stats,\r\n hitRate: `${hitRate}%`,\r\n items: this.memoryCache.size,\r\n sizeMB: (this.stats.size / 1024 / 1024).toFixed(2)\r\n };\r\n }\r\n\r\n /**\r\n * ⚙️ CONFIGURE: Actualizar configuración\r\n * @param {Object} config - Nueva configuración\r\n */\r\n configure(config) {\r\n this.config = {\r\n ...this.config,\r\n ...config\r\n };\r\n }\r\n}\r\n","/**\r\n * 📡 WU-EVENT-BUS: SECURE PUB/SUB SYSTEM\r\n *\r\n * Sistema de eventos para comunicación entre microfrontends\r\n * - Pub/Sub pattern con validación de origen\r\n * - Event namespaces\r\n * - Wildcards\r\n * - Event replay\r\n * - Verificación de apps autorizadas\r\n */\r\nimport { logger } from './wu-logger.js';\r\n\r\n/**\r\n * @typedef {Object} WuEvent\r\n * @property {string} name - Event name\r\n * @property {*} data - Event payload\r\n * @property {number} timestamp - Event timestamp\r\n * @property {string} appName - Source app name\r\n * @property {Object} meta - Additional metadata\r\n * @property {boolean} verified - Whether origin was verified\r\n */\r\n\r\n/**\r\n * @typedef {Object} WuEventBusConfig\r\n * @property {number} [maxHistory=100] - Maximum events in history\r\n * @property {boolean} [enableReplay=true] - Enable event replay\r\n * @property {boolean} [enableWildcards=true] - Enable wildcard matching\r\n * @property {boolean} [logEvents=false] - Log all events\r\n * @property {boolean} [strictMode=false] - Reject unauthorized events\r\n * @property {boolean} [validateOrigin=true] - Validate event origins\r\n */\r\n\r\nexport class WuEventBus {\r\n constructor() {\r\n this.listeners = new Map();\r\n this.history = [];\r\n\r\n // 🔐 SEGURIDAD: Registro de apps autorizadas con tokens\r\n this.authorizedApps = new Map(); // appName -> { token, permissions }\r\n this.trustedEvents = new Set(['wu:*', 'system:*']); // Eventos del sistema\r\n\r\n // Auto-detect production environment for strictMode default\r\n const isProduction = typeof process !== 'undefined' && process.env?.NODE_ENV === 'production';\r\n\r\n this.config = {\r\n maxHistory: 100,\r\n enableReplay: true,\r\n enableWildcards: true,\r\n logEvents: false,\r\n // 🔐 Opciones de seguridad\r\n strictMode: isProduction, // Auto-enabled in production, permissive in development\r\n validateOrigin: true // Valida que appName sea una app registrada\r\n };\r\n\r\n this._permissiveWarned = false;\r\n\r\n this.stats = {\r\n emitted: 0,\r\n subscriptions: 0,\r\n rejected: 0 // Eventos rechazados por seguridad\r\n };\r\n }\r\n\r\n /**\r\n * 🔐 REGISTER APP: Registrar app autorizada para emitir eventos\r\n * @param {string} appName - Nombre de la app\r\n * @param {Object} options - { permissions: ['event:*'], token }\r\n * @returns {string} Token de autorización\r\n */\r\n registerApp(appName, options = {}) {\r\n const token = options.token || this._generateToken();\r\n\r\n this.authorizedApps.set(appName, {\r\n token,\r\n permissions: options.permissions || ['*'], // Por defecto puede emitir todo\r\n registeredAt: Date.now()\r\n });\r\n\r\n return token;\r\n }\r\n\r\n /**\r\n * 🔓 UNREGISTER APP: Desregistrar app\r\n * @param {string} appName\r\n */\r\n unregisterApp(appName) {\r\n this.authorizedApps.delete(appName);\r\n }\r\n\r\n /**\r\n * 🔐 VALIDATE ORIGIN: Verificar que el emisor está autorizado\r\n * @param {string} eventName\r\n * @param {string} appName\r\n * @param {string} token\r\n * @returns {boolean}\r\n */\r\n _validateOrigin(eventName, appName, token) {\r\n // Eventos del sistema siempre permitidos\r\n if (this._isSystemEvent(eventName)) {\r\n return true;\r\n }\r\n\r\n // Si no está en modo estricto, permitir todo\r\n if (!this.config.strictMode) {\r\n return true;\r\n }\r\n\r\n // Verificar que la app esté registrada\r\n const appInfo = this.authorizedApps.get(appName);\r\n if (!appInfo) {\r\n return false;\r\n }\r\n\r\n // Verificar token si se proporciona\r\n if (token && appInfo.token !== token) {\r\n return false;\r\n }\r\n\r\n // Verificar permisos\r\n return this._hasPermission(appInfo.permissions, eventName);\r\n }\r\n\r\n /**\r\n * 🔐 HAS PERMISSION: Verificar si la app tiene permiso para el evento\r\n */\r\n _hasPermission(permissions, eventName) {\r\n if (permissions.includes('*')) return true;\r\n\r\n return permissions.some(pattern => {\r\n if (pattern === eventName) return true;\r\n if (pattern.includes('*')) {\r\n return this.matchesWildcard(eventName, pattern);\r\n }\r\n return false;\r\n });\r\n }\r\n\r\n /**\r\n * 🔐 IS SYSTEM EVENT: Verificar si es un evento del sistema\r\n */\r\n _isSystemEvent(eventName) {\r\n return eventName.startsWith('wu:') ||\r\n eventName.startsWith('system:') ||\r\n eventName.startsWith('app:');\r\n }\r\n\r\n /**\r\n * 🔐 GENERATE TOKEN: Generar token único\r\n */\r\n _generateToken() {\r\n return `wu_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n }\r\n\r\n /**\r\n * WARN PERMISSIVE MODE: Log a one-time warning when strictMode is off\r\n * Alerts developers that events are flowing without authorization checks\r\n */\r\n _warnPermissiveMode() {\r\n if (this._permissiveWarned) return;\r\n this._permissiveWarned = true;\r\n logger.warn(\r\n '[WuEventBus] strictMode is disabled. Events are emitted without authorization checks. ' +\r\n 'Enable strictMode for production by calling enableStrictMode() or setting NODE_ENV=production.'\r\n );\r\n }\r\n\r\n /**\r\n * 📢 EMIT: Emitir evento con validación de origen\r\n * @param {string} eventName - Nombre del evento\r\n * @param {*} data - Datos del evento\r\n * @param {Object} options - { appName, timestamp, meta, token }\r\n */\r\n emit(eventName, data, options = {}) {\r\n const appName = options.appName || 'unknown';\r\n\r\n // Warn once if running in permissive mode (strictMode off)\r\n if (!this.config.strictMode) {\r\n this._warnPermissiveMode();\r\n }\r\n\r\n // 🔐 Validar origen si está habilitado\r\n if (this.config.validateOrigin && this.config.strictMode) {\r\n if (!this._validateOrigin(eventName, appName, options.token)) {\r\n this.stats.rejected++;\r\n logger.warn(`[WuEventBus] 🚫 Event rejected: ${eventName} from ${appName} (unauthorized)`);\r\n return false;\r\n }\r\n }\r\n\r\n const event = {\r\n name: eventName,\r\n data,\r\n timestamp: options.timestamp || Date.now(),\r\n appName,\r\n meta: options.meta || {},\r\n // 🔐 Marcar si el origen fue verificado\r\n verified: this.authorizedApps.has(appName)\r\n };\r\n\r\n // Agregar a historial\r\n if (this.config.enableReplay) {\r\n this.addToHistory(event);\r\n }\r\n\r\n // Log si está habilitado\r\n if (this.config.logEvents) {\r\n logger.debug(`[WuEventBus] 📢 ${eventName}`, data);\r\n }\r\n\r\n // Notificar listeners exactos\r\n const exactListeners = this.listeners.get(eventName);\r\n if (exactListeners) {\r\n exactListeners.forEach(callback => {\r\n try {\r\n callback(event);\r\n } catch (error) {\r\n console.error(`[WuEventBus] ❌ Error in listener for ${eventName}:`, error);\r\n }\r\n });\r\n }\r\n\r\n // Notificar listeners con wildcards\r\n if (this.config.enableWildcards) {\r\n this.notifyWildcardListeners(eventName, event);\r\n }\r\n\r\n this.stats.emitted++;\r\n return true;\r\n }\r\n\r\n /**\r\n * 👂 ON: Suscribirse a evento\r\n */\r\n on(eventName, callback) {\r\n if (!this.listeners.has(eventName)) {\r\n this.listeners.set(eventName, new Set());\r\n }\r\n\r\n this.listeners.get(eventName).add(callback);\r\n this.stats.subscriptions++;\r\n\r\n return () => this.off(eventName, callback);\r\n }\r\n\r\n /**\r\n * 🔇 OFF: Desuscribirse de evento\r\n */\r\n off(eventName, callback) {\r\n const listeners = this.listeners.get(eventName);\r\n if (listeners) {\r\n listeners.delete(callback);\r\n if (listeners.size === 0) {\r\n this.listeners.delete(eventName);\r\n }\r\n this.stats.subscriptions--;\r\n }\r\n }\r\n\r\n /**\r\n * 🎯 ONCE: Suscribirse una sola vez\r\n */\r\n once(eventName, callback) {\r\n const wrappedCallback = (event) => {\r\n callback(event);\r\n this.off(eventName, wrappedCallback);\r\n };\r\n return this.on(eventName, wrappedCallback);\r\n }\r\n\r\n /**\r\n * 🌟 WILDCARD LISTENERS\r\n */\r\n notifyWildcardListeners(eventName, event) {\r\n for (const [pattern, listeners] of this.listeners) {\r\n if (this.matchesWildcard(eventName, pattern)) {\r\n listeners.forEach(callback => {\r\n try {\r\n callback(event);\r\n } catch (error) {\r\n console.error(`[WuEventBus] ❌ Error in wildcard listener for ${pattern}:`, error);\r\n }\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 🎯 MATCHES WILDCARD\r\n */\r\n matchesWildcard(eventName, pattern) {\r\n if (!pattern.includes('*')) return false;\r\n const regexPattern = pattern\r\n .replace(/\\./g, '\\\\.')\r\n .replace(/\\*/g, '.*');\r\n const regex = new RegExp(`^${regexPattern}$`);\r\n return regex.test(eventName);\r\n }\r\n\r\n /**\r\n * 📝 ADD TO HISTORY\r\n */\r\n addToHistory(event) {\r\n this.history.push(event);\r\n if (this.history.length > this.config.maxHistory) {\r\n this.history.shift();\r\n }\r\n }\r\n\r\n /**\r\n * 🔄 REPLAY\r\n */\r\n replay(eventNameOrPattern, callback) {\r\n const events = this.history.filter(event => {\r\n if (eventNameOrPattern.includes('*')) {\r\n return this.matchesWildcard(event.name, eventNameOrPattern);\r\n }\r\n return event.name === eventNameOrPattern;\r\n });\r\n\r\n events.forEach(event => {\r\n try {\r\n callback(event);\r\n } catch (error) {\r\n console.error(`[WuEventBus] ❌ Error replaying event:`, error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 🧹 CLEAR HISTORY\r\n */\r\n clearHistory(eventNameOrPattern) {\r\n if (!eventNameOrPattern) {\r\n this.history = [];\r\n return;\r\n }\r\n\r\n this.history = this.history.filter(event => {\r\n if (eventNameOrPattern.includes('*')) {\r\n return !this.matchesWildcard(event.name, eventNameOrPattern);\r\n }\r\n return event.name !== eventNameOrPattern;\r\n });\r\n }\r\n\r\n /**\r\n * 📊 GET STATS\r\n */\r\n getStats() {\r\n return {\r\n ...this.stats,\r\n activeListeners: this.listeners.size,\r\n historySize: this.history.length,\r\n authorizedApps: this.authorizedApps.size,\r\n listenersByEvent: Array.from(this.listeners.entries()).map(([event, listeners]) => ({\r\n event,\r\n listeners: listeners.size\r\n }))\r\n };\r\n }\r\n\r\n /**\r\n * ⚙️ CONFIGURE\r\n */\r\n configure(config) {\r\n this.config = { ...this.config, ...config };\r\n }\r\n\r\n /**\r\n * 🔐 ENABLE STRICT MODE: Activar modo estricto de seguridad\r\n */\r\n enableStrictMode() {\r\n this.config.strictMode = true;\r\n }\r\n\r\n /**\r\n * 🔓 DISABLE STRICT MODE\r\n */\r\n disableStrictMode() {\r\n this.config.strictMode = false;\r\n }\r\n\r\n /**\r\n * 🗑️ REMOVE ALL\r\n */\r\n removeAll() {\r\n this.listeners.clear();\r\n this.stats.subscriptions = 0;\r\n }\r\n}\r\n","/**\r\n * ⚡ WU-PERFORMANCE: MICROFRONTEND LIFECYCLE MONITORING\r\n *\r\n * Monitoreo de performance específico para operaciones del framework:\r\n * - Tiempos de mount/unmount\r\n * - Tiempos de carga de módulos\r\n * - Estadísticas por app\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuPerformance {\r\n constructor() {\r\n this.metrics = new Map(); // appName -> metrics\r\n this.measurements = [];\r\n this.marks = new Map();\r\n\r\n this.config = {\r\n enabled: true,\r\n maxMeasurements: 1000\r\n };\r\n\r\n this.thresholds = {\r\n mount: 3000, // ms\r\n unmount: 1000, // ms\r\n load: 5000 // ms\r\n };\r\n\r\n logger.debug('[WuPerformance] ⚡ Framework performance monitoring initialized');\r\n }\r\n\r\n /**\r\n * 📊 START MEASURE: Iniciar medición\r\n * @param {string} name - Nombre de la medición\r\n * @param {string} appName - Nombre de la app (opcional)\r\n */\r\n startMeasure(name, appName = 'global') {\r\n const markName = `${appName}:${name}:start`;\r\n this.marks.set(markName, performance.now());\r\n\r\n logger.debug(`[WuPerformance] 📊 Measure started: ${markName}`);\r\n }\r\n\r\n /**\r\n * ⏹️ END MEASURE: Finalizar medición\r\n * @param {string} name - Nombre de la medición\r\n * @param {string} appName - Nombre de la app (opcional)\r\n * @returns {number} Duración en ms\r\n */\r\n endMeasure(name, appName = 'global') {\r\n const markName = `${appName}:${name}:start`;\r\n const startTime = this.marks.get(markName);\r\n\r\n if (!startTime) {\r\n // Puede ocurrir en React StrictMode (doble mount) — no es un error\r\n return 0;\r\n }\r\n\r\n const duration = performance.now() - startTime;\r\n this.marks.delete(markName);\r\n\r\n // Registrar medición\r\n this.recordMeasurement({\r\n name,\r\n appName,\r\n duration,\r\n timestamp: Date.now(),\r\n type: 'duration'\r\n });\r\n\r\n // Verificar threshold\r\n if (this.checkThreshold(name, duration)) {\r\n logger.warn(`[WuPerformance] ⚠️ Threshold exceeded for ${name}: ${duration.toFixed(2)}ms`);\r\n }\r\n\r\n logger.debug(`[WuPerformance] ⏹️ Measure ended: ${markName} (${duration.toFixed(2)}ms)`);\r\n return duration;\r\n }\r\n\r\n /**\r\n * 📝 RECORD MEASUREMENT: Registrar medición\r\n * @param {Object} measurement - Medición\r\n */\r\n recordMeasurement(measurement) {\r\n this.measurements.push(measurement);\r\n\r\n // Mantener tamaño máximo\r\n if (this.measurements.length > this.config.maxMeasurements) {\r\n this.measurements.shift();\r\n }\r\n\r\n // Actualizar métricas de la app\r\n if (!this.metrics.has(measurement.appName)) {\r\n this.metrics.set(measurement.appName, {\r\n appName: measurement.appName,\r\n measurements: [],\r\n stats: {}\r\n });\r\n }\r\n\r\n const appMetrics = this.metrics.get(measurement.appName);\r\n appMetrics.measurements.push(measurement);\r\n\r\n // Calcular estadísticas\r\n this.calculateStats(measurement.appName);\r\n }\r\n\r\n /**\r\n * 📊 CALCULATE STATS: Calcular estadísticas\r\n * @param {string} appName - Nombre de la app\r\n */\r\n calculateStats(appName) {\r\n const appMetrics = this.metrics.get(appName);\r\n if (!appMetrics) return;\r\n\r\n const measurements = appMetrics.measurements;\r\n if (measurements.length === 0) return;\r\n\r\n // Agrupar por tipo de medición\r\n const byType = {};\r\n measurements.forEach(m => {\r\n if (!byType[m.name]) byType[m.name] = [];\r\n byType[m.name].push(m.duration);\r\n });\r\n\r\n // Calcular estadísticas para cada tipo\r\n appMetrics.stats = {};\r\n Object.entries(byType).forEach(([name, durations]) => {\r\n appMetrics.stats[name] = {\r\n count: durations.length,\r\n avg: durations.reduce((a, b) => a + b, 0) / durations.length,\r\n min: Math.min(...durations),\r\n max: Math.max(...durations),\r\n last: durations[durations.length - 1]\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * 🎯 CHECK THRESHOLD: Verificar si se excedió threshold\r\n * @param {string} name - Nombre de la medición\r\n * @param {number} value - Valor\r\n * @returns {boolean}\r\n */\r\n checkThreshold(name, value) {\r\n const threshold = this.thresholds[name];\r\n return threshold && value > threshold;\r\n }\r\n\r\n /**\r\n * 📊 GENERATE REPORT: Generar reporte de performance del framework\r\n * @returns {Object}\r\n */\r\n generateReport() {\r\n const report = {\r\n timestamp: Date.now(),\r\n totalMeasurements: this.measurements.length,\r\n apps: {}\r\n };\r\n\r\n // Agregar métricas por app\r\n for (const [appName, metrics] of this.metrics) {\r\n report.apps[appName] = {\r\n measurementCount: metrics.measurements.length,\r\n stats: metrics.stats\r\n };\r\n }\r\n\r\n return report;\r\n }\r\n\r\n /**\r\n * 📋 GET METRICS: Obtener métricas de una app\r\n * @param {string} appName - Nombre de la app\r\n * @returns {Object}\r\n */\r\n getMetrics(appName) {\r\n return this.metrics.get(appName) || null;\r\n }\r\n\r\n /**\r\n * 📊 GET ALL METRICS: Obtener todas las métricas\r\n * @returns {Object}\r\n */\r\n getAllMetrics() {\r\n const allMetrics = {};\r\n\r\n for (const [appName, metrics] of this.metrics) {\r\n allMetrics[appName] = metrics;\r\n }\r\n\r\n return allMetrics;\r\n }\r\n\r\n /**\r\n * 🧹 CLEAR METRICS: Limpiar métricas\r\n * @param {string} appName - Nombre de la app (opcional)\r\n */\r\n clearMetrics(appName) {\r\n if (appName) {\r\n this.metrics.delete(appName);\r\n this.measurements = this.measurements.filter(m => m.appName !== appName);\r\n } else {\r\n this.metrics.clear();\r\n this.measurements = [];\r\n }\r\n\r\n logger.debug(`[WuPerformance] 🧹 Metrics cleared${appName ? ` for ${appName}` : ''}`);\r\n }\r\n\r\n /**\r\n * ⚙️ CONFIGURE: Configurar performance monitor\r\n * @param {Object} config - Nueva configuración\r\n */\r\n configure(config) {\r\n this.config = {\r\n ...this.config,\r\n ...config\r\n };\r\n\r\n if (config.thresholds) {\r\n this.thresholds = {\r\n ...this.thresholds,\r\n ...config.thresholds\r\n };\r\n }\r\n }\r\n}\r\n","/**\r\n * 🔌 WU-PLUGIN: SECURE PLUGIN SYSTEM\r\n *\r\n * Sistema de plugins con sandboxing de seguridad\r\n * - Plugin lifecycle (install, beforeMount, afterMount, etc.)\r\n * - Sandboxed API (plugins no tienen acceso completo al core)\r\n * - Permission system\r\n * - Timeout protection\r\n */\r\nimport { logger } from './wu-logger.js';\r\n\r\n\r\nexport class WuPluginSystem {\r\n constructor(core, options = {}) {\r\n this._core = core; // Privado - no expuesto a plugins\r\n this.plugins = new Map();\r\n this.hooks = new Map();\r\n\r\n // Hooks disponibles\r\n this.availableHooks = [\r\n 'beforeInit', 'afterInit',\r\n 'beforeMount', 'afterMount',\r\n 'beforeUnmount', 'afterUnmount',\r\n 'onError', 'onDestroy'\r\n ];\r\n\r\n // 🔐 Permisos disponibles\r\n this.availablePermissions = [\r\n 'mount', // Puede montar/desmontar apps\r\n 'events', // Puede emitir/escuchar eventos\r\n 'store', // Puede leer/escribir store\r\n 'apps', // Puede ver lista de apps\r\n 'config', // Puede modificar configuración\r\n 'unsafe' // Acceso completo (peligroso)\r\n ];\r\n\r\n // 🔐 Timeout para hooks (evita que plugins bloqueen)\r\n this.hookTimeout = options.hookTimeout || 5000; // Default: 5 segundos\r\n\r\n this.availableHooks.forEach(hook => {\r\n this.hooks.set(hook, []);\r\n });\r\n }\r\n\r\n /**\r\n * 🔐 CREATE SANDBOXED API: Crea API limitada para el plugin\r\n * @param {Array} permissions - Permisos del plugin\r\n * @returns {Object} API sandboxeada\r\n */\r\n _createSandboxedApi(permissions) {\r\n const api = {\r\n // Info básica siempre disponible\r\n version: this._core.version,\r\n info: this._core.info,\r\n\r\n // 📊 Métodos de solo lectura\r\n getAppInfo: (appName) => {\r\n const mounted = this._core.mounted.get(appName);\r\n if (!mounted) return null;\r\n return {\r\n name: appName,\r\n state: mounted.state,\r\n timestamp: mounted.timestamp\r\n };\r\n },\r\n\r\n getMountedApps: () => {\r\n return Array.from(this._core.mounted.keys());\r\n },\r\n\r\n getStats: () => this._core.getStats()\r\n };\r\n\r\n // 🔐 Agregar métodos según permisos\r\n if (permissions.includes('events') || permissions.includes('unsafe')) {\r\n api.emit = (event, data) => this._core.eventBus.emit(event, data, { appName: 'plugin' });\r\n api.on = (event, cb) => this._core.eventBus.on(event, cb);\r\n api.off = (event, cb) => this._core.eventBus.off(event, cb);\r\n }\r\n\r\n if (permissions.includes('store') || permissions.includes('unsafe')) {\r\n api.getState = (path) => this._core.store.get(path);\r\n api.setState = (path, value) => this._core.store.set(path, value);\r\n }\r\n\r\n if (permissions.includes('mount') || permissions.includes('unsafe')) {\r\n api.mount = (appName, container) => this._core.mount(appName, container);\r\n api.unmount = (appName) => this._core.unmount(appName);\r\n }\r\n\r\n if (permissions.includes('config') || permissions.includes('unsafe')) {\r\n api.configure = (config) => {\r\n // Solo permitir configuración segura\r\n const safeKeys = ['debug', 'logLevel'];\r\n const safeConfig = {};\r\n for (const key of safeKeys) {\r\n if (key in config) safeConfig[key] = config[key];\r\n }\r\n Object.assign(this._core, safeConfig);\r\n };\r\n }\r\n\r\n // 🚨 Acceso completo solo con permiso 'unsafe'\r\n if (permissions.includes('unsafe')) {\r\n api._unsafeCore = this._core;\r\n logger.warn('[WuPlugin] ⚠️ Plugin has unsafe access to core!');\r\n }\r\n\r\n // Congelar API recursivamente para evitar modificaciones en cualquier nivel\r\n return WuPluginSystem._deepFreeze(api);\r\n }\r\n\r\n /**\r\n * Deep-freeze an object and all its nested plain objects and arrays.\r\n * Functions, DOM nodes, and other non-plain types are left untouched\r\n * so they remain callable / functional. A WeakSet guards against\r\n * circular references.\r\n *\r\n * @param {*} obj - The value to deep-freeze\r\n * @param {WeakSet} [seen] - Internal tracker for circular references\r\n * @returns {*} The same object, now deeply frozen\r\n */\r\n static _deepFreeze(obj, seen) {\r\n if (obj === null || obj === undefined) {\r\n return obj;\r\n }\r\n\r\n // Only freeze plain objects and arrays.\r\n // Functions must stay invocable; DOM nodes, class instances, etc.\r\n // should not be tampered with.\r\n const dominated = typeof obj === 'object';\r\n if (!dominated) {\r\n return obj;\r\n }\r\n\r\n const isPlainObject =\r\n Object.getPrototypeOf(obj) === Object.prototype ||\r\n Object.getPrototypeOf(obj) === null;\r\n const isArray = Array.isArray(obj);\r\n\r\n if (!isPlainObject && !isArray) {\r\n return obj;\r\n }\r\n\r\n // Circular-reference guard\r\n if (!seen) {\r\n seen = new WeakSet();\r\n }\r\n if (seen.has(obj)) {\r\n return obj;\r\n }\r\n seen.add(obj);\r\n\r\n // Recurse into own enumerable properties\r\n const keys = Object.keys(obj);\r\n for (let i = 0; i < keys.length; i++) {\r\n const value = obj[keys[i]];\r\n if (value !== null && value !== undefined && typeof value === 'object') {\r\n WuPluginSystem._deepFreeze(value, seen);\r\n }\r\n }\r\n\r\n return Object.freeze(obj);\r\n }\r\n\r\n /**\r\n * 🔐 VALIDATE PLUGIN: Validar estructura del plugin\r\n * @param {Object} plugin\r\n * @returns {boolean}\r\n */\r\n _validatePlugin(plugin) {\r\n if (!plugin || typeof plugin !== 'object') {\r\n throw new Error('[WuPlugin] Invalid plugin: must be an object');\r\n }\r\n\r\n if (!plugin.name || typeof plugin.name !== 'string') {\r\n throw new Error('[WuPlugin] Invalid plugin: must have a name (string)');\r\n }\r\n\r\n if (plugin.name.length > 50) {\r\n throw new Error('[WuPlugin] Invalid plugin: name too long (max 50 chars)');\r\n }\r\n\r\n // Validar que los hooks sean funciones\r\n for (const hookName of this.availableHooks) {\r\n if (plugin[hookName] && typeof plugin[hookName] !== 'function') {\r\n throw new Error(`[WuPlugin] Invalid plugin: ${hookName} must be a function`);\r\n }\r\n }\r\n\r\n // Validar permisos\r\n if (plugin.permissions) {\r\n if (!Array.isArray(plugin.permissions)) {\r\n throw new Error('[WuPlugin] Invalid plugin: permissions must be an array');\r\n }\r\n\r\n for (const perm of plugin.permissions) {\r\n if (!this.availablePermissions.includes(perm)) {\r\n throw new Error(`[WuPlugin] Invalid permission: ${perm}`);\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * 📦 USE: Instalar plugin con sandboxing\r\n * @param {Object|Function} plugin - Plugin o factory function\r\n * @param {Object} options - Opciones del plugin\r\n */\r\n use(plugin, options = {}) {\r\n // Si es una función, ejecutarla para obtener el plugin\r\n // Nota: factory functions NO reciben acceso al core\r\n if (typeof plugin === 'function') {\r\n plugin = plugin(options);\r\n }\r\n\r\n // Validar plugin\r\n this._validatePlugin(plugin);\r\n\r\n // Verificar si ya está instalado\r\n if (this.plugins.has(plugin.name)) {\r\n logger.warn(`[WuPlugin] Plugin \"${plugin.name}\" already installed`);\r\n return;\r\n }\r\n\r\n // Determinar permisos (por defecto: solo eventos)\r\n const permissions = plugin.permissions || ['events'];\r\n\r\n // 🔐 Crear API sandboxeada\r\n const sandboxedApi = this._createSandboxedApi(permissions);\r\n\r\n // Ejecutar install del plugin con API sandboxeada\r\n if (plugin.install) {\r\n try {\r\n plugin.install(sandboxedApi, options);\r\n } catch (error) {\r\n console.error(`[WuPlugin] Error installing \"${plugin.name}\":`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n // Registrar hooks del plugin con protección\r\n this.availableHooks.forEach(hookName => {\r\n if (typeof plugin[hookName] === 'function') {\r\n // Wrap el hook con timeout y try-catch\r\n const wrappedHook = this._wrapHook(plugin[hookName].bind(plugin), plugin.name, hookName);\r\n this.registerHook(hookName, wrappedHook);\r\n }\r\n });\r\n\r\n // Guardar plugin\r\n this.plugins.set(plugin.name, {\r\n plugin,\r\n options,\r\n permissions,\r\n sandboxedApi,\r\n installedAt: Date.now()\r\n });\r\n\r\n logger.debug(`[WuPlugin] ✅ Plugin \"${plugin.name}\" installed (permissions: ${permissions.join(', ')})`);\r\n }\r\n\r\n /**\r\n * 🔐 WRAP HOOK: Envolver hook con timeout y error handling\r\n */\r\n _wrapHook(hookFn, pluginName, hookName) {\r\n return async (context) => {\r\n const timeoutPromise = new Promise((_, reject) => {\r\n setTimeout(() => {\r\n reject(new Error(`Plugin \"${pluginName}\" hook \"${hookName}\" timed out after ${this.hookTimeout}ms`));\r\n }, this.hookTimeout);\r\n });\r\n\r\n try {\r\n // Race entre el hook y el timeout\r\n return await Promise.race([\r\n hookFn(context),\r\n timeoutPromise\r\n ]);\r\n } catch (error) {\r\n console.error(`[WuPlugin] Error in ${pluginName}.${hookName}:`, error);\r\n // No propagar error para no romper otros plugins\r\n return undefined;\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * 🪝 REGISTER HOOK\r\n */\r\n registerHook(hookName, callback) {\r\n if (!this.hooks.has(hookName)) {\r\n logger.warn(`[WuPlugin] Unknown hook: ${hookName}`);\r\n return;\r\n }\r\n this.hooks.get(hookName).push(callback);\r\n }\r\n\r\n /**\r\n * 🎯 CALL HOOK\r\n */\r\n async callHook(hookName, context) {\r\n const callbacks = this.hooks.get(hookName) || [];\r\n\r\n for (const callback of callbacks) {\r\n try {\r\n const result = await callback(context);\r\n if (result === false) {\r\n return false;\r\n }\r\n } catch (error) {\r\n console.error(`[WuPlugin] Error in hook ${hookName}:`, error);\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * 🗑️ UNINSTALL\r\n */\r\n uninstall(pluginName) {\r\n const pluginData = this.plugins.get(pluginName);\r\n if (!pluginData) {\r\n logger.warn(`[WuPlugin] Plugin \"${pluginName}\" not found`);\r\n return;\r\n }\r\n\r\n const { plugin, sandboxedApi } = pluginData;\r\n\r\n if (plugin.uninstall) {\r\n try {\r\n plugin.uninstall(sandboxedApi);\r\n } catch (error) {\r\n console.error(`[WuPlugin] Error uninstalling \"${pluginName}\":`, error);\r\n }\r\n }\r\n\r\n this.plugins.delete(pluginName);\r\n logger.debug(`[WuPlugin] ✅ Plugin \"${pluginName}\" uninstalled`);\r\n }\r\n\r\n /**\r\n * 📋 GET PLUGIN\r\n */\r\n getPlugin(pluginName) {\r\n return this.plugins.get(pluginName)?.plugin;\r\n }\r\n\r\n /**\r\n * 📊 GET STATS\r\n */\r\n getStats() {\r\n return {\r\n totalPlugins: this.plugins.size,\r\n plugins: Array.from(this.plugins.entries()).map(([name, data]) => ({\r\n name,\r\n permissions: data.permissions,\r\n installedAt: data.installedAt\r\n })),\r\n hooks: Array.from(this.hooks.entries()).map(([name, callbacks]) => ({\r\n name,\r\n callbacks: callbacks.length\r\n }))\r\n };\r\n }\r\n\r\n /**\r\n * 🧹 CLEANUP\r\n */\r\n cleanup() {\r\n for (const [name] of this.plugins) {\r\n this.uninstall(name);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 📦 PLUGIN HELPER: Helper para crear plugins\r\n * @param {Object} config - Configuración del plugin\r\n * @param {string} config.name - Nombre del plugin\r\n * @param {Array} config.permissions - Permisos requeridos\r\n */\r\nexport const createPlugin = (config) => {\r\n return {\r\n name: config.name,\r\n permissions: config.permissions || ['events'],\r\n install: config.install,\r\n uninstall: config.uninstall,\r\n beforeInit: config.beforeInit,\r\n afterInit: config.afterInit,\r\n beforeMount: config.beforeMount,\r\n afterMount: config.afterMount,\r\n beforeUnmount: config.beforeUnmount,\r\n afterUnmount: config.afterUnmount,\r\n onError: config.onError,\r\n onDestroy: config.onDestroy\r\n };\r\n};\r\n","/**\r\n * 🎯 WU-STRATEGIES: LOADING STRATEGIES\r\n *\r\n * Estrategias de carga para optimizar performance:\r\n * - Lazy: Carga solo cuando se monta\r\n * - Eager: Precarga en init\r\n * - Preload: Usa <link rel=\"prefetch\">\r\n * - Idle: Carga cuando el navegador está idle\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuLoadingStrategy {\r\n constructor(core) {\r\n this.core = core;\r\n this.strategies = new Map();\r\n this.loadingQueue = [];\r\n this.isIdle = false;\r\n\r\n this.registerDefaultStrategies();\r\n this.setupIdleCallback();\r\n\r\n logger.debug('[WuStrategies] 🎯 Loading strategies initialized');\r\n }\r\n\r\n /**\r\n * 📋 REGISTER DEFAULT STRATEGIES\r\n */\r\n registerDefaultStrategies() {\r\n // Lazy: Solo carga cuando se necesita (no precarga)\r\n this.register('lazy', {\r\n shouldPreload: false,\r\n load: async (appName, config) => {\r\n logger.debug(`[Strategy:Lazy] Loading ${appName} on demand (no preload)`);\r\n // No hace nada, la app se carga cuando se monta\r\n return;\r\n }\r\n });\r\n\r\n // Eager: Carga inmediatamente en init\r\n this.register('eager', {\r\n shouldPreload: true,\r\n priority: 'high',\r\n load: async (appName, config) => {\r\n logger.debug(`[Strategy:Eager] Preloading ${appName} immediately`);\r\n\r\n // Cargar el módulo de la app\r\n const app = this.core.apps.get(appName);\r\n if (app) {\r\n const moduleUrl = await this.core.resolveModulePath(app);\r\n await import(/* @vite-ignore */ moduleUrl);\r\n logger.debug(`[Strategy:Eager] ✅ ${appName} preloaded`);\r\n }\r\n }\r\n });\r\n\r\n // Preload: Usa resource hints del navegador\r\n this.register('preload', {\r\n shouldPreload: true,\r\n priority: 'medium',\r\n load: async (appName, config) => {\r\n logger.debug(`[Strategy:Preload] Using resource hints for ${appName}`);\r\n\r\n // Crear <link rel=\"prefetch\">\r\n const app = this.core.apps.get(appName);\r\n if (app) {\r\n const moduleUrl = await this.core.resolveModulePath(app);\r\n\r\n const link = document.createElement('link');\r\n link.rel = 'prefetch';\r\n link.href = moduleUrl;\r\n link.as = 'script';\r\n document.head.appendChild(link);\r\n\r\n logger.debug(`[Strategy:Preload] ✅ Resource hint added for ${appName}`);\r\n }\r\n }\r\n });\r\n\r\n // Speculate: Uses Speculation Rules API (Chrome 121+) with fallbacks\r\n this.register('speculate', {\r\n shouldPreload: true,\r\n priority: 'medium',\r\n load: async (appName, config) => {\r\n if (this.core.prefetcher) {\r\n await this.core.prefetcher.prefetch(appName, {\r\n eagerness: config.eagerness || 'moderate'\r\n });\r\n }\r\n }\r\n });\r\n\r\n // Idle: Carga cuando el navegador está idle\r\n this.register('idle', {\r\n shouldPreload: false,\r\n load: async (appName, config) => {\r\n logger.debug(`[Strategy:Idle] Queueing ${appName} for idle loading`);\r\n\r\n return new Promise((resolve) => {\r\n this.loadingQueue.push({\r\n appName,\r\n config,\r\n resolve\r\n });\r\n\r\n // Si ya estamos idle, procesar inmediatamente\r\n if (this.isIdle) {\r\n this.processIdleQueue();\r\n }\r\n });\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 📦 REGISTER: Registrar estrategia personalizada\r\n * @param {string} name - Nombre de la estrategia\r\n * @param {Object} strategy - Configuración de la estrategia\r\n */\r\n register(name, strategy) {\r\n if (!strategy.load || typeof strategy.load !== 'function') {\r\n throw new Error('[WuStrategies] Strategy must have a load function');\r\n }\r\n\r\n this.strategies.set(name, {\r\n name,\r\n shouldPreload: strategy.shouldPreload || false,\r\n priority: strategy.priority || 'low',\r\n load: strategy.load\r\n });\r\n\r\n logger.debug(`[WuStrategies] Strategy \"${name}\" registered`);\r\n }\r\n\r\n /**\r\n * 🚀 LOAD: Cargar app con estrategia\r\n * @param {string} appName - Nombre de la app\r\n * @param {Object} config - Configuración con strategy\r\n * @returns {Promise}\r\n */\r\n async load(appName, config) {\r\n const strategyName = config.strategy || 'lazy';\r\n const strategy = this.strategies.get(strategyName);\r\n\r\n if (!strategy) {\r\n logger.warn(`[WuStrategies] Strategy \"${strategyName}\" not found, using lazy`);\r\n return await this.strategies.get('lazy').load(appName, config);\r\n }\r\n\r\n return await strategy.load(appName, config);\r\n }\r\n\r\n /**\r\n * 🎯 PRELOAD: Precargar apps según estrategia\r\n * @param {Array} apps - Apps a evaluar para precarga\r\n */\r\n async preload(apps) {\r\n const toPreload = apps.filter(app => {\r\n const strategy = this.strategies.get(app.strategy || 'lazy');\r\n return strategy.shouldPreload;\r\n });\r\n\r\n // Ordenar por prioridad\r\n toPreload.sort((a, b) => {\r\n const priorityOrder = { high: 0, medium: 1, low: 2 };\r\n const aPriority = this.strategies.get(a.strategy)?.priority || 'low';\r\n const bPriority = this.strategies.get(b.strategy)?.priority || 'low';\r\n return priorityOrder[aPriority] - priorityOrder[bPriority];\r\n });\r\n\r\n logger.debug(`[WuStrategies] Preloading ${toPreload.length} apps`);\r\n\r\n // Precargar en orden\r\n for (const app of toPreload) {\r\n try {\r\n await this.load(app.name, app);\r\n } catch (error) {\r\n console.error(`[WuStrategies] Failed to preload ${app.name}:`, error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * ⏰ SETUP IDLE CALLBACK: Configurar idle loading\r\n */\r\n setupIdleCallback() {\r\n if ('requestIdleCallback' in window) {\r\n const idleCallback = (deadline) => {\r\n this.isIdle = true;\r\n this.processIdleQueue(deadline);\r\n\r\n // Re-schedule\r\n requestIdleCallback(idleCallback);\r\n };\r\n\r\n requestIdleCallback(idleCallback);\r\n } else {\r\n // Fallback: usar setTimeout\r\n setTimeout(() => {\r\n this.isIdle = true;\r\n this.processIdleQueue();\r\n }, 2000);\r\n }\r\n }\r\n\r\n /**\r\n * 📋 PROCESS IDLE QUEUE: Procesar cola de carga idle\r\n * @param {Object} deadline - IdleDeadline object\r\n */\r\n async processIdleQueue(deadline) {\r\n while (this.loadingQueue.length > 0) {\r\n // Si tenemos deadline y se acabó el tiempo, salir\r\n if (deadline && deadline.timeRemaining() <= 0) {\r\n break;\r\n }\r\n\r\n const item = this.loadingQueue.shift();\r\n\r\n try {\r\n const app = this.core.apps.get(item.appName);\r\n if (app) {\r\n const moduleUrl = await this.core.resolveModulePath(app);\r\n await import(/* @vite-ignore */ moduleUrl);\r\n logger.debug(`[Strategy:Idle] ✅ ${item.appName} loaded during idle time`);\r\n item.resolve(true);\r\n } else {\r\n item.resolve(null);\r\n }\r\n } catch (error) {\r\n console.error(`[Strategy:Idle] Failed to load ${item.appName}:`, error);\r\n item.resolve(null);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 📊 GET STATS: Estadísticas de estrategias\r\n * @returns {Object}\r\n */\r\n getStats() {\r\n return {\r\n totalStrategies: this.strategies.size,\r\n strategies: Array.from(this.strategies.keys()),\r\n idleQueueSize: this.loadingQueue.length,\r\n isIdle: this.isIdle\r\n };\r\n }\r\n\r\n /**\r\n * 🧹 CLEANUP: Limpiar estrategias\r\n */\r\n cleanup() {\r\n this.loadingQueue = [];\r\n logger.debug('[WuStrategies] 🧹 Strategies cleaned up');\r\n }\r\n}\r\n","/**\r\n * 🛡️ WU-ERROR-BOUNDARY: ADVANCED ERROR HANDLING\r\n *\r\n * Sistema de error boundaries con:\r\n * - Chain of Responsibility pattern\r\n * - Recovery strategies\r\n * - Error classification\r\n * - Fallback rendering\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuErrorBoundary {\r\n constructor(core) {\r\n this.core = core;\r\n this.handlers = [];\r\n this.errorLog = [];\r\n this.maxErrorLog = 100;\r\n\r\n this.config = {\r\n maxRetries: 3,\r\n retryDelay: 1000,\r\n showErrorUI: true\r\n };\r\n\r\n this.registerDefaultHandlers();\r\n\r\n logger.debug('[WuErrorBoundary] 🛡️ Error boundary initialized');\r\n }\r\n\r\n /**\r\n * 📋 REGISTER DEFAULT HANDLERS: Chain of responsibility\r\n */\r\n registerDefaultHandlers() {\r\n // 1. Network Error Handler\r\n this.register({\r\n name: 'network',\r\n canHandle: (error) => {\r\n return error.name === 'TypeError' &&\r\n (error.message.includes('fetch') || error.message.includes('network'));\r\n },\r\n handle: async (error, context) => {\r\n logger.debug('[ErrorHandler:Network] Handling network error');\r\n\r\n // Retry con backoff\r\n if (context.retryCount < this.config.maxRetries) {\r\n const delay = this.config.retryDelay * Math.pow(2, context.retryCount);\r\n logger.debug(`[ErrorHandler:Network] Retrying in ${delay}ms...`);\r\n\r\n await new Promise(resolve => setTimeout(resolve, delay));\r\n\r\n return {\r\n recovered: true,\r\n action: 'retry',\r\n retryCount: context.retryCount + 1\r\n };\r\n }\r\n\r\n return {\r\n recovered: false,\r\n action: 'fallback',\r\n message: 'Network error: Please check your connection'\r\n };\r\n }\r\n });\r\n\r\n // 2. Script Load Error Handler\r\n this.register({\r\n name: 'script-load',\r\n canHandle: (error) => {\r\n return error.name === 'Error' &&\r\n (error.message.includes('Loading') ||\r\n error.message.includes('Failed to fetch'));\r\n },\r\n handle: async (error, context) => {\r\n logger.debug('[ErrorHandler:ScriptLoad] Handling script load error');\r\n\r\n // Intentar URL alternativa si existe\r\n if (context.fallbackUrl) {\r\n logger.debug('[ErrorHandler:ScriptLoad] Trying fallback URL');\r\n return {\r\n recovered: true,\r\n action: 'use-fallback-url',\r\n url: context.fallbackUrl\r\n };\r\n }\r\n\r\n return {\r\n recovered: false,\r\n action: 'fallback',\r\n message: 'Failed to load microfrontend'\r\n };\r\n }\r\n });\r\n\r\n // 3. Mount Error Handler\r\n this.register({\r\n name: 'mount',\r\n canHandle: (error) => {\r\n return error.message && error.message.includes('mount');\r\n },\r\n handle: async (error, context) => {\r\n logger.debug('[ErrorHandler:Mount] Handling mount error');\r\n\r\n // Limpiar y reintentar\r\n if (context.retryCount < 2) {\r\n logger.debug('[ErrorHandler:Mount] Cleaning up and retrying...');\r\n\r\n // Cleanup\r\n try {\r\n await this.core.unmount(context.appName);\r\n } catch (cleanupError) {\r\n logger.warn('[ErrorHandler:Mount] Cleanup failed:', cleanupError);\r\n }\r\n\r\n await new Promise(resolve => setTimeout(resolve, 500));\r\n\r\n return {\r\n recovered: true,\r\n action: 'retry',\r\n retryCount: context.retryCount + 1\r\n };\r\n }\r\n\r\n return {\r\n recovered: false,\r\n action: 'fallback',\r\n message: 'Failed to mount application'\r\n };\r\n }\r\n });\r\n\r\n // 4. Timeout Error Handler\r\n this.register({\r\n name: 'timeout',\r\n canHandle: (error) => {\r\n return error.name === 'TimeoutError' ||\r\n error.message.includes('timeout');\r\n },\r\n handle: async (error, context) => {\r\n logger.debug('[ErrorHandler:Timeout] Handling timeout error');\r\n\r\n // Aumentar timeout y reintentar\r\n if (context.retryCount < 2) {\r\n return {\r\n recovered: true,\r\n action: 'retry-with-longer-timeout',\r\n timeout: (context.timeout || 5000) * 2,\r\n retryCount: context.retryCount + 1\r\n };\r\n }\r\n\r\n return {\r\n recovered: false,\r\n action: 'fallback',\r\n message: 'Operation timed out'\r\n };\r\n }\r\n });\r\n\r\n // 5. Generic Error Handler (fallback)\r\n this.register({\r\n name: 'generic',\r\n canHandle: () => true, // Maneja todo\r\n handle: async (error, context) => {\r\n logger.debug('[ErrorHandler:Generic] Handling generic error');\r\n\r\n return {\r\n recovered: false,\r\n action: 'fallback',\r\n message: error.message || 'An unexpected error occurred'\r\n };\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 📦 REGISTER: Registrar error handler\r\n * @param {Object} handler - Error handler { name, canHandle, handle }\r\n */\r\n register(handler) {\r\n if (!handler.name || !handler.canHandle || !handler.handle) {\r\n throw new Error('[WuErrorBoundary] Handler must have name, canHandle, and handle');\r\n }\r\n\r\n this.handlers.push(handler);\r\n logger.debug(`[WuErrorBoundary] Handler \"${handler.name}\" registered`);\r\n }\r\n\r\n /**\r\n * 🎯 HANDLE: Manejar error con chain of responsibility\r\n * @param {Error} error - Error a manejar\r\n * @param {Object} context - Contexto del error\r\n * @returns {Promise<Object>} Recovery result\r\n */\r\n async handle(error, context = {}) {\r\n // Agregar valores por defecto\r\n context = {\r\n retryCount: 0,\r\n timestamp: Date.now(),\r\n ...context\r\n };\r\n\r\n // Log error\r\n this.logError(error, context);\r\n\r\n // Buscar handler que pueda manejar este error\r\n for (const handler of this.handlers) {\r\n try {\r\n if (handler.canHandle(error, context)) {\r\n logger.debug(`[WuErrorBoundary] Using handler: ${handler.name}`);\r\n\r\n const result = await handler.handle(error, context);\r\n\r\n if (result.recovered) {\r\n logger.debug(`[WuErrorBoundary] ✅ Error recovered by ${handler.name}`);\r\n return result;\r\n }\r\n\r\n // Si no se recuperó, renderizar fallback\r\n if (result.action === 'fallback' && this.config.showErrorUI) {\r\n this.renderFallback(context, result);\r\n }\r\n\r\n return result;\r\n }\r\n } catch (handlerError) {\r\n console.error(`[WuErrorBoundary] Handler \"${handler.name}\" failed:`, handlerError);\r\n }\r\n }\r\n\r\n // No handler pudo manejar el error\r\n console.error('[WuErrorBoundary] ❌ No handler could handle the error');\r\n\r\n return {\r\n recovered: false,\r\n action: 'unhandled',\r\n message: 'Unhandled error'\r\n };\r\n }\r\n\r\n /**\r\n * 🎨 RENDER FALLBACK: Renderizar UI de error\r\n * @param {Object} context - Contexto del error\r\n * @param {Object} result - Resultado del handler\r\n */\r\n renderFallback(context, result) {\r\n if (!context.container) {\r\n logger.warn('[WuErrorBoundary] No container to render fallback');\r\n return;\r\n }\r\n\r\n const container = typeof context.container === 'string'\r\n ? document.querySelector(context.container)\r\n : context.container;\r\n\r\n if (!container) return;\r\n\r\n // Limpiar container\r\n container.innerHTML = '';\r\n\r\n // Crear UI de error\r\n const errorUI = document.createElement('div');\r\n errorUI.className = 'wu-error-boundary';\r\n\r\n Object.assign(errorUI.style, {\r\n padding: '2rem',\r\n borderRadius: '8px',\r\n background: '#fff3cd',\r\n border: '1px solid #ffc107',\r\n color: '#856404',\r\n fontFamily: 'system-ui, -apple-system, sans-serif',\r\n textAlign: 'center'\r\n });\r\n\r\n const icon = document.createElement('div');\r\n icon.textContent = '⚠️';\r\n icon.style.fontSize = '3rem';\r\n icon.style.marginBottom = '1rem';\r\n\r\n const title = document.createElement('h3');\r\n title.textContent = 'Application Error';\r\n title.style.margin = '0 0 0.5rem 0';\r\n\r\n const message = document.createElement('p');\r\n message.textContent = result.message || 'An error occurred';\r\n message.style.margin = '0 0 1rem 0';\r\n\r\n const button = document.createElement('button');\r\n button.textContent = '🔄 Reload';\r\n Object.assign(button.style, {\r\n padding: '0.5rem 1rem',\r\n background: '#ffc107',\r\n border: 'none',\r\n borderRadius: '4px',\r\n cursor: 'pointer',\r\n fontWeight: 'bold',\r\n color: '#000'\r\n });\r\n\r\n button.addEventListener('click', () => window.location.reload());\r\n\r\n errorUI.appendChild(icon);\r\n errorUI.appendChild(title);\r\n errorUI.appendChild(message);\r\n errorUI.appendChild(button);\r\n\r\n container.appendChild(errorUI);\r\n }\r\n\r\n /**\r\n * 📝 LOG ERROR: Registrar error\r\n * @param {Error} error - Error\r\n * @param {Object} context - Contexto\r\n */\r\n logError(error, context) {\r\n // Truncate stack to first 5 lines to prevent retaining large object references\r\n const stack = error.stack ? error.stack.split('\\n').slice(0, 5).join('\\n') : '';\r\n\r\n // Shallow-copy context to avoid retaining references to live objects\r\n const safeContext = {};\r\n for (const key of Object.keys(context)) {\r\n const val = context[key];\r\n if (typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean' || val === null) {\r\n safeContext[key] = val;\r\n } else {\r\n safeContext[key] = String(val);\r\n }\r\n }\r\n\r\n const errorEntry = {\r\n error: {\r\n name: error.name,\r\n message: error.message,\r\n stack\r\n },\r\n context: safeContext,\r\n timestamp: Date.now()\r\n };\r\n\r\n this.errorLog.push(errorEntry);\r\n\r\n // Maintain log limit\r\n if (this.errorLog.length > this.maxErrorLog) {\r\n this.errorLog.shift();\r\n }\r\n }\r\n\r\n /**\r\n * 📋 GET ERROR LOG: Obtener log de errores\r\n * @param {number} limit - Límite de errores a retornar\r\n * @returns {Array}\r\n */\r\n getErrorLog(limit = 10) {\r\n return this.errorLog.slice(-limit);\r\n }\r\n\r\n /**\r\n * 📊 GET STATS: Estadísticas de errores\r\n * @returns {Object}\r\n */\r\n getStats() {\r\n const errorsByType = {};\r\n\r\n this.errorLog.forEach(entry => {\r\n const type = entry.error.name || 'Unknown';\r\n errorsByType[type] = (errorsByType[type] || 0) + 1;\r\n });\r\n\r\n return {\r\n totalErrors: this.errorLog.length,\r\n handlers: this.handlers.length,\r\n errorsByType,\r\n recentErrors: this.getErrorLog(5)\r\n };\r\n }\r\n\r\n /**\r\n * ⚙️ CONFIGURE: Configurar error boundary\r\n * @param {Object} config - Nueva configuración\r\n */\r\n configure(config) {\r\n this.config = {\r\n ...this.config,\r\n ...config\r\n };\r\n }\r\n\r\n /**\r\n * 🧹 CLEANUP: Limpiar error boundary\r\n */\r\n cleanup() {\r\n this.errorLog = [];\r\n logger.debug('[WuErrorBoundary] 🧹 Error boundary cleaned up');\r\n }\r\n}\r\n","/**\r\n * 🪝 WU-HOOKS: LIFECYCLE MIDDLEWARE SYSTEM\r\n *\r\n * Sistema de hooks basado en middleware pattern para control fino:\r\n * - Middleware chain con next()\r\n * - Puede cancelar operaciones (no llamar next)\r\n * - Puede modificar contexto\r\n * - Prioridad de hooks\r\n * - Async/await support\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuLifecycleHooks {\r\n constructor(core) {\r\n this.core = core;\r\n this.hooks = new Map();\r\n this.executionLog = [];\r\n this.maxLogSize = 100;\r\n\r\n // Lifecycle phases disponibles\r\n this.lifecyclePhases = [\r\n 'beforeInit', // Antes de inicializar framework\r\n 'afterInit', // Después de inicializar\r\n 'beforeLoad', // Antes de cargar una app\r\n 'afterLoad', // Después de cargar\r\n 'beforeMount', // Antes de montar\r\n 'afterMount', // Después de montar\r\n 'beforeUnmount', // Antes de desmontar\r\n 'afterUnmount', // Después de desmontar\r\n 'beforeDestroy', // Antes de destruir framework\r\n 'afterDestroy' // Después de destruir\r\n ];\r\n\r\n // Inicializar hooks\r\n this.lifecyclePhases.forEach(phase => {\r\n this.hooks.set(phase, []);\r\n });\r\n\r\n logger.debug('[WuHooks] 🪝 Lifecycle hooks initialized');\r\n }\r\n\r\n /**\r\n * 📦 USE: Registrar middleware hook\r\n * @param {string} phase - Fase del lifecycle\r\n * @param {Function} middleware - Función middleware (context, next)\r\n * @param {Object} options - { priority, name }\r\n */\r\n use(phase, middleware, options = {}) {\r\n if (!this.hooks.has(phase)) {\r\n throw new Error(`[WuHooks] Unknown lifecycle phase: ${phase}`);\r\n }\r\n\r\n if (typeof middleware !== 'function') {\r\n throw new Error('[WuHooks] Middleware must be a function');\r\n }\r\n\r\n const hook = {\r\n middleware,\r\n name: options.name || `hook_${Date.now()}`,\r\n priority: options.priority || 0,\r\n registeredAt: Date.now()\r\n };\r\n\r\n const hooks = this.hooks.get(phase);\r\n hooks.push(hook);\r\n\r\n // Ordenar por prioridad (mayor primero)\r\n hooks.sort((a, b) => b.priority - a.priority);\r\n\r\n logger.debug(`[WuHooks] Hook \"${hook.name}\" registered for ${phase} (priority: ${hook.priority})`);\r\n\r\n // Retornar función para desregistrar\r\n return () => this.remove(phase, hook.name);\r\n }\r\n\r\n /**\r\n * 🗑️ REMOVE: Remover hook\r\n * @param {string} phase - Fase del lifecycle\r\n * @param {string} name - Nombre del hook\r\n */\r\n remove(phase, name) {\r\n if (!this.hooks.has(phase)) return;\r\n\r\n const hooks = this.hooks.get(phase);\r\n const index = hooks.findIndex(h => h.name === name);\r\n\r\n if (index > -1) {\r\n hooks.splice(index, 1);\r\n logger.debug(`[WuHooks] Hook \"${name}\" removed from ${phase}`);\r\n }\r\n }\r\n\r\n /**\r\n * 🎯 EXECUTE: Ejecutar middleware chain\r\n * @param {string} phase - Fase del lifecycle\r\n * @param {Object} context - Contexto a pasar\r\n * @returns {Promise<Object>} Contexto modificado o { cancelled: true }\r\n */\r\n async execute(phase, context = {}) {\r\n const hooks = this.hooks.get(phase);\r\n\r\n if (!hooks || hooks.length === 0) {\r\n return context;\r\n }\r\n\r\n logger.debug(`[WuHooks] Executing ${hooks.length} hooks for ${phase}`);\r\n\r\n // Log para debugging\r\n const executionEntry = {\r\n phase,\r\n timestamp: Date.now(),\r\n hooksCount: hooks.length,\r\n hookNames: hooks.map(h => h.name)\r\n };\r\n\r\n let currentContext = { ...context };\r\n let cancelled = false;\r\n\r\n // Crear cadena de middleware\r\n const executeChain = async (index) => {\r\n // Si llegamos al final de la cadena, retornar contexto\r\n if (index >= hooks.length) {\r\n return currentContext;\r\n }\r\n\r\n const hook = hooks[index];\r\n const startTime = Date.now();\r\n\r\n try {\r\n let nextCalled = false;\r\n\r\n // Función next\r\n const next = async (modifiedContext) => {\r\n nextCalled = true;\r\n\r\n // Si se pasa un contexto modificado, usarlo\r\n if (modifiedContext !== undefined) {\r\n currentContext = { ...currentContext, ...modifiedContext };\r\n }\r\n\r\n // Continuar con siguiente hook\r\n return await executeChain(index + 1);\r\n };\r\n\r\n // Ejecutar middleware\r\n await hook.middleware(currentContext, next);\r\n\r\n // Si no se llamó next(), la operación fue cancelada\r\n if (!nextCalled) {\r\n logger.debug(`[WuHooks] Hook \"${hook.name}\" cancelled execution`);\r\n cancelled = true;\r\n return { cancelled: true };\r\n }\r\n\r\n const duration = Date.now() - startTime;\r\n logger.debug(`[WuHooks] Hook \"${hook.name}\" executed in ${duration}ms`);\r\n\r\n } catch (error) {\r\n console.error(`[WuHooks] Error in hook \"${hook.name}\":`, error);\r\n\r\n // Si hay error, pasar al siguiente hook\r\n return await executeChain(index + 1);\r\n }\r\n\r\n return currentContext;\r\n };\r\n\r\n // Ejecutar cadena\r\n const result = await executeChain(0);\r\n\r\n // Completar log\r\n executionEntry.duration = Date.now() - executionEntry.timestamp;\r\n executionEntry.cancelled = cancelled;\r\n executionEntry.success = !cancelled;\r\n\r\n this.executionLog.push(executionEntry);\r\n\r\n // Mantener límite de log\r\n if (this.executionLog.length > this.maxLogSize) {\r\n this.executionLog.shift();\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 🚀 HELPER: Registrar hook para múltiples fases\r\n * @param {Array<string>} phases - Fases del lifecycle\r\n * @param {Function} middleware - Función middleware\r\n * @param {Object} options - Opciones\r\n * @returns {Function} Función para desregistrar de todas las fases\r\n */\r\n useMultiple(phases, middleware, options = {}) {\r\n const unregisterFns = phases.map(phase =>\r\n this.use(phase, middleware, { ...options, name: `${options.name}_${phase}` })\r\n );\r\n\r\n // Retornar función que desregistra de todas las fases\r\n return () => unregisterFns.forEach(fn => fn());\r\n }\r\n\r\n /**\r\n * 📋 GET HOOKS: Obtener hooks registrados\r\n * @param {string} phase - Fase del lifecycle (opcional)\r\n * @returns {Object|Array}\r\n */\r\n getHooks(phase) {\r\n if (phase) {\r\n return this.hooks.get(phase) || [];\r\n }\r\n\r\n // Retornar todos los hooks\r\n const allHooks = {};\r\n this.hooks.forEach((hooks, phase) => {\r\n allHooks[phase] = hooks.map(h => ({\r\n name: h.name,\r\n priority: h.priority,\r\n registeredAt: h.registeredAt\r\n }));\r\n });\r\n\r\n return allHooks;\r\n }\r\n\r\n /**\r\n * 📊 GET STATS: Estadísticas de hooks\r\n * @returns {Object}\r\n */\r\n getStats() {\r\n const totalHooks = Array.from(this.hooks.values())\r\n .reduce((sum, hooks) => sum + hooks.length, 0);\r\n\r\n const executionsByPhase = {};\r\n this.executionLog.forEach(entry => {\r\n executionsByPhase[entry.phase] = (executionsByPhase[entry.phase] || 0) + 1;\r\n });\r\n\r\n const avgDuration = this.executionLog.length > 0\r\n ? this.executionLog.reduce((sum, entry) => sum + entry.duration, 0) / this.executionLog.length\r\n : 0;\r\n\r\n const cancelledCount = this.executionLog.filter(entry => entry.cancelled).length;\r\n\r\n return {\r\n totalHooks,\r\n totalExecutions: this.executionLog.length,\r\n executionsByPhase,\r\n avgDuration: Math.round(avgDuration),\r\n cancelledCount,\r\n recentExecutions: this.executionLog.slice(-10)\r\n };\r\n }\r\n\r\n /**\r\n * 🧹 CLEANUP: Limpiar todos los hooks\r\n * @param {string} phase - Fase específica (opcional)\r\n */\r\n cleanup(phase) {\r\n if (phase) {\r\n this.hooks.set(phase, []);\r\n logger.debug(`[WuHooks] Hooks cleaned for ${phase}`);\r\n } else {\r\n this.lifecyclePhases.forEach(p => {\r\n this.hooks.set(p, []);\r\n });\r\n this.executionLog = [];\r\n logger.debug('[WuHooks] 🧹 All hooks cleaned');\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 🔧 HELPER: Crear middleware hooks fácilmente\r\n */\r\n\r\n/**\r\n * Crear hook simple que siempre llama next\r\n * @param {Function} fn - Función a ejecutar\r\n * @returns {Function} Middleware function\r\n */\r\nexport const createSimpleHook = (fn) => {\r\n return async (context, next) => {\r\n await fn(context);\r\n await next();\r\n };\r\n};\r\n\r\n/**\r\n * Crear hook condicional\r\n * @param {Function} condition - Función de condición (context) => boolean\r\n * @param {Function} fn - Función a ejecutar si condición es true\r\n * @returns {Function} Middleware function\r\n */\r\nexport const createConditionalHook = (condition, fn) => {\r\n return async (context, next) => {\r\n if (await condition(context)) {\r\n await fn(context);\r\n }\r\n await next();\r\n };\r\n};\r\n\r\n/**\r\n * Crear hook que puede cancelar operación\r\n * @param {Function} shouldContinue - Función que retorna true para continuar\r\n * @returns {Function} Middleware function\r\n */\r\nexport const createGuardHook = (shouldContinue) => {\r\n return async (context, next) => {\r\n if (await shouldContinue(context)) {\r\n await next();\r\n }\r\n // Si no retorna true, no llama next() y cancela\r\n };\r\n};\r\n\r\n/**\r\n * Crear hook que modifica contexto\r\n * @param {Function} transformer - Función que transforma el contexto\r\n * @returns {Function} Middleware function\r\n */\r\nexport const createTransformHook = (transformer) => {\r\n return async (context, next) => {\r\n const modified = await transformer(context);\r\n await next(modified);\r\n };\r\n};\r\n\r\n/**\r\n * Crear hook con timeout\r\n * @param {Function} fn - Función a ejecutar\r\n * @param {number} timeout - Timeout en ms\r\n * @returns {Function} Middleware function\r\n */\r\nexport const createTimedHook = (fn, timeout = 5000) => {\r\n return async (context, next) => {\r\n const timeoutPromise = new Promise((_, reject) =>\r\n setTimeout(() => reject(new Error('Hook timeout')), timeout)\r\n );\r\n\r\n try {\r\n await Promise.race([fn(context), timeoutPromise]);\r\n await next();\r\n } catch (error) {\r\n console.error('[WuHooks] Timed hook failed:', error);\r\n await next(); // Continuar a pesar del error\r\n }\r\n };\r\n};\r\n","/**\r\n * WU-HTML-PARSER: Fetch and parse HTML entries from micro-apps.\r\n *\r\n * Used in \"strict\" sandbox mode. The flow:\r\n * 1. Fetch the HTML page at the app's URL\r\n * 2. Parse it: extract inline/external scripts, inline/external styles, and clean DOM\r\n * 3. Return structured result so wu-core can inject DOM + styles into Shadow DOM\r\n * and execute scripts inside the proxy sandbox via WuScriptExecutor.\r\n *\r\n * This is the qiankun-style \"HTML entry\" approach that enables real JS isolation.\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuHtmlParser {\r\n constructor() {\r\n this._cache = new Map();\r\n }\r\n\r\n /**\r\n * Fetch HTML content from a URL.\r\n * @param {string} url - App URL (e.g. http://localhost:3001)\r\n * @param {string} appName - For logging\r\n * @returns {Promise<string>} Raw HTML string\r\n */\r\n async fetchHtml(url, appName) {\r\n logger.wuDebug(`[HtmlParser] Fetching HTML for ${appName} from ${url}`);\r\n\r\n const response = await fetch(url, {\r\n method: 'GET',\r\n headers: { 'Accept': 'text/html,application/xhtml+xml,*/*' }\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`[HtmlParser] Failed to fetch ${url}: HTTP ${response.status}`);\r\n }\r\n\r\n const html = await response.text();\r\n if (!html || !html.trim()) {\r\n throw new Error(`[HtmlParser] Empty HTML response from ${url}`);\r\n }\r\n\r\n logger.wuDebug(`[HtmlParser] Fetched ${html.length} chars for ${appName}`);\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse HTML string into structured parts.\r\n *\r\n * @param {string} html - Raw HTML\r\n * @param {string} appName - App identifier\r\n * @param {string} baseUrl - Base URL for resolving relative paths\r\n * @returns {{\r\n * dom: string,\r\n * scripts: { inline: string[], external: string[] },\r\n * styles: { inline: string[], external: string[] }\r\n * }}\r\n */\r\n parse(html, appName, baseUrl) {\r\n const cacheKey = `${appName}:${html.length}`;\r\n if (this._cache.has(cacheKey)) {\r\n return this._cache.get(cacheKey);\r\n }\r\n\r\n const parser = new DOMParser();\r\n const doc = parser.parseFromString(html, 'text/html');\r\n\r\n const inlineScripts = [];\r\n const externalScripts = [];\r\n const inlineStyles = [];\r\n const externalStyles = [];\r\n\r\n const ctx = {\r\n inlineScripts, externalScripts,\r\n inlineStyles, externalStyles,\r\n baseUrl\r\n };\r\n\r\n // DOMParser moves <style>, <link>, and some <script> tags to <head>.\r\n // Extract resources from both head and body to capture everything.\r\n if (doc.head) {\r\n this._extractResources(doc.head, ctx);\r\n }\r\n\r\n const temp = doc.body || doc.documentElement;\r\n this._extractResources(temp, ctx);\r\n\r\n const result = {\r\n dom: temp.innerHTML,\r\n scripts: { inline: inlineScripts, external: externalScripts },\r\n styles: { inline: inlineStyles, external: externalStyles }\r\n };\r\n\r\n this._cache.set(cacheKey, result);\r\n\r\n logger.wuDebug(\r\n `[HtmlParser] ${appName}: ${inlineScripts.length} inline scripts, ` +\r\n `${externalScripts.length} external scripts, ` +\r\n `${inlineStyles.length + externalStyles.length} styles`\r\n );\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Convenience: fetch + parse in one call.\r\n */\r\n async fetchAndParse(url, appName) {\r\n const html = await this.fetchHtml(url, appName);\r\n return this.parse(html, appName, url);\r\n }\r\n\r\n /**\r\n * Recursively walk the DOM, extracting scripts and styles,\r\n * replacing them with comments to keep the DOM clean.\r\n */\r\n _extractResources(element, ctx) {\r\n // Iterate over a static copy since we mutate the DOM\r\n const children = Array.from(element.children);\r\n\r\n for (const child of children) {\r\n const tag = child.nodeName.toLowerCase();\r\n\r\n if (tag === 'script') {\r\n this._extractScript(child, ctx);\r\n child.replaceWith(document.createComment('wu:script'));\r\n continue;\r\n }\r\n\r\n if (tag === 'style') {\r\n const text = child.textContent?.trim();\r\n if (text) ctx.inlineStyles.push(text);\r\n child.replaceWith(document.createComment('wu:style'));\r\n continue;\r\n }\r\n\r\n if (tag === 'link') {\r\n const rel = child.getAttribute('rel');\r\n const href = child.getAttribute('href');\r\n if (rel === 'stylesheet' && href) {\r\n ctx.externalStyles.push(this._resolveUrl(href, ctx.baseUrl));\r\n child.replaceWith(document.createComment('wu:link'));\r\n continue;\r\n }\r\n }\r\n\r\n // Recurse into children\r\n if (child.children.length > 0) {\r\n this._extractResources(child, ctx);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Extract a <script> tag into inline or external list.\r\n * Skips type=\"module\" scripts (they can't be eval'd — use module mode for those).\r\n */\r\n _extractScript(el, ctx) {\r\n const type = el.getAttribute('type') || '';\r\n const src = el.getAttribute('src');\r\n\r\n // Module scripts can't be executed via new Function / eval.\r\n // If the app uses ES modules, it should use sandbox: 'module' mode.\r\n if (type === 'module') {\r\n logger.wuDebug('[HtmlParser] Skipping type=\"module\" script (use sandbox: \"module\" for ES modules)');\r\n return;\r\n }\r\n\r\n if (src) {\r\n ctx.externalScripts.push(this._resolveUrl(src, ctx.baseUrl));\r\n } else {\r\n const text = el.textContent?.trim();\r\n if (text) ctx.inlineScripts.push(text);\r\n }\r\n }\r\n\r\n /**\r\n * Resolve a relative URL against a base URL.\r\n */\r\n _resolveUrl(url, baseUrl) {\r\n if (url.startsWith('http://') || url.startsWith('https://')) return url;\r\n if (url.startsWith('//')) return `https:${url}`;\r\n\r\n try {\r\n return new URL(url, baseUrl).href;\r\n } catch {\r\n // Fallback for environments without URL constructor\r\n const base = baseUrl.replace(/\\/$/, '');\r\n return url.startsWith('/') ? base + url : `${base}/${url}`;\r\n }\r\n }\r\n\r\n /**\r\n * Clear the parse cache.\r\n */\r\n clearCache() {\r\n this._cache.clear();\r\n }\r\n}\r\n","/**\r\n * WU-SCRIPT-EXECUTOR: Execute scripts inside a Proxy sandbox.\r\n *\r\n * Two isolation levels:\r\n * - strictGlobal: true → with(proxy) { code } — all global access goes through proxy\r\n * - strictGlobal: false → (function(window){ code })(proxy) — only explicit window.xxx\r\n *\r\n * This is what makes the sandbox REAL instead of decorative.\r\n * Without this, import() runs code in global scope and the proxy is just a cleanup tracker.\r\n * With this, code receives the proxy as \"window\" and every setTimeout, addEventListener,\r\n * document.querySelector, localStorage access goes through the proxy's traps.\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuScriptExecutor {\r\n\r\n /**\r\n * Dangerous patterns that indicate prototype pollution, sandbox escape,\r\n * or direct access to sensitive APIs. Each entry is a regex paired with\r\n * a human-readable label used in error messages.\r\n *\r\n * This is a tripwire, not a full parser. It catches the most common\r\n * attack vectors without the overhead of AST analysis.\r\n */\r\n static DANGEROUS_PATTERNS = [\r\n // Prototype pollution vectors\r\n { pattern: /constructor\\s*\\[\\s*['\"`]constructor['\"`]\\s*\\]/, label: 'constructor chain access (sandbox escape)' },\r\n { pattern: /__proto__/, label: '__proto__ access (prototype pollution)' },\r\n\r\n // Sandbox escape via proxy introspection\r\n { pattern: /Object\\s*\\.\\s*getPrototypeOf\\s*\\(\\s*proxy\\s*\\)/, label: 'Object.getPrototypeOf(proxy) (sandbox escape)' },\r\n\r\n // Dynamic code generation that bypasses the sandbox\r\n { pattern: /Function\\s*\\(\\s*['\"`]/, label: 'Function() constructor (dynamic code generation)' },\r\n { pattern: /\\beval\\s*\\(/, label: 'eval() (dynamic code execution)' },\r\n\r\n // Dynamic import escapes the sandbox entirely (runs in global scope)\r\n { pattern: /\\bimport\\s*\\(/, label: 'import() (dynamic import escapes sandbox)' },\r\n\r\n // Direct cookie access (should go through proxy traps, not raw document)\r\n { pattern: /document\\s*\\.\\s*cookie/, label: 'document.cookie (direct cookie access)' },\r\n ];\r\n\r\n /**\r\n * Validate script text against known dangerous patterns before execution.\r\n * Throws if any pattern matches. This is intentionally lightweight --\r\n * pattern detection only, not a full parse.\r\n *\r\n * @param {string} scriptText - The raw script to validate\r\n * @param {string} appName - App identifier (for error context)\r\n * @throws {Error} If a dangerous pattern is detected\r\n */\r\n _validateScript(scriptText, appName) {\r\n for (const { pattern, label } of WuScriptExecutor.DANGEROUS_PATTERNS) {\r\n if (pattern.test(scriptText)) {\r\n const msg = `[ScriptExecutor] Blocked dangerous pattern in \"${appName}\": ${label}`;\r\n logger.wuError(msg);\r\n throw new Error(msg);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Execute a script string inside the proxy sandbox.\r\n *\r\n * @param {string} scriptText - JavaScript code to execute\r\n * @param {string} appName - App identifier (for logging)\r\n * @param {Proxy} proxy - The activated proxy sandbox\r\n * @param {Object} [options]\r\n * @param {boolean} [options.strictGlobal=true] - Use with(proxy) for maximum isolation\r\n * @param {string} [options.sourceUrl=''] - Source URL for devtools (//# sourceURL)\r\n * @returns {*} Return value of the executed code\r\n */\r\n execute(scriptText, appName, proxy, options = {}) {\r\n const { strictGlobal = true, sourceUrl = '' } = options;\r\n\r\n if (!scriptText || !scriptText.trim()) return;\r\n\r\n this._validateScript(scriptText, appName);\r\n\r\n const sourceComment = sourceUrl ? `\\n//# sourceURL=wu-sandbox:///${appName}/${sourceUrl}\\n` : '';\r\n\r\n let wrappedCode;\r\n\r\n if (strictGlobal) {\r\n // MAXIMUM ISOLATION\r\n // with(window) makes ALL unqualified identifiers (setTimeout, fetch, document, etc.)\r\n // resolve through the proxy's has/get traps, not the real window.\r\n // Note: 'use strict' inside the with block becomes a no-op string expression,\r\n // so bundled code with strict mode still works.\r\n wrappedCode = `;(function(window, self, globalThis, top, parent) {\r\n with(window) {\r\n ;${scriptText}${sourceComment}\r\n }\r\n}).call(proxy, proxy, proxy, proxy, proxy, proxy);`;\r\n } else {\r\n // IIFE ONLY — only explicit window.xxx goes through proxy\r\n wrappedCode = `;(function(window, self, globalThis, top, parent) {\r\n ;${scriptText}${sourceComment}\r\n}).call(proxy, proxy, proxy, proxy, proxy, proxy);`;\r\n }\r\n\r\n try {\r\n // new Function('proxy', code) creates a function with 'proxy' as the single param.\r\n // This avoids polluting scope — the only bridge to the sandbox is the proxy argument.\r\n const fn = new Function('proxy', wrappedCode);\r\n return fn(proxy);\r\n } catch (error) {\r\n // If strictGlobal failed (rare edge case with with-statement), retry without it\r\n if (strictGlobal) {\r\n logger.wuWarn(`[ScriptExecutor] strictGlobal failed for ${appName}, retrying without with(): ${error.message}`);\r\n return this.execute(scriptText, appName, proxy, { ...options, strictGlobal: false });\r\n }\r\n logger.wuError(`[ScriptExecutor] Execution failed for ${appName}:`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Fetch script content from a URL.\r\n * @param {string} url - Script URL\r\n * @returns {Promise<string>} Script text\r\n */\r\n async fetchScript(url) {\r\n const response = await fetch(url);\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch script ${url}: HTTP ${response.status}`);\r\n }\r\n return response.text();\r\n }\r\n\r\n /**\r\n * Execute an array of scripts in sequence inside the proxy.\r\n * External scripts (with src) are fetched first.\r\n *\r\n * @param {Array<{content?: string, src?: string}>} scripts\r\n * @param {string} appName\r\n * @param {Proxy} proxy\r\n * @param {Object} [options]\r\n */\r\n async executeAll(scripts, appName, proxy, options = {}) {\r\n for (const script of scripts) {\r\n let text = script.content;\r\n\r\n if (!text && script.src) {\r\n logger.wuDebug(`[ScriptExecutor] Fetching external script: ${script.src}`);\r\n text = await this.fetchScript(script.src);\r\n }\r\n\r\n if (text && text.trim()) {\r\n this.execute(text, appName, proxy, {\r\n ...options,\r\n sourceUrl: script.src || options.sourceUrl || ''\r\n });\r\n }\r\n }\r\n\r\n logger.wuDebug(`[ScriptExecutor] Executed ${scripts.length} scripts for ${appName}`);\r\n }\r\n}\r\n","/**\r\n * WU-IFRAME-SANDBOX: Real JS isolation using hidden iframes.\r\n *\r\n * Architecture:\r\n * ┌── Main Window ────────────────────────────────┐\r\n * │ ┌── Shadow DOM Container ──────────────────┐ │\r\n * │ │ App renders here (CSS isolated) │ │\r\n * │ └──────────────────────────────────────────┘ │\r\n * │ ┌── Hidden iframe ────────────────────────┐ │\r\n * │ │ import() runs here (REAL modules) │ │\r\n * │ │ window = iframe.contentWindow (ISOLATED)│ │\r\n * │ │ document patched → Shadow DOM │ │\r\n * │ └────────────────────────────────────────-─┘ │\r\n * └───────────────────────────────────────────────┘\r\n *\r\n * Why iframe?\r\n * - import() is REAL → tree shaking, source maps, HMR all work\r\n * - iframe has its own window → globals are isolated\r\n * - Destroying iframe kills all timers/listeners at once\r\n *\r\n * How it works:\r\n * 1. Create hidden iframe with <base href=\"appUrl\"> for URL resolution\r\n * 2. Patch iframe's document: createElement → main document (no ownerDocument issues),\r\n * querySelector/body → Shadow DOM container\r\n * 3. Track timers for guaranteed cleanup (some browsers don't kill iframe timers)\r\n * 4. import() the app module inside iframe → runs in isolated context\r\n * 5. App calls wu.define() → lifecycle registered on parent's WuCore\r\n * 6. On unmount: destroy iframe = nuclear cleanup\r\n *\r\n * Fallback:\r\n * If import() fails (CORS, module errors), wu-core falls back to eval mode\r\n * (fetch HTML + parse + execute with(proxy)).\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuIframeSandbox {\r\n constructor(appName) {\r\n this.appName = appName;\r\n this.iframe = null;\r\n this._active = false;\r\n\r\n // Side-effect tracking for guaranteed cleanup\r\n this._timers = new Set();\r\n this._intervals = new Set();\r\n this._rafs = new Set();\r\n this._listeners = [];\r\n }\r\n\r\n /**\r\n * Create and activate the iframe sandbox.\r\n *\r\n * @param {string} appUrl - App's base URL (for <base href> and relative imports)\r\n * @param {HTMLElement} shadowContainer - Shadow DOM container for DOM redirection\r\n * @param {ShadowRoot|null} shadowRoot - Shadow root for query scoping\r\n * @returns {Window} The iframe's contentWindow (isolated execution context)\r\n */\r\n activate(appUrl, shadowContainer, shadowRoot) {\r\n if (this._active) return this.iframe.contentWindow;\r\n\r\n // 1. Create hidden iframe\r\n const iframe = document.createElement('iframe');\r\n iframe.setAttribute('data-wu-sandbox', this.appName);\r\n iframe.style.cssText = 'display:none !important;position:absolute;width:0;height:0;border:0;';\r\n\r\n // Must be in DOM before accessing contentWindow\r\n document.body.appendChild(iframe);\r\n this.iframe = iframe;\r\n\r\n // 2. Write base HTML with <base href> pointing to app URL.\r\n // This makes relative URL resolution work for fetch(), CSS url(), etc.\r\n // import() of full URLs works regardless of base.\r\n const baseUrl = appUrl.replace(/\\/$/, '');\r\n const iframeWin = iframe.contentWindow;\r\n const iframeDoc = iframeWin.document;\r\n\r\n iframeDoc.open();\r\n iframeDoc.write(\r\n `<!DOCTYPE html><html><head><base href=\"${baseUrl}/\"></head><body></body></html>`\r\n );\r\n iframeDoc.close();\r\n\r\n // 3. Make wu available inside iframe for wu.define()\r\n iframeWin.wu = window.wu;\r\n\r\n // 4. Patch document: redirect DOM operations to Shadow DOM\r\n this._patchDocument(iframeWin, shadowContainer, shadowRoot);\r\n\r\n // 5. Track timers for guaranteed cleanup\r\n this._patchTimers(iframeWin);\r\n\r\n this._active = true;\r\n logger.wuDebug(`[IframeSandbox] Activated for ${this.appName} (base: ${baseUrl})`);\r\n return iframeWin;\r\n }\r\n\r\n /**\r\n * Import an ES module inside the iframe via real import().\r\n * Preserves tree shaking, source maps, and Vite HMR.\r\n *\r\n * @param {string} url - Full module URL to import\r\n * @param {number} [timeout=30000] - Max wait time in ms\r\n * @returns {Promise<void>}\r\n */\r\n importModule(url, timeout = 30000) {\r\n if (!this._active) {\r\n throw new Error(`[IframeSandbox] Not active for ${this.appName}`);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const channelId = `wu_${this.appName}_${Date.now()}`;\r\n\r\n // Listen for import completion via postMessage\r\n const onMessage = (event) => {\r\n if (event.data?.channelId !== channelId) return;\r\n cleanup();\r\n if (event.data.error) {\r\n reject(new Error(event.data.error));\r\n } else {\r\n resolve();\r\n }\r\n };\r\n\r\n const timer = setTimeout(() => {\r\n cleanup();\r\n reject(new Error(\r\n `[IframeSandbox] import() timed out for ${this.appName}: ${url}`\r\n ));\r\n }, timeout);\r\n\r\n const cleanup = () => {\r\n window.removeEventListener('message', onMessage);\r\n clearTimeout(timer);\r\n };\r\n\r\n window.addEventListener('message', onMessage);\r\n\r\n // Inject module script into iframe\r\n const iframeDoc = this.iframe.contentWindow.document;\r\n const script = iframeDoc.createElement('script');\r\n script.type = 'module';\r\n script.textContent =\r\n `import(\"${url.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\")` +\r\n `.then(() => parent.postMessage({ channelId: \"${channelId}\", success: true }, '*'))` +\r\n `.catch(e => parent.postMessage({ channelId: \"${channelId}\", error: e.message || String(e) }, '*'));`;\r\n\r\n iframeDoc.head.appendChild(script);\r\n logger.wuDebug(`[IframeSandbox] Importing module: ${url}`);\r\n });\r\n }\r\n\r\n /**\r\n * Patch the iframe's document to redirect DOM operations.\r\n *\r\n * Critical patches:\r\n * - createElement/createTextNode → main document (avoids ownerDocument mismatch)\r\n * React/Vue create nodes and append to Shadow DOM container.\r\n * Nodes must belong to the main document to avoid cross-document adoption issues.\r\n *\r\n * - querySelector/body → Shadow DOM container\r\n * Libraries that query the document will find app elements in the Shadow DOM.\r\n *\r\n * - addEventListener → tracked for cleanup\r\n */\r\n _patchDocument(iframeWin, shadowContainer, shadowRoot) {\r\n const iframeDoc = iframeWin.document;\r\n const queryTarget = shadowRoot || shadowContainer;\r\n const mainDoc = document; // parent document\r\n\r\n // --- Node creation: use main document to avoid ownerDocument mismatch ---\r\n // React uses container.ownerDocument.createElement() internally,\r\n // but other code might use document.createElement() directly.\r\n // By redirecting to main document, all nodes belong to the same document tree.\r\n iframeDoc.createElement = (tag, options) => mainDoc.createElement(tag, options);\r\n iframeDoc.createElementNS = (ns, tag, options) => mainDoc.createElementNS(ns, tag, options);\r\n iframeDoc.createTextNode = (text) => mainDoc.createTextNode(text);\r\n iframeDoc.createComment = (text) => mainDoc.createComment(text);\r\n iframeDoc.createDocumentFragment = () => mainDoc.createDocumentFragment();\r\n\r\n // --- DOM queries: redirect to Shadow DOM ---\r\n iframeDoc.querySelector = (sel) => queryTarget.querySelector(sel);\r\n iframeDoc.querySelectorAll = (sel) => queryTarget.querySelectorAll(sel);\r\n iframeDoc.getElementById = (id) => queryTarget.querySelector(`#${id}`);\r\n iframeDoc.getElementsByClassName = (cls) => queryTarget.querySelectorAll(`.${cls}`);\r\n iframeDoc.getElementsByTagName = (tag) => queryTarget.querySelectorAll(tag);\r\n\r\n // --- document.body → shadow container ---\r\n // Frameworks that append to document.body (portals, modals) will target the Shadow DOM.\r\n try {\r\n Object.defineProperty(iframeDoc, 'body', {\r\n get: () => shadowContainer,\r\n configurable: true\r\n });\r\n } catch {\r\n // Some environments don't allow redefining body — not critical\r\n logger.wuDebug('[IframeSandbox] Could not redefine document.body');\r\n }\r\n\r\n // --- document.addEventListener: track for cleanup ---\r\n const origDocAdd = iframeDoc.addEventListener.bind(iframeDoc);\r\n const origDocRemove = iframeDoc.removeEventListener.bind(iframeDoc);\r\n\r\n iframeDoc.addEventListener = (event, handler, options) => {\r\n this._listeners.push({ target: iframeDoc, event, handler, options });\r\n origDocAdd(event, handler, options);\r\n };\r\n\r\n iframeDoc.removeEventListener = (event, handler, options) => {\r\n this._listeners = this._listeners.filter(\r\n l => !(l.target === iframeDoc && l.event === event && l.handler === handler)\r\n );\r\n origDocRemove(event, handler, options);\r\n };\r\n\r\n logger.wuDebug(`[IframeSandbox] Document patched for ${this.appName}`);\r\n }\r\n\r\n /**\r\n * Patch timers in the iframe for guaranteed cleanup.\r\n * Some browsers don't fully kill timers when an iframe is removed.\r\n * We track all IDs and clear them explicitly on destroy.\r\n */\r\n _patchTimers(iframeWin) {\r\n const origSetTimeout = iframeWin.setTimeout.bind(iframeWin);\r\n const origClearTimeout = iframeWin.clearTimeout.bind(iframeWin);\r\n const origSetInterval = iframeWin.setInterval.bind(iframeWin);\r\n const origClearInterval = iframeWin.clearInterval.bind(iframeWin);\r\n\r\n iframeWin.setTimeout = (fn, ms, ...args) => {\r\n const id = origSetTimeout((...a) => {\r\n this._timers.delete(id);\r\n if (typeof fn === 'function') fn(...a);\r\n }, ms, ...args);\r\n this._timers.add(id);\r\n return id;\r\n };\r\n\r\n iframeWin.clearTimeout = (id) => {\r\n this._timers.delete(id);\r\n origClearTimeout(id);\r\n };\r\n\r\n iframeWin.setInterval = (fn, ms, ...args) => {\r\n const id = origSetInterval(fn, ms, ...args);\r\n this._intervals.add(id);\r\n return id;\r\n };\r\n\r\n iframeWin.clearInterval = (id) => {\r\n this._intervals.delete(id);\r\n origClearInterval(id);\r\n };\r\n\r\n // requestAnimationFrame may not exist in all iframe contexts\r\n if (iframeWin.requestAnimationFrame) {\r\n const origRAF = iframeWin.requestAnimationFrame.bind(iframeWin);\r\n const origCancelRAF = iframeWin.cancelAnimationFrame.bind(iframeWin);\r\n\r\n iframeWin.requestAnimationFrame = (fn) => {\r\n const id = origRAF((...a) => {\r\n this._rafs.delete(id);\r\n fn(...a);\r\n });\r\n this._rafs.add(id);\r\n return id;\r\n };\r\n\r\n iframeWin.cancelAnimationFrame = (id) => {\r\n this._rafs.delete(id);\r\n origCancelRAF(id);\r\n };\r\n }\r\n\r\n logger.wuDebug(`[IframeSandbox] Timer tracking active for ${this.appName}`);\r\n }\r\n\r\n /**\r\n * Destroy the iframe and all side effects.\r\n * Nuclear cleanup: kills everything at once.\r\n */\r\n destroy() {\r\n if (!this._active) return;\r\n this._active = false;\r\n\r\n // 1. Clear all tracked timers\r\n for (const id of this._timers) { try { clearTimeout(id); } catch {} }\r\n for (const id of this._intervals) { try { clearInterval(id); } catch {} }\r\n for (const id of this._rafs) { try { cancelAnimationFrame(id); } catch {} }\r\n this._timers.clear();\r\n this._intervals.clear();\r\n this._rafs.clear();\r\n\r\n // 2. Remove all tracked event listeners\r\n for (const { target, event, handler, options } of this._listeners) {\r\n try { target.removeEventListener(event, handler, options); } catch {}\r\n }\r\n this._listeners = [];\r\n\r\n // 3. Wipe and remove iframe\r\n if (this.iframe) {\r\n try {\r\n const doc = this.iframe.contentDocument;\r\n if (doc) {\r\n doc.open();\r\n doc.write('');\r\n doc.close();\r\n }\r\n } catch {\r\n // Cross-origin or already detached — ignore\r\n }\r\n\r\n if (this.iframe.parentNode) {\r\n this.iframe.parentNode.removeChild(this.iframe);\r\n }\r\n this.iframe = null;\r\n }\r\n\r\n logger.wuDebug(`[IframeSandbox] Destroyed for ${this.appName}`);\r\n }\r\n\r\n /**\r\n * Check if this sandbox is active.\r\n * @returns {boolean}\r\n */\r\n isActive() {\r\n return this._active;\r\n }\r\n}\r\n","/**\r\n * WU-PREFETCH: Intelligent Prefetching with Speculation Rules API\r\n *\r\n * Prefetches microfrontend modules BEFORE they're needed using:\r\n * 1. Speculation Rules API (Chrome 121+) — browser-native prerender/prefetch\r\n * 2. <link rel=\"modulepreload\"> — ES module prefetch (all modern browsers)\r\n * 3. <link rel=\"prefetch\"> — generic fallback\r\n *\r\n * Trigger modes:\r\n * - immediate: prefetch now\r\n * - hover: prefetch when user hovers a target element\r\n * - visible: prefetch when target element enters viewport (IntersectionObserver)\r\n * - idle: prefetch during browser idle time (requestIdleCallback)\r\n *\r\n * @example\r\n * // Prefetch immediately\r\n * wu.prefetch('cart');\r\n *\r\n * // Prefetch when user hovers the cart link\r\n * wu.prefetch('cart', { on: 'hover', target: '#cart-link' });\r\n *\r\n * // Prefetch when the section becomes visible\r\n * wu.prefetch('cart', { on: 'visible', target: '#cart-section' });\r\n *\r\n * // Prefetch during idle time\r\n * wu.prefetch('cart', { on: 'idle' });\r\n *\r\n * // Prefetch multiple apps with eagerness control\r\n * wu.prefetch(['cart', 'profile'], { eagerness: 'moderate' });\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nexport class WuPrefetch {\r\n constructor(core) {\r\n this.core = core;\r\n\r\n // Track what we've already prefetched to avoid duplicates\r\n this.prefetched = new Set();\r\n\r\n // Active observers and listeners (for cleanup)\r\n this._observers = new Map();\r\n this._listeners = [];\r\n\r\n // Speculation Rules script element (one per page, updated dynamically)\r\n this._speculationScript = null;\r\n this._speculationRules = { prefetch: [], prerender: [] };\r\n\r\n // Detect browser support\r\n this.supportsSpeculationRules = this._detectSpeculationRules();\r\n this.supportsModulePreload = this._detectModulePreload();\r\n\r\n logger.wuDebug(\r\n `[WuPrefetch] Initialized — ` +\r\n `Speculation Rules: ${this.supportsSpeculationRules ? 'yes' : 'no'}, ` +\r\n `Module Preload: ${this.supportsModulePreload ? 'yes' : 'no'}`\r\n );\r\n }\r\n\r\n // ─── Detection ───────────────────────────────────────────────\r\n\r\n _detectSpeculationRules() {\r\n if (typeof HTMLScriptElement === 'undefined') return false;\r\n return HTMLScriptElement.supports?.('speculationrules') ?? false;\r\n }\r\n\r\n _detectModulePreload() {\r\n if (typeof document === 'undefined') return false;\r\n const link = document.createElement('link');\r\n return link.relList?.supports?.('modulepreload') ?? false;\r\n }\r\n\r\n // ─── Main API ────────────────────────────────────────────────\r\n\r\n /**\r\n * Prefetch one or more apps.\r\n *\r\n * @param {string|string[]} appNames - App name(s) to prefetch\r\n * @param {Object} [options]\r\n * @param {'immediate'|'hover'|'visible'|'idle'} [options.on='immediate'] - Trigger mode\r\n * @param {string|Element} [options.target] - CSS selector or element (for hover/visible)\r\n * @param {'conservative'|'moderate'|'eager'} [options.eagerness='moderate'] - Speculation Rules eagerness\r\n * @returns {Promise<void>|Function} Promise for immediate, cleanup function for deferred\r\n */\r\n async prefetch(appNames, options = {}) {\r\n const names = Array.isArray(appNames) ? appNames : [appNames];\r\n const trigger = options.on || 'immediate';\r\n\r\n switch (trigger) {\r\n case 'immediate':\r\n return this._prefetchImmediate(names, options);\r\n\r\n case 'hover':\r\n return this._prefetchOnHover(names, options);\r\n\r\n case 'visible':\r\n return this._prefetchOnVisible(names, options);\r\n\r\n case 'idle':\r\n return this._prefetchOnIdle(names, options);\r\n\r\n default:\r\n logger.wuWarn(`[WuPrefetch] Unknown trigger \"${trigger}\", using immediate`);\r\n return this._prefetchImmediate(names, options);\r\n }\r\n }\r\n\r\n // ─── Immediate Prefetch ──────────────────────────────────────\r\n\r\n async _prefetchImmediate(appNames, options) {\r\n const urls = await this._resolveAppUrls(appNames);\r\n if (urls.length === 0) return;\r\n\r\n // Mark all as prefetched by name (prevents duplicate resolution)\r\n urls.forEach(({ name }) => this.prefetched.add(name));\r\n\r\n // Strategy 1: Speculation Rules API (Chrome 121+)\r\n if (this.supportsSpeculationRules) {\r\n this._addSpeculationRules(urls, options.eagerness || 'moderate');\r\n return;\r\n }\r\n\r\n // Strategy 2: <link rel=\"modulepreload\"> for ES modules\r\n if (this.supportsModulePreload) {\r\n urls.forEach(({ url }) => this._injectModulePreload(url));\r\n return;\r\n }\r\n\r\n // Strategy 3: <link rel=\"prefetch\"> fallback\r\n urls.forEach(({ url }) => this._injectPrefetch(url));\r\n }\r\n\r\n // ─── Hover Trigger ───────────────────────────────────────────\r\n\r\n _prefetchOnHover(appNames, options) {\r\n const target = this._resolveTarget(options.target);\r\n if (!target) {\r\n logger.wuWarn('[WuPrefetch] hover trigger requires a target element or selector');\r\n return () => {};\r\n }\r\n\r\n let done = false;\r\n\r\n const handler = () => {\r\n if (done) return;\r\n done = true;\r\n this._prefetchImmediate(appNames, options);\r\n // One-shot: remove after first trigger\r\n target.removeEventListener('mouseenter', handler);\r\n target.removeEventListener('focusin', handler);\r\n };\r\n\r\n // Mouse hover OR keyboard focus\r\n target.addEventListener('mouseenter', handler, { passive: true });\r\n target.addEventListener('focusin', handler, { passive: true });\r\n\r\n const cleanup = () => {\r\n target.removeEventListener('mouseenter', handler);\r\n target.removeEventListener('focusin', handler);\r\n };\r\n\r\n this._listeners.push(cleanup);\r\n return cleanup;\r\n }\r\n\r\n // ─── Visibility Trigger (IntersectionObserver) ───────────────\r\n\r\n _prefetchOnVisible(appNames, options) {\r\n const target = this._resolveTarget(options.target);\r\n if (!target) {\r\n logger.wuWarn('[WuPrefetch] visible trigger requires a target element or selector');\r\n return () => {};\r\n }\r\n\r\n if (typeof IntersectionObserver === 'undefined') {\r\n // No IntersectionObserver → prefetch immediately\r\n this._prefetchImmediate(appNames, options);\r\n return () => {};\r\n }\r\n\r\n const observer = new IntersectionObserver(\r\n (entries) => {\r\n for (const entry of entries) {\r\n if (entry.isIntersecting) {\r\n this._prefetchImmediate(appNames, options);\r\n observer.disconnect();\r\n this._observers.delete(target);\r\n break;\r\n }\r\n }\r\n },\r\n { rootMargin: '200px' } // Start prefetching 200px before visible\r\n );\r\n\r\n observer.observe(target);\r\n this._observers.set(target, observer);\r\n\r\n const cleanup = () => {\r\n observer.disconnect();\r\n this._observers.delete(target);\r\n };\r\n\r\n return cleanup;\r\n }\r\n\r\n // ─── Idle Trigger ────────────────────────────────────────────\r\n\r\n _prefetchOnIdle(appNames, options) {\r\n const callback = () => this._prefetchImmediate(appNames, options);\r\n\r\n if ('requestIdleCallback' in window) {\r\n const id = requestIdleCallback(callback, { timeout: 3000 });\r\n const cleanup = () => cancelIdleCallback(id);\r\n this._listeners.push(cleanup);\r\n return cleanup;\r\n }\r\n\r\n // Fallback: setTimeout 2s\r\n const id = setTimeout(callback, 2000);\r\n const cleanup = () => clearTimeout(id);\r\n this._listeners.push(cleanup);\r\n return cleanup;\r\n }\r\n\r\n // ─── Speculation Rules API ───────────────────────────────────\r\n\r\n _addSpeculationRules(urls, eagerness) {\r\n const newEntries = urls.filter(({ name }) => !this.prefetched.has(name));\r\n if (newEntries.length === 0) return;\r\n\r\n // Mark as prefetched\r\n newEntries.forEach(({ name }) => this.prefetched.add(name));\r\n\r\n // Build URL list for speculation rules\r\n const urlList = newEntries.map(({ url }) => url);\r\n\r\n // Add prefetch rule\r\n this._speculationRules.prefetch.push({\r\n source: 'list',\r\n urls: urlList,\r\n eagerness\r\n });\r\n\r\n // Inject or update the speculation rules script\r\n this._updateSpeculationScript();\r\n\r\n logger.wuDebug(\r\n `[WuPrefetch] Speculation Rules: prefetch ${newEntries.map(e => e.name).join(', ')} ` +\r\n `(eagerness: ${eagerness})`\r\n );\r\n }\r\n\r\n _updateSpeculationScript() {\r\n // Remove existing script (spec requires replacing, not updating)\r\n if (this._speculationScript) {\r\n this._speculationScript.remove();\r\n }\r\n\r\n const script = document.createElement('script');\r\n script.type = 'speculationrules';\r\n script.textContent = JSON.stringify(this._speculationRules);\r\n document.head.appendChild(script);\r\n\r\n this._speculationScript = script;\r\n }\r\n\r\n // ─── Module Preload ──────────────────────────────────────────\r\n\r\n _injectModulePreload(url) {\r\n if (this.prefetched.has(url)) return;\r\n this.prefetched.add(url);\r\n\r\n const link = document.createElement('link');\r\n link.rel = 'modulepreload';\r\n link.href = url;\r\n document.head.appendChild(link);\r\n\r\n logger.wuDebug(`[WuPrefetch] modulepreload: ${url}`);\r\n }\r\n\r\n // ─── Generic Prefetch ────────────────────────────────────────\r\n\r\n _injectPrefetch(url) {\r\n if (this.prefetched.has(url)) return;\r\n this.prefetched.add(url);\r\n\r\n const link = document.createElement('link');\r\n link.rel = 'prefetch';\r\n link.href = url;\r\n link.as = 'script';\r\n document.head.appendChild(link);\r\n\r\n logger.wuDebug(`[WuPrefetch] prefetch: ${url}`);\r\n }\r\n\r\n // ─── URL Resolution ──────────────────────────────────────────\r\n\r\n /**\r\n * Resolve app names to their module URLs.\r\n * Skips apps that are already mounted, already prefetched, or not registered.\r\n */\r\n async _resolveAppUrls(appNames) {\r\n const results = [];\r\n\r\n for (const name of appNames) {\r\n // Skip if already prefetched\r\n if (this.prefetched.has(name)) {\r\n logger.wuDebug(`[WuPrefetch] ${name} already prefetched, skipping`);\r\n continue;\r\n }\r\n\r\n // Skip if already mounted (no need to prefetch)\r\n if (this.core.mounted.has(name)) {\r\n logger.wuDebug(`[WuPrefetch] ${name} already mounted, skipping`);\r\n continue;\r\n }\r\n\r\n // Skip if already loaded (definition exists)\r\n if (this.core.definitions.has(name)) {\r\n logger.wuDebug(`[WuPrefetch] ${name} already defined, skipping`);\r\n continue;\r\n }\r\n\r\n const app = this.core.apps.get(name);\r\n if (!app) {\r\n logger.wuWarn(`[WuPrefetch] App \"${name}\" not registered, cannot prefetch`);\r\n continue;\r\n }\r\n\r\n try {\r\n const url = await this.core.resolveModulePath(app);\r\n results.push({ name, url });\r\n } catch (error) {\r\n logger.wuWarn(`[WuPrefetch] Failed to resolve URL for \"${name}\":`, error.message);\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n // ─── Helpers ─────────────────────────────────────────────────\r\n\r\n _resolveTarget(target) {\r\n if (!target) return null;\r\n if (typeof target === 'string') return document.querySelector(target);\r\n if (target instanceof Element) return target;\r\n return null;\r\n }\r\n\r\n // ─── Prefetch All Registered (utility) ───────────────────────\r\n\r\n /**\r\n * Prefetch all registered but not-yet-mounted apps.\r\n * Useful for aggressive prefetching after initial load.\r\n *\r\n * @param {Object} [options] - Same options as prefetch()\r\n */\r\n async prefetchAll(options = {}) {\r\n const unmountedApps = [];\r\n for (const [name] of this.core.apps) {\r\n if (!this.core.mounted.has(name) && !this.prefetched.has(name)) {\r\n unmountedApps.push(name);\r\n }\r\n }\r\n\r\n if (unmountedApps.length === 0) {\r\n logger.wuDebug('[WuPrefetch] No apps to prefetch');\r\n return;\r\n }\r\n\r\n logger.wuDebug(`[WuPrefetch] Prefetching all: ${unmountedApps.join(', ')}`);\r\n return this.prefetch(unmountedApps, options);\r\n }\r\n\r\n // ─── Stats ───────────────────────────────────────────────────\r\n\r\n getStats() {\r\n return {\r\n prefetched: [...this.prefetched],\r\n activeObservers: this._observers.size,\r\n activeListeners: this._listeners.length,\r\n speculationRulesSupported: this.supportsSpeculationRules,\r\n modulePreloadSupported: this.supportsModulePreload,\r\n speculationRules: this._speculationRules\r\n };\r\n }\r\n\r\n // ─── Cleanup ─────────────────────────────────────────────────\r\n\r\n cleanup() {\r\n // Disconnect all IntersectionObservers\r\n for (const [, observer] of this._observers) {\r\n observer.disconnect();\r\n }\r\n this._observers.clear();\r\n\r\n // Remove all event listeners\r\n for (const cleanup of this._listeners) {\r\n cleanup();\r\n }\r\n this._listeners = [];\r\n\r\n // Remove speculation rules script\r\n if (this._speculationScript) {\r\n this._speculationScript.remove();\r\n this._speculationScript = null;\r\n }\r\n\r\n this._speculationRules = { prefetch: [], prerender: [] };\r\n this.prefetched.clear();\r\n\r\n logger.wuDebug('[WuPrefetch] Cleaned up');\r\n }\r\n}\r\n","/**\r\n * WU-OVERRIDES: Cookie-based URL overrides for QA/testing\r\n *\r\n * SECURITY MODEL:\r\n * - DISABLED in production by default (must opt-in with allowOverrides: true)\r\n * - Allowlist of trusted domains (only overrides to whitelisted hosts are accepted)\r\n * - Visual indicator when overrides are active (prevents silent phishing)\r\n *\r\n * How it works:\r\n * 1. QA sets a cookie: wu-override:cart=http://localhost:5173\r\n * 2. During wu.init(), overrides are parsed from document.cookie\r\n * 3. The URL for \"cart\" is replaced ONLY in that browser session\r\n * 4. Everyone else sees the production URL\r\n *\r\n * Cookie format:\r\n * wu-override:<appName>=<url>\r\n *\r\n * @example\r\n * // Enable in init (required in production)\r\n * wu.init({\r\n * apps: [...],\r\n * overrides: {\r\n * enabled: true,\r\n * allowedDomains: ['*.company.com', 'localhost', '*.vercel.app'],\r\n * showIndicator: true\r\n * }\r\n * });\r\n *\r\n * // Programmatic API\r\n * wu.override('cart', 'http://localhost:5173');\r\n * wu.removeOverride('cart');\r\n * wu.getOverrides();\r\n * wu.clearOverrides();\r\n */\r\n\r\nimport { logger } from './wu-logger.js';\r\n\r\nconst COOKIE_PREFIX = 'wu-override:';\r\n\r\nexport class WuOverrides {\r\n constructor(config = {}) {\r\n // In-memory cache of active overrides (synced with cookies)\r\n this._overrides = new Map();\r\n\r\n // Security config\r\n this._allowedDomains = config.allowedDomains || [];\r\n this._showIndicator = config.showIndicator ?? true;\r\n this._indicatorElement = null;\r\n\r\n // Determine enabled state:\r\n // - If explicitly passed → use that value (respect user intent)\r\n // - If not passed → auto-detect from environment\r\n if (config.enabled !== undefined) {\r\n this._enabled = config.enabled;\r\n } else {\r\n this._enabled = this._isDevEnvironment();\r\n }\r\n\r\n // Parse existing cookies on construction (only if enabled)\r\n if (this._enabled) {\r\n this._parseFromCookies();\r\n }\r\n }\r\n\r\n // ─── Security: Environment Detection ─────────────────────────\r\n\r\n /**\r\n * Detect if we're in a development environment.\r\n * Overrides are auto-enabled in dev, disabled in production.\r\n */\r\n _isDevEnvironment() {\r\n if (typeof window === 'undefined') return false;\r\n\r\n const hostname = window.location?.hostname || '';\r\n const port = window.location?.port || '';\r\n\r\n // localhost, 127.0.0.1, or non-standard ports = development\r\n return (\r\n hostname === 'localhost' ||\r\n hostname === '127.0.0.1' ||\r\n hostname === '0.0.0.0' ||\r\n hostname.endsWith('.local') ||\r\n (port !== '' && port !== '80' && port !== '443')\r\n );\r\n }\r\n\r\n // ─── Security: Domain Allowlist ──────────────────────────────\r\n\r\n /**\r\n * Check if a URL's domain is in the allowlist.\r\n * If no allowlist is configured, all valid URLs are accepted (dev-mode behavior).\r\n * If an allowlist IS configured, only matching domains pass.\r\n *\r\n * @param {string} url\r\n * @returns {boolean}\r\n */\r\n _isDomainAllowed(url) {\r\n // No allowlist = allow everything (but only if overrides are enabled)\r\n if (this._allowedDomains.length === 0) return true;\r\n\r\n const hostname = this._extractHostname(url);\r\n if (!hostname) return false;\r\n\r\n for (const pattern of this._allowedDomains) {\r\n if (this._matchDomain(hostname, pattern)) return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Extract hostname from a URL string.\r\n */\r\n _extractHostname(url) {\r\n try {\r\n // Handle localhost:PORT shorthand\r\n if (/^localhost(:\\d+)?/.test(url)) return 'localhost';\r\n\r\n // Handle protocol-relative\r\n const normalized = url.startsWith('//') ? `https:${url}` : url;\r\n const parsed = new URL(normalized);\r\n return parsed.hostname;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Match a hostname against a domain pattern.\r\n * Supports wildcard: *.company.com matches sub.company.com\r\n *\r\n * @param {string} hostname - e.g., 'cart.staging.company.com'\r\n * @param {string} pattern - e.g., '*.company.com' or 'localhost'\r\n * @returns {boolean}\r\n */\r\n _matchDomain(hostname, pattern) {\r\n // Exact match\r\n if (hostname === pattern) return true;\r\n\r\n // Wildcard match: *.company.com\r\n if (pattern.startsWith('*.')) {\r\n const suffix = pattern.substring(2); // 'company.com'\r\n return hostname === suffix || hostname.endsWith('.' + suffix);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n // ─── Cookie Parsing ──────────────────────────────────────────\r\n\r\n /**\r\n * Parse all wu-override cookies from document.cookie.\r\n * Called automatically on construction and can be called manually to refresh.\r\n *\r\n * @returns {Map<string, string>} Map of appName → overrideUrl\r\n */\r\n _parseFromCookies() {\r\n this._overrides.clear();\r\n\r\n if (typeof document === 'undefined') return this._overrides;\r\n\r\n if (!this._enabled) {\r\n logger.wuDebug('[WuOverrides] Overrides disabled — skipping cookie parse');\r\n return this._overrides;\r\n }\r\n\r\n const cookies = document.cookie;\r\n if (!cookies) return this._overrides;\r\n\r\n // Split cookies and find wu-override:* entries\r\n const pairs = cookies.split(';');\r\n\r\n for (const pair of pairs) {\r\n const trimmed = pair.trim();\r\n\r\n if (!trimmed.startsWith(COOKIE_PREFIX)) continue;\r\n\r\n // wu-override:cart=http://localhost:5173\r\n const eqIndex = trimmed.indexOf('=');\r\n if (eqIndex === -1) continue;\r\n\r\n const appName = trimmed.substring(COOKIE_PREFIX.length, eqIndex).trim();\r\n const url = trimmed.substring(eqIndex + 1).trim();\r\n\r\n if (!appName || !url) continue;\r\n\r\n // Validate URL format\r\n if (!this._isValidUrl(url)) {\r\n logger.wuWarn(`[WuOverrides] Invalid override URL for \"${appName}\": ${url}`);\r\n continue;\r\n }\r\n\r\n // Validate domain is allowed\r\n if (!this._isDomainAllowed(url)) {\r\n logger.wuWarn(\r\n `[WuOverrides] BLOCKED: \"${appName}\" override to \"${url}\" — ` +\r\n `domain not in allowedDomains. ` +\r\n `Allowed: [${this._allowedDomains.join(', ')}]`\r\n );\r\n continue;\r\n }\r\n\r\n this._overrides.set(appName, url);\r\n logger.wuDebug(`[WuOverrides] Parsed override: ${appName} → ${url}`);\r\n }\r\n\r\n if (this._overrides.size > 0) {\r\n logger.wuInfo(\r\n `[WuOverrides] ${this._overrides.size} active override(s): ` +\r\n [...this._overrides.keys()].join(', ')\r\n );\r\n }\r\n\r\n return this._overrides;\r\n }\r\n\r\n // ─── Apply Overrides ─────────────────────────────────────────\r\n\r\n /**\r\n * Apply overrides to an array of app configs.\r\n * Mutates the url field of matching apps.\r\n * Called by WuCore during init, before registerApp.\r\n *\r\n * @param {Array<{name: string, url: string}>} apps - App configs to process\r\n * @returns {Array<{name: string, url: string, _originalUrl?: string}>} Same array, mutated\r\n */\r\n applyToApps(apps) {\r\n if (!this._enabled || this._overrides.size === 0) return apps;\r\n\r\n for (const app of apps) {\r\n const overrideUrl = this._overrides.get(app.name);\r\n if (overrideUrl) {\r\n app._originalUrl = app.url;\r\n app.url = overrideUrl;\r\n logger.wuInfo(\r\n `[WuOverrides] \"${app.name}\" overridden: ${app._originalUrl} → ${overrideUrl}`\r\n );\r\n }\r\n }\r\n\r\n // Show visual indicator if overrides were applied\r\n if (this._showIndicator && this._overrides.size > 0) {\r\n this._showOverrideIndicator();\r\n }\r\n\r\n return apps;\r\n }\r\n\r\n /**\r\n * Get the override URL for a specific app, or null if none.\r\n *\r\n * @param {string} appName\r\n * @returns {string|null}\r\n */\r\n getOverrideFor(appName) {\r\n return this._overrides.get(appName) || null;\r\n }\r\n\r\n // ─── Programmatic API ────────────────────────────────────────\r\n\r\n /**\r\n * Set an override for an app. Writes a cookie and updates in-memory cache.\r\n *\r\n * @param {string} appName - App to override\r\n * @param {string} url - Override URL (e.g., 'http://localhost:5173')\r\n * @param {Object} [options]\r\n * @param {number} [options.maxAge=86400] - Cookie max-age in seconds (default: 24h)\r\n * @param {string} [options.path='/'] - Cookie path\r\n */\r\n set(appName, url, options = {}) {\r\n if (!appName || !url) {\r\n throw new Error('[WuOverrides] appName and url are required');\r\n }\r\n\r\n if (!this._enabled) {\r\n throw new Error(\r\n '[WuOverrides] Overrides are disabled in this environment. ' +\r\n 'Enable with wu.init({ overrides: { enabled: true } })'\r\n );\r\n }\r\n\r\n if (!this._isValidUrl(url)) {\r\n throw new Error(`[WuOverrides] Invalid URL: ${url}`);\r\n }\r\n\r\n if (!this._isDomainAllowed(url)) {\r\n throw new Error(\r\n `[WuOverrides] Domain not allowed: \"${this._extractHostname(url)}\". ` +\r\n `Allowed: [${this._allowedDomains.join(', ')}]`\r\n );\r\n }\r\n\r\n const maxAge = options.maxAge ?? 86400; // 24 hours default\r\n const path = options.path ?? '/';\r\n\r\n // Set cookie\r\n if (typeof document !== 'undefined') {\r\n document.cookie =\r\n `${COOKIE_PREFIX}${appName}=${url}; path=${path}; max-age=${maxAge}; SameSite=Lax`;\r\n }\r\n\r\n // Update in-memory cache\r\n this._overrides.set(appName, url);\r\n\r\n // Update visual indicator\r\n if (this._showIndicator) {\r\n this._showOverrideIndicator();\r\n }\r\n\r\n logger.wuInfo(`[WuOverrides] Override set: ${appName} → ${url} (expires in ${maxAge}s)`);\r\n }\r\n\r\n /**\r\n * Remove an override for a specific app.\r\n *\r\n * @param {string} appName - App to remove override for\r\n */\r\n remove(appName) {\r\n // Delete cookie by setting max-age=0\r\n if (typeof document !== 'undefined') {\r\n document.cookie = `${COOKIE_PREFIX}${appName}=; path=/; max-age=0`;\r\n }\r\n\r\n this._overrides.delete(appName);\r\n\r\n // Update or remove indicator\r\n if (this._showIndicator) {\r\n if (this._overrides.size === 0) {\r\n this._removeOverrideIndicator();\r\n } else {\r\n this._showOverrideIndicator();\r\n }\r\n }\r\n\r\n logger.wuInfo(`[WuOverrides] Override removed: ${appName}`);\r\n }\r\n\r\n /**\r\n * Remove all overrides.\r\n */\r\n clearAll() {\r\n for (const appName of [...this._overrides.keys()]) {\r\n this.remove(appName);\r\n }\r\n\r\n this._removeOverrideIndicator();\r\n\r\n logger.wuInfo('[WuOverrides] All overrides cleared');\r\n }\r\n\r\n /**\r\n * Get all active overrides as a plain object.\r\n *\r\n * @returns {Object} { appName: url, ... }\r\n */\r\n getAll() {\r\n return Object.fromEntries(this._overrides);\r\n }\r\n\r\n /**\r\n * Check if any overrides are active.\r\n *\r\n * @returns {boolean}\r\n */\r\n hasOverrides() {\r\n return this._overrides.size > 0;\r\n }\r\n\r\n /**\r\n * Check if overrides are enabled in this environment.\r\n *\r\n * @returns {boolean}\r\n */\r\n isEnabled() {\r\n return this._enabled;\r\n }\r\n\r\n /**\r\n * Configure the override system.\r\n * Called by WuCore during init with config.overrides.\r\n *\r\n * @param {Object} config\r\n * @param {boolean} [config.enabled]\r\n * @param {string[]} [config.allowedDomains]\r\n * @param {boolean} [config.showIndicator]\r\n */\r\n configure(config = {}) {\r\n if (config.enabled !== undefined) {\r\n this._enabled = config.enabled;\r\n }\r\n if (config.allowedDomains) {\r\n this._allowedDomains = config.allowedDomains;\r\n }\r\n if (config.showIndicator !== undefined) {\r\n this._showIndicator = config.showIndicator;\r\n }\r\n\r\n // Re-parse cookies with new config\r\n if (this._enabled) {\r\n this._parseFromCookies();\r\n }\r\n }\r\n\r\n /**\r\n * Refresh overrides by re-parsing cookies.\r\n * Useful if cookies were modified externally (DevTools, other tabs).\r\n */\r\n refresh() {\r\n this._parseFromCookies();\r\n }\r\n\r\n // ─── Visual Indicator (anti-phishing) ────────────────────────\r\n\r\n /**\r\n * Show a fixed banner when overrides are active.\r\n * This prevents silent phishing — the user ALWAYS sees when\r\n * microfrontends are being loaded from non-standard URLs.\r\n */\r\n _showOverrideIndicator() {\r\n if (typeof document === 'undefined') return;\r\n\r\n // Remove existing indicator first\r\n this._removeOverrideIndicator();\r\n\r\n const indicator = document.createElement('div');\r\n indicator.id = 'wu-override-indicator';\r\n\r\n const overrideList = [...this._overrides.entries()]\r\n .map(([name, url]) => `${name} → ${url}`)\r\n .join(' | ');\r\n\r\n indicator.textContent = `WU OVERRIDE ACTIVE: ${overrideList}`;\r\n\r\n indicator.style.cssText = [\r\n 'position: fixed',\r\n 'bottom: 0',\r\n 'left: 0',\r\n 'right: 0',\r\n 'z-index: 2147483647',\r\n 'background: #f59e0b',\r\n 'color: #000',\r\n 'font-family: monospace',\r\n 'font-size: 12px',\r\n 'font-weight: bold',\r\n 'padding: 6px 12px',\r\n 'text-align: center',\r\n 'cursor: pointer',\r\n 'user-select: none',\r\n 'box-shadow: 0 -2px 8px rgba(0,0,0,0.2)'\r\n ].join(';');\r\n\r\n // Click to dismiss (but override stays active)\r\n indicator.addEventListener('click', () => {\r\n indicator.style.display = 'none';\r\n });\r\n\r\n // Double-click to clear all overrides\r\n indicator.addEventListener('dblclick', (e) => {\r\n e.preventDefault();\r\n this.clearAll();\r\n });\r\n\r\n indicator.title = 'Click to hide | Double-click to clear all overrides';\r\n\r\n document.body.appendChild(indicator);\r\n this._indicatorElement = indicator;\r\n }\r\n\r\n /**\r\n * Remove the visual indicator.\r\n */\r\n _removeOverrideIndicator() {\r\n if (this._indicatorElement) {\r\n this._indicatorElement.remove();\r\n this._indicatorElement = null;\r\n }\r\n // Also remove by ID in case element reference was lost\r\n if (typeof document !== 'undefined') {\r\n const existing = document.getElementById('wu-override-indicator');\r\n if (existing) existing.remove();\r\n }\r\n }\r\n\r\n // ─── Validation ──────────────────────────────────────────────\r\n\r\n _isValidUrl(url) {\r\n // Accept http://, https://, and // protocol-relative\r\n if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('//')) {\r\n return true;\r\n }\r\n // Accept localhost shorthand like localhost:3000\r\n if (/^localhost(:\\d+)?/.test(url)) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n // ─── Stats ───────────────────────────────────────────────────\r\n\r\n getStats() {\r\n return {\r\n enabled: this._enabled,\r\n activeOverrides: this._overrides.size,\r\n overrides: this.getAll(),\r\n allowedDomains: this._allowedDomains,\r\n showIndicator: this._showIndicator,\r\n environment: this._isDevEnvironment() ? 'development' : 'production'\r\n };\r\n }\r\n}\r\n","/**\r\n * WU-FRAMEWORK: UNIVERSAL MICROFRONTENDS\r\n * Motor principal agnostico - Funciona con cualquier framework\r\n */\r\n\r\nimport { WuLoader } from './wu-loader.js';\r\nimport { WuSandbox } from './wu-sandbox.js';\r\nimport { WuManifest } from './wu-manifest.js';\r\nimport { logger } from './wu-logger.js';\r\nimport { default as store } from './wu-store.js';\r\nimport { WuApp } from './wu-app.js';\r\nimport { WuCache } from './wu-cache.js';\r\nimport { WuEventBus } from './wu-event-bus.js';\r\nimport { WuPerformance } from './wu-performance.js';\r\nimport { WuPluginSystem } from './wu-plugin.js';\r\nimport { WuLoadingStrategy } from './wu-strategies.js';\r\nimport { WuErrorBoundary } from './wu-error-boundary.js';\r\nimport { WuLifecycleHooks } from './wu-hooks.js';\r\nimport { WuHtmlParser } from './wu-html-parser.js';\r\nimport { WuScriptExecutor } from './wu-script-executor.js';\r\nimport { WuIframeSandbox } from './wu-iframe-sandbox.js';\r\nimport { WuPrefetch } from './wu-prefetch.js';\r\nimport { WuOverrides } from './wu-overrides.js';\r\n\r\nexport class WuCore {\r\n constructor(options = {}) {\r\n // Registros principales\r\n this.apps = new Map(); // Apps registradas\r\n this.definitions = new Map(); // Definiciones de lifecycle\r\n this.manifests = new Map(); // Manifiestos cargados\r\n this.mounted = new Map(); // Apps montadas\r\n this.hidden = new Map(); // Keep-alive hidden apps\r\n this._pendingUnmounts = new Map(); // Deferred unmount timers (StrictMode compat)\r\n this._mountingPromises = new Map(); // In-flight mount dedup\r\n\r\n // Componentes core\r\n this.loader = new WuLoader();\r\n this.sandbox = new WuSandbox();\r\n this.manifest = new WuManifest();\r\n this.store = store;\r\n\r\n // Strict sandbox support: HTML entry + script execution in proxy\r\n this.htmlParser = new WuHtmlParser();\r\n this.scriptExecutor = new WuScriptExecutor();\r\n\r\n // Sistemas esenciales\r\n this.cache = new WuCache({ storage: 'localStorage', maxSize: 100 }); // 100MB cache\r\n this.eventBus = new WuEventBus();\r\n this.performance = new WuPerformance();\r\n\r\n // Advanced systems\r\n this.pluginSystem = new WuPluginSystem(this);\r\n this.strategies = new WuLoadingStrategy(this);\r\n this.errorBoundary = new WuErrorBoundary(this);\r\n this.hooks = new WuLifecycleHooks(this);\r\n this.prefetcher = new WuPrefetch(this);\r\n this.overrides = new WuOverrides();\r\n\r\n // Estado\r\n this.isInitialized = false;\r\n\r\n logger.wuInfo('Wu Framework initialized - Universal Microfrontends');\r\n }\r\n\r\n /**\r\n * Inicializar wu-framework con configuracion de apps\r\n * @param {Object} config - Configuracion { apps: [{name, url}, ...] }\r\n */\r\n async init(config) {\r\n if (this.isInitialized) {\r\n logger.wuWarn('Framework already initialized');\r\n return;\r\n }\r\n\r\n // Global sandbox mode: 'module' (default) or 'strict'\r\n this._sandboxMode = config.sandbox || 'module';\r\n\r\n logger.wuDebug(`Initializing (sandbox: ${this._sandboxMode}) with apps:`, config.apps?.map(app => app.name));\r\n\r\n try {\r\n // Execute beforeInit hooks\r\n const beforeInitResult = await this.hooks.execute('beforeInit', { config });\r\n if (beforeInitResult.cancelled) {\r\n logger.wuWarn('Initialization cancelled by beforeInit hook');\r\n return;\r\n }\r\n\r\n // Call plugin beforeInit hooks\r\n await this.pluginSystem.callHook('beforeInit', { config });\r\n\r\n // Configure and apply cookie overrides (QA/testing: wu-override:<app>=<url>)\r\n if (config.overrides) {\r\n this.overrides.configure(config.overrides);\r\n }\r\n const apps = config.apps || [];\r\n this.overrides.refresh();\r\n this.overrides.applyToApps(apps);\r\n\r\n // Registrar todas las apps\r\n for (const appConfig of apps) {\r\n await this.registerApp(appConfig);\r\n }\r\n\r\n // Preload apps with eager/preload strategies\r\n await this.strategies.preload(config.apps || []);\r\n\r\n this.isInitialized = true;\r\n\r\n // Execute afterInit hooks\r\n await this.hooks.execute('afterInit', { config });\r\n\r\n // Call plugin afterInit hooks\r\n await this.pluginSystem.callHook('afterInit', { config });\r\n\r\n logger.wuInfo('Framework initialized successfully');\r\n } catch (error) {\r\n logger.wuError('Initialization failed:', error);\r\n\r\n // Call plugin error hooks\r\n await this.pluginSystem.callHook('onError', { phase: 'init', error });\r\n\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Registrar una aplicacion\r\n * @param {Object} appConfig - { name, url, keepAlive, sandbox, container, ... }\r\n */\r\n async registerApp(appConfig) {\r\n const { name, url } = appConfig;\r\n\r\n try {\r\n logger.wuDebug(`Registering app: ${name} from ${url}`);\r\n\r\n // Cargar manifest\r\n const manifestData = await this.manifest.load(url);\r\n this.manifests.set(name, manifestData);\r\n\r\n // Registrar la app — preserve all config fields (keepAlive, sandbox, container, etc.)\r\n this.apps.set(name, {\r\n ...appConfig,\r\n manifest: manifestData,\r\n status: 'registered'\r\n });\r\n\r\n logger.wuDebug(`App ${name} registered successfully`);\r\n } catch (error) {\r\n logger.wuError(`Failed to register app ${name}:`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Definir lifecycle de una micro-app\r\n * @param {string} appName - Nombre de la app\r\n * @param {Object} lifecycle - { mount, unmount }\r\n */\r\n define(appName, lifecycle) {\r\n if (!lifecycle.mount) {\r\n throw new Error(`[Wu] Mount function required for app: ${appName}`);\r\n }\r\n\r\n this.definitions.set(appName, lifecycle);\r\n\r\n // Dispatch custom event for external listeners\r\n const event = new CustomEvent('wu:app:ready', {\r\n detail: { appName, timestamp: Date.now() }\r\n });\r\n window.dispatchEvent(event);\r\n\r\n logger.wuDebug(`Lifecycle defined for: ${appName}`);\r\n }\r\n\r\n /**\r\n * Mount app with multi-retry mounting and recovery.\r\n * If the app is in keep-alive (hidden) state, shows it instantly.\r\n *\r\n * @param {string} appName - Nombre de la app\r\n * @param {string} containerSelector - Selector del contenedor\r\n */\r\n async mount(appName, containerSelector) {\r\n // ── StrictMode guard: cancel pending deferred unmount ──\r\n // React StrictMode cycle: effect(mount) → cleanup(unmount) → effect(mount)\r\n // The cleanup fires between two mounts. By deferring the actual unmount,\r\n // the second mount cancels it and the app stays alive — zero flicker.\r\n if (this._pendingUnmounts.has(appName)) {\r\n clearTimeout(this._pendingUnmounts.get(appName));\r\n this._pendingUnmounts.delete(appName);\r\n logger.wuDebug(`${appName} deferred unmount cancelled by remount`);\r\n }\r\n\r\n // Already mounted in same container → no-op\r\n if (this.mounted.has(appName)) {\r\n const existing = this.mounted.get(appName);\r\n if (existing.containerSelector === containerSelector) {\r\n logger.wuDebug(`${appName} already mounted in ${containerSelector}`);\r\n return;\r\n }\r\n }\r\n\r\n // Deduplicate concurrent mounts (StrictMode fires effect twice)\r\n if (this._mountingPromises.has(appName)) {\r\n logger.wuDebug(`${appName} mount already in progress, deduplicating`);\r\n return await this._mountingPromises.get(appName);\r\n }\r\n\r\n // Check if app is in keep-alive (hidden) state\r\n const hiddenEntry = this.hidden.get(appName);\r\n if (hiddenEntry) {\r\n if (hiddenEntry.containerSelector === containerSelector) {\r\n // Same container → instant show (no reload)\r\n return await this.show(appName);\r\n }\r\n // Different container → destroy hidden state, remount normally\r\n await this._destroyHidden(appName);\r\n }\r\n\r\n // Track mount promise for deduplication\r\n const mountPromise = this.mountWithRecovery(appName, containerSelector, 0);\r\n this._mountingPromises.set(appName, mountPromise);\r\n\r\n try {\r\n return await mountPromise;\r\n } finally {\r\n this._mountingPromises.delete(appName);\r\n }\r\n }\r\n\r\n /**\r\n * Mount with recovery: self-healing app mounting\r\n */\r\n async mountWithRecovery(appName, containerSelector, attempt = 0) {\r\n const maxAttempts = 3;\r\n\r\n try {\r\n // Start performance measurement\r\n this.performance.startMeasure('mount', appName);\r\n\r\n logger.wuDebug(`Mounting ${appName} in ${containerSelector} (attempt ${attempt + 1})`);\r\n\r\n // Execute beforeLoad hooks\r\n const beforeLoadResult = await this.hooks.execute('beforeLoad', { appName, containerSelector, attempt });\r\n if (beforeLoadResult.cancelled) {\r\n logger.wuWarn('Mount cancelled by beforeLoad hook');\r\n return;\r\n }\r\n\r\n // Call plugin beforeMount hooks\r\n const pluginBeforeMount = await this.pluginSystem.callHook('beforeMount', { appName, containerSelector });\r\n if (pluginBeforeMount === false) {\r\n logger.wuWarn('Mount cancelled by plugin beforeMount hook');\r\n return;\r\n }\r\n\r\n // Verify app is registered\r\n const app = this.apps.get(appName);\r\n if (!app) {\r\n throw new Error(`App ${appName} not registered. Call wu.init() first.`);\r\n }\r\n\r\n // Container reality check\r\n const container = document.querySelector(containerSelector);\r\n if (!container) {\r\n throw new Error(`Container not found: ${containerSelector}`);\r\n }\r\n\r\n // Create sandbox - pasar manifest con styleMode y URL de la app\r\n const sandbox = this.sandbox.create(appName, container, {\r\n manifest: app.manifest,\r\n styleMode: app.manifest?.styleMode,\r\n appUrl: app.url // Pasar URL de la app para filtrar estilos de apps fully-isolated\r\n });\r\n\r\n // Execute afterLoad hooks\r\n await this.hooks.execute('afterLoad', { appName, containerSelector, sandbox });\r\n\r\n // Resolve lifecycle definition\r\n let lifecycle = this.definitions.get(appName);\r\n if (!lifecycle) {\r\n // Load remote app\r\n await this.loadAndMountRemoteApp(app, sandbox);\r\n lifecycle = this.definitions.get(appName);\r\n\r\n if (!lifecycle) {\r\n throw new Error(`App ${appName} did not register with wu.define()`);\r\n }\r\n }\r\n\r\n // Execute beforeMount hooks\r\n const beforeMountResult = await this.hooks.execute('beforeMount', { appName, containerSelector, sandbox, lifecycle });\r\n if (beforeMountResult.cancelled) {\r\n logger.wuWarn('Mount cancelled by beforeMount hook');\r\n return;\r\n }\r\n\r\n // Wait for styles to be ready before mounting\r\n if (sandbox.stylesReady) {\r\n logger.wuDebug(`Waiting for styles to be ready for ${appName}...`);\r\n await sandbox.stylesReady;\r\n logger.wuDebug(`Styles ready for ${appName}`);\r\n }\r\n\r\n // Execute mount lifecycle\r\n await lifecycle.mount(sandbox.container);\r\n\r\n // Register mounted app\r\n this.mounted.set(appName, {\r\n app,\r\n sandbox,\r\n lifecycle,\r\n container: sandbox.container,\r\n hostContainer: container,\r\n containerSelector,\r\n timestamp: Date.now(),\r\n state: 'stable'\r\n });\r\n\r\n // End performance measurement\r\n const mountTime = this.performance.endMeasure('mount', appName);\r\n\r\n // Execute afterMount hooks\r\n await this.hooks.execute('afterMount', { appName, containerSelector, sandbox, mountTime });\r\n\r\n // Call plugin afterMount hooks\r\n await this.pluginSystem.callHook('afterMount', { appName, containerSelector, mountTime });\r\n\r\n // Emit mount event\r\n this.eventBus.emit('app:mounted', { appName, mountTime, attempt }, { appName });\r\n\r\n logger.wuInfo(`${appName} mounted successfully in ${mountTime.toFixed(2)}ms`);\r\n\r\n } catch (error) {\r\n logger.wuError(`Mount attempt ${attempt + 1} failed for ${appName}:`, error);\r\n\r\n // Cleanup sandbox to prevent orphaned shadow DOMs\r\n try {\r\n if (this.sandbox && this.sandbox.sandboxes && this.sandbox.sandboxes.has(appName)) {\r\n const sb = this.sandbox.sandboxes.get(appName);\r\n if (sb && sb.proxySandbox) {\r\n sb.proxySandbox.deactivate();\r\n }\r\n this.sandbox.sandboxes.delete(appName);\r\n logger.wuDebug(`Sandbox cleaned up after mount failure for ${appName}`);\r\n }\r\n } catch (cleanupError) {\r\n logger.wuWarn(`Sandbox cleanup failed for ${appName}:`, cleanupError);\r\n }\r\n\r\n // Use error boundary for intelligent error handling\r\n const errorResult = await this.errorBoundary.handle(error, {\r\n appName,\r\n containerSelector,\r\n retryCount: attempt,\r\n container: containerSelector\r\n });\r\n\r\n // Si el error boundary recupero el error, no necesitamos reintentar\r\n if (errorResult.recovered) {\r\n logger.wuDebug('Error recovered by error boundary');\r\n return;\r\n }\r\n\r\n // Recovery protocol\r\n if (attempt < maxAttempts - 1 && errorResult.action === 'retry') {\r\n logger.wuDebug('Initiating recovery protocol...');\r\n\r\n // Clean app state\r\n await this.appStateCleanup(appName, containerSelector);\r\n\r\n // Temporal stabilization\r\n await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1)));\r\n\r\n // Recursive mounting with recovery\r\n return await this.mountWithRecovery(appName, containerSelector, attempt + 1);\r\n }\r\n\r\n // Call plugin error hooks\r\n await this.pluginSystem.callHook('onError', { phase: 'mount', error, appName });\r\n\r\n // Final mount failure - error boundary already handled fallback UI\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * App state cleanup: Enhanced container cleanup with framework protection\r\n */\r\n async appStateCleanup(appName, containerSelector) {\r\n try {\r\n logger.wuDebug(`Starting app state cleanup for ${appName}...`);\r\n\r\n // Clear hidden (keep-alive) state if present\r\n if (this.hidden.has(appName)) {\r\n try {\r\n await this._destroyHidden(appName);\r\n } catch (hiddenError) {\r\n logger.wuWarn('Hidden app cleanup failed:', hiddenError);\r\n }\r\n }\r\n\r\n // Clear any existing mounted state safely\r\n if (this.mounted.has(appName)) {\r\n try {\r\n await this.unmount(appName, { force: true });\r\n } catch (unmountError) {\r\n logger.wuWarn('Unmount failed during cleanup:', unmountError);\r\n }\r\n }\r\n\r\n // Enhanced container cleanup with Vue safety measures\r\n const container = document.querySelector(containerSelector);\r\n if (container) {\r\n // Protect Vue's reactivity system\r\n if (container.shadowRoot) {\r\n try {\r\n // Clear shadow root content safely\r\n const shadowChildren = Array.from(container.shadowRoot.children);\r\n shadowChildren.forEach(child => {\r\n try {\r\n child.remove();\r\n } catch (removeError) {\r\n logger.wuWarn('Failed to remove shadow child:', removeError);\r\n }\r\n });\r\n } catch (shadowError) {\r\n logger.wuWarn('Shadow root cleanup failed:', shadowError);\r\n }\r\n }\r\n\r\n // Clear any direct children if no shadow root\r\n if (!container.shadowRoot && container.children.length > 0) {\r\n try {\r\n container.innerHTML = '';\r\n } catch (htmlError) {\r\n logger.wuWarn('Container innerHTML cleanup failed:', htmlError);\r\n }\r\n }\r\n\r\n // Reset container attributes\r\n container.removeAttribute('data-wu-app');\r\n container.removeAttribute('data-quantum-state');\r\n container.removeAttribute('wu-debug');\r\n }\r\n\r\n // Reset definition state\r\n this.definitions.delete(appName);\r\n\r\n // Clear sandbox registry\r\n if (this.sandbox && this.sandbox.sandboxes) {\r\n this.sandbox.sandboxes.delete(appName);\r\n }\r\n\r\n logger.wuDebug(`App state cleaned successfully for ${appName}`);\r\n\r\n } catch (cleanupError) {\r\n logger.wuWarn(`App cleanup partial failure for ${appName}:`, cleanupError);\r\n\r\n // Emergency cleanup - force clear everything\r\n try {\r\n const container = document.querySelector(containerSelector);\r\n if (container) {\r\n container.style.display = 'none';\r\n setTimeout(() => {\r\n if (container) {\r\n container.style.display = '';\r\n }\r\n }, 100);\r\n }\r\n } catch (emergencyError) {\r\n logger.wuError('Emergency cleanup failed:', emergencyError);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Remote app loader: Load app in the configured sandbox mode.\r\n *\r\n * Three modes:\r\n *\r\n * - module (default): ES6 import() + patchWindow for side-effect tracking.\r\n * Works with Vite, HMR, ES modules. App code runs in global scope.\r\n * Proxy is a cleanup tracker, not an isolation boundary.\r\n *\r\n * - strict: Hidden iframe + real import(). True JS isolation.\r\n * App code runs in iframe's window (separate global context).\r\n * Document operations proxied to Shadow DOM.\r\n * Preserves: tree shaking, source maps, HMR.\r\n * Falls back to eval mode if import() fails (CORS, etc.)\r\n *\r\n * - eval: Fetch HTML → parse scripts → execute with(proxy).\r\n * Maximum JS isolation via with(proxy) statement.\r\n * Requires bundled apps (UMD/IIFE), not ES modules.\r\n * No tree shaking, no source maps, no HMR.\r\n *\r\n * Set per-app: { name: 'app', url: '...', sandbox: 'strict' }\r\n * Or globally: wu.init({ sandbox: 'strict', apps: [...] })\r\n */\r\n async loadAndMountRemoteApp(app, sandbox) {\r\n const mode = app.sandbox || this._sandboxMode || 'module';\r\n\r\n if (mode === 'strict') {\r\n await this._loadStrict(app, sandbox);\r\n } else if (mode === 'eval') {\r\n await this._loadEval(app, sandbox);\r\n } else {\r\n await this._loadModule(app, sandbox);\r\n }\r\n }\r\n\r\n /**\r\n * MODULE MODE: import() + patchWindow (default).\r\n * Side effects tracked during load, cleaned on unmount.\r\n * App code runs in global scope.\r\n */\r\n async _loadModule(app, sandbox) {\r\n const moduleUrl = await this.resolveModulePath(app);\r\n logger.wuDebug(`[module] Loading ES module: ${moduleUrl}`);\r\n\r\n const jsSandbox = sandbox.jsSandbox;\r\n if (jsSandbox?.patchWindow) {\r\n jsSandbox.patchWindow();\r\n }\r\n\r\n try {\r\n await this.moduleLoader(moduleUrl, app.name);\r\n logger.wuDebug(`[module] ES module loaded: ${app.name}`);\r\n } catch (error) {\r\n logger.wuError(`[module] Failed to load ${moduleUrl}:`, error);\r\n throw error;\r\n } finally {\r\n if (jsSandbox?.unpatchWindow) {\r\n jsSandbox.unpatchWindow();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * STRICT MODE: Hidden iframe + real import().\r\n *\r\n * The iframe provides a separate window context. import() inside the iframe\r\n * is a real ES module import — tree shaking, source maps, and HMR all work.\r\n *\r\n * Pipeline:\r\n * 1. Create hidden iframe with <base href=\"appUrl\">\r\n * 2. Patch iframe's document → DOM operations go to Shadow DOM\r\n * 3. import() the app module inside iframe\r\n * 4. Wait for wu.define() registration\r\n *\r\n * If import() fails (CORS, network, etc.), falls back to eval mode\r\n * with a console warning explaining why.\r\n */\r\n async _loadStrict(app, sandbox) {\r\n logger.wuDebug(`[strict] Loading ${app.name} via iframe sandbox`);\r\n\r\n // Create and activate iframe sandbox\r\n const iframeSandbox = new WuIframeSandbox(app.name);\r\n iframeSandbox.activate(app.url, sandbox.container, sandbox.shadowRoot);\r\n sandbox.iframeSandbox = iframeSandbox;\r\n\r\n try {\r\n // Resolve module path (same logic as module mode)\r\n const moduleUrl = await this.resolveModulePath(app);\r\n logger.wuDebug(`[strict] Importing module in iframe: ${moduleUrl}`);\r\n\r\n // Import module inside iframe — real import()!\r\n await iframeSandbox.importModule(moduleUrl);\r\n logger.wuDebug(`[strict] Module imported for ${app.name}`);\r\n\r\n } catch (importError) {\r\n // import() failed — likely CORS or module error.\r\n // Fall back to eval mode (fetch + parse + with(proxy)).\r\n logger.wuWarn(\r\n `[strict] iframe import failed for ${app.name}: ${importError.message}\\n` +\r\n `Falling back to eval mode (fetch + parse + execute with proxy).\\n` +\r\n `To fix: ensure the app's dev server sets Access-Control-Allow-Origin: * headers,\\n` +\r\n `or use sandbox: 'eval' explicitly for UMD/IIFE bundles.`\r\n );\r\n\r\n // Destroy failed iframe\r\n iframeSandbox.destroy();\r\n sandbox.iframeSandbox = null;\r\n\r\n // Fallback to eval mode\r\n await this._loadEval(app, sandbox);\r\n return;\r\n }\r\n\r\n // Wait for wu.define()\r\n await this._waitForDefine(app.name, 'strict');\r\n\r\n logger.wuDebug(`[strict] ${app.name} loaded and registered via iframe`);\r\n }\r\n\r\n /**\r\n * EVAL MODE: Fetch HTML → parse → execute scripts inside proxy.\r\n *\r\n * Maximum JS isolation via with(proxy) statement — all unqualified\r\n * identifiers (setTimeout, document, fetch) go through proxy traps.\r\n *\r\n * Requires bundled apps (UMD/IIFE). ES modules cannot be eval'd.\r\n * No tree shaking, no source maps, no HMR.\r\n *\r\n * Pipeline:\r\n * 1. Fetch HTML from app URL\r\n * 2. Parse: extract scripts (inline + external), styles, clean DOM\r\n * 3. Inject DOM + styles into Shadow DOM\r\n * 4. Execute all scripts inside the proxy via WuScriptExecutor\r\n * 5. Wait for wu.define()\r\n */\r\n async _loadEval(app, sandbox) {\r\n logger.wuDebug(`[eval] Loading ${app.name} from ${app.url}`);\r\n\r\n const jsSandbox = sandbox.jsSandbox;\r\n const proxy = jsSandbox.getProxy();\r\n\r\n if (!proxy) {\r\n throw new Error(`[eval] No active proxy for ${app.name}. Sandbox must be activated first.`);\r\n }\r\n\r\n // 1. Fetch and parse HTML\r\n const parsed = await this.htmlParser.fetchAndParse(app.url, app.name);\r\n\r\n // 2. Inject clean DOM into container\r\n if (parsed.dom) {\r\n sandbox.container.innerHTML = parsed.dom;\r\n }\r\n\r\n // 3. Inject styles into shadow root\r\n const styleTarget = sandbox.shadowRoot || sandbox.container;\r\n\r\n for (const cssText of parsed.styles.inline) {\r\n const style = document.createElement('style');\r\n style.textContent = cssText;\r\n styleTarget.appendChild(style);\r\n }\r\n\r\n for (const href of parsed.styles.external) {\r\n const link = document.createElement('link');\r\n link.rel = 'stylesheet';\r\n link.href = href;\r\n styleTarget.appendChild(link);\r\n }\r\n\r\n // 4. Build and execute scripts inside the proxy\r\n const scripts = [];\r\n for (const content of parsed.scripts.inline) {\r\n scripts.push({ content });\r\n }\r\n for (const src of parsed.scripts.external) {\r\n scripts.push({ src });\r\n }\r\n\r\n await this.scriptExecutor.executeAll(scripts, app.name, proxy);\r\n logger.wuDebug(`[eval] Scripts executed for ${app.name}`);\r\n\r\n // 5. Wait for wu.define()\r\n await this._waitForDefine(app.name, 'eval');\r\n\r\n logger.wuDebug(`[eval] ${app.name} loaded and registered`);\r\n }\r\n\r\n /**\r\n * Wait for an app to call wu.define() with a timeout.\r\n * Shared by strict and eval modes.\r\n */\r\n async _waitForDefine(appName, mode) {\r\n const maxWaitTime = 10000;\r\n const checkInterval = 50;\r\n const startTime = Date.now();\r\n\r\n while (!this.definitions.has(appName)) {\r\n if (Date.now() - startTime >= maxWaitTime) {\r\n throw new Error(\r\n `[${mode}] App '${appName}' loaded but wu.define() was not called within ${maxWaitTime}ms.\\n` +\r\n `Make sure your app calls: window.wu.define('${appName}', { mount, unmount })`\r\n );\r\n }\r\n await new Promise(resolve => setTimeout(resolve, checkInterval));\r\n }\r\n }\r\n\r\n /**\r\n * Module path resolver: Intelligent URL construction with fallback\r\n * Intelligently resolves module paths with real-time validation\r\n */\r\n async resolveModulePath(app) {\r\n const entryFile = app.manifest?.entry || 'main.js';\r\n const baseUrl = app.url.replace(/\\/$/, ''); // Remove trailing slash\r\n\r\n // Normalize path: Remove duplicated directories\r\n // If entry already starts with 'src/', 'dist/', etc., use it as-is\r\n const hasFolderPrefix = /^(src|dist|public|build|assets|lib|es)\\//.test(entryFile);\r\n\r\n if (hasFolderPrefix) {\r\n logger.wuDebug(`Entry already has folder prefix: ${entryFile}`);\r\n // Entry already has folder, just use baseUrl + entryFile\r\n const directPath = `${baseUrl}/${entryFile}`;\r\n logger.wuDebug(`Using direct path: ${directPath}`);\r\n return directPath;\r\n }\r\n\r\n // Multi-path candidates (in order of preference)\r\n const pathCandidates = [\r\n `${baseUrl}/src/${entryFile}`, // Standard structure\r\n `${baseUrl}/${entryFile}`, // Root level\r\n `${baseUrl}/dist/${entryFile}`, // Built version\r\n `${baseUrl}/public/${entryFile}`, // Public folder\r\n `${baseUrl}/build/${entryFile}`, // Build folder\r\n `${baseUrl}/assets/${entryFile}`, // Assets folder\r\n `${baseUrl}/lib/${entryFile}`, // Library folder\r\n `${baseUrl}/es/${entryFile}` // ES modules folder\r\n ];\r\n\r\n logger.wuDebug(`Attempting path resolution for ${app.name}...`);\r\n\r\n // Smart path discovery: Try each candidate with validation\r\n for (let i = 0; i < pathCandidates.length; i++) {\r\n const candidate = pathCandidates[i];\r\n\r\n try {\r\n logger.wuDebug(`Testing path candidate ${i + 1}/${pathCandidates.length}: ${candidate}`);\r\n\r\n // Path validation with enhanced verification\r\n const isValid = await this.validatePath(candidate);\r\n\r\n if (isValid) {\r\n logger.wuDebug(`Path resolved successfully: ${candidate}`);\r\n return candidate;\r\n } else {\r\n logger.wuDebug(`Path candidate ${i + 1} failed validation: ${candidate}`);\r\n }\r\n\r\n } catch (error) {\r\n logger.wuDebug(`Path candidate ${i + 1} threw error: ${candidate} - ${error.message}`);\r\n continue;\r\n }\r\n }\r\n\r\n // Fallback: If all candidates fail, use the first one and let the error bubble up\r\n const fallbackPath = pathCandidates[0];\r\n logger.wuWarn(`All path candidates failed, using fallback: ${fallbackPath}`);\r\n return fallbackPath;\r\n }\r\n\r\n /**\r\n * Path validator: Smart existence verification with module testing\r\n * Validates if a path exists and can be loaded as an ES module\r\n */\r\n async validatePath(url) {\r\n try {\r\n // Enhanced validation: Try actual module import for reliable verification\r\n logger.wuDebug(`Testing path: ${url}`);\r\n\r\n // First, try a GET request to check if file exists and is accessible\r\n const response = await fetch(url, {\r\n method: 'GET',\r\n cache: 'no-cache',\r\n signal: AbortSignal.timeout(2000) // 2 second timeout\r\n });\r\n\r\n if (!response.ok) {\r\n logger.wuDebug(`Path validation failed - HTTP ${response.status}: ${url}`);\r\n return false;\r\n }\r\n\r\n // Check content type and file extension\r\n const contentType = response.headers.get('content-type') || '';\r\n const isJavaScript =\r\n contentType.includes('javascript') ||\r\n contentType.includes('module') ||\r\n contentType.includes('text/plain') || // Some servers serve JS as plain text\r\n url.endsWith('.js') ||\r\n url.endsWith('.mjs');\r\n\r\n if (!isJavaScript) {\r\n logger.wuDebug(`Path validation failed - Invalid content type '${contentType}': ${url}`);\r\n return false;\r\n }\r\n\r\n // Final verification: Check if content looks like a valid module\r\n const content = await response.text();\r\n\r\n // Detect HTML fallback: Check if server returned HTML instead of JS\r\n // Only check if content STARTS with HTML markers (trimmed), not if it contains them anywhere\r\n // This avoids false positives for Angular/React bundles that contain template strings\r\n const trimmedContent = content.trim().toLowerCase();\r\n const isHtmlFallback =\r\n trimmedContent.startsWith('<!doctype') ||\r\n trimmedContent.startsWith('<html') ||\r\n trimmedContent.startsWith('<head') ||\r\n trimmedContent.startsWith('<body') ||\r\n trimmedContent.startsWith('<!-');\r\n\r\n if (isHtmlFallback) {\r\n logger.wuDebug(`Path validation failed - Server returned HTML fallback page: ${url}`);\r\n return false;\r\n }\r\n\r\n // Check for valid JavaScript module content\r\n const hasModuleContent =\r\n content.includes('export') ||\r\n content.includes('import') ||\r\n content.includes('wu.define') ||\r\n content.includes('module.exports') ||\r\n content.includes('console.log') ||\r\n (content.includes('function') && content.length > 10);\r\n\r\n if (!hasModuleContent) {\r\n logger.wuDebug(`Path validation failed - No valid module content: ${url}`);\r\n logger.wuDebug(`Content preview: ${content.substring(0, 100)}...`);\r\n return false;\r\n }\r\n\r\n logger.wuDebug(`Path validation successful: ${url} (${content.length} chars)`);\r\n return true;\r\n\r\n } catch (error) {\r\n // Network, timeout, or parsing error means path is invalid\r\n logger.wuDebug(`Path validation failed for ${url}: ${error.message}`);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Module loader: Advanced registration patterns\r\n * Handles asynchronous registration with timing synchronization\r\n * Verifica que definitions tenga el lifecycle despues de cargar\r\n */\r\n async moduleLoader(moduleUrl, appName) {\r\n // Check if already registered\r\n if (this.definitions.has(appName)) {\r\n logger.wuDebug(`App ${appName} already registered`);\r\n return;\r\n }\r\n\r\n logger.wuDebug(`Using event-based registration for ${appName}`);\r\n\r\n // Load module first\r\n try {\r\n await import(/* @vite-ignore */ moduleUrl);\r\n } catch (loadError) {\r\n logger.wuError(`Failed to import module ${moduleUrl}:`, loadError);\r\n throw loadError;\r\n }\r\n\r\n // Wait for wu.define() to be called with real verification\r\n const maxWaitTime = 10000; // 10 segundos\r\n const checkInterval = 50; // Verificar cada 50ms\r\n const startTime = Date.now();\r\n\r\n while (!this.definitions.has(appName)) {\r\n const elapsed = Date.now() - startTime;\r\n\r\n if (elapsed >= maxWaitTime) {\r\n throw new Error(\r\n `App '${appName}' module loaded but wu.define() was not called within ${maxWaitTime}ms.\\n\\n` +\r\n `Make sure your module calls:\\n` +\r\n ` wu.define('${appName}', { mount, unmount })\\n\\n` +\r\n `Or using window.wu:\\n` +\r\n ` window.wu.define('${appName}', { mount, unmount })`\r\n );\r\n }\r\n\r\n // Esperar un poco antes de verificar de nuevo\r\n await new Promise(resolve => setTimeout(resolve, checkInterval));\r\n }\r\n\r\n logger.wuDebug(`App ${appName} loaded and registered (verified in definitions)`);\r\n }\r\n\r\n /**\r\n * Desmontar una aplicacion.\r\n *\r\n * With keepAlive, the app is hidden instead of destroyed.\r\n * All DOM, JS state, timers, and iframe are preserved.\r\n * Re-mounting shows the app instantly.\r\n *\r\n * keepAlive is resolved from (in priority order):\r\n * 1. options.keepAlive (per-call override)\r\n * 2. app config keepAlive (set via wu.app() or registerApp)\r\n * 3. false (default: destroy)\r\n *\r\n * Use options.force = true to destroy even if keepAlive is set.\r\n *\r\n * @param {string} appName - Nombre de la app\r\n * @param {Object} [options] - Unmount options\r\n * @param {boolean} [options.keepAlive] - Preserve state for instant re-mount\r\n * @param {boolean} [options.force] - Force destroy even if keepAlive\r\n */\r\n async unmount(appName, options = {}) {\r\n logger.wuDebug(`Unmounting ${appName}`);\r\n\r\n const mounted = this.mounted.get(appName);\r\n if (!mounted) {\r\n // Check if it's hidden (keep-alive) — force destroy if requested\r\n if (options.force && this.hidden.has(appName)) {\r\n return await this._destroyHidden(appName);\r\n }\r\n logger.wuWarn(`App ${appName} not mounted`);\r\n return;\r\n }\r\n\r\n // Resolve keepAlive: per-call > per-app config > default false\r\n const keepAlive = options.force\r\n ? false\r\n : (options.keepAlive ?? mounted.app?.keepAlive ?? false);\r\n\r\n if (keepAlive) {\r\n return await this.hide(appName);\r\n }\r\n\r\n // Force → immediate unmount (no deferral)\r\n if (options.force) {\r\n return await this._executeUnmount(appName, mounted);\r\n }\r\n\r\n // ── Deferred unmount: 60ms window for React StrictMode ──\r\n // StrictMode cycle: effect(mount) → cleanup(unmount) → effect(mount)\r\n // The cleanup fires between two mounts. By deferring the actual unmount,\r\n // the second mount() call cancels the timer and the app stays alive.\r\n if (this._pendingUnmounts.has(appName)) {\r\n clearTimeout(this._pendingUnmounts.get(appName));\r\n }\r\n\r\n this._pendingUnmounts.set(appName, setTimeout(async () => {\r\n this._pendingUnmounts.delete(appName);\r\n // Re-verify: only unmount if the same mount entry is still current\r\n if (this.mounted.has(appName) && this.mounted.get(appName) === mounted) {\r\n try {\r\n await this._executeUnmount(appName, mounted);\r\n } catch (error) {\r\n logger.wuError(`Deferred unmount failed for ${appName}:`, error);\r\n }\r\n }\r\n }, 60));\r\n }\r\n\r\n /**\r\n * Execute the actual unmount immediately (no deferral).\r\n * Called by the deferred timer, force unmount, or destroy.\r\n * @private\r\n */\r\n async _executeUnmount(appName, mounted) {\r\n try {\r\n // Execute beforeUnmount hooks\r\n const beforeUnmountResult = await this.hooks.execute('beforeUnmount', { appName, mounted });\r\n if (beforeUnmountResult.cancelled) {\r\n logger.wuWarn('Unmount cancelled by beforeUnmount hook');\r\n return;\r\n }\r\n\r\n // Call plugin beforeUnmount hooks\r\n const pluginBeforeUnmount = await this.pluginSystem.callHook('beforeUnmount', { appName });\r\n if (pluginBeforeUnmount === false) {\r\n logger.wuWarn('Unmount cancelled by plugin beforeUnmount hook');\r\n return;\r\n }\r\n\r\n // Ejecutar unmount del lifecycle si existe\r\n if (mounted.lifecycle?.unmount) {\r\n await mounted.lifecycle.unmount(mounted.container);\r\n }\r\n\r\n // Destroy iframe sandbox if present (strict mode)\r\n if (mounted.sandbox.iframeSandbox) {\r\n mounted.sandbox.iframeSandbox.destroy();\r\n mounted.sandbox.iframeSandbox = null;\r\n }\r\n\r\n // Limpiar sandbox\r\n this.sandbox.cleanup(mounted.sandbox);\r\n\r\n // Remover del registro de montadas\r\n this.mounted.delete(appName);\r\n\r\n // Execute afterUnmount hooks\r\n await this.hooks.execute('afterUnmount', { appName });\r\n\r\n // Call plugin afterUnmount hooks\r\n await this.pluginSystem.callHook('afterUnmount', { appName });\r\n\r\n // Emit unmount event\r\n this.eventBus.emit('app:unmounted', { appName }, { appName });\r\n\r\n logger.wuDebug(`${appName} unmounted successfully`);\r\n } catch (error) {\r\n logger.wuError(`Failed to unmount ${appName}:`, error);\r\n\r\n // Call plugin error hooks\r\n await this.pluginSystem.callHook('onError', { phase: 'unmount', error, appName });\r\n\r\n // Emit error event\r\n this.eventBus.emit('app:error', { appName, error: error.message }, { appName });\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Hide a mounted app (keep-alive).\r\n *\r\n * Preserves all state: DOM in Shadow DOM, JS in iframe, timers, listeners.\r\n * The app's optional `deactivate()` lifecycle hook is called.\r\n * Re-show with `show()` or `mount()` with the same container.\r\n *\r\n * @param {string} appName - App to hide\r\n */\r\n async hide(appName) {\r\n const mounted = this.mounted.get(appName);\r\n if (!mounted) {\r\n logger.wuWarn(`Cannot hide ${appName}: not mounted`);\r\n return;\r\n }\r\n\r\n logger.wuDebug(`Hiding ${appName} (keep-alive)`);\r\n\r\n // Call optional deactivate lifecycle hook\r\n if (mounted.lifecycle?.deactivate) {\r\n try {\r\n await mounted.lifecycle.deactivate(mounted.container);\r\n } catch (err) {\r\n logger.wuWarn(`deactivate() failed for ${appName}:`, err);\r\n }\r\n }\r\n\r\n // Execute beforeUnmount hooks (so plugins know)\r\n await this.hooks.execute('beforeUnmount', { appName, mounted, keepAlive: true });\r\n await this.pluginSystem.callHook('beforeUnmount', { appName, keepAlive: true });\r\n\r\n // Hide the host container — all Shadow DOM content stays intact\r\n mounted.hostContainer.style.display = 'none';\r\n mounted.state = 'hidden';\r\n mounted.hiddenAt = Date.now();\r\n\r\n // Move from mounted → hidden\r\n this.hidden.set(appName, mounted);\r\n this.mounted.delete(appName);\r\n\r\n // Execute afterUnmount hooks\r\n await this.hooks.execute('afterUnmount', { appName, keepAlive: true });\r\n await this.pluginSystem.callHook('afterUnmount', { appName, keepAlive: true });\r\n\r\n // Emit event\r\n this.eventBus.emit('app:hidden', { appName }, { appName });\r\n\r\n logger.wuInfo(`${appName} hidden (keep-alive) — state preserved`);\r\n }\r\n\r\n /**\r\n * Show a hidden (keep-alive) app.\r\n *\r\n * Restores visibility instantly — no reload, no remount.\r\n * The app's optional `activate()` lifecycle hook is called.\r\n *\r\n * @param {string} appName - App to show\r\n */\r\n async show(appName) {\r\n const hidden = this.hidden.get(appName);\r\n if (!hidden) {\r\n logger.wuWarn(`Cannot show ${appName}: not in keep-alive state`);\r\n return;\r\n }\r\n\r\n this.performance.startMeasure('show', appName);\r\n logger.wuDebug(`Showing ${appName} from keep-alive`);\r\n\r\n // Execute beforeMount hooks\r\n await this.hooks.execute('beforeMount', {\r\n appName,\r\n containerSelector: hidden.containerSelector,\r\n sandbox: hidden.sandbox,\r\n lifecycle: hidden.lifecycle,\r\n keepAlive: true\r\n });\r\n await this.pluginSystem.callHook('beforeMount', {\r\n appName,\r\n containerSelector: hidden.containerSelector,\r\n keepAlive: true\r\n });\r\n\r\n // Show the host container\r\n hidden.hostContainer.style.display = '';\r\n hidden.state = 'stable';\r\n delete hidden.hiddenAt;\r\n\r\n // Move from hidden → mounted\r\n this.mounted.set(appName, hidden);\r\n this.hidden.delete(appName);\r\n\r\n // Call optional activate lifecycle hook\r\n if (hidden.lifecycle?.activate) {\r\n try {\r\n await hidden.lifecycle.activate(hidden.container);\r\n } catch (err) {\r\n logger.wuWarn(`activate() failed for ${appName}:`, err);\r\n }\r\n }\r\n\r\n const showTime = this.performance.endMeasure('show', appName);\r\n\r\n // Execute afterMount hooks\r\n await this.hooks.execute('afterMount', {\r\n appName,\r\n containerSelector: hidden.containerSelector,\r\n sandbox: hidden.sandbox,\r\n mountTime: showTime,\r\n keepAlive: true\r\n });\r\n await this.pluginSystem.callHook('afterMount', {\r\n appName,\r\n containerSelector: hidden.containerSelector,\r\n mountTime: showTime,\r\n keepAlive: true\r\n });\r\n\r\n // Emit event\r\n this.eventBus.emit('app:shown', { appName, showTime }, { appName });\r\n\r\n logger.wuInfo(`${appName} shown from keep-alive in ${showTime.toFixed(2)}ms`);\r\n }\r\n\r\n /**\r\n * Force-destroy a hidden (keep-alive) app.\r\n * Runs full cleanup: lifecycle unmount, iframe destroy, sandbox cleanup.\r\n *\r\n * @param {string} appName\r\n * @private\r\n */\r\n async _destroyHidden(appName) {\r\n const hidden = this.hidden.get(appName);\r\n if (!hidden) return;\r\n\r\n logger.wuDebug(`Force-destroying hidden app: ${appName}`);\r\n\r\n // Show first (so unmount sees the container)\r\n hidden.hostContainer.style.display = '';\r\n hidden.state = 'stable';\r\n\r\n // Move back to mounted temporarily\r\n this.mounted.set(appName, hidden);\r\n this.hidden.delete(appName);\r\n\r\n // Now do a full unmount\r\n await this.unmount(appName, { force: true });\r\n }\r\n\r\n /**\r\n * Check if an app is in keep-alive (hidden) state.\r\n * @param {string} appName\r\n * @returns {boolean}\r\n */\r\n isHidden(appName) {\r\n return this.hidden.has(appName);\r\n }\r\n\r\n /**\r\n * Cargar componente compartido (para imports/exports)\r\n * @param {string} componentPath - Ruta del componente (ej: \"shared.Button\")\r\n */\r\n async use(componentPath) {\r\n const [appName, componentName] = componentPath.split('.');\r\n\r\n if (!appName || !componentName) {\r\n throw new Error(`Invalid component path: ${componentPath}. Use format \"app.component\"`);\r\n }\r\n\r\n const app = this.apps.get(appName);\r\n if (!app) {\r\n throw new Error(`App ${appName} not registered`);\r\n }\r\n\r\n const manifest = this.manifests.get(appName);\r\n const exportPath = manifest?.wu?.exports?.[componentName];\r\n\r\n if (!exportPath) {\r\n throw new Error(`Component ${componentName} not exported by ${appName}`);\r\n }\r\n\r\n // Cargar componente\r\n return await this.loader.loadComponent(app.url, exportPath);\r\n }\r\n\r\n /**\r\n * Obtener informacion de una app\r\n * @param {string} appName - Nombre de la app\r\n */\r\n getAppInfo(appName) {\r\n return {\r\n registered: this.apps.get(appName),\r\n manifest: this.manifests.get(appName),\r\n mounted: this.mounted.get(appName),\r\n definition: this.definitions.get(appName)\r\n };\r\n }\r\n\r\n /**\r\n * Obtener estadisticas del framework\r\n */\r\n getStats() {\r\n return {\r\n registered: this.apps.size,\r\n defined: this.definitions.size,\r\n mounted: this.mounted.size,\r\n hidden: this.hidden.size,\r\n apps: Array.from(this.apps.keys())\r\n };\r\n }\r\n\r\n /**\r\n * Store methods: Convenience methods for state management\r\n */\r\n\r\n /**\r\n * Get value from global store\r\n * @param {string} path - Dot notation path\r\n * @returns {*} Value at path\r\n */\r\n getState(path) {\r\n return this.store.get(path);\r\n }\r\n\r\n /**\r\n * Set value in global store\r\n * @param {string} path - Dot notation path\r\n * @param {*} value - Value to set\r\n * @returns {number} Sequence number\r\n */\r\n setState(path, value) {\r\n return this.store.set(path, value);\r\n }\r\n\r\n /**\r\n * Subscribe to state changes\r\n * @param {string} pattern - Path or pattern\r\n * @param {Function} callback - Callback function\r\n * @returns {Function} Unsubscribe function\r\n */\r\n onStateChange(pattern, callback) {\r\n return this.store.on(pattern, callback);\r\n }\r\n\r\n /**\r\n * Batch set multiple state values\r\n * @param {Object} updates - Object with path:value pairs\r\n * @returns {Array} Sequence numbers\r\n */\r\n batchState(updates) {\r\n return this.store.batch(updates);\r\n }\r\n\r\n /**\r\n * Get store metrics\r\n * @returns {Object} Performance metrics\r\n */\r\n getStoreMetrics() {\r\n return this.store.getMetrics();\r\n }\r\n\r\n /**\r\n * Clear all state\r\n */\r\n clearState() {\r\n this.store.clear();\r\n }\r\n\r\n /**\r\n * Set a URL override for an app (QA/testing).\r\n * Sets a cookie so the override persists across page reloads.\r\n * Only affects the current browser — no one else sees it.\r\n *\r\n * @param {string} appName - App to override\r\n * @param {string} url - Override URL (e.g., 'http://localhost:5173')\r\n * @param {Object} [options]\r\n * @param {number} [options.maxAge=86400] - Cookie lifetime in seconds (default: 24h)\r\n *\r\n * @example\r\n * wu.override('cart', 'http://localhost:5173');\r\n * wu.override('header', 'https://preview-abc123.vercel.app');\r\n */\r\n override(appName, url, options) {\r\n this.overrides.set(appName, url, options);\r\n }\r\n\r\n /**\r\n * Remove URL override for an app.\r\n * @param {string} appName\r\n */\r\n removeOverride(appName) {\r\n this.overrides.remove(appName);\r\n }\r\n\r\n /**\r\n * Get all active overrides.\r\n * @returns {Object} { appName: url, ... }\r\n */\r\n getOverrides() {\r\n return this.overrides.getAll();\r\n }\r\n\r\n /**\r\n * Remove all overrides.\r\n */\r\n clearOverrides() {\r\n this.overrides.clearAll();\r\n }\r\n\r\n /**\r\n * Prefetch one or more apps before they're needed.\r\n *\r\n * Uses Speculation Rules API (Chrome 121+), falls back to\r\n * <link rel=\"modulepreload\"> or <link rel=\"prefetch\">.\r\n *\r\n * @param {string|string[]} appNames - App name(s) to prefetch\r\n * @param {Object} [options]\r\n * @param {'immediate'|'hover'|'visible'|'idle'} [options.on='immediate'] - When to trigger\r\n * @param {string|Element} [options.target] - Element for hover/visible triggers\r\n * @param {'conservative'|'moderate'|'eager'} [options.eagerness='moderate'] - Speculation eagerness\r\n * @returns {Promise<void>|Function} Promise or cleanup function\r\n *\r\n * @example\r\n * wu.prefetch('cart');\r\n * wu.prefetch('cart', { on: 'hover', target: '#cart-link' });\r\n * wu.prefetch('cart', { on: 'visible', target: '#cart-section' });\r\n * wu.prefetch(['profile', 'settings'], { on: 'idle' });\r\n */\r\n prefetch(appNames, options) {\r\n return this.prefetcher.prefetch(appNames, options);\r\n }\r\n\r\n /**\r\n * Prefetch all registered but not-yet-mounted apps.\r\n * @param {Object} [options] - Same options as prefetch()\r\n */\r\n prefetchAll(options) {\r\n return this.prefetcher.prefetchAll(options);\r\n }\r\n\r\n /**\r\n * Create WuApp instance for declarative usage\r\n * @param {string} name - App name\r\n * @param {Object} config - Configuration { url, container, autoInit }\r\n * @returns {WuApp} WuApp instance\r\n */\r\n app(name, config) {\r\n return new WuApp(name, config, this);\r\n }\r\n\r\n /**\r\n * Limpiar todo el framework\r\n */\r\n async destroy() {\r\n logger.wuDebug('Destroying framework...');\r\n\r\n try {\r\n // Execute beforeDestroy hooks\r\n await this.hooks.execute('beforeDestroy', {});\r\n\r\n // Call plugin onDestroy hooks\r\n await this.pluginSystem.callHook('onDestroy', {});\r\n\r\n // Cancel all pending deferred unmounts\r\n for (const timer of this._pendingUnmounts.values()) {\r\n clearTimeout(timer);\r\n }\r\n this._pendingUnmounts.clear();\r\n this._mountingPromises.clear();\r\n\r\n // Force-destroy all hidden (keep-alive) apps first\r\n for (const appName of [...this.hidden.keys()]) {\r\n await this._destroyHidden(appName);\r\n }\r\n\r\n // Desmontar todas las apps\r\n for (const appName of [...this.mounted.keys()]) {\r\n await this.unmount(appName, { force: true });\r\n }\r\n\r\n // Limpiar sistemas esenciales\r\n this.cache.clear();\r\n this.eventBus.removeAll();\r\n this.eventBus.clearHistory();\r\n this.performance.clearMetrics();\r\n\r\n // Limpiar advanced systems\r\n this.pluginSystem.cleanup();\r\n this.strategies.cleanup();\r\n this.errorBoundary.cleanup();\r\n this.hooks.cleanup();\r\n this.prefetcher.cleanup();\r\n\r\n // Limpiar registros\r\n this.apps.clear();\r\n this.definitions.clear();\r\n this.manifests.clear();\r\n this.mounted.clear();\r\n this.hidden.clear();\r\n\r\n // Limpiar store\r\n this.store.clear();\r\n\r\n this.isInitialized = false;\r\n\r\n // Execute afterDestroy hooks\r\n await this.hooks.execute('afterDestroy', {});\r\n\r\n logger.wuDebug('Framework destroyed');\r\n } catch (error) {\r\n logger.wuError('Error during destroy:', error);\r\n throw error;\r\n }\r\n }\r\n}\r\n","/**\r\n * WU-AI-PROVIDER: BYOL (Bring Your Own LLM) provider system\r\n *\r\n * Pure fetch(), zero dependencies. Adapters normalize request/response\r\n * across OpenAI, Anthropic, Ollama, and custom providers.\r\n *\r\n * Internal normalized format:\r\n * Request: { role, content, tool_calls?, tool_call_id? }\r\n * Response: { content, tool_calls?, usage? }\r\n */\r\n\r\nimport { logger } from '../core/wu-logger.js';\r\n\r\n// ─── Normalized types (internal) ─────────────────────────────────\r\n//\r\n// Message: { role: 'system'|'user'|'assistant'|'tool', content: string,\r\n// tool_calls?: ToolCall[], tool_call_id?: string }\r\n//\r\n// ToolCall: { id: string, name: string, arguments: object }\r\n//\r\n// Response: { content: string, tool_calls?: ToolCall[], usage?: { prompt_tokens, completion_tokens } }\r\n//\r\n// StreamChunk: { type: 'text'|'tool_call'|'done'|'error', content?: string,\r\n// tool_call?: ToolCall, usage?: object, error?: string }\r\n\r\n// ─── Base Adapter ────────────────────────────────────────────────\r\n\r\nclass BaseAdapter {\r\n constructor(config = {}) {\r\n this.model = config.model || '';\r\n }\r\n\r\n /** Format messages + options into provider-specific request body */\r\n formatRequest(/* messages, options */) {\r\n throw new Error('Adapter must implement formatRequest()');\r\n }\r\n\r\n /** Parse provider response into normalized Response */\r\n parseResponse(/* rawData */) {\r\n throw new Error('Adapter must implement parseResponse()');\r\n }\r\n\r\n /** Parse a streaming SSE line into a StreamChunk (or null to skip) */\r\n parseStreamChunk(/* line */) {\r\n throw new Error('Adapter must implement parseStreamChunk()');\r\n }\r\n\r\n /** Get required headers for the provider */\r\n getHeaders(/* config */) {\r\n return { 'Content-Type': 'application/json' };\r\n }\r\n}\r\n\r\n// ─── OpenAI Adapter ──────────────────────────────────────────────\r\n\r\nclass OpenAIAdapter extends BaseAdapter {\r\n constructor(config) {\r\n super(config);\r\n this.model = config.model || 'gpt-4o';\r\n }\r\n\r\n getHeaders(config) {\r\n const h = { 'Content-Type': 'application/json' };\r\n if (config.apiKey) h['Authorization'] = `Bearer ${config.apiKey}`;\r\n return h;\r\n }\r\n\r\n formatRequest(messages, options = {}) {\r\n const body = {\r\n model: options.model || this.model,\r\n messages: messages.map(m => {\r\n const msg = { role: m.role, content: m.content };\r\n if (m.tool_call_id) msg.tool_call_id = m.tool_call_id;\r\n if (m.tool_calls) msg.tool_calls = m.tool_calls.map(tc => ({\r\n id: tc.id,\r\n type: 'function',\r\n function: { name: tc.name, arguments: JSON.stringify(tc.arguments) },\r\n }));\r\n return msg;\r\n }),\r\n };\r\n if (options.tools?.length) {\r\n body.tools = options.tools.map(t => ({\r\n type: 'function',\r\n function: { name: t.name, description: t.description, parameters: t.parameters },\r\n }));\r\n }\r\n if (options.temperature !== undefined) body.temperature = options.temperature;\r\n if (options.maxTokens) body.max_tokens = options.maxTokens;\r\n if (options.stream) body.stream = true;\r\n\r\n // Structured output / JSON mode\r\n if (options.responseFormat) {\r\n const rf = options.responseFormat;\r\n if (rf === 'json' || rf?.type === 'json_object') {\r\n body.response_format = { type: 'json_object' };\r\n } else if (rf?.type === 'json_schema') {\r\n body.response_format = {\r\n type: 'json_schema',\r\n json_schema: {\r\n name: rf.name || 'response',\r\n schema: rf.schema,\r\n strict: rf.strict !== false,\r\n },\r\n };\r\n }\r\n }\r\n\r\n return body;\r\n }\r\n\r\n parseResponse(data) {\r\n const choice = data.choices?.[0];\r\n if (!choice) return { content: '', tool_calls: [], usage: data.usage };\r\n\r\n const msg = choice.message || {};\r\n const toolCalls = (msg.tool_calls || []).map(tc => ({\r\n id: tc.id,\r\n name: tc.function?.name,\r\n arguments: this._safeParseArgs(tc.function?.arguments),\r\n }));\r\n\r\n return {\r\n content: msg.content || '',\r\n tool_calls: toolCalls.length > 0 ? toolCalls : undefined,\r\n usage: data.usage ? {\r\n prompt_tokens: data.usage.prompt_tokens,\r\n completion_tokens: data.usage.completion_tokens,\r\n } : undefined,\r\n };\r\n }\r\n\r\n parseStreamChunk(line) {\r\n if (!line.startsWith('data: ')) return null;\r\n const raw = line.slice(6).trim();\r\n if (raw === '[DONE]') return { type: 'done' };\r\n\r\n try {\r\n const data = JSON.parse(raw);\r\n const delta = data.choices?.[0]?.delta;\r\n if (!delta) return null;\r\n\r\n if (delta.tool_calls?.length) {\r\n const tc = delta.tool_calls[0];\r\n return {\r\n type: 'tool_call_delta',\r\n index: tc.index,\r\n id: tc.id,\r\n name: tc.function?.name,\r\n argumentsDelta: tc.function?.arguments || '',\r\n };\r\n }\r\n\r\n if (delta.content) {\r\n return { type: 'text', content: delta.content };\r\n }\r\n\r\n if (data.usage) {\r\n return { type: 'usage', usage: data.usage };\r\n }\r\n\r\n return null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n _safeParseArgs(str) {\r\n if (!str) return {};\r\n try { return JSON.parse(str); } catch { return {}; }\r\n }\r\n}\r\n\r\n// ─── Anthropic Adapter ───────────────────────────────────────────\r\n\r\nclass AnthropicAdapter extends BaseAdapter {\r\n constructor(config) {\r\n super(config);\r\n this.model = config.model || 'claude-sonnet-4-5-20250929';\r\n }\r\n\r\n getHeaders(config) {\r\n const h = { 'Content-Type': 'application/json' };\r\n if (config.apiKey) {\r\n h['x-api-key'] = config.apiKey;\r\n h['anthropic-version'] = '2023-06-01';\r\n }\r\n return h;\r\n }\r\n\r\n formatRequest(messages, options = {}) {\r\n // Anthropic separates system from messages\r\n const systemMsgs = messages.filter(m => m.role === 'system');\r\n const otherMsgs = messages.filter(m => m.role !== 'system');\r\n\r\n const body = {\r\n model: options.model || this.model,\r\n max_tokens: options.maxTokens || 4096,\r\n messages: otherMsgs.map(m => {\r\n if (m.role === 'tool') {\r\n return {\r\n role: 'user',\r\n content: [{\r\n type: 'tool_result',\r\n tool_use_id: m.tool_call_id,\r\n content: m.content,\r\n }],\r\n };\r\n }\r\n if (m.tool_calls) {\r\n return {\r\n role: 'assistant',\r\n content: m.tool_calls.map(tc => ({\r\n type: 'tool_use',\r\n id: tc.id,\r\n name: tc.name,\r\n input: tc.arguments,\r\n })),\r\n };\r\n }\r\n return { role: m.role, content: m.content };\r\n }),\r\n };\r\n\r\n if (systemMsgs.length) {\r\n body.system = systemMsgs.map(m => m.content).join('\\n\\n');\r\n }\r\n\r\n // Structured output / JSON mode (Anthropic has no native support)\r\n // Strategy: augment system prompt + prefill assistant turn with '{'\r\n if (options.responseFormat) {\r\n const rf = options.responseFormat;\r\n const jsonInstruction = '\\n\\nYou MUST respond with valid JSON only. No markdown, no explanation.';\r\n\r\n if (rf === 'json' || rf?.type === 'json_object') {\r\n body.system = (body.system || '') + jsonInstruction;\r\n } else if (rf?.type === 'json_schema') {\r\n const schemaStr = JSON.stringify(rf.schema, null, 2);\r\n body.system = (body.system || '') +\r\n jsonInstruction +\r\n `\\n\\nYour response MUST conform to this JSON schema:\\n${schemaStr}`;\r\n }\r\n\r\n // Prefill assistant message with '{' to force JSON output\r\n body.messages.push({ role: 'assistant', content: '{' });\r\n }\r\n\r\n if (options.tools?.length) {\r\n body.tools = options.tools.map(t => ({\r\n name: t.name,\r\n description: t.description,\r\n input_schema: t.parameters,\r\n }));\r\n }\r\n if (options.temperature !== undefined) body.temperature = options.temperature;\r\n if (options.stream) body.stream = true;\r\n return body;\r\n }\r\n\r\n parseResponse(data) {\r\n const textBlocks = (data.content || []).filter(b => b.type === 'text');\r\n const toolBlocks = (data.content || []).filter(b => b.type === 'tool_use');\r\n\r\n const content = textBlocks.map(b => b.text).join('');\r\n const toolCalls = toolBlocks.map(b => ({\r\n id: b.id,\r\n name: b.name,\r\n arguments: b.input || {},\r\n }));\r\n\r\n return {\r\n content,\r\n tool_calls: toolCalls.length > 0 ? toolCalls : undefined,\r\n usage: data.usage ? {\r\n prompt_tokens: data.usage.input_tokens,\r\n completion_tokens: data.usage.output_tokens,\r\n } : undefined,\r\n };\r\n }\r\n\r\n parseStreamChunk(line) {\r\n if (!line.startsWith('data: ')) return null;\r\n const raw = line.slice(6).trim();\r\n\r\n try {\r\n const data = JSON.parse(raw);\r\n\r\n if (data.type === 'content_block_delta') {\r\n if (data.delta?.type === 'text_delta') {\r\n return { type: 'text', content: data.delta.text };\r\n }\r\n if (data.delta?.type === 'input_json_delta') {\r\n return { type: 'tool_call_delta', argumentsDelta: data.delta.partial_json || '' };\r\n }\r\n }\r\n\r\n if (data.type === 'content_block_start' && data.content_block?.type === 'tool_use') {\r\n return {\r\n type: 'tool_call_start',\r\n id: data.content_block.id,\r\n name: data.content_block.name,\r\n };\r\n }\r\n\r\n if (data.type === 'message_delta' && data.usage) {\r\n return {\r\n type: 'usage',\r\n usage: { prompt_tokens: data.usage.input_tokens, completion_tokens: data.usage.output_tokens },\r\n };\r\n }\r\n\r\n if (data.type === 'message_stop') {\r\n return { type: 'done' };\r\n }\r\n\r\n return null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n}\r\n\r\n// ─── Ollama Adapter ──────────────────────────────────────────────\r\n\r\nclass OllamaAdapter extends BaseAdapter {\r\n constructor(config) {\r\n super(config);\r\n this.model = config.model || 'llama3';\r\n }\r\n\r\n getHeaders() {\r\n return { 'Content-Type': 'application/json' };\r\n }\r\n\r\n formatRequest(messages, options = {}) {\r\n const body = {\r\n model: options.model || this.model,\r\n messages: messages.map(m => ({ role: m.role, content: m.content })),\r\n };\r\n if (options.tools?.length) {\r\n body.tools = options.tools.map(t => ({\r\n type: 'function',\r\n function: { name: t.name, description: t.description, parameters: t.parameters },\r\n }));\r\n }\r\n if (options.temperature !== undefined) body.options = { temperature: options.temperature };\r\n if (options.stream !== undefined) body.stream = options.stream;\r\n\r\n // Structured output / JSON mode\r\n if (options.responseFormat) {\r\n const rf = options.responseFormat;\r\n if (rf === 'json' || rf?.type === 'json_object') {\r\n body.format = 'json';\r\n } else if (rf?.type === 'json_schema') {\r\n body.format = rf.schema;\r\n }\r\n }\r\n\r\n return body;\r\n }\r\n\r\n parseResponse(data) {\r\n const msg = data.message || {};\r\n const toolCalls = (msg.tool_calls || []).map((tc, i) => ({\r\n id: `ollama_${i}_${Date.now()}`,\r\n name: tc.function?.name,\r\n arguments: tc.function?.arguments || {},\r\n }));\r\n\r\n return {\r\n content: msg.content || '',\r\n tool_calls: toolCalls.length > 0 ? toolCalls : undefined,\r\n usage: data.eval_count ? {\r\n prompt_tokens: data.prompt_eval_count || 0,\r\n completion_tokens: data.eval_count || 0,\r\n } : undefined,\r\n };\r\n }\r\n\r\n parseStreamChunk(line) {\r\n try {\r\n const data = JSON.parse(line);\r\n if (data.done) return { type: 'done' };\r\n if (data.message?.content) return { type: 'text', content: data.message.content };\r\n return null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n}\r\n\r\n// ─── Custom Adapter (user-provided send/stream) ──────────────────\r\n\r\nclass CustomAdapter extends BaseAdapter {\r\n constructor(config) {\r\n super(config);\r\n this._sendFn = config.send || null;\r\n this._streamFn = config.stream || null;\r\n }\r\n\r\n /** Custom adapters bypass formatRequest/parseResponse */\r\n get isCustom() { return true; }\r\n}\r\n\r\n// ─── Provider Registry ───────────────────────────────────────────\r\n\r\nconst BUILTIN_ADAPTERS = {\r\n openai: OpenAIAdapter,\r\n anthropic: AnthropicAdapter,\r\n ollama: OllamaAdapter,\r\n};\r\n\r\n// ─── Main Provider Class ─────────────────────────────────────────\r\n\r\nexport class WuAIProvider {\r\n constructor() {\r\n this._providers = new Map();\r\n this._active = null;\r\n this._activeName = null;\r\n this._activeConfig = {};\r\n this._retryConfig = { maxRetries: 3, baseDelayMs: 1000 };\r\n }\r\n\r\n /**\r\n * Register and activate a provider.\r\n *\r\n * @param {string} name - Provider name or built-in adapter ('openai', 'anthropic', 'ollama', 'custom')\r\n * @param {object} config - Provider configuration\r\n * @param {string} [config.endpoint] - API endpoint URL\r\n * @param {string} [config.adapter] - Built-in adapter name (if name is custom)\r\n * @param {string} [config.apiKey] - API key (WARNING: exposed in browser)\r\n * @param {string} [config.model] - Model name\r\n * @param {Function} [config.send] - Custom send function\r\n * @param {Function} [config.stream] - Custom stream generator function\r\n */\r\n register(name, config = {}) {\r\n const adapterName = config.adapter || name;\r\n const AdapterClass = BUILTIN_ADAPTERS[adapterName];\r\n\r\n let adapter;\r\n if (config.send || config.stream) {\r\n adapter = new CustomAdapter(config);\r\n } else if (AdapterClass) {\r\n adapter = new AdapterClass(config);\r\n } else {\r\n throw new Error(\r\n `[wu-ai] Unknown adapter '${adapterName}'. ` +\r\n `Available: ${Object.keys(BUILTIN_ADAPTERS).join(', ')}, or provide custom send/stream.`\r\n );\r\n }\r\n\r\n this._providers.set(name, { adapter, config });\r\n\r\n // Auto-activate if first provider or explicitly active\r\n if (!this._active || config.active !== false) {\r\n this._active = adapter;\r\n this._activeName = name;\r\n this._activeConfig = config;\r\n }\r\n\r\n logger.wuInfo(`[wu-ai] Provider registered: '${name}' (adapter: ${adapterName})`);\r\n }\r\n\r\n /**\r\n * Switch active provider.\r\n */\r\n use(name) {\r\n const entry = this._providers.get(name);\r\n if (!entry) throw new Error(`[wu-ai] Provider '${name}' not registered`);\r\n this._active = entry.adapter;\r\n this._activeName = name;\r\n this._activeConfig = entry.config;\r\n }\r\n\r\n /**\r\n * Send a non-streaming request.\r\n *\r\n * @param {Array} messages - Normalized messages\r\n * @param {object} [options] - { tools, temperature, maxTokens, signal }\r\n * @returns {Promise<{ content: string, tool_calls?: Array, usage?: object }>}\r\n */\r\n async send(messages, options = {}) {\r\n const { adapter, config } = this._resolveProvider(options.provider);\r\n\r\n // Custom adapter: call user function directly\r\n if (adapter.isCustom && adapter._sendFn) {\r\n return adapter._sendFn(messages, options);\r\n }\r\n\r\n const endpoint = config.endpoint || config.baseUrl;\r\n if (!endpoint) {\r\n throw new Error('[wu-ai] No endpoint configured. Set config.endpoint or config.baseUrl.');\r\n }\r\n\r\n const url = this._resolveUrl(endpoint);\r\n const body = adapter.formatRequest(messages, { ...options, stream: false });\r\n const headers = adapter.getHeaders(config);\r\n\r\n const response = await this._fetchWithRetry(url, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify(body),\r\n signal: options.signal,\r\n });\r\n\r\n const data = await response.json();\r\n const result = adapter.parseResponse(data);\r\n\r\n // Anthropic prefill compensation: we prepended '{' to force JSON,\r\n // so the response content is the continuation — restore the full JSON\r\n if (adapter instanceof AnthropicAdapter && options.responseFormat && result.content) {\r\n result.content = '{' + result.content;\r\n }\r\n\r\n // Validate JSON when responseFormat was requested\r\n if (options.responseFormat && result.content) {\r\n try {\r\n result.parsed = JSON.parse(result.content);\r\n } catch {\r\n result.parseError = 'Response is not valid JSON';\r\n logger.wuDebug('[wu-ai] responseFormat requested but LLM returned invalid JSON');\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Send a streaming request. Returns an async generator of chunks.\r\n *\r\n * @param {Array} messages - Normalized messages\r\n * @param {object} [options] - { tools, temperature, maxTokens, signal }\r\n * @yields {StreamChunk}\r\n */\r\n async *stream(messages, options = {}) {\r\n const { adapter, config } = this._resolveProvider(options.provider);\r\n\r\n // Custom adapter: call user generator directly\r\n if (adapter.isCustom && adapter._streamFn) {\r\n yield* adapter._streamFn(messages, options);\r\n return;\r\n }\r\n\r\n const endpoint = config.endpoint || config.baseUrl;\r\n if (!endpoint) {\r\n throw new Error('[wu-ai] No endpoint configured. Set config.endpoint or config.baseUrl.');\r\n }\r\n\r\n const url = this._resolveUrl(endpoint);\r\n const body = adapter.formatRequest(messages, { ...options, stream: true });\r\n const headers = adapter.getHeaders(config);\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify(body),\r\n signal: options.signal,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`[wu-ai] Stream request failed: ${response.status} ${response.statusText}`);\r\n }\r\n\r\n const reader = response.body.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = '';\r\n\r\n // Anthropic prefill compensation for streaming:\r\n // emit the '{' we used as prefill before the first real chunk\r\n let needsPrefill = adapter instanceof AnthropicAdapter && !!options.responseFormat;\r\n\r\n try {\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n\r\n buffer += decoder.decode(value, { stream: true });\r\n const lines = buffer.split('\\n');\r\n buffer = lines.pop() || ''; // keep incomplete last line\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed) continue;\r\n\r\n const chunk = adapter.parseStreamChunk(trimmed);\r\n if (chunk) {\r\n if (needsPrefill && chunk.type === 'text') {\r\n chunk.content = '{' + chunk.content;\r\n needsPrefill = false;\r\n }\r\n yield chunk;\r\n }\r\n if (chunk?.type === 'done') return;\r\n }\r\n }\r\n\r\n // Process remaining buffer\r\n if (buffer.trim()) {\r\n const chunk = adapter.parseStreamChunk(buffer.trim());\r\n if (chunk) yield chunk;\r\n }\r\n } finally {\r\n reader.releaseLock();\r\n }\r\n }\r\n\r\n // ── Retry logic ──\r\n\r\n async _fetchWithRetry(url, options) {\r\n let lastError;\r\n for (let attempt = 0; attempt <= this._retryConfig.maxRetries; attempt++) {\r\n try {\r\n const response = await fetch(url, options);\r\n\r\n // Only retry on 429 (rate limit) and 5xx\r\n if (response.ok) return response;\r\n\r\n if (response.status === 429 || response.status >= 500) {\r\n lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n if (attempt < this._retryConfig.maxRetries) {\r\n const delay = this._retryConfig.baseDelayMs * Math.pow(2, attempt);\r\n logger.wuDebug(`[wu-ai] Retry ${attempt + 1}/${this._retryConfig.maxRetries} in ${delay}ms (${response.status})`);\r\n await new Promise(r => setTimeout(r, delay));\r\n continue;\r\n }\r\n }\r\n\r\n // 4xx (except 429) — don't retry, fail immediately\r\n const clientError = new Error(`[wu-ai] Request failed: ${response.status} ${response.statusText}`);\r\n clientError._noRetry = true;\r\n throw clientError;\r\n } catch (err) {\r\n if (err.name === 'AbortError') throw err;\r\n if (err._noRetry) throw err; // 4xx — don't retry\r\n lastError = err;\r\n if (attempt < this._retryConfig.maxRetries) {\r\n const delay = this._retryConfig.baseDelayMs * Math.pow(2, attempt);\r\n await new Promise(r => setTimeout(r, delay));\r\n continue;\r\n }\r\n }\r\n }\r\n throw lastError;\r\n }\r\n\r\n // ── Helpers ──\r\n\r\n _resolveUrl(endpoint) {\r\n // Relative URLs (e.g., '/api/ai/chat') resolve against current origin\r\n if (endpoint.startsWith('/')) {\r\n return typeof window !== 'undefined'\r\n ? `${window.location.origin}${endpoint}`\r\n : endpoint;\r\n }\r\n return endpoint;\r\n }\r\n\r\n /**\r\n * Resolve which provider/adapter to use for a request.\r\n * Supports per-call selection: options.provider = 'anthropic'\r\n *\r\n * @param {string} [providerName] - Optional provider name override\r\n * @returns {{ adapter: BaseAdapter, config: object }}\r\n */\r\n _resolveProvider(providerName) {\r\n if (providerName) {\r\n const entry = this._providers.get(providerName);\r\n if (!entry) {\r\n throw new Error(`[wu-ai] Provider '${providerName}' not registered. Available: ${[...this._providers.keys()].join(', ')}`);\r\n }\r\n return { adapter: entry.adapter, config: entry.config };\r\n }\r\n this._ensureActive();\r\n return { adapter: this._active, config: this._activeConfig };\r\n }\r\n\r\n _ensureActive() {\r\n if (!this._active) {\r\n throw new Error(\r\n '[wu-ai] No provider configured. Call wu.ai.provider(\"name\", { endpoint, adapter }) first.'\r\n );\r\n }\r\n }\r\n\r\n configureRetry(config) {\r\n if (config.maxRetries !== undefined) this._retryConfig.maxRetries = config.maxRetries;\r\n if (config.baseDelayMs !== undefined) this._retryConfig.baseDelayMs = config.baseDelayMs;\r\n }\r\n\r\n getActiveProvider() {\r\n return this._activeName;\r\n }\r\n\r\n getStats() {\r\n return {\r\n activeProvider: this._activeName,\r\n registeredProviders: [...this._providers.keys()],\r\n };\r\n }\r\n}\r\n","/**\r\n * WU-AI-PERMISSIONS: Security, rate limiting, circuit breaker, loop protection\r\n *\r\n * 4-layer defense:\r\n * 1. Permission flags (readStore, writeStore, emitEvents, etc.)\r\n * 2. Rate limiting (per-minute, per-namespace, concurrent)\r\n * 3. Circuit breaker (CLOSED → OPEN → HALF-OPEN)\r\n * 4. Loop protection (depth counter + causal chain tracking)\r\n */\r\n\r\nimport { logger } from '../core/wu-logger.js';\r\n\r\n// ─── Permission Defaults ─────────────────────────────────────────\r\n\r\nconst DEFAULT_PERMISSIONS = {\r\n readStore: true,\r\n writeStore: false,\r\n emitEvents: true,\r\n readDOM: false,\r\n modifyDOM: false,\r\n executeActions: true,\r\n allowDirectKey: false,\r\n};\r\n\r\n// ─── Circuit Breaker States ──────────────────────────────────────\r\n\r\nconst CB_CLOSED = 'closed';\r\nconst CB_OPEN = 'open';\r\nconst CB_HALF_OPEN = 'half-open';\r\n\r\n// ─── Rate Limiter ────────────────────────────────────────────────\r\n\r\nclass RateLimiter {\r\n constructor(config = {}) {\r\n this._maxPerMinute = config.requestsPerMinute ?? 20;\r\n this._maxPerMinutePerNs = config.requestsPerMinutePerNs ?? 10;\r\n this._maxConcurrent = config.maxConcurrent ?? 3;\r\n\r\n this._globalTimestamps = [];\r\n this._nsTimestamps = new Map();\r\n this._concurrent = 0;\r\n }\r\n\r\n configure(config) {\r\n if (config.requestsPerMinute !== undefined) this._maxPerMinute = config.requestsPerMinute;\r\n if (config.requestsPerMinutePerNs !== undefined) this._maxPerMinutePerNs = config.requestsPerMinutePerNs;\r\n if (config.maxConcurrent !== undefined) this._maxConcurrent = config.maxConcurrent;\r\n }\r\n\r\n canSend(namespace = 'default') {\r\n this._pruneOld();\r\n\r\n if (this._concurrent >= this._maxConcurrent) {\r\n return { allowed: false, reason: `Max concurrent (${this._maxConcurrent}) reached` };\r\n }\r\n if (this._globalTimestamps.length >= this._maxPerMinute) {\r\n return { allowed: false, reason: `Global rate limit (${this._maxPerMinute}/min) exceeded` };\r\n }\r\n\r\n const nsTs = this._nsTimestamps.get(namespace) || [];\r\n if (nsTs.length >= this._maxPerMinutePerNs) {\r\n return { allowed: false, reason: `Namespace '${namespace}' rate limit (${this._maxPerMinutePerNs}/min) exceeded` };\r\n }\r\n\r\n return { allowed: true };\r\n }\r\n\r\n recordStart(namespace = 'default') {\r\n const now = Date.now();\r\n this._globalTimestamps.push(now);\r\n if (!this._nsTimestamps.has(namespace)) this._nsTimestamps.set(namespace, []);\r\n this._nsTimestamps.get(namespace).push(now);\r\n this._concurrent++;\r\n }\r\n\r\n recordEnd() {\r\n this._concurrent = Math.max(0, this._concurrent - 1);\r\n }\r\n\r\n _pruneOld() {\r\n const cutoff = Date.now() - 60000;\r\n this._globalTimestamps = this._globalTimestamps.filter(t => t > cutoff);\r\n for (const [ns, timestamps] of this._nsTimestamps) {\r\n const pruned = timestamps.filter(t => t > cutoff);\r\n if (pruned.length === 0) this._nsTimestamps.delete(ns);\r\n else this._nsTimestamps.set(ns, pruned);\r\n }\r\n }\r\n\r\n getStats() {\r\n this._pruneOld();\r\n return {\r\n globalRequestsLastMinute: this._globalTimestamps.length,\r\n concurrent: this._concurrent,\r\n maxPerMinute: this._maxPerMinute,\r\n maxConcurrent: this._maxConcurrent,\r\n };\r\n }\r\n}\r\n\r\n// ─── Circuit Breaker ─────────────────────────────────────────────\r\n\r\nclass CircuitBreaker {\r\n constructor(config = {}) {\r\n this._state = CB_CLOSED;\r\n this._failureCount = 0;\r\n this._maxFailures = config.maxFailures ?? 3;\r\n this._cooldownMs = config.cooldownMs ?? 30000;\r\n this._openedAt = 0;\r\n this._rapidFireThreshold = config.rapidFireThreshold ?? 5;\r\n this._rapidFireWindowMs = config.rapidFireWindowMs ?? 2000;\r\n this._recentRequests = [];\r\n }\r\n\r\n configure(config) {\r\n if (config.maxFailures !== undefined) this._maxFailures = config.maxFailures;\r\n if (config.cooldownMs !== undefined) this._cooldownMs = config.cooldownMs;\r\n }\r\n\r\n canPass() {\r\n if (this._state === CB_CLOSED) return { allowed: true };\r\n\r\n if (this._state === CB_OPEN) {\r\n if (Date.now() - this._openedAt >= this._cooldownMs) {\r\n this._state = CB_HALF_OPEN;\r\n logger.wuDebug('[wu-ai] Circuit breaker → HALF-OPEN (testing)');\r\n return { allowed: true };\r\n }\r\n const remainingMs = this._cooldownMs - (Date.now() - this._openedAt);\r\n return { allowed: false, reason: `Circuit breaker OPEN (${Math.ceil(remainingMs / 1000)}s remaining)` };\r\n }\r\n\r\n // HALF-OPEN: allow one request through\r\n return { allowed: true };\r\n }\r\n\r\n recordSuccess() {\r\n if (this._state === CB_HALF_OPEN) {\r\n this._state = CB_CLOSED;\r\n this._failureCount = 0;\r\n logger.wuInfo('[wu-ai] Circuit breaker → CLOSED (recovered)');\r\n } else {\r\n this._failureCount = 0;\r\n }\r\n this._recordRequest();\r\n }\r\n\r\n recordFailure() {\r\n this._failureCount++;\r\n this._recordRequest();\r\n\r\n if (this._state === CB_HALF_OPEN) {\r\n this._tripOpen('Failed during half-open test');\r\n return;\r\n }\r\n\r\n if (this._failureCount >= this._maxFailures) {\r\n this._tripOpen(`${this._failureCount} consecutive failures`);\r\n }\r\n }\r\n\r\n _recordRequest() {\r\n const now = Date.now();\r\n this._recentRequests.push(now);\r\n this._recentRequests = this._recentRequests.filter(t => now - t < this._rapidFireWindowMs);\r\n\r\n if (this._state === CB_CLOSED && this._recentRequests.length >= this._rapidFireThreshold) {\r\n this._tripOpen(`${this._recentRequests.length} requests in ${this._rapidFireWindowMs}ms (rapid fire)`);\r\n }\r\n }\r\n\r\n _tripOpen(reason) {\r\n this._state = CB_OPEN;\r\n this._openedAt = Date.now();\r\n logger.wuWarn(`[wu-ai] Circuit breaker → OPEN: ${reason}. Cooldown: ${this._cooldownMs / 1000}s`);\r\n }\r\n\r\n getState() {\r\n return this._state;\r\n }\r\n\r\n getStats() {\r\n return {\r\n state: this._state,\r\n failureCount: this._failureCount,\r\n maxFailures: this._maxFailures,\r\n cooldownMs: this._cooldownMs,\r\n openedAt: this._openedAt,\r\n };\r\n }\r\n\r\n reset() {\r\n this._state = CB_CLOSED;\r\n this._failureCount = 0;\r\n this._openedAt = 0;\r\n this._recentRequests = [];\r\n }\r\n}\r\n\r\n// ─── Loop Protection ─────────────────────────────────────────────\r\n\r\nclass LoopProtection {\r\n constructor(config = {}) {\r\n this._maxDepth = config.maxDepth ?? 3;\r\n this._activeTraces = new Map(); // traceId → count\r\n this._traceLog = []; // last N traces for debugging\r\n this._maxTraceLog = 50;\r\n }\r\n\r\n configure(config) {\r\n if (config.maxDepth !== undefined) this._maxDepth = config.maxDepth;\r\n }\r\n\r\n /**\r\n * Check if a request at the given depth/trace is allowed.\r\n * @param {number} depth - Current AI depth\r\n * @param {string} traceId - Causal chain trace ID\r\n * @returns {{ allowed: boolean, reason?: string }}\r\n */\r\n canProceed(depth, traceId) {\r\n if (depth > this._maxDepth) {\r\n return { allowed: false, reason: `Max AI depth (${this._maxDepth}) exceeded at depth ${depth}` };\r\n }\r\n\r\n if (traceId) {\r\n const count = (this._activeTraces.get(traceId) || 0) + 1;\r\n if (count > this._maxDepth) {\r\n return { allowed: false, reason: `Causal chain '${traceId}' looped ${count} times (max ${this._maxDepth})` };\r\n }\r\n }\r\n\r\n return { allowed: true };\r\n }\r\n\r\n /**\r\n * Record that a trace is being processed.\r\n */\r\n enter(traceId) {\r\n if (!traceId) return;\r\n const count = (this._activeTraces.get(traceId) || 0) + 1;\r\n this._activeTraces.set(traceId, count);\r\n\r\n this._traceLog.push({ traceId, count, timestamp: Date.now() });\r\n if (this._traceLog.length > this._maxTraceLog) {\r\n this._traceLog.shift();\r\n }\r\n }\r\n\r\n /**\r\n * Record that a trace finished processing.\r\n */\r\n exit(traceId) {\r\n if (!traceId) return;\r\n const count = (this._activeTraces.get(traceId) || 0) - 1;\r\n if (count <= 0) this._activeTraces.delete(traceId);\r\n else this._activeTraces.set(traceId, count);\r\n }\r\n\r\n /**\r\n * Generate a new trace ID.\r\n */\r\n createTraceId() {\r\n return `t_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;\r\n }\r\n\r\n getTraces() {\r\n return [...this._traceLog];\r\n }\r\n\r\n getStats() {\r\n return {\r\n maxDepth: this._maxDepth,\r\n activeTraces: this._activeTraces.size,\r\n traceLogSize: this._traceLog.length,\r\n };\r\n }\r\n}\r\n\r\n// ─── Main Permissions Class ──────────────────────────────────────\r\n\r\nexport class WuAIPermissions {\r\n constructor(config = {}) {\r\n this._permissions = { ...DEFAULT_PERMISSIONS };\r\n this.rateLimiter = new RateLimiter(config.rateLimit);\r\n this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);\r\n this.loopProtection = new LoopProtection(config.loopProtection);\r\n this._allowedDomains = config.allowedDomains || [];\r\n\r\n if (config.permissions) {\r\n this.configure(config.permissions);\r\n }\r\n }\r\n\r\n // ── Permission checks ──\r\n\r\n configure(permissions) {\r\n Object.assign(this._permissions, permissions);\r\n\r\n // HARD BLOCK: never allow direct API key in production\r\n if (this._isProduction() && this._permissions.allowDirectKey) {\r\n logger.wuWarn('[wu-ai] allowDirectKey FORCED to false in production');\r\n this._permissions.allowDirectKey = false;\r\n }\r\n }\r\n\r\n check(permission) {\r\n return this._permissions[permission] === true;\r\n }\r\n\r\n getPermissions() {\r\n return { ...this._permissions };\r\n }\r\n\r\n // ── Domain whitelist for action fetch ──\r\n\r\n setAllowedDomains(domains) {\r\n this._allowedDomains = domains;\r\n }\r\n\r\n isDomainAllowed(url) {\r\n if (this._allowedDomains.length === 0) return true;\r\n try {\r\n const hostname = new URL(url).hostname;\r\n return this._allowedDomains.some(pattern => {\r\n if (pattern.startsWith('*.')) {\r\n const suffix = pattern.slice(2);\r\n return hostname === suffix || hostname.endsWith('.' + suffix);\r\n }\r\n return hostname === pattern;\r\n });\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n // ── Full pre-flight check ──\r\n\r\n /**\r\n * Run all checks before sending an AI request.\r\n * @param {{ namespace?: string, depth?: number, traceId?: string }} meta\r\n * @returns {{ allowed: boolean, reason?: string }}\r\n */\r\n preflight(meta = {}) {\r\n // 1. Circuit breaker\r\n const cb = this.circuitBreaker.canPass();\r\n if (!cb.allowed) return cb;\r\n\r\n // 2. Rate limiter\r\n const rl = this.rateLimiter.canSend(meta.namespace);\r\n if (!rl.allowed) return rl;\r\n\r\n // 3. Loop protection\r\n const lp = this.loopProtection.canProceed(meta.depth || 0, meta.traceId);\r\n if (!lp.allowed) return lp;\r\n\r\n return { allowed: true };\r\n }\r\n\r\n // ── Stats ──\r\n\r\n getStats() {\r\n return {\r\n permissions: { ...this._permissions },\r\n rateLimiter: this.rateLimiter.getStats(),\r\n circuitBreaker: this.circuitBreaker.getStats(),\r\n loopProtection: this.loopProtection.getStats(),\r\n allowedDomains: [...this._allowedDomains],\r\n };\r\n }\r\n\r\n // ── Private ──\r\n\r\n _isProduction() {\r\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return true;\r\n if (typeof window !== 'undefined') {\r\n const h = window.location?.hostname || '';\r\n return h !== 'localhost' && h !== '127.0.0.1' && h !== '0.0.0.0' && !h.endsWith('.local');\r\n }\r\n return false;\r\n }\r\n}\r\n","/**\r\n * WU-AI-SCHEMA: Tool schema generation for function calling\r\n *\r\n * Converts wu.ai.action() definitions into the canonical tool format\r\n * that providers consume. Also handles input sanitization for prompts.\r\n *\r\n * Canonical tool format:\r\n * { name: string, description: string, parameters: JSONSchema }\r\n */\r\n\r\n// ─── Sanitization ────────────────────────────────────────────────\r\n\r\nconst SENSITIVE_KEYS = ['password', 'token', 'apiKey', 'secret', 'credential', 'authorization', 'cookie', 'session'];\r\n\r\n/**\r\n * Sanitize data before injecting into prompts.\r\n * Prevents prompt injection and redacts sensitive fields.\r\n *\r\n * @param {*} data - Any value to sanitize\r\n * @param {number} [maxChars=2000] - Max chars per value\r\n * @returns {string} Safe string representation\r\n */\r\nexport function sanitizeForPrompt(data, maxChars = 2000) {\r\n if (data === null || data === undefined) return 'null';\r\n if (typeof data === 'function') return '[Function]';\r\n if (typeof data === 'symbol') return '[Symbol]';\r\n\r\n if (typeof data === 'string') {\r\n const truncated = data.length > maxChars ? data.slice(0, maxChars) + '...[truncated]' : data;\r\n return `<user_data>${truncated}</user_data>`;\r\n }\r\n\r\n if (typeof data === 'number' || typeof data === 'boolean') {\r\n return String(data);\r\n }\r\n\r\n if (typeof data === 'object') {\r\n const redacted = redactSensitive(data);\r\n const json = JSON.stringify(redacted);\r\n if (json.length > maxChars) {\r\n return `<user_data>${json.slice(0, maxChars)}...[truncated]</user_data>`;\r\n }\r\n return `<user_data>${json}</user_data>`;\r\n }\r\n\r\n return String(data).slice(0, maxChars);\r\n}\r\n\r\n/**\r\n * Deep-clone an object, replacing sensitive keys with [REDACTED].\r\n *\r\n * @param {*} obj\r\n * @param {number} [depth=0]\r\n * @returns {*}\r\n */\r\nexport function redactSensitive(obj, depth = 0) {\r\n if (depth > 10) return '[MAX_DEPTH]';\r\n if (obj === null || obj === undefined) return obj;\r\n if (typeof obj !== 'object') return obj;\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(item => redactSensitive(item, depth + 1));\r\n }\r\n\r\n const result = {};\r\n for (const [key, value] of Object.entries(obj)) {\r\n const lowerKey = key.toLowerCase();\r\n if (SENSITIVE_KEYS.some(sk => lowerKey.includes(sk.toLowerCase()))) {\r\n result[key] = '[REDACTED]';\r\n } else {\r\n result[key] = redactSensitive(value, depth + 1);\r\n }\r\n }\r\n return result;\r\n}\r\n\r\n// ─── Template Interpolation ──────────────────────────────────────\r\n\r\n/**\r\n * Interpolate {{var}} placeholders in a template string.\r\n * Supports dot-notation: {{data.user.name}}\r\n *\r\n * @param {string} template\r\n * @param {object} vars - Variable map { data: ..., context: ... }\r\n * @returns {string}\r\n */\r\nexport function interpolate(template, vars) {\r\n return template.replace(/\\{\\{(\\w+(?:\\.\\w+)*)\\}\\}/g, (_match, path) => {\r\n const value = path.split('.').reduce((obj, key) => obj?.[key], vars);\r\n if (value === undefined || value === null) return '';\r\n if (typeof value === 'object') return sanitizeForPrompt(value);\r\n return String(value);\r\n });\r\n}\r\n\r\n// ─── Tool Schema Builder ─────────────────────────────────────────\r\n\r\n/**\r\n * Build canonical tool definitions from registered actions.\r\n *\r\n * @param {Map<string, object>} actions - Map of action name → config\r\n * @returns {Array<{ name: string, description: string, parameters: object }>}\r\n */\r\nexport function buildToolSchemas(actions) {\r\n const tools = [];\r\n\r\n for (const [name, config] of actions) {\r\n tools.push({\r\n name,\r\n description: config.description || `Execute action: ${name}`,\r\n parameters: normalizeParameters(config.parameters),\r\n });\r\n }\r\n\r\n return tools;\r\n}\r\n\r\n/**\r\n * Normalize user-provided parameter definitions into JSON Schema.\r\n *\r\n * Accepts two formats:\r\n * 1. Full JSON Schema: { type: 'object', properties: {...}, required: [...] }\r\n * 2. Shorthand: { message: { type: 'string', required: true }, count: { type: 'number' } }\r\n *\r\n * @param {object} params\r\n * @returns {object} Valid JSON Schema\r\n */\r\nexport function normalizeParameters(params) {\r\n if (!params || typeof params !== 'object') {\r\n return { type: 'object', properties: {}, required: [] };\r\n }\r\n\r\n // Already a JSON Schema\r\n if (params.type === 'object' && params.properties) {\r\n return params;\r\n }\r\n\r\n // Shorthand format — convert\r\n const properties = {};\r\n const required = [];\r\n\r\n for (const [key, def] of Object.entries(params)) {\r\n if (typeof def === 'string') {\r\n // Simplest: { message: 'string' }\r\n properties[key] = { type: def };\r\n } else if (typeof def === 'object') {\r\n const { required: isRequired, ...rest } = def;\r\n properties[key] = rest.type ? rest : { type: 'string', ...rest };\r\n if (isRequired) required.push(key);\r\n }\r\n }\r\n\r\n return { type: 'object', properties, required };\r\n}\r\n\r\n/**\r\n * Validate params against a JSON Schema (lightweight, no external deps).\r\n * Only checks type, required, and enum — not full JSON Schema validation.\r\n *\r\n * @param {object} params - Actual params from LLM\r\n * @param {object} schema - JSON Schema from normalizeParameters()\r\n * @returns {{ valid: boolean, errors: string[] }}\r\n */\r\nexport function validateParams(params, schema) {\r\n const errors = [];\r\n if (!schema || !schema.properties) return { valid: true, errors };\r\n\r\n // Check required\r\n for (const key of (schema.required || [])) {\r\n if (params[key] === undefined || params[key] === null) {\r\n errors.push(`'${key}' is required`);\r\n }\r\n }\r\n\r\n // Check types and enums\r\n for (const [key, def] of Object.entries(schema.properties)) {\r\n const value = params[key];\r\n if (value === undefined || value === null) continue;\r\n\r\n if (def.type && def.type !== 'any') {\r\n const actualType = Array.isArray(value) ? 'array' : typeof value;\r\n if (def.type === 'integer') {\r\n if (typeof value !== 'number' || !Number.isInteger(value)) {\r\n errors.push(`'${key}' must be integer, got ${actualType}`);\r\n }\r\n } else if (def.type !== actualType) {\r\n errors.push(`'${key}' must be ${def.type}, got ${actualType}`);\r\n }\r\n }\r\n\r\n if (def.enum && !def.enum.includes(value)) {\r\n errors.push(`'${key}' must be one of [${def.enum.join(', ')}], got '${value}'`);\r\n }\r\n }\r\n\r\n return { valid: errors.length === 0, errors };\r\n}\r\n\r\n// ─── Context Budget ──────────────────────────────────────────────\r\n\r\n/**\r\n * Estimate token count from character count.\r\n * Rough heuristic: 1 token ≈ 4 chars for English, ≈ 2 chars for CJK.\r\n *\r\n * @param {string} text\r\n * @param {number} [charRatio=4]\r\n * @returns {number}\r\n */\r\nexport function estimateTokens(text, charRatio = 4) {\r\n return Math.ceil(text.length / charRatio);\r\n}\r\n\r\n/**\r\n * Truncate text to fit within a token budget.\r\n *\r\n * @param {string} text\r\n * @param {number} maxTokens\r\n * @param {number} [charRatio=4]\r\n * @returns {string}\r\n */\r\nexport function truncateToTokenBudget(text, maxTokens, charRatio = 4) {\r\n const maxChars = maxTokens * charRatio;\r\n if (text.length <= maxChars) return text;\r\n return text.slice(0, maxChars) + '\\n...[truncated to fit token budget]';\r\n}\r\n","/**\r\n * WU-AI-CONTEXT: Automatic context collector for LLMs\r\n *\r\n * Collects state from wu.store, wu.eventBus, and registered apps.\r\n * Builds a structured context object and system prompt for the LLM.\r\n *\r\n * Key design:\r\n * - ON-DEMAND collection (no polling, zero CPU idle)\r\n * - Token budget with priority (high > medium > low)\r\n * - Sensitive data redaction\r\n * - System prompt generation\r\n */\r\n\r\nimport { logger } from '../core/wu-logger.js';\r\nimport { redactSensitive, estimateTokens, truncateToTokenBudget } from './wu-ai-schema.js';\r\n\r\n// ─── Context Source Config ───────────────────────────────────────\r\n//\r\n// store: { include: ['user.*', 'cart.*'], priority: 'high' }\r\n// events: { include: ['cart:*', 'user:*'], lastN: 10, priority: 'medium' }\r\n// custom: [{ key: 'appVersion', value: () => '1.0', priority: 'low' }]\r\n\r\nexport class WuAIContext {\r\n constructor({ store, eventBus, core }) {\r\n this._store = store;\r\n this._eventBus = eventBus;\r\n this._core = core;\r\n\r\n this._config = {\r\n budget: 4000, // token budget\r\n charRatio: 4, // chars per token estimate\r\n sources: {\r\n store: { include: [], priority: 'high' },\r\n events: { include: [], lastN: 10, priority: 'medium' },\r\n custom: [],\r\n },\r\n };\r\n\r\n this._collectors = new Map(); // name → { collector, priority }\r\n this._lastSnapshot = null;\r\n }\r\n\r\n /**\r\n * Configure context collection.\r\n */\r\n configure(config) {\r\n if (config.budget !== undefined) this._config.budget = config.budget;\r\n if (config.charRatio !== undefined) this._config.charRatio = config.charRatio;\r\n if (config.sources) {\r\n if (config.sources.store) Object.assign(this._config.sources.store, config.sources.store);\r\n if (config.sources.events) Object.assign(this._config.sources.events, config.sources.events);\r\n if (config.sources.custom) this._config.sources.custom = config.sources.custom;\r\n }\r\n }\r\n\r\n /**\r\n * Register a named context collector.\r\n *\r\n * @param {string} name - Collector name (e.g., 'dashboard', 'analytics')\r\n * @param {{ collector: Function, priority?: string }} config\r\n */\r\n register(name, config) {\r\n this._collectors.set(name, {\r\n collector: config.collector,\r\n priority: config.priority || 'medium',\r\n });\r\n logger.wuDebug(`[wu-ai] Context collector registered: '${name}' (${config.priority || 'medium'})`);\r\n }\r\n\r\n /**\r\n * Collect all context ON-DEMAND.\r\n * Called before sending a message to the LLM.\r\n *\r\n * @returns {object} Context snapshot\r\n */\r\n async collect() {\r\n const snapshot = {\r\n _timestamp: Date.now(),\r\n _mountedApps: this._getMountedApps(),\r\n };\r\n\r\n // Collect store sources\r\n const storeData = this._collectStore();\r\n if (storeData && Object.keys(storeData).length > 0) {\r\n snapshot._store = storeData;\r\n }\r\n\r\n // Collect recent events\r\n const events = this._collectEvents();\r\n if (events.length > 0) {\r\n snapshot._events = events;\r\n }\r\n\r\n // Collect custom sources\r\n for (const custom of this._config.sources.custom) {\r\n try {\r\n const value = typeof custom.value === 'function' ? await custom.value() : custom.value;\r\n snapshot[custom.key] = value;\r\n } catch (err) {\r\n logger.wuDebug(`[wu-ai] Custom collector '${custom.key}' failed: ${err.message}`);\r\n }\r\n }\r\n\r\n // Collect registered collectors\r\n for (const [name, config] of this._collectors) {\r\n try {\r\n const data = await config.collector();\r\n snapshot[name] = data;\r\n } catch (err) {\r\n logger.wuDebug(`[wu-ai] Collector '${name}' failed: ${err.message}`);\r\n }\r\n }\r\n\r\n this._lastSnapshot = snapshot;\r\n return snapshot;\r\n }\r\n\r\n /**\r\n * Build a system prompt from the context for the LLM.\r\n *\r\n * @param {{ tools?: Array }} [options] - Available tools to include\r\n * @returns {string} System prompt\r\n */\r\n toSystemPrompt(options = {}) {\r\n const snapshot = this._lastSnapshot;\r\n if (!snapshot) return this._baseSystemPrompt(options);\r\n\r\n const parts = [];\r\n\r\n // Base instruction\r\n parts.push(\r\n 'You are an AI assistant connected to a live web application via Wu Framework.',\r\n 'You can observe application state and execute actions when appropriate.',\r\n ''\r\n );\r\n\r\n // Mounted apps (always included)\r\n if (snapshot._mountedApps?.length) {\r\n parts.push(`MOUNTED APPS: ${snapshot._mountedApps.join(', ')}`, '');\r\n }\r\n\r\n // Budget tracking\r\n const budget = this._config.budget;\r\n const charBudget = budget * this._config.charRatio;\r\n let usedChars = parts.join('\\n').length;\r\n\r\n // Priority-based inclusion\r\n const prioritized = this._prioritizeSections(snapshot);\r\n\r\n for (const section of prioritized) {\r\n const sectionText = section.text;\r\n if (usedChars + sectionText.length > charBudget) {\r\n // Try to truncate if high priority\r\n if (section.priority === 'high') {\r\n const remaining = charBudget - usedChars;\r\n if (remaining > 100) {\r\n parts.push(sectionText.slice(0, remaining) + '\\n...[truncated]');\r\n usedChars += remaining;\r\n }\r\n }\r\n continue; // skip if over budget\r\n }\r\n parts.push(sectionText);\r\n usedChars += sectionText.length;\r\n }\r\n\r\n // Tools (outside budget — LLM needs these)\r\n if (options.tools?.length) {\r\n parts.push('', 'AVAILABLE TOOLS:');\r\n for (const tool of options.tools) {\r\n parts.push(`- ${tool.name}: ${tool.description}`);\r\n }\r\n }\r\n\r\n return parts.join('\\n');\r\n }\r\n\r\n /**\r\n * Get the last collected snapshot.\r\n */\r\n getSnapshot() {\r\n return this._lastSnapshot;\r\n }\r\n\r\n /**\r\n * Get a simplified context object for template interpolation.\r\n */\r\n getInterpolationContext() {\r\n if (!this._lastSnapshot) return {};\r\n const { _timestamp, _mountedApps, _store, _events, ...custom } = this._lastSnapshot;\r\n return {\r\n apps: _mountedApps,\r\n store: _store,\r\n events: _events,\r\n ...custom,\r\n };\r\n }\r\n\r\n // ── Private: Data Collection ──\r\n\r\n _collectStore() {\r\n if (!this._store) return {};\r\n const { include } = this._config.sources.store;\r\n if (!include || include.length === 0) return {};\r\n\r\n const data = {};\r\n for (const path of include) {\r\n try {\r\n const value = this._store.get(path);\r\n if (value !== undefined) {\r\n data[path] = redactSensitive(value);\r\n }\r\n } catch {\r\n // Path doesn't exist, skip\r\n }\r\n }\r\n return data;\r\n }\r\n\r\n _collectEvents() {\r\n if (!this._eventBus) return [];\r\n const { include, lastN } = this._config.sources.events;\r\n if (!include || include.length === 0) return [];\r\n\r\n const history = this._eventBus.history || [];\r\n const matching = history.filter(event => {\r\n return include.some(pattern => this._matchPattern(event.name || event.event, pattern));\r\n });\r\n\r\n return matching.slice(-(lastN || 10)).map(e => ({\r\n event: e.name || e.event,\r\n data: redactSensitive(e.data),\r\n timestamp: e.timestamp,\r\n }));\r\n }\r\n\r\n _getMountedApps() {\r\n if (!this._core) return [];\r\n try {\r\n // WuCore exposes mounted as Map or getStats()\r\n if (this._core.mounted instanceof Map) {\r\n return [...this._core.mounted.keys()];\r\n }\r\n const stats = this._core.getStats?.();\r\n return stats?.apps || stats?.mounted || [];\r\n } catch {\r\n return [];\r\n }\r\n }\r\n\r\n // ── Private: Priority & Budget ──\r\n\r\n _prioritizeSections(snapshot) {\r\n const sections = [];\r\n const storePriority = this._config.sources.store.priority || 'high';\r\n const eventPriority = this._config.sources.events.priority || 'medium';\r\n\r\n // Store snapshot\r\n if (snapshot._store && Object.keys(snapshot._store).length > 0) {\r\n sections.push({\r\n priority: storePriority,\r\n text: `APPLICATION STATE:\\n${JSON.stringify(snapshot._store, null, 2)}`,\r\n });\r\n }\r\n\r\n // Recent events\r\n if (snapshot._events?.length) {\r\n const eventLines = snapshot._events.map(e =>\r\n ` [${e.event}] ${JSON.stringify(e.data)}`\r\n ).join('\\n');\r\n sections.push({\r\n priority: eventPriority,\r\n text: `RECENT EVENTS:\\n${eventLines}`,\r\n });\r\n }\r\n\r\n // Custom collectors\r\n for (const [name, config] of this._collectors) {\r\n if (snapshot[name] !== undefined) {\r\n sections.push({\r\n priority: config.priority,\r\n text: `${name.toUpperCase()}:\\n${JSON.stringify(snapshot[name], null, 2)}`,\r\n });\r\n }\r\n }\r\n\r\n // Custom sources\r\n for (const custom of this._config.sources.custom) {\r\n if (snapshot[custom.key] !== undefined) {\r\n sections.push({\r\n priority: custom.priority || 'low',\r\n text: `${custom.key}: ${JSON.stringify(snapshot[custom.key])}`,\r\n });\r\n }\r\n }\r\n\r\n // Sort: high → medium → low\r\n const order = { high: 0, medium: 1, low: 2 };\r\n sections.sort((a, b) => (order[a.priority] ?? 1) - (order[b.priority] ?? 1));\r\n\r\n return sections;\r\n }\r\n\r\n _baseSystemPrompt(options = {}) {\r\n let prompt = 'You are an AI assistant connected to a web application via Wu Framework.';\r\n if (options.tools?.length) {\r\n prompt += '\\n\\nAVAILABLE TOOLS:\\n' + options.tools.map(t => `- ${t.name}: ${t.description}`).join('\\n');\r\n }\r\n return prompt;\r\n }\r\n\r\n // ── Pattern Matching (reuse wu-framework convention) ──\r\n\r\n _matchPattern(eventName, pattern) {\r\n if (!eventName || !pattern) return false;\r\n if (pattern === '*') return true;\r\n if (!pattern.includes('*')) return eventName === pattern;\r\n\r\n const regex = new RegExp('^' + pattern.replace(/\\*/g, '[^:]*') + '$');\r\n return regex.test(eventName);\r\n }\r\n\r\n getStats() {\r\n return {\r\n budget: this._config.budget,\r\n collectors: [...this._collectors.keys()],\r\n storePaths: this._config.sources.store.include,\r\n eventPatterns: this._config.sources.events.include,\r\n lastCollected: this._lastSnapshot?._timestamp || null,\r\n };\r\n }\r\n}\r\n","/**\r\n * WU-AI-ACTIONS: Action registry and executor\r\n *\r\n * Actions are capabilities that the LLM can invoke via tool_use / function_call.\r\n * Each action has:\r\n * - A handler function (sandboxed API, not raw wu access)\r\n * - JSON Schema parameters\r\n * - Permission requirements\r\n * - Optional confirmation flow\r\n *\r\n * Security: Actions receive a sandboxed API, not the full wu object.\r\n * The LLM cannot do anything the developer didn't explicitly expose.\r\n */\r\n\r\nimport { logger } from '../core/wu-logger.js';\r\nimport { validateParams, normalizeParameters, buildToolSchemas } from './wu-ai-schema.js';\r\n\r\nexport class WuAIActions {\r\n constructor({ eventBus, store, permissions }) {\r\n this._eventBus = eventBus;\r\n this._store = store;\r\n this._permissions = permissions;\r\n this._actions = new Map();\r\n this._executionLog = [];\r\n this._maxLogSize = 100;\r\n this._pendingConfirms = new Map(); // callId → { resolve, reject, timeout }\r\n }\r\n\r\n /**\r\n * Register an action that the LLM can invoke.\r\n *\r\n * @param {string} name - Action name (used in tool_call)\r\n * @param {object} config\r\n * @param {string} config.description - Human-readable description (sent to LLM)\r\n * @param {object} [config.parameters] - JSON Schema or shorthand for params\r\n * @param {Function} config.handler - async (params, sandboxedApi) => result\r\n * @param {boolean} [config.confirm=false] - Require user confirmation before executing\r\n * @param {string[]} [config.permissions=[]] - Required permission flags\r\n * @param {boolean} [config.dangerous=false] - Mark as dangerous in logs\r\n */\r\n register(name, config) {\r\n if (!config.handler || typeof config.handler !== 'function') {\r\n throw new Error(`[wu-ai] Action '${name}' must have a handler function`);\r\n }\r\n\r\n this._actions.set(name, {\r\n description: config.description || `Execute: ${name}`,\r\n parameters: normalizeParameters(config.parameters),\r\n handler: config.handler,\r\n confirm: config.confirm || false,\r\n permissions: config.permissions || [],\r\n dangerous: config.dangerous || false,\r\n });\r\n\r\n logger.wuDebug(`[wu-ai] Action registered: '${name}'${config.dangerous ? ' [DANGEROUS]' : ''}`);\r\n }\r\n\r\n /**\r\n * Unregister an action.\r\n */\r\n unregister(name) {\r\n this._actions.delete(name);\r\n }\r\n\r\n /**\r\n * Execute an action (called when LLM returns tool_call).\r\n *\r\n * @param {string} name - Action name\r\n * @param {object} params - Parameters from LLM\r\n * @param {object} [meta] - { traceId, depth, callId }\r\n * @returns {Promise<{ success: boolean, result?: any, reason?: string }>}\r\n */\r\n async execute(name, params, meta = {}) {\r\n const action = this._actions.get(name);\r\n if (!action) {\r\n return { success: false, reason: `Action '${name}' not registered` };\r\n }\r\n\r\n // 1. Check permissions\r\n for (const perm of action.permissions) {\r\n if (!this._permissions.check(perm)) {\r\n this._emitDenied(name, params, `Missing permission: ${perm}`);\r\n return { success: false, reason: `Permission denied: ${perm}` };\r\n }\r\n }\r\n\r\n // 2. Validate params\r\n const validation = validateParams(params || {}, action.parameters);\r\n if (!validation.valid) {\r\n return { success: false, reason: `Invalid params: ${validation.errors.join(', ')}` };\r\n }\r\n\r\n // 3. Confirmation (if required)\r\n if (action.confirm) {\r\n const confirmed = await this._requestConfirmation(name, params, meta.callId);\r\n if (!confirmed) {\r\n return { success: false, reason: 'User denied action' };\r\n }\r\n }\r\n\r\n // 4. Execute with sandboxed API\r\n try {\r\n if (action.dangerous) {\r\n logger.wuWarn(`[wu-ai] Executing DANGEROUS action: '${name}' with params: ${JSON.stringify(params)}`);\r\n }\r\n\r\n const api = this._createSandboxedApi(action.permissions);\r\n const result = await action.handler(params, api);\r\n\r\n // Audit log\r\n this._log(name, params, result, meta);\r\n\r\n // Emit success event\r\n this._eventBus.emit('ai:action:executed', {\r\n action: name,\r\n params,\r\n result,\r\n traceId: meta.traceId,\r\n }, { appName: 'wu-ai' });\r\n\r\n return { success: true, result };\r\n } catch (err) {\r\n this._eventBus.emit('ai:action:error', {\r\n action: name,\r\n params,\r\n error: err.message,\r\n traceId: meta.traceId,\r\n }, { appName: 'wu-ai' });\r\n\r\n return { success: false, reason: err.message };\r\n }\r\n }\r\n\r\n /**\r\n * Get tool schemas for the LLM (function calling format).\r\n */\r\n getToolSchemas() {\r\n return buildToolSchemas(this._actions);\r\n }\r\n\r\n /**\r\n * Check if an action is registered.\r\n */\r\n has(name) {\r\n return this._actions.has(name);\r\n }\r\n\r\n /**\r\n * Get registered action names.\r\n */\r\n getNames() {\r\n return [...this._actions.keys()];\r\n }\r\n\r\n /**\r\n * Get execution log.\r\n */\r\n getLog() {\r\n return [...this._executionLog];\r\n }\r\n\r\n /**\r\n * Confirm a pending tool call (called by developer/UI).\r\n */\r\n confirmTool(callId) {\r\n const pending = this._pendingConfirms.get(callId);\r\n if (pending) {\r\n clearTimeout(pending.timeout);\r\n this._pendingConfirms.delete(callId);\r\n pending.resolve(true);\r\n }\r\n }\r\n\r\n /**\r\n * Reject a pending tool call.\r\n */\r\n rejectTool(callId) {\r\n const pending = this._pendingConfirms.get(callId);\r\n if (pending) {\r\n clearTimeout(pending.timeout);\r\n this._pendingConfirms.delete(callId);\r\n pending.resolve(false);\r\n }\r\n }\r\n\r\n // ── Private: Sandboxed API ──\r\n\r\n _createSandboxedApi(requiredPermissions) {\r\n const api = {};\r\n const perms = new Set(requiredPermissions);\r\n\r\n // Store access (read)\r\n if (this._permissions.check('readStore')) {\r\n api.getState = (path) => this._store.get(path);\r\n }\r\n\r\n // Store access (write) — only if explicitly permitted\r\n if (this._permissions.check('writeStore') && perms.has('writeStore')) {\r\n api.setState = (path, value) => this._store.set(path, value);\r\n }\r\n\r\n // Event emission\r\n if (this._permissions.check('emitEvents')) {\r\n api.emit = (event, data) => this._eventBus.emit(event, data, { appName: 'wu-ai' });\r\n }\r\n\r\n return api;\r\n }\r\n\r\n // ── Private: Confirmation Flow ──\r\n\r\n _requestConfirmation(actionName, params, callId) {\r\n const id = callId || `confirm_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;\r\n\r\n return new Promise((resolve) => {\r\n const timeoutHandle = setTimeout(() => {\r\n this._pendingConfirms.delete(id);\r\n resolve(false); // Timeout = deny\r\n logger.wuDebug(`[wu-ai] Confirmation timeout for action '${actionName}'`);\r\n }, 30000);\r\n\r\n this._pendingConfirms.set(id, { resolve, timeout: timeoutHandle });\r\n\r\n this._eventBus.emit('ai:tool:confirm', {\r\n callId: id,\r\n action: actionName,\r\n params,\r\n message: `AI wants to execute: ${actionName}`,\r\n }, { appName: 'wu-ai' });\r\n });\r\n }\r\n\r\n // ── Private: Logging ──\r\n\r\n _log(action, params, result, meta) {\r\n this._executionLog.push({\r\n action,\r\n params,\r\n result: typeof result === 'object' ? { ...result } : result,\r\n timestamp: Date.now(),\r\n traceId: meta.traceId,\r\n });\r\n\r\n if (this._executionLog.length > this._maxLogSize) {\r\n this._executionLog.shift();\r\n }\r\n }\r\n\r\n _emitDenied(action, params, reason) {\r\n this._eventBus.emit('ai:action:denied', { action, params, reason }, { appName: 'wu-ai' });\r\n logger.wuWarn(`[wu-ai] Action denied: '${action}' — ${reason}`);\r\n }\r\n\r\n getStats() {\r\n return {\r\n registeredActions: [...this._actions.keys()],\r\n executionLogSize: this._executionLog.length,\r\n pendingConfirmations: this._pendingConfirms.size,\r\n };\r\n }\r\n}\r\n","/**\r\n * WU-AI-CONVERSATION: Multi-turn conversation manager\r\n *\r\n * Manages conversation state per namespace. Each namespace maintains\r\n * its own message history, enabling multiple independent AI conversations\r\n * (e.g., chat widget, background triggers, admin panel).\r\n *\r\n * Key features:\r\n * - Multi-turn per namespace (isolated histories)\r\n * - Streaming with async generator passthrough\r\n * - Tool call loop (max rounds configurable, default 5)\r\n * - Abort support via AbortController\r\n * - Automatic context injection before each send\r\n * - Token-aware history truncation\r\n */\r\n\r\nimport { logger } from '../core/wu-logger.js';\r\nimport { sanitizeForPrompt, interpolate } from './wu-ai-schema.js';\r\n\r\n// ─── Default Config ──────────────────────────────────────────────\r\n\r\nconst DEFAULT_CONFIG = {\r\n maxHistoryMessages: 50, // per namespace\r\n maxToolRounds: 5, // tool call loop limit\r\n defaultNamespace: 'default',\r\n systemPrompt: null, // string or function returning string\r\n temperature: undefined,\r\n maxTokens: undefined,\r\n namespaceTTL: 30 * 60_000, // 30 min — auto-expire inactive namespaces (0 = disabled)\r\n gcInterval: 5 * 60_000, // 5 min — how often to sweep for expired namespaces\r\n};\r\n\r\n// ─── Conversation Namespace ──────────────────────────────────────\r\n\r\nclass ConversationNamespace {\r\n constructor(name) {\r\n this.name = name;\r\n this.messages = [];\r\n this.createdAt = Date.now();\r\n this.lastActivity = Date.now();\r\n this._abortController = null;\r\n }\r\n\r\n addMessage(msg) {\r\n this.messages.push({ ...msg, _ts: Date.now() });\r\n this.lastActivity = Date.now();\r\n }\r\n\r\n getMessages() {\r\n return this.messages.map(({ _ts, ...rest }) => rest);\r\n }\r\n\r\n truncate(maxMessages) {\r\n if (this.messages.length <= maxMessages) return;\r\n\r\n // Keep system messages + last N messages\r\n const system = this.messages.filter(m => m.role === 'system');\r\n const nonSystem = this.messages.filter(m => m.role !== 'system');\r\n const kept = nonSystem.slice(-maxMessages);\r\n this.messages = [...system, ...kept];\r\n }\r\n\r\n clear() {\r\n this.messages = [];\r\n this.lastActivity = Date.now();\r\n }\r\n\r\n abort() {\r\n if (this._abortController) {\r\n this._abortController.abort();\r\n this._abortController = null;\r\n }\r\n }\r\n\r\n createAbortController() {\r\n this.abort(); // cancel previous if any\r\n this._abortController = new AbortController();\r\n return this._abortController;\r\n }\r\n}\r\n\r\n// ─── Main Conversation Manager ───────────────────────────────────\r\n\r\nexport class WuAIConversation {\r\n constructor({ provider, actions, context, permissions, eventBus }) {\r\n this._provider = provider;\r\n this._actions = actions;\r\n this._context = context;\r\n this._permissions = permissions;\r\n this._eventBus = eventBus;\r\n\r\n this._config = { ...DEFAULT_CONFIG };\r\n this._namespaces = new Map();\r\n this._activeRequests = new Map(); // namespace → promise\r\n this._lastGcRun = Date.now();\r\n }\r\n\r\n /**\r\n * Configure conversation defaults.\r\n */\r\n configure(config) {\r\n Object.assign(this._config, config);\r\n }\r\n\r\n /**\r\n * Send a message and get a complete response.\r\n * Handles multi-turn tool call loops automatically.\r\n *\r\n * @param {string} message - User message\r\n * @param {object} [options]\r\n * @param {string} [options.namespace='default'] - Conversation namespace\r\n * @param {string} [options.systemPrompt] - Override system prompt\r\n * @param {object} [options.templateVars] - Variables for template interpolation\r\n * @param {number} [options.temperature] - Override temperature\r\n * @param {number} [options.maxTokens] - Override max tokens\r\n * @param {string|object} [options.responseFormat] - Request JSON output ('json' or { type: 'json_schema', schema, name? })\r\n * @param {AbortSignal} [options.signal] - External abort signal\r\n * @returns {Promise<{ content: string, tool_results?: Array, usage?: object, namespace: string }>}\r\n */\r\n async send(message, options = {}) {\r\n const ns = this._getOrCreateNamespace(options.namespace);\r\n const traceId = this._permissions.loopProtection.createTraceId();\r\n const meta = { namespace: ns.name, depth: 0, traceId };\r\n\r\n // Preflight checks\r\n const preflight = this._permissions.preflight(meta);\r\n if (!preflight.allowed) {\r\n return { content: `[blocked] ${preflight.reason}`, namespace: ns.name };\r\n }\r\n\r\n // Build system prompt\r\n const systemPrompt = await this._buildSystemPrompt(options);\r\n\r\n // Ensure system message is set/updated\r\n this._setSystemMessage(ns, systemPrompt);\r\n\r\n // Add user message\r\n const processedMessage = this._processMessage(message, options.templateVars);\r\n ns.addMessage({ role: 'user', content: processedMessage });\r\n\r\n // Truncate history if needed\r\n ns.truncate(this._config.maxHistoryMessages);\r\n\r\n // Create abort controller (merges with external signal)\r\n const controller = ns.createAbortController();\r\n const signal = this._mergeSignals(controller.signal, options.signal);\r\n\r\n // Rate limit tracking\r\n this._permissions.rateLimiter.recordStart(ns.name);\r\n\r\n try {\r\n // Tool call loop\r\n const toolResults = [];\r\n let rounds = 0;\r\n const maxRounds = this._config.maxToolRounds;\r\n\r\n while (rounds <= maxRounds) {\r\n // Get tools if actions are registered\r\n const tools = this._actions.getToolSchemas();\r\n\r\n const response = await this._provider.send(ns.getMessages(), {\r\n tools: tools.length > 0 ? tools : undefined,\r\n temperature: options.temperature ?? this._config.temperature,\r\n maxTokens: options.maxTokens ?? this._config.maxTokens,\r\n responseFormat: options.responseFormat,\r\n provider: options.provider,\r\n signal,\r\n });\r\n\r\n // Add assistant response to history\r\n const assistantMsg = { role: 'assistant', content: response.content || '' };\r\n if (response.tool_calls) assistantMsg.tool_calls = response.tool_calls;\r\n ns.addMessage(assistantMsg);\r\n\r\n // No tool calls → we're done\r\n if (!response.tool_calls || response.tool_calls.length === 0) {\r\n this._permissions.circuitBreaker.recordSuccess();\r\n\r\n this._eventBus.emit('ai:response', {\r\n namespace: ns.name,\r\n content: response.content,\r\n toolResults: toolResults.length > 0 ? toolResults : undefined,\r\n usage: response.usage,\r\n traceId,\r\n }, { appName: 'wu-ai' });\r\n\r\n return {\r\n content: response.content || '',\r\n tool_results: toolResults.length > 0 ? toolResults : undefined,\r\n usage: response.usage,\r\n namespace: ns.name,\r\n };\r\n }\r\n\r\n // Execute tool calls\r\n rounds++;\r\n if (rounds > maxRounds) {\r\n const msg = `[wu-ai] Tool call loop limit (${maxRounds}) reached in namespace '${ns.name}'`;\r\n logger.wuWarn(msg);\r\n ns.addMessage({ role: 'assistant', content: msg });\r\n return { content: msg, tool_results: toolResults, namespace: ns.name };\r\n }\r\n\r\n // Loop protection\r\n this._permissions.loopProtection.enter(traceId);\r\n\r\n for (const toolCall of response.tool_calls) {\r\n const result = await this._actions.execute(toolCall.name, toolCall.arguments, {\r\n traceId,\r\n depth: rounds,\r\n callId: toolCall.id,\r\n });\r\n\r\n toolResults.push({\r\n tool: toolCall.name,\r\n params: toolCall.arguments,\r\n result: result.result,\r\n success: result.success,\r\n });\r\n\r\n // Add tool result to conversation\r\n ns.addMessage({\r\n role: 'tool',\r\n content: JSON.stringify(result.success ? result.result : { error: result.reason }),\r\n tool_call_id: toolCall.id,\r\n });\r\n }\r\n\r\n this._permissions.loopProtection.exit(traceId);\r\n }\r\n\r\n // Should not reach here, but safety net\r\n return { content: '', tool_results: toolResults, namespace: ns.name };\r\n\r\n } catch (err) {\r\n this._permissions.circuitBreaker.recordFailure();\r\n\r\n if (err.name === 'AbortError') {\r\n return { content: '[aborted]', namespace: ns.name };\r\n }\r\n\r\n this._eventBus.emit('ai:error', {\r\n namespace: ns.name,\r\n error: err.message,\r\n traceId,\r\n }, { appName: 'wu-ai' });\r\n\r\n throw err;\r\n } finally {\r\n this._permissions.rateLimiter.recordEnd();\r\n ns._abortController = null;\r\n }\r\n }\r\n\r\n /**\r\n * Send a message with streaming response.\r\n * Returns an async generator that yields chunks.\r\n *\r\n * @param {string} message - User message\r\n * @param {object} [options] - Same as send()\r\n * @yields {{ type: 'text'|'tool_call'|'done'|'error', content?: string, tool_call?: object }}\r\n */\r\n async *stream(message, options = {}) {\r\n const ns = this._getOrCreateNamespace(options.namespace);\r\n const traceId = this._permissions.loopProtection.createTraceId();\r\n const meta = { namespace: ns.name, depth: 0, traceId };\r\n\r\n // Preflight checks\r\n const preflight = this._permissions.preflight(meta);\r\n if (!preflight.allowed) {\r\n yield { type: 'error', error: preflight.reason };\r\n return;\r\n }\r\n\r\n // Build system prompt and set it\r\n const systemPrompt = await this._buildSystemPrompt(options);\r\n this._setSystemMessage(ns, systemPrompt);\r\n\r\n // Add user message\r\n const processedMessage = this._processMessage(message, options.templateVars);\r\n ns.addMessage({ role: 'user', content: processedMessage });\r\n ns.truncate(this._config.maxHistoryMessages);\r\n\r\n // Abort controller\r\n const controller = ns.createAbortController();\r\n const signal = this._mergeSignals(controller.signal, options.signal);\r\n\r\n this._permissions.rateLimiter.recordStart(ns.name);\r\n\r\n try {\r\n // Tool call loop — mirrors send() behavior (up to maxToolRounds)\r\n let rounds = 0;\r\n const maxRounds = this._config.maxToolRounds;\r\n\r\n while (rounds <= maxRounds) {\r\n const tools = this._actions.getToolSchemas();\r\n let fullContent = '';\r\n const toolCallAccumulator = new Map(); // index → { id, name, args }\r\n let streamEnded = false;\r\n\r\n for await (const chunk of this._provider.stream(ns.getMessages(), {\r\n tools: tools.length > 0 ? tools : undefined,\r\n temperature: options.temperature ?? this._config.temperature,\r\n maxTokens: options.maxTokens ?? this._config.maxTokens,\r\n responseFormat: options.responseFormat,\r\n provider: options.provider,\r\n signal,\r\n })) {\r\n if (chunk.type === 'text') {\r\n fullContent += chunk.content;\r\n yield chunk;\r\n } else if (chunk.type === 'tool_call_start') {\r\n toolCallAccumulator.set(toolCallAccumulator.size, {\r\n id: chunk.id,\r\n name: chunk.name,\r\n args: '',\r\n });\r\n } else if (chunk.type === 'tool_call_delta') {\r\n const idx = chunk.index ?? (toolCallAccumulator.size - 1);\r\n const acc = toolCallAccumulator.get(idx);\r\n if (acc) {\r\n if (chunk.id) acc.id = chunk.id;\r\n if (chunk.name) acc.name = chunk.name;\r\n acc.args += chunk.argumentsDelta || '';\r\n } else {\r\n toolCallAccumulator.set(idx, {\r\n id: chunk.id || `tc_${idx}`,\r\n name: chunk.name || '',\r\n args: chunk.argumentsDelta || '',\r\n });\r\n }\r\n } else if (chunk.type === 'done') {\r\n streamEnded = true;\r\n break; // exit inner loop, handle tool calls below\r\n } else if (chunk.type === 'usage') {\r\n yield chunk;\r\n } else if (chunk.type === 'error') {\r\n yield chunk;\r\n }\r\n }\r\n\r\n // No tool calls → final response, we're done\r\n if (toolCallAccumulator.size === 0) {\r\n if (fullContent) {\r\n ns.addMessage({ role: 'assistant', content: fullContent });\r\n }\r\n this._permissions.circuitBreaker.recordSuccess();\r\n yield { type: 'done' };\r\n return;\r\n }\r\n\r\n // Tool calls detected — execute them\r\n rounds++;\r\n if (rounds > maxRounds) {\r\n const msg = `[wu-ai] Tool call loop limit (${maxRounds}) reached in streaming namespace '${ns.name}'`;\r\n logger.wuWarn(msg);\r\n yield { type: 'error', error: msg };\r\n yield { type: 'done' };\r\n return;\r\n }\r\n\r\n // Parse accumulated tool calls\r\n const toolCalls = [];\r\n for (const [, acc] of toolCallAccumulator) {\r\n let parsedArgs = {};\r\n try { parsedArgs = JSON.parse(acc.args); } catch { /* empty args */ }\r\n toolCalls.push({ id: acc.id, name: acc.name, arguments: parsedArgs });\r\n }\r\n\r\n // Add assistant message with tool calls to history\r\n ns.addMessage({ role: 'assistant', content: fullContent, tool_calls: toolCalls });\r\n\r\n // Execute each tool call\r\n this._permissions.loopProtection.enter(traceId);\r\n for (const tc of toolCalls) {\r\n const result = await this._actions.execute(tc.name, tc.arguments, {\r\n traceId, depth: rounds, callId: tc.id,\r\n });\r\n\r\n yield {\r\n type: 'tool_result',\r\n tool: tc.name,\r\n result: result.success ? result.result : { error: result.reason },\r\n success: result.success,\r\n };\r\n\r\n ns.addMessage({\r\n role: 'tool',\r\n content: JSON.stringify(result.success ? result.result : { error: result.reason }),\r\n tool_call_id: tc.id,\r\n });\r\n }\r\n this._permissions.loopProtection.exit(traceId);\r\n\r\n yield { type: 'tool_calls_done', count: toolCalls.length };\r\n // Loop continues → re-stream with tool results in history\r\n }\r\n\r\n } catch (err) {\r\n this._permissions.circuitBreaker.recordFailure();\r\n\r\n if (err.name === 'AbortError') {\r\n yield { type: 'error', error: 'aborted' };\r\n return;\r\n }\r\n\r\n yield { type: 'error', error: err.message };\r\n\r\n this._eventBus.emit('ai:error', {\r\n namespace: ns.name,\r\n error: err.message,\r\n traceId,\r\n }, { appName: 'wu-ai' });\r\n } finally {\r\n this._permissions.rateLimiter.recordEnd();\r\n ns._abortController = null;\r\n }\r\n }\r\n\r\n /**\r\n * Add a message to a namespace without sending to LLM.\r\n * Useful for injecting context or tool results manually.\r\n */\r\n inject(role, content, options = {}) {\r\n const ns = this._getOrCreateNamespace(options.namespace);\r\n ns.addMessage({ role, content });\r\n }\r\n\r\n /**\r\n * Get conversation history for a namespace.\r\n */\r\n getHistory(namespace) {\r\n const ns = this._namespaces.get(namespace || this._config.defaultNamespace);\r\n return ns ? ns.getMessages() : [];\r\n }\r\n\r\n /**\r\n * Clear conversation history for a namespace.\r\n */\r\n clear(namespace) {\r\n const ns = this._namespaces.get(namespace || this._config.defaultNamespace);\r\n if (ns) ns.clear();\r\n }\r\n\r\n /**\r\n * Clear all namespaces.\r\n */\r\n clearAll() {\r\n for (const ns of this._namespaces.values()) {\r\n ns.clear();\r\n }\r\n }\r\n\r\n /**\r\n * Abort an active request in a namespace.\r\n */\r\n abort(namespace) {\r\n const ns = this._namespaces.get(namespace || this._config.defaultNamespace);\r\n if (ns) ns.abort();\r\n }\r\n\r\n /**\r\n * Abort all active requests.\r\n */\r\n abortAll() {\r\n for (const ns of this._namespaces.values()) {\r\n ns.abort();\r\n }\r\n }\r\n\r\n /**\r\n * List active namespaces.\r\n */\r\n getNamespaces() {\r\n return [...this._namespaces.keys()];\r\n }\r\n\r\n /**\r\n * Delete a namespace entirely.\r\n */\r\n deleteNamespace(namespace) {\r\n const ns = this._namespaces.get(namespace);\r\n if (ns) {\r\n ns.abort();\r\n this._namespaces.delete(namespace);\r\n }\r\n }\r\n\r\n // ── Private ──\r\n\r\n _getOrCreateNamespace(name) {\r\n const nsName = name || this._config.defaultNamespace;\r\n\r\n // Lazy GC sweep — only runs periodically, not on every access\r\n this._maybeGcSweep();\r\n\r\n if (!this._namespaces.has(nsName)) {\r\n this._namespaces.set(nsName, new ConversationNamespace(nsName));\r\n }\r\n const ns = this._namespaces.get(nsName);\r\n ns.lastActivity = Date.now();\r\n return ns;\r\n }\r\n\r\n /**\r\n * Sweep expired namespaces. Called lazily on access, throttled by gcInterval.\r\n * Never deletes the default namespace or namespaces with active requests.\r\n */\r\n _maybeGcSweep() {\r\n const ttl = this._config.namespaceTTL;\r\n const interval = this._config.gcInterval;\r\n if (!ttl || ttl <= 0) return; // GC disabled\r\n\r\n const now = Date.now();\r\n if (now - this._lastGcRun < interval) return; // Not time yet\r\n this._lastGcRun = now;\r\n\r\n const cutoff = now - ttl;\r\n const toDelete = [];\r\n\r\n for (const [name, ns] of this._namespaces) {\r\n // Never GC the default namespace\r\n if (name === this._config.defaultNamespace) continue;\r\n // Don't GC namespaces with active abort controllers (in-flight request)\r\n if (ns._abortController) continue;\r\n // Expired?\r\n if (ns.lastActivity < cutoff) {\r\n toDelete.push(name);\r\n }\r\n }\r\n\r\n for (const name of toDelete) {\r\n this._namespaces.delete(name);\r\n }\r\n\r\n if (toDelete.length > 0) {\r\n logger.wuDebug(`[wu-ai] GC sweep: removed ${toDelete.length} expired namespace(s): ${toDelete.join(', ')}`);\r\n }\r\n }\r\n\r\n async _buildSystemPrompt(options) {\r\n // 1. Explicit override\r\n if (options.systemPrompt) {\r\n return typeof options.systemPrompt === 'function'\r\n ? await options.systemPrompt()\r\n : options.systemPrompt;\r\n }\r\n\r\n // 2. Config-level system prompt\r\n if (this._config.systemPrompt) {\r\n return typeof this._config.systemPrompt === 'function'\r\n ? await this._config.systemPrompt()\r\n : this._config.systemPrompt;\r\n }\r\n\r\n // 3. Auto-generate from context\r\n if (this._context) {\r\n await this._context.collect();\r\n const tools = this._actions.getToolSchemas();\r\n return this._context.toSystemPrompt({ tools });\r\n }\r\n\r\n return 'You are an AI assistant connected to a web application via Wu Framework.';\r\n }\r\n\r\n _setSystemMessage(ns, systemPrompt) {\r\n // Replace or insert system message at the beginning\r\n if (ns.messages.length > 0 && ns.messages[0].role === 'system') {\r\n ns.messages[0].content = systemPrompt;\r\n ns.messages[0]._ts = Date.now();\r\n } else {\r\n ns.messages.unshift({ role: 'system', content: systemPrompt, _ts: Date.now() });\r\n }\r\n }\r\n\r\n _processMessage(message, templateVars) {\r\n if (!templateVars) return message;\r\n try {\r\n const contextVars = this._context?.getInterpolationContext() || {};\r\n return interpolate(message, { ...contextVars, ...templateVars });\r\n } catch {\r\n return message;\r\n }\r\n }\r\n\r\n _mergeSignals(internalSignal, externalSignal) {\r\n if (!externalSignal) return internalSignal;\r\n\r\n // If AbortSignal.any is available (modern browsers), use it\r\n if (typeof AbortSignal !== 'undefined' && AbortSignal.any) {\r\n return AbortSignal.any([internalSignal, externalSignal]);\r\n }\r\n\r\n // Fallback: create a new controller that listens to both\r\n const merged = new AbortController();\r\n const onAbort = () => merged.abort();\r\n internalSignal.addEventListener('abort', onAbort, { once: true });\r\n externalSignal.addEventListener('abort', onAbort, { once: true });\r\n return merged.signal;\r\n }\r\n\r\n getStats() {\r\n const namespaces = {};\r\n for (const [name, ns] of this._namespaces) {\r\n namespaces[name] = {\r\n messageCount: ns.messages.length,\r\n lastActivity: ns.lastActivity,\r\n hasActiveRequest: !!ns._abortController,\r\n };\r\n }\r\n return { namespaces, config: { ...this._config } };\r\n }\r\n}\r\n","/**\r\n * WU-AI-TRIGGERS: Event-to-AI bridge\r\n *\r\n * Listens to wu.eventBus events and automatically triggers LLM interactions.\r\n * This is the \"reactive AI\" — the app becomes intelligent by responding\r\n * to events with AI-generated actions.\r\n *\r\n * Features:\r\n * - Pattern-based event matching (wu convention: 'cart:*', 'user:login')\r\n * - Debounce per trigger (avoid flooding LLM)\r\n * - Conditional execution (only trigger if condition returns true)\r\n * - Priority batching (high triggers fire immediately, low ones batch)\r\n * - Template interpolation ({{event.data.user}} in prompts)\r\n * - Namespace isolation (each trigger uses its own conversation namespace)\r\n */\r\n\r\nimport { logger } from '../core/wu-logger.js';\r\nimport { interpolate, sanitizeForPrompt } from './wu-ai-schema.js';\r\n\r\n// ─── Trigger Config ──────────────────────────────────────────────\r\n\r\nconst DEFAULT_TRIGGER_CONFIG = {\r\n enabled: true,\r\n maxActiveTriggers: 20,\r\n defaultDebounceMs: 1000,\r\n batchIntervalMs: 2000,\r\n};\r\n\r\n// ─── Single Trigger ──────────────────────────────────────────────\r\n\r\nclass Trigger {\r\n constructor(name, config) {\r\n this.name = name;\r\n this.pattern = config.pattern; // event pattern: 'cart:updated', 'user:*'\r\n this.prompt = config.prompt; // string or function(eventData) → string\r\n this.condition = config.condition || null; // function(eventData) → boolean\r\n this.debounceMs = config.debounce ?? DEFAULT_TRIGGER_CONFIG.defaultDebounceMs;\r\n this.priority = config.priority || 'medium'; // 'high' | 'medium' | 'low'\r\n this.namespace = config.namespace || `trigger:${name}`;\r\n this.systemPrompt = config.systemPrompt || null;\r\n this.onResult = config.onResult || null; // callback(result, eventData) → void\r\n this.enabled = config.enabled !== false;\r\n this.maxTokens = config.maxTokens || undefined;\r\n this.temperature = config.temperature || undefined;\r\n\r\n // Internal state\r\n this._debounceTimer = null;\r\n this._lastFired = 0;\r\n this._fireCount = 0;\r\n this._pendingEvent = null;\r\n }\r\n\r\n /**\r\n * Check if this trigger matches an event name.\r\n */\r\n matches(eventName) {\r\n if (!this.pattern) return false;\r\n if (this.pattern === '*') return true;\r\n if (!this.pattern.includes('*')) return eventName === this.pattern;\r\n\r\n const regex = new RegExp('^' + this.pattern.replace(/\\*/g, '[^:]*') + '$');\r\n return regex.test(eventName);\r\n }\r\n\r\n /**\r\n * Build the prompt for this trigger given event data.\r\n */\r\n buildPrompt(eventData) {\r\n if (typeof this.prompt === 'function') {\r\n return this.prompt(eventData);\r\n }\r\n\r\n // Template interpolation\r\n return interpolate(this.prompt, {\r\n event: eventData,\r\n data: eventData?.data,\r\n timestamp: Date.now(),\r\n });\r\n }\r\n\r\n /**\r\n * Check condition (if any).\r\n */\r\n async checkCondition(eventData) {\r\n if (!this.condition) return true;\r\n try {\r\n const result = this.condition(eventData);\r\n return result instanceof Promise ? await result : result;\r\n } catch (err) {\r\n logger.wuDebug(`[wu-ai] Trigger '${this.name}' condition error: ${err.message}`);\r\n return false;\r\n }\r\n }\r\n}\r\n\r\n// ─── Main Triggers Manager ───────────────────────────────────────\r\n\r\nexport class WuAITriggers {\r\n constructor({ eventBus, conversation, permissions }) {\r\n this._eventBus = eventBus;\r\n this._conversation = conversation;\r\n this._permissions = permissions;\r\n\r\n this._config = { ...DEFAULT_TRIGGER_CONFIG };\r\n this._triggers = new Map(); // name → Trigger\r\n this._listeners = new Map(); // name → unsubscribe function\r\n this._batchQueue = []; // low-priority triggers pending batch\r\n this._batchTimer = null;\r\n this._stats = {\r\n totalFired: 0,\r\n totalSkipped: 0,\r\n totalErrors: 0,\r\n };\r\n }\r\n\r\n /**\r\n * Configure trigger system.\r\n */\r\n configure(config) {\r\n Object.assign(this._config, config);\r\n }\r\n\r\n /**\r\n * Register a trigger.\r\n *\r\n * @param {string} name - Trigger name (unique identifier)\r\n * @param {object} config\r\n * @param {string} config.pattern - Event pattern to match (e.g., 'cart:*')\r\n * @param {string|Function} config.prompt - Prompt template or function\r\n * @param {Function} [config.condition] - Optional condition function\r\n * @param {number} [config.debounce=1000] - Debounce in ms\r\n * @param {string} [config.priority='medium'] - 'high' | 'medium' | 'low'\r\n * @param {string} [config.namespace] - Conversation namespace\r\n * @param {string} [config.systemPrompt] - Override system prompt\r\n * @param {Function} [config.onResult] - Callback for results\r\n * @param {boolean} [config.enabled=true] - Whether trigger is active\r\n */\r\n register(name, config) {\r\n if (this._triggers.size >= this._config.maxActiveTriggers) {\r\n logger.wuWarn(`[wu-ai] Max triggers (${this._config.maxActiveTriggers}) reached. Cannot register '${name}'.`);\r\n return;\r\n }\r\n\r\n // Unregister existing trigger with same name\r\n if (this._triggers.has(name)) {\r\n this.unregister(name);\r\n }\r\n\r\n const trigger = new Trigger(name, config);\r\n this._triggers.set(name, trigger);\r\n\r\n // Subscribe to matching events\r\n const handler = (eventData) => this._handleEvent(name, eventData);\r\n const unsub = this._eventBus.on(trigger.pattern, handler);\r\n this._listeners.set(name, unsub);\r\n\r\n logger.wuDebug(`[wu-ai] Trigger registered: '${name}' → pattern '${trigger.pattern}' (${trigger.priority})`);\r\n }\r\n\r\n /**\r\n * Unregister a trigger.\r\n */\r\n unregister(name) {\r\n const trigger = this._triggers.get(name);\r\n if (trigger) {\r\n // Clear any pending debounce\r\n if (trigger._debounceTimer) {\r\n clearTimeout(trigger._debounceTimer);\r\n }\r\n }\r\n\r\n // Remove event listener\r\n const unsub = this._listeners.get(name);\r\n if (typeof unsub === 'function') {\r\n unsub();\r\n }\r\n\r\n this._triggers.delete(name);\r\n this._listeners.delete(name);\r\n }\r\n\r\n /**\r\n * Enable/disable a trigger.\r\n */\r\n setEnabled(name, enabled) {\r\n const trigger = this._triggers.get(name);\r\n if (trigger) trigger.enabled = enabled;\r\n }\r\n\r\n /**\r\n * Enable/disable all triggers.\r\n */\r\n setAllEnabled(enabled) {\r\n this._config.enabled = enabled;\r\n for (const trigger of this._triggers.values()) {\r\n trigger.enabled = enabled;\r\n }\r\n }\r\n\r\n /**\r\n * Fire a trigger manually (bypasses event matching).\r\n */\r\n async fire(name, eventData = {}) {\r\n const trigger = this._triggers.get(name);\r\n if (!trigger) {\r\n logger.wuWarn(`[wu-ai] Trigger '${name}' not found`);\r\n return null;\r\n }\r\n return this._executeTrigger(trigger, eventData);\r\n }\r\n\r\n /**\r\n * Get registered trigger names.\r\n */\r\n getNames() {\r\n return [...this._triggers.keys()];\r\n }\r\n\r\n /**\r\n * Get trigger info.\r\n */\r\n getTrigger(name) {\r\n const t = this._triggers.get(name);\r\n if (!t) return null;\r\n return {\r\n name: t.name,\r\n pattern: t.pattern,\r\n priority: t.priority,\r\n namespace: t.namespace,\r\n enabled: t.enabled,\r\n fireCount: t._fireCount,\r\n lastFired: t._lastFired,\r\n };\r\n }\r\n\r\n /**\r\n * Destroy all triggers and clean up.\r\n */\r\n destroy() {\r\n for (const name of [...this._triggers.keys()]) {\r\n this.unregister(name);\r\n }\r\n if (this._batchTimer) {\r\n clearTimeout(this._batchTimer);\r\n this._batchTimer = null;\r\n }\r\n this._batchQueue = [];\r\n }\r\n\r\n // ── Private: Event Handling ──\r\n\r\n async _handleEvent(triggerName, eventData) {\r\n if (!this._config.enabled) return;\r\n\r\n const trigger = this._triggers.get(triggerName);\r\n if (!trigger || !trigger.enabled) return;\r\n\r\n // Check condition\r\n const conditionMet = await trigger.checkCondition(eventData);\r\n if (!conditionMet) {\r\n this._stats.totalSkipped++;\r\n return;\r\n }\r\n\r\n // Priority routing\r\n if (trigger.priority === 'high') {\r\n // High priority: fire immediately (with debounce)\r\n this._debouncedFire(trigger, eventData);\r\n } else if (trigger.priority === 'low') {\r\n // Low priority: batch\r\n this._batchQueue.push({ trigger, eventData });\r\n this._scheduleBatch();\r\n } else {\r\n // Medium: debounce\r\n this._debouncedFire(trigger, eventData);\r\n }\r\n }\r\n\r\n _debouncedFire(trigger, eventData) {\r\n // Store pending event (latest wins for debounce)\r\n trigger._pendingEvent = eventData;\r\n\r\n if (trigger._debounceTimer) {\r\n clearTimeout(trigger._debounceTimer);\r\n }\r\n\r\n if (trigger.debounceMs <= 0) {\r\n // No debounce\r\n this._executeTrigger(trigger, eventData);\r\n return;\r\n }\r\n\r\n trigger._debounceTimer = setTimeout(() => {\r\n trigger._debounceTimer = null;\r\n const pending = trigger._pendingEvent;\r\n trigger._pendingEvent = null;\r\n if (pending) {\r\n this._executeTrigger(trigger, pending);\r\n }\r\n }, trigger.debounceMs);\r\n }\r\n\r\n _scheduleBatch() {\r\n if (this._batchTimer) return;\r\n\r\n this._batchTimer = setTimeout(() => {\r\n this._batchTimer = null;\r\n this._processBatch();\r\n }, this._config.batchIntervalMs);\r\n }\r\n\r\n async _processBatch() {\r\n const batch = [...this._batchQueue];\r\n this._batchQueue = [];\r\n\r\n // Deduplicate: keep last event per trigger\r\n const byTrigger = new Map();\r\n for (const { trigger, eventData } of batch) {\r\n byTrigger.set(trigger.name, { trigger, eventData });\r\n }\r\n\r\n for (const { trigger, eventData } of byTrigger.values()) {\r\n await this._executeTrigger(trigger, eventData);\r\n }\r\n }\r\n\r\n async _executeTrigger(trigger, eventData) {\r\n try {\r\n const prompt = trigger.buildPrompt(eventData);\r\n if (!prompt) {\r\n this._stats.totalSkipped++;\r\n return null;\r\n }\r\n\r\n logger.wuDebug(`[wu-ai] Trigger '${trigger.name}' firing with prompt: ${prompt.slice(0, 100)}...`);\r\n\r\n const result = await this._conversation.send(prompt, {\r\n namespace: trigger.namespace,\r\n systemPrompt: trigger.systemPrompt,\r\n temperature: trigger.temperature,\r\n maxTokens: trigger.maxTokens,\r\n });\r\n\r\n trigger._fireCount++;\r\n trigger._lastFired = Date.now();\r\n this._stats.totalFired++;\r\n\r\n // Emit trigger result event\r\n this._eventBus.emit('ai:trigger:result', {\r\n trigger: trigger.name,\r\n pattern: trigger.pattern,\r\n result,\r\n }, { appName: 'wu-ai' });\r\n\r\n // Call onResult callback if provided\r\n if (trigger.onResult) {\r\n try {\r\n await trigger.onResult(result, eventData);\r\n } catch (err) {\r\n logger.wuDebug(`[wu-ai] Trigger '${trigger.name}' onResult error: ${err.message}`);\r\n }\r\n }\r\n\r\n return result;\r\n } catch (err) {\r\n this._stats.totalErrors++;\r\n logger.wuWarn(`[wu-ai] Trigger '${trigger.name}' error: ${err.message}`);\r\n\r\n this._eventBus.emit('ai:trigger:error', {\r\n trigger: trigger.name,\r\n error: err.message,\r\n }, { appName: 'wu-ai' });\r\n\r\n return null;\r\n }\r\n }\r\n\r\n getStats() {\r\n const triggers = {};\r\n for (const [name, t] of this._triggers) {\r\n triggers[name] = {\r\n pattern: t.pattern,\r\n priority: t.priority,\r\n enabled: t.enabled,\r\n fireCount: t._fireCount,\r\n lastFired: t._lastFired,\r\n };\r\n }\r\n return {\r\n ...this._stats,\r\n triggerCount: this._triggers.size,\r\n batchQueueSize: this._batchQueue.length,\r\n triggers,\r\n };\r\n }\r\n}\r\n","/**\r\n * WU-AI-AGENT: Autonomous agent loop (Paradigm 3)\r\n *\r\n * The agent is the third paradigm of wu.ai:\r\n * Paradigm 1 — App sends messages to LLM (conversation)\r\n * Paradigm 2 — External LLM calls into app (tools/WebMCP)\r\n * Paradigm 3 — AI as autonomous director (this file)\r\n *\r\n * The agent receives a goal and iterates: send to LLM, execute tool calls,\r\n * observe results, repeat — until the goal is achieved or limits are hit.\r\n * It is an async generator, yielding each step so the caller can observe,\r\n * log, render, or intervene at any point.\r\n *\r\n * This is a foundation, not a planner. It does not decompose goals into\r\n * sub-tasks or maintain a world model. It trusts the LLM to drive the\r\n * loop and uses the [DONE] marker or tool-call cessation as termination\r\n * signals. More sophisticated planning belongs in userland, composed\r\n * on top of this primitive.\r\n *\r\n * Key features:\r\n * - Async generator yielding step results (observable, composable)\r\n * - Human-in-the-loop via shouldContinue callback\r\n * - Abort support via AbortController\r\n * - Permission preflight before every step\r\n * - Event emission on start, step, done, error\r\n * - Auto-generated system prompt describing agent role and tools\r\n * - Configurable step limit (default 10)\r\n */\r\n\r\nimport { logger } from '../core/wu-logger.js';\r\n\r\n// ─── Constants ──────────────────────────────────────────────────\r\n\r\nconst DONE_MARKER = '[DONE]';\r\n\r\nconst DEFAULT_MAX_STEPS = 10;\r\n\r\nconst AGENT_NAMESPACE_PREFIX = 'agent:';\r\n\r\n// ─── Step Result Types ──────────────────────────────────────────\r\n\r\n/**\r\n * @typedef {object} AgentStepResult\r\n * @property {number} step - Step number (1-indexed)\r\n * @property {'thinking'|'tool_call'|'done'|'blocked'|'aborted'|'interrupted'} type\r\n * @property {string} [content] - LLM text response for this step\r\n * @property {Array} [toolResults] - Tool execution results (if tools were called)\r\n * @property {object} [usage] - Token usage for this step\r\n * @property {string} [reason] - Reason for termination (done/blocked/aborted)\r\n * @property {number} elapsed - Time in ms for this step\r\n */\r\n\r\n// ─── Agent Class ────────────────────────────────────────────────\r\n\r\nexport class WuAIAgent {\r\n /**\r\n * @param {object} deps - Injected dependencies (same pattern as other wu-ai modules)\r\n * @param {import('./wu-ai-conversation.js').WuAIConversation} deps.conversation - Conversation manager\r\n * @param {import('./wu-ai-actions.js').WuAIActions} deps.actions - Action registry\r\n * @param {import('./wu-ai-context.js').WuAIContext} deps.context - Context collector\r\n * @param {import('./wu-ai-permissions.js').WuAIPermissions} deps.permissions - Permission system\r\n * @param {object} deps.eventBus - WuEventBus instance\r\n */\r\n constructor({ conversation, actions, context, permissions, eventBus }) {\r\n this._conversation = conversation;\r\n this._actions = actions;\r\n this._context = context;\r\n this._permissions = permissions;\r\n this._eventBus = eventBus;\r\n\r\n this._config = {\r\n maxSteps: DEFAULT_MAX_STEPS,\r\n systemPrompt: null,\r\n };\r\n\r\n this._activeRuns = new Map(); // runId -> AbortController\r\n this._stats = {\r\n totalRuns: 0,\r\n totalSteps: 0,\r\n completedRuns: 0,\r\n abortedRuns: 0,\r\n errorRuns: 0,\r\n };\r\n }\r\n\r\n /**\r\n * Post-init configuration.\r\n *\r\n * @param {object} config\r\n * @param {number} [config.maxSteps] - Default max steps for all runs\r\n * @param {string|Function} [config.systemPrompt] - Default agent system prompt\r\n */\r\n configure(config) {\r\n if (config.maxSteps !== undefined) this._config.maxSteps = config.maxSteps;\r\n if (config.systemPrompt !== undefined) this._config.systemPrompt = config.systemPrompt;\r\n }\r\n\r\n /**\r\n * Run the agent loop toward a goal.\r\n *\r\n * The generator yields after each LLM round. The caller can inspect\r\n * the result, update UI, or break out of the loop to abort early.\r\n *\r\n * Termination conditions (checked in order):\r\n * 1. AbortController signal fired\r\n * 2. shouldContinue() returns false (human-in-the-loop gate)\r\n * 3. Permission preflight denied\r\n * 4. LLM response contains [DONE] marker\r\n * 5. LLM stops requesting tool calls (after previously requesting them)\r\n * 6. maxSteps reached\r\n *\r\n * @param {string} goal - Natural language description of what to achieve\r\n * @param {object} [options]\r\n * @param {number} [options.maxSteps] - Override max steps for this run\r\n * @param {string} [options.provider] - Use a specific registered provider\r\n * @param {string} [options.namespace] - Conversation namespace (auto-generated if omitted)\r\n * @param {string|Function} [options.systemPrompt] - Override system prompt\r\n * @param {Function} [options.onStep] - Callback invoked after each step: (stepResult) => void\r\n * @param {Function} [options.shouldContinue] - Async gate: (stepResult) => boolean. Return false to stop.\r\n * @param {AbortSignal} [options.signal] - External abort signal\r\n * @param {number} [options.temperature] - LLM temperature\r\n * @param {number} [options.maxTokens] - LLM max tokens per step\r\n * @yields {AgentStepResult}\r\n */\r\n async *run(goal, options = {}) {\r\n const maxSteps = options.maxSteps ?? this._config.maxSteps;\r\n const namespace = options.namespace || this._generateNamespace();\r\n const runId = this._generateRunId();\r\n\r\n // Abort controller: merge external signal with our own\r\n const controller = new AbortController();\r\n this._activeRuns.set(runId, controller);\r\n\r\n if (options.signal) {\r\n if (options.signal.aborted) {\r\n controller.abort();\r\n } else {\r\n options.signal.addEventListener('abort', () => controller.abort(), { once: true });\r\n }\r\n }\r\n\r\n this._stats.totalRuns++;\r\n\r\n // Build the agent system prompt\r\n const systemPrompt = await this._buildAgentSystemPrompt(goal, options);\r\n\r\n // Emit start event\r\n this._eventBus.emit('ai:agent:start', {\r\n runId,\r\n goal,\r\n namespace,\r\n maxSteps,\r\n }, { appName: 'wu-ai' });\r\n\r\n logger.wuInfo(`[wu-ai] Agent run started: \"${goal.slice(0, 80)}${goal.length > 80 ? '...' : ''}\" (max ${maxSteps} steps)`);\r\n\r\n let step = 0;\r\n let previousHadToolCalls = false;\r\n let finalReason = 'max_steps';\r\n\r\n try {\r\n // Inject the goal as the first user message via conversation.send\r\n // The loop sends the goal on step 1, then follow-up prompts on subsequent steps.\r\n\r\n while (step < maxSteps) {\r\n step++;\r\n const stepStart = Date.now();\r\n\r\n // ── 1. Check abort ──\r\n if (controller.signal.aborted) {\r\n const result = this._buildStepResult(step, 'aborted', {\r\n reason: 'Aborted by caller',\r\n elapsed: Date.now() - stepStart,\r\n });\r\n this._stats.abortedRuns++;\r\n finalReason = 'aborted';\r\n this._emitStep(runId, result);\r\n yield result;\r\n return;\r\n }\r\n\r\n // ── 2. Permission preflight ──\r\n const traceId = this._permissions.loopProtection.createTraceId();\r\n const preflight = this._permissions.preflight({\r\n namespace,\r\n depth: step,\r\n traceId,\r\n });\r\n\r\n if (!preflight.allowed) {\r\n const result = this._buildStepResult(step, 'blocked', {\r\n reason: preflight.reason,\r\n elapsed: Date.now() - stepStart,\r\n });\r\n finalReason = 'blocked';\r\n this._emitStep(runId, result);\r\n yield result;\r\n return;\r\n }\r\n\r\n // ── 3. Compose the message for this step ──\r\n const message = step === 1\r\n ? goal\r\n : 'Continue working toward the goal. If you are done, include [DONE] in your response.';\r\n\r\n // ── 4. Send to conversation (handles tool call loops internally) ──\r\n let response;\r\n try {\r\n response = await this._conversation.send(message, {\r\n namespace,\r\n systemPrompt,\r\n provider: options.provider,\r\n temperature: options.temperature,\r\n maxTokens: options.maxTokens,\r\n signal: controller.signal,\r\n });\r\n } catch (err) {\r\n if (err.name === 'AbortError' || controller.signal.aborted) {\r\n const result = this._buildStepResult(step, 'aborted', {\r\n reason: 'Aborted during LLM call',\r\n elapsed: Date.now() - stepStart,\r\n });\r\n this._stats.abortedRuns++;\r\n finalReason = 'aborted';\r\n this._emitStep(runId, result);\r\n yield result;\r\n return;\r\n }\r\n throw err;\r\n }\r\n\r\n const elapsed = Date.now() - stepStart;\r\n this._stats.totalSteps++;\r\n\r\n const hasToolResults = response.tool_results && response.tool_results.length > 0;\r\n const content = response.content || '';\r\n\r\n // ── 5. Check for DONE marker ──\r\n if (content.includes(DONE_MARKER)) {\r\n const result = this._buildStepResult(step, 'done', {\r\n content: content.replace(DONE_MARKER, '').trim(),\r\n toolResults: response.tool_results,\r\n usage: response.usage,\r\n reason: 'Goal completed (DONE marker)',\r\n elapsed,\r\n });\r\n finalReason = 'done';\r\n this._stats.completedRuns++;\r\n this._emitStep(runId, result);\r\n if (options.onStep) await this._safeCallback(options.onStep, result);\r\n yield result;\r\n return;\r\n }\r\n\r\n // ── 6. Check for tool-call cessation ──\r\n // If the LLM was previously calling tools but stopped, it has\r\n // settled on a final answer. This is the implicit completion signal.\r\n const currentHasToolCalls = hasToolResults;\r\n if (previousHadToolCalls && !currentHasToolCalls) {\r\n const result = this._buildStepResult(step, 'done', {\r\n content,\r\n toolResults: response.tool_results,\r\n usage: response.usage,\r\n reason: 'Goal completed (no further tool calls)',\r\n elapsed,\r\n });\r\n finalReason = 'done';\r\n this._stats.completedRuns++;\r\n this._emitStep(runId, result);\r\n if (options.onStep) await this._safeCallback(options.onStep, result);\r\n yield result;\r\n return;\r\n }\r\n\r\n previousHadToolCalls = currentHasToolCalls;\r\n\r\n // ── 7. Yield the step result ──\r\n const stepType = hasToolResults ? 'tool_call' : 'thinking';\r\n const result = this._buildStepResult(step, stepType, {\r\n content,\r\n toolResults: response.tool_results,\r\n usage: response.usage,\r\n elapsed,\r\n });\r\n\r\n this._emitStep(runId, result);\r\n if (options.onStep) await this._safeCallback(options.onStep, result);\r\n yield result;\r\n\r\n // ── 8. Human-in-the-loop gate ──\r\n if (options.shouldContinue) {\r\n let shouldGo;\r\n try {\r\n shouldGo = await options.shouldContinue(result);\r\n } catch {\r\n shouldGo = false;\r\n }\r\n\r\n if (!shouldGo) {\r\n const interrupted = this._buildStepResult(step, 'interrupted', {\r\n content,\r\n reason: 'Stopped by shouldContinue callback',\r\n elapsed: 0,\r\n });\r\n finalReason = 'interrupted';\r\n this._emitStep(runId, interrupted);\r\n yield interrupted;\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // ── Max steps reached ──\r\n const maxStepResult = this._buildStepResult(step, 'done', {\r\n reason: `Max steps (${maxSteps}) reached`,\r\n elapsed: 0,\r\n });\r\n finalReason = 'max_steps';\r\n yield maxStepResult;\r\n\r\n } catch (err) {\r\n this._stats.errorRuns++;\r\n finalReason = 'error';\r\n\r\n logger.wuWarn(`[wu-ai] Agent run error: ${err.message}`);\r\n\r\n this._eventBus.emit('ai:agent:error', {\r\n runId,\r\n goal,\r\n namespace,\r\n step,\r\n error: err.message,\r\n }, { appName: 'wu-ai' });\r\n\r\n throw err;\r\n } finally {\r\n // Clean up\r\n this._activeRuns.delete(runId);\r\n\r\n // Delete auto-generated agent namespaces to prevent memory leaks\r\n // User-provided namespaces are preserved (the user owns their lifecycle)\r\n if (!options.namespace && namespace.startsWith(AGENT_NAMESPACE_PREFIX)) {\r\n this._conversation.deleteNamespace(namespace);\r\n }\r\n\r\n this._eventBus.emit('ai:agent:done', {\r\n runId,\r\n goal,\r\n namespace,\r\n totalSteps: step,\r\n reason: finalReason,\r\n }, { appName: 'wu-ai' });\r\n\r\n logger.wuDebug(`[wu-ai] Agent run finished: ${finalReason} after ${step} step(s)`);\r\n }\r\n }\r\n\r\n /**\r\n * Abort an active agent run by runId.\r\n *\r\n * @param {string} runId - The run ID to abort\r\n */\r\n abort(runId) {\r\n const controller = this._activeRuns.get(runId);\r\n if (controller) {\r\n controller.abort();\r\n logger.wuDebug(`[wu-ai] Agent run aborted: ${runId}`);\r\n }\r\n }\r\n\r\n /**\r\n * Abort all active agent runs.\r\n */\r\n abortAll() {\r\n for (const [runId, controller] of this._activeRuns) {\r\n controller.abort();\r\n }\r\n this._activeRuns.clear();\r\n }\r\n\r\n /**\r\n * Get IDs of currently active runs.\r\n *\r\n * @returns {string[]}\r\n */\r\n getActiveRuns() {\r\n return [...this._activeRuns.keys()];\r\n }\r\n\r\n /**\r\n * Get agent statistics.\r\n *\r\n * @returns {object}\r\n */\r\n getStats() {\r\n return {\r\n ...this._stats,\r\n activeRuns: this._activeRuns.size,\r\n config: { ...this._config },\r\n };\r\n }\r\n\r\n /**\r\n * Destroy the agent, aborting all active runs.\r\n */\r\n destroy() {\r\n this.abortAll();\r\n this._stats = {\r\n totalRuns: 0,\r\n totalSteps: 0,\r\n completedRuns: 0,\r\n abortedRuns: 0,\r\n errorRuns: 0,\r\n };\r\n }\r\n\r\n // ─── Private ──────────────────────────────────────────────────\r\n\r\n /**\r\n * Build the agent-specific system prompt. This tells the LLM it is\r\n * operating as an autonomous agent with a goal, available tools, and\r\n * the [DONE] completion protocol.\r\n */\r\n async _buildAgentSystemPrompt(goal, options) {\r\n // Explicit override takes precedence\r\n const basePrompt = options.systemPrompt\r\n ?? this._config.systemPrompt\r\n ?? null;\r\n\r\n if (basePrompt) {\r\n const resolved = typeof basePrompt === 'function'\r\n ? await basePrompt(goal)\r\n : basePrompt;\r\n return resolved;\r\n }\r\n\r\n // Auto-generate from context and tools\r\n const parts = [];\r\n\r\n parts.push(\r\n 'You are an autonomous AI agent connected to a live web application via Wu Framework.',\r\n 'You have been given a goal and must work step-by-step to achieve it.',\r\n '',\r\n 'PROTOCOL:',\r\n '- Each message you send is one \"step\" in your execution.',\r\n '- You may call tools to read or modify application state.',\r\n '- After each step, you will be prompted to continue.',\r\n '- When the goal is fully achieved, include the marker [DONE] in your response.',\r\n '- If you determine the goal cannot be achieved, include [DONE] and explain why.',\r\n '- Be concise. Each step should make meaningful progress.',\r\n '',\r\n );\r\n\r\n // Collect context if available\r\n if (this._context) {\r\n try {\r\n await this._context.collect();\r\n const snapshot = this._context.getSnapshot();\r\n if (snapshot?._mountedApps?.length) {\r\n parts.push(`MOUNTED APPS: ${snapshot._mountedApps.join(', ')}`, '');\r\n }\r\n if (snapshot?._store && Object.keys(snapshot._store).length > 0) {\r\n parts.push(`APPLICATION STATE:\\n${JSON.stringify(snapshot._store, null, 2)}`, '');\r\n }\r\n } catch {\r\n // Context collection is best-effort\r\n }\r\n }\r\n\r\n // List available tools\r\n const tools = this._actions.getToolSchemas();\r\n if (tools.length > 0) {\r\n parts.push('AVAILABLE TOOLS:');\r\n for (const tool of tools) {\r\n const paramKeys = tool.parameters?.properties\r\n ? Object.keys(tool.parameters.properties).join(', ')\r\n : 'none';\r\n parts.push(`- ${tool.name}(${paramKeys}): ${tool.description}`);\r\n }\r\n parts.push('');\r\n }\r\n\r\n parts.push(`GOAL: ${goal}`);\r\n\r\n return parts.join('\\n');\r\n }\r\n\r\n /**\r\n * Build a normalized step result object.\r\n *\r\n * @param {number} step\r\n * @param {string} type\r\n * @param {object} data\r\n * @returns {AgentStepResult}\r\n */\r\n _buildStepResult(step, type, data = {}) {\r\n return {\r\n step,\r\n type,\r\n content: data.content ?? null,\r\n toolResults: data.toolResults ?? null,\r\n usage: data.usage ?? null,\r\n reason: data.reason ?? null,\r\n elapsed: data.elapsed ?? 0,\r\n };\r\n }\r\n\r\n /**\r\n * Emit an ai:agent:step event.\r\n */\r\n _emitStep(runId, result) {\r\n this._eventBus.emit('ai:agent:step', {\r\n runId,\r\n ...result,\r\n }, { appName: 'wu-ai' });\r\n }\r\n\r\n /**\r\n * Safely invoke a callback, swallowing errors so the agent loop\r\n * is never broken by a faulty onStep handler.\r\n */\r\n async _safeCallback(fn, ...args) {\r\n try {\r\n const result = fn(...args);\r\n if (result && typeof result.then === 'function') {\r\n await result;\r\n }\r\n } catch (err) {\r\n logger.wuDebug(`[wu-ai] Agent callback error: ${err.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Generate a unique namespace for an agent run.\r\n */\r\n _generateNamespace() {\r\n return AGENT_NAMESPACE_PREFIX + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 6);\r\n }\r\n\r\n /**\r\n * Generate a unique run ID.\r\n */\r\n _generateRunId() {\r\n return 'run_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 8);\r\n }\r\n}\r\n","/**\r\n * WU-AI Browser Primitives\r\n *\r\n * Shared browser capabilities used by both wu-ai-browser.js (Paradigm 1/2)\r\n * and wu-mcp-bridge.js (Paradigm 3). Single source of truth to avoid\r\n * duplicating interceptors, DOM traversal, and Canvas rendering.\r\n */\r\n\r\n// ── Shared capture buffers (singleton) ──\r\n\r\nexport const networkLog = [];\r\nexport const MAX_NETWORK_LOG = 300;\r\nexport const consoleLog = [];\r\nexport const MAX_CONSOLE_LOG = 500;\r\n\r\nlet _interceptorsInstalled = false;\r\n\r\n/**\r\n * Install network + console interceptors (idempotent — only runs once).\r\n */\r\nexport function ensureInterceptors() {\r\n if (_interceptorsInstalled) return;\r\n _installNetworkInterceptor();\r\n _installConsoleInterceptor();\r\n _interceptorsInstalled = true;\r\n}\r\n\r\n/**\r\n * Build an accessibility tree representation of a DOM element.\r\n * Traverses into Shadow DOM if present.\r\n */\r\nexport function buildA11yTree(el, depth = 0, maxDepth = 5) {\r\n if (depth > maxDepth || !el) return '';\r\n\r\n const indent = ' '.repeat(depth);\r\n const tag = el.tagName?.toLowerCase() || '';\r\n const role = el.getAttribute?.('role') || '';\r\n const ariaLabel = el.getAttribute?.('aria-label') || '';\r\n const text = el.childNodes?.length === 1 && el.childNodes[0].nodeType === 3\r\n ? el.textContent?.trim().slice(0, 80) : '';\r\n\r\n let line = `${indent}<${tag}`;\r\n if (el.id) line += ` id=\"${el.id}\"`;\r\n if (role) line += ` role=\"${role}\"`;\r\n if (ariaLabel) line += ` aria-label=\"${ariaLabel}\"`;\r\n if (el.className && typeof el.className === 'string') {\r\n const cls = el.className.trim().slice(0, 60);\r\n if (cls) line += ` class=\"${cls}\"`;\r\n }\r\n line += '>';\r\n if (text) line += ` \"${text}\"`;\r\n\r\n let result = line + '\\n';\r\n const root = el.shadowRoot || el;\r\n const children = root.children || [];\r\n\r\n for (let i = 0; i < children.length && i < 50; i++) {\r\n result += buildA11yTree(children[i], depth + 1, maxDepth);\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * Recursively inline computed styles from source to clone for Canvas rendering.\r\n */\r\nexport function inlineComputedStyles(source, clone) {\r\n const props = ['color', 'background', 'background-color', 'font-family',\r\n 'font-size', 'font-weight', 'border', 'border-radius', 'padding', 'margin',\r\n 'display', 'flex-direction', 'align-items', 'justify-content', 'gap',\r\n 'width', 'height', 'max-width', 'max-height', 'overflow', 'opacity',\r\n 'box-shadow', 'text-align', 'line-height', 'position', 'top', 'left',\r\n 'right', 'bottom', 'z-index', 'transform', 'visibility'];\r\n\r\n try {\r\n const style = window.getComputedStyle(source);\r\n for (const prop of props) {\r\n const val = style.getPropertyValue(prop);\r\n if (val) clone.style?.setProperty(prop, val);\r\n }\r\n } catch (_) { /* skip */ }\r\n\r\n const srcKids = source.children || [];\r\n const cloneKids = clone.children || [];\r\n const max = Math.min(srcKids.length, cloneKids.length, 200);\r\n for (let i = 0; i < max; i++) {\r\n inlineComputedStyles(srcKids[i], cloneKids[i]);\r\n }\r\n}\r\n\r\n/**\r\n * Capture a screenshot of a DOM element via Canvas API (SVG foreignObject).\r\n * @returns {Promise<{ width, height, format, base64, sizeKB } | { error: string }>}\r\n */\r\nexport async function captureScreenshot(selector, quality = 0.8) {\r\n const target = selector\r\n ? document.querySelector(selector)\r\n : document.documentElement;\r\n\r\n if (!target) return { error: `Element not found: ${selector}` };\r\n\r\n const rect = target.getBoundingClientRect();\r\n const w = Math.ceil(Math.min(rect.width || window.innerWidth, 1920));\r\n const h = Math.ceil(Math.min(rect.height || window.innerHeight, 1080));\r\n\r\n const clone = target.cloneNode(true);\r\n inlineComputedStyles(target, clone);\r\n\r\n const serializer = new XMLSerializer();\r\n const xhtml = serializer.serializeToString(clone);\r\n\r\n const svgStr = [\r\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${w}\" height=\"${h}\">`,\r\n '<foreignObject width=\"100%\" height=\"100%\">',\r\n `<div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"width:${w}px;height:${h}px;overflow:hidden;\">`,\r\n xhtml,\r\n '</div>',\r\n '</foreignObject>',\r\n '</svg>',\r\n ].join('');\r\n\r\n const svgBlob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });\r\n const url = URL.createObjectURL(svgBlob);\r\n\r\n const dataUrl = await new Promise((resolve) => {\r\n const img = new Image();\r\n img.onload = () => {\r\n const canvas = document.createElement('canvas');\r\n canvas.width = w;\r\n canvas.height = h;\r\n const ctx = canvas.getContext('2d');\r\n ctx.drawImage(img, 0, 0);\r\n URL.revokeObjectURL(url);\r\n resolve(canvas.toDataURL('image/png', quality));\r\n };\r\n img.onerror = () => {\r\n URL.revokeObjectURL(url);\r\n resolve(null);\r\n };\r\n img.src = url;\r\n });\r\n\r\n if (!dataUrl) return { error: 'Canvas rendering failed' };\r\n\r\n const base64 = dataUrl.split(',')[1];\r\n return {\r\n width: w,\r\n height: h,\r\n format: 'png',\r\n base64,\r\n sizeKB: Math.round((base64.length * 3) / 4 / 1024),\r\n };\r\n}\r\n\r\n/**\r\n * Click an element by CSS selector or visible text content.\r\n * @returns {{ clicked, text } | { error }}\r\n */\r\nexport function clickElement(selector, text) {\r\n let el = null;\r\n\r\n if (selector) {\r\n el = document.querySelector(selector);\r\n }\r\n\r\n if (!el && text) {\r\n const candidates = document.querySelectorAll(\r\n 'button, a, [role=\"button\"], input[type=\"submit\"], input[type=\"button\"], [data-click], label, [onclick]'\r\n );\r\n const searchText = text.toLowerCase();\r\n for (const candidate of candidates) {\r\n if (candidate.textContent?.trim().toLowerCase().includes(searchText)) {\r\n el = candidate;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!el) return { error: `Element not found: ${selector || `text=\"${text}\"`}` };\r\n\r\n el.scrollIntoView({ behavior: 'instant', block: 'center' });\r\n el.click();\r\n\r\n const tag = el.tagName?.toLowerCase();\r\n const id = el.id ? `#${el.id}` : '';\r\n return {\r\n clicked: `${tag}${id}`,\r\n text: el.textContent?.trim().slice(0, 100) || '',\r\n rect: el.getBoundingClientRect().toJSON?.() || null,\r\n };\r\n}\r\n\r\n/**\r\n * Type into an input, textarea, or contenteditable element.\r\n * Works with React, Vue, Angular, and other frameworks.\r\n * @returns {{ selector, typed, currentValue, submitted } | { error }}\r\n */\r\nexport function typeIntoElement(selector, text, { clear = false, submit = false } = {}) {\r\n if (!selector) return { error: 'selector is required' };\r\n if (text === undefined) return { error: 'text is required' };\r\n\r\n const el = document.querySelector(selector);\r\n if (!el) return { error: `Element not found: ${selector}` };\r\n\r\n el.focus();\r\n\r\n if (clear) {\r\n el.value = '';\r\n el.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n\r\n // Use native setter to trigger framework reactivity (React, Vue, etc.)\r\n const nativeSetter = Object.getOwnPropertyDescriptor(\r\n window.HTMLInputElement.prototype, 'value'\r\n )?.set || Object.getOwnPropertyDescriptor(\r\n window.HTMLTextAreaElement.prototype, 'value'\r\n )?.set;\r\n\r\n const newValue = clear ? text : (el.value || '') + text;\r\n if (nativeSetter) {\r\n nativeSetter.call(el, newValue);\r\n } else {\r\n el.value = newValue;\r\n }\r\n\r\n el.dispatchEvent(new Event('input', { bubbles: true }));\r\n el.dispatchEvent(new Event('change', { bubbles: true }));\r\n\r\n if (submit) {\r\n const form = el.closest('form');\r\n if (form) {\r\n form.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));\r\n } else {\r\n el.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', bubbles: true }));\r\n }\r\n }\r\n\r\n return {\r\n selector,\r\n typed: text,\r\n currentValue: el.value?.slice(0, 200),\r\n submitted: !!submit,\r\n };\r\n}\r\n\r\n/**\r\n * Filter and return network log entries.\r\n */\r\nexport function getFilteredNetwork(method, status, limit = 30) {\r\n let filtered = networkLog;\r\n if (method) {\r\n filtered = filtered.filter((r) => r.method === method.toUpperCase());\r\n }\r\n if (status) {\r\n if (status === 'error') {\r\n filtered = filtered.filter((r) => r.status === 0 || r.status >= 400);\r\n } else {\r\n filtered = filtered.filter((r) => String(r.status).startsWith(String(status)));\r\n }\r\n }\r\n return {\r\n requests: filtered.slice(-limit),\r\n total: networkLog.length,\r\n showing: Math.min(filtered.length, limit),\r\n };\r\n}\r\n\r\n/**\r\n * Filter and return console log entries.\r\n */\r\nexport function getFilteredConsole(level, limit = 30) {\r\n const filtered = level && level !== 'all'\r\n ? consoleLog.filter((m) => m.level === level)\r\n : consoleLog;\r\n return {\r\n messages: filtered.slice(-limit),\r\n total: consoleLog.length,\r\n showing: Math.min(filtered.length, limit),\r\n };\r\n}\r\n\r\n// ── Private: Interceptors ──\r\n\r\nfunction _installNetworkInterceptor() {\r\n // Intercept fetch\r\n const originalFetch = window.fetch;\r\n window.fetch = async function (...args) {\r\n const start = Date.now();\r\n const req = args[0];\r\n const url = typeof req === 'string' ? req : req?.url || '';\r\n const method = (args[1]?.method || req?.method || 'GET').toUpperCase();\r\n\r\n try {\r\n const response = await originalFetch.apply(window, args);\r\n const size = parseInt(response.headers?.get('content-length') || '0', 10);\r\n networkLog.push({\r\n type: 'fetch', method, url,\r\n status: response.status, statusText: response.statusText,\r\n duration: Date.now() - start, size, timestamp: start,\r\n });\r\n if (networkLog.length > MAX_NETWORK_LOG) networkLog.shift();\r\n return response;\r\n } catch (err) {\r\n networkLog.push({\r\n type: 'fetch', method, url,\r\n status: 0, error: err.message,\r\n duration: Date.now() - start, timestamp: start,\r\n });\r\n if (networkLog.length > MAX_NETWORK_LOG) networkLog.shift();\r\n throw err;\r\n }\r\n };\r\n\r\n // Intercept XMLHttpRequest\r\n const origOpen = XMLHttpRequest.prototype.open;\r\n const origSend = XMLHttpRequest.prototype.send;\r\n\r\n XMLHttpRequest.prototype.open = function (method, url, ...rest) {\r\n this._wuAi = { method: (method || 'GET').toUpperCase(), url: String(url) };\r\n return origOpen.call(this, method, url, ...rest);\r\n };\r\n\r\n XMLHttpRequest.prototype.send = function (...args) {\r\n if (this._wuAi) {\r\n this._wuAi.start = Date.now();\r\n this.addEventListener('loadend', () => {\r\n networkLog.push({\r\n type: 'xhr', method: this._wuAi.method, url: this._wuAi.url,\r\n status: this.status, statusText: this.statusText,\r\n duration: Date.now() - this._wuAi.start,\r\n size: parseInt(this.getResponseHeader('content-length') || '0', 10),\r\n timestamp: this._wuAi.start,\r\n });\r\n if (networkLog.length > MAX_NETWORK_LOG) networkLog.shift();\r\n });\r\n }\r\n return origSend.apply(this, args);\r\n };\r\n}\r\n\r\nfunction _installConsoleInterceptor() {\r\n const levels = ['log', 'warn', 'error'];\r\n for (const level of levels) {\r\n const original = console[level];\r\n console[level] = (...args) => {\r\n consoleLog.push({\r\n level,\r\n message: args.map((a) => (typeof a === 'object' ? JSON.stringify(a) : String(a))).join(' '),\r\n timestamp: Date.now(),\r\n });\r\n if (consoleLog.length > MAX_CONSOLE_LOG) consoleLog.shift();\r\n original.apply(console, args);\r\n };\r\n }\r\n}\r\n","/**\r\n * WU-AI-ORCHESTRATE: Cross-Micro-App AI Coordination (Paradigm 4)\r\n *\r\n * The fourth paradigm of wu.ai:\r\n * Paradigm 1 — App sends messages to LLM (conversation)\r\n * Paradigm 2 — External LLM calls into app (tools/WebMCP)\r\n * Paradigm 3 — AI as autonomous director (agent loop)\r\n * Paradigm 4 — AI as microfrontend glue (this file)\r\n *\r\n * The Problem:\r\n * In microfrontend architectures, apps are isolated by design.\r\n * Cross-app coordination requires manual wiring through events\r\n * and shared state. As apps grow, wiring becomes n² complexity.\r\n *\r\n * The Solution:\r\n * Each micro-app declares its capabilities to the AI layer.\r\n * The AI understands the semantic meaning of each capability\r\n * and can resolve natural-language intents by calling the right\r\n * actions across the right apps — without tight coupling.\r\n *\r\n * Key Concepts:\r\n * - Capability: An action scoped to a specific micro-app\r\n * Registered as 'appName:actionName', cleaned up on unmount.\r\n * - Intent: A natural-language cross-app request resolved in\r\n * a single conversation turn with an orchestrator system prompt.\r\n * - Capability Map: The AI's understanding of system topology —\r\n * which apps exist and what each can do.\r\n *\r\n * This module does NOT replace actions, triggers, or agents.\r\n * It enriches them with cross-app topology awareness.\r\n *\r\n * API (accessible via wu.ai):\r\n * wu.ai.capability(app, name, config) → Register app-scoped capability\r\n * wu.ai.intent(description, options) → Resolve cross-app intent\r\n * wu.ai.removeApp(appName) → Cleanup on unmount\r\n * wu.ai.workflow(name, config) → Register reusable AI workflow\r\n * wu.ai.runWorkflow(name, params, opts) → Execute a registered workflow\r\n */\r\n\r\nimport { logger } from '../core/wu-logger.js';\r\nimport { clickElement, typeIntoElement } from './wu-ai-browser-primitives.js';\r\n\r\n// ─── Constants ──────────────────────────────────────────────────\r\n\r\nconst INTENT_NAMESPACE_PREFIX = 'intent:';\r\n\r\n// ─── Deterministic Step Actions ─────────────────────────────────\r\n\r\n/**\r\n * Execute a single deterministic workflow step.\r\n * No AI needed — directly calls browser primitives.\r\n *\r\n * @param {object} step - Step definition\r\n * @param {string} step.action - 'click' | 'type' | 'navigate' | 'wait' | 'emit' | 'setState'\r\n * @param {object} params - Interpolated params\r\n * @returns {{ success: boolean, detail?: string, error?: string }}\r\n */\r\nfunction executeDeterministicStep(step, eventBus, store) {\r\n switch (step.action) {\r\n case 'click': {\r\n const result = clickElement(step.selector, step.text);\r\n if (result.error) return { success: false, error: result.error };\r\n return { success: true, detail: `Clicked: ${step.selector || step.text}` };\r\n }\r\n\r\n case 'type': {\r\n const result = typeIntoElement(step.selector, step.value, {\r\n clear: step.clear ?? true,\r\n submit: step.submit ?? false,\r\n });\r\n if (result.error) return { success: false, error: result.error };\r\n return { success: true, detail: `Typed \"${step.value}\" into ${step.selector}` };\r\n }\r\n\r\n case 'navigate': {\r\n if (eventBus && step.section) {\r\n eventBus.emit('nav:section', { section: step.section }, { appName: 'wu-ai' });\r\n return { success: true, detail: `Navigated to section: ${step.section}` };\r\n }\r\n if (step.selector) {\r\n const result = clickElement(step.selector, step.text);\r\n if (result.error) return { success: false, error: result.error };\r\n return { success: true, detail: `Navigated via click: ${step.selector}` };\r\n }\r\n return { success: false, error: 'navigate requires \"section\" or \"selector\"' };\r\n }\r\n\r\n case 'wait': {\r\n // Wait is handled by the runner (delay + optional selector poll)\r\n return { success: true, detail: `Wait: ${step.ms || 0}ms` };\r\n }\r\n\r\n case 'emit': {\r\n if (!eventBus) return { success: false, error: 'eventBus not available' };\r\n eventBus.emit(step.event, step.data || {}, { appName: 'wu-ai' });\r\n return { success: true, detail: `Emitted: ${step.event}` };\r\n }\r\n\r\n case 'setState': {\r\n if (!store) return { success: false, error: 'store not available' };\r\n store.set(step.path, step.value);\r\n return { success: true, detail: `Set state: ${step.path}` };\r\n }\r\n\r\n default:\r\n return { success: false, error: `Unknown action: ${step.action}` };\r\n }\r\n}\r\n\r\n/**\r\n * Wait for a selector to appear in the DOM (with timeout).\r\n *\r\n * @param {string} selector\r\n * @param {number} timeout - ms\r\n * @returns {Promise<boolean>}\r\n */\r\nfunction waitForSelector(selector, timeout = 5000) {\r\n return new Promise((resolve) => {\r\n if (document.querySelector(selector)) {\r\n resolve(true);\r\n return;\r\n }\r\n\r\n const interval = 100;\r\n let elapsed = 0;\r\n const timer = setInterval(() => {\r\n elapsed += interval;\r\n if (document.querySelector(selector)) {\r\n clearInterval(timer);\r\n resolve(true);\r\n } else if (elapsed >= timeout) {\r\n clearInterval(timer);\r\n resolve(false);\r\n }\r\n }, interval);\r\n });\r\n}\r\n\r\n/**\r\n * Simple delay.\r\n */\r\nfunction delay(ms) {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\n// ─── WuAIOrchestrate ────────────────────────────────────────────\r\n\r\nexport class WuAIOrchestrate {\r\n /**\r\n * @param {object} deps\r\n * @param {import('./wu-ai-actions.js').WuAIActions} deps.actions\r\n * @param {import('./wu-ai-conversation.js').WuAIConversation} deps.conversation\r\n * @param {import('./wu-ai-context.js').WuAIContext} deps.context\r\n * @param {import('./wu-ai-permissions.js').WuAIPermissions} deps.permissions\r\n * @param {object} deps.eventBus\r\n */\r\n constructor({ actions, conversation, context, permissions, eventBus, agent, store }) {\r\n this._actions = actions;\r\n this._conversation = conversation;\r\n this._context = context;\r\n this._permissions = permissions;\r\n this._eventBus = eventBus;\r\n this._agent = agent; // WuAIAgent — for workflow execution\r\n this._store = store; // WuStore — for deterministic setState steps\r\n\r\n // appName → Map<actionName, { description, qualifiedName }>\r\n this._capabilities = new Map();\r\n\r\n // name → { goal, steps, parameters, provider, ... }\r\n this._workflows = new Map();\r\n\r\n this._config = {\r\n defaultProvider: null,\r\n defaultTemperature: 0.3, // lower temp for orchestration\r\n };\r\n\r\n this._stats = {\r\n totalIntents: 0,\r\n resolvedIntents: 0,\r\n failedIntents: 0,\r\n workflowsRegistered: 0,\r\n workflowsExecuted: 0,\r\n };\r\n }\r\n\r\n /**\r\n * Post-init configuration.\r\n *\r\n * @param {object} config\r\n * @param {string} [config.defaultProvider] - Default provider for intents\r\n * @param {number} [config.defaultTemperature] - Default temperature for intents\r\n */\r\n configure(config) {\r\n if (config.defaultProvider !== undefined) this._config.defaultProvider = config.defaultProvider;\r\n if (config.defaultTemperature !== undefined) this._config.defaultTemperature = config.defaultTemperature;\r\n }\r\n\r\n // ─── Capability Registration ────────────────────────────────────\r\n\r\n /**\r\n * Register a capability scoped to a micro-app.\r\n *\r\n * Under the hood this registers a normal action with the qualified\r\n * name 'appName:actionName' so the LLM can call it directly.\r\n * The capability map is tracked separately for lifecycle management\r\n * (removeApp) and system prompt enrichment.\r\n *\r\n * @param {string} appName - The micro-app name (e.g., 'orders', 'dashboard')\r\n * @param {string} actionName - The capability name (e.g., 'getRecent', 'updateKPIs')\r\n * @param {object} config - Same as wu.ai.action() config:\r\n * { description, parameters, handler, confirm?, permissions?, dangerous? }\r\n */\r\n register(appName, actionName, config) {\r\n if (!appName || !actionName) {\r\n throw new Error('[wu-ai] capability() requires both appName and actionName');\r\n }\r\n if (!config || typeof config.handler !== 'function') {\r\n throw new Error(`[wu-ai] capability '${appName}:${actionName}' must have a handler function`);\r\n }\r\n\r\n const qualifiedName = `${appName}:${actionName}`;\r\n\r\n // Track in capability map\r\n if (!this._capabilities.has(appName)) {\r\n this._capabilities.set(appName, new Map());\r\n }\r\n this._capabilities.get(appName).set(actionName, {\r\n description: config.description || actionName,\r\n qualifiedName,\r\n });\r\n\r\n // Register as a normal action with enriched description\r\n this._actions.register(qualifiedName, {\r\n ...config,\r\n description: `[${appName}] ${config.description || actionName}`,\r\n });\r\n\r\n logger.wuDebug(`[wu-ai] Capability registered: ${qualifiedName}`);\r\n }\r\n\r\n /**\r\n * Remove a single capability.\r\n *\r\n * @param {string} appName\r\n * @param {string} actionName\r\n */\r\n unregister(appName, actionName) {\r\n const appCaps = this._capabilities.get(appName);\r\n if (!appCaps) return;\r\n\r\n const qualifiedName = `${appName}:${actionName}`;\r\n appCaps.delete(actionName);\r\n this._actions.unregister(qualifiedName);\r\n\r\n // Clean up empty app entry\r\n if (appCaps.size === 0) {\r\n this._capabilities.delete(appName);\r\n }\r\n }\r\n\r\n /**\r\n * Remove all capabilities for a micro-app (unmount cleanup).\r\n *\r\n * Call this when a micro-app is unmounted to prevent stale\r\n * capabilities from appearing in the AI's capability map.\r\n *\r\n * @param {string} appName\r\n * @returns {number} Number of capabilities removed\r\n */\r\n removeApp(appName) {\r\n const appCaps = this._capabilities.get(appName);\r\n if (!appCaps) return 0;\r\n\r\n let removed = 0;\r\n for (const [actionName] of appCaps) {\r\n const qualifiedName = `${appName}:${actionName}`;\r\n this._actions.unregister(qualifiedName);\r\n removed++;\r\n }\r\n\r\n this._capabilities.delete(appName);\r\n\r\n logger.wuDebug(`[wu-ai] All capabilities removed for app '${appName}' (${removed})`);\r\n\r\n this._eventBus.emit('ai:app:removed', {\r\n appName,\r\n capabilitiesRemoved: removed,\r\n }, { appName: 'wu-ai' });\r\n\r\n return removed;\r\n }\r\n\r\n // ─── Capability Map ─────────────────────────────────────────────\r\n\r\n /**\r\n * Get the full capability map grouped by app.\r\n *\r\n * Used for system prompt enrichment and debugging.\r\n *\r\n * @returns {object} { appName: [{ action, description }], ... }\r\n */\r\n getCapabilityMap() {\r\n const map = {};\r\n for (const [appName, actions] of this._capabilities) {\r\n map[appName] = [];\r\n for (const [, meta] of actions) {\r\n map[appName].push({\r\n action: meta.qualifiedName,\r\n description: meta.description,\r\n });\r\n }\r\n }\r\n return map;\r\n }\r\n\r\n /**\r\n * Get app names that have registered capabilities.\r\n *\r\n * @returns {string[]}\r\n */\r\n getRegisteredApps() {\r\n return [...this._capabilities.keys()];\r\n }\r\n\r\n /**\r\n * Check if an app has registered capabilities.\r\n *\r\n * @param {string} appName\r\n * @returns {boolean}\r\n */\r\n hasApp(appName) {\r\n return this._capabilities.has(appName);\r\n }\r\n\r\n /**\r\n * Get the total number of registered capabilities across all apps.\r\n *\r\n * @returns {number}\r\n */\r\n getTotalCapabilities() {\r\n let count = 0;\r\n for (const actions of this._capabilities.values()) {\r\n count += actions.size;\r\n }\r\n return count;\r\n }\r\n\r\n // ─── Intent Resolution ──────────────────────────────────────────\r\n\r\n /**\r\n * Resolve a cross-app intent in a single conversation turn.\r\n *\r\n * The AI receives:\r\n * - The full capability map (what each app can do)\r\n * - Current application state (via context)\r\n * - Mounted apps list\r\n * - All registered tools (capabilities are tools)\r\n *\r\n * Unlike agent(), this is NOT a multi-step autonomous loop.\r\n * The LLM resolves the intent in one logical request (which may\r\n * include multiple tool calls within the conversation's tool-call\r\n * loop, but conceptually is a single turn).\r\n *\r\n * Unlike send(), the namespace is ephemeral and auto-cleaned,\r\n * and the system prompt is auto-built with the capability map.\r\n *\r\n * @param {string} description - Natural language intent\r\n * e.g., \"Show me the top customer by order count\"\r\n * e.g., \"Update dashboard stats and notify the topbar\"\r\n * @param {object} [options]\r\n * @param {string[]} [options.plan] - Optional action sequence hint.\r\n * The AI uses this as guidance but can deviate if needed.\r\n * e.g., ['orders:getRecent', 'customers:lookup']\r\n * @param {string} [options.provider] - LLM provider override\r\n * @param {number} [options.temperature] - Temperature override\r\n * @param {number} [options.maxTokens] - Max tokens override\r\n * @param {AbortSignal} [options.signal] - Abort signal\r\n * @param {string|object} [options.responseFormat] - Response format\r\n * @returns {Promise<{\r\n * content: string,\r\n * tool_results: Array,\r\n * usage: object|null,\r\n * resolved: boolean,\r\n * appsInvolved: string[]\r\n * }>}\r\n */\r\n async resolve(description, options = {}) {\r\n if (!description || typeof description !== 'string') {\r\n throw new Error('[wu-ai] intent() requires a description string');\r\n }\r\n\r\n this._stats.totalIntents++;\r\n const namespace = this._generateNamespace();\r\n\r\n // Collect fresh context before building the prompt\r\n if (this._context) {\r\n try {\r\n await this._context.collect();\r\n } catch {\r\n // Context collection is best-effort\r\n }\r\n }\r\n\r\n const systemPrompt = this._buildOrchestratorPrompt(options);\r\n\r\n this._eventBus.emit('ai:intent:start', {\r\n description: description.slice(0, 200),\r\n namespace,\r\n capabilities: this.getTotalCapabilities(),\r\n }, { appName: 'wu-ai' });\r\n\r\n try {\r\n const response = await this._conversation.send(description, {\r\n namespace,\r\n systemPrompt,\r\n provider: options.provider || this._config.defaultProvider,\r\n temperature: options.temperature ?? this._config.defaultTemperature,\r\n maxTokens: options.maxTokens,\r\n signal: options.signal,\r\n responseFormat: options.responseFormat,\r\n });\r\n\r\n const toolResults = response.tool_results || [];\r\n const appsInvolved = this._extractInvolvedApps(toolResults);\r\n const resolved = !!(response.content);\r\n\r\n if (resolved) {\r\n this._stats.resolvedIntents++;\r\n } else {\r\n this._stats.failedIntents++;\r\n }\r\n\r\n const result = {\r\n content: response.content || '',\r\n tool_results: toolResults,\r\n usage: response.usage || null,\r\n resolved,\r\n appsInvolved,\r\n };\r\n\r\n this._eventBus.emit('ai:intent:resolved', {\r\n description: description.slice(0, 200),\r\n resolved,\r\n appsInvolved,\r\n }, { appName: 'wu-ai' });\r\n\r\n return result;\r\n } catch (err) {\r\n this._stats.failedIntents++;\r\n\r\n this._eventBus.emit('ai:intent:error', {\r\n description: description.slice(0, 200),\r\n error: err.message,\r\n }, { appName: 'wu-ai' });\r\n\r\n throw err;\r\n } finally {\r\n // Always clean up the ephemeral namespace\r\n this._conversation.deleteNamespace(namespace);\r\n }\r\n }\r\n\r\n // ─── System Prompt Builder ──────────────────────────────────────\r\n\r\n /**\r\n * Build the orchestrator system prompt with full capability map.\r\n *\r\n * This method is also available to other modules (triggers, agents)\r\n * that want capability-aware system prompts.\r\n *\r\n * @param {object} [options]\r\n * @param {string[]} [options.plan] - Optional action sequence hint\r\n * @returns {string}\r\n */\r\n buildOrchestratorPrompt(options = {}) {\r\n return this._buildOrchestratorPrompt(options);\r\n }\r\n\r\n /** @private */\r\n _buildOrchestratorPrompt(options = {}) {\r\n const parts = [];\r\n\r\n parts.push(\r\n 'You are an AI orchestrator for a microfrontend application.',\r\n 'Multiple independent apps are mounted, each with specific capabilities.',\r\n 'Resolve cross-app requests by calling the right capabilities in the right order.',\r\n '',\r\n 'RULES:',\r\n '- Call capabilities (tools) to gather data or trigger actions.',\r\n '- You may call multiple capabilities from different apps if needed.',\r\n '- Synthesize results into a clear, actionable response.',\r\n '- If a required app is not available or lacks a capability, explain what is missing.',\r\n '',\r\n );\r\n\r\n // Capability map\r\n const capMap = this.getCapabilityMap();\r\n const appNames = Object.keys(capMap);\r\n\r\n if (appNames.length > 0) {\r\n parts.push('CAPABILITY MAP:');\r\n for (const appName of appNames) {\r\n parts.push(` ${appName}:`);\r\n for (const cap of capMap[appName]) {\r\n parts.push(` - ${cap.action}: ${cap.description}`);\r\n }\r\n }\r\n parts.push('');\r\n } else {\r\n parts.push(\r\n 'NOTE: No app capabilities are registered. Answer based on available context only.',\r\n '',\r\n );\r\n }\r\n\r\n // Optional plan hint\r\n if (options.plan && options.plan.length > 0) {\r\n parts.push(\r\n 'SUGGESTED PLAN (follow this unless a better approach is evident):',\r\n );\r\n for (let i = 0; i < options.plan.length; i++) {\r\n parts.push(` ${i + 1}. ${options.plan[i]}`);\r\n }\r\n parts.push('');\r\n }\r\n\r\n // Context snapshot (state, mounted apps)\r\n const snapshot = this._context?.getSnapshot();\r\n if (snapshot?._mountedApps?.length) {\r\n parts.push(`MOUNTED APPS: ${snapshot._mountedApps.join(', ')}`, '');\r\n }\r\n if (snapshot?._store && Object.keys(snapshot._store).length > 0) {\r\n parts.push(\r\n 'CURRENT STATE:',\r\n JSON.stringify(snapshot._store, null, 2),\r\n '',\r\n );\r\n }\r\n\r\n return parts.join('\\n');\r\n }\r\n\r\n // ─── Workflows ─────────────────────────────────────────────────\r\n\r\n /**\r\n * Register a reusable AI workflow.\r\n *\r\n * A workflow is a named, parameterized recipe that the AI agent\r\n * follows step by step. Think of it as a macro: you define it once,\r\n * then run it whenever you need with different parameters.\r\n *\r\n * The AI receives the steps as instructions and uses browser actions\r\n * (screenshot, click, type) plus any registered capabilities/actions\r\n * to execute them. You can watch every step in real time.\r\n *\r\n * @param {string} name - Workflow name (e.g., 'register-user')\r\n * @param {object} config\r\n * @param {string} config.description - What this workflow does\r\n * @param {string[]} config.steps - Step-by-step instructions for the AI\r\n * @param {object} [config.parameters] - Parameter definitions for interpolation\r\n * e.g., { name: { type: 'string', required: true }, email: { type: 'string' } }\r\n * @param {number} [config.maxSteps=15] - Max agent steps allowed\r\n * @param {string} [config.provider] - LLM provider to use\r\n * @param {number} [config.temperature] - Temperature (default: 0.2 for precision)\r\n *\r\n * @example\r\n * // ── AI Mode (default): steps are natural language ──\r\n * wu.ai.workflow('register-user', {\r\n * description: 'Register a new user in the system',\r\n * steps: [\r\n * 'Navigate to the Customers section',\r\n * 'Click the \"Add Customer\" button',\r\n * 'Fill in the name field with {{name}}',\r\n * 'Click Submit',\r\n * ],\r\n * parameters: { name: { type: 'string', required: true } },\r\n * });\r\n *\r\n * // ── Deterministic Mode: steps are exact actions, NO AI NEEDED ──\r\n * wu.ai.workflow('register-user', {\r\n * mode: 'deterministic',\r\n * description: 'Register a new user',\r\n * steps: [\r\n * { action: 'navigate', section: 'customers' },\r\n * { action: 'click', selector: '#add-customer-btn' },\r\n * { action: 'type', selector: '#name', value: '{{name}}' },\r\n * { action: 'type', selector: '#email', value: '{{email}}' },\r\n * { action: 'click', selector: '#submit-btn' },\r\n * { action: 'wait', selector: '.success-message', timeout: 5000 },\r\n * ],\r\n * parameters: {\r\n * name: { type: 'string', required: true },\r\n * email: { type: 'string', required: true },\r\n * },\r\n * });\r\n */\r\n registerWorkflow(name, config) {\r\n if (!name) {\r\n throw new Error('[wu-ai] workflow() requires a name');\r\n }\r\n if (!config || !config.steps || !Array.isArray(config.steps) || config.steps.length === 0) {\r\n throw new Error(`[wu-ai] workflow '${name}' must have a non-empty steps array`);\r\n }\r\n\r\n // Detect mode: if steps are objects with 'action', it's deterministic\r\n const mode = config.mode || (\r\n config.steps.length > 0 && typeof config.steps[0] === 'object' && config.steps[0].action\r\n ? 'deterministic'\r\n : 'ai'\r\n );\r\n\r\n this._workflows.set(name, {\r\n description: config.description || name,\r\n steps: config.steps,\r\n mode,\r\n parameters: config.parameters || {},\r\n maxSteps: config.maxSteps ?? 15,\r\n provider: config.provider || null,\r\n temperature: config.temperature ?? 0.2,\r\n });\r\n\r\n this._stats.workflowsRegistered++;\r\n\r\n logger.wuDebug(`[wu-ai] Workflow registered: '${name}' (${config.steps.length} steps)`);\r\n }\r\n\r\n /**\r\n * Execute a registered workflow with parameters.\r\n *\r\n * Returns an async generator (like agent) — you iterate over it\r\n * to observe each step in real time.\r\n *\r\n * @param {string} name - Workflow name\r\n * @param {object} [params={}] - Parameters to interpolate into steps\r\n * e.g., { name: 'Juan Pérez', email: 'juan@test.com' }\r\n * @param {object} [options={}]\r\n * @param {Function} [options.onStep] - Callback per step\r\n * @param {Function} [options.shouldContinue] - Human-in-the-loop gate\r\n * @param {AbortSignal} [options.signal] - Abort signal\r\n * @returns {AsyncGenerator<AgentStepResult>}\r\n *\r\n * @example\r\n * for await (const step of wu.ai.runWorkflow('register-user', {\r\n * name: 'Juan Pérez',\r\n * email: 'juan@test.com',\r\n * })) {\r\n * console.log(`Paso ${step.step}: ${step.content}`);\r\n * if (step.type === 'done') console.log('Workflow completado!');\r\n * }\r\n *\r\n * // With human approval per step:\r\n * for await (const step of wu.ai.runWorkflow('register-user', params, {\r\n * shouldContinue: (step) => confirm(`¿Continuar? ${step.content?.slice(0, 60)}`),\r\n * })) {\r\n * renderStep(step);\r\n * }\r\n */\r\n async *executeWorkflow(name, params = {}, options = {}) {\r\n const workflow = this._workflows.get(name);\r\n if (!workflow) {\r\n throw new Error(`[wu-ai] Workflow '${name}' is not registered`);\r\n }\r\n\r\n // Validate required parameters\r\n for (const [paramName, paramConfig] of Object.entries(workflow.parameters)) {\r\n if (paramConfig.required && (params[paramName] === undefined || params[paramName] === null)) {\r\n throw new Error(`[wu-ai] Workflow '${name}' requires parameter '${paramName}'`);\r\n }\r\n }\r\n\r\n this._stats.workflowsExecuted++;\r\n\r\n // Branch on mode\r\n if (workflow.mode === 'deterministic') {\r\n yield* this._executeDeterministic(name, workflow, params, options);\r\n } else {\r\n yield* this._executeWithAgent(name, workflow, params, options);\r\n }\r\n }\r\n\r\n /**\r\n * Execute workflow using the AI agent (natural language steps).\r\n * @private\r\n */\r\n async *_executeWithAgent(name, workflow, params, options) {\r\n if (!this._agent) {\r\n throw new Error('[wu-ai] Agent module not available for workflow execution');\r\n }\r\n\r\n // Interpolate parameters into string steps\r\n const interpolatedSteps = workflow.steps.map(step => {\r\n let result = step;\r\n for (const [key, value] of Object.entries(params)) {\r\n result = result.replace(new RegExp(`\\\\{\\\\{${key}\\\\}\\\\}`, 'g'), String(value));\r\n }\r\n return result;\r\n });\r\n\r\n const goal = this._buildWorkflowGoal(workflow, interpolatedSteps, params);\r\n\r\n this._eventBus.emit('ai:workflow:start', {\r\n workflow: name,\r\n mode: 'ai',\r\n params,\r\n steps: interpolatedSteps.length,\r\n }, { appName: 'wu-ai' });\r\n\r\n let finalStep = null;\r\n\r\n try {\r\n yield* this._agent.run(goal, {\r\n maxSteps: workflow.maxSteps,\r\n provider: options.provider || workflow.provider || this._config.defaultProvider,\r\n temperature: workflow.temperature ?? 0.2,\r\n onStep: (step) => {\r\n finalStep = step;\r\n if (options.onStep) options.onStep(step);\r\n },\r\n shouldContinue: options.shouldContinue,\r\n signal: options.signal,\r\n });\r\n } finally {\r\n this._eventBus.emit('ai:workflow:done', {\r\n workflow: name,\r\n params,\r\n totalSteps: finalStep?.step || 0,\r\n result: finalStep?.type || 'unknown',\r\n }, { appName: 'wu-ai' });\r\n }\r\n }\r\n\r\n /**\r\n * Execute workflow deterministically — NO AI NEEDED.\r\n * Steps are exact actions: { action: 'click', selector: '#btn' }\r\n * @private\r\n */\r\n async *_executeDeterministic(name, workflow, params, options) {\r\n // Interpolate parameters into step values\r\n const steps = workflow.steps.map(step => {\r\n const interpolated = { ...step };\r\n for (const [key, value] of Object.entries(params)) {\r\n const pattern = new RegExp(`\\\\{\\\\{${key}\\\\}\\\\}`, 'g');\r\n for (const field of ['value', 'selector', 'text', 'section', 'event', 'path']) {\r\n if (typeof interpolated[field] === 'string') {\r\n interpolated[field] = interpolated[field].replace(pattern, String(value));\r\n }\r\n }\r\n }\r\n return interpolated;\r\n });\r\n\r\n this._eventBus?.emit('ai:workflow:start', {\r\n workflow: name,\r\n mode: 'deterministic',\r\n params,\r\n steps: steps.length,\r\n }, { appName: 'wu-ai' });\r\n\r\n let lastStep = null;\r\n\r\n try {\r\n for (let i = 0; i < steps.length; i++) {\r\n const step = steps[i];\r\n const stepNum = i + 1;\r\n const startTime = Date.now();\r\n\r\n // Check abort\r\n if (options.signal?.aborted) {\r\n const result = {\r\n step: stepNum,\r\n type: 'aborted',\r\n content: 'Workflow aborted',\r\n reason: 'Aborted by caller',\r\n elapsed: 0,\r\n };\r\n lastStep = result;\r\n yield result;\r\n return;\r\n }\r\n\r\n // Handle 'wait' specially — it's async\r\n if (step.action === 'wait') {\r\n if (step.selector) {\r\n const found = await waitForSelector(step.selector, step.timeout || 5000);\r\n const elapsed = Date.now() - startTime;\r\n const result = {\r\n step: stepNum,\r\n type: found ? 'action' : 'error',\r\n content: found\r\n ? `Waited for \"${step.selector}\" — found`\r\n : `Timeout waiting for \"${step.selector}\"`,\r\n elapsed,\r\n };\r\n lastStep = result;\r\n if (options.onStep) options.onStep(result);\r\n yield result;\r\n if (!found) return; // stop on timeout\r\n } else if (step.ms) {\r\n await delay(step.ms);\r\n const result = {\r\n step: stepNum,\r\n type: 'action',\r\n content: `Waited ${step.ms}ms`,\r\n elapsed: step.ms,\r\n };\r\n lastStep = result;\r\n if (options.onStep) options.onStep(result);\r\n yield result;\r\n }\r\n continue;\r\n }\r\n\r\n // Execute the step\r\n const execResult = executeDeterministicStep(step, this._eventBus, this._store);\r\n const elapsed = Date.now() - startTime;\r\n\r\n const stepResult = {\r\n step: stepNum,\r\n type: execResult.success ? 'action' : 'error',\r\n content: execResult.success ? execResult.detail : execResult.error,\r\n elapsed,\r\n };\r\n\r\n lastStep = stepResult;\r\n if (options.onStep) options.onStep(stepResult);\r\n yield stepResult;\r\n\r\n // Human-in-the-loop gate\r\n if (options.shouldContinue) {\r\n let shouldGo;\r\n try {\r\n shouldGo = await options.shouldContinue(stepResult);\r\n } catch {\r\n shouldGo = false;\r\n }\r\n if (!shouldGo) {\r\n const interrupted = {\r\n step: stepNum,\r\n type: 'interrupted',\r\n content: 'Stopped by user',\r\n reason: 'shouldContinue returned false',\r\n elapsed: 0,\r\n };\r\n lastStep = interrupted;\r\n yield interrupted;\r\n return;\r\n }\r\n }\r\n\r\n // Stop on error\r\n if (!execResult.success) return;\r\n\r\n // Small delay between steps for UI to update\r\n if (i < steps.length - 1) {\r\n await delay(step.delay ?? 200);\r\n }\r\n }\r\n\r\n // All steps completed\r\n const done = {\r\n step: steps.length,\r\n type: 'done',\r\n content: `Workflow \"${name}\" completed (${steps.length} steps)`,\r\n reason: 'All steps executed',\r\n elapsed: 0,\r\n };\r\n lastStep = done;\r\n if (options.onStep) options.onStep(done);\r\n yield done;\r\n\r\n } finally {\r\n this._eventBus?.emit('ai:workflow:done', {\r\n workflow: name,\r\n mode: 'deterministic',\r\n params,\r\n totalSteps: lastStep?.step || 0,\r\n result: lastStep?.type || 'unknown',\r\n }, { appName: 'wu-ai' });\r\n }\r\n }\r\n\r\n /**\r\n * Check if a workflow is registered.\r\n *\r\n * @param {string} name\r\n * @returns {boolean}\r\n */\r\n hasWorkflow(name) {\r\n return this._workflows.has(name);\r\n }\r\n\r\n /**\r\n * Get a workflow definition.\r\n *\r\n * @param {string} name\r\n * @returns {object|null}\r\n */\r\n getWorkflow(name) {\r\n const w = this._workflows.get(name);\r\n if (!w) return null;\r\n return {\r\n description: w.description,\r\n steps: [...w.steps],\r\n mode: w.mode,\r\n parameters: { ...w.parameters },\r\n maxSteps: w.maxSteps,\r\n };\r\n }\r\n\r\n /**\r\n * Remove a registered workflow.\r\n *\r\n * @param {string} name\r\n */\r\n removeWorkflow(name) {\r\n this._workflows.delete(name);\r\n }\r\n\r\n /**\r\n * Get all workflow names.\r\n *\r\n * @returns {string[]}\r\n */\r\n getWorkflowNames() {\r\n return [...this._workflows.keys()];\r\n }\r\n\r\n /** @private */\r\n _buildWorkflowGoal(workflow, steps, params) {\r\n const parts = [];\r\n\r\n parts.push(\r\n `WORKFLOW: ${workflow.description}`,\r\n '',\r\n 'You must follow these steps IN ORDER. Use browser tools (screenshot, click, type)',\r\n 'to interact with the application. After each step, take a screenshot to verify.',\r\n '',\r\n 'STEPS:',\r\n );\r\n\r\n for (let i = 0; i < steps.length; i++) {\r\n parts.push(` ${i + 1}. ${steps[i]}`);\r\n }\r\n\r\n parts.push(\r\n '',\r\n 'After completing all steps successfully, respond with [DONE].',\r\n 'If a step fails, explain what went wrong.',\r\n );\r\n\r\n // Add capability context if available\r\n const capMap = this.getCapabilityMap();\r\n const appNames = Object.keys(capMap);\r\n if (appNames.length > 0) {\r\n parts.push('', 'AVAILABLE APP CAPABILITIES:');\r\n for (const appName of appNames) {\r\n for (const cap of capMap[appName]) {\r\n parts.push(` - ${cap.action}: ${cap.description}`);\r\n }\r\n }\r\n }\r\n\r\n return parts.join('\\n');\r\n }\r\n\r\n // ─── Stats & Lifecycle ──────────────────────────────────────────\r\n\r\n getStats() {\r\n return {\r\n ...this._stats,\r\n registeredApps: this.getRegisteredApps(),\r\n totalCapabilities: this.getTotalCapabilities(),\r\n capabilityMap: this.getCapabilityMap(),\r\n workflows: this.getWorkflowNames(),\r\n config: { ...this._config },\r\n };\r\n }\r\n\r\n destroy() {\r\n // Remove all capabilities from the action registry\r\n for (const [appName, actions] of this._capabilities) {\r\n for (const [actionName] of actions) {\r\n this._actions.unregister(`${appName}:${actionName}`);\r\n }\r\n }\r\n this._capabilities.clear();\r\n this._workflows.clear();\r\n\r\n this._stats = {\r\n totalIntents: 0,\r\n resolvedIntents: 0,\r\n failedIntents: 0,\r\n workflowsRegistered: 0,\r\n workflowsExecuted: 0,\r\n };\r\n }\r\n\r\n // ─── Private Helpers ────────────────────────────────────────────\r\n\r\n /**\r\n * Extract app names from tool results based on qualified action names.\r\n * e.g., tool name 'orders:getRecent' → app 'orders'\r\n */\r\n _extractInvolvedApps(toolResults) {\r\n if (!toolResults || !Array.isArray(toolResults)) return [];\r\n const apps = new Set();\r\n for (const result of toolResults) {\r\n const name = result.name || result.tool || '';\r\n const colonIdx = name.indexOf(':');\r\n if (colonIdx > 0) {\r\n apps.add(name.slice(0, colonIdx));\r\n }\r\n }\r\n return [...apps];\r\n }\r\n\r\n _generateNamespace() {\r\n return INTENT_NAMESPACE_PREFIX + Date.now().toString(36) +\r\n '_' + Math.random().toString(36).slice(2, 6);\r\n }\r\n}\r\n","/**\r\n * WU-AI Browser Actions\r\n *\r\n * Registers browser automation tools into wu.ai so any LLM provider\r\n * (OpenAI, Claude, Gemini, Ollama, etc.) can autonomously see and\r\n * control the page — no human intervention required.\r\n *\r\n * Tools registered:\r\n * browser_screenshot — Capture page/element as PNG (Canvas API)\r\n * browser_click — Click element by selector or visible text\r\n * browser_type — Type into inputs (React/Vue/framework compatible)\r\n * browser_snapshot — Get accessibility tree of the DOM\r\n * browser_navigate — Navigate SPA routes\r\n * browser_network — View captured HTTP requests (fetch + XHR)\r\n * browser_console — View captured console messages\r\n * browser_info — Get page state: apps, store, URL, viewport\r\n * browser_select — Select option in dropdowns\r\n * browser_scroll — Scroll page or element\r\n *\r\n * @example\r\n * // Auto-registered when wu.ai initializes\r\n * // Any LLM connected via wu.ai.provider can now use these tools:\r\n * const tools = wu.ai.tools();\r\n * // → includes browser_screenshot, browser_click, etc.\r\n */\r\n\r\nimport {\r\n ensureInterceptors,\r\n networkLog,\r\n consoleLog,\r\n captureScreenshot,\r\n buildA11yTree,\r\n clickElement,\r\n typeIntoElement,\r\n getFilteredNetwork,\r\n getFilteredConsole,\r\n} from './wu-ai-browser-primitives.js';\r\n\r\n/**\r\n * Register all browser automation actions into a WuAI instance.\r\n *\r\n * @param {object} ai - The WuAI instance (wu.ai)\r\n * @param {object} wu - The Wu Framework instance (window.wu)\r\n */\r\nexport function registerBrowserActions(ai, wu) {\r\n ensureInterceptors();\r\n\r\n // ════════════════════════════════════════════\r\n // SCREENSHOT — Canvas API (SVG foreignObject)\r\n // ════════════════════════════════════════════\r\n\r\n ai.action('browser_screenshot', {\r\n description: 'Take a screenshot of the current page or a specific element. Returns a base64 PNG image. Use this to SEE what the user sees.',\r\n parameters: {\r\n selector: {\r\n type: 'string',\r\n description: 'CSS selector of the element to capture. Empty = full visible page.',\r\n required: false,\r\n },\r\n },\r\n handler: async (params) => captureScreenshot(params.selector),\r\n permissions: [],\r\n });\r\n\r\n // ════════════════════════════════════════════\r\n // CLICK\r\n // ════════════════════════════════════════════\r\n\r\n ai.action('browser_click', {\r\n description: 'Click an element on the page. Find by CSS selector or by visible text content. Use this to interact with buttons, links, tabs, etc.',\r\n parameters: {\r\n selector: {\r\n type: 'string',\r\n description: 'CSS selector (e.g. \"#submit-btn\", \".nav-link\", \"button[type=submit]\")',\r\n required: false,\r\n },\r\n text: {\r\n type: 'string',\r\n description: 'Visible text to find and click (e.g. \"Submit\", \"Next\", \"Guardar\"). Searches buttons, links, and clickable elements.',\r\n required: false,\r\n },\r\n },\r\n handler: async (params, api) => {\r\n const result = clickElement(params.selector, params.text);\r\n if (!result.error) {\r\n api.emit?.('browser:clicked', { selector: params.selector, text: params.text });\r\n }\r\n return result;\r\n },\r\n permissions: ['emitEvents'],\r\n });\r\n\r\n // ════════════════════════════════════════════\r\n // TYPE\r\n // ════════════════════════════════════════════\r\n\r\n ai.action('browser_type', {\r\n description: 'Type text into an input, textarea, or contenteditable element. Works with React, Vue, Angular, and other frameworks. Can optionally clear existing text first and submit the form.',\r\n parameters: {\r\n selector: {\r\n type: 'string',\r\n description: 'CSS selector of the input (e.g. \"#email\", \"input[name=search]\", \"textarea.comment\")',\r\n required: true,\r\n },\r\n text: {\r\n type: 'string',\r\n description: 'Text to type into the element',\r\n required: true,\r\n },\r\n clear: {\r\n type: 'boolean',\r\n description: 'Clear existing value before typing (default: false)',\r\n required: false,\r\n },\r\n submit: {\r\n type: 'boolean',\r\n description: 'Submit the form or press Enter after typing (default: false)',\r\n required: false,\r\n },\r\n },\r\n handler: async (params, api) => {\r\n const result = typeIntoElement(params.selector, params.text, {\r\n clear: params.clear,\r\n submit: params.submit,\r\n });\r\n if (!result.error) {\r\n api.emit?.('browser:typed', { selector: params.selector, length: params.text.length });\r\n }\r\n return result;\r\n },\r\n permissions: ['emitEvents'],\r\n });\r\n\r\n // ════════════════════════════════════════════\r\n // SELECT (dropdowns)\r\n // ════════════════════════════════════════════\r\n\r\n ai.action('browser_select', {\r\n description: 'Select an option in a <select> dropdown or a custom dropdown component.',\r\n parameters: {\r\n selector: {\r\n type: 'string',\r\n description: 'CSS selector of the <select> element',\r\n required: true,\r\n },\r\n value: {\r\n type: 'string',\r\n description: 'The value attribute of the option to select. Use \"text:\" prefix to match by visible text (e.g. \"text:Mexico\")',\r\n required: true,\r\n },\r\n },\r\n handler: async (params, api) => {\r\n const el = document.querySelector(params.selector);\r\n if (!el) return { error: `Element not found: ${params.selector}` };\r\n\r\n if (el.tagName?.toLowerCase() === 'select') {\r\n const options = Array.from(el.options);\r\n let option;\r\n\r\n if (params.value.startsWith('text:')) {\r\n const searchText = params.value.slice(5).toLowerCase();\r\n option = options.find((o) => o.textContent.trim().toLowerCase().includes(searchText));\r\n } else {\r\n option = options.find((o) => o.value === params.value);\r\n }\r\n\r\n if (!option) return { error: `Option not found: ${params.value}` };\r\n\r\n el.value = option.value;\r\n el.dispatchEvent(new Event('change', { bubbles: true }));\r\n el.dispatchEvent(new Event('input', { bubbles: true }));\r\n\r\n api.emit?.('browser:selected', { selector: params.selector, value: option.value });\r\n return { selected: option.value, text: option.textContent.trim() };\r\n }\r\n\r\n // Custom dropdown: try clicking the trigger, then the option\r\n el.click();\r\n return { clicked: params.selector, note: 'Custom dropdown — clicked trigger. Use browser_click to select an option from the opened menu.' };\r\n },\r\n permissions: ['emitEvents'],\r\n });\r\n\r\n // ════════════════════════════════════════════\r\n // SCROLL\r\n // ════════════════════════════════════════════\r\n\r\n ai.action('browser_scroll', {\r\n description: 'Scroll the page or a specific element. Use to reveal content that is not visible.',\r\n parameters: {\r\n direction: {\r\n type: 'string',\r\n description: 'Direction: \"up\", \"down\", \"top\", \"bottom\"',\r\n required: true,\r\n },\r\n selector: {\r\n type: 'string',\r\n description: 'CSS selector of scrollable container (empty = page)',\r\n required: false,\r\n },\r\n amount: {\r\n type: 'number',\r\n description: 'Pixels to scroll (default: 500). Ignored for \"top\"/\"bottom\".',\r\n required: false,\r\n },\r\n },\r\n handler: async (params) => {\r\n const target = params.selector\r\n ? document.querySelector(params.selector)\r\n : window;\r\n const amount = params.amount || 500;\r\n\r\n if (params.selector && !target) return { error: `Element not found: ${params.selector}` };\r\n\r\n const scrollEl = target === window ? document.documentElement : target;\r\n\r\n switch (params.direction) {\r\n case 'up': scrollEl.scrollBy({ top: -amount, behavior: 'smooth' }); break;\r\n case 'down': scrollEl.scrollBy({ top: amount, behavior: 'smooth' }); break;\r\n case 'top': scrollEl.scrollTo({ top: 0, behavior: 'smooth' }); break;\r\n case 'bottom': scrollEl.scrollTo({ top: scrollEl.scrollHeight, behavior: 'smooth' }); break;\r\n default: return { error: `Invalid direction: ${params.direction}` };\r\n }\r\n\r\n return {\r\n scrolled: params.direction,\r\n amount: params.direction === 'top' || params.direction === 'bottom' ? 'max' : amount,\r\n currentScroll: scrollEl.scrollTop,\r\n };\r\n },\r\n permissions: [],\r\n });\r\n\r\n // ════════════════════════════════════════════\r\n // SNAPSHOT — Accessibility tree\r\n // ════════════════════════════════════════════\r\n\r\n ai.action('browser_snapshot', {\r\n description: 'Get a text representation of the visible DOM structure (accessibility tree). Use this to understand what elements are on the page, their roles, IDs, and text content. Cheaper and faster than a screenshot.',\r\n parameters: {\r\n selector: {\r\n type: 'string',\r\n description: 'CSS selector to snapshot (empty = full page). Use \"[data-wu-app=appName]\" for a specific micro-app.',\r\n required: false,\r\n },\r\n depth: {\r\n type: 'number',\r\n description: 'Max depth to traverse (default: 5)',\r\n required: false,\r\n },\r\n },\r\n handler: async (params) => {\r\n const target = params.selector\r\n ? document.querySelector(params.selector)\r\n : document.body;\r\n\r\n if (!target) return { error: `Element not found: ${params.selector}` };\r\n\r\n const tree = buildA11yTree(target, 0, params.depth || 5);\r\n return { snapshot: tree };\r\n },\r\n permissions: [],\r\n });\r\n\r\n // ════════════════════════════════════════════\r\n // NAVIGATE\r\n // ════════════════════════════════════════════\r\n\r\n ai.action('browser_navigate', {\r\n description: 'Navigate to a route within the SPA application. Emits a shell:navigate event and updates the store.',\r\n parameters: {\r\n route: {\r\n type: 'string',\r\n description: 'Route path (e.g. \"/dashboard\", \"/users\", \"/pos/cotizador\")',\r\n required: true,\r\n },\r\n },\r\n handler: async (params, api) => {\r\n api.emit?.('shell:navigate', { route: params.route });\r\n api.setState?.('currentPath', params.route);\r\n return { navigated: params.route };\r\n },\r\n permissions: ['emitEvents', 'writeStore'],\r\n });\r\n\r\n // ════════════════════════════════════════════\r\n // NETWORK — Captured HTTP requests\r\n // ════════════════════════════════════════════\r\n\r\n ai.action('browser_network', {\r\n description: 'View captured HTTP network requests (fetch and XHR). Shows URL, method, status code, duration, and size. Use to debug API calls, check for errors, or monitor performance.',\r\n parameters: {\r\n method: {\r\n type: 'string',\r\n description: 'Filter by HTTP method: GET, POST, PUT, DELETE (empty = all)',\r\n required: false,\r\n },\r\n status: {\r\n type: 'string',\r\n description: 'Filter: \"2\" (2xx success), \"4\" (4xx errors), \"5\" (5xx errors), \"error\" (all failures)',\r\n required: false,\r\n },\r\n limit: {\r\n type: 'number',\r\n description: 'Max requests to return (default: 30)',\r\n required: false,\r\n },\r\n },\r\n handler: async (params) => getFilteredNetwork(params.method, params.status, params.limit),\r\n permissions: [],\r\n });\r\n\r\n // ════════════════════════════════════════════\r\n // CONSOLE — Captured logs\r\n // ════════════════════════════════════════════\r\n\r\n ai.action('browser_console', {\r\n description: 'View captured browser console messages (log, warn, error). Use to check for errors, warnings, or debug output.',\r\n parameters: {\r\n level: {\r\n type: 'string',\r\n description: 'Filter by level: \"log\", \"warn\", \"error\" (empty = all)',\r\n required: false,\r\n },\r\n limit: {\r\n type: 'number',\r\n description: 'Max messages to return (default: 30)',\r\n required: false,\r\n },\r\n },\r\n handler: async (params) => getFilteredConsole(params.level, params.limit),\r\n permissions: [],\r\n });\r\n\r\n // ════════════════════════════════════════════\r\n // INFO — Page state overview\r\n // ════════════════════════════════════════════\r\n\r\n ai.action('browser_info', {\r\n description: 'Get an overview of the current page state: URL, viewport size, mounted micro-apps, store keys, visible elements summary. Use this FIRST to understand the page before taking actions.',\r\n parameters: {},\r\n handler: async (params, api) => {\r\n const apps = [];\r\n\r\n // Discover mounted apps\r\n if (wu._apps) {\r\n for (const [name, app] of Object.entries(wu._apps)) {\r\n apps.push({\r\n name,\r\n mounted: app.mounted || app.isMounted || false,\r\n status: app.status || 'unknown',\r\n });\r\n }\r\n }\r\n if (apps.length === 0) {\r\n document.querySelectorAll('[data-wu-app]').forEach((el) => {\r\n apps.push({ name: el.getAttribute('data-wu-app'), mounted: true });\r\n });\r\n }\r\n\r\n const storeData = api.getState?.('') || {};\r\n const storeKeys = typeof storeData === 'object' ? Object.keys(storeData) : [];\r\n\r\n return {\r\n url: window.location.href,\r\n title: document.title,\r\n viewport: { width: window.innerWidth, height: window.innerHeight },\r\n apps,\r\n storeKeys,\r\n networkRequests: networkLog.length,\r\n consoleMessages: consoleLog.length,\r\n consoleErrors: consoleLog.filter((m) => m.level === 'error').length,\r\n };\r\n },\r\n permissions: ['readStore'],\r\n });\r\n}\r\n\r\n// All private helpers (buildA11yTree, inlineComputedStyles, interceptors)\r\n// are now in wu-ai-browser-primitives.js — single source of truth.\r\n","/**\r\n * WU-AI: Central orchestrator for AI integration\r\n *\r\n * This is the main entry point for wu.ai — it wires together all sub-modules\r\n * and exposes the public API. Lazy-initialized on first use.\r\n *\r\n * Architecture:\r\n * WuAI (this file)\r\n * ├── WuAIProvider → BYOL provider management (OpenAI, Anthropic, Ollama, Custom)\r\n * ├── WuAIPermissions → 4-layer security (perms, rate limit, circuit breaker, loop guard)\r\n * ├── WuAIContext → Auto context collection with token budget\r\n * ├── WuAIActions → Tool/action registry and sandboxed execution\r\n * ├── WuAIConversation → Multi-turn conversation manager with namespaces\r\n * ├── WuAITriggers → Event-to-AI reactive bridge\r\n * ├── WuAIAgent → Autonomous agent loop (goal → steps → done)\r\n * ├── WuAIOrchestrate → Cross-micro-app AI coordination (capabilities + intents)\r\n * └── BrowserPrimitives → Shared screenshot, click, type, a11y tree, interceptors\r\n *\r\n * Four Paradigms:\r\n * 1. App → LLM send/stream/json → conversation with tool loops\r\n * 2. LLM → App tools/execute/expose → external agents call into the app\r\n * 3. AI Director agent(goal) → autonomous multi-step loop\r\n * 4. MF Glue capability/intent → cross-app coordination via AI\r\n *\r\n * Public API (accessible via wu.ai):\r\n * wu.ai.provider(name, config) → Register LLM provider\r\n * wu.ai.send(message, opts) → Send message (non-streaming)\r\n * wu.ai.stream(message, opts) → Send message (streaming)\r\n * wu.ai.json(message, schema?) → Send and get parsed JSON back\r\n * wu.ai.agent(goal, opts) → Run autonomous agent loop\r\n * wu.ai.action(name, config) → Register an action/tool\r\n * wu.ai.trigger(name, config) → Register an event trigger\r\n * wu.ai.capability(app, name, c) → Register app-scoped capability\r\n * wu.ai.intent(desc, opts) → Resolve cross-app intent\r\n * wu.ai.removeApp(appName) → Remove app capabilities (unmount)\r\n * wu.ai.workflow(name, config) → Register reusable AI workflow\r\n * wu.ai.runWorkflow(name, params)→ Execute workflow (async generator)\r\n * wu.ai.context.configure(...) → Configure context collection\r\n * wu.ai.abort(namespace?) → Abort active request\r\n *\r\n * Paradigm 2 (External agent access):\r\n * wu.ai.tools() → Get all registered tools (for CDP/WebMCP)\r\n * wu.ai.execute(name, params) → Execute action directly (for external agents)\r\n * wu.ai.expose() → Register tools via WebMCP (navigator.modelContext)\r\n */\r\n\r\nimport { logger } from '../core/wu-logger.js';\r\nimport { WuAIProvider } from './wu-ai-provider.js';\r\nimport { WuAIPermissions } from './wu-ai-permissions.js';\r\nimport { WuAIContext } from './wu-ai-context.js';\r\nimport { WuAIActions } from './wu-ai-actions.js';\r\nimport { WuAIConversation } from './wu-ai-conversation.js';\r\nimport { WuAITriggers } from './wu-ai-triggers.js';\r\nimport { WuAIAgent } from './wu-ai-agent.js';\r\nimport { WuAIOrchestrate } from './wu-ai-orchestrate.js';\r\nimport { registerBrowserActions } from './wu-ai-browser.js';\r\n\r\nexport class WuAI {\r\n /**\r\n * @param {object} deps - Injected from WuCore\r\n * @param {object} deps.eventBus - WuEventBus instance\r\n * @param {object} deps.store - WuStore instance\r\n * @param {object} deps.core - WuCore instance (for mounted apps)\r\n */\r\n constructor({ eventBus, store, core }) {\r\n this._eventBus = eventBus;\r\n this._store = store;\r\n this._core = core;\r\n this._initialized = false;\r\n this._modules = {};\r\n }\r\n\r\n // ─── Lazy Initialization ───────────────────────────────────────\r\n\r\n /**\r\n * Initialize all sub-modules. Called automatically on first use,\r\n * or can be called explicitly with configuration.\r\n *\r\n * @param {object} [config]\r\n * @param {object} [config.permissions] - Permission overrides\r\n * @param {object} [config.rateLimit] - Rate limit config\r\n * @param {object} [config.circuitBreaker] - Circuit breaker config\r\n * @param {object} [config.loopProtection] - Loop protection config\r\n * @param {object} [config.context] - Context collection config\r\n * @param {object} [config.conversation] - Conversation defaults\r\n * @param {object} [config.triggers] - Trigger system config\r\n */\r\n init(config = {}) {\r\n if (this._initialized) {\r\n // Reconfigure if already initialized\r\n this._reconfigure(config);\r\n return this;\r\n }\r\n\r\n // 1. Permissions (independent — no deps)\r\n this._modules.permissions = new WuAIPermissions({\r\n permissions: config.permissions,\r\n rateLimit: config.rateLimit,\r\n circuitBreaker: config.circuitBreaker,\r\n loopProtection: config.loopProtection,\r\n allowedDomains: config.allowedDomains,\r\n });\r\n\r\n // 2. Provider (independent — no deps)\r\n this._modules.provider = new WuAIProvider();\r\n\r\n // 3. Context (depends on store, eventBus, core)\r\n this._modules.context = new WuAIContext({\r\n store: this._store,\r\n eventBus: this._eventBus,\r\n core: this._core,\r\n });\r\n if (config.context) {\r\n this._modules.context.configure(config.context);\r\n }\r\n\r\n // 4. Actions (depends on eventBus, store, permissions)\r\n this._modules.actions = new WuAIActions({\r\n eventBus: this._eventBus,\r\n store: this._store,\r\n permissions: this._modules.permissions,\r\n });\r\n\r\n // 5. Conversation (depends on provider, actions, context, permissions, eventBus)\r\n this._modules.conversation = new WuAIConversation({\r\n provider: this._modules.provider,\r\n actions: this._modules.actions,\r\n context: this._modules.context,\r\n permissions: this._modules.permissions,\r\n eventBus: this._eventBus,\r\n });\r\n if (config.conversation) {\r\n this._modules.conversation.configure(config.conversation);\r\n }\r\n\r\n // 6. Triggers (depends on eventBus, conversation, permissions)\r\n this._modules.triggers = new WuAITriggers({\r\n eventBus: this._eventBus,\r\n conversation: this._modules.conversation,\r\n permissions: this._modules.permissions,\r\n });\r\n if (config.triggers) {\r\n this._modules.triggers.configure(config.triggers);\r\n }\r\n\r\n // 7. Agent (depends on conversation, actions, context, permissions, eventBus)\r\n this._modules.agent = new WuAIAgent({\r\n conversation: this._modules.conversation,\r\n actions: this._modules.actions,\r\n context: this._modules.context,\r\n permissions: this._modules.permissions,\r\n eventBus: this._eventBus,\r\n });\r\n if (config.agent) {\r\n this._modules.agent.configure(config.agent);\r\n }\r\n\r\n // 8. Orchestrate — Paradigm 4: AI as microfrontend glue\r\n // Agent ref is passed so workflows can delegate to the agent loop\r\n // Store ref is passed for deterministic setState steps\r\n this._modules.orchestrate = new WuAIOrchestrate({\r\n actions: this._modules.actions,\r\n conversation: this._modules.conversation,\r\n context: this._modules.context,\r\n permissions: this._modules.permissions,\r\n eventBus: this._eventBus,\r\n agent: this._modules.agent,\r\n store: this._store,\r\n });\r\n if (config.orchestrate) {\r\n this._modules.orchestrate.configure(config.orchestrate);\r\n }\r\n\r\n this._initialized = true;\r\n logger.wuInfo('[wu-ai] Initialized');\r\n\r\n // 9. Browser automation actions (screenshot, click, type, network, etc.)\r\n // Must be AFTER _initialized = true to prevent recursive init loop\r\n if (typeof window !== 'undefined') {\r\n registerBrowserActions(this, this._core);\r\n logger.wuInfo('[wu-ai] Browser actions registered (10 tools)');\r\n }\r\n\r\n this._eventBus.emit('ai:initialized', {}, { appName: 'wu-ai' });\r\n\r\n return this;\r\n }\r\n\r\n // ─── Provider Management ───────────────────────────────────────\r\n\r\n /**\r\n * Register an LLM provider.\r\n *\r\n * @param {string} name - Provider name ('openai', 'anthropic', 'ollama', or custom)\r\n * @param {object} config - { endpoint, apiKey?, model?, adapter?, send?, stream? }\r\n *\r\n * @example\r\n * // OpenAI via proxy (recommended)\r\n * wu.ai.provider('openai', { endpoint: '/api/ai/chat', model: 'gpt-4o' });\r\n *\r\n * // Anthropic direct (development only)\r\n * wu.ai.provider('anthropic', {\r\n * endpoint: 'https://api.anthropic.com/v1/messages',\r\n * apiKey: 'sk-...',\r\n * model: 'claude-sonnet-4-5-20250929',\r\n * });\r\n *\r\n * // Local Ollama\r\n * wu.ai.provider('ollama', { endpoint: 'http://localhost:11434/api/chat', model: 'llama3' });\r\n *\r\n * // Custom provider\r\n * wu.ai.provider('my-llm', { send: async (messages, opts) => ({ content: '...' }) });\r\n */\r\n provider(name, config) {\r\n this._ensureInit();\r\n this._modules.provider.register(name, config);\r\n return this;\r\n }\r\n\r\n // ─── Paradigm 1: App → LLM (Conversation) ─────────────────────\r\n\r\n /**\r\n * Send a message to the LLM and get a complete response.\r\n *\r\n * @param {string} message - User message\r\n * @param {object} [options] - { namespace, systemPrompt, templateVars, temperature, maxTokens, provider, responseFormat, signal }\r\n * @param {string} [options.provider] - Use a specific registered provider (e.g., 'anthropic', 'openai')\r\n * @param {string|object} [options.responseFormat] - Request JSON output.\r\n * - `'json'` — simple JSON mode (OpenAI: json_object, Ollama: format:\"json\", Anthropic: prompt injection)\r\n * - `{ type: 'json_schema', schema: {...}, name?: string }` — structured output with JSON Schema\r\n * (OpenAI: native json_schema mode, Ollama: schema in format, Anthropic: schema in system prompt)\r\n * @returns {Promise<{ content: string, tool_results?: Array, usage?: object, namespace: string }>}\r\n *\r\n * @example\r\n * const response = await wu.ai.send('What items are in the cart?');\r\n * console.log(response.content);\r\n *\r\n * // With namespace for separate conversation\r\n * const response = await wu.ai.send('Analyze this chart', { namespace: 'analytics' });\r\n *\r\n * // Use a specific provider for this message\r\n * const response = await wu.ai.send('Translate this', { provider: 'anthropic' });\r\n *\r\n * // Simple JSON mode\r\n * const response = await wu.ai.send('List 5 colors', { responseFormat: 'json' });\r\n *\r\n * // Structured output with JSON Schema\r\n * const response = await wu.ai.send('List 5 colors', {\r\n * responseFormat: {\r\n * type: 'json_schema',\r\n * schema: { type: 'object', properties: { colors: { type: 'array', items: { type: 'string' } } } },\r\n * name: 'color_list',\r\n * },\r\n * });\r\n */\r\n async send(message, options = {}) {\r\n this._ensureInit();\r\n return this._modules.conversation.send(message, options);\r\n }\r\n\r\n /**\r\n * Send a message and stream the response.\r\n *\r\n * @param {string} message - User message\r\n * @param {object} [options] - Same as send()\r\n * @yields {{ type: 'text'|'tool_result'|'done'|'error', content?: string }}\r\n *\r\n * @example\r\n * for await (const chunk of wu.ai.stream('Tell me about this page')) {\r\n * if (chunk.type === 'text') outputEl.textContent += chunk.content;\r\n * if (chunk.type === 'done') console.log('Done!');\r\n * }\r\n */\r\n async *stream(message, options = {}) {\r\n this._ensureInit();\r\n yield* this._modules.conversation.stream(message, options);\r\n }\r\n\r\n /**\r\n * Send a message and get a parsed JSON response.\r\n * Shortcut for send() with responseFormat + automatic JSON.parse().\r\n *\r\n * @param {string} message - User message\r\n * @param {object} [options] - All send() options plus:\r\n * @param {object} [options.schema] - JSON Schema for structured output\r\n * @param {string} [options.schemaName='response'] - Schema name (required by OpenAI)\r\n * @returns {Promise<{ data: object|null, raw: string, error?: string, usage?: object, namespace: string }>}\r\n *\r\n * @example\r\n * // Simple JSON (no schema)\r\n * const { data } = await wu.ai.json('List 5 colors as a JSON array');\r\n * // data = [\"red\", \"blue\", ...]\r\n *\r\n * // With schema\r\n * const { data } = await wu.ai.json('List 5 colors', {\r\n * schema: { type: 'object', properties: { colors: { type: 'array', items: { type: 'string' } } } },\r\n * });\r\n * // data = { colors: [\"red\", \"blue\", ...] }\r\n *\r\n * // With schema + provider\r\n * const { data } = await wu.ai.json('List 5 colors', {\r\n * schema: mySchema,\r\n * provider: 'openai',\r\n * temperature: 0,\r\n * });\r\n */\r\n async json(message, options = {}) {\r\n this._ensureInit();\r\n\r\n const { schema, schemaName, ...rest } = options;\r\n\r\n let responseFormat;\r\n if (schema) {\r\n responseFormat = { type: 'json_schema', schema, name: schemaName || 'response' };\r\n } else {\r\n responseFormat = options.responseFormat || 'json';\r\n }\r\n\r\n const response = await this._modules.conversation.send(message, { ...rest, responseFormat });\r\n\r\n // The provider already attempts parse and sets response.parsed / response.parseError\r\n let data = null;\r\n let error;\r\n\r\n if (response.parsed !== undefined) {\r\n data = response.parsed;\r\n } else if (response.content) {\r\n try {\r\n data = JSON.parse(response.content);\r\n } catch {\r\n error = 'LLM response is not valid JSON';\r\n }\r\n }\r\n\r\n return {\r\n data,\r\n raw: response.content || '',\r\n error: error || response.parseError,\r\n usage: response.usage,\r\n namespace: response.namespace,\r\n };\r\n }\r\n\r\n /**\r\n * Abort active request(s).\r\n *\r\n * @param {string} [namespace] - Specific namespace, or all if omitted\r\n */\r\n abort(namespace) {\r\n if (!this._initialized) return;\r\n if (namespace) {\r\n this._modules.conversation.abort(namespace);\r\n } else {\r\n this._modules.conversation.abortAll();\r\n }\r\n }\r\n\r\n // ─── Actions / Tools ───────────────────────────────────────────\r\n\r\n /**\r\n * Register an action that the LLM can call.\r\n *\r\n * @param {string} name - Action name (used in tool_call)\r\n * @param {object} config - { description, parameters, handler, confirm?, permissions?, dangerous? }\r\n *\r\n * @example\r\n * wu.ai.action('addToCart', {\r\n * description: 'Add an item to the shopping cart',\r\n * parameters: {\r\n * productId: { type: 'string', required: true },\r\n * quantity: { type: 'number' },\r\n * },\r\n * handler: async (params, api) => {\r\n * api.setState('cart.items', [...api.getState('cart.items'), params]);\r\n * api.emit('cart:updated', params);\r\n * return { added: params.productId };\r\n * },\r\n * confirm: true, // require user confirmation\r\n * });\r\n */\r\n action(name, config) {\r\n this._ensureInit();\r\n this._modules.actions.register(name, config);\r\n return this;\r\n }\r\n\r\n /**\r\n * Execute an action directly (used by external agents via CDP/WebMCP).\r\n *\r\n * @param {string} name - Action name\r\n * @param {object} params - Parameters\r\n * @returns {Promise<{ success: boolean, result?: any, reason?: string }>}\r\n */\r\n async execute(name, params) {\r\n this._ensureInit();\r\n const traceId = this._modules.permissions.loopProtection.createTraceId();\r\n return this._modules.actions.execute(name, params, { traceId, depth: 0 });\r\n }\r\n\r\n // ─── Triggers (Reactive AI) ────────────────────────────────────\r\n\r\n /**\r\n * Register a trigger that automatically sends messages to the LLM\r\n * when specific events occur.\r\n *\r\n * @param {string} name - Trigger name\r\n * @param {object} config - { pattern, prompt, condition?, debounce?, priority?, onResult? }\r\n *\r\n * @example\r\n * wu.ai.trigger('cartAnalysis', {\r\n * pattern: 'cart:updated',\r\n * prompt: 'The cart was updated: {{data}}. Suggest complementary products.',\r\n * debounce: 3000,\r\n * priority: 'low',\r\n * onResult: (result) => {\r\n * wu.emit('ai:suggestions', { suggestions: result.content });\r\n * },\r\n * });\r\n */\r\n trigger(name, config) {\r\n this._ensureInit();\r\n this._modules.triggers.register(name, config);\r\n return this;\r\n }\r\n\r\n /**\r\n * Fire a trigger manually.\r\n */\r\n async fireTrigger(name, eventData) {\r\n this._ensureInit();\r\n return this._modules.triggers.fire(name, eventData);\r\n }\r\n\r\n // ─── Agent (Paradigm 3: Autonomous AI) ─────────────────────────\r\n\r\n /**\r\n * Run an autonomous agent that pursues a goal using available tools.\r\n * Returns an async generator that yields step-by-step results.\r\n *\r\n * @param {string} goal - What the agent should accomplish\r\n * @param {object} [options]\r\n * @param {number} [options.maxSteps=10] - Maximum autonomous steps\r\n * @param {string} [options.provider] - Which LLM provider to use\r\n * @param {string} [options.namespace] - Conversation namespace\r\n * @param {string} [options.systemPrompt] - Override system prompt\r\n * @param {Function} [options.onStep] - Callback per step: (stepResult) => void\r\n * @param {Function} [options.shouldContinue] - Human-in-the-loop: (stepResult) => boolean|Promise<boolean>\r\n * @param {AbortSignal} [options.signal] - Abort signal\r\n * @returns {AsyncGenerator<AgentStepResult>}\r\n *\r\n * @example\r\n * // Basic usage\r\n * for await (const step of wu.ai.agent('Find all orders above $100 and summarize them')) {\r\n * console.log(`Step ${step.step}: ${step.content?.slice(0, 100)}`);\r\n * if (step.done) console.log('Agent finished!');\r\n * }\r\n *\r\n * // With human-in-the-loop\r\n * for await (const step of wu.ai.agent('Reorganize the product catalog', {\r\n * shouldContinue: (step) => confirm(`Continue? Step ${step.step}: ${step.content?.slice(0, 50)}`),\r\n * })) {\r\n * updateUI(step);\r\n * }\r\n */\r\n async *agent(goal, options = {}) {\r\n this._ensureInit();\r\n yield* this._modules.agent.run(goal, options);\r\n }\r\n\r\n // ─── Paradigm 4: AI as Microfrontend Glue ─────────────────────\r\n\r\n /**\r\n * Register a capability scoped to a specific micro-app.\r\n *\r\n * Each micro-app calls this to declare what it can do. The AI uses\r\n * the capability map to resolve cross-app intents.\r\n *\r\n * @param {string} appName - The micro-app name (e.g., 'orders', 'dashboard')\r\n * @param {string} actionName - The capability name (e.g., 'getRecent', 'updateKPIs')\r\n * @param {object} config - Same as wu.ai.action() config:\r\n * { description, parameters, handler, confirm?, permissions?, dangerous? }\r\n *\r\n * @example\r\n * // In orders micro-app (React):\r\n * wu.ai.capability('orders', 'getRecent', {\r\n * description: 'Get the N most recent orders',\r\n * parameters: { limit: { type: 'number' } },\r\n * handler: async (params) => fetchOrders({ limit: params.limit || 10 }),\r\n * });\r\n *\r\n * // In dashboard micro-app (Svelte):\r\n * wu.ai.capability('dashboard', 'updateKPIs', {\r\n * description: 'Refresh the KPI cards with latest data',\r\n * handler: async () => { refreshKPIs(); return { updated: true }; },\r\n * });\r\n */\r\n capability(appName, actionName, config) {\r\n this._ensureInit();\r\n this._modules.orchestrate.register(appName, actionName, config);\r\n return this;\r\n }\r\n\r\n /**\r\n * Resolve a cross-app intent in a single conversation turn.\r\n *\r\n * The AI receives the full capability map (what each app can do),\r\n * current application state, and mounted apps. It resolves the\r\n * intent by calling the right capabilities across app boundaries.\r\n *\r\n * @param {string} description - Natural language intent\r\n * @param {object} [options]\r\n * @param {string[]} [options.plan] - Optional action sequence hint\r\n * @param {string} [options.provider] - LLM provider override\r\n * @param {number} [options.temperature] - Temperature override\r\n * @param {number} [options.maxTokens] - Max tokens override\r\n * @param {AbortSignal} [options.signal] - Abort signal\r\n * @param {string|object} [options.responseFormat] - Response format\r\n * @returns {Promise<{ content: string, tool_results: Array, usage: object|null, resolved: boolean, appsInvolved: string[] }>}\r\n *\r\n * @example\r\n * // Simple cross-app query\r\n * const result = await wu.ai.intent('Show me the top customer by order count');\r\n * // AI calls orders:getRecent → aggregates → returns answer\r\n *\r\n * // With plan hint\r\n * const result = await wu.ai.intent('Update all views after a new order', {\r\n * plan: ['orders:getRecent', 'dashboard:updateKPIs', 'analytics:refresh'],\r\n * });\r\n *\r\n * // With JSON response\r\n * const result = await wu.ai.intent('Get order stats by status', {\r\n * responseFormat: 'json',\r\n * });\r\n */\r\n async intent(description, options = {}) {\r\n this._ensureInit();\r\n return this._modules.orchestrate.resolve(description, options);\r\n }\r\n\r\n /**\r\n * Remove all capabilities for a micro-app.\r\n * Call this when a micro-app is unmounted to prevent stale\r\n * capabilities from appearing in the AI's capability map.\r\n *\r\n * @param {string} appName - The micro-app name\r\n *\r\n * @example\r\n * // In unmount lifecycle:\r\n * wu.ai.removeApp('orders');\r\n */\r\n removeApp(appName) {\r\n this._ensureInit();\r\n this._modules.orchestrate.removeApp(appName);\r\n return this;\r\n }\r\n\r\n /**\r\n * Register a reusable AI workflow — a named, step-by-step recipe\r\n * that the AI agent follows using browser automation.\r\n *\r\n * @param {string} name - Workflow name (e.g., 'register-user')\r\n * @param {object} config\r\n * @param {string} config.description - What this workflow does\r\n * @param {string[]} config.steps - Step-by-step instructions\r\n * Use {{paramName}} for parameter interpolation.\r\n * @param {object} [config.parameters] - Parameter definitions\r\n * @param {number} [config.maxSteps=15] - Max agent steps\r\n * @param {string} [config.provider] - LLM provider\r\n *\r\n * @example\r\n * wu.ai.workflow('register-user', {\r\n * description: 'Register a new user in the system',\r\n * steps: [\r\n * 'Navigate to the Customers section',\r\n * 'Click the \"Add Customer\" button',\r\n * 'Type \"{{name}}\" into the name field',\r\n * 'Type \"{{email}}\" into the email field',\r\n * 'Click Submit',\r\n * 'Verify the success message appears',\r\n * ],\r\n * parameters: {\r\n * name: { type: 'string', required: true },\r\n * email: { type: 'string', required: true },\r\n * },\r\n * });\r\n */\r\n workflow(name, config) {\r\n this._ensureInit();\r\n this._modules.orchestrate.registerWorkflow(name, config);\r\n return this;\r\n }\r\n\r\n /**\r\n * Execute a registered workflow. Returns an async generator\r\n * so you can observe each step in real time.\r\n *\r\n * @param {string} name - Workflow name\r\n * @param {object} [params={}] - Parameters to fill into the steps\r\n * @param {object} [options={}]\r\n * @param {Function} [options.onStep] - Callback per step\r\n * @param {Function} [options.shouldContinue] - Human-in-the-loop gate\r\n * @param {AbortSignal} [options.signal] - Abort signal\r\n * @returns {AsyncGenerator<AgentStepResult>}\r\n *\r\n * @example\r\n * // Run and watch every step\r\n * for await (const step of wu.ai.runWorkflow('register-user', {\r\n * name: 'Juan Pérez',\r\n * email: 'juan@test.com',\r\n * })) {\r\n * console.log(`Step ${step.step}: ${step.content}`);\r\n * if (step.type === 'done') console.log('Workflow complete!');\r\n * }\r\n *\r\n * // With human approval per step\r\n * for await (const step of wu.ai.runWorkflow('register-user', params, {\r\n * shouldContinue: (s) => confirm(`Continue? ${s.content?.slice(0, 60)}`),\r\n * })) {\r\n * renderStep(step);\r\n * }\r\n */\r\n async *runWorkflow(name, params = {}, options = {}) {\r\n this._ensureInit();\r\n yield* this._modules.orchestrate.executeWorkflow(name, params, options);\r\n }\r\n\r\n // ─── Context ───────────────────────────────────────────────────\r\n\r\n /**\r\n * Context configuration sub-API.\r\n * Access via wu.ai.context\r\n */\r\n get context() {\r\n this._ensureInit();\r\n return {\r\n configure: (config) => this._modules.context.configure(config),\r\n register: (name, config) => this._modules.context.register(name, config),\r\n collect: () => this._modules.context.collect(),\r\n getSnapshot: () => this._modules.context.getSnapshot(),\r\n };\r\n }\r\n\r\n // ─── Conversation Management ───────────────────────────────────\r\n\r\n /**\r\n * Conversation sub-API for direct history management.\r\n */\r\n get conversation() {\r\n this._ensureInit();\r\n return {\r\n getHistory: (ns) => this._modules.conversation.getHistory(ns),\r\n clear: (ns) => this._modules.conversation.clear(ns),\r\n clearAll: () => this._modules.conversation.clearAll(),\r\n inject: (role, content, opts) => this._modules.conversation.inject(role, content, opts),\r\n getNamespaces: () => this._modules.conversation.getNamespaces(),\r\n deleteNamespace: (ns) => this._modules.conversation.deleteNamespace(ns),\r\n };\r\n }\r\n\r\n // ─── Permissions ───────────────────────────────────────────────\r\n\r\n /**\r\n * Permissions sub-API.\r\n */\r\n get permissions() {\r\n this._ensureInit();\r\n return {\r\n configure: (config) => this._modules.permissions.configure(config),\r\n check: (perm) => this._modules.permissions.check(perm),\r\n getPermissions: () => this._modules.permissions.getPermissions(),\r\n setAllowedDomains: (domains) => this._modules.permissions.setAllowedDomains(domains),\r\n };\r\n }\r\n\r\n // ─── Paradigm 2: LLM → App (External Agent Access) ────────────\r\n\r\n /**\r\n * Get all registered tools (for external agents).\r\n * An agent connected via CDP can call: window.wu.ai.tools()\r\n *\r\n * @returns {Array<{ name, description, parameters }>}\r\n */\r\n tools() {\r\n this._ensureInit();\r\n return this._modules.actions.getToolSchemas();\r\n }\r\n\r\n /**\r\n * Expose tools via WebMCP (Chrome 146+ / W3C proposal).\r\n * Registers all actions with navigator.modelContext.registerTool()\r\n *\r\n * @returns {boolean} Whether WebMCP is available\r\n */\r\n expose() {\r\n this._ensureInit();\r\n\r\n if (typeof navigator === 'undefined' || !navigator.modelContext) {\r\n logger.wuDebug('[wu-ai] WebMCP not available (navigator.modelContext missing)');\r\n return false;\r\n }\r\n\r\n const tools = this._modules.actions.getToolSchemas();\r\n const actionNames = this._modules.actions.getNames();\r\n\r\n for (let i = 0; i < tools.length; i++) {\r\n const tool = tools[i];\r\n const actionName = actionNames[i];\r\n\r\n try {\r\n navigator.modelContext.registerTool({\r\n name: tool.name,\r\n description: tool.description,\r\n inputSchema: tool.parameters,\r\n handler: async (params) => {\r\n const result = await this.execute(actionName, params);\r\n return result.success ? result.result : { error: result.reason };\r\n },\r\n });\r\n } catch (err) {\r\n logger.wuDebug(`[wu-ai] WebMCP register failed for '${tool.name}': ${err.message}`);\r\n }\r\n }\r\n\r\n logger.wuInfo(`[wu-ai] Exposed ${tools.length} tools via WebMCP`);\r\n\r\n this._eventBus.emit('ai:webmcp:exposed', {\r\n toolCount: tools.length,\r\n tools: tools.map(t => t.name),\r\n }, { appName: 'wu-ai' });\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Confirm a pending tool call (for UI integration).\r\n */\r\n confirmTool(callId) {\r\n if (!this._initialized) return;\r\n this._modules.actions.confirmTool(callId);\r\n }\r\n\r\n /**\r\n * Reject a pending tool call.\r\n */\r\n rejectTool(callId) {\r\n if (!this._initialized) return;\r\n this._modules.actions.rejectTool(callId);\r\n }\r\n\r\n // ─── Stats & Debug ─────────────────────────────────────────────\r\n\r\n getStats() {\r\n if (!this._initialized) return { initialized: false };\r\n\r\n return {\r\n initialized: true,\r\n provider: this._modules.provider.getStats(),\r\n permissions: this._modules.permissions.getStats(),\r\n context: this._modules.context.getStats(),\r\n actions: this._modules.actions.getStats(),\r\n conversation: this._modules.conversation.getStats(),\r\n triggers: this._modules.triggers.getStats(),\r\n agent: this._modules.agent.getStats(),\r\n orchestrate: this._modules.orchestrate.getStats(),\r\n };\r\n }\r\n\r\n /**\r\n * Destroy the AI system and clean up all resources.\r\n */\r\n destroy() {\r\n if (!this._initialized) return;\r\n\r\n this._modules.orchestrate.destroy();\r\n this._modules.agent.destroy();\r\n this._modules.conversation.abortAll();\r\n this._modules.triggers.destroy();\r\n this._modules = {};\r\n this._initialized = false;\r\n\r\n logger.wuInfo('[wu-ai] Destroyed');\r\n this._eventBus.emit('ai:destroyed', {}, { appName: 'wu-ai' });\r\n }\r\n\r\n // ─── Private ───────────────────────────────────────────────────\r\n\r\n _ensureInit() {\r\n if (!this._initialized) {\r\n this.init();\r\n }\r\n }\r\n\r\n _reconfigure(config) {\r\n if (config.permissions) this._modules.permissions.configure(config.permissions);\r\n if (config.rateLimit) this._modules.permissions.rateLimiter.configure(config.rateLimit);\r\n if (config.circuitBreaker) this._modules.permissions.circuitBreaker.configure(config.circuitBreaker);\r\n if (config.loopProtection) this._modules.permissions.loopProtection.configure(config.loopProtection);\r\n if (config.context) this._modules.context.configure(config.context);\r\n if (config.conversation) this._modules.conversation.configure(config.conversation);\r\n if (config.triggers) this._modules.triggers.configure(config.triggers);\r\n if (config.agent) this._modules.agent.configure(config.agent);\r\n if (config.orchestrate) this._modules.orchestrate.configure(config.orchestrate);\r\n }\r\n}\r\n","/**\r\n * WU-MCP Bridge (Browser Side)\r\n *\r\n * Connects to the wu-mcp-server via WebSocket and executes\r\n * commands using wu.* APIs. This is the \"eyes and hands\" of\r\n * the MCP server inside the browser.\r\n *\r\n * Security:\r\n * - Optional auth token sent on first message (handshake)\r\n * - All state/event/mount operations check wu.ai permissions\r\n * - Mutating operations emit audit events\r\n * - Read-only operations (status, list_apps, snapshot, console, network) are unrestricted\r\n *\r\n * @example\r\n * // Connect with auth token\r\n * wu.mcp.connect('ws://localhost:19100', { token: 'my-secret' });\r\n *\r\n * // Connect without auth (development only)\r\n * wu.mcp.connect();\r\n */\r\n\r\nimport {\r\n ensureInterceptors,\r\n networkLog,\r\n consoleLog,\r\n captureScreenshot,\r\n buildA11yTree,\r\n clickElement,\r\n typeIntoElement,\r\n getFilteredNetwork,\r\n getFilteredConsole,\r\n} from '../ai/wu-ai-browser-primitives.js';\r\nimport { logger } from './wu-logger.js';\r\n\r\n/**\r\n * Create the MCP bridge for a Wu instance.\r\n *\r\n * @param {object} wu - The Wu Framework instance (window.wu)\r\n * @returns {object} Bridge API: { connect, disconnect, isConnected }\r\n */\r\nexport function createMcpBridge(wu) {\r\n let ws = null;\r\n let reconnectTimer = null;\r\n let reconnectAttempts = 0;\r\n let authenticated = false;\r\n let authToken = null;\r\n const MAX_RECONNECT_ATTEMPTS = 10;\r\n const RECONNECT_DELAY = 2000;\r\n\r\n // Event log for wu_list_events\r\n const eventLog = [];\r\n const MAX_EVENT_LOG = 200;\r\n\r\n // Capture events for history\r\n if (wu.eventBus) {\r\n wu.eventBus.on('*', (event) => {\r\n eventLog.push({\r\n name: event.name,\r\n data: event.data,\r\n timestamp: event.timestamp || Date.now(),\r\n source: event.source || 'unknown',\r\n });\r\n if (eventLog.length > MAX_EVENT_LOG) eventLog.shift();\r\n });\r\n }\r\n\r\n // Install shared interceptors (idempotent — safe if wu-ai-browser already did it)\r\n ensureInterceptors();\r\n\r\n // ── Permission helpers ──\r\n\r\n /**\r\n * Check a permission flag via wu.ai.permissions if available.\r\n * Falls back to deny if wu.ai is not initialized.\r\n */\r\n function _checkPermission(perm) {\r\n if (wu.ai && wu.ai.permissions) {\r\n return wu.ai.permissions.check(perm);\r\n }\r\n // If AI module not initialized, deny write operations, allow reads\r\n const readPerms = ['readStore', 'executeActions'];\r\n return readPerms.includes(perm);\r\n }\r\n\r\n /**\r\n * Emit an audit event for bridge operations.\r\n */\r\n function _audit(operation, params, result) {\r\n if (wu.eventBus) {\r\n wu.eventBus.emit('mcp:bridge:operation', {\r\n operation,\r\n params,\r\n result: result?.error ? { error: result.error } : { success: true },\r\n timestamp: Date.now(),\r\n }, { appName: 'wu-mcp-bridge' });\r\n }\r\n }\r\n\r\n // ── Command handlers ──\r\n\r\n const handlers = {\r\n // ── Read-only operations (no permission gates) ──\r\n\r\n status() {\r\n return {\r\n connected: true,\r\n framework: 'wu-framework',\r\n apps: _getAppList(),\r\n storeKeys: wu.store ? Object.keys(wu.store.get('') || {}) : [],\r\n actionsCount: wu.ai ? wu.ai.tools().length : 0,\r\n eventLogSize: eventLog.length,\r\n };\r\n },\r\n\r\n list_apps() {\r\n return _getAppList();\r\n },\r\n\r\n list_events({ limit = 20 }) {\r\n return eventLog.slice(-limit);\r\n },\r\n\r\n list_actions() {\r\n if (!wu.ai) return { actions: [], note: 'wu.ai not initialized' };\r\n const tools = wu.ai.tools();\r\n return { actions: tools, count: tools.length };\r\n },\r\n\r\n snapshot({ appName }) {\r\n try {\r\n const target = appName\r\n ? document.querySelector(`[data-wu-app=\"${appName}\"]`) || document.querySelector(`#wu-app-${appName}`)\r\n : document.body;\r\n\r\n if (!target) return { error: `App \"${appName}\" not found in DOM` };\r\n\r\n return {\r\n app: appName || '(page)',\r\n snapshot: buildA11yTree(target, 0, 5),\r\n timestamp: Date.now(),\r\n };\r\n } catch (err) {\r\n return { error: err.message };\r\n }\r\n },\r\n\r\n console({ level = 'all', limit = 50 }) {\r\n return getFilteredConsole(level, limit);\r\n },\r\n\r\n async screenshot({ selector, quality = 0.8 }) {\r\n const result = await captureScreenshot(selector, quality);\r\n if (!result.error) result.timestamp = Date.now();\r\n return result;\r\n },\r\n\r\n network({ method, status, limit = 50 }) {\r\n return getFilteredNetwork(method, status, limit);\r\n },\r\n\r\n // ── Permission-gated operations ──\r\n\r\n get_state({ path }) {\r\n if (!wu.store) return { error: 'wu.store not available' };\r\n if (!_checkPermission('readStore')) {\r\n return { error: 'Permission denied: readStore is disabled' };\r\n }\r\n const value = wu.store.get(path || '');\r\n return { path: path || '(root)', value };\r\n },\r\n\r\n set_state({ path, value }) {\r\n if (!wu.store) return { error: 'wu.store not available' };\r\n if (!path) return { error: 'path is required' };\r\n if (!_checkPermission('writeStore')) {\r\n _audit('set_state', { path }, { error: 'Permission denied' });\r\n return { error: 'Permission denied: writeStore is disabled' };\r\n }\r\n wu.store.set(path, value);\r\n _audit('set_state', { path, value }, { success: true });\r\n return { path, value, updated: true };\r\n },\r\n\r\n emit_event({ event, data }) {\r\n if (!wu.eventBus) return { error: 'wu.eventBus not available' };\r\n if (!event) return { error: 'event name is required' };\r\n if (!_checkPermission('emitEvents')) {\r\n _audit('emit_event', { event }, { error: 'Permission denied' });\r\n return { error: 'Permission denied: emitEvents is disabled' };\r\n }\r\n wu.eventBus.emit(event, data, { appName: 'wu-mcp-bridge' });\r\n _audit('emit_event', { event, data }, { success: true });\r\n return { emitted: event, data };\r\n },\r\n\r\n navigate({ route }) {\r\n if (!route) return { error: 'Route is required' };\r\n if (!_checkPermission('emitEvents')) {\r\n _audit('navigate', { route }, { error: 'Permission denied: emitEvents' });\r\n return { error: 'Permission denied: emitEvents is disabled' };\r\n }\r\n if (wu.eventBus) {\r\n wu.eventBus.emit('shell:navigate', { route }, { appName: 'wu-mcp-bridge' });\r\n }\r\n if (wu.store && _checkPermission('writeStore')) {\r\n wu.store.set('currentPath', route);\r\n }\r\n _audit('navigate', { route }, { success: true });\r\n return { navigated: route };\r\n },\r\n\r\n mount_app({ appName, container }) {\r\n if (!appName) return { error: 'appName is required' };\r\n if (!_checkPermission('modifyDOM')) {\r\n _audit('mount_app', { appName }, { error: 'Permission denied' });\r\n return { error: 'Permission denied: modifyDOM is disabled' };\r\n }\r\n try {\r\n if (wu.mount) {\r\n wu.mount(appName, container);\r\n _audit('mount_app', { appName, container }, { success: true });\r\n return { mounted: appName, container };\r\n }\r\n return { error: 'wu.mount not available' };\r\n } catch (err) {\r\n return { error: err.message };\r\n }\r\n },\r\n\r\n unmount_app({ appName }) {\r\n if (!appName) return { error: 'appName is required' };\r\n if (!_checkPermission('modifyDOM')) {\r\n _audit('unmount_app', { appName }, { error: 'Permission denied' });\r\n return { error: 'Permission denied: modifyDOM is disabled' };\r\n }\r\n try {\r\n if (wu.unmount) {\r\n wu.unmount(appName);\r\n _audit('unmount_app', { appName }, { success: true });\r\n return { unmounted: appName };\r\n }\r\n return { error: 'wu.unmount not available' };\r\n } catch (err) {\r\n return { error: err.message };\r\n }\r\n },\r\n\r\n click({ selector, text }) {\r\n if (!_checkPermission('modifyDOM')) {\r\n return { error: 'Permission denied: modifyDOM is disabled' };\r\n }\r\n const result = clickElement(selector, text);\r\n _audit('click', { selector, text }, result);\r\n return result;\r\n },\r\n\r\n type({ selector, text, clear = false, submit = false }) {\r\n if (!_checkPermission('modifyDOM')) {\r\n return { error: 'Permission denied: modifyDOM is disabled' };\r\n }\r\n const result = typeIntoElement(selector, text, { clear, submit });\r\n _audit('type', { selector, textLength: text?.length }, result);\r\n return result;\r\n },\r\n\r\n async execute_action({ action, params }) {\r\n if (!wu.ai) return { error: 'wu.ai not available' };\r\n if (!action) return { error: 'action name is required' };\r\n\r\n try {\r\n // Execute through public API (respects permissions, validation, audit)\r\n const result = await wu.ai.execute(action, params || {});\r\n return { action, ...result };\r\n } catch (err) {\r\n return { error: err.message };\r\n }\r\n },\r\n };\r\n\r\n // ── WebSocket connection ──\r\n\r\n function connect(url = 'ws://localhost:19100', options = {}) {\r\n if (ws && ws.readyState <= 1) {\r\n logger.warn('[wu-mcp-bridge] Already connected or connecting');\r\n return;\r\n }\r\n\r\n authToken = options.token || null;\r\n authenticated = !authToken; // No token = auto-authenticated (dev mode)\r\n\r\n try {\r\n ws = new WebSocket(url);\r\n\r\n ws.onopen = () => {\r\n logger.debug('[wu-mcp-bridge] Connected to wu-mcp-server');\r\n reconnectAttempts = 0;\r\n\r\n // Send auth handshake if token provided\r\n if (authToken) {\r\n ws.send(JSON.stringify({\r\n type: 'auth',\r\n token: authToken,\r\n }));\r\n }\r\n };\r\n\r\n ws.onmessage = async (event) => {\r\n try {\r\n const msg = JSON.parse(event.data);\r\n\r\n // Handle auth response\r\n if (msg.type === 'auth_result') {\r\n authenticated = msg.success === true;\r\n if (!authenticated) {\r\n console.error('[wu-mcp-bridge] Authentication failed:', msg.reason || 'Invalid token');\r\n disconnect();\r\n } else {\r\n logger.debug('[wu-mcp-bridge] Authenticated successfully');\r\n }\r\n return;\r\n }\r\n\r\n // Reject commands if not authenticated\r\n if (!authenticated) {\r\n if (msg.id) {\r\n _respond(msg.id, null, 'Not authenticated. Send auth token first.');\r\n }\r\n return;\r\n }\r\n\r\n const { id, command, params } = msg;\r\n\r\n if (!id || !command) {\r\n logger.warn('[wu-mcp-bridge] Invalid message:', msg);\r\n return;\r\n }\r\n\r\n const handler = handlers[command];\r\n if (!handler) {\r\n _respond(id, null, `Unknown command: ${command}`);\r\n return;\r\n }\r\n\r\n try {\r\n const result = await handler(params || {});\r\n _respond(id, result);\r\n } catch (err) {\r\n _respond(id, null, err.message);\r\n }\r\n } catch (err) {\r\n console.error('[wu-mcp-bridge] Failed to handle message:', err);\r\n }\r\n };\r\n\r\n ws.onclose = () => {\r\n logger.debug('[wu-mcp-bridge] Disconnected');\r\n ws = null;\r\n authenticated = false;\r\n _scheduleReconnect(url, options);\r\n };\r\n\r\n ws.onerror = () => {\r\n // onclose will fire after this\r\n };\r\n } catch (err) {\r\n console.error('[wu-mcp-bridge] Connection failed:', err.message);\r\n _scheduleReconnect(url, options);\r\n }\r\n }\r\n\r\n function disconnect() {\r\n if (reconnectTimer) {\r\n clearTimeout(reconnectTimer);\r\n reconnectTimer = null;\r\n }\r\n reconnectAttempts = MAX_RECONNECT_ATTEMPTS; // prevent reconnect\r\n if (ws) {\r\n ws.close();\r\n ws = null;\r\n }\r\n authenticated = false;\r\n }\r\n\r\n function isConnected() {\r\n return ws !== null && ws.readyState === 1 && authenticated;\r\n }\r\n\r\n // ── Private helpers ──\r\n\r\n function _respond(id, result, error) {\r\n if (!ws || ws.readyState !== 1) return;\r\n const msg = error ? { id, error } : { id, result };\r\n ws.send(JSON.stringify(msg));\r\n }\r\n\r\n function _scheduleReconnect(url, options) {\r\n if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) return;\r\n reconnectAttempts++;\r\n const delay = RECONNECT_DELAY * Math.min(reconnectAttempts, 5);\r\n reconnectTimer = setTimeout(() => connect(url, options), delay);\r\n }\r\n\r\n function _getAppList() {\r\n const apps = [];\r\n\r\n if (wu._apps) {\r\n for (const [name, app] of Object.entries(wu._apps)) {\r\n apps.push({\r\n name,\r\n mounted: app.mounted || app.isMounted || false,\r\n url: app.url || app.info?.url || '',\r\n status: app.status || app.info?.status || 'unknown',\r\n });\r\n }\r\n }\r\n\r\n // Fallback: scan DOM for wu-app elements\r\n if (apps.length === 0) {\r\n document.querySelectorAll('[data-wu-app]').forEach((el) => {\r\n apps.push({\r\n name: el.getAttribute('data-wu-app'),\r\n mounted: true,\r\n container: `#${el.id || '(no-id)'}`,\r\n });\r\n });\r\n }\r\n\r\n return apps;\r\n }\r\n\r\n return { connect, disconnect, isConnected };\r\n}\r\n","/**\r\n * WU-FRAMEWORK: UNIVERSAL MICROFRONTENDS\r\n *\r\n * Framework agnostic microfrontends with Shadow DOM isolation.\r\n * Supports React, Vue, Angular, Svelte, Solid, Preact, Lit, Vanilla.\r\n *\r\n * @example\r\n * import { wu, emit, on } from 'wu-framework';\r\n *\r\n * const canvas = wu.app('canvas', { url: 'http://localhost:5178', container: '#canvas' });\r\n * await canvas.mount();\r\n *\r\n * emit('user:login', { userId: 123 });\r\n * on('user:*', (e) => console.log(e.data));\r\n */\r\n\r\nimport { WuCore } from './core/wu-core.js';\r\nimport { WuAI } from './ai/wu-ai.js';\r\n\r\n// --- Singleton: reuse host instance if it exists ---\r\nlet wu;\r\n\r\nif (typeof window !== 'undefined' && window.wu && window.wu._isWuFramework) {\r\n wu = window.wu;\r\n} else {\r\n wu = new WuCore();\r\n wu._isWuFramework = true;\r\n\r\n // Also store on a Symbol key for collision-safe access\r\n if (typeof window !== 'undefined') {\r\n const WU_KEY = Symbol.for('wu-framework');\r\n window[WU_KEY] = wu;\r\n }\r\n}\r\n\r\n// Expose globally for microfrontends\r\nif (typeof window !== 'undefined') {\r\n // Warn if window.wu exists but is not a Wu Framework instance\r\n if (window.wu && !window.wu._isWuFramework) {\r\n console.warn('[Wu Framework] window.wu already exists and is not a Wu Framework instance. Overwriting. Use Symbol.for(\"wu-framework\") for collision-safe access.');\r\n }\r\n window.wu = wu;\r\n\r\n if (!wu.version) {\r\n wu.version = '1.1.17';\r\n wu.info = {\r\n name: 'Wu Framework',\r\n description: 'Universal Microfrontends',\r\n features: ['Framework Agnostic', 'Zero Config', 'Shadow DOM Isolation', 'Runtime Loading']\r\n };\r\n }\r\n\r\n // Event Bus shortcuts on window.wu\r\n if (!wu.emit) {\r\n wu.emit = (event, data, opts) => wu.eventBus.emit(event, data, opts);\r\n wu.on = (event, cb) => wu.eventBus.on(event, cb);\r\n wu.once = (event, cb) => wu.eventBus.once(event, cb);\r\n wu.off = (event, cb) => wu.eventBus.off(event, cb);\r\n }\r\n\r\n // Prefetch shortcuts on window.wu\r\n if (!wu.prefetch) {\r\n wu.prefetch = (appNames, opts) => wu.prefetcher.prefetch(appNames, opts);\r\n wu.prefetchAll = (opts) => wu.prefetcher.prefetchAll(opts);\r\n }\r\n\r\n // Override shortcuts on window.wu\r\n if (!wu.override) {\r\n wu.override = (name, url, opts) => wu.overrides.set(name, url, opts);\r\n wu.removeOverride = (name) => wu.overrides.remove(name);\r\n wu.getOverrides = () => wu.overrides.getAll();\r\n wu.clearOverrides = () => wu.overrides.clearAll();\r\n }\r\n\r\n // Log control: window.wu.silence() / window.wu.verbose()\r\n if (!wu.silence) {\r\n wu.silence = async () => { const { silenceAllLogs } = await import('./core/wu-logger.js'); silenceAllLogs(); };\r\n wu.verbose = async () => { const { enableAllLogs } = await import('./core/wu-logger.js'); enableAllLogs(); };\r\n }\r\n\r\n // AI integration — lazy instantiated on first access\r\n if (!wu.ai) {\r\n let _aiInstance = null;\r\n Object.defineProperty(wu, 'ai', {\r\n get() {\r\n if (!_aiInstance) {\r\n _aiInstance = new WuAI({\r\n eventBus: wu.eventBus,\r\n store: wu.store,\r\n core: wu,\r\n });\r\n }\r\n return _aiInstance;\r\n },\r\n configurable: true,\r\n });\r\n }\r\n\r\n // MCP bridge — connects to wu-mcp-server for AI agent control\r\n if (!wu.mcp) {\r\n let _mcpBridge = null;\r\n wu.mcp = {\r\n async connect(url = 'ws://localhost:19100', options = {}) {\r\n if (!_mcpBridge) {\r\n const { createMcpBridge } = await import('./core/wu-mcp-bridge.js');\r\n _mcpBridge = createMcpBridge(wu);\r\n }\r\n _mcpBridge.connect(url, options);\r\n },\r\n disconnect() {\r\n _mcpBridge?.disconnect();\r\n },\r\n isConnected() {\r\n return _mcpBridge?.isConnected() || false;\r\n },\r\n };\r\n }\r\n}\r\n\r\n// --- Primary exports ---\r\nexport { wu };\r\nexport default wu;\r\n\r\n// --- Core classes (advanced usage) ---\r\nexport { WuCore } from './core/wu-core.js';\r\nexport { WuLoader } from './core/wu-loader.js';\r\nexport { WuSandbox } from './core/wu-sandbox.js';\r\nexport { WuManifest } from './core/wu-manifest.js';\r\nexport { WuStore, default as store } from './core/wu-store.js';\r\nexport { WuApp } from './core/wu-app.js';\r\nexport { WuStyleBridge } from './core/wu-style-bridge.js';\r\nexport { WuCache } from './core/wu-cache.js';\r\nexport { WuEventBus } from './core/wu-event-bus.js';\r\nexport { WuPerformance } from './core/wu-performance.js';\r\nexport { WuProxySandbox } from './core/wu-proxy-sandbox.js';\r\nexport { WuSnapshotSandbox } from './core/wu-snapshot-sandbox.js';\r\nexport { WuHtmlParser } from './core/wu-html-parser.js';\r\nexport { WuScriptExecutor } from './core/wu-script-executor.js';\r\nexport { WuIframeSandbox } from './core/wu-iframe-sandbox.js';\r\nexport { WuPluginSystem, createPlugin } from './core/wu-plugin.js';\r\nexport { WuLoadingStrategy } from './core/wu-strategies.js';\r\nexport { WuPrefetch } from './core/wu-prefetch.js';\r\nexport { WuOverrides } from './core/wu-overrides.js';\r\nexport { WuErrorBoundary } from './core/wu-error-boundary.js';\r\nexport {\r\n WuLifecycleHooks,\r\n createSimpleHook,\r\n createConditionalHook,\r\n createGuardHook,\r\n createTransformHook,\r\n createTimedHook\r\n} from './core/wu-hooks.js';\r\nexport { silenceAllLogs, enableAllLogs } from './core/wu-logger.js';\r\n\r\n// --- Convenience API (most-used shortcuts) ---\r\nexport const init = (apps) => wu.init({ apps });\r\nexport const mount = (name, container) => wu.mount(name, container);\r\nexport const unmount = (name, opts) => wu.unmount(name, opts);\r\nexport const define = (name, lifecycle) => wu.define(name, lifecycle);\r\nexport const app = (name, config) => wu.app(name, config);\r\nexport const destroy = () => wu.destroy();\r\n\r\n// Keep-alive\r\nexport const hide = (name) => wu.hide(name);\r\nexport const show = (name) => wu.show(name);\r\nexport const isHidden = (name) => wu.isHidden(name);\r\n\r\n// Event Bus\r\nexport const emit = (event, data, opts) => wu.eventBus.emit(event, data, opts);\r\nexport const on = (event, cb) => wu.eventBus.on(event, cb);\r\nexport const once = (event, cb) => wu.eventBus.once(event, cb);\r\nexport const off = (event, cb) => wu.eventBus.off(event, cb);\r\n\r\n// Store\r\nexport const getState = (path) => wu.store.get(path);\r\nexport const setState = (path, value) => wu.store.set(path, value);\r\nexport const onStateChange = (pattern, cb) => wu.store.on(pattern, cb);\r\n\r\n// Performance\r\nexport const startMeasure = (name, app) => wu.performance.startMeasure(name, app);\r\nexport const endMeasure = (name, app) => wu.performance.endMeasure(name, app);\r\nexport const generatePerformanceReport = () => wu.performance.generateReport();\r\n\r\n// Prefetch\r\nexport const prefetch = (appNames, opts) => wu.prefetch(appNames, opts);\r\nexport const prefetchAll = (opts) => wu.prefetchAll(opts);\r\n\r\n// Overrides (QA/testing)\r\nexport const override = (name, url, opts) => wu.override(name, url, opts);\r\nexport const removeOverride = (name) => wu.removeOverride(name);\r\nexport const getOverrides = () => wu.getOverrides();\r\nexport const clearOverrides = () => wu.clearOverrides();\r\n\r\n// Plugins & Hooks\r\nexport const usePlugin = (plugin, opts) => wu.pluginSystem.use(plugin, opts);\r\nexport const useHook = (phase, middleware, opts) => wu.hooks.use(phase, middleware, opts);\r\n\r\n// --- AI classes (advanced usage) ---\r\nexport { WuAI } from './ai/wu-ai.js';\r\nexport { WuAIProvider } from './ai/wu-ai-provider.js';\r\nexport { WuAIPermissions } from './ai/wu-ai-permissions.js';\r\nexport { WuAIContext } from './ai/wu-ai-context.js';\r\nexport { WuAIActions } from './ai/wu-ai-actions.js';\r\nexport { WuAIConversation } from './ai/wu-ai-conversation.js';\r\nexport { WuAITriggers } from './ai/wu-ai-triggers.js';\r\nexport { WuAIAgent } from './ai/wu-ai-agent.js';\r\nexport { WuAIOrchestrate } from './ai/wu-ai-orchestrate.js';\r\nexport {\r\n sanitizeForPrompt,\r\n redactSensitive,\r\n interpolate,\r\n buildToolSchemas,\r\n normalizeParameters,\r\n validateParams,\r\n estimateTokens,\r\n truncateToTokenBudget,\r\n} from './ai/wu-ai-schema.js';\r\n\r\n// --- MCP Bridge (browser-side connection to wu-mcp-server) ---\r\nexport { createMcpBridge } from './core/wu-mcp-bridge.js';\r\n\r\n// --- AI Browser Actions (autonomous agent control) ---\r\nexport { registerBrowserActions } from './ai/wu-ai-browser.js';\r\n\r\n// --- AI Browser Primitives (shared browser automation functions) ---\r\nexport {\r\n ensureInterceptors,\r\n captureScreenshot,\r\n buildA11yTree,\r\n clickElement,\r\n typeIntoElement,\r\n getFilteredNetwork,\r\n getFilteredConsole,\r\n} from './ai/wu-ai-browser-primitives.js';\r\n"],"names":["WuLogger","constructor","this","isDevelopment","detectEnvironment","logLevel","levels","debug","info","warn","error","silent","window","WU_DEBUG","process","env","NODE_ENV","location","hostname","URLSearchParams","search","has","setLevel","level","setDevelopment","isDev","shouldLog","args","console","log","wu","wuDebug","wuInfo","wuWarn","wuError","logger","silenceAllLogs","enableAllLogs","WuLoader","options","maxCacheSize","cacheTTL","cache","Map","loadingPromises","_cacheGet","key","entry","get","now","Date","timestamp","delete","lastAccess","set","code","_cacheSet","_evictIfNeeded","size","oldestKey","keys","next","value","loadApp","appUrl","manifest","_ensureSentinelVerified","fullUrl","cached","undefined","loadingPromise","fetchCode","Error","message","loadComponent","componentPath","normalizedPath","startsWith","substring","endsWith","loadCode","componentFunction","Function","fakeModule","exports","component","name","url","response","fetch","headers","Accept","ok","status","statusText","text","trim","preload","appConfigs","length","preloadPromises","map","async","config","Promise","allSettled","isAvailable","method","resolveDependencies","imports","availableApps","resolved","importPath","appName","componentName","split","app","exportPath","clearCache","pattern","regex","RegExp","test","clear","getStats","loading","cacheKeys","Array","from","host","__wu_sentinel","isVerified","resolve","reject","timeout","setTimeout","cleanup","onVerified","clearTimeout","removeEventListener","addEventListener","check","setInterval","clearInterval","origCleanup","WuStyleBridge","styleObserver","fullyIsolatedApps","autoShareLibraries","sharePatterns","mode","cacheEnabled","registerFullyIsolatedApp","isStyleFromFullyIsolatedApp","styleUrlOrElement","getAttribute","href","viteId","element","normalizedUrl","replace","toLowerCase","entries","normalizedAppUrl","normalizedAppName","includes","detectDocumentStyles","styles","document","querySelectorAll","forEach","link","push","type","library","extractLibraryName","style","index","content","textContent","adoptedStyleSheets","sheet","shouldShareStyle","urlOrId","lib","nodeModulesMatch","match","viteMatch","injectStylesIntoShadow","shadowRoot","styleMode","injectedCount","injectLinkStyle","injectInlineStyle","injectAdoptedStyleSheet","querySelector","createElement","rel","setAttribute","insertBefore","firstChild","styleTag","observeStyleChanges","callback","disconnect","MutationObserver","mutations","hasStyleChanges","mutation","addedNodes","some","node","tagName","observe","head","childList","subtree","configure","totalStyles","linkStyles","filter","s","inlineStyles","libraries","Set","Boolean","WuProxySandbox","proxy","fakeWindow","Object","create","active","modifiedKeys","_timers","_intervals","_rafs","_eventListeners","_container","_shadowRoot","_scopedDocument","_scopedLocalStorage","_scopedSessionStorage","_patched","_originals","setContainer","container","activate","self","Proxy","target","prop","intercepted","_intercept","_isConstructor","bind","add","deleteProperty","deactivate","unpatchWindow","id","cancelAnimationFrame","timerCount","listenerCount","event","handler","patchWindow","originals","requestAnimationFrame","fn","delay","call","l","_getScopedDocument","_getScopedStorage","root","selector","CSS","escape","className","tag","cacheKey","realStorage","localStorage","sessionStorage","prefix","getItem","setItem","String","removeItem","toRemove","i","k","count","slice","prototype","getProxy","isActive","patched","isolatedPropsCount","trackedTimers","trackedIntervals","trackedRAFs","trackedEventListeners","hasContainer","hasShadowRoot","WuSnapshotSandbox","snapshot","restoredCount","deletedCount","currentValue","originalValue","snapshotSize","WuSandbox","sandboxes","styleBridge","jsSandboxes","sandboxStrategy","detectSandboxStrategy","hostContainer","attachShadow","innerHTML","delegatesFocus","appContainer","toString","baseStyles","generateSandboxStyles","appendChild","jsSandbox","createAdvancedJSSandbox","jsProxy","sandbox","created","sandbox_state","recovery_count","stylesReady","tryInject","injectOwnStylesToShadow","observer","newStyleCount","m","n","nodeName","pop","fallbackCount","injectAllStylesToShadow","then","catch","err","createFallbackSandbox","fallbackContainer","cssText","healedSandbox","fallback_mode","healingError","addStyles","css","styleElement","loadExternalStyles","linkElement","setDebugMode","enabled","removeAttribute","cleanupEventListeners","cloneNode","clone","parentNode","replaceChild","getSandboxInfo","elementCount","children","uptime","strategy","total","details","elements","hasJsSandbox","jsSandboxActive","cleanupAll","configureStyleSharing","getStyleStats","reinjectStyles","allStyles","appPatterns","matchingCount","normalizedViteId","belongsToApp","clonedStyle","styleName","lastIndexOf","WuManifest","schemas","security","maxManifestSize","maxNameLength","maxEntryLength","maxExports","maxImports","maxRoutes","dangerousPatterns","blockedDomains","defineSchema","required","optional","routes","permissions","load","manifestUrl","createDefaultManifest","manifestText","JSON","parse","parseError","validatedManifest","validate","defaultError","extractAppNameFromUrl","defaultManifest","pathSegments","URL","pathname","_sanitizeString","str","_hasDangerousPatterns","_isUrlSafe","urlObj","d","schema","isArray","field","path","validModes","join","version","folder","normalize","normalized","normalizeEntry","normalizedExports","normalizeComponentPath","imp","validateDependencies","result","valid","invalid","missing","import","reason","exportExists","WuStore","bufferSize","nextPowerOfTwo","mask","buffer","cursor","state","listeners","patternListeners","metrics","reads","writes","notifications","reduce","obj","sequence","performance","updateState","queueMicrotask","notify","notifyPatterns","on","batch","updates","sequences","getMetrics","bufferUtilization","Math","min","pow","ceil","log2","last","exactListeners","parts","parentPath","parentListeners","parentValue","matchesPattern","regexPattern","part","getRecentEvents","events","max","reverse","store","WuApp","keepAlive","_wu","_mounted","_autoInit","autoInit","_registerApp","apps","mount","targetContainer","isInitialized","init","unmount","isHidden","hide","show","remount","force","isMounted","mounted","reload","loader","verify","hasShadowDOM","hasContent","found","registered","mountedInWu","start","stop","destroy","WuCache","maxSize","maxItems","defaultTTL","persistent","storage","rateLimiting","maxOpsPerSecond","windowMs","cooldownMs","operations","inCooldown","cooldownUntil","_rateLimitNotified","memoryCache","accessOrder","stats","hits","misses","sets","evictions","rateLimited","_checkRateLimit","windowStart","ts","_onRateLimited","operation","cooldownRemaining","getRateLimitStatus","currentOps","maxOps","isExpired","stored","getFromStorage","ttl","estimateSize","ensureSpace","saveToStorage","deleteFromStorage","clearStorage","stringify","neededSize","maxSizeBytes","maxIterations","iterations","oldestTime","Infinity","time","getStorage","cleanOldStorageEntries","sort","a","b","hitRate","toFixed","items","sizeMB","WuEventBus","history","authorizedApps","trustedEvents","isProduction","maxHistory","enableReplay","enableWildcards","logEvents","strictMode","validateOrigin","_permissiveWarned","emitted","subscriptions","rejected","registerApp","token","_generateToken","registeredAt","unregisterApp","_validateOrigin","eventName","_isSystemEvent","appInfo","_hasPermission","matchesWildcard","random","substr","_warnPermissiveMode","emit","data","meta","verified","addToHistory","notifyWildcardListeners","off","once","wrappedCallback","shift","replay","eventNameOrPattern","clearHistory","activeListeners","historySize","listenersByEvent","enableStrictMode","disableStrictMode","removeAll","WuPerformance","measurements","marks","maxMeasurements","thresholds","startMeasure","markName","endMeasure","startTime","duration","recordMeasurement","checkThreshold","measurement","calculateStats","appMetrics","byType","durations","avg","threshold","generateReport","report","totalMeasurements","measurementCount","getAllMetrics","allMetrics","clearMetrics","WuPluginSystem","core","_core","plugins","hooks","availableHooks","availablePermissions","hookTimeout","hook","_createSandboxedApi","api","getAppInfo","getMountedApps","eventBus","cb","getState","setState","safeKeys","safeConfig","assign","_unsafeCore","_deepFreeze","seen","isPlainObject","getPrototypeOf","WeakSet","freeze","_validatePlugin","plugin","hookName","perm","use","sandboxedApi","install","wrappedHook","_wrapHook","registerHook","installedAt","hookFn","pluginName","context","timeoutPromise","_","race","callHook","callbacks","uninstall","pluginData","getPlugin","totalPlugins","WuLoadingStrategy","strategies","loadingQueue","isIdle","registerDefaultStrategies","setupIdleCallback","register","shouldPreload","priority","moduleUrl","resolveModulePath","as","prefetcher","prefetch","eagerness","processIdleQueue","strategyName","toPreload","priorityOrder","high","medium","low","aPriority","bPriority","idleCallback","deadline","requestIdleCallback","timeRemaining","item","totalStrategies","idleQueueSize","WuErrorBoundary","handlers","errorLog","maxErrorLog","maxRetries","retryDelay","showErrorUI","registerDefaultHandlers","canHandle","handle","retryCount","recovered","action","fallbackUrl","cleanupError","logError","renderFallback","handlerError","errorUI","padding","borderRadius","background","border","color","fontFamily","textAlign","icon","fontSize","marginBottom","title","margin","button","fontWeight","stack","safeContext","val","errorEntry","getErrorLog","limit","errorsByType","totalErrors","recentErrors","WuLifecycleHooks","executionLog","maxLogSize","lifecyclePhases","phase","middleware","remove","findIndex","h","splice","execute","executionEntry","hooksCount","hookNames","currentContext","cancelled","executeChain","nextCalled","modifiedContext","success","useMultiple","phases","unregisterFns","getHooks","allHooks","totalHooks","values","sum","executionsByPhase","avgDuration","cancelledCount","totalExecutions","round","recentExecutions","p","WuHtmlParser","_cache","fetchHtml","html","baseUrl","doc","DOMParser","parseFromString","inlineScripts","externalScripts","externalStyles","ctx","_extractResources","temp","body","documentElement","dom","scripts","inline","external","fetchAndParse","child","replaceWith","createComment","_resolveUrl","_extractScript","el","src","base","WuScriptExecutor","static","label","_validateScript","scriptText","DANGEROUS_PATTERNS","msg","strictGlobal","sourceUrl","sourceComment","wrappedCode","fetchScript","executeAll","script","WuIframeSandbox","iframe","_active","_listeners","shadowContainer","contentWindow","iframeWin","iframeDoc","open","write","close","_patchDocument","_patchTimers","importModule","channelId","onMessage","timer","queryTarget","mainDoc","createElementNS","ns","createTextNode","createDocumentFragment","sel","getElementById","getElementsByClassName","cls","getElementsByTagName","defineProperty","configurable","origDocAdd","origDocRemove","origSetTimeout","origClearTimeout","origSetInterval","origClearInterval","ms","origRAF","origCancelRAF","contentDocument","removeChild","WuPrefetch","prefetched","_observers","_speculationScript","_speculationRules","prerender","supportsSpeculationRules","_detectSpeculationRules","supportsModulePreload","_detectModulePreload","HTMLScriptElement","supports","relList","appNames","names","trigger","_prefetchImmediate","_prefetchOnHover","_prefetchOnVisible","_prefetchOnIdle","urls","_resolveAppUrls","_addSpeculationRules","_injectModulePreload","_injectPrefetch","_resolveTarget","done","passive","IntersectionObserver","isIntersecting","rootMargin","cancelIdleCallback","newEntries","urlList","source","_updateSpeculationScript","e","results","definitions","Element","prefetchAll","unmountedApps","activeObservers","speculationRulesSupported","modulePreloadSupported","speculationRules","COOKIE_PREFIX","WuOverrides","_overrides","_allowedDomains","allowedDomains","_showIndicator","showIndicator","_indicatorElement","_enabled","_isDevEnvironment","_parseFromCookies","port","_isDomainAllowed","_extractHostname","_matchDomain","suffix","cookies","cookie","pairs","pair","trimmed","eqIndex","indexOf","_isValidUrl","applyToApps","overrideUrl","_originalUrl","_showOverrideIndicator","getOverrideFor","maxAge","_removeOverrideIndicator","clearAll","getAll","fromEntries","hasOverrides","isEnabled","refresh","indicator","overrideList","display","preventDefault","existing","activeOverrides","overrides","environment","WuCore","manifests","hidden","_pendingUnmounts","_mountingPromises","htmlParser","scriptExecutor","pluginSystem","errorBoundary","_sandboxMode","appConfig","manifestData","define","lifecycle","CustomEvent","detail","dispatchEvent","containerSelector","hiddenEntry","_destroyHidden","mountPromise","mountWithRecovery","attempt","loadAndMountRemoteApp","mountTime","sb","proxySandbox","errorResult","maxAttempts","appStateCleanup","hiddenError","unmountError","removeError","shadowError","htmlError","emergencyError","_loadStrict","_loadEval","_loadModule","moduleLoader","iframeSandbox","importError","_waitForDefine","parsed","styleTarget","entryFile","directPath","pathCandidates","candidate","validatePath","fallbackPath","signal","AbortSignal","contentType","trimmedContent","loadError","_executeUnmount","hiddenAt","showTime","definition","defined","onStateChange","batchState","getStoreMetrics","clearState","override","removeOverride","getOverrides","clearOverrides","BaseAdapter","model","formatRequest","parseResponse","parseStreamChunk","getHeaders","AnthropicAdapter","super","apiKey","messages","systemMsgs","role","otherMsgs","max_tokens","maxTokens","tool_use_id","tool_call_id","tool_calls","tc","input","arguments","system","responseFormat","rf","jsonInstruction","schemaStr","tools","t","description","input_schema","parameters","temperature","stream","textBlocks","toolBlocks","toolCalls","usage","prompt_tokens","input_tokens","completion_tokens","output_tokens","line","raw","delta","argumentsDelta","partial_json","content_block","CustomAdapter","_sendFn","send","_streamFn","isCustom","BUILTIN_ADAPTERS","openai","function","response_format","json_schema","strict","choice","choices","_safeParseArgs","anthropic","ollama","format","eval_count","prompt_eval_count","WuAIProvider","_providers","_activeName","_activeConfig","_retryConfig","baseDelayMs","adapterName","adapter","AdapterClass","_resolveProvider","provider","endpoint","_fetchWithRetry","json","reader","getReader","decoder","TextDecoder","needsPrefill","read","decode","lines","chunk","releaseLock","lastError","r","clientError","_noRetry","origin","providerName","_ensureActive","configureRetry","getActiveProvider","activeProvider","registeredProviders","DEFAULT_PERMISSIONS","readStore","writeStore","emitEvents","readDOM","modifyDOM","executeActions","allowDirectKey","CB_CLOSED","CB_OPEN","CB_HALF_OPEN","RateLimiter","_maxPerMinute","requestsPerMinute","_maxPerMinutePerNs","requestsPerMinutePerNs","_maxConcurrent","maxConcurrent","_globalTimestamps","_nsTimestamps","_concurrent","canSend","namespace","_pruneOld","allowed","recordStart","recordEnd","cutoff","timestamps","pruned","globalRequestsLastMinute","concurrent","maxPerMinute","CircuitBreaker","_state","_failureCount","_maxFailures","maxFailures","_cooldownMs","_openedAt","_rapidFireThreshold","rapidFireThreshold","_rapidFireWindowMs","rapidFireWindowMs","_recentRequests","canPass","remainingMs","recordSuccess","_recordRequest","recordFailure","_tripOpen","failureCount","openedAt","reset","LoopProtection","_maxDepth","maxDepth","_activeTraces","_traceLog","_maxTraceLog","canProceed","depth","traceId","enter","exit","createTraceId","getTraces","activeTraces","traceLogSize","WuAIPermissions","_permissions","rateLimiter","rateLimit","circuitBreaker","loopProtection","_isProduction","permission","getPermissions","setAllowedDomains","domains","isDomainAllowed","preflight","rl","lp","SENSITIVE_KEYS","sanitizeForPrompt","maxChars","redacted","redactSensitive","lowerKey","sk","interpolate","template","vars","_match","buildToolSchemas","actions","normalizeParameters","params","properties","def","isRequired","rest","validateParams","errors","actualType","Number","isInteger","enum","WuAIContext","_store","_eventBus","_config","budget","charRatio","sources","include","lastN","custom","_collectors","_lastSnapshot","collector","collect","_timestamp","_mountedApps","_getMountedApps","storeData","_collectStore","_collectEvents","_events","toSystemPrompt","_baseSystemPrompt","charBudget","usedChars","prioritized","_prioritizeSections","section","sectionText","remaining","tool","getSnapshot","getInterpolationContext","_matchPattern","sections","storePriority","eventPriority","eventLines","toUpperCase","order","prompt","collectors","storePaths","eventPatterns","lastCollected","WuAIActions","_actions","_executionLog","_maxLogSize","_pendingConfirms","confirm","dangerous","unregister","_emitDenied","validation","_requestConfirmation","callId","_log","getToolSchemas","getNames","getLog","confirmTool","pending","rejectTool","requiredPermissions","perms","actionName","timeoutHandle","registeredActions","executionLogSize","pendingConfirmations","DEFAULT_CONFIG","maxHistoryMessages","maxToolRounds","defaultNamespace","systemPrompt","namespaceTTL","gcInterval","ConversationNamespace","createdAt","lastActivity","_abortController","addMessage","_ts","getMessages","truncate","maxMessages","kept","abort","createAbortController","AbortController","WuAIConversation","_provider","_context","_namespaces","_activeRequests","_lastGcRun","_getOrCreateNamespace","_buildSystemPrompt","_setSystemMessage","processedMessage","_processMessage","templateVars","controller","_mergeSignals","toolResults","rounds","maxRounds","assistantMsg","tool_results","toolCall","fullContent","toolCallAccumulator","streamEnded","idx","acc","parsedArgs","inject","getHistory","abortAll","getNamespaces","deleteNamespace","nsName","_maybeGcSweep","interval","toDelete","unshift","internalSignal","externalSignal","any","merged","onAbort","namespaces","messageCount","hasActiveRequest","DEFAULT_TRIGGER_CONFIG","maxActiveTriggers","defaultDebounceMs","batchIntervalMs","Trigger","condition","debounceMs","debounce","onResult","_debounceTimer","_lastFired","_fireCount","_pendingEvent","matches","buildPrompt","eventData","checkCondition","WuAITriggers","conversation","_conversation","_triggers","_batchQueue","_batchTimer","_stats","totalFired","totalSkipped","unsub","_handleEvent","setEnabled","setAllEnabled","fire","_executeTrigger","getTrigger","fireCount","lastFired","triggerName","_debouncedFire","_scheduleBatch","_processBatch","byTrigger","triggers","triggerCount","batchQueueSize","DONE_MARKER","AGENT_NAMESPACE_PREFIX","WuAIAgent","maxSteps","_activeRuns","totalRuns","totalSteps","completedRuns","abortedRuns","errorRuns","run","goal","_generateNamespace","runId","_generateRunId","aborted","_buildAgentSystemPrompt","step","previousHadToolCalls","finalReason","stepStart","_buildStepResult","elapsed","_emitStep","hasToolResults","onStep","_safeCallback","currentHasToolCalls","stepType","shouldContinue","shouldGo","interrupted","maxStepResult","getActiveRuns","activeRuns","basePrompt","paramKeys","networkLog","MAX_NETWORK_LOG","consoleLog","_interceptorsInstalled","ensureInterceptors","originalFetch","req","apply","parseInt","origOpen","XMLHttpRequest","origSend","_wuAi","getResponseHeader","_installNetworkInterceptor","original","_installConsoleInterceptor","buildA11yTree","indent","repeat","ariaLabel","childNodes","nodeType","inlineComputedStyles","props","getComputedStyle","getPropertyValue","setProperty","srcKids","cloneKids","captureScreenshot","quality","rect","getBoundingClientRect","w","width","innerWidth","height","innerHeight","xhtml","XMLSerializer","serializeToString","svgStr","svgBlob","Blob","createObjectURL","dataUrl","img","Image","onload","canvas","getContext","drawImage","revokeObjectURL","toDataURL","onerror","base64","sizeKB","clickElement","candidates","searchText","scrollIntoView","behavior","block","click","clicked","toJSON","typeIntoElement","submit","focus","Event","bubbles","nativeSetter","getOwnPropertyDescriptor","HTMLInputElement","HTMLTextAreaElement","newValue","form","closest","cancelable","KeyboardEvent","typed","submitted","getFilteredNetwork","filtered","requests","showing","getFilteredConsole","executeDeterministicStep","waitForSelector","WuAIOrchestrate","agent","_agent","_capabilities","_workflows","defaultProvider","defaultTemperature","totalIntents","resolvedIntents","failedIntents","workflowsRegistered","workflowsExecuted","qualifiedName","appCaps","removeApp","removed","capabilitiesRemoved","getCapabilityMap","getRegisteredApps","hasApp","getTotalCapabilities","_buildOrchestratorPrompt","capabilities","appsInvolved","_extractInvolvedApps","buildOrchestratorPrompt","capMap","cap","plan","registerWorkflow","steps","executeWorkflow","workflow","paramName","paramConfig","_executeDeterministic","_executeWithAgent","interpolatedSteps","_buildWorkflowGoal","finalStep","interpolated","lastStep","stepNum","execResult","stepResult","hasWorkflow","getWorkflow","removeWorkflow","getWorkflowNames","registeredApps","totalCapabilities","capabilityMap","workflows","colonIdx","registerBrowserActions","ai","option","find","o","selected","note","direction","amount","scrollEl","scrollBy","top","scrollTo","scrollHeight","scrolled","currentScroll","scrollTop","route","navigated","_apps","storeKeys","viewport","networkRequests","consoleMessages","consoleErrors","WuAI","_initialized","_modules","_reconfigure","orchestrate","_ensureInit","schemaName","fireTrigger","capability","intent","runWorkflow","opts","expose","navigator","modelContext","actionNames","registerTool","inputSchema","toolCount","initialized","createMcpBridge","ws","reconnectTimer","reconnectAttempts","authenticated","authToken","eventLog","_checkPermission","_audit","connected","framework","_getAppList","actionsCount","eventLogSize","list_apps","list_events","list_actions","screenshot","network","get_state","set_state","updated","emit_event","navigate","mount_app","unmount_app","unmounted","textLength","execute_action","connect","readyState","WebSocket","onopen","onmessage","_respond","command","onclose","_scheduleReconnect","isConnected","_isWuFramework","WU_KEY","Symbol","for","features","silence","wuLogger","verbose","_aiInstance","mcp","_mcpBridge","wu_default","beforeInit","afterInit","beforeMount","afterMount","beforeUnmount","afterUnmount","onError","onDestroy","transformer","modified"],"mappings":"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"}