From 480d4d618e04a679d249609089df72bc4bb41643 Mon Sep 17 00:00:00 2001 From: josedario87 Date: Fri, 13 Feb 2026 03:05:55 -0600 Subject: [PATCH] Reconexion automatica en el cliente cuando falla la conexion WebSocket - Retry con backoff (hasta 3 intentos, delay incremental) - Suprimir errores de consola durante reintentos - Mostrar estado "Reconectando" en el widget - Si todos los reintentos fallan, limpiar sesion y mostrar form de token --- build/webmcp.js | 35 +++++++++++++++++++++++++++-------- build/webmcp.js.map | 4 ++-- src/webmcp.js | 45 ++++++++++++++++++++++++++++++++++++--------- 3 files changed, 65 insertions(+), 19 deletions(-) diff --git a/build/webmcp.js b/build/webmcp.js index c6868ae..ebdbf66 100644 --- a/build/webmcp.js +++ b/build/webmcp.js @@ -26,6 +26,10 @@ this.registeredTools = /* @__PURE__ */ new Set(); this.registeredPrompts = /* @__PURE__ */ new Set(); this.registeredResources = /* @__PURE__ */ new Set(); + this._reconnectAttempts = 0; + this._maxReconnectAttempts = 3; + this._reconnectDelay = 1e3; + this._lastConnectionToken = null; this.SESSION_STORAGE_KEY = "webmcp_token"; this.TOOLS_STORAGE_KEY = "webmcp_tools"; this.PROMPTS_STORAGE_KEY = "webmcp_prompts"; @@ -739,6 +743,7 @@ this._updateStatus("disconnected", "Error: No token provided"); return; } + this._lastConnectionToken = connectionToken; this._updateStatus("connecting", "Connecting..."); try { if (!this._processConnectionToken(connectionToken)) { @@ -884,6 +889,7 @@ } this.socket.addEventListener("open", () => { this.isConnected = true; + this._reconnectAttempts = 0; this._updateStatus("connected", `Connected to ${this.currentChannel}`); this._updateConnectionUI(true); console.log("WebMCP connection established"); @@ -891,18 +897,31 @@ }); this.socket.addEventListener("close", (event) => { this.isConnected = false; + console.log(`Connection closed: ${event.code} ${event.reason}`); + if (event.code === 1e3) { + this._updateStatus("disconnected", "Disconnected"); + this._updateConnectionUI(false); + return; + } + if (this._reconnectAttempts < this._maxReconnectAttempts && this._lastConnectionToken) { + this._reconnectAttempts++; + const delay = this._reconnectDelay * this._reconnectAttempts; + console.log(`Reconnecting (attempt ${this._reconnectAttempts}/${this._maxReconnectAttempts}) in ${delay}ms...`); + this._updateStatus("connecting", `Reconectando (${this._reconnectAttempts}/${this._maxReconnectAttempts})...`); + setTimeout(() => { + this.connect(this._lastConnectionToken); + }, delay); + return; + } this._updateStatus("disconnected", "Disconnected"); this._updateConnectionUI(false); - console.log(`Connection closed: ${event.code} ${event.reason}`); - if (event.code === 1001 || event.code === 401) { - this._updateStatus("disconnected", "Authorization failed"); - this.currentToken = ""; - this.currentServer = ""; - this.currentChannel = ""; - sessionStorage.removeItem(this.SESSION_STORAGE_KEY); - } + this.currentToken = ""; + this.currentServer = ""; + this.currentChannel = ""; + sessionStorage.removeItem(this.SESSION_STORAGE_KEY); }); this.socket.addEventListener("error", () => { + if (this._reconnectAttempts > 0) return; console.error("WebSocket error"); if (this.isConnected) { this._updateStatus("disconnected", "Connection error occurred"); diff --git a/build/webmcp.js.map b/build/webmcp.js.map index d201e78..02f13c0 100644 --- a/build/webmcp.js.map +++ b/build/webmcp.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/webmcp.js"], - "sourcesContent": ["/**\n * WebMCP - Snippet to add MCP functionality to any website\n *\n * Shows as a small blue square in bottom right corner\n * On click, expands to allow connection with token\n * Auto-disconnects after 5 minutes of inactivity\n */\n\nclass WebMCP {\n constructor(options = {}) {\n // Options with defaults\n this.options = {\n color: '#007bff',\n position: 'bottom-right',\n size: '30px',\n padding: '20px',\n inactivityTimeout: 5 * 60 * 1000, // 5 minutes in milliseconds\n ...options\n };\n\n // State variables\n this.isConnected = false;\n this.isExpanded = false;\n this.socket = null;\n this.inactivityTimer = null;\n this.availableTools = new Map();\n this.availablePrompts = new Map();\n this.availableResources = new Map();\n this.samplingCallbacks = new Map(); // For storing sampling callbacks\n this.currentToken = '';\n this.currentServer = '';\n this.currentChannel = '';\n this.elementId = 'webmcp-widget-' + Math.random().toString(36).substr(2, 9);\n this.registeredTools = new Set();\n this.registeredPrompts = new Set();\n this.registeredResources = new Set();\n\n // Storage keys for sessionStorage\n this.SESSION_STORAGE_KEY = 'webmcp_token';\n this.TOOLS_STORAGE_KEY = 'webmcp_tools';\n this.PROMPTS_STORAGE_KEY = 'webmcp_prompts';\n this.RESOURCES_STORAGE_KEY = 'webmcp_resources';\n\n // Constants\n this.REGISTER_PATH = '/register';\n\n // Initialize\n this._init();\n }\n\n _format(s) {\n return s.replace(/[.:]/g, '_');\n }\n\n /**\n * Initialize the WebMCP widget\n * @private\n */\n _init() {\n // Check if already initialized on this page\n if (document.querySelector('[data-webmcp-widget]')) {\n console.warn('WebMCP widget already initialized on this page');\n return;\n }\n\n // Create and inject the widget\n this._createWidget();\n\n // Set up event listeners\n this._setupEventListeners();\n\n // Start inactivity timer\n this._resetInactivityTimer();\n\n // Check for stored token and connect if available\n this._checkStoredToken();\n }\n\n /**\n * Check for stored connection info in sessionStorage and connect if found\n * @private\n */\n _checkStoredToken() {\n const storedConnectionInfo = sessionStorage.getItem(this.SESSION_STORAGE_KEY);\n\n if (storedConnectionInfo) {\n try {\n const connectionInfo = JSON.parse(storedConnectionInfo);\n if (connectionInfo.token) {\n console.log('Found stored connection info, attempting to connect');\n\n // Set the connection properties directly\n this.currentServer = connectionInfo.server;\n this.currentChannel = `/${connectionInfo.channelHost || this._format(window.location.host)}`;\n\n // Set the current token from connection info\n if (connectionInfo.token.includes('{')) {\n // It's already parsed JSON\n const tokenData = JSON.parse(connectionInfo.token);\n this.currentToken = tokenData.token;\n } else {\n // It's a base64 encoded string\n try {\n const jsonStr = atob(connectionInfo.token);\n const tokenData = JSON.parse(jsonStr);\n this.currentToken = tokenData.token;\n } catch (e) {\n this.currentToken = connectionInfo.token;\n }\n }\n\n // Load stored items before connecting\n this._loadStoredItems();\n\n // Connect using the stored token\n this.connect(connectionInfo.token);\n }\n } catch (error) {\n console.error('Error parsing stored connection info:', error);\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n this._clearStoredItems();\n }\n }\n }\n\n /**\n * Save tools, prompts, and resources to session storage\n * @private\n */\n _saveItemsToStorage() {\n try {\n // Save tools\n const toolsData = {};\n this.availableTools.forEach((tool, name) => {\n toolsData[name] = {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n // We don't store the execution function as it can't be serialized\n };\n });\n sessionStorage.setItem(this.TOOLS_STORAGE_KEY, JSON.stringify(toolsData));\n\n // Save prompts\n const promptsData = {};\n this.availablePrompts.forEach((prompt, name) => {\n promptsData[name] = {\n name: prompt.name,\n description: prompt.description,\n arguments: prompt.arguments,\n // We don't store the execution function as it can't be serialized\n };\n });\n sessionStorage.setItem(this.PROMPTS_STORAGE_KEY, JSON.stringify(promptsData));\n\n // Save resources\n const resourcesData = {};\n this.availableResources.forEach((resource, name) => {\n resourcesData[name] = {\n name: resource.name,\n description: resource.description,\n uri: resource.uri,\n uriTemplate: resource.uriTemplate,\n isTemplate: resource.isTemplate,\n mimeType: resource.mimeType,\n // We don't store the provide function as it can't be serialized\n };\n });\n sessionStorage.setItem(this.RESOURCES_STORAGE_KEY, JSON.stringify(resourcesData));\n\n console.log('Saved items to session storage:', {\n tools: Object.keys(toolsData).length,\n prompts: Object.keys(promptsData).length,\n resources: Object.keys(resourcesData).length\n });\n } catch (error) {\n console.error('Error saving items to session storage:', error);\n }\n }\n\n /**\n * Load tools, prompts, and resources from session storage\n * @private\n */\n _loadStoredItems() {\n try {\n // Load tools\n const storedTools = sessionStorage.getItem(this.TOOLS_STORAGE_KEY);\n if (storedTools) {\n const toolsData = JSON.parse(storedTools);\n Object.entries(toolsData).forEach(([name, tool]) => {\n // Add to the available tools with placeholder execute function\n this.availableTools.set(name, {\n ...tool,\n execute: function (args) {\n console.warn(`Tool ${name} was loaded from storage but has not been re-registered with an execution function`);\n return `Tool ${name} needs to be re-registered`;\n }\n });\n });\n }\n\n // Load prompts\n const storedPrompts = sessionStorage.getItem(this.PROMPTS_STORAGE_KEY);\n if (storedPrompts) {\n const promptsData = JSON.parse(storedPrompts);\n Object.entries(promptsData).forEach(([name, prompt]) => {\n // Add to the available prompts with placeholder execute function\n this.availablePrompts.set(name, {\n ...prompt,\n execute: function (args) {\n console.warn(`Prompt ${name} was loaded from storage but has not been re-registered with an execution function`);\n return {\n messages: [{\n role: \"user\",\n content: {\n type: \"text\",\n text: `Prompt ${name} needs to be re-registered`\n }\n }]\n };\n }\n });\n });\n }\n\n // Load resources\n const storedResources = sessionStorage.getItem(this.RESOURCES_STORAGE_KEY);\n if (storedResources) {\n const resourcesData = JSON.parse(storedResources);\n Object.entries(resourcesData).forEach(([name, resource]) => {\n // Add to the available resources with placeholder provide function\n this.availableResources.set(name, {\n ...resource,\n provide: function (uri) {\n console.warn(`Resource ${name} was loaded from storage but has not been re-registered with a provider function`);\n return {\n contents: [{\n uri: uri,\n text: `Resource ${name} needs to be re-registered`,\n mimeType: resource.mimeType || \"text/plain\"\n }]\n };\n }\n });\n });\n }\n\n console.log('Loaded items from session storage:', {\n tools: this.availableTools.size,\n prompts: this.availablePrompts.size,\n resources: this.availableResources.size\n });\n\n // Update the UI\n this._updateToolsList();\n this._updatePromptsList();\n this._updateResourcesList();\n\n } catch (error) {\n console.error('Error loading items from session storage:', error);\n this._clearStoredItems();\n }\n }\n\n /**\n * Clear all stored items from session storage\n * @private\n */\n _clearStoredItems() {\n sessionStorage.removeItem(this.TOOLS_STORAGE_KEY);\n sessionStorage.removeItem(this.PROMPTS_STORAGE_KEY);\n sessionStorage.removeItem(this.RESOURCES_STORAGE_KEY);\n console.log('Cleared stored items from session storage');\n }\n\n /**\n * Create and inject the WebMCP widget into the DOM\n * @private\n */\n _createWidget() {\n // Create main container\n const container = document.createElement('div');\n container.id = this.elementId;\n container.dataset.webmcpWidget = true;\n\n // Apply styles\n Object.assign(container.style, {\n position: 'fixed',\n zIndex: '9999',\n display: 'flex',\n flexDirection: 'column',\n fontFamily: 'Arial, sans-serif',\n fontSize: '14px',\n transition: 'all 0.3s ease'\n });\n\n // Set position based on option\n this._setWidgetPosition(container);\n\n // Create trigger button (blue square)\n const triggerButton = document.createElement('div');\n triggerButton.className = 'webmcp-trigger';\n Object.assign(triggerButton.style, {\n width: this.options.size,\n height: this.options.size,\n backgroundColor: this.options.color,\n borderRadius: '4px',\n cursor: 'pointer',\n boxShadow: '0 2px 10px rgba(0,0,0,0.2)',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n alignSelf: 'flex-end'\n });\n\n // Create content panel (initially hidden) - positioned above the trigger\n const contentPanel = document.createElement('div');\n contentPanel.className = 'webmcp-content';\n Object.assign(contentPanel.style, {\n backgroundColor: '#ffffff',\n border: '1px solid #e1e1e1',\n borderRadius: '5px',\n padding: '15px',\n marginBottom: '10px',\n boxShadow: '0 5px 15px rgba(0,0,0,0.1)',\n width: '250px',\n display: 'none',\n overflow: 'hidden',\n position: 'absolute',\n bottom: '40px'\n });\n\n // Add header with title and close button\n const header = document.createElement('div');\n Object.assign(header.style, {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n marginBottom: '15px'\n });\n\n const title = document.createElement('div');\n title.textContent = 'WebMCP';\n Object.assign(title.style, {\n fontWeight: 'bold',\n fontSize: '16px'\n });\n\n const closeButton = document.createElement('button');\n closeButton.innerHTML = '×'; // \u00D7 symbol\n closeButton.className = 'webmcp-close';\n Object.assign(closeButton.style, {\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n fontSize: '20px',\n padding: '0',\n lineHeight: '1',\n color: '#999'\n });\n\n header.appendChild(title);\n header.appendChild(closeButton);\n contentPanel.appendChild(header);\n\n // Add connection form\n this._createConnectionForm(contentPanel);\n\n // Add status indicator\n const statusIndicator = document.createElement('div');\n statusIndicator.className = 'webmcp-status';\n statusIndicator.textContent = 'Disconnected';\n Object.assign(statusIndicator.style, {\n padding: '8px',\n borderRadius: '3px',\n backgroundColor: '#f8d7da',\n color: '#721c24',\n textAlign: 'center',\n marginBottom: '10px',\n fontSize: '12px'\n });\n contentPanel.appendChild(statusIndicator);\n\n // Add connection panel\n const connectionPanel = document.createElement('div');\n connectionPanel.className = 'webmcp-connection-panel';\n contentPanel.appendChild(connectionPanel);\n\n // Create a single container for all registered items\n const registeredItemsContainer = document.createElement('div');\n registeredItemsContainer.className = 'webmcp-registered-items';\n Object.assign(registeredItemsContainer.style, {\n marginTop: '15px',\n fontSize: '12px',\n display: 'none',\n maxHeight: '200px',\n overflow: 'auto',\n border: '1px solid #eee',\n borderRadius: '4px'\n });\n contentPanel.appendChild(registeredItemsContainer);\n\n // Add features lists (initially empty)\n // Tools list\n const toolsList = document.createElement('div');\n toolsList.className = 'webmcp-tools-list';\n Object.assign(toolsList.style, {\n padding: '10px',\n borderBottom: '1px solid #eee'\n });\n\n const toolsHeader = document.createElement('div');\n toolsHeader.textContent = 'Registered Tools:';\n Object.assign(toolsHeader.style, {\n fontWeight: 'bold',\n marginBottom: '5px'\n });\n\n const toolsContainer = document.createElement('ul');\n toolsContainer.className = 'webmcp-tools-container';\n Object.assign(toolsContainer.style, {\n listStyle: 'none',\n padding: '0',\n margin: '0'\n });\n\n toolsList.appendChild(toolsHeader);\n toolsList.appendChild(toolsContainer);\n registeredItemsContainer.appendChild(toolsList);\n\n // Prompts list\n const promptsList = document.createElement('div');\n promptsList.className = 'webmcp-prompts-list';\n Object.assign(promptsList.style, {\n padding: '10px',\n borderBottom: '1px solid #eee'\n });\n\n const promptsHeader = document.createElement('div');\n promptsHeader.textContent = 'Registered Prompts:';\n Object.assign(promptsHeader.style, {\n fontWeight: 'bold',\n marginBottom: '5px'\n });\n\n const promptsContainer = document.createElement('ul');\n promptsContainer.className = 'webmcp-prompts-container';\n Object.assign(promptsContainer.style, {\n listStyle: 'none',\n padding: '0',\n margin: '0'\n });\n\n promptsList.appendChild(promptsHeader);\n promptsList.appendChild(promptsContainer);\n registeredItemsContainer.appendChild(promptsList);\n\n // Resources list\n const resourcesList = document.createElement('div');\n resourcesList.className = 'webmcp-resources-list';\n Object.assign(resourcesList.style, {\n padding: '10px'\n });\n\n const resourcesHeader = document.createElement('div');\n resourcesHeader.textContent = 'Registered Resources:';\n Object.assign(resourcesHeader.style, {\n fontWeight: 'bold',\n marginBottom: '5px'\n });\n\n const resourcesContainer = document.createElement('ul');\n resourcesContainer.className = 'webmcp-resources-container';\n Object.assign(resourcesContainer.style, {\n listStyle: 'none',\n padding: '0',\n margin: '0'\n });\n\n resourcesList.appendChild(resourcesHeader);\n resourcesList.appendChild(resourcesContainer);\n registeredItemsContainer.appendChild(resourcesList);\n\n // Add to main container and then to document - content panel first so it appears above trigger\n container.appendChild(contentPanel);\n container.appendChild(triggerButton);\n document.body.appendChild(container);\n }\n\n /**\n * Set widget position based on option\n * @private\n */\n _setWidgetPosition(container) {\n const {position, padding} = this.options;\n\n switch (position) {\n case 'bottom-right':\n Object.assign(container.style, {\n bottom: padding,\n right: padding,\n alignItems: 'flex-end'\n });\n break;\n case 'bottom-left':\n Object.assign(container.style, {\n bottom: padding,\n left: padding,\n alignItems: 'flex-start'\n });\n break;\n case 'top-right':\n Object.assign(container.style, {\n top: padding,\n right: padding,\n alignItems: 'flex-end'\n });\n break;\n case 'top-left':\n Object.assign(container.style, {\n top: padding,\n left: padding,\n alignItems: 'flex-start'\n });\n break;\n default:\n // Default to bottom-right\n Object.assign(container.style, {\n bottom: padding,\n right: padding,\n alignItems: 'flex-end'\n });\n }\n }\n\n /**\n * Create the connection form\n * @private\n */\n _createConnectionForm(container) {\n const form = document.createElement('div');\n Object.assign(form.style, {\n marginBottom: '8px',\n });\n\n // Token input field\n const inputGroup = document.createElement('div');\n Object.assign(inputGroup.style, {\n display: 'flex',\n marginBottom: '8px',\n });\n\n const tokenInput = document.createElement('input');\n tokenInput.type = 'text';\n tokenInput.className = 'webmcp-token-input';\n tokenInput.placeholder = 'Paste connection token';\n Object.assign(tokenInput.style, {\n flex: '1',\n padding: '8px',\n border: '1px solid #ccc',\n borderRadius: '4px 0 0 4px',\n fontSize: '12px'\n });\n\n const connectButton = document.createElement('button');\n connectButton.className = 'webmcp-connect-btn';\n connectButton.textContent = 'Connect';\n Object.assign(connectButton.style, {\n padding: '8px 12px',\n backgroundColor: this.options.color,\n color: 'white',\n border: 'none',\n borderRadius: '0 4px 4px 0',\n cursor: 'pointer',\n fontSize: '12px'\n });\n\n inputGroup.appendChild(tokenInput);\n inputGroup.appendChild(connectButton);\n\n const disconnectButton = document.createElement('button');\n disconnectButton.className = 'webmcp-disconnect-btn';\n disconnectButton.textContent = 'Disconnect';\n Object.assign(disconnectButton.style, {\n padding: '8px 12px',\n backgroundColor: '#dc3545',\n color: 'white',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '12px',\n width: '100%',\n display: 'none'\n });\n\n form.appendChild(inputGroup);\n form.appendChild(disconnectButton);\n container.appendChild(form);\n }\n\n /**\n * Set up event listeners for the widget\n * @private\n */\n _setupEventListeners() {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n // Trigger button click - expand/collapse\n const trigger = container.querySelector('.webmcp-trigger');\n trigger.addEventListener('click', () => {\n this._toggleExpanded();\n });\n\n // Close button click - collapse\n const closeBtn = container.querySelector('.webmcp-close');\n closeBtn.addEventListener('click', () => {\n this._toggleExpanded(false);\n });\n\n // Connect button click\n const connectBtn = container.querySelector('.webmcp-connect-btn');\n connectBtn.addEventListener('click', () => {\n const tokenInput = container.querySelector('.webmcp-token-input');\n this.connect(tokenInput.value);\n });\n\n // Disconnect button click\n const disconnectBtn = container.querySelector('.webmcp-disconnect-btn');\n disconnectBtn.addEventListener('click', () => {\n this.disconnect();\n });\n\n // User activity detection to reset inactivity timer\n document.addEventListener('mousemove', () => this._resetInactivityTimer());\n document.addEventListener('keypress', () => this._resetInactivityTimer());\n document.addEventListener('click', () => this._resetInactivityTimer());\n document.addEventListener('scroll', () => this._resetInactivityTimer());\n }\n\n /**\n * Toggle the expanded state of the widget\n * @private\n */\n _toggleExpanded(force = null) {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const contentPanel = container.querySelector('.webmcp-content');\n this.isExpanded = force !== null ? force : !this.isExpanded;\n\n if (this.isExpanded) {\n contentPanel.style.display = 'block';\n } else {\n contentPanel.style.display = 'none';\n }\n\n this._resetInactivityTimer();\n }\n\n /**\n * Update the status indicator\n * @private\n */\n _updateStatus(status, message) {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const statusIndicator = container.querySelector('.webmcp-status');\n if (!statusIndicator) return;\n\n // Clear existing classes\n statusIndicator.classList.remove('connected', 'disconnected', 'connecting', 'pending-auth');\n\n // Set new status\n statusIndicator.textContent = message || status;\n\n // Apply styling based on status\n switch (status) {\n case 'connected':\n Object.assign(statusIndicator.style, {\n backgroundColor: '#d4edda',\n color: '#155724'\n });\n break;\n case 'disconnected':\n Object.assign(statusIndicator.style, {\n backgroundColor: '#f8d7da',\n color: '#721c24'\n });\n break;\n case 'connecting':\n Object.assign(statusIndicator.style, {\n backgroundColor: '#fff3cd',\n color: '#856404'\n });\n break;\n case 'pending-auth':\n Object.assign(statusIndicator.style, {\n backgroundColor: '#d1ecf1',\n color: '#0c5460'\n });\n break;\n }\n }\n\n /**\n * Update UI based on connection state\n * @private\n */\n _updateConnectionUI(isConnected) {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const tokenInput = container.querySelector('.webmcp-token-input');\n const connectBtn = container.querySelector('.webmcp-connect-btn');\n const disconnectBtn = container.querySelector('.webmcp-disconnect-btn');\n const registeredItemsContainer = container.querySelector('.webmcp-registered-items');\n\n if (isConnected) {\n tokenInput.style.display = 'none';\n connectBtn.style.display = 'none';\n disconnectBtn.style.display = 'block';\n registeredItemsContainer.style.display = 'block';\n\n // Update the trigger button to show connected state\n const trigger = container.querySelector('.webmcp-trigger');\n trigger.innerHTML = '\u2713';\n trigger.style.color = 'white';\n trigger.style.fontWeight = 'bold';\n } else {\n tokenInput.style.display = 'block';\n connectBtn.style.display = 'block';\n disconnectBtn.style.display = 'none';\n registeredItemsContainer.style.display = 'none';\n\n // Reset the trigger button\n const trigger = container.querySelector('.webmcp-trigger');\n trigger.innerHTML = '';\n }\n }\n\n /**\n * Update tools list in UI\n * @private\n */\n _updateToolsList() {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const toolsContainer = container.querySelector('.webmcp-tools-container');\n if (!toolsContainer) return;\n\n // Clear current list\n toolsContainer.innerHTML = '';\n\n if (this.availableTools.size === 0) {\n const emptyMessage = document.createElement('li');\n emptyMessage.textContent = 'No tools registered';\n emptyMessage.style.fontStyle = 'italic';\n emptyMessage.style.color = '#666';\n toolsContainer.appendChild(emptyMessage);\n return;\n }\n\n // Add each tool to the list\n this.availableTools.forEach((tool, name) => {\n const toolItem = document.createElement('li');\n Object.assign(toolItem.style, {\n padding: '5px 0',\n borderBottom: '1px solid #eee'\n });\n\n const toolName = document.createElement('strong');\n toolName.textContent = name;\n\n const toolDesc = document.createElement('div');\n toolDesc.textContent = tool.description;\n toolDesc.style.fontSize = '10px';\n toolDesc.style.color = '#666';\n\n toolItem.appendChild(toolName);\n toolItem.appendChild(toolDesc);\n toolsContainer.appendChild(toolItem);\n });\n }\n\n /**\n * Update prompts list in UI\n * @private\n */\n _updatePromptsList() {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const promptsContainer = container.querySelector('.webmcp-prompts-container');\n if (!promptsContainer) return;\n\n // Clear current list\n promptsContainer.innerHTML = '';\n\n if (this.availablePrompts.size === 0) {\n const emptyMessage = document.createElement('li');\n emptyMessage.textContent = 'No prompts registered';\n emptyMessage.style.fontStyle = 'italic';\n emptyMessage.style.color = '#666';\n promptsContainer.appendChild(emptyMessage);\n return;\n }\n\n // Add each prompt to the list\n this.availablePrompts.forEach((prompt, name) => {\n const promptItem = document.createElement('li');\n Object.assign(promptItem.style, {\n padding: '5px 0',\n borderBottom: '1px solid #eee'\n });\n\n const promptName = document.createElement('strong');\n promptName.textContent = name;\n\n const promptDesc = document.createElement('div');\n promptDesc.textContent = prompt.description;\n promptDesc.style.fontSize = '10px';\n promptDesc.style.color = '#666';\n\n promptItem.appendChild(promptName);\n promptItem.appendChild(promptDesc);\n promptsContainer.appendChild(promptItem);\n });\n }\n\n /**\n * Update resources list in UI\n * @private\n */\n _updateResourcesList() {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const resourcesContainer = container.querySelector('.webmcp-resources-container');\n if (!resourcesContainer) return;\n\n // Clear current list\n resourcesContainer.innerHTML = '';\n\n if (this.availableResources.size === 0) {\n const emptyMessage = document.createElement('li');\n emptyMessage.textContent = 'No resources registered';\n emptyMessage.style.fontStyle = 'italic';\n emptyMessage.style.color = '#666';\n resourcesContainer.appendChild(emptyMessage);\n return;\n }\n\n // Add each resource to the list\n this.availableResources.forEach((resource, name) => {\n const resourceItem = document.createElement('li');\n Object.assign(resourceItem.style, {\n padding: '5px 0',\n borderBottom: '1px solid #eee'\n });\n\n const resourceName = document.createElement('strong');\n resourceName.textContent = name;\n\n const resourceDesc = document.createElement('div');\n resourceDesc.textContent = resource.description +\n (resource.isTemplate ? ' (Template)' : '');\n resourceDesc.style.fontSize = '10px';\n resourceDesc.style.color = '#666';\n\n resourceItem.appendChild(resourceName);\n resourceItem.appendChild(resourceDesc);\n resourcesContainer.appendChild(resourceItem);\n });\n }\n\n /**\n * Reset the inactivity timer\n * @private\n */\n _resetInactivityTimer() {\n // Clear existing timer\n if (this.inactivityTimer) {\n clearTimeout(this.inactivityTimer);\n }\n\n // Set new timer\n this.inactivityTimer = setTimeout(() => {\n this._handleInactivity();\n }, this.options.inactivityTimeout);\n }\n\n /**\n * Handle user inactivity\n * @private\n */\n _handleInactivity() {\n console.log('Inactivity timeout reached, disconnecting');\n\n // Disconnect if connected\n if (this.isConnected) {\n this.disconnect();\n }\n\n // Minimize UI\n this._toggleExpanded(false);\n\n // Clear the stored token\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n }\n\n\n /**\n * Connect to the WebSocket server\n * @public\n * @param {string} connectionToken - The encoded connection token\n */\n async connect(connectionToken) {\n if (!connectionToken) {\n this._updateStatus('disconnected', 'Error: No token provided');\n return;\n }\n\n // Update UI to show connecting state\n this._updateStatus('connecting', 'Connecting...');\n\n try {\n // Process the connection token\n if (!this._processConnectionToken(connectionToken)) {\n return;\n }\n\n // Store the connection info in sessionStorage for page navigations\n const connectionInfo = {\n token: connectionToken,\n server: this.currentServer,\n host: this._format(window.location.host)\n };\n\n // Check if we have connection data already in sessionStorage\n const storedConnectionInfo = sessionStorage.getItem(this.SESSION_STORAGE_KEY);\n let skipRegistration = false;\n\n if (storedConnectionInfo) {\n try {\n const connectionInfo = JSON.parse(storedConnectionInfo);\n // If we already have a valid token and server, we can skip registration\n if (connectionInfo.server === this.currentServer &&\n connectionInfo.host === this._format(window.location.host)) {\n skipRegistration = true;\n }\n } catch (error) {\n console.error('Error parsing stored connection info:', error);\n }\n }\n\n if (!skipRegistration) {\n // First register with server\n const response = await this._registerWithServer(connectionToken);\n\n if (!response.token) {\n this._updateStatus('disconnected', 'Registration failed');\n return;\n }\n\n // Save the new token\n connectionInfo.token = response.token;\n this.currentToken = response.token;\n\n sessionStorage.setItem(this.SESSION_STORAGE_KEY, JSON.stringify(connectionInfo));\n }\n\n // Now connect to the actual channel\n const serverUrl = `${this.currentServer}${this.currentChannel}?token=${this.currentToken}`;\n\n // Update UI\n this._updateStatus('connecting', 'Connecting to channel...');\n\n // Create WebSocket connection with the path and token\n this.socket = new WebSocket(serverUrl);\n\n // Set up socket event listeners\n this._setupSocketListeners();\n\n // Reset inactivity timer\n this._resetInactivityTimer();\n\n } catch (error) {\n console.error('Connection error:', error);\n this._updateStatus('disconnected', `Error: ${error.message}`);\n }\n }\n\n /**\n * Disconnect from WebSocket server\n * @public\n */\n disconnect() {\n // Close the WebSocket connection if it exists\n if (this.socket) {\n this.socket.close();\n this.socket = null;\n }\n\n this.isConnected = false;\n this._updateStatus('disconnected', 'Disconnected');\n this._updateConnectionUI(false);\n\n // Reset state\n this.currentToken = '';\n this.currentServer = '';\n this.currentChannel = '';\n\n // Remove the token from sessionStorage\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n\n // Clear items from sessionStorage\n this._clearStoredItems();\n }\n\n /**\n * Process connection token\n * @private\n * @param {string} encodedToken - The encoded connection token\n * @returns {boolean} - True if processing was successful\n */\n _processConnectionToken(encodedToken) {\n try {\n // Decode the base64 token\n const jsonStr = atob(encodedToken);\n const connectionData = JSON.parse(jsonStr);\n\n // Extract server and token\n const {server, token} = connectionData;\n\n if (!server || !token) {\n this._updateStatus('disconnected', 'Invalid token');\n return false;\n }\n\n // Store connection info\n this.currentServer = server;\n this.currentToken = token;\n\n // Format channel based on hostname\n this.currentChannel = `/${this._format(window.location.host)}`;\n\n return true;\n } catch (error) {\n this._updateStatus('disconnected', `Unable to parse token`);\n return false;\n }\n }\n\n /**\n * Register with server using connection token\n * @private\n * @param {string} encodedToken - The encoded connection token\n * @returns {Promise<{ token: string }>} - Resolves to true if registration was successful\n */\n _registerWithServer(encodedToken) {\n // Update UI\n this._updateStatus('pending-auth', 'Registering...');\n\n // Connect to the registration endpoint\n const regSocket = new WebSocket(`${this.currentServer}${this.REGISTER_PATH}`);\n\n return new Promise((resolve, reject) => {\n // Connection opened - send the token\n regSocket.addEventListener('open', (event) => {\n console.log('Registration connection established');\n\n // Send the original encoded token back to the server\n const jsonStr = atob(encodedToken);\n const connectionData = JSON.parse(jsonStr);\n connectionData.host = this._format(window.location.host);\n regSocket.send(btoa(JSON.stringify(connectionData)));\n });\n\n // Listen for registration response\n regSocket.addEventListener('message', (event) => {\n try {\n const message = JSON.parse(event.data);\n\n if (message.type === 'registerSuccess' && message.token) {\n console.log(`Registration successful: ${message.message}`);\n\n // Registration complete, can now connect to channel\n resolve({ token: message.token });\n } else if (message.type === 'error') {\n console.error(`Registration failed: ${message.message}`);\n this._updateStatus('disconnected', `Registration failed: ${message.message}`);\n reject(new Error(message.message));\n }\n } catch (error) {\n console.error(`Error parsing registration response: ${error.message}`);\n this._updateStatus('disconnected', 'Error parsing server response');\n reject(error);\n }\n });\n\n // Handle registration errors\n regSocket.addEventListener('error', (event) => {\n console.error('Registration connection error');\n this._updateStatus('disconnected', 'Registration connection error');\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n reject(new Error('Connection error'));\n });\n\n // Handle registration connection close\n regSocket.addEventListener('close', (event) => {\n console.log(`Registration connection closed: ${event.code} ${event.reason}`);\n\n if (event.code !== 1000) {\n // If it wasn't a normal closure, show an error\n this._updateStatus('disconnected', 'Registration failed');\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n reject(new Error('Connection closed'));\n }\n });\n });\n }\n\n /**\n * Set up WebSocket event listeners for direct connection\n * @private\n */\n _setupSocketListeners() {\n if (!this.socket) {\n console.error('Cannot set up socket listeners: WebSocket not available');\n return;\n }\n\n // Set up socket open handler\n this.socket.addEventListener('open', () => {\n this.isConnected = true;\n this._updateStatus('connected', `Connected to ${this.currentChannel}`);\n this._updateConnectionUI(true);\n console.log('WebMCP connection established');\n this._registerItemsWithServer();\n });\n\n // Set up socket close handler\n this.socket.addEventListener('close', (event) => {\n this.isConnected = false;\n this._updateStatus('disconnected', 'Disconnected');\n this._updateConnectionUI(false);\n console.log(`Connection closed: ${event.code} ${event.reason}`);\n\n // Check if it was an authorization error\n if (event.code === 1001 || event.code === 401) {\n this._updateStatus('disconnected', 'Authorization failed');\n this.currentToken = '';\n this.currentServer = '';\n this.currentChannel = '';\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n }\n });\n\n // Set up socket error handler\n this.socket.addEventListener('error', () => {\n console.error('WebSocket error');\n\n if (this.isConnected) {\n this._updateStatus('disconnected', 'Connection error occurred');\n } else {\n this._updateStatus('disconnected', 'Connection failed');\n }\n\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n });\n\n // Set up socket message handler\n this.socket.addEventListener('message', (event) => {\n try {\n const message = JSON.parse(event.data);\n this._handleServerMessage(message);\n } catch (error) {\n console.error(`Error parsing message: ${error.message}`);\n }\n });\n }\n\n /**\n * Handle messages from the server\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleServerMessage(message) {\n switch (message.type) {\n case 'welcome':\n console.log(`Server says: ${message.message}`);\n this._sendMessage({\n type: 'clientInfo',\n userAgent: navigator.userAgent,\n url: window.location.href,\n hostname: window.location.hostname,\n language: navigator.language,\n screenWidth: window.innerWidth,\n screenHeight: window.innerHeight,\n timestamp: Date.now()\n });\n break;\n\n case 'toolRegistered':\n console.log(`Tool registered with server: ${message.name}`);\n break;\n\n case 'promptRegistered':\n console.log(`Prompt registered with server: ${message.name}`);\n break;\n\n case 'resourceRegistered':\n console.log(`Resource registered with server: ${message.name}`);\n break;\n\n case 'callTool':\n // Server is asking us to execute a tool\n this._handleToolCall(message);\n break;\n\n case 'getPrompt':\n // Server is asking us to provide a prompt\n this._handleGetPrompt(message);\n break;\n\n case 'readResource':\n // Server is asking us to provide a resource\n this._handleReadResource(message);\n break;\n\n case 'createSamplingMessage':\n // Server is asking us to create a sampling message\n this._handleCreateSamplingMessage(message);\n break;\n\n case 'listTools':\n // Server is asking for available tools\n this._sendToolsList(message.id);\n break;\n\n case 'listPrompts':\n // Server is asking for available prompts\n this._sendPromptsList(message.id);\n break;\n\n case 'listResources':\n // Server is asking for available resources\n this._sendResourcesList(message.id);\n break;\n\n case 'ping':\n // Respond to ping\n this._sendMessage({\n type: 'pong',\n id: message.id,\n timestamp: Date.now()\n });\n break;\n\n case 'createTool':\n this._handleCreateTool(message);\n break;\n\n case 'removeTool':\n if (message.name && this.availableTools.has(message.name)) {\n this.availableTools.delete(message.name);\n this.registeredTools.delete(message.name);\n this._saveItemsToStorage();\n this._updateToolsList();\n console.log(`Tool removed by server: ${message.name}`);\n }\n break;\n\n case 'removeAllTools':\n this.availableTools.clear();\n this.registeredTools.clear();\n this._saveItemsToStorage();\n this._updateToolsList();\n console.log('All tools removed by server');\n break;\n\n case 'getClientInfo':\n this._sendMessage({\n id: message.id,\n type: 'clientInfoResponse',\n userAgent: navigator.userAgent,\n url: window.location.href,\n hostname: window.location.hostname,\n language: navigator.language,\n screenWidth: window.innerWidth,\n screenHeight: window.innerHeight,\n timestamp: Date.now()\n });\n break;\n\n case 'clipboardCopy':\n if (message.text && navigator.clipboard) {\n navigator.clipboard.writeText(message.text).then(() => {\n console.log('Token copiado al portapapeles');\n }).catch(err => {\n console.error('Error copiando al portapapeles:', err);\n });\n }\n break;\n\n case 'error':\n console.error(`Server error: ${message.message}`);\n break;\n\n default:\n console.warn(`Unknown message type: ${message.type}`);\n }\n }\n\n /**\n * Handle createTool request from server (via built-in agregar-tool)\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleCreateTool(message) {\n const {id, name, description, code, parametros} = message;\n try {\n let props = {};\n if (parametros) props = JSON.parse(parametros);\n const schema = { type: 'object', properties: props };\n const fn = new Function('args', code);\n this.registerTool(name, description, schema, fn);\n this._sendMessage({\n id,\n type: 'toolResponse',\n result: { content: [{ type: 'text', text: `Herramienta \"${name}\" registrada exitosamente` }] }\n });\n console.log(`Tool created by agent: ${name}`);\n } catch (e) {\n this._sendMessage({\n id,\n type: 'toolResponse',\n error: `Error creando herramienta: ${e.message}`\n });\n }\n }\n\n /**\n * Handle tool call from server\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleToolCall(message) {\n const {id, tool, arguments: args} = message;\n\n console.log(`Tool call: ${tool} with args:`, args);\n\n if (!this.availableTools.has(tool)) {\n this._sendMessage({\n id,\n type: 'toolResponse',\n error: `Tool not found: ${tool}`\n });\n return;\n }\n\n // Execute the tool\n try {\n const toolObj = this.availableTools.get(tool);\n\n // Normalize result to MCP content format\n const wrapResult = (raw) => {\n if (raw && raw.content && Array.isArray(raw.content)) return raw;\n const text = typeof raw === 'string' ? raw : JSON.stringify(raw);\n return { content: [{ type: \"text\", text }] };\n };\n\n // Call the tool's execute function\n const result = toolObj.execute(args);\n\n // Handle promises\n if (result instanceof Promise) {\n result\n .then(resolvedResult => {\n this._sendMessage({\n id,\n type: 'toolResponse',\n result: wrapResult(resolvedResult)\n });\n })\n .catch(error => {\n this._sendMessage({\n id,\n type: 'toolResponse',\n error: error.message || 'Tool execution error'\n });\n });\n } else {\n // Send immediate result\n this._sendMessage({\n id,\n type: 'toolResponse',\n result: wrapResult(result)\n });\n }\n\n console.log(`Tool response sent for ${tool}`);\n } catch (error) {\n this._sendMessage({\n id,\n type: 'toolResponse',\n error: error.message || 'Tool execution error'\n });\n console.error(`Tool execution error:`, error);\n }\n }\n\n /**\n * Handle prompt request from server\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleGetPrompt(message) {\n const {id, name, arguments: args} = message;\n\n console.log(`Prompt request: ${name} with args:`, args);\n\n if (!this.availablePrompts.has(name)) {\n this._sendMessage({\n id,\n type: 'promptResponse',\n error: `Prompt not found: ${name}`\n });\n return;\n }\n\n // Execute the prompt\n try {\n const promptObj = this.availablePrompts.get(name);\n\n // Call the prompt's execute function\n const result = promptObj.execute(args);\n\n // Handle promises\n if (result instanceof Promise) {\n result\n .then(resolvedResult => {\n this._sendMessage({\n id,\n type: 'promptResponse',\n result: resolvedResult\n });\n })\n .catch(error => {\n this._sendMessage({\n id,\n type: 'promptResponse',\n error: error.message || 'Prompt execution error'\n });\n });\n } else {\n // Send immediate result\n this._sendMessage({\n id,\n type: 'promptResponse',\n result\n });\n }\n\n console.log(`Prompt response sent for ${name}`);\n } catch (error) {\n this._sendMessage({\n id,\n type: 'promptResponse',\n error: error.message || 'Prompt execution error'\n });\n console.error(`Prompt execution error:`, error);\n }\n }\n\n /**\n * Handle resource request from server\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleReadResource(message) {\n const {id, uri} = message;\n\n console.log(`Resource request: ${uri}`);\n\n // Find resource that handles this URI\n let resourceObj = null;\n\n // First check for direct URI match\n for (const resource of this.availableResources.values()) {\n if (!resource.isTemplate && resource.uri === uri) {\n resourceObj = resource;\n break;\n }\n }\n\n // If no direct match, check for template match\n if (!resourceObj) {\n for (const resource of this.availableResources.values()) {\n if (resource.isTemplate) {\n // Simple check - if URI starts with template prefix (before any parameters)\n const templatePrefix = resource.uriTemplate.split('{')[0];\n if (uri.startsWith(templatePrefix)) {\n resourceObj = resource;\n break;\n }\n }\n }\n }\n\n if (!resourceObj) {\n this._sendMessage({\n id,\n type: 'resourceResponse',\n error: `No resource handler found for URI: ${uri}`\n });\n return;\n }\n\n // Execute the resource provider\n try {\n // Call the resource's provide function\n const result = resourceObj.provide(uri);\n\n // Handle promises\n if (result instanceof Promise) {\n result\n .then(resolvedResult => {\n this._sendMessage({\n id,\n type: 'resourceResponse',\n result: resolvedResult\n });\n })\n .catch(error => {\n this._sendMessage({\n id,\n type: 'resourceResponse',\n error: error.message || 'Resource read error'\n });\n });\n } else {\n // Send immediate result\n this._sendMessage({\n id,\n type: 'resourceResponse',\n result\n });\n }\n\n console.log(`Resource response sent for ${uri}`);\n } catch (error) {\n this._sendMessage({\n id,\n type: 'resourceResponse',\n error: error.message || 'Resource read error'\n });\n console.error(`Resource read error:`, error);\n }\n }\n\n /**\n * Send available tools list\n * @private\n * @param {string} requestId - The request ID to respond to\n */\n _sendToolsList(requestId) {\n const toolsList = Array.from(this.availableTools.values()).map(tool => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n }));\n\n this._sendMessage({\n id: requestId,\n type: 'listToolsResponse',\n tools: toolsList\n });\n\n console.log(`Sent tools list: ${toolsList.length} tools`);\n }\n\n /**\n * Send available prompts list\n * @private\n * @param {string} requestId - The request ID to respond to\n */\n _sendPromptsList(requestId) {\n const promptsList = Array.from(this.availablePrompts.values()).map(prompt => ({\n name: prompt.name,\n description: prompt.description,\n arguments: prompt.arguments,\n }));\n\n this._sendMessage({\n id: requestId,\n type: 'listPromptsResponse',\n prompts: promptsList\n });\n\n console.log(`Sent prompts list: ${promptsList.length} prompts`);\n }\n\n /**\n * Send available resources list\n * @private\n * @param {string} requestId - The request ID to respond to\n */\n _sendResourcesList(requestId) {\n const resources = [];\n const resourceTemplates = [];\n\n // Split resources and templates\n this.availableResources.forEach((resource) => {\n if (resource.isTemplate) {\n resourceTemplates.push({\n name: resource.name,\n description: resource.description,\n uriTemplate: resource.uriTemplate,\n mimeType: resource.mimeType\n });\n } else {\n resources.push({\n name: resource.name,\n description: resource.description,\n uri: resource.uri,\n mimeType: resource.mimeType\n });\n }\n });\n\n this._sendMessage({\n id: requestId,\n type: 'listResourcesResponse',\n resources,\n resourceTemplates\n });\n\n console.log(`Sent resources list: ${resources.length} resources, ${resourceTemplates.length} templates`);\n }\n\n /**\n * Send a message to the server via direct WebSocket\n * @private\n * @param {Object} message - The message object to send\n */\n _sendMessage(message) {\n if (!this.isConnected || !this.socket) {\n console.error('Cannot send message: not connected');\n return;\n }\n\n try {\n // Send the message directly through the WebSocket\n this.socket.send(JSON.stringify(message));\n return Promise.resolve();\n } catch (error) {\n console.error(`Error sending message: ${error.message}`);\n return Promise.reject(error);\n }\n }\n\n /**\n * Register all items with server that were registered while disconnected\n * @private\n */\n _registerItemsWithServer() {\n if (!this.isConnected) return;\n\n // Clear registration tracking sets - we'll re-register everything\n this.registeredTools = new Set();\n this.registeredPrompts = new Set();\n this.registeredResources = new Set();\n\n // Register all tools with the server\n this.availableTools.forEach((tool, name) => {\n this._sendMessage({\n type: 'registerTool',\n name,\n description: tool.description,\n inputSchema: tool.inputSchema\n });\n\n this.registeredTools.add(name);\n console.log(`Registering tool with server: ${name}`);\n });\n\n // Register all prompts with the server\n this.availablePrompts.forEach((prompt, name) => {\n this._sendMessage({\n type: 'registerPrompt',\n name,\n description: prompt.description,\n arguments: prompt.arguments\n });\n\n this.registeredPrompts.add(name);\n console.log(`Registering prompt with server: ${name}`);\n });\n\n // Register all resources with the server\n this.availableResources.forEach((resource, name) => {\n this._sendMessage({\n type: 'registerResource',\n name,\n description: resource.description,\n uri: resource.uri,\n uriTemplate: resource.uriTemplate,\n isTemplate: resource.isTemplate,\n mimeType: resource.mimeType\n });\n\n this.registeredResources.add(name);\n console.log(`Registering resource with server: ${name}`);\n });\n }\n\n /**\n * Register a tool\n * @public\n * @param {string} name - The name of the tool\n * @param {string} description - The description of the tool\n * @param {Object} schema - The schema for the tool's input\n * @param {Function} executeFn - The function to execute when the tool is called\n */\n registerTool(name, description, schema, executeFn) {\n if (!name) {\n console.error('Tool name is required');\n return;\n }\n\n // Add the tool to local registry\n this.availableTools.set(name, {\n name,\n description: description || `Tool: ${name}`,\n execute: executeFn || function (args) {\n return `Default implementation of ${name} with args: ${JSON.stringify(args)}`;\n },\n inputSchema: schema || {\n type: \"object\",\n properties: {}\n }\n });\n\n // Register the tool with the server if connected\n if (this.isConnected) {\n this._sendMessage({\n type: 'registerTool',\n name,\n description: description || `Tool: ${name}`,\n inputSchema: schema || {\n type: \"object\",\n properties: {}\n },\n });\n\n this.registeredTools.add(name);\n }\n\n // Save to session storage\n this._saveItemsToStorage();\n\n // Update tools display\n this._updateToolsList();\n console.log(`Tool registered: ${name}`);\n }\n\n /**\n * Unregister a tool\n * @public\n * @param {string} name - The name of the tool to unregister\n */\n unregisterTool(name) {\n if (!name) {\n console.error('Tool name is required');\n return;\n }\n\n if (!this.availableTools.has(name)) {\n console.warn(`Tool not found: ${name}`);\n return;\n }\n\n this.availableTools.delete(name);\n\n if (this.isConnected) {\n this._sendMessage({\n type: 'unregisterTool',\n name\n });\n }\n\n this.registeredTools.delete(name);\n this._saveItemsToStorage();\n this._updateToolsList();\n console.log(`Tool unregistered: ${name}`);\n }\n\n /**\n * Unregister all tools at once (single notification)\n * @public\n */\n unregisterAllTools() {\n if (this.availableTools.size === 0) return;\n\n this.availableTools.clear();\n this.registeredTools.clear();\n\n if (this.isConnected) {\n this._sendMessage({ type: 'unregisterAllTools' });\n }\n\n this._saveItemsToStorage();\n this._updateToolsList();\n console.log('All tools unregistered');\n }\n\n /**\n * Register a prompt\n * @public\n * @param {string} name - The name of the prompt\n * @param {string} description - The description of the prompt\n * @param {Array} promptArgs - The arguments for the prompt\n * @param {Function} executeFn - The function to execute when the prompt is called\n */\n registerPrompt(name, description, promptArgs, executeFn) {\n if (!name) {\n console.error('Prompt name is required');\n return;\n }\n\n // Add the prompt to local registry\n this.availablePrompts.set(name, {\n name,\n description: description || `Prompt: ${name}`,\n execute: executeFn || function (args) {\n return {\n messages: [{\n role: \"user\",\n content: {\n type: \"text\",\n text: `Default implementation of prompt ${name} with args: ${JSON.stringify(args)}`\n }\n }]\n };\n },\n arguments: promptArgs || []\n });\n\n // Register the prompt with the server if connected\n if (this.isConnected) {\n this._sendMessage({\n type: 'registerPrompt',\n name,\n description: description || `Prompt: ${name}`,\n arguments: promptArgs || []\n });\n\n this.registeredPrompts.add(name);\n }\n\n // Save to session storage\n this._saveItemsToStorage();\n\n // Update prompts display\n this._updatePromptsList();\n console.log(`Prompt registered: ${name}`);\n }\n\n /**\n * Unregister a prompt\n * @public\n * @param {string} name - The name of the prompt to unregister\n */\n unregisterPrompt(name) {\n if (!name) {\n console.error('Prompt name is required');\n return;\n }\n\n if (!this.availablePrompts.has(name)) {\n console.warn(`Prompt not found: ${name}`);\n return;\n }\n\n this.availablePrompts.delete(name);\n\n if (this.isConnected) {\n this._sendMessage({\n type: 'unregisterPrompt',\n name\n });\n }\n\n this.registeredPrompts.delete(name);\n this._saveItemsToStorage();\n this._updatePromptsList();\n console.log(`Prompt unregistered: ${name}`);\n }\n\n /**\n * Register a resource\n * @public\n * @param {string} name - The name of the resource\n * @param {string} description - The description of the resource\n * @param {Object} options - The resource options including uri, uriTemplate, and mimeType\n * @param {Function} provideFn - The function to execute when the resource is requested\n */\n registerResource(name, description, options, provideFn) {\n if (!name) {\n console.error('Resource name is required');\n return;\n }\n\n if (!options.uri && !options.uriTemplate) {\n console.error('Either uri or uriTemplate is required for a resource');\n return;\n }\n\n const isTemplate = !!options.uriTemplate;\n\n // Add the resource to local registry\n this.availableResources.set(name, {\n name,\n description: description || `Resource: ${name}`,\n uri: options.uri,\n uriTemplate: options.uriTemplate,\n isTemplate,\n mimeType: options.mimeType,\n provide: provideFn || function (uri) {\n return {\n contents: [{\n uri: uri,\n text: `Default implementation of resource ${name} for URI: ${uri}`,\n mimeType: options.mimeType || \"text/plain\"\n }]\n };\n }\n });\n\n // Register the resource with the server if connected\n if (this.isConnected) {\n this._sendMessage({\n type: 'registerResource',\n name,\n description: description || `Resource: ${name}`,\n uri: options.uri,\n uriTemplate: options.uriTemplate,\n isTemplate,\n mimeType: options.mimeType\n });\n\n this.registeredResources.add(name);\n }\n\n // Save to session storage\n this._saveItemsToStorage();\n\n // Update resources display\n this._updateResourcesList();\n console.log(`Resource registered: ${name}`);\n }\n\n /**\n * Unregister a resource\n * @public\n * @param {string} name - The name of the resource to unregister\n */\n unregisterResource(name) {\n if (!name) {\n console.error('Resource name is required');\n return;\n }\n\n if (!this.availableResources.has(name)) {\n console.warn(`Resource not found: ${name}`);\n return;\n }\n\n this.availableResources.delete(name);\n\n if (this.isConnected) {\n this._sendMessage({\n type: 'unregisterResource',\n name\n });\n }\n\n this.registeredResources.delete(name);\n this._saveItemsToStorage();\n this._updateResourcesList();\n console.log(`Resource unregistered: ${name}`);\n }\n\n /**\n * Handle sampling message creation request\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleCreateSamplingMessage(message) {\n const {\n id,\n messages,\n systemPrompt,\n includeContext,\n temperature,\n maxTokens,\n stopSequences,\n metadata,\n modelPreferences\n } = message;\n\n console.log(`Sampling request received with ${messages?.length || 0} messages`);\n\n // Create a modal dialog to show the sampling request\n const modal = document.createElement('div');\n Object.assign(modal.style, {\n position: 'fixed',\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n backgroundColor: 'rgba(0, 0, 0, 0.5)',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: '10000'\n });\n\n // Create modal content\n const modalContent = document.createElement('div');\n Object.assign(modalContent.style, {\n backgroundColor: 'white',\n padding: '20px',\n borderRadius: '5px',\n maxWidth: '500px',\n width: '90%',\n maxHeight: '80%',\n overflow: 'auto'\n });\n\n // Create header\n const header = document.createElement('h3');\n header.textContent = 'Sampling Request';\n Object.assign(header.style, {\n margin: '0 0 15px 0',\n padding: '0 0 10px 0',\n borderBottom: '1px solid #ddd'\n });\n\n // Create content area to show messages\n const content = document.createElement('div');\n Object.assign(content.style, {\n marginBottom: '15px',\n maxHeight: '300px',\n overflow: 'auto',\n border: '1px solid #ddd',\n padding: '10px',\n backgroundColor: '#f9f9f9'\n });\n\n // Display messages\n if (messages && messages.length > 0) {\n messages.forEach(msg => {\n const msgDiv = document.createElement('div');\n Object.assign(msgDiv.style, {\n marginBottom: '10px',\n padding: '5px',\n borderRadius: '3px',\n backgroundColor: msg.role === 'user' ? '#e1f5fe' : '#f1f8e9'\n });\n\n const roleSpan = document.createElement('strong');\n roleSpan.textContent = msg.role === 'user' ? 'User: ' : 'Assistant: ';\n\n const contentSpan = document.createElement('span');\n if (msg.content.type === 'text') {\n contentSpan.textContent = msg.content.text;\n } else if (msg.content.type === 'image') {\n contentSpan.textContent = '[Image data]';\n }\n\n msgDiv.appendChild(roleSpan);\n msgDiv.appendChild(contentSpan);\n content.appendChild(msgDiv);\n });\n } else {\n content.textContent = 'No messages provided in sampling request';\n }\n\n // System prompt if available\n if (systemPrompt) {\n const sysPromptDiv = document.createElement('div');\n Object.assign(sysPromptDiv.style, {\n marginBottom: '10px',\n padding: '5px',\n backgroundColor: '#fff8e1'\n });\n\n const sysPromptLabel = document.createElement('strong');\n sysPromptLabel.textContent = 'System Prompt: ';\n\n const sysPromptContent = document.createElement('span');\n sysPromptContent.textContent = systemPrompt;\n\n sysPromptDiv.appendChild(sysPromptLabel);\n sysPromptDiv.appendChild(sysPromptContent);\n content.appendChild(sysPromptDiv);\n }\n\n // Create response input\n const responseLabel = document.createElement('label');\n responseLabel.textContent = 'Assistant Response:';\n Object.assign(responseLabel.style, {\n display: 'block',\n marginBottom: '5px',\n fontWeight: 'bold'\n });\n\n const responseInput = document.createElement('textarea');\n Object.assign(responseInput.style, {\n width: '100%',\n minHeight: '100px',\n padding: '10px',\n marginBottom: '15px',\n boxSizing: 'border-box'\n });\n\n // Create buttons\n const buttonContainer = document.createElement('div');\n Object.assign(buttonContainer.style, {\n display: 'flex',\n justifyContent: 'space-between'\n });\n\n const submitButton = document.createElement('button');\n submitButton.textContent = 'Submit Response';\n Object.assign(submitButton.style, {\n padding: '8px 15px',\n backgroundColor: '#4CAF50',\n color: 'white',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer'\n });\n\n const cancelButton = document.createElement('button');\n cancelButton.textContent = 'Cancel';\n Object.assign(cancelButton.style, {\n padding: '8px 15px',\n backgroundColor: '#f44336',\n color: 'white',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer'\n });\n\n // Add elements to modal\n buttonContainer.appendChild(cancelButton);\n buttonContainer.appendChild(submitButton);\n\n modalContent.appendChild(header);\n modalContent.appendChild(content);\n modalContent.appendChild(responseLabel);\n modalContent.appendChild(responseInput);\n modalContent.appendChild(buttonContainer);\n\n modal.appendChild(modalContent);\n document.body.appendChild(modal);\n\n // Focus the response input\n responseInput.focus();\n\n // Setup button handlers\n submitButton.addEventListener('click', () => {\n const responseText = responseInput.value.trim();\n if (responseText) {\n // Send response back to server\n this._sendMessage({\n id,\n type: 'samplingResponse',\n result: {\n model: 'web-user-input',\n role: 'assistant',\n content: {\n type: 'text',\n text: responseText\n }\n }\n });\n\n // Remove modal\n document.body.removeChild(modal);\n } else {\n alert('Please enter a response');\n }\n });\n\n cancelButton.addEventListener('click', () => {\n // Send error response\n this._sendMessage({\n id,\n type: 'samplingResponse',\n error: 'User cancelled sampling request'\n });\n\n // Remove modal\n document.body.removeChild(modal);\n });\n }\n}\n\n// Export for module usage\nif (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {\n module.exports = WebMCP;\n}\n"], - "mappings": "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", + "sourcesContent": ["/**\n * WebMCP - Snippet to add MCP functionality to any website\n *\n * Shows as a small blue square in bottom right corner\n * On click, expands to allow connection with token\n * Auto-disconnects after 5 minutes of inactivity\n */\n\nclass WebMCP {\n constructor(options = {}) {\n // Options with defaults\n this.options = {\n color: '#007bff',\n position: 'bottom-right',\n size: '30px',\n padding: '20px',\n inactivityTimeout: 5 * 60 * 1000, // 5 minutes in milliseconds\n ...options\n };\n\n // State variables\n this.isConnected = false;\n this.isExpanded = false;\n this.socket = null;\n this.inactivityTimer = null;\n this.availableTools = new Map();\n this.availablePrompts = new Map();\n this.availableResources = new Map();\n this.samplingCallbacks = new Map(); // For storing sampling callbacks\n this.currentToken = '';\n this.currentServer = '';\n this.currentChannel = '';\n this.elementId = 'webmcp-widget-' + Math.random().toString(36).substr(2, 9);\n this.registeredTools = new Set();\n this.registeredPrompts = new Set();\n this.registeredResources = new Set();\n this._reconnectAttempts = 0;\n this._maxReconnectAttempts = 3;\n this._reconnectDelay = 1000;\n this._lastConnectionToken = null;\n\n // Storage keys for sessionStorage\n this.SESSION_STORAGE_KEY = 'webmcp_token';\n this.TOOLS_STORAGE_KEY = 'webmcp_tools';\n this.PROMPTS_STORAGE_KEY = 'webmcp_prompts';\n this.RESOURCES_STORAGE_KEY = 'webmcp_resources';\n\n // Constants\n this.REGISTER_PATH = '/register';\n\n // Initialize\n this._init();\n }\n\n _format(s) {\n return s.replace(/[.:]/g, '_');\n }\n\n /**\n * Initialize the WebMCP widget\n * @private\n */\n _init() {\n // Check if already initialized on this page\n if (document.querySelector('[data-webmcp-widget]')) {\n console.warn('WebMCP widget already initialized on this page');\n return;\n }\n\n // Create and inject the widget\n this._createWidget();\n\n // Set up event listeners\n this._setupEventListeners();\n\n // Start inactivity timer\n this._resetInactivityTimer();\n\n // Check for stored token and connect if available\n this._checkStoredToken();\n }\n\n /**\n * Check for stored connection info in sessionStorage and connect if found\n * @private\n */\n _checkStoredToken() {\n const storedConnectionInfo = sessionStorage.getItem(this.SESSION_STORAGE_KEY);\n\n if (storedConnectionInfo) {\n try {\n const connectionInfo = JSON.parse(storedConnectionInfo);\n if (connectionInfo.token) {\n console.log('Found stored connection info, attempting to connect');\n\n // Set the connection properties directly\n this.currentServer = connectionInfo.server;\n this.currentChannel = `/${connectionInfo.channelHost || this._format(window.location.host)}`;\n\n // Set the current token from connection info\n if (connectionInfo.token.includes('{')) {\n // It's already parsed JSON\n const tokenData = JSON.parse(connectionInfo.token);\n this.currentToken = tokenData.token;\n } else {\n // It's a base64 encoded string\n try {\n const jsonStr = atob(connectionInfo.token);\n const tokenData = JSON.parse(jsonStr);\n this.currentToken = tokenData.token;\n } catch (e) {\n this.currentToken = connectionInfo.token;\n }\n }\n\n // Load stored items before connecting\n this._loadStoredItems();\n\n // Connect using the stored token\n this.connect(connectionInfo.token);\n }\n } catch (error) {\n console.error('Error parsing stored connection info:', error);\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n this._clearStoredItems();\n }\n }\n }\n\n /**\n * Save tools, prompts, and resources to session storage\n * @private\n */\n _saveItemsToStorage() {\n try {\n // Save tools\n const toolsData = {};\n this.availableTools.forEach((tool, name) => {\n toolsData[name] = {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n // We don't store the execution function as it can't be serialized\n };\n });\n sessionStorage.setItem(this.TOOLS_STORAGE_KEY, JSON.stringify(toolsData));\n\n // Save prompts\n const promptsData = {};\n this.availablePrompts.forEach((prompt, name) => {\n promptsData[name] = {\n name: prompt.name,\n description: prompt.description,\n arguments: prompt.arguments,\n // We don't store the execution function as it can't be serialized\n };\n });\n sessionStorage.setItem(this.PROMPTS_STORAGE_KEY, JSON.stringify(promptsData));\n\n // Save resources\n const resourcesData = {};\n this.availableResources.forEach((resource, name) => {\n resourcesData[name] = {\n name: resource.name,\n description: resource.description,\n uri: resource.uri,\n uriTemplate: resource.uriTemplate,\n isTemplate: resource.isTemplate,\n mimeType: resource.mimeType,\n // We don't store the provide function as it can't be serialized\n };\n });\n sessionStorage.setItem(this.RESOURCES_STORAGE_KEY, JSON.stringify(resourcesData));\n\n console.log('Saved items to session storage:', {\n tools: Object.keys(toolsData).length,\n prompts: Object.keys(promptsData).length,\n resources: Object.keys(resourcesData).length\n });\n } catch (error) {\n console.error('Error saving items to session storage:', error);\n }\n }\n\n /**\n * Load tools, prompts, and resources from session storage\n * @private\n */\n _loadStoredItems() {\n try {\n // Load tools\n const storedTools = sessionStorage.getItem(this.TOOLS_STORAGE_KEY);\n if (storedTools) {\n const toolsData = JSON.parse(storedTools);\n Object.entries(toolsData).forEach(([name, tool]) => {\n // Add to the available tools with placeholder execute function\n this.availableTools.set(name, {\n ...tool,\n execute: function (args) {\n console.warn(`Tool ${name} was loaded from storage but has not been re-registered with an execution function`);\n return `Tool ${name} needs to be re-registered`;\n }\n });\n });\n }\n\n // Load prompts\n const storedPrompts = sessionStorage.getItem(this.PROMPTS_STORAGE_KEY);\n if (storedPrompts) {\n const promptsData = JSON.parse(storedPrompts);\n Object.entries(promptsData).forEach(([name, prompt]) => {\n // Add to the available prompts with placeholder execute function\n this.availablePrompts.set(name, {\n ...prompt,\n execute: function (args) {\n console.warn(`Prompt ${name} was loaded from storage but has not been re-registered with an execution function`);\n return {\n messages: [{\n role: \"user\",\n content: {\n type: \"text\",\n text: `Prompt ${name} needs to be re-registered`\n }\n }]\n };\n }\n });\n });\n }\n\n // Load resources\n const storedResources = sessionStorage.getItem(this.RESOURCES_STORAGE_KEY);\n if (storedResources) {\n const resourcesData = JSON.parse(storedResources);\n Object.entries(resourcesData).forEach(([name, resource]) => {\n // Add to the available resources with placeholder provide function\n this.availableResources.set(name, {\n ...resource,\n provide: function (uri) {\n console.warn(`Resource ${name} was loaded from storage but has not been re-registered with a provider function`);\n return {\n contents: [{\n uri: uri,\n text: `Resource ${name} needs to be re-registered`,\n mimeType: resource.mimeType || \"text/plain\"\n }]\n };\n }\n });\n });\n }\n\n console.log('Loaded items from session storage:', {\n tools: this.availableTools.size,\n prompts: this.availablePrompts.size,\n resources: this.availableResources.size\n });\n\n // Update the UI\n this._updateToolsList();\n this._updatePromptsList();\n this._updateResourcesList();\n\n } catch (error) {\n console.error('Error loading items from session storage:', error);\n this._clearStoredItems();\n }\n }\n\n /**\n * Clear all stored items from session storage\n * @private\n */\n _clearStoredItems() {\n sessionStorage.removeItem(this.TOOLS_STORAGE_KEY);\n sessionStorage.removeItem(this.PROMPTS_STORAGE_KEY);\n sessionStorage.removeItem(this.RESOURCES_STORAGE_KEY);\n console.log('Cleared stored items from session storage');\n }\n\n /**\n * Create and inject the WebMCP widget into the DOM\n * @private\n */\n _createWidget() {\n // Create main container\n const container = document.createElement('div');\n container.id = this.elementId;\n container.dataset.webmcpWidget = true;\n\n // Apply styles\n Object.assign(container.style, {\n position: 'fixed',\n zIndex: '9999',\n display: 'flex',\n flexDirection: 'column',\n fontFamily: 'Arial, sans-serif',\n fontSize: '14px',\n transition: 'all 0.3s ease'\n });\n\n // Set position based on option\n this._setWidgetPosition(container);\n\n // Create trigger button (blue square)\n const triggerButton = document.createElement('div');\n triggerButton.className = 'webmcp-trigger';\n Object.assign(triggerButton.style, {\n width: this.options.size,\n height: this.options.size,\n backgroundColor: this.options.color,\n borderRadius: '4px',\n cursor: 'pointer',\n boxShadow: '0 2px 10px rgba(0,0,0,0.2)',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n alignSelf: 'flex-end'\n });\n\n // Create content panel (initially hidden) - positioned above the trigger\n const contentPanel = document.createElement('div');\n contentPanel.className = 'webmcp-content';\n Object.assign(contentPanel.style, {\n backgroundColor: '#ffffff',\n border: '1px solid #e1e1e1',\n borderRadius: '5px',\n padding: '15px',\n marginBottom: '10px',\n boxShadow: '0 5px 15px rgba(0,0,0,0.1)',\n width: '250px',\n display: 'none',\n overflow: 'hidden',\n position: 'absolute',\n bottom: '40px'\n });\n\n // Add header with title and close button\n const header = document.createElement('div');\n Object.assign(header.style, {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n marginBottom: '15px'\n });\n\n const title = document.createElement('div');\n title.textContent = 'WebMCP';\n Object.assign(title.style, {\n fontWeight: 'bold',\n fontSize: '16px'\n });\n\n const closeButton = document.createElement('button');\n closeButton.innerHTML = '×'; // \u00D7 symbol\n closeButton.className = 'webmcp-close';\n Object.assign(closeButton.style, {\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n fontSize: '20px',\n padding: '0',\n lineHeight: '1',\n color: '#999'\n });\n\n header.appendChild(title);\n header.appendChild(closeButton);\n contentPanel.appendChild(header);\n\n // Add connection form\n this._createConnectionForm(contentPanel);\n\n // Add status indicator\n const statusIndicator = document.createElement('div');\n statusIndicator.className = 'webmcp-status';\n statusIndicator.textContent = 'Disconnected';\n Object.assign(statusIndicator.style, {\n padding: '8px',\n borderRadius: '3px',\n backgroundColor: '#f8d7da',\n color: '#721c24',\n textAlign: 'center',\n marginBottom: '10px',\n fontSize: '12px'\n });\n contentPanel.appendChild(statusIndicator);\n\n // Add connection panel\n const connectionPanel = document.createElement('div');\n connectionPanel.className = 'webmcp-connection-panel';\n contentPanel.appendChild(connectionPanel);\n\n // Create a single container for all registered items\n const registeredItemsContainer = document.createElement('div');\n registeredItemsContainer.className = 'webmcp-registered-items';\n Object.assign(registeredItemsContainer.style, {\n marginTop: '15px',\n fontSize: '12px',\n display: 'none',\n maxHeight: '200px',\n overflow: 'auto',\n border: '1px solid #eee',\n borderRadius: '4px'\n });\n contentPanel.appendChild(registeredItemsContainer);\n\n // Add features lists (initially empty)\n // Tools list\n const toolsList = document.createElement('div');\n toolsList.className = 'webmcp-tools-list';\n Object.assign(toolsList.style, {\n padding: '10px',\n borderBottom: '1px solid #eee'\n });\n\n const toolsHeader = document.createElement('div');\n toolsHeader.textContent = 'Registered Tools:';\n Object.assign(toolsHeader.style, {\n fontWeight: 'bold',\n marginBottom: '5px'\n });\n\n const toolsContainer = document.createElement('ul');\n toolsContainer.className = 'webmcp-tools-container';\n Object.assign(toolsContainer.style, {\n listStyle: 'none',\n padding: '0',\n margin: '0'\n });\n\n toolsList.appendChild(toolsHeader);\n toolsList.appendChild(toolsContainer);\n registeredItemsContainer.appendChild(toolsList);\n\n // Prompts list\n const promptsList = document.createElement('div');\n promptsList.className = 'webmcp-prompts-list';\n Object.assign(promptsList.style, {\n padding: '10px',\n borderBottom: '1px solid #eee'\n });\n\n const promptsHeader = document.createElement('div');\n promptsHeader.textContent = 'Registered Prompts:';\n Object.assign(promptsHeader.style, {\n fontWeight: 'bold',\n marginBottom: '5px'\n });\n\n const promptsContainer = document.createElement('ul');\n promptsContainer.className = 'webmcp-prompts-container';\n Object.assign(promptsContainer.style, {\n listStyle: 'none',\n padding: '0',\n margin: '0'\n });\n\n promptsList.appendChild(promptsHeader);\n promptsList.appendChild(promptsContainer);\n registeredItemsContainer.appendChild(promptsList);\n\n // Resources list\n const resourcesList = document.createElement('div');\n resourcesList.className = 'webmcp-resources-list';\n Object.assign(resourcesList.style, {\n padding: '10px'\n });\n\n const resourcesHeader = document.createElement('div');\n resourcesHeader.textContent = 'Registered Resources:';\n Object.assign(resourcesHeader.style, {\n fontWeight: 'bold',\n marginBottom: '5px'\n });\n\n const resourcesContainer = document.createElement('ul');\n resourcesContainer.className = 'webmcp-resources-container';\n Object.assign(resourcesContainer.style, {\n listStyle: 'none',\n padding: '0',\n margin: '0'\n });\n\n resourcesList.appendChild(resourcesHeader);\n resourcesList.appendChild(resourcesContainer);\n registeredItemsContainer.appendChild(resourcesList);\n\n // Add to main container and then to document - content panel first so it appears above trigger\n container.appendChild(contentPanel);\n container.appendChild(triggerButton);\n document.body.appendChild(container);\n }\n\n /**\n * Set widget position based on option\n * @private\n */\n _setWidgetPosition(container) {\n const {position, padding} = this.options;\n\n switch (position) {\n case 'bottom-right':\n Object.assign(container.style, {\n bottom: padding,\n right: padding,\n alignItems: 'flex-end'\n });\n break;\n case 'bottom-left':\n Object.assign(container.style, {\n bottom: padding,\n left: padding,\n alignItems: 'flex-start'\n });\n break;\n case 'top-right':\n Object.assign(container.style, {\n top: padding,\n right: padding,\n alignItems: 'flex-end'\n });\n break;\n case 'top-left':\n Object.assign(container.style, {\n top: padding,\n left: padding,\n alignItems: 'flex-start'\n });\n break;\n default:\n // Default to bottom-right\n Object.assign(container.style, {\n bottom: padding,\n right: padding,\n alignItems: 'flex-end'\n });\n }\n }\n\n /**\n * Create the connection form\n * @private\n */\n _createConnectionForm(container) {\n const form = document.createElement('div');\n Object.assign(form.style, {\n marginBottom: '8px',\n });\n\n // Token input field\n const inputGroup = document.createElement('div');\n Object.assign(inputGroup.style, {\n display: 'flex',\n marginBottom: '8px',\n });\n\n const tokenInput = document.createElement('input');\n tokenInput.type = 'text';\n tokenInput.className = 'webmcp-token-input';\n tokenInput.placeholder = 'Paste connection token';\n Object.assign(tokenInput.style, {\n flex: '1',\n padding: '8px',\n border: '1px solid #ccc',\n borderRadius: '4px 0 0 4px',\n fontSize: '12px'\n });\n\n const connectButton = document.createElement('button');\n connectButton.className = 'webmcp-connect-btn';\n connectButton.textContent = 'Connect';\n Object.assign(connectButton.style, {\n padding: '8px 12px',\n backgroundColor: this.options.color,\n color: 'white',\n border: 'none',\n borderRadius: '0 4px 4px 0',\n cursor: 'pointer',\n fontSize: '12px'\n });\n\n inputGroup.appendChild(tokenInput);\n inputGroup.appendChild(connectButton);\n\n const disconnectButton = document.createElement('button');\n disconnectButton.className = 'webmcp-disconnect-btn';\n disconnectButton.textContent = 'Disconnect';\n Object.assign(disconnectButton.style, {\n padding: '8px 12px',\n backgroundColor: '#dc3545',\n color: 'white',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '12px',\n width: '100%',\n display: 'none'\n });\n\n form.appendChild(inputGroup);\n form.appendChild(disconnectButton);\n container.appendChild(form);\n }\n\n /**\n * Set up event listeners for the widget\n * @private\n */\n _setupEventListeners() {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n // Trigger button click - expand/collapse\n const trigger = container.querySelector('.webmcp-trigger');\n trigger.addEventListener('click', () => {\n this._toggleExpanded();\n });\n\n // Close button click - collapse\n const closeBtn = container.querySelector('.webmcp-close');\n closeBtn.addEventListener('click', () => {\n this._toggleExpanded(false);\n });\n\n // Connect button click\n const connectBtn = container.querySelector('.webmcp-connect-btn');\n connectBtn.addEventListener('click', () => {\n const tokenInput = container.querySelector('.webmcp-token-input');\n this.connect(tokenInput.value);\n });\n\n // Disconnect button click\n const disconnectBtn = container.querySelector('.webmcp-disconnect-btn');\n disconnectBtn.addEventListener('click', () => {\n this.disconnect();\n });\n\n // User activity detection to reset inactivity timer\n document.addEventListener('mousemove', () => this._resetInactivityTimer());\n document.addEventListener('keypress', () => this._resetInactivityTimer());\n document.addEventListener('click', () => this._resetInactivityTimer());\n document.addEventListener('scroll', () => this._resetInactivityTimer());\n }\n\n /**\n * Toggle the expanded state of the widget\n * @private\n */\n _toggleExpanded(force = null) {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const contentPanel = container.querySelector('.webmcp-content');\n this.isExpanded = force !== null ? force : !this.isExpanded;\n\n if (this.isExpanded) {\n contentPanel.style.display = 'block';\n } else {\n contentPanel.style.display = 'none';\n }\n\n this._resetInactivityTimer();\n }\n\n /**\n * Update the status indicator\n * @private\n */\n _updateStatus(status, message) {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const statusIndicator = container.querySelector('.webmcp-status');\n if (!statusIndicator) return;\n\n // Clear existing classes\n statusIndicator.classList.remove('connected', 'disconnected', 'connecting', 'pending-auth');\n\n // Set new status\n statusIndicator.textContent = message || status;\n\n // Apply styling based on status\n switch (status) {\n case 'connected':\n Object.assign(statusIndicator.style, {\n backgroundColor: '#d4edda',\n color: '#155724'\n });\n break;\n case 'disconnected':\n Object.assign(statusIndicator.style, {\n backgroundColor: '#f8d7da',\n color: '#721c24'\n });\n break;\n case 'connecting':\n Object.assign(statusIndicator.style, {\n backgroundColor: '#fff3cd',\n color: '#856404'\n });\n break;\n case 'pending-auth':\n Object.assign(statusIndicator.style, {\n backgroundColor: '#d1ecf1',\n color: '#0c5460'\n });\n break;\n }\n }\n\n /**\n * Update UI based on connection state\n * @private\n */\n _updateConnectionUI(isConnected) {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const tokenInput = container.querySelector('.webmcp-token-input');\n const connectBtn = container.querySelector('.webmcp-connect-btn');\n const disconnectBtn = container.querySelector('.webmcp-disconnect-btn');\n const registeredItemsContainer = container.querySelector('.webmcp-registered-items');\n\n if (isConnected) {\n tokenInput.style.display = 'none';\n connectBtn.style.display = 'none';\n disconnectBtn.style.display = 'block';\n registeredItemsContainer.style.display = 'block';\n\n // Update the trigger button to show connected state\n const trigger = container.querySelector('.webmcp-trigger');\n trigger.innerHTML = '\u2713';\n trigger.style.color = 'white';\n trigger.style.fontWeight = 'bold';\n } else {\n tokenInput.style.display = 'block';\n connectBtn.style.display = 'block';\n disconnectBtn.style.display = 'none';\n registeredItemsContainer.style.display = 'none';\n\n // Reset the trigger button\n const trigger = container.querySelector('.webmcp-trigger');\n trigger.innerHTML = '';\n }\n }\n\n /**\n * Update tools list in UI\n * @private\n */\n _updateToolsList() {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const toolsContainer = container.querySelector('.webmcp-tools-container');\n if (!toolsContainer) return;\n\n // Clear current list\n toolsContainer.innerHTML = '';\n\n if (this.availableTools.size === 0) {\n const emptyMessage = document.createElement('li');\n emptyMessage.textContent = 'No tools registered';\n emptyMessage.style.fontStyle = 'italic';\n emptyMessage.style.color = '#666';\n toolsContainer.appendChild(emptyMessage);\n return;\n }\n\n // Add each tool to the list\n this.availableTools.forEach((tool, name) => {\n const toolItem = document.createElement('li');\n Object.assign(toolItem.style, {\n padding: '5px 0',\n borderBottom: '1px solid #eee'\n });\n\n const toolName = document.createElement('strong');\n toolName.textContent = name;\n\n const toolDesc = document.createElement('div');\n toolDesc.textContent = tool.description;\n toolDesc.style.fontSize = '10px';\n toolDesc.style.color = '#666';\n\n toolItem.appendChild(toolName);\n toolItem.appendChild(toolDesc);\n toolsContainer.appendChild(toolItem);\n });\n }\n\n /**\n * Update prompts list in UI\n * @private\n */\n _updatePromptsList() {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const promptsContainer = container.querySelector('.webmcp-prompts-container');\n if (!promptsContainer) return;\n\n // Clear current list\n promptsContainer.innerHTML = '';\n\n if (this.availablePrompts.size === 0) {\n const emptyMessage = document.createElement('li');\n emptyMessage.textContent = 'No prompts registered';\n emptyMessage.style.fontStyle = 'italic';\n emptyMessage.style.color = '#666';\n promptsContainer.appendChild(emptyMessage);\n return;\n }\n\n // Add each prompt to the list\n this.availablePrompts.forEach((prompt, name) => {\n const promptItem = document.createElement('li');\n Object.assign(promptItem.style, {\n padding: '5px 0',\n borderBottom: '1px solid #eee'\n });\n\n const promptName = document.createElement('strong');\n promptName.textContent = name;\n\n const promptDesc = document.createElement('div');\n promptDesc.textContent = prompt.description;\n promptDesc.style.fontSize = '10px';\n promptDesc.style.color = '#666';\n\n promptItem.appendChild(promptName);\n promptItem.appendChild(promptDesc);\n promptsContainer.appendChild(promptItem);\n });\n }\n\n /**\n * Update resources list in UI\n * @private\n */\n _updateResourcesList() {\n const container = document.getElementById(this.elementId);\n if (!container) return;\n\n const resourcesContainer = container.querySelector('.webmcp-resources-container');\n if (!resourcesContainer) return;\n\n // Clear current list\n resourcesContainer.innerHTML = '';\n\n if (this.availableResources.size === 0) {\n const emptyMessage = document.createElement('li');\n emptyMessage.textContent = 'No resources registered';\n emptyMessage.style.fontStyle = 'italic';\n emptyMessage.style.color = '#666';\n resourcesContainer.appendChild(emptyMessage);\n return;\n }\n\n // Add each resource to the list\n this.availableResources.forEach((resource, name) => {\n const resourceItem = document.createElement('li');\n Object.assign(resourceItem.style, {\n padding: '5px 0',\n borderBottom: '1px solid #eee'\n });\n\n const resourceName = document.createElement('strong');\n resourceName.textContent = name;\n\n const resourceDesc = document.createElement('div');\n resourceDesc.textContent = resource.description +\n (resource.isTemplate ? ' (Template)' : '');\n resourceDesc.style.fontSize = '10px';\n resourceDesc.style.color = '#666';\n\n resourceItem.appendChild(resourceName);\n resourceItem.appendChild(resourceDesc);\n resourcesContainer.appendChild(resourceItem);\n });\n }\n\n /**\n * Reset the inactivity timer\n * @private\n */\n _resetInactivityTimer() {\n // Clear existing timer\n if (this.inactivityTimer) {\n clearTimeout(this.inactivityTimer);\n }\n\n // Set new timer\n this.inactivityTimer = setTimeout(() => {\n this._handleInactivity();\n }, this.options.inactivityTimeout);\n }\n\n /**\n * Handle user inactivity\n * @private\n */\n _handleInactivity() {\n console.log('Inactivity timeout reached, disconnecting');\n\n // Disconnect if connected\n if (this.isConnected) {\n this.disconnect();\n }\n\n // Minimize UI\n this._toggleExpanded(false);\n\n // Clear the stored token\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n }\n\n\n /**\n * Connect to the WebSocket server\n * @public\n * @param {string} connectionToken - The encoded connection token\n */\n async connect(connectionToken) {\n if (!connectionToken) {\n this._updateStatus('disconnected', 'Error: No token provided');\n return;\n }\n\n // Store for reconnection attempts\n this._lastConnectionToken = connectionToken;\n\n // Update UI to show connecting state\n this._updateStatus('connecting', 'Connecting...');\n\n try {\n // Process the connection token\n if (!this._processConnectionToken(connectionToken)) {\n return;\n }\n\n // Store the connection info in sessionStorage for page navigations\n const connectionInfo = {\n token: connectionToken,\n server: this.currentServer,\n host: this._format(window.location.host)\n };\n\n // Check if we have connection data already in sessionStorage\n const storedConnectionInfo = sessionStorage.getItem(this.SESSION_STORAGE_KEY);\n let skipRegistration = false;\n\n if (storedConnectionInfo) {\n try {\n const connectionInfo = JSON.parse(storedConnectionInfo);\n // If we already have a valid token and server, we can skip registration\n if (connectionInfo.server === this.currentServer &&\n connectionInfo.host === this._format(window.location.host)) {\n skipRegistration = true;\n }\n } catch (error) {\n console.error('Error parsing stored connection info:', error);\n }\n }\n\n if (!skipRegistration) {\n // First register with server\n const response = await this._registerWithServer(connectionToken);\n\n if (!response.token) {\n this._updateStatus('disconnected', 'Registration failed');\n return;\n }\n\n // Save the new token\n connectionInfo.token = response.token;\n this.currentToken = response.token;\n\n sessionStorage.setItem(this.SESSION_STORAGE_KEY, JSON.stringify(connectionInfo));\n }\n\n // Now connect to the actual channel\n const serverUrl = `${this.currentServer}${this.currentChannel}?token=${this.currentToken}`;\n\n // Update UI\n this._updateStatus('connecting', 'Connecting to channel...');\n\n // Create WebSocket connection with the path and token\n this.socket = new WebSocket(serverUrl);\n\n // Set up socket event listeners\n this._setupSocketListeners();\n\n // Reset inactivity timer\n this._resetInactivityTimer();\n\n } catch (error) {\n console.error('Connection error:', error);\n this._updateStatus('disconnected', `Error: ${error.message}`);\n }\n }\n\n /**\n * Disconnect from WebSocket server\n * @public\n */\n disconnect() {\n // Close the WebSocket connection if it exists\n if (this.socket) {\n this.socket.close();\n this.socket = null;\n }\n\n this.isConnected = false;\n this._updateStatus('disconnected', 'Disconnected');\n this._updateConnectionUI(false);\n\n // Reset state\n this.currentToken = '';\n this.currentServer = '';\n this.currentChannel = '';\n\n // Remove the token from sessionStorage\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n\n // Clear items from sessionStorage\n this._clearStoredItems();\n }\n\n /**\n * Process connection token\n * @private\n * @param {string} encodedToken - The encoded connection token\n * @returns {boolean} - True if processing was successful\n */\n _processConnectionToken(encodedToken) {\n try {\n // Decode the base64 token\n const jsonStr = atob(encodedToken);\n const connectionData = JSON.parse(jsonStr);\n\n // Extract server and token\n const {server, token} = connectionData;\n\n if (!server || !token) {\n this._updateStatus('disconnected', 'Invalid token');\n return false;\n }\n\n // Store connection info\n this.currentServer = server;\n this.currentToken = token;\n\n // Format channel based on hostname\n this.currentChannel = `/${this._format(window.location.host)}`;\n\n return true;\n } catch (error) {\n this._updateStatus('disconnected', `Unable to parse token`);\n return false;\n }\n }\n\n /**\n * Register with server using connection token\n * @private\n * @param {string} encodedToken - The encoded connection token\n * @returns {Promise<{ token: string }>} - Resolves to true if registration was successful\n */\n _registerWithServer(encodedToken) {\n // Update UI\n this._updateStatus('pending-auth', 'Registering...');\n\n // Connect to the registration endpoint\n const regSocket = new WebSocket(`${this.currentServer}${this.REGISTER_PATH}`);\n\n return new Promise((resolve, reject) => {\n // Connection opened - send the token\n regSocket.addEventListener('open', (event) => {\n console.log('Registration connection established');\n\n // Send the original encoded token back to the server\n const jsonStr = atob(encodedToken);\n const connectionData = JSON.parse(jsonStr);\n connectionData.host = this._format(window.location.host);\n regSocket.send(btoa(JSON.stringify(connectionData)));\n });\n\n // Listen for registration response\n regSocket.addEventListener('message', (event) => {\n try {\n const message = JSON.parse(event.data);\n\n if (message.type === 'registerSuccess' && message.token) {\n console.log(`Registration successful: ${message.message}`);\n\n // Registration complete, can now connect to channel\n resolve({ token: message.token });\n } else if (message.type === 'error') {\n console.error(`Registration failed: ${message.message}`);\n this._updateStatus('disconnected', `Registration failed: ${message.message}`);\n reject(new Error(message.message));\n }\n } catch (error) {\n console.error(`Error parsing registration response: ${error.message}`);\n this._updateStatus('disconnected', 'Error parsing server response');\n reject(error);\n }\n });\n\n // Handle registration errors\n regSocket.addEventListener('error', (event) => {\n console.error('Registration connection error');\n this._updateStatus('disconnected', 'Registration connection error');\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n reject(new Error('Connection error'));\n });\n\n // Handle registration connection close\n regSocket.addEventListener('close', (event) => {\n console.log(`Registration connection closed: ${event.code} ${event.reason}`);\n\n if (event.code !== 1000) {\n // If it wasn't a normal closure, show an error\n this._updateStatus('disconnected', 'Registration failed');\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n reject(new Error('Connection closed'));\n }\n });\n });\n }\n\n /**\n * Set up WebSocket event listeners for direct connection\n * @private\n */\n _setupSocketListeners() {\n if (!this.socket) {\n console.error('Cannot set up socket listeners: WebSocket not available');\n return;\n }\n\n // Set up socket open handler\n this.socket.addEventListener('open', () => {\n this.isConnected = true;\n this._reconnectAttempts = 0;\n this._updateStatus('connected', `Connected to ${this.currentChannel}`);\n this._updateConnectionUI(true);\n console.log('WebMCP connection established');\n this._registerItemsWithServer();\n });\n\n // Set up socket close handler\n this.socket.addEventListener('close', (event) => {\n this.isConnected = false;\n console.log(`Connection closed: ${event.code} ${event.reason}`);\n\n // Normal closure \u2014 no retry\n if (event.code === 1000) {\n this._updateStatus('disconnected', 'Disconnected');\n this._updateConnectionUI(false);\n return;\n }\n\n // Abnormal closure \u2014 try to reconnect\n if (this._reconnectAttempts < this._maxReconnectAttempts && this._lastConnectionToken) {\n this._reconnectAttempts++;\n const delay = this._reconnectDelay * this._reconnectAttempts;\n console.log(`Reconnecting (attempt ${this._reconnectAttempts}/${this._maxReconnectAttempts}) in ${delay}ms...`);\n this._updateStatus('connecting', `Reconectando (${this._reconnectAttempts}/${this._maxReconnectAttempts})...`);\n setTimeout(() => {\n this.connect(this._lastConnectionToken);\n }, delay);\n return;\n }\n\n // Max retries exceeded or no token \u2014 give up\n this._updateStatus('disconnected', 'Disconnected');\n this._updateConnectionUI(false);\n this.currentToken = '';\n this.currentServer = '';\n this.currentChannel = '';\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n });\n\n // Set up socket error handler\n this.socket.addEventListener('error', () => {\n // Suppress noisy errors during reconnection attempts\n if (this._reconnectAttempts > 0) return;\n\n console.error('WebSocket error');\n\n if (this.isConnected) {\n this._updateStatus('disconnected', 'Connection error occurred');\n } else {\n this._updateStatus('disconnected', 'Connection failed');\n }\n\n sessionStorage.removeItem(this.SESSION_STORAGE_KEY);\n });\n\n // Set up socket message handler\n this.socket.addEventListener('message', (event) => {\n try {\n const message = JSON.parse(event.data);\n this._handleServerMessage(message);\n } catch (error) {\n console.error(`Error parsing message: ${error.message}`);\n }\n });\n }\n\n /**\n * Handle messages from the server\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleServerMessage(message) {\n switch (message.type) {\n case 'welcome':\n console.log(`Server says: ${message.message}`);\n this._sendMessage({\n type: 'clientInfo',\n userAgent: navigator.userAgent,\n url: window.location.href,\n hostname: window.location.hostname,\n language: navigator.language,\n screenWidth: window.innerWidth,\n screenHeight: window.innerHeight,\n timestamp: Date.now()\n });\n break;\n\n case 'toolRegistered':\n console.log(`Tool registered with server: ${message.name}`);\n break;\n\n case 'promptRegistered':\n console.log(`Prompt registered with server: ${message.name}`);\n break;\n\n case 'resourceRegistered':\n console.log(`Resource registered with server: ${message.name}`);\n break;\n\n case 'callTool':\n // Server is asking us to execute a tool\n this._handleToolCall(message);\n break;\n\n case 'getPrompt':\n // Server is asking us to provide a prompt\n this._handleGetPrompt(message);\n break;\n\n case 'readResource':\n // Server is asking us to provide a resource\n this._handleReadResource(message);\n break;\n\n case 'createSamplingMessage':\n // Server is asking us to create a sampling message\n this._handleCreateSamplingMessage(message);\n break;\n\n case 'listTools':\n // Server is asking for available tools\n this._sendToolsList(message.id);\n break;\n\n case 'listPrompts':\n // Server is asking for available prompts\n this._sendPromptsList(message.id);\n break;\n\n case 'listResources':\n // Server is asking for available resources\n this._sendResourcesList(message.id);\n break;\n\n case 'ping':\n // Respond to ping\n this._sendMessage({\n type: 'pong',\n id: message.id,\n timestamp: Date.now()\n });\n break;\n\n case 'createTool':\n this._handleCreateTool(message);\n break;\n\n case 'removeTool':\n if (message.name && this.availableTools.has(message.name)) {\n this.availableTools.delete(message.name);\n this.registeredTools.delete(message.name);\n this._saveItemsToStorage();\n this._updateToolsList();\n console.log(`Tool removed by server: ${message.name}`);\n }\n break;\n\n case 'removeAllTools':\n this.availableTools.clear();\n this.registeredTools.clear();\n this._saveItemsToStorage();\n this._updateToolsList();\n console.log('All tools removed by server');\n break;\n\n case 'getClientInfo':\n this._sendMessage({\n id: message.id,\n type: 'clientInfoResponse',\n userAgent: navigator.userAgent,\n url: window.location.href,\n hostname: window.location.hostname,\n language: navigator.language,\n screenWidth: window.innerWidth,\n screenHeight: window.innerHeight,\n timestamp: Date.now()\n });\n break;\n\n case 'clipboardCopy':\n if (message.text && navigator.clipboard) {\n navigator.clipboard.writeText(message.text).then(() => {\n console.log('Token copiado al portapapeles');\n }).catch(err => {\n console.error('Error copiando al portapapeles:', err);\n });\n }\n break;\n\n case 'error':\n console.error(`Server error: ${message.message}`);\n break;\n\n default:\n console.warn(`Unknown message type: ${message.type}`);\n }\n }\n\n /**\n * Handle createTool request from server (via built-in agregar-tool)\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleCreateTool(message) {\n const {id, name, description, code, parametros} = message;\n try {\n let props = {};\n if (parametros) props = JSON.parse(parametros);\n const schema = { type: 'object', properties: props };\n const fn = new Function('args', code);\n this.registerTool(name, description, schema, fn);\n this._sendMessage({\n id,\n type: 'toolResponse',\n result: { content: [{ type: 'text', text: `Herramienta \"${name}\" registrada exitosamente` }] }\n });\n console.log(`Tool created by agent: ${name}`);\n } catch (e) {\n this._sendMessage({\n id,\n type: 'toolResponse',\n error: `Error creando herramienta: ${e.message}`\n });\n }\n }\n\n /**\n * Handle tool call from server\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleToolCall(message) {\n const {id, tool, arguments: args} = message;\n\n console.log(`Tool call: ${tool} with args:`, args);\n\n if (!this.availableTools.has(tool)) {\n this._sendMessage({\n id,\n type: 'toolResponse',\n error: `Tool not found: ${tool}`\n });\n return;\n }\n\n // Execute the tool\n try {\n const toolObj = this.availableTools.get(tool);\n\n // Normalize result to MCP content format\n const wrapResult = (raw) => {\n if (raw && raw.content && Array.isArray(raw.content)) return raw;\n const text = typeof raw === 'string' ? raw : JSON.stringify(raw);\n return { content: [{ type: \"text\", text }] };\n };\n\n // Call the tool's execute function\n const result = toolObj.execute(args);\n\n // Handle promises\n if (result instanceof Promise) {\n result\n .then(resolvedResult => {\n this._sendMessage({\n id,\n type: 'toolResponse',\n result: wrapResult(resolvedResult)\n });\n })\n .catch(error => {\n this._sendMessage({\n id,\n type: 'toolResponse',\n error: error.message || 'Tool execution error'\n });\n });\n } else {\n // Send immediate result\n this._sendMessage({\n id,\n type: 'toolResponse',\n result: wrapResult(result)\n });\n }\n\n console.log(`Tool response sent for ${tool}`);\n } catch (error) {\n this._sendMessage({\n id,\n type: 'toolResponse',\n error: error.message || 'Tool execution error'\n });\n console.error(`Tool execution error:`, error);\n }\n }\n\n /**\n * Handle prompt request from server\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleGetPrompt(message) {\n const {id, name, arguments: args} = message;\n\n console.log(`Prompt request: ${name} with args:`, args);\n\n if (!this.availablePrompts.has(name)) {\n this._sendMessage({\n id,\n type: 'promptResponse',\n error: `Prompt not found: ${name}`\n });\n return;\n }\n\n // Execute the prompt\n try {\n const promptObj = this.availablePrompts.get(name);\n\n // Call the prompt's execute function\n const result = promptObj.execute(args);\n\n // Handle promises\n if (result instanceof Promise) {\n result\n .then(resolvedResult => {\n this._sendMessage({\n id,\n type: 'promptResponse',\n result: resolvedResult\n });\n })\n .catch(error => {\n this._sendMessage({\n id,\n type: 'promptResponse',\n error: error.message || 'Prompt execution error'\n });\n });\n } else {\n // Send immediate result\n this._sendMessage({\n id,\n type: 'promptResponse',\n result\n });\n }\n\n console.log(`Prompt response sent for ${name}`);\n } catch (error) {\n this._sendMessage({\n id,\n type: 'promptResponse',\n error: error.message || 'Prompt execution error'\n });\n console.error(`Prompt execution error:`, error);\n }\n }\n\n /**\n * Handle resource request from server\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleReadResource(message) {\n const {id, uri} = message;\n\n console.log(`Resource request: ${uri}`);\n\n // Find resource that handles this URI\n let resourceObj = null;\n\n // First check for direct URI match\n for (const resource of this.availableResources.values()) {\n if (!resource.isTemplate && resource.uri === uri) {\n resourceObj = resource;\n break;\n }\n }\n\n // If no direct match, check for template match\n if (!resourceObj) {\n for (const resource of this.availableResources.values()) {\n if (resource.isTemplate) {\n // Simple check - if URI starts with template prefix (before any parameters)\n const templatePrefix = resource.uriTemplate.split('{')[0];\n if (uri.startsWith(templatePrefix)) {\n resourceObj = resource;\n break;\n }\n }\n }\n }\n\n if (!resourceObj) {\n this._sendMessage({\n id,\n type: 'resourceResponse',\n error: `No resource handler found for URI: ${uri}`\n });\n return;\n }\n\n // Execute the resource provider\n try {\n // Call the resource's provide function\n const result = resourceObj.provide(uri);\n\n // Handle promises\n if (result instanceof Promise) {\n result\n .then(resolvedResult => {\n this._sendMessage({\n id,\n type: 'resourceResponse',\n result: resolvedResult\n });\n })\n .catch(error => {\n this._sendMessage({\n id,\n type: 'resourceResponse',\n error: error.message || 'Resource read error'\n });\n });\n } else {\n // Send immediate result\n this._sendMessage({\n id,\n type: 'resourceResponse',\n result\n });\n }\n\n console.log(`Resource response sent for ${uri}`);\n } catch (error) {\n this._sendMessage({\n id,\n type: 'resourceResponse',\n error: error.message || 'Resource read error'\n });\n console.error(`Resource read error:`, error);\n }\n }\n\n /**\n * Send available tools list\n * @private\n * @param {string} requestId - The request ID to respond to\n */\n _sendToolsList(requestId) {\n const toolsList = Array.from(this.availableTools.values()).map(tool => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n }));\n\n this._sendMessage({\n id: requestId,\n type: 'listToolsResponse',\n tools: toolsList\n });\n\n console.log(`Sent tools list: ${toolsList.length} tools`);\n }\n\n /**\n * Send available prompts list\n * @private\n * @param {string} requestId - The request ID to respond to\n */\n _sendPromptsList(requestId) {\n const promptsList = Array.from(this.availablePrompts.values()).map(prompt => ({\n name: prompt.name,\n description: prompt.description,\n arguments: prompt.arguments,\n }));\n\n this._sendMessage({\n id: requestId,\n type: 'listPromptsResponse',\n prompts: promptsList\n });\n\n console.log(`Sent prompts list: ${promptsList.length} prompts`);\n }\n\n /**\n * Send available resources list\n * @private\n * @param {string} requestId - The request ID to respond to\n */\n _sendResourcesList(requestId) {\n const resources = [];\n const resourceTemplates = [];\n\n // Split resources and templates\n this.availableResources.forEach((resource) => {\n if (resource.isTemplate) {\n resourceTemplates.push({\n name: resource.name,\n description: resource.description,\n uriTemplate: resource.uriTemplate,\n mimeType: resource.mimeType\n });\n } else {\n resources.push({\n name: resource.name,\n description: resource.description,\n uri: resource.uri,\n mimeType: resource.mimeType\n });\n }\n });\n\n this._sendMessage({\n id: requestId,\n type: 'listResourcesResponse',\n resources,\n resourceTemplates\n });\n\n console.log(`Sent resources list: ${resources.length} resources, ${resourceTemplates.length} templates`);\n }\n\n /**\n * Send a message to the server via direct WebSocket\n * @private\n * @param {Object} message - The message object to send\n */\n _sendMessage(message) {\n if (!this.isConnected || !this.socket) {\n console.error('Cannot send message: not connected');\n return;\n }\n\n try {\n // Send the message directly through the WebSocket\n this.socket.send(JSON.stringify(message));\n return Promise.resolve();\n } catch (error) {\n console.error(`Error sending message: ${error.message}`);\n return Promise.reject(error);\n }\n }\n\n /**\n * Register all items with server that were registered while disconnected\n * @private\n */\n _registerItemsWithServer() {\n if (!this.isConnected) return;\n\n // Clear registration tracking sets - we'll re-register everything\n this.registeredTools = new Set();\n this.registeredPrompts = new Set();\n this.registeredResources = new Set();\n\n // Register all tools with the server\n this.availableTools.forEach((tool, name) => {\n this._sendMessage({\n type: 'registerTool',\n name,\n description: tool.description,\n inputSchema: tool.inputSchema\n });\n\n this.registeredTools.add(name);\n console.log(`Registering tool with server: ${name}`);\n });\n\n // Register all prompts with the server\n this.availablePrompts.forEach((prompt, name) => {\n this._sendMessage({\n type: 'registerPrompt',\n name,\n description: prompt.description,\n arguments: prompt.arguments\n });\n\n this.registeredPrompts.add(name);\n console.log(`Registering prompt with server: ${name}`);\n });\n\n // Register all resources with the server\n this.availableResources.forEach((resource, name) => {\n this._sendMessage({\n type: 'registerResource',\n name,\n description: resource.description,\n uri: resource.uri,\n uriTemplate: resource.uriTemplate,\n isTemplate: resource.isTemplate,\n mimeType: resource.mimeType\n });\n\n this.registeredResources.add(name);\n console.log(`Registering resource with server: ${name}`);\n });\n }\n\n /**\n * Register a tool\n * @public\n * @param {string} name - The name of the tool\n * @param {string} description - The description of the tool\n * @param {Object} schema - The schema for the tool's input\n * @param {Function} executeFn - The function to execute when the tool is called\n */\n registerTool(name, description, schema, executeFn) {\n if (!name) {\n console.error('Tool name is required');\n return;\n }\n\n // Add the tool to local registry\n this.availableTools.set(name, {\n name,\n description: description || `Tool: ${name}`,\n execute: executeFn || function (args) {\n return `Default implementation of ${name} with args: ${JSON.stringify(args)}`;\n },\n inputSchema: schema || {\n type: \"object\",\n properties: {}\n }\n });\n\n // Register the tool with the server if connected\n if (this.isConnected) {\n this._sendMessage({\n type: 'registerTool',\n name,\n description: description || `Tool: ${name}`,\n inputSchema: schema || {\n type: \"object\",\n properties: {}\n },\n });\n\n this.registeredTools.add(name);\n }\n\n // Save to session storage\n this._saveItemsToStorage();\n\n // Update tools display\n this._updateToolsList();\n console.log(`Tool registered: ${name}`);\n }\n\n /**\n * Unregister a tool\n * @public\n * @param {string} name - The name of the tool to unregister\n */\n unregisterTool(name) {\n if (!name) {\n console.error('Tool name is required');\n return;\n }\n\n if (!this.availableTools.has(name)) {\n console.warn(`Tool not found: ${name}`);\n return;\n }\n\n this.availableTools.delete(name);\n\n if (this.isConnected) {\n this._sendMessage({\n type: 'unregisterTool',\n name\n });\n }\n\n this.registeredTools.delete(name);\n this._saveItemsToStorage();\n this._updateToolsList();\n console.log(`Tool unregistered: ${name}`);\n }\n\n /**\n * Unregister all tools at once (single notification)\n * @public\n */\n unregisterAllTools() {\n if (this.availableTools.size === 0) return;\n\n this.availableTools.clear();\n this.registeredTools.clear();\n\n if (this.isConnected) {\n this._sendMessage({ type: 'unregisterAllTools' });\n }\n\n this._saveItemsToStorage();\n this._updateToolsList();\n console.log('All tools unregistered');\n }\n\n /**\n * Register a prompt\n * @public\n * @param {string} name - The name of the prompt\n * @param {string} description - The description of the prompt\n * @param {Array} promptArgs - The arguments for the prompt\n * @param {Function} executeFn - The function to execute when the prompt is called\n */\n registerPrompt(name, description, promptArgs, executeFn) {\n if (!name) {\n console.error('Prompt name is required');\n return;\n }\n\n // Add the prompt to local registry\n this.availablePrompts.set(name, {\n name,\n description: description || `Prompt: ${name}`,\n execute: executeFn || function (args) {\n return {\n messages: [{\n role: \"user\",\n content: {\n type: \"text\",\n text: `Default implementation of prompt ${name} with args: ${JSON.stringify(args)}`\n }\n }]\n };\n },\n arguments: promptArgs || []\n });\n\n // Register the prompt with the server if connected\n if (this.isConnected) {\n this._sendMessage({\n type: 'registerPrompt',\n name,\n description: description || `Prompt: ${name}`,\n arguments: promptArgs || []\n });\n\n this.registeredPrompts.add(name);\n }\n\n // Save to session storage\n this._saveItemsToStorage();\n\n // Update prompts display\n this._updatePromptsList();\n console.log(`Prompt registered: ${name}`);\n }\n\n /**\n * Unregister a prompt\n * @public\n * @param {string} name - The name of the prompt to unregister\n */\n unregisterPrompt(name) {\n if (!name) {\n console.error('Prompt name is required');\n return;\n }\n\n if (!this.availablePrompts.has(name)) {\n console.warn(`Prompt not found: ${name}`);\n return;\n }\n\n this.availablePrompts.delete(name);\n\n if (this.isConnected) {\n this._sendMessage({\n type: 'unregisterPrompt',\n name\n });\n }\n\n this.registeredPrompts.delete(name);\n this._saveItemsToStorage();\n this._updatePromptsList();\n console.log(`Prompt unregistered: ${name}`);\n }\n\n /**\n * Register a resource\n * @public\n * @param {string} name - The name of the resource\n * @param {string} description - The description of the resource\n * @param {Object} options - The resource options including uri, uriTemplate, and mimeType\n * @param {Function} provideFn - The function to execute when the resource is requested\n */\n registerResource(name, description, options, provideFn) {\n if (!name) {\n console.error('Resource name is required');\n return;\n }\n\n if (!options.uri && !options.uriTemplate) {\n console.error('Either uri or uriTemplate is required for a resource');\n return;\n }\n\n const isTemplate = !!options.uriTemplate;\n\n // Add the resource to local registry\n this.availableResources.set(name, {\n name,\n description: description || `Resource: ${name}`,\n uri: options.uri,\n uriTemplate: options.uriTemplate,\n isTemplate,\n mimeType: options.mimeType,\n provide: provideFn || function (uri) {\n return {\n contents: [{\n uri: uri,\n text: `Default implementation of resource ${name} for URI: ${uri}`,\n mimeType: options.mimeType || \"text/plain\"\n }]\n };\n }\n });\n\n // Register the resource with the server if connected\n if (this.isConnected) {\n this._sendMessage({\n type: 'registerResource',\n name,\n description: description || `Resource: ${name}`,\n uri: options.uri,\n uriTemplate: options.uriTemplate,\n isTemplate,\n mimeType: options.mimeType\n });\n\n this.registeredResources.add(name);\n }\n\n // Save to session storage\n this._saveItemsToStorage();\n\n // Update resources display\n this._updateResourcesList();\n console.log(`Resource registered: ${name}`);\n }\n\n /**\n * Unregister a resource\n * @public\n * @param {string} name - The name of the resource to unregister\n */\n unregisterResource(name) {\n if (!name) {\n console.error('Resource name is required');\n return;\n }\n\n if (!this.availableResources.has(name)) {\n console.warn(`Resource not found: ${name}`);\n return;\n }\n\n this.availableResources.delete(name);\n\n if (this.isConnected) {\n this._sendMessage({\n type: 'unregisterResource',\n name\n });\n }\n\n this.registeredResources.delete(name);\n this._saveItemsToStorage();\n this._updateResourcesList();\n console.log(`Resource unregistered: ${name}`);\n }\n\n /**\n * Handle sampling message creation request\n * @private\n * @param {Object} message - The parsed message object\n */\n _handleCreateSamplingMessage(message) {\n const {\n id,\n messages,\n systemPrompt,\n includeContext,\n temperature,\n maxTokens,\n stopSequences,\n metadata,\n modelPreferences\n } = message;\n\n console.log(`Sampling request received with ${messages?.length || 0} messages`);\n\n // Create a modal dialog to show the sampling request\n const modal = document.createElement('div');\n Object.assign(modal.style, {\n position: 'fixed',\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n backgroundColor: 'rgba(0, 0, 0, 0.5)',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: '10000'\n });\n\n // Create modal content\n const modalContent = document.createElement('div');\n Object.assign(modalContent.style, {\n backgroundColor: 'white',\n padding: '20px',\n borderRadius: '5px',\n maxWidth: '500px',\n width: '90%',\n maxHeight: '80%',\n overflow: 'auto'\n });\n\n // Create header\n const header = document.createElement('h3');\n header.textContent = 'Sampling Request';\n Object.assign(header.style, {\n margin: '0 0 15px 0',\n padding: '0 0 10px 0',\n borderBottom: '1px solid #ddd'\n });\n\n // Create content area to show messages\n const content = document.createElement('div');\n Object.assign(content.style, {\n marginBottom: '15px',\n maxHeight: '300px',\n overflow: 'auto',\n border: '1px solid #ddd',\n padding: '10px',\n backgroundColor: '#f9f9f9'\n });\n\n // Display messages\n if (messages && messages.length > 0) {\n messages.forEach(msg => {\n const msgDiv = document.createElement('div');\n Object.assign(msgDiv.style, {\n marginBottom: '10px',\n padding: '5px',\n borderRadius: '3px',\n backgroundColor: msg.role === 'user' ? '#e1f5fe' : '#f1f8e9'\n });\n\n const roleSpan = document.createElement('strong');\n roleSpan.textContent = msg.role === 'user' ? 'User: ' : 'Assistant: ';\n\n const contentSpan = document.createElement('span');\n if (msg.content.type === 'text') {\n contentSpan.textContent = msg.content.text;\n } else if (msg.content.type === 'image') {\n contentSpan.textContent = '[Image data]';\n }\n\n msgDiv.appendChild(roleSpan);\n msgDiv.appendChild(contentSpan);\n content.appendChild(msgDiv);\n });\n } else {\n content.textContent = 'No messages provided in sampling request';\n }\n\n // System prompt if available\n if (systemPrompt) {\n const sysPromptDiv = document.createElement('div');\n Object.assign(sysPromptDiv.style, {\n marginBottom: '10px',\n padding: '5px',\n backgroundColor: '#fff8e1'\n });\n\n const sysPromptLabel = document.createElement('strong');\n sysPromptLabel.textContent = 'System Prompt: ';\n\n const sysPromptContent = document.createElement('span');\n sysPromptContent.textContent = systemPrompt;\n\n sysPromptDiv.appendChild(sysPromptLabel);\n sysPromptDiv.appendChild(sysPromptContent);\n content.appendChild(sysPromptDiv);\n }\n\n // Create response input\n const responseLabel = document.createElement('label');\n responseLabel.textContent = 'Assistant Response:';\n Object.assign(responseLabel.style, {\n display: 'block',\n marginBottom: '5px',\n fontWeight: 'bold'\n });\n\n const responseInput = document.createElement('textarea');\n Object.assign(responseInput.style, {\n width: '100%',\n minHeight: '100px',\n padding: '10px',\n marginBottom: '15px',\n boxSizing: 'border-box'\n });\n\n // Create buttons\n const buttonContainer = document.createElement('div');\n Object.assign(buttonContainer.style, {\n display: 'flex',\n justifyContent: 'space-between'\n });\n\n const submitButton = document.createElement('button');\n submitButton.textContent = 'Submit Response';\n Object.assign(submitButton.style, {\n padding: '8px 15px',\n backgroundColor: '#4CAF50',\n color: 'white',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer'\n });\n\n const cancelButton = document.createElement('button');\n cancelButton.textContent = 'Cancel';\n Object.assign(cancelButton.style, {\n padding: '8px 15px',\n backgroundColor: '#f44336',\n color: 'white',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer'\n });\n\n // Add elements to modal\n buttonContainer.appendChild(cancelButton);\n buttonContainer.appendChild(submitButton);\n\n modalContent.appendChild(header);\n modalContent.appendChild(content);\n modalContent.appendChild(responseLabel);\n modalContent.appendChild(responseInput);\n modalContent.appendChild(buttonContainer);\n\n modal.appendChild(modalContent);\n document.body.appendChild(modal);\n\n // Focus the response input\n responseInput.focus();\n\n // Setup button handlers\n submitButton.addEventListener('click', () => {\n const responseText = responseInput.value.trim();\n if (responseText) {\n // Send response back to server\n this._sendMessage({\n id,\n type: 'samplingResponse',\n result: {\n model: 'web-user-input',\n role: 'assistant',\n content: {\n type: 'text',\n text: responseText\n }\n }\n });\n\n // Remove modal\n document.body.removeChild(modal);\n } else {\n alert('Please enter a response');\n }\n });\n\n cancelButton.addEventListener('click', () => {\n // Send error response\n this._sendMessage({\n id,\n type: 'samplingResponse',\n error: 'User cancelled sampling request'\n });\n\n // Remove modal\n document.body.removeChild(modal);\n });\n }\n}\n\n// Export for module usage\nif (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {\n module.exports = WebMCP;\n}\n"], + "mappings": ";;AAQA,MAAM,SAAN,MAAa;AAAA,IACT,YAAY,UAAU,CAAC,GAAG;AAEtB,WAAK,UAAU;AAAA,QACX,OAAO;AAAA,QACP,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,QACT,mBAAmB,IAAI,KAAK;AAAA;AAAA,QAC5B,GAAG;AAAA,MACP;AAGA,WAAK,cAAc;AACnB,WAAK,aAAa;AAClB,WAAK,SAAS;AACd,WAAK,kBAAkB;AACvB,WAAK,iBAAiB,oBAAI,IAAI;AAC9B,WAAK,mBAAmB,oBAAI,IAAI;AAChC,WAAK,qBAAqB,oBAAI,IAAI;AAClC,WAAK,oBAAoB,oBAAI,IAAI;AACjC,WAAK,eAAe;AACpB,WAAK,gBAAgB;AACrB,WAAK,iBAAiB;AACtB,WAAK,YAAY,mBAAmB,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC;AAC1E,WAAK,kBAAkB,oBAAI,IAAI;AAC/B,WAAK,oBAAoB,oBAAI,IAAI;AACjC,WAAK,sBAAsB,oBAAI,IAAI;AACnC,WAAK,qBAAqB;AAC1B,WAAK,wBAAwB;AAC7B,WAAK,kBAAkB;AACvB,WAAK,uBAAuB;AAG5B,WAAK,sBAAsB;AAC3B,WAAK,oBAAoB;AACzB,WAAK,sBAAsB;AAC3B,WAAK,wBAAwB;AAG7B,WAAK,gBAAgB;AAGrB,WAAK,MAAM;AAAA,IACf;AAAA,IAEA,QAAQ,GAAG;AACP,aAAO,EAAE,QAAQ,SAAS,GAAG;AAAA,IACjC;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,QAAQ;AAEJ,UAAI,SAAS,cAAc,sBAAsB,GAAG;AAChD,gBAAQ,KAAK,gDAAgD;AAC7D;AAAA,MACJ;AAGA,WAAK,cAAc;AAGnB,WAAK,qBAAqB;AAG1B,WAAK,sBAAsB;AAG3B,WAAK,kBAAkB;AAAA,IAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,oBAAoB;AAChB,YAAM,uBAAuB,eAAe,QAAQ,KAAK,mBAAmB;AAE5E,UAAI,sBAAsB;AACtB,YAAI;AACA,gBAAM,iBAAiB,KAAK,MAAM,oBAAoB;AACtD,cAAI,eAAe,OAAO;AACtB,oBAAQ,IAAI,qDAAqD;AAGjE,iBAAK,gBAAgB,eAAe;AACpC,iBAAK,iBAAiB,IAAI,eAAe,eAAe,KAAK,QAAQ,OAAO,SAAS,IAAI,CAAC;AAG1F,gBAAI,eAAe,MAAM,SAAS,GAAG,GAAG;AAEpC,oBAAM,YAAY,KAAK,MAAM,eAAe,KAAK;AACjD,mBAAK,eAAe,UAAU;AAAA,YAClC,OAAO;AAEH,kBAAI;AACA,sBAAM,UAAU,KAAK,eAAe,KAAK;AACzC,sBAAM,YAAY,KAAK,MAAM,OAAO;AACpC,qBAAK,eAAe,UAAU;AAAA,cAClC,SAAS,GAAG;AACR,qBAAK,eAAe,eAAe;AAAA,cACvC;AAAA,YACJ;AAGA,iBAAK,iBAAiB;AAGtB,iBAAK,QAAQ,eAAe,KAAK;AAAA,UACrC;AAAA,QACJ,SAAS,OAAO;AACZ,kBAAQ,MAAM,yCAAyC,KAAK;AAC5D,yBAAe,WAAW,KAAK,mBAAmB;AAClD,eAAK,kBAAkB;AAAA,QAC3B;AAAA,MACJ;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,sBAAsB;AAClB,UAAI;AAEA,cAAM,YAAY,CAAC;AACnB,aAAK,eAAe,QAAQ,CAAC,MAAM,SAAS;AACxC,oBAAU,IAAI,IAAI;AAAA,YACd,MAAM,KAAK;AAAA,YACX,aAAa,KAAK;AAAA,YAClB,aAAa,KAAK;AAAA;AAAA,UAEtB;AAAA,QACJ,CAAC;AACD,uBAAe,QAAQ,KAAK,mBAAmB,KAAK,UAAU,SAAS,CAAC;AAGxE,cAAM,cAAc,CAAC;AACrB,aAAK,iBAAiB,QAAQ,CAAC,QAAQ,SAAS;AAC5C,sBAAY,IAAI,IAAI;AAAA,YAChB,MAAM,OAAO;AAAA,YACb,aAAa,OAAO;AAAA,YACpB,WAAW,OAAO;AAAA;AAAA,UAEtB;AAAA,QACJ,CAAC;AACD,uBAAe,QAAQ,KAAK,qBAAqB,KAAK,UAAU,WAAW,CAAC;AAG5E,cAAM,gBAAgB,CAAC;AACvB,aAAK,mBAAmB,QAAQ,CAAC,UAAU,SAAS;AAChD,wBAAc,IAAI,IAAI;AAAA,YAClB,MAAM,SAAS;AAAA,YACf,aAAa,SAAS;AAAA,YACtB,KAAK,SAAS;AAAA,YACd,aAAa,SAAS;AAAA,YACtB,YAAY,SAAS;AAAA,YACrB,UAAU,SAAS;AAAA;AAAA,UAEvB;AAAA,QACJ,CAAC;AACD,uBAAe,QAAQ,KAAK,uBAAuB,KAAK,UAAU,aAAa,CAAC;AAEhF,gBAAQ,IAAI,mCAAmC;AAAA,UAC3C,OAAO,OAAO,KAAK,SAAS,EAAE;AAAA,UAC9B,SAAS,OAAO,KAAK,WAAW,EAAE;AAAA,UAClC,WAAW,OAAO,KAAK,aAAa,EAAE;AAAA,QAC1C,CAAC;AAAA,MACL,SAAS,OAAO;AACZ,gBAAQ,MAAM,0CAA0C,KAAK;AAAA,MACjE;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,mBAAmB;AACf,UAAI;AAEA,cAAM,cAAc,eAAe,QAAQ,KAAK,iBAAiB;AACjE,YAAI,aAAa;AACb,gBAAM,YAAY,KAAK,MAAM,WAAW;AACxC,iBAAO,QAAQ,SAAS,EAAE,QAAQ,CAAC,CAAC,MAAM,IAAI,MAAM;AAEhD,iBAAK,eAAe,IAAI,MAAM;AAAA,cAC1B,GAAG;AAAA,cACH,SAAS,SAAU,MAAM;AACrB,wBAAQ,KAAK,QAAQ,IAAI,oFAAoF;AAC7G,uBAAO,QAAQ,IAAI;AAAA,cACvB;AAAA,YACJ,CAAC;AAAA,UACL,CAAC;AAAA,QACL;AAGA,cAAM,gBAAgB,eAAe,QAAQ,KAAK,mBAAmB;AACrE,YAAI,eAAe;AACf,gBAAM,cAAc,KAAK,MAAM,aAAa;AAC5C,iBAAO,QAAQ,WAAW,EAAE,QAAQ,CAAC,CAAC,MAAM,MAAM,MAAM;AAEpD,iBAAK,iBAAiB,IAAI,MAAM;AAAA,cAC5B,GAAG;AAAA,cACH,SAAS,SAAU,MAAM;AACrB,wBAAQ,KAAK,UAAU,IAAI,oFAAoF;AAC/G,uBAAO;AAAA,kBACH,UAAU,CAAC;AAAA,oBACP,MAAM;AAAA,oBACN,SAAS;AAAA,sBACL,MAAM;AAAA,sBACN,MAAM,UAAU,IAAI;AAAA,oBACxB;AAAA,kBACJ,CAAC;AAAA,gBACL;AAAA,cACJ;AAAA,YACJ,CAAC;AAAA,UACL,CAAC;AAAA,QACL;AAGA,cAAM,kBAAkB,eAAe,QAAQ,KAAK,qBAAqB;AACzE,YAAI,iBAAiB;AACjB,gBAAM,gBAAgB,KAAK,MAAM,eAAe;AAChD,iBAAO,QAAQ,aAAa,EAAE,QAAQ,CAAC,CAAC,MAAM,QAAQ,MAAM;AAExD,iBAAK,mBAAmB,IAAI,MAAM;AAAA,cAC9B,GAAG;AAAA,cACH,SAAS,SAAU,KAAK;AACpB,wBAAQ,KAAK,YAAY,IAAI,kFAAkF;AAC/G,uBAAO;AAAA,kBACH,UAAU,CAAC;AAAA,oBACP;AAAA,oBACA,MAAM,YAAY,IAAI;AAAA,oBACtB,UAAU,SAAS,YAAY;AAAA,kBACnC,CAAC;AAAA,gBACL;AAAA,cACJ;AAAA,YACJ,CAAC;AAAA,UACL,CAAC;AAAA,QACL;AAEA,gBAAQ,IAAI,sCAAsC;AAAA,UAC9C,OAAO,KAAK,eAAe;AAAA,UAC3B,SAAS,KAAK,iBAAiB;AAAA,UAC/B,WAAW,KAAK,mBAAmB;AAAA,QACvC,CAAC;AAGD,aAAK,iBAAiB;AACtB,aAAK,mBAAmB;AACxB,aAAK,qBAAqB;AAAA,MAE9B,SAAS,OAAO;AACZ,gBAAQ,MAAM,6CAA6C,KAAK;AAChE,aAAK,kBAAkB;AAAA,MAC3B;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,oBAAoB;AAChB,qBAAe,WAAW,KAAK,iBAAiB;AAChD,qBAAe,WAAW,KAAK,mBAAmB;AAClD,qBAAe,WAAW,KAAK,qBAAqB;AACpD,cAAQ,IAAI,2CAA2C;AAAA,IAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,gBAAgB;AAEZ,YAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,gBAAU,KAAK,KAAK;AACpB,gBAAU,QAAQ,eAAe;AAGjC,aAAO,OAAO,UAAU,OAAO;AAAA,QAC3B,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,eAAe;AAAA,QACf,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,YAAY;AAAA,MAChB,CAAC;AAGD,WAAK,mBAAmB,SAAS;AAGjC,YAAM,gBAAgB,SAAS,cAAc,KAAK;AAClD,oBAAc,YAAY;AAC1B,aAAO,OAAO,cAAc,OAAO;AAAA,QAC/B,OAAO,KAAK,QAAQ;AAAA,QACpB,QAAQ,KAAK,QAAQ;AAAA,QACrB,iBAAiB,KAAK,QAAQ;AAAA,QAC9B,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,WAAW;AAAA,MACf,CAAC;AAGD,YAAM,eAAe,SAAS,cAAc,KAAK;AACjD,mBAAa,YAAY;AACzB,aAAO,OAAO,aAAa,OAAO;AAAA,QAC9B,iBAAiB;AAAA,QACjB,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,SAAS;AAAA,QACT,cAAc;AAAA,QACd,WAAW;AAAA,QACX,OAAO;AAAA,QACP,SAAS;AAAA,QACT,UAAU;AAAA,QACV,UAAU;AAAA,QACV,QAAQ;AAAA,MACZ,CAAC;AAGD,YAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,aAAO,OAAO,OAAO,OAAO;AAAA,QACxB,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,cAAc;AAAA,MAClB,CAAC;AAED,YAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,YAAM,cAAc;AACpB,aAAO,OAAO,MAAM,OAAO;AAAA,QACvB,YAAY;AAAA,QACZ,UAAU;AAAA,MACd,CAAC;AAED,YAAM,cAAc,SAAS,cAAc,QAAQ;AACnD,kBAAY,YAAY;AACxB,kBAAY,YAAY;AACxB,aAAO,OAAO,YAAY,OAAO;AAAA,QAC7B,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,OAAO;AAAA,MACX,CAAC;AAED,aAAO,YAAY,KAAK;AACxB,aAAO,YAAY,WAAW;AAC9B,mBAAa,YAAY,MAAM;AAG/B,WAAK,sBAAsB,YAAY;AAGvC,YAAM,kBAAkB,SAAS,cAAc,KAAK;AACpD,sBAAgB,YAAY;AAC5B,sBAAgB,cAAc;AAC9B,aAAO,OAAO,gBAAgB,OAAO;AAAA,QACjC,SAAS;AAAA,QACT,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,OAAO;AAAA,QACP,WAAW;AAAA,QACX,cAAc;AAAA,QACd,UAAU;AAAA,MACd,CAAC;AACD,mBAAa,YAAY,eAAe;AAGxC,YAAM,kBAAkB,SAAS,cAAc,KAAK;AACpD,sBAAgB,YAAY;AAC5B,mBAAa,YAAY,eAAe;AAGxC,YAAM,2BAA2B,SAAS,cAAc,KAAK;AAC7D,+BAAyB,YAAY;AACrC,aAAO,OAAO,yBAAyB,OAAO;AAAA,QAC1C,WAAW;AAAA,QACX,UAAU;AAAA,QACV,SAAS;AAAA,QACT,WAAW;AAAA,QACX,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,cAAc;AAAA,MAClB,CAAC;AACD,mBAAa,YAAY,wBAAwB;AAIjD,YAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,gBAAU,YAAY;AACtB,aAAO,OAAO,UAAU,OAAO;AAAA,QAC3B,SAAS;AAAA,QACT,cAAc;AAAA,MAClB,CAAC;AAED,YAAM,cAAc,SAAS,cAAc,KAAK;AAChD,kBAAY,cAAc;AAC1B,aAAO,OAAO,YAAY,OAAO;AAAA,QAC7B,YAAY;AAAA,QACZ,cAAc;AAAA,MAClB,CAAC;AAED,YAAM,iBAAiB,SAAS,cAAc,IAAI;AAClD,qBAAe,YAAY;AAC3B,aAAO,OAAO,eAAe,OAAO;AAAA,QAChC,WAAW;AAAA,QACX,SAAS;AAAA,QACT,QAAQ;AAAA,MACZ,CAAC;AAED,gBAAU,YAAY,WAAW;AACjC,gBAAU,YAAY,cAAc;AACpC,+BAAyB,YAAY,SAAS;AAG9C,YAAM,cAAc,SAAS,cAAc,KAAK;AAChD,kBAAY,YAAY;AACxB,aAAO,OAAO,YAAY,OAAO;AAAA,QAC7B,SAAS;AAAA,QACT,cAAc;AAAA,MAClB,CAAC;AAED,YAAM,gBAAgB,SAAS,cAAc,KAAK;AAClD,oBAAc,cAAc;AAC5B,aAAO,OAAO,cAAc,OAAO;AAAA,QAC/B,YAAY;AAAA,QACZ,cAAc;AAAA,MAClB,CAAC;AAED,YAAM,mBAAmB,SAAS,cAAc,IAAI;AACpD,uBAAiB,YAAY;AAC7B,aAAO,OAAO,iBAAiB,OAAO;AAAA,QAClC,WAAW;AAAA,QACX,SAAS;AAAA,QACT,QAAQ;AAAA,MACZ,CAAC;AAED,kBAAY,YAAY,aAAa;AACrC,kBAAY,YAAY,gBAAgB;AACxC,+BAAyB,YAAY,WAAW;AAGhD,YAAM,gBAAgB,SAAS,cAAc,KAAK;AAClD,oBAAc,YAAY;AAC1B,aAAO,OAAO,cAAc,OAAO;AAAA,QAC/B,SAAS;AAAA,MACb,CAAC;AAED,YAAM,kBAAkB,SAAS,cAAc,KAAK;AACpD,sBAAgB,cAAc;AAC9B,aAAO,OAAO,gBAAgB,OAAO;AAAA,QACjC,YAAY;AAAA,QACZ,cAAc;AAAA,MAClB,CAAC;AAED,YAAM,qBAAqB,SAAS,cAAc,IAAI;AACtD,yBAAmB,YAAY;AAC/B,aAAO,OAAO,mBAAmB,OAAO;AAAA,QACpC,WAAW;AAAA,QACX,SAAS;AAAA,QACT,QAAQ;AAAA,MACZ,CAAC;AAED,oBAAc,YAAY,eAAe;AACzC,oBAAc,YAAY,kBAAkB;AAC5C,+BAAyB,YAAY,aAAa;AAGlD,gBAAU,YAAY,YAAY;AAClC,gBAAU,YAAY,aAAa;AACnC,eAAS,KAAK,YAAY,SAAS;AAAA,IACvC;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,mBAAmB,WAAW;AAC1B,YAAM,EAAC,UAAU,QAAO,IAAI,KAAK;AAEjC,cAAQ,UAAU;AAAA,QACd,KAAK;AACD,iBAAO,OAAO,UAAU,OAAO;AAAA,YAC3B,QAAQ;AAAA,YACR,OAAO;AAAA,YACP,YAAY;AAAA,UAChB,CAAC;AACD;AAAA,QACJ,KAAK;AACD,iBAAO,OAAO,UAAU,OAAO;AAAA,YAC3B,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,YAAY;AAAA,UAChB,CAAC;AACD;AAAA,QACJ,KAAK;AACD,iBAAO,OAAO,UAAU,OAAO;AAAA,YAC3B,KAAK;AAAA,YACL,OAAO;AAAA,YACP,YAAY;AAAA,UAChB,CAAC;AACD;AAAA,QACJ,KAAK;AACD,iBAAO,OAAO,UAAU,OAAO;AAAA,YAC3B,KAAK;AAAA,YACL,MAAM;AAAA,YACN,YAAY;AAAA,UAChB,CAAC;AACD;AAAA,QACJ;AAEI,iBAAO,OAAO,UAAU,OAAO;AAAA,YAC3B,QAAQ;AAAA,YACR,OAAO;AAAA,YACP,YAAY;AAAA,UAChB,CAAC;AAAA,MACT;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,sBAAsB,WAAW;AAC7B,YAAM,OAAO,SAAS,cAAc,KAAK;AACzC,aAAO,OAAO,KAAK,OAAO;AAAA,QACtB,cAAc;AAAA,MAClB,CAAC;AAGD,YAAM,aAAa,SAAS,cAAc,KAAK;AAC/C,aAAO,OAAO,WAAW,OAAO;AAAA,QAC5B,SAAS;AAAA,QACT,cAAc;AAAA,MAClB,CAAC;AAED,YAAM,aAAa,SAAS,cAAc,OAAO;AACjD,iBAAW,OAAO;AAClB,iBAAW,YAAY;AACvB,iBAAW,cAAc;AACzB,aAAO,OAAO,WAAW,OAAO;AAAA,QAC5B,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,UAAU;AAAA,MACd,CAAC;AAED,YAAM,gBAAgB,SAAS,cAAc,QAAQ;AACrD,oBAAc,YAAY;AAC1B,oBAAc,cAAc;AAC5B,aAAO,OAAO,cAAc,OAAO;AAAA,QAC/B,SAAS;AAAA,QACT,iBAAiB,KAAK,QAAQ;AAAA,QAC9B,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,UAAU;AAAA,MACd,CAAC;AAED,iBAAW,YAAY,UAAU;AACjC,iBAAW,YAAY,aAAa;AAEpC,YAAM,mBAAmB,SAAS,cAAc,QAAQ;AACxD,uBAAiB,YAAY;AAC7B,uBAAiB,cAAc;AAC/B,aAAO,OAAO,iBAAiB,OAAO;AAAA,QAClC,SAAS;AAAA,QACT,iBAAiB;AAAA,QACjB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,OAAO;AAAA,QACP,SAAS;AAAA,MACb,CAAC;AAED,WAAK,YAAY,UAAU;AAC3B,WAAK,YAAY,gBAAgB;AACjC,gBAAU,YAAY,IAAI;AAAA,IAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,uBAAuB;AACnB,YAAM,YAAY,SAAS,eAAe,KAAK,SAAS;AACxD,UAAI,CAAC,UAAW;AAGhB,YAAM,UAAU,UAAU,cAAc,iBAAiB;AACzD,cAAQ,iBAAiB,SAAS,MAAM;AACpC,aAAK,gBAAgB;AAAA,MACzB,CAAC;AAGD,YAAM,WAAW,UAAU,cAAc,eAAe;AACxD,eAAS,iBAAiB,SAAS,MAAM;AACrC,aAAK,gBAAgB,KAAK;AAAA,MAC9B,CAAC;AAGD,YAAM,aAAa,UAAU,cAAc,qBAAqB;AAChE,iBAAW,iBAAiB,SAAS,MAAM;AACvC,cAAM,aAAa,UAAU,cAAc,qBAAqB;AAChE,aAAK,QAAQ,WAAW,KAAK;AAAA,MACjC,CAAC;AAGD,YAAM,gBAAgB,UAAU,cAAc,wBAAwB;AACtE,oBAAc,iBAAiB,SAAS,MAAM;AAC1C,aAAK,WAAW;AAAA,MACpB,CAAC;AAGD,eAAS,iBAAiB,aAAa,MAAM,KAAK,sBAAsB,CAAC;AACzE,eAAS,iBAAiB,YAAY,MAAM,KAAK,sBAAsB,CAAC;AACxE,eAAS,iBAAiB,SAAS,MAAM,KAAK,sBAAsB,CAAC;AACrE,eAAS,iBAAiB,UAAU,MAAM,KAAK,sBAAsB,CAAC;AAAA,IAC1E;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,gBAAgB,QAAQ,MAAM;AAC1B,YAAM,YAAY,SAAS,eAAe,KAAK,SAAS;AACxD,UAAI,CAAC,UAAW;AAEhB,YAAM,eAAe,UAAU,cAAc,iBAAiB;AAC9D,WAAK,aAAa,UAAU,OAAO,QAAQ,CAAC,KAAK;AAEjD,UAAI,KAAK,YAAY;AACjB,qBAAa,MAAM,UAAU;AAAA,MACjC,OAAO;AACH,qBAAa,MAAM,UAAU;AAAA,MACjC;AAEA,WAAK,sBAAsB;AAAA,IAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,cAAc,QAAQ,SAAS;AAC3B,YAAM,YAAY,SAAS,eAAe,KAAK,SAAS;AACxD,UAAI,CAAC,UAAW;AAEhB,YAAM,kBAAkB,UAAU,cAAc,gBAAgB;AAChE,UAAI,CAAC,gBAAiB;AAGtB,sBAAgB,UAAU,OAAO,aAAa,gBAAgB,cAAc,cAAc;AAG1F,sBAAgB,cAAc,WAAW;AAGzC,cAAQ,QAAQ;AAAA,QACZ,KAAK;AACD,iBAAO,OAAO,gBAAgB,OAAO;AAAA,YACjC,iBAAiB;AAAA,YACjB,OAAO;AAAA,UACX,CAAC;AACD;AAAA,QACJ,KAAK;AACD,iBAAO,OAAO,gBAAgB,OAAO;AAAA,YACjC,iBAAiB;AAAA,YACjB,OAAO;AAAA,UACX,CAAC;AACD;AAAA,QACJ,KAAK;AACD,iBAAO,OAAO,gBAAgB,OAAO;AAAA,YACjC,iBAAiB;AAAA,YACjB,OAAO;AAAA,UACX,CAAC;AACD;AAAA,QACJ,KAAK;AACD,iBAAO,OAAO,gBAAgB,OAAO;AAAA,YACjC,iBAAiB;AAAA,YACjB,OAAO;AAAA,UACX,CAAC;AACD;AAAA,MACR;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,oBAAoB,aAAa;AAC7B,YAAM,YAAY,SAAS,eAAe,KAAK,SAAS;AACxD,UAAI,CAAC,UAAW;AAEhB,YAAM,aAAa,UAAU,cAAc,qBAAqB;AAChE,YAAM,aAAa,UAAU,cAAc,qBAAqB;AAChE,YAAM,gBAAgB,UAAU,cAAc,wBAAwB;AACtE,YAAM,2BAA2B,UAAU,cAAc,0BAA0B;AAEnF,UAAI,aAAa;AACb,mBAAW,MAAM,UAAU;AAC3B,mBAAW,MAAM,UAAU;AAC3B,sBAAc,MAAM,UAAU;AAC9B,iCAAyB,MAAM,UAAU;AAGzC,cAAM,UAAU,UAAU,cAAc,iBAAiB;AACzD,gBAAQ,YAAY;AACpB,gBAAQ,MAAM,QAAQ;AACtB,gBAAQ,MAAM,aAAa;AAAA,MAC/B,OAAO;AACH,mBAAW,MAAM,UAAU;AAC3B,mBAAW,MAAM,UAAU;AAC3B,sBAAc,MAAM,UAAU;AAC9B,iCAAyB,MAAM,UAAU;AAGzC,cAAM,UAAU,UAAU,cAAc,iBAAiB;AACzD,gBAAQ,YAAY;AAAA,MACxB;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,mBAAmB;AACf,YAAM,YAAY,SAAS,eAAe,KAAK,SAAS;AACxD,UAAI,CAAC,UAAW;AAEhB,YAAM,iBAAiB,UAAU,cAAc,yBAAyB;AACxE,UAAI,CAAC,eAAgB;AAGrB,qBAAe,YAAY;AAE3B,UAAI,KAAK,eAAe,SAAS,GAAG;AAChC,cAAM,eAAe,SAAS,cAAc,IAAI;AAChD,qBAAa,cAAc;AAC3B,qBAAa,MAAM,YAAY;AAC/B,qBAAa,MAAM,QAAQ;AAC3B,uBAAe,YAAY,YAAY;AACvC;AAAA,MACJ;AAGA,WAAK,eAAe,QAAQ,CAAC,MAAM,SAAS;AACxC,cAAM,WAAW,SAAS,cAAc,IAAI;AAC5C,eAAO,OAAO,SAAS,OAAO;AAAA,UAC1B,SAAS;AAAA,UACT,cAAc;AAAA,QAClB,CAAC;AAED,cAAM,WAAW,SAAS,cAAc,QAAQ;AAChD,iBAAS,cAAc;AAEvB,cAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,iBAAS,cAAc,KAAK;AAC5B,iBAAS,MAAM,WAAW;AAC1B,iBAAS,MAAM,QAAQ;AAEvB,iBAAS,YAAY,QAAQ;AAC7B,iBAAS,YAAY,QAAQ;AAC7B,uBAAe,YAAY,QAAQ;AAAA,MACvC,CAAC;AAAA,IACL;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,qBAAqB;AACjB,YAAM,YAAY,SAAS,eAAe,KAAK,SAAS;AACxD,UAAI,CAAC,UAAW;AAEhB,YAAM,mBAAmB,UAAU,cAAc,2BAA2B;AAC5E,UAAI,CAAC,iBAAkB;AAGvB,uBAAiB,YAAY;AAE7B,UAAI,KAAK,iBAAiB,SAAS,GAAG;AAClC,cAAM,eAAe,SAAS,cAAc,IAAI;AAChD,qBAAa,cAAc;AAC3B,qBAAa,MAAM,YAAY;AAC/B,qBAAa,MAAM,QAAQ;AAC3B,yBAAiB,YAAY,YAAY;AACzC;AAAA,MACJ;AAGA,WAAK,iBAAiB,QAAQ,CAAC,QAAQ,SAAS;AAC5C,cAAM,aAAa,SAAS,cAAc,IAAI;AAC9C,eAAO,OAAO,WAAW,OAAO;AAAA,UAC5B,SAAS;AAAA,UACT,cAAc;AAAA,QAClB,CAAC;AAED,cAAM,aAAa,SAAS,cAAc,QAAQ;AAClD,mBAAW,cAAc;AAEzB,cAAM,aAAa,SAAS,cAAc,KAAK;AAC/C,mBAAW,cAAc,OAAO;AAChC,mBAAW,MAAM,WAAW;AAC5B,mBAAW,MAAM,QAAQ;AAEzB,mBAAW,YAAY,UAAU;AACjC,mBAAW,YAAY,UAAU;AACjC,yBAAiB,YAAY,UAAU;AAAA,MAC3C,CAAC;AAAA,IACL;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,uBAAuB;AACnB,YAAM,YAAY,SAAS,eAAe,KAAK,SAAS;AACxD,UAAI,CAAC,UAAW;AAEhB,YAAM,qBAAqB,UAAU,cAAc,6BAA6B;AAChF,UAAI,CAAC,mBAAoB;AAGzB,yBAAmB,YAAY;AAE/B,UAAI,KAAK,mBAAmB,SAAS,GAAG;AACpC,cAAM,eAAe,SAAS,cAAc,IAAI;AAChD,qBAAa,cAAc;AAC3B,qBAAa,MAAM,YAAY;AAC/B,qBAAa,MAAM,QAAQ;AAC3B,2BAAmB,YAAY,YAAY;AAC3C;AAAA,MACJ;AAGA,WAAK,mBAAmB,QAAQ,CAAC,UAAU,SAAS;AAChD,cAAM,eAAe,SAAS,cAAc,IAAI;AAChD,eAAO,OAAO,aAAa,OAAO;AAAA,UAC9B,SAAS;AAAA,UACT,cAAc;AAAA,QAClB,CAAC;AAED,cAAM,eAAe,SAAS,cAAc,QAAQ;AACpD,qBAAa,cAAc;AAE3B,cAAM,eAAe,SAAS,cAAc,KAAK;AACjD,qBAAa,cAAc,SAAS,eAC/B,SAAS,aAAa,gBAAgB;AAC3C,qBAAa,MAAM,WAAW;AAC9B,qBAAa,MAAM,QAAQ;AAE3B,qBAAa,YAAY,YAAY;AACrC,qBAAa,YAAY,YAAY;AACrC,2BAAmB,YAAY,YAAY;AAAA,MAC/C,CAAC;AAAA,IACL;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,wBAAwB;AAEpB,UAAI,KAAK,iBAAiB;AACtB,qBAAa,KAAK,eAAe;AAAA,MACrC;AAGA,WAAK,kBAAkB,WAAW,MAAM;AACpC,aAAK,kBAAkB;AAAA,MAC3B,GAAG,KAAK,QAAQ,iBAAiB;AAAA,IACrC;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,oBAAoB;AAChB,cAAQ,IAAI,2CAA2C;AAGvD,UAAI,KAAK,aAAa;AAClB,aAAK,WAAW;AAAA,MACpB;AAGA,WAAK,gBAAgB,KAAK;AAG1B,qBAAe,WAAW,KAAK,mBAAmB;AAAA,IACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,MAAM,QAAQ,iBAAiB;AAC3B,UAAI,CAAC,iBAAiB;AAClB,aAAK,cAAc,gBAAgB,0BAA0B;AAC7D;AAAA,MACJ;AAGA,WAAK,uBAAuB;AAG5B,WAAK,cAAc,cAAc,eAAe;AAEhD,UAAI;AAEA,YAAI,CAAC,KAAK,wBAAwB,eAAe,GAAG;AAChD;AAAA,QACJ;AAGA,cAAM,iBAAiB;AAAA,UACnB,OAAO;AAAA,UACP,QAAQ,KAAK;AAAA,UACb,MAAM,KAAK,QAAQ,OAAO,SAAS,IAAI;AAAA,QAC3C;AAGA,cAAM,uBAAuB,eAAe,QAAQ,KAAK,mBAAmB;AAC5E,YAAI,mBAAmB;AAEvB,YAAI,sBAAsB;AACtB,cAAI;AACA,kBAAMA,kBAAiB,KAAK,MAAM,oBAAoB;AAEtD,gBAAIA,gBAAe,WAAW,KAAK,iBAC/BA,gBAAe,SAAS,KAAK,QAAQ,OAAO,SAAS,IAAI,GAAG;AAC5D,iCAAmB;AAAA,YACvB;AAAA,UACJ,SAAS,OAAO;AACZ,oBAAQ,MAAM,yCAAyC,KAAK;AAAA,UAChE;AAAA,QACJ;AAEA,YAAI,CAAC,kBAAkB;AAEnB,gBAAM,WAAW,MAAM,KAAK,oBAAoB,eAAe;AAE/D,cAAI,CAAC,SAAS,OAAO;AACjB,iBAAK,cAAc,gBAAgB,qBAAqB;AACxD;AAAA,UACJ;AAGA,yBAAe,QAAQ,SAAS;AAChC,eAAK,eAAe,SAAS;AAE7B,yBAAe,QAAQ,KAAK,qBAAqB,KAAK,UAAU,cAAc,CAAC;AAAA,QACnF;AAGA,cAAM,YAAY,GAAG,KAAK,aAAa,GAAG,KAAK,cAAc,UAAU,KAAK,YAAY;AAGxF,aAAK,cAAc,cAAc,0BAA0B;AAG3D,aAAK,SAAS,IAAI,UAAU,SAAS;AAGrC,aAAK,sBAAsB;AAG3B,aAAK,sBAAsB;AAAA,MAE/B,SAAS,OAAO;AACZ,gBAAQ,MAAM,qBAAqB,KAAK;AACxC,aAAK,cAAc,gBAAgB,UAAU,MAAM,OAAO,EAAE;AAAA,MAChE;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,aAAa;AAET,UAAI,KAAK,QAAQ;AACb,aAAK,OAAO,MAAM;AAClB,aAAK,SAAS;AAAA,MAClB;AAEA,WAAK,cAAc;AACnB,WAAK,cAAc,gBAAgB,cAAc;AACjD,WAAK,oBAAoB,KAAK;AAG9B,WAAK,eAAe;AACpB,WAAK,gBAAgB;AACrB,WAAK,iBAAiB;AAGtB,qBAAe,WAAW,KAAK,mBAAmB;AAGlD,WAAK,kBAAkB;AAAA,IAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,wBAAwB,cAAc;AAClC,UAAI;AAEA,cAAM,UAAU,KAAK,YAAY;AACjC,cAAM,iBAAiB,KAAK,MAAM,OAAO;AAGzC,cAAM,EAAC,QAAQ,MAAK,IAAI;AAExB,YAAI,CAAC,UAAU,CAAC,OAAO;AACnB,eAAK,cAAc,gBAAgB,eAAe;AAClD,iBAAO;AAAA,QACX;AAGA,aAAK,gBAAgB;AACrB,aAAK,eAAe;AAGpB,aAAK,iBAAiB,IAAI,KAAK,QAAQ,OAAO,SAAS,IAAI,CAAC;AAE5D,eAAO;AAAA,MACX,SAAS,OAAO;AACZ,aAAK,cAAc,gBAAgB,uBAAuB;AAC1D,eAAO;AAAA,MACX;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,oBAAoB,cAAc;AAE9B,WAAK,cAAc,gBAAgB,gBAAgB;AAGnD,YAAM,YAAY,IAAI,UAAU,GAAG,KAAK,aAAa,GAAG,KAAK,aAAa,EAAE;AAE5E,aAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAEpC,kBAAU,iBAAiB,QAAQ,CAAC,UAAU;AAC1C,kBAAQ,IAAI,qCAAqC;AAGjD,gBAAM,UAAU,KAAK,YAAY;AACjC,gBAAM,iBAAiB,KAAK,MAAM,OAAO;AACzC,yBAAe,OAAO,KAAK,QAAQ,OAAO,SAAS,IAAI;AACvD,oBAAU,KAAK,KAAK,KAAK,UAAU,cAAc,CAAC,CAAC;AAAA,QACvD,CAAC;AAGD,kBAAU,iBAAiB,WAAW,CAAC,UAAU;AAC7C,cAAI;AACA,kBAAM,UAAU,KAAK,MAAM,MAAM,IAAI;AAErC,gBAAI,QAAQ,SAAS,qBAAqB,QAAQ,OAAO;AACrD,sBAAQ,IAAI,4BAA4B,QAAQ,OAAO,EAAE;AAGzD,sBAAQ,EAAE,OAAO,QAAQ,MAAM,CAAC;AAAA,YACpC,WAAW,QAAQ,SAAS,SAAS;AACjC,sBAAQ,MAAM,wBAAwB,QAAQ,OAAO,EAAE;AACvD,mBAAK,cAAc,gBAAgB,wBAAwB,QAAQ,OAAO,EAAE;AAC5E,qBAAO,IAAI,MAAM,QAAQ,OAAO,CAAC;AAAA,YACrC;AAAA,UACJ,SAAS,OAAO;AACZ,oBAAQ,MAAM,wCAAwC,MAAM,OAAO,EAAE;AACrE,iBAAK,cAAc,gBAAgB,+BAA+B;AAClE,mBAAO,KAAK;AAAA,UAChB;AAAA,QACJ,CAAC;AAGD,kBAAU,iBAAiB,SAAS,CAAC,UAAU;AAC3C,kBAAQ,MAAM,+BAA+B;AAC7C,eAAK,cAAc,gBAAgB,+BAA+B;AAClE,yBAAe,WAAW,KAAK,mBAAmB;AAClD,iBAAO,IAAI,MAAM,kBAAkB,CAAC;AAAA,QACxC,CAAC;AAGD,kBAAU,iBAAiB,SAAS,CAAC,UAAU;AAC3C,kBAAQ,IAAI,mCAAmC,MAAM,IAAI,IAAI,MAAM,MAAM,EAAE;AAE3E,cAAI,MAAM,SAAS,KAAM;AAErB,iBAAK,cAAc,gBAAgB,qBAAqB;AACxD,2BAAe,WAAW,KAAK,mBAAmB;AAClD,mBAAO,IAAI,MAAM,mBAAmB,CAAC;AAAA,UACzC;AAAA,QACJ,CAAC;AAAA,MACL,CAAC;AAAA,IACL;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,wBAAwB;AACpB,UAAI,CAAC,KAAK,QAAQ;AACd,gBAAQ,MAAM,yDAAyD;AACvE;AAAA,MACJ;AAGA,WAAK,OAAO,iBAAiB,QAAQ,MAAM;AACvC,aAAK,cAAc;AACnB,aAAK,qBAAqB;AAC1B,aAAK,cAAc,aAAa,gBAAgB,KAAK,cAAc,EAAE;AACrE,aAAK,oBAAoB,IAAI;AAC7B,gBAAQ,IAAI,+BAA+B;AAC3C,aAAK,yBAAyB;AAAA,MAClC,CAAC;AAGD,WAAK,OAAO,iBAAiB,SAAS,CAAC,UAAU;AAC7C,aAAK,cAAc;AACnB,gBAAQ,IAAI,sBAAsB,MAAM,IAAI,IAAI,MAAM,MAAM,EAAE;AAG9D,YAAI,MAAM,SAAS,KAAM;AACrB,eAAK,cAAc,gBAAgB,cAAc;AACjD,eAAK,oBAAoB,KAAK;AAC9B;AAAA,QACJ;AAGA,YAAI,KAAK,qBAAqB,KAAK,yBAAyB,KAAK,sBAAsB;AACnF,eAAK;AACL,gBAAM,QAAQ,KAAK,kBAAkB,KAAK;AAC1C,kBAAQ,IAAI,yBAAyB,KAAK,kBAAkB,IAAI,KAAK,qBAAqB,QAAQ,KAAK,OAAO;AAC9G,eAAK,cAAc,cAAc,iBAAiB,KAAK,kBAAkB,IAAI,KAAK,qBAAqB,MAAM;AAC7G,qBAAW,MAAM;AACb,iBAAK,QAAQ,KAAK,oBAAoB;AAAA,UAC1C,GAAG,KAAK;AACR;AAAA,QACJ;AAGA,aAAK,cAAc,gBAAgB,cAAc;AACjD,aAAK,oBAAoB,KAAK;AAC9B,aAAK,eAAe;AACpB,aAAK,gBAAgB;AACrB,aAAK,iBAAiB;AACtB,uBAAe,WAAW,KAAK,mBAAmB;AAAA,MACtD,CAAC;AAGD,WAAK,OAAO,iBAAiB,SAAS,MAAM;AAExC,YAAI,KAAK,qBAAqB,EAAG;AAEjC,gBAAQ,MAAM,iBAAiB;AAE/B,YAAI,KAAK,aAAa;AAClB,eAAK,cAAc,gBAAgB,2BAA2B;AAAA,QAClE,OAAO;AACH,eAAK,cAAc,gBAAgB,mBAAmB;AAAA,QAC1D;AAEA,uBAAe,WAAW,KAAK,mBAAmB;AAAA,MACtD,CAAC;AAGD,WAAK,OAAO,iBAAiB,WAAW,CAAC,UAAU;AAC/C,YAAI;AACA,gBAAM,UAAU,KAAK,MAAM,MAAM,IAAI;AACrC,eAAK,qBAAqB,OAAO;AAAA,QACrC,SAAS,OAAO;AACZ,kBAAQ,MAAM,0BAA0B,MAAM,OAAO,EAAE;AAAA,QAC3D;AAAA,MACJ,CAAC;AAAA,IACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,qBAAqB,SAAS;AAC1B,cAAQ,QAAQ,MAAM;AAAA,QAClB,KAAK;AACD,kBAAQ,IAAI,gBAAgB,QAAQ,OAAO,EAAE;AAC7C,eAAK,aAAa;AAAA,YACd,MAAM;AAAA,YACN,WAAW,UAAU;AAAA,YACrB,KAAK,OAAO,SAAS;AAAA,YACrB,UAAU,OAAO,SAAS;AAAA,YAC1B,UAAU,UAAU;AAAA,YACpB,aAAa,OAAO;AAAA,YACpB,cAAc,OAAO;AAAA,YACrB,WAAW,KAAK,IAAI;AAAA,UACxB,CAAC;AACD;AAAA,QAEJ,KAAK;AACD,kBAAQ,IAAI,gCAAgC,QAAQ,IAAI,EAAE;AAC1D;AAAA,QAEJ,KAAK;AACD,kBAAQ,IAAI,kCAAkC,QAAQ,IAAI,EAAE;AAC5D;AAAA,QAEJ,KAAK;AACD,kBAAQ,IAAI,oCAAoC,QAAQ,IAAI,EAAE;AAC9D;AAAA,QAEJ,KAAK;AAED,eAAK,gBAAgB,OAAO;AAC5B;AAAA,QAEJ,KAAK;AAED,eAAK,iBAAiB,OAAO;AAC7B;AAAA,QAEJ,KAAK;AAED,eAAK,oBAAoB,OAAO;AAChC;AAAA,QAEJ,KAAK;AAED,eAAK,6BAA6B,OAAO;AACzC;AAAA,QAEJ,KAAK;AAED,eAAK,eAAe,QAAQ,EAAE;AAC9B;AAAA,QAEJ,KAAK;AAED,eAAK,iBAAiB,QAAQ,EAAE;AAChC;AAAA,QAEJ,KAAK;AAED,eAAK,mBAAmB,QAAQ,EAAE;AAClC;AAAA,QAEJ,KAAK;AAED,eAAK,aAAa;AAAA,YACd,MAAM;AAAA,YACN,IAAI,QAAQ;AAAA,YACZ,WAAW,KAAK,IAAI;AAAA,UACxB,CAAC;AACD;AAAA,QAEJ,KAAK;AACD,eAAK,kBAAkB,OAAO;AAC9B;AAAA,QAEJ,KAAK;AACD,cAAI,QAAQ,QAAQ,KAAK,eAAe,IAAI,QAAQ,IAAI,GAAG;AACvD,iBAAK,eAAe,OAAO,QAAQ,IAAI;AACvC,iBAAK,gBAAgB,OAAO,QAAQ,IAAI;AACxC,iBAAK,oBAAoB;AACzB,iBAAK,iBAAiB;AACtB,oBAAQ,IAAI,2BAA2B,QAAQ,IAAI,EAAE;AAAA,UACzD;AACA;AAAA,QAEJ,KAAK;AACD,eAAK,eAAe,MAAM;AAC1B,eAAK,gBAAgB,MAAM;AAC3B,eAAK,oBAAoB;AACzB,eAAK,iBAAiB;AACtB,kBAAQ,IAAI,6BAA6B;AACzC;AAAA,QAEJ,KAAK;AACD,eAAK,aAAa;AAAA,YACd,IAAI,QAAQ;AAAA,YACZ,MAAM;AAAA,YACN,WAAW,UAAU;AAAA,YACrB,KAAK,OAAO,SAAS;AAAA,YACrB,UAAU,OAAO,SAAS;AAAA,YAC1B,UAAU,UAAU;AAAA,YACpB,aAAa,OAAO;AAAA,YACpB,cAAc,OAAO;AAAA,YACrB,WAAW,KAAK,IAAI;AAAA,UACxB,CAAC;AACD;AAAA,QAEJ,KAAK;AACD,cAAI,QAAQ,QAAQ,UAAU,WAAW;AACrC,sBAAU,UAAU,UAAU,QAAQ,IAAI,EAAE,KAAK,MAAM;AACnD,sBAAQ,IAAI,+BAA+B;AAAA,YAC/C,CAAC,EAAE,MAAM,SAAO;AACZ,sBAAQ,MAAM,mCAAmC,GAAG;AAAA,YACxD,CAAC;AAAA,UACL;AACA;AAAA,QAEJ,KAAK;AACD,kBAAQ,MAAM,iBAAiB,QAAQ,OAAO,EAAE;AAChD;AAAA,QAEJ;AACI,kBAAQ,KAAK,yBAAyB,QAAQ,IAAI,EAAE;AAAA,MAC5D;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,kBAAkB,SAAS;AACvB,YAAM,EAAC,IAAI,MAAM,aAAa,MAAM,WAAU,IAAI;AAClD,UAAI;AACA,YAAI,QAAQ,CAAC;AACb,YAAI,WAAY,SAAQ,KAAK,MAAM,UAAU;AAC7C,cAAM,SAAS,EAAE,MAAM,UAAU,YAAY,MAAM;AACnD,cAAM,KAAK,IAAI,SAAS,QAAQ,IAAI;AACpC,aAAK,aAAa,MAAM,aAAa,QAAQ,EAAE;AAC/C,aAAK,aAAa;AAAA,UACd;AAAA,UACA,MAAM;AAAA,UACN,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,gBAAgB,IAAI,4BAA4B,CAAC,EAAE;AAAA,QACjG,CAAC;AACD,gBAAQ,IAAI,0BAA0B,IAAI,EAAE;AAAA,MAChD,SAAS,GAAG;AACR,aAAK,aAAa;AAAA,UACd;AAAA,UACA,MAAM;AAAA,UACN,OAAO,8BAA8B,EAAE,OAAO;AAAA,QAClD,CAAC;AAAA,MACL;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,gBAAgB,SAAS;AACrB,YAAM,EAAC,IAAI,MAAM,WAAW,KAAI,IAAI;AAEpC,cAAQ,IAAI,cAAc,IAAI,eAAe,IAAI;AAEjD,UAAI,CAAC,KAAK,eAAe,IAAI,IAAI,GAAG;AAChC,aAAK,aAAa;AAAA,UACd;AAAA,UACA,MAAM;AAAA,UACN,OAAO,mBAAmB,IAAI;AAAA,QAClC,CAAC;AACD;AAAA,MACJ;AAGA,UAAI;AACA,cAAM,UAAU,KAAK,eAAe,IAAI,IAAI;AAG5C,cAAM,aAAa,CAAC,QAAQ;AACxB,cAAI,OAAO,IAAI,WAAW,MAAM,QAAQ,IAAI,OAAO,EAAG,QAAO;AAC7D,gBAAM,OAAO,OAAO,QAAQ,WAAW,MAAM,KAAK,UAAU,GAAG;AAC/D,iBAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,EAAE;AAAA,QAC/C;AAGA,cAAM,SAAS,QAAQ,QAAQ,IAAI;AAGnC,YAAI,kBAAkB,SAAS;AAC3B,iBACK,KAAK,oBAAkB;AACpB,iBAAK,aAAa;AAAA,cACd;AAAA,cACA,MAAM;AAAA,cACN,QAAQ,WAAW,cAAc;AAAA,YACrC,CAAC;AAAA,UACL,CAAC,EACA,MAAM,WAAS;AACZ,iBAAK,aAAa;AAAA,cACd;AAAA,cACA,MAAM;AAAA,cACN,OAAO,MAAM,WAAW;AAAA,YAC5B,CAAC;AAAA,UACL,CAAC;AAAA,QACT,OAAO;AAEH,eAAK,aAAa;AAAA,YACd;AAAA,YACA,MAAM;AAAA,YACN,QAAQ,WAAW,MAAM;AAAA,UAC7B,CAAC;AAAA,QACL;AAEA,gBAAQ,IAAI,0BAA0B,IAAI,EAAE;AAAA,MAChD,SAAS,OAAO;AACZ,aAAK,aAAa;AAAA,UACd;AAAA,UACA,MAAM;AAAA,UACN,OAAO,MAAM,WAAW;AAAA,QAC5B,CAAC;AACD,gBAAQ,MAAM,yBAAyB,KAAK;AAAA,MAChD;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,iBAAiB,SAAS;AACtB,YAAM,EAAC,IAAI,MAAM,WAAW,KAAI,IAAI;AAEpC,cAAQ,IAAI,mBAAmB,IAAI,eAAe,IAAI;AAEtD,UAAI,CAAC,KAAK,iBAAiB,IAAI,IAAI,GAAG;AAClC,aAAK,aAAa;AAAA,UACd;AAAA,UACA,MAAM;AAAA,UACN,OAAO,qBAAqB,IAAI;AAAA,QACpC,CAAC;AACD;AAAA,MACJ;AAGA,UAAI;AACA,cAAM,YAAY,KAAK,iBAAiB,IAAI,IAAI;AAGhD,cAAM,SAAS,UAAU,QAAQ,IAAI;AAGrC,YAAI,kBAAkB,SAAS;AAC3B,iBACK,KAAK,oBAAkB;AACpB,iBAAK,aAAa;AAAA,cACd;AAAA,cACA,MAAM;AAAA,cACN,QAAQ;AAAA,YACZ,CAAC;AAAA,UACL,CAAC,EACA,MAAM,WAAS;AACZ,iBAAK,aAAa;AAAA,cACd;AAAA,cACA,MAAM;AAAA,cACN,OAAO,MAAM,WAAW;AAAA,YAC5B,CAAC;AAAA,UACL,CAAC;AAAA,QACT,OAAO;AAEH,eAAK,aAAa;AAAA,YACd;AAAA,YACA,MAAM;AAAA,YACN;AAAA,UACJ,CAAC;AAAA,QACL;AAEA,gBAAQ,IAAI,4BAA4B,IAAI,EAAE;AAAA,MAClD,SAAS,OAAO;AACZ,aAAK,aAAa;AAAA,UACd;AAAA,UACA,MAAM;AAAA,UACN,OAAO,MAAM,WAAW;AAAA,QAC5B,CAAC;AACD,gBAAQ,MAAM,2BAA2B,KAAK;AAAA,MAClD;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,oBAAoB,SAAS;AACzB,YAAM,EAAC,IAAI,IAAG,IAAI;AAElB,cAAQ,IAAI,qBAAqB,GAAG,EAAE;AAGtC,UAAI,cAAc;AAGlB,iBAAW,YAAY,KAAK,mBAAmB,OAAO,GAAG;AACrD,YAAI,CAAC,SAAS,cAAc,SAAS,QAAQ,KAAK;AAC9C,wBAAc;AACd;AAAA,QACJ;AAAA,MACJ;AAGA,UAAI,CAAC,aAAa;AACd,mBAAW,YAAY,KAAK,mBAAmB,OAAO,GAAG;AACrD,cAAI,SAAS,YAAY;AAErB,kBAAM,iBAAiB,SAAS,YAAY,MAAM,GAAG,EAAE,CAAC;AACxD,gBAAI,IAAI,WAAW,cAAc,GAAG;AAChC,4BAAc;AACd;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAEA,UAAI,CAAC,aAAa;AACd,aAAK,aAAa;AAAA,UACd;AAAA,UACA,MAAM;AAAA,UACN,OAAO,sCAAsC,GAAG;AAAA,QACpD,CAAC;AACD;AAAA,MACJ;AAGA,UAAI;AAEA,cAAM,SAAS,YAAY,QAAQ,GAAG;AAGtC,YAAI,kBAAkB,SAAS;AAC3B,iBACK,KAAK,oBAAkB;AACpB,iBAAK,aAAa;AAAA,cACd;AAAA,cACA,MAAM;AAAA,cACN,QAAQ;AAAA,YACZ,CAAC;AAAA,UACL,CAAC,EACA,MAAM,WAAS;AACZ,iBAAK,aAAa;AAAA,cACd;AAAA,cACA,MAAM;AAAA,cACN,OAAO,MAAM,WAAW;AAAA,YAC5B,CAAC;AAAA,UACL,CAAC;AAAA,QACT,OAAO;AAEH,eAAK,aAAa;AAAA,YACd;AAAA,YACA,MAAM;AAAA,YACN;AAAA,UACJ,CAAC;AAAA,QACL;AAEA,gBAAQ,IAAI,8BAA8B,GAAG,EAAE;AAAA,MACnD,SAAS,OAAO;AACZ,aAAK,aAAa;AAAA,UACd;AAAA,UACA,MAAM;AAAA,UACN,OAAO,MAAM,WAAW;AAAA,QAC5B,CAAC;AACD,gBAAQ,MAAM,wBAAwB,KAAK;AAAA,MAC/C;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,eAAe,WAAW;AACtB,YAAM,YAAY,MAAM,KAAK,KAAK,eAAe,OAAO,CAAC,EAAE,IAAI,WAAS;AAAA,QACpE,MAAM,KAAK;AAAA,QACX,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,MACtB,EAAE;AAEF,WAAK,aAAa;AAAA,QACd,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,OAAO;AAAA,MACX,CAAC;AAED,cAAQ,IAAI,oBAAoB,UAAU,MAAM,QAAQ;AAAA,IAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,iBAAiB,WAAW;AACxB,YAAM,cAAc,MAAM,KAAK,KAAK,iBAAiB,OAAO,CAAC,EAAE,IAAI,aAAW;AAAA,QAC1E,MAAM,OAAO;AAAA,QACb,aAAa,OAAO;AAAA,QACpB,WAAW,OAAO;AAAA,MACtB,EAAE;AAEF,WAAK,aAAa;AAAA,QACd,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,MACb,CAAC;AAED,cAAQ,IAAI,sBAAsB,YAAY,MAAM,UAAU;AAAA,IAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,mBAAmB,WAAW;AAC1B,YAAM,YAAY,CAAC;AACnB,YAAM,oBAAoB,CAAC;AAG3B,WAAK,mBAAmB,QAAQ,CAAC,aAAa;AAC1C,YAAI,SAAS,YAAY;AACrB,4BAAkB,KAAK;AAAA,YACnB,MAAM,SAAS;AAAA,YACf,aAAa,SAAS;AAAA,YACtB,aAAa,SAAS;AAAA,YACtB,UAAU,SAAS;AAAA,UACvB,CAAC;AAAA,QACL,OAAO;AACH,oBAAU,KAAK;AAAA,YACX,MAAM,SAAS;AAAA,YACf,aAAa,SAAS;AAAA,YACtB,KAAK,SAAS;AAAA,YACd,UAAU,SAAS;AAAA,UACvB,CAAC;AAAA,QACL;AAAA,MACJ,CAAC;AAED,WAAK,aAAa;AAAA,QACd,IAAI;AAAA,QACJ,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACJ,CAAC;AAED,cAAQ,IAAI,wBAAwB,UAAU,MAAM,eAAe,kBAAkB,MAAM,YAAY;AAAA,IAC3G;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,aAAa,SAAS;AAClB,UAAI,CAAC,KAAK,eAAe,CAAC,KAAK,QAAQ;AACnC,gBAAQ,MAAM,oCAAoC;AAClD;AAAA,MACJ;AAEA,UAAI;AAEA,aAAK,OAAO,KAAK,KAAK,UAAU,OAAO,CAAC;AACxC,eAAO,QAAQ,QAAQ;AAAA,MAC3B,SAAS,OAAO;AACZ,gBAAQ,MAAM,0BAA0B,MAAM,OAAO,EAAE;AACvD,eAAO,QAAQ,OAAO,KAAK;AAAA,MAC/B;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,2BAA2B;AACvB,UAAI,CAAC,KAAK,YAAa;AAGvB,WAAK,kBAAkB,oBAAI,IAAI;AAC/B,WAAK,oBAAoB,oBAAI,IAAI;AACjC,WAAK,sBAAsB,oBAAI,IAAI;AAGnC,WAAK,eAAe,QAAQ,CAAC,MAAM,SAAS;AACxC,aAAK,aAAa;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,aAAa,KAAK;AAAA,UAClB,aAAa,KAAK;AAAA,QACtB,CAAC;AAED,aAAK,gBAAgB,IAAI,IAAI;AAC7B,gBAAQ,IAAI,iCAAiC,IAAI,EAAE;AAAA,MACvD,CAAC;AAGD,WAAK,iBAAiB,QAAQ,CAAC,QAAQ,SAAS;AAC5C,aAAK,aAAa;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,aAAa,OAAO;AAAA,UACpB,WAAW,OAAO;AAAA,QACtB,CAAC;AAED,aAAK,kBAAkB,IAAI,IAAI;AAC/B,gBAAQ,IAAI,mCAAmC,IAAI,EAAE;AAAA,MACzD,CAAC;AAGD,WAAK,mBAAmB,QAAQ,CAAC,UAAU,SAAS;AAChD,aAAK,aAAa;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,aAAa,SAAS;AAAA,UACtB,KAAK,SAAS;AAAA,UACd,aAAa,SAAS;AAAA,UACtB,YAAY,SAAS;AAAA,UACrB,UAAU,SAAS;AAAA,QACvB,CAAC;AAED,aAAK,oBAAoB,IAAI,IAAI;AACjC,gBAAQ,IAAI,qCAAqC,IAAI,EAAE;AAAA,MAC3D,CAAC;AAAA,IACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,aAAa,MAAM,aAAa,QAAQ,WAAW;AAC/C,UAAI,CAAC,MAAM;AACP,gBAAQ,MAAM,uBAAuB;AACrC;AAAA,MACJ;AAGA,WAAK,eAAe,IAAI,MAAM;AAAA,QAC1B;AAAA,QACA,aAAa,eAAe,SAAS,IAAI;AAAA,QACzC,SAAS,aAAa,SAAU,MAAM;AAClC,iBAAO,6BAA6B,IAAI,eAAe,KAAK,UAAU,IAAI,CAAC;AAAA,QAC/E;AAAA,QACA,aAAa,UAAU;AAAA,UACnB,MAAM;AAAA,UACN,YAAY,CAAC;AAAA,QACjB;AAAA,MACJ,CAAC;AAGD,UAAI,KAAK,aAAa;AAClB,aAAK,aAAa;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,aAAa,eAAe,SAAS,IAAI;AAAA,UACzC,aAAa,UAAU;AAAA,YACnB,MAAM;AAAA,YACN,YAAY,CAAC;AAAA,UACjB;AAAA,QACJ,CAAC;AAED,aAAK,gBAAgB,IAAI,IAAI;AAAA,MACjC;AAGA,WAAK,oBAAoB;AAGzB,WAAK,iBAAiB;AACtB,cAAQ,IAAI,oBAAoB,IAAI,EAAE;AAAA,IAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,eAAe,MAAM;AACjB,UAAI,CAAC,MAAM;AACP,gBAAQ,MAAM,uBAAuB;AACrC;AAAA,MACJ;AAEA,UAAI,CAAC,KAAK,eAAe,IAAI,IAAI,GAAG;AAChC,gBAAQ,KAAK,mBAAmB,IAAI,EAAE;AACtC;AAAA,MACJ;AAEA,WAAK,eAAe,OAAO,IAAI;AAE/B,UAAI,KAAK,aAAa;AAClB,aAAK,aAAa;AAAA,UACd,MAAM;AAAA,UACN;AAAA,QACJ,CAAC;AAAA,MACL;AAEA,WAAK,gBAAgB,OAAO,IAAI;AAChC,WAAK,oBAAoB;AACzB,WAAK,iBAAiB;AACtB,cAAQ,IAAI,sBAAsB,IAAI,EAAE;AAAA,IAC5C;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,qBAAqB;AACjB,UAAI,KAAK,eAAe,SAAS,EAAG;AAEpC,WAAK,eAAe,MAAM;AAC1B,WAAK,gBAAgB,MAAM;AAE3B,UAAI,KAAK,aAAa;AAClB,aAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAAA,MACpD;AAEA,WAAK,oBAAoB;AACzB,WAAK,iBAAiB;AACtB,cAAQ,IAAI,wBAAwB;AAAA,IACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,eAAe,MAAM,aAAa,YAAY,WAAW;AACrD,UAAI,CAAC,MAAM;AACP,gBAAQ,MAAM,yBAAyB;AACvC;AAAA,MACJ;AAGA,WAAK,iBAAiB,IAAI,MAAM;AAAA,QAC5B;AAAA,QACA,aAAa,eAAe,WAAW,IAAI;AAAA,QAC3C,SAAS,aAAa,SAAU,MAAM;AAClC,iBAAO;AAAA,YACH,UAAU,CAAC;AAAA,cACP,MAAM;AAAA,cACN,SAAS;AAAA,gBACL,MAAM;AAAA,gBACN,MAAM,oCAAoC,IAAI,eAAe,KAAK,UAAU,IAAI,CAAC;AAAA,cACrF;AAAA,YACJ,CAAC;AAAA,UACL;AAAA,QACJ;AAAA,QACA,WAAW,cAAc,CAAC;AAAA,MAC9B,CAAC;AAGD,UAAI,KAAK,aAAa;AAClB,aAAK,aAAa;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,aAAa,eAAe,WAAW,IAAI;AAAA,UAC3C,WAAW,cAAc,CAAC;AAAA,QAC9B,CAAC;AAED,aAAK,kBAAkB,IAAI,IAAI;AAAA,MACnC;AAGA,WAAK,oBAAoB;AAGzB,WAAK,mBAAmB;AACxB,cAAQ,IAAI,sBAAsB,IAAI,EAAE;AAAA,IAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,iBAAiB,MAAM;AACnB,UAAI,CAAC,MAAM;AACP,gBAAQ,MAAM,yBAAyB;AACvC;AAAA,MACJ;AAEA,UAAI,CAAC,KAAK,iBAAiB,IAAI,IAAI,GAAG;AAClC,gBAAQ,KAAK,qBAAqB,IAAI,EAAE;AACxC;AAAA,MACJ;AAEA,WAAK,iBAAiB,OAAO,IAAI;AAEjC,UAAI,KAAK,aAAa;AAClB,aAAK,aAAa;AAAA,UACd,MAAM;AAAA,UACN;AAAA,QACJ,CAAC;AAAA,MACL;AAEA,WAAK,kBAAkB,OAAO,IAAI;AAClC,WAAK,oBAAoB;AACzB,WAAK,mBAAmB;AACxB,cAAQ,IAAI,wBAAwB,IAAI,EAAE;AAAA,IAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,iBAAiB,MAAM,aAAa,SAAS,WAAW;AACpD,UAAI,CAAC,MAAM;AACP,gBAAQ,MAAM,2BAA2B;AACzC;AAAA,MACJ;AAEA,UAAI,CAAC,QAAQ,OAAO,CAAC,QAAQ,aAAa;AACtC,gBAAQ,MAAM,sDAAsD;AACpE;AAAA,MACJ;AAEA,YAAM,aAAa,CAAC,CAAC,QAAQ;AAG7B,WAAK,mBAAmB,IAAI,MAAM;AAAA,QAC9B;AAAA,QACA,aAAa,eAAe,aAAa,IAAI;AAAA,QAC7C,KAAK,QAAQ;AAAA,QACb,aAAa,QAAQ;AAAA,QACrB;AAAA,QACA,UAAU,QAAQ;AAAA,QAClB,SAAS,aAAa,SAAU,KAAK;AACjC,iBAAO;AAAA,YACH,UAAU,CAAC;AAAA,cACP;AAAA,cACA,MAAM,sCAAsC,IAAI,aAAa,GAAG;AAAA,cAChE,UAAU,QAAQ,YAAY;AAAA,YAClC,CAAC;AAAA,UACL;AAAA,QACJ;AAAA,MACJ,CAAC;AAGD,UAAI,KAAK,aAAa;AAClB,aAAK,aAAa;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,aAAa,eAAe,aAAa,IAAI;AAAA,UAC7C,KAAK,QAAQ;AAAA,UACb,aAAa,QAAQ;AAAA,UACrB;AAAA,UACA,UAAU,QAAQ;AAAA,QACtB,CAAC;AAED,aAAK,oBAAoB,IAAI,IAAI;AAAA,MACrC;AAGA,WAAK,oBAAoB;AAGzB,WAAK,qBAAqB;AAC1B,cAAQ,IAAI,wBAAwB,IAAI,EAAE;AAAA,IAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,mBAAmB,MAAM;AACrB,UAAI,CAAC,MAAM;AACP,gBAAQ,MAAM,2BAA2B;AACzC;AAAA,MACJ;AAEA,UAAI,CAAC,KAAK,mBAAmB,IAAI,IAAI,GAAG;AACpC,gBAAQ,KAAK,uBAAuB,IAAI,EAAE;AAC1C;AAAA,MACJ;AAEA,WAAK,mBAAmB,OAAO,IAAI;AAEnC,UAAI,KAAK,aAAa;AAClB,aAAK,aAAa;AAAA,UACd,MAAM;AAAA,UACN;AAAA,QACJ,CAAC;AAAA,MACL;AAEA,WAAK,oBAAoB,OAAO,IAAI;AACpC,WAAK,oBAAoB;AACzB,WAAK,qBAAqB;AAC1B,cAAQ,IAAI,0BAA0B,IAAI,EAAE;AAAA,IAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,6BAA6B,SAAS;AAClC,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACJ,IAAI;AAEJ,cAAQ,IAAI,kCAAkC,UAAU,UAAU,CAAC,WAAW;AAG9E,YAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,aAAO,OAAO,MAAM,OAAO;AAAA,QACvB,UAAU;AAAA,QACV,KAAK;AAAA,QACL,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,iBAAiB;AAAA,QACjB,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,QAAQ;AAAA,MACZ,CAAC;AAGD,YAAM,eAAe,SAAS,cAAc,KAAK;AACjD,aAAO,OAAO,aAAa,OAAO;AAAA,QAC9B,iBAAiB;AAAA,QACjB,SAAS;AAAA,QACT,cAAc;AAAA,QACd,UAAU;AAAA,QACV,OAAO;AAAA,QACP,WAAW;AAAA,QACX,UAAU;AAAA,MACd,CAAC;AAGD,YAAM,SAAS,SAAS,cAAc,IAAI;AAC1C,aAAO,cAAc;AACrB,aAAO,OAAO,OAAO,OAAO;AAAA,QACxB,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAc;AAAA,MAClB,CAAC;AAGD,YAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,aAAO,OAAO,QAAQ,OAAO;AAAA,QACzB,cAAc;AAAA,QACd,WAAW;AAAA,QACX,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,iBAAiB;AAAA,MACrB,CAAC;AAGD,UAAI,YAAY,SAAS,SAAS,GAAG;AACjC,iBAAS,QAAQ,SAAO;AACpB,gBAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,iBAAO,OAAO,OAAO,OAAO;AAAA,YACxB,cAAc;AAAA,YACd,SAAS;AAAA,YACT,cAAc;AAAA,YACd,iBAAiB,IAAI,SAAS,SAAS,YAAY;AAAA,UACvD,CAAC;AAED,gBAAM,WAAW,SAAS,cAAc,QAAQ;AAChD,mBAAS,cAAc,IAAI,SAAS,SAAS,WAAW;AAExD,gBAAM,cAAc,SAAS,cAAc,MAAM;AACjD,cAAI,IAAI,QAAQ,SAAS,QAAQ;AAC7B,wBAAY,cAAc,IAAI,QAAQ;AAAA,UAC1C,WAAW,IAAI,QAAQ,SAAS,SAAS;AACrC,wBAAY,cAAc;AAAA,UAC9B;AAEA,iBAAO,YAAY,QAAQ;AAC3B,iBAAO,YAAY,WAAW;AAC9B,kBAAQ,YAAY,MAAM;AAAA,QAC9B,CAAC;AAAA,MACL,OAAO;AACH,gBAAQ,cAAc;AAAA,MAC1B;AAGA,UAAI,cAAc;AACd,cAAM,eAAe,SAAS,cAAc,KAAK;AACjD,eAAO,OAAO,aAAa,OAAO;AAAA,UAC9B,cAAc;AAAA,UACd,SAAS;AAAA,UACT,iBAAiB;AAAA,QACrB,CAAC;AAED,cAAM,iBAAiB,SAAS,cAAc,QAAQ;AACtD,uBAAe,cAAc;AAE7B,cAAM,mBAAmB,SAAS,cAAc,MAAM;AACtD,yBAAiB,cAAc;AAE/B,qBAAa,YAAY,cAAc;AACvC,qBAAa,YAAY,gBAAgB;AACzC,gBAAQ,YAAY,YAAY;AAAA,MACpC;AAGA,YAAM,gBAAgB,SAAS,cAAc,OAAO;AACpD,oBAAc,cAAc;AAC5B,aAAO,OAAO,cAAc,OAAO;AAAA,QAC/B,SAAS;AAAA,QACT,cAAc;AAAA,QACd,YAAY;AAAA,MAChB,CAAC;AAED,YAAM,gBAAgB,SAAS,cAAc,UAAU;AACvD,aAAO,OAAO,cAAc,OAAO;AAAA,QAC/B,OAAO;AAAA,QACP,WAAW;AAAA,QACX,SAAS;AAAA,QACT,cAAc;AAAA,QACd,WAAW;AAAA,MACf,CAAC;AAGD,YAAM,kBAAkB,SAAS,cAAc,KAAK;AACpD,aAAO,OAAO,gBAAgB,OAAO;AAAA,QACjC,SAAS;AAAA,QACT,gBAAgB;AAAA,MACpB,CAAC;AAED,YAAM,eAAe,SAAS,cAAc,QAAQ;AACpD,mBAAa,cAAc;AAC3B,aAAO,OAAO,aAAa,OAAO;AAAA,QAC9B,SAAS;AAAA,QACT,iBAAiB;AAAA,QACjB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,QAAQ;AAAA,MACZ,CAAC;AAED,YAAM,eAAe,SAAS,cAAc,QAAQ;AACpD,mBAAa,cAAc;AAC3B,aAAO,OAAO,aAAa,OAAO;AAAA,QAC9B,SAAS;AAAA,QACT,iBAAiB;AAAA,QACjB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,QAAQ;AAAA,MACZ,CAAC;AAGD,sBAAgB,YAAY,YAAY;AACxC,sBAAgB,YAAY,YAAY;AAExC,mBAAa,YAAY,MAAM;AAC/B,mBAAa,YAAY,OAAO;AAChC,mBAAa,YAAY,aAAa;AACtC,mBAAa,YAAY,aAAa;AACtC,mBAAa,YAAY,eAAe;AAExC,YAAM,YAAY,YAAY;AAC9B,eAAS,KAAK,YAAY,KAAK;AAG/B,oBAAc,MAAM;AAGpB,mBAAa,iBAAiB,SAAS,MAAM;AACzC,cAAM,eAAe,cAAc,MAAM,KAAK;AAC9C,YAAI,cAAc;AAEd,eAAK,aAAa;AAAA,YACd;AAAA,YACA,MAAM;AAAA,YACN,QAAQ;AAAA,cACJ,OAAO;AAAA,cACP,MAAM;AAAA,cACN,SAAS;AAAA,gBACL,MAAM;AAAA,gBACN,MAAM;AAAA,cACV;AAAA,YACJ;AAAA,UACJ,CAAC;AAGD,mBAAS,KAAK,YAAY,KAAK;AAAA,QACnC,OAAO;AACH,gBAAM,yBAAyB;AAAA,QACnC;AAAA,MACJ,CAAC;AAED,mBAAa,iBAAiB,SAAS,MAAM;AAEzC,aAAK,aAAa;AAAA,UACd;AAAA,UACA,MAAM;AAAA,UACN,OAAO;AAAA,QACX,CAAC;AAGD,iBAAS,KAAK,YAAY,KAAK;AAAA,MACnC,CAAC;AAAA,IACL;AAAA,EACJ;AAGA,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,YAAY,aAAa;AACxE,WAAO,UAAU;AAAA,EACrB;", "names": ["connectionInfo"] } diff --git a/src/webmcp.js b/src/webmcp.js index 5525195..a3a3f64 100644 --- a/src/webmcp.js +++ b/src/webmcp.js @@ -34,6 +34,10 @@ class WebMCP { this.registeredTools = new Set(); this.registeredPrompts = new Set(); this.registeredResources = new Set(); + this._reconnectAttempts = 0; + this._maxReconnectAttempts = 3; + this._reconnectDelay = 1000; + this._lastConnectionToken = null; // Storage keys for sessionStorage this.SESSION_STORAGE_KEY = 'webmcp_token'; @@ -924,6 +928,9 @@ class WebMCP { return; } + // Store for reconnection attempts + this._lastConnectionToken = connectionToken; + // Update UI to show connecting state this._updateStatus('connecting', 'Connecting...'); @@ -1137,6 +1144,7 @@ class WebMCP { // Set up socket open handler this.socket.addEventListener('open', () => { this.isConnected = true; + this._reconnectAttempts = 0; this._updateStatus('connected', `Connected to ${this.currentChannel}`); this._updateConnectionUI(true); console.log('WebMCP connection established'); @@ -1146,22 +1154,41 @@ class WebMCP { // Set up socket close handler this.socket.addEventListener('close', (event) => { this.isConnected = false; - this._updateStatus('disconnected', 'Disconnected'); - this._updateConnectionUI(false); console.log(`Connection closed: ${event.code} ${event.reason}`); - // Check if it was an authorization error - if (event.code === 1001 || event.code === 401) { - this._updateStatus('disconnected', 'Authorization failed'); - this.currentToken = ''; - this.currentServer = ''; - this.currentChannel = ''; - sessionStorage.removeItem(this.SESSION_STORAGE_KEY); + // Normal closure — no retry + if (event.code === 1000) { + this._updateStatus('disconnected', 'Disconnected'); + this._updateConnectionUI(false); + return; } + + // Abnormal closure — try to reconnect + if (this._reconnectAttempts < this._maxReconnectAttempts && this._lastConnectionToken) { + this._reconnectAttempts++; + const delay = this._reconnectDelay * this._reconnectAttempts; + console.log(`Reconnecting (attempt ${this._reconnectAttempts}/${this._maxReconnectAttempts}) in ${delay}ms...`); + this._updateStatus('connecting', `Reconectando (${this._reconnectAttempts}/${this._maxReconnectAttempts})...`); + setTimeout(() => { + this.connect(this._lastConnectionToken); + }, delay); + return; + } + + // Max retries exceeded or no token — give up + this._updateStatus('disconnected', 'Disconnected'); + this._updateConnectionUI(false); + this.currentToken = ''; + this.currentServer = ''; + this.currentChannel = ''; + sessionStorage.removeItem(this.SESSION_STORAGE_KEY); }); // Set up socket error handler this.socket.addEventListener('error', () => { + // Suppress noisy errors during reconnection attempts + if (this._reconnectAttempts > 0) return; + console.error('WebSocket error'); if (this.isConnected) {