maquito-chat-plugin 1.1.2 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -252,6 +252,14 @@ class IntelligentChatPluginComponent {
|
|
|
252
252
|
}, ...(ngDevMode ? [{ debugName: "sanitizedModalUrl" }] : []));
|
|
253
253
|
ngOnInit() {
|
|
254
254
|
window.addEventListener('storage', this.storageListener);
|
|
255
|
+
// Self-heal: always reset transient state on init to prevent
|
|
256
|
+
// corrupted sessions from freezing the page
|
|
257
|
+
this.isLoading.set(false);
|
|
258
|
+
this.pipelineStep = '';
|
|
259
|
+
this.isExpanded.set(false);
|
|
260
|
+
this.setHostScrollLock(false);
|
|
261
|
+
this.currentSubscription?.unsubscribe();
|
|
262
|
+
this.currentSubscription = undefined;
|
|
255
263
|
}
|
|
256
264
|
ngOnDestroy() {
|
|
257
265
|
window.removeEventListener('storage', this.storageListener);
|
|
@@ -308,6 +316,7 @@ class IntelligentChatPluginComponent {
|
|
|
308
316
|
if (!this.isOpen()) {
|
|
309
317
|
this.isExpanded.set(false);
|
|
310
318
|
this.setHostScrollLock(false);
|
|
319
|
+
this.cancelQuery();
|
|
311
320
|
}
|
|
312
321
|
if (this.isOpen())
|
|
313
322
|
this.shouldScroll = true;
|
|
@@ -558,9 +567,13 @@ class IntelligentChatPluginComponent {
|
|
|
558
567
|
if (!text)
|
|
559
568
|
return '';
|
|
560
569
|
try {
|
|
561
|
-
|
|
570
|
+
// Safety valve: if text is extremely long, skip regex-heavy preprocessing
|
|
571
|
+
// to avoid catastrophic backtracking that freezes the browser
|
|
572
|
+
let preprocessed = text.length < 100_000 ? this.preprocessMarkdownTable(text) : text;
|
|
562
573
|
// Encode spaces in markdown image & link URLs:  and [text](url)
|
|
563
|
-
|
|
574
|
+
if (preprocessed.length < 100_000) {
|
|
575
|
+
preprocessed = preprocessed.replace(/(!?\[[^\]]*\])\(([^)]+)\)/g, (_match, bracket, url) => `${bracket}(${url.replace(/ /g, '%20')})`);
|
|
576
|
+
}
|
|
564
577
|
let html = marked.parse(preprocessed, { breaks: true });
|
|
565
578
|
// Inject inline styles + onerror on <img> to force small thumbnails & hide broken ones
|
|
566
579
|
const imgStyle = `style="max-height:48px;max-width:100px;object-fit:contain;border-radius:6px;cursor:pointer;display:inline-block;vertical-align:middle;margin:2px 4px;border:1px solid rgba(255,255,255,0.15);box-shadow:0 1px 3px rgba(0,0,0,0.2);"`;
|
|
@@ -700,7 +713,14 @@ class IntelligentChatPluginComponent {
|
|
|
700
713
|
return;
|
|
701
714
|
}
|
|
702
715
|
const data = JSON.parse(raw);
|
|
703
|
-
|
|
716
|
+
// Validate data is an array of valid message objects
|
|
717
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
718
|
+
this.messages.set([]);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
const msgs = data
|
|
722
|
+
.filter(m => m && typeof m.text === 'string' && typeof m.sender === 'string')
|
|
723
|
+
.map(m => ({
|
|
704
724
|
...m,
|
|
705
725
|
timestamp: new Date(m.timestamp)
|
|
706
726
|
}));
|
|
@@ -709,6 +729,11 @@ class IntelligentChatPluginComponent {
|
|
|
709
729
|
this.shouldScroll = true;
|
|
710
730
|
}
|
|
711
731
|
catch {
|
|
732
|
+
// Corrupted session data — wipe it and start fresh
|
|
733
|
+
try {
|
|
734
|
+
localStorage.removeItem(this.sessionKey);
|
|
735
|
+
}
|
|
736
|
+
catch { /* ignore */ }
|
|
712
737
|
this.messages.set([]);
|
|
713
738
|
}
|
|
714
739
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"maquito-chat-plugin.mjs","sources":["../../../frontend/maquito-chat-plugin/src/lib/intelligent-chat.service.ts","../../../frontend/maquito-chat-plugin/src/lib/intelligent-chat-plugin.component.ts","../../../frontend/maquito-chat-plugin/src/public-api.ts","../../../frontend/maquito-chat-plugin/src/maquito-chat-plugin.ts"],"sourcesContent":["import { Injectable, inject } from '@angular/core';\r\nimport { HttpClient, HttpHeaders } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\n\r\n/**\r\n * Standalone HTTP service for the Maquito Chat Plugin.\r\n * Decoupled from any host app service — uses apiUrl + token from config.\r\n * Replicates exactly the same endpoints used by the Maquito Core API.\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class IntelligentChatService {\r\n\r\n private http = inject(HttpClient);\r\n\r\n /**\r\n * Execute an intelligent query (POST /api/query).\r\n * Auth via X-Api-Key header.\r\n */\r\n executeIntelligentQuery(\r\n apiUrl: string,\r\n token: string,\r\n systemId: string,\r\n question: string,\r\n conversationHistory: { role: string; content: string }[] = [],\r\n baseContext?: string,\r\n skipPatternCache?: boolean,\r\n preferTableFormat?: boolean,\r\n userName?: string,\r\n personality?: string\r\n ): Observable<any> {\r\n const headers = this.buildHeaders(token);\r\n const body: any = { systemId, question, conversationHistory };\r\n if (baseContext) body.baseContext = baseContext;\r\n if (skipPatternCache) body.skipPatternCache = skipPatternCache;\r\n if (preferTableFormat !== undefined) body.preferTableFormat = preferTableFormat;\r\n if (userName) body.userName = userName;\r\n if (personality) body.personality = personality;\r\n return this.http.post<any>(`${apiUrl}/query`, body, { headers });\r\n }\r\n\r\n /**\r\n * Execute an intelligent query with SSE streaming progress.\r\n * Emits: { type: 'progress', step: string, message: string }\r\n * { type: 'result', data: any }\r\n */\r\n executeIntelligentQueryStream(\r\n apiUrl: string,\r\n token: string,\r\n systemId: string,\r\n question: string,\r\n conversationHistory: { role: string; content: string }[] = [],\r\n baseContext?: string,\r\n skipPatternCache?: boolean,\r\n preferTableFormat?: boolean,\r\n userName?: string,\r\n personality?: string\r\n ): Observable<{ type: 'progress' | 'result'; step?: string; message?: string; data?: any }> {\r\n const body: any = { systemId, question, conversationHistory };\r\n if (baseContext) body.baseContext = baseContext;\r\n if (skipPatternCache) body.skipPatternCache = skipPatternCache;\r\n if (preferTableFormat !== undefined) body.preferTableFormat = preferTableFormat;\r\n if (userName) body.userName = userName;\r\n if (personality) body.personality = personality;\r\n\r\n const FETCH_TIMEOUT_MS = 120_000; // 2 min max for the entire request\r\n const INACTIVITY_TIMEOUT_MS = 60_000; // 60s without data = abort\r\n\r\n return new Observable(observer => {\r\n const abortController = new AbortController();\r\n\r\n // Combine user abort + global timeout\r\n let signal: AbortSignal;\r\n if (typeof AbortSignal.any === 'function') {\r\n signal = AbortSignal.any([abortController.signal, AbortSignal.timeout(FETCH_TIMEOUT_MS)]);\r\n } else {\r\n // Fallback for older browsers\r\n signal = abortController.signal;\r\n setTimeout(() => abortController.abort(), FETCH_TIMEOUT_MS);\r\n }\r\n\r\n fetch(`${apiUrl}/query/stream`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json', 'X-Api-Key': token },\r\n body: JSON.stringify(body),\r\n signal\r\n }).then(async response => {\r\n if (!response.ok || !response.body) {\r\n observer.error(new Error(`HTTP ${response.status}`));\r\n return;\r\n }\r\n const reader = response.body.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = '';\r\n let lastDataTime = Date.now();\r\n\r\n while (true) {\r\n // Race reader vs inactivity timeout\r\n const readPromise = reader.read();\r\n const timeoutPromise = new Promise<never>((_, reject) => {\r\n const elapsed = Date.now() - lastDataTime;\r\n const remaining = Math.max(INACTIVITY_TIMEOUT_MS - elapsed, 100);\r\n setTimeout(() => reject(new Error('SSE inactivity timeout: no data received for 60s')), remaining);\r\n });\r\n\r\n let result: ReadableStreamReadResult<Uint8Array>;\r\n try {\r\n result = await Promise.race([readPromise, timeoutPromise]);\r\n } catch (err) {\r\n reader.cancel();\r\n abortController.abort();\r\n observer.error(err);\r\n return;\r\n }\r\n\r\n const { done, value } = result;\r\n if (done) break;\r\n lastDataTime = Date.now();\r\n buffer += decoder.decode(value, { stream: true });\r\n\r\n const parts = buffer.split('\\n\\n');\r\n buffer = parts.pop() || '';\r\n for (const part of parts) {\r\n const lines = part.split('\\n');\r\n let eventType = '';\r\n let eventData = '';\r\n for (const line of lines) {\r\n if (line.startsWith('event: ')) eventType = line.slice(7);\r\n else if (line.startsWith('data: ')) eventData = line.slice(6);\r\n }\r\n if (!eventType || !eventData) continue;\r\n try {\r\n const parsed = JSON.parse(eventData);\r\n if (eventType === 'progress') {\r\n observer.next({ type: 'progress', step: parsed.step, message: parsed.message });\r\n } else if (eventType === 'result') {\r\n observer.next({ type: 'result', data: parsed });\r\n observer.complete();\r\n } else if (eventType === 'error') {\r\n observer.error(parsed);\r\n }\r\n } catch { /* skip malformed JSON */ }\r\n }\r\n }\r\n if (!observer.closed) observer.complete();\r\n }).catch(err => {\r\n if (err.name !== 'AbortError') observer.error(err);\r\n });\r\n\r\n return () => abortController.abort();\r\n });\r\n }\r\n\r\n /**\r\n * Standard orchestration ask (POST /api/cortex/ask).\r\n * Used when intelligent query mode is disabled.\r\n */\r\n ask(apiUrl: string, token: string, text: string): Observable<any> {\r\n const headers = this.buildHeaders(token);\r\n return this.http.post<any>(`${apiUrl}/cortex/ask`, { text }, { headers });\r\n }\r\n\r\n private buildHeaders(token: string): HttpHeaders {\r\n return new HttpHeaders({ 'X-Api-Key': token });\r\n }\r\n}\r\n","import {\r\n Component, Input, inject, signal, computed, ViewChild, ElementRef,\r\n AfterViewChecked, OnChanges, OnInit, OnDestroy, SimpleChanges, HostListener\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { DomSanitizer, SafeHtml, SafeResourceUrl } from '@angular/platform-browser';\r\nimport { marked } from 'marked';\r\nimport { Subscription } from 'rxjs';\r\nimport { IntelligentChatConfig, ChatMessage, PluginTheme } from './intelligent-chat.models';\r\nimport { IntelligentChatService } from './intelligent-chat.service';\r\n\r\n@Component({\r\n selector: 'intelligent-chat-plugin',\r\n standalone: true,\r\n imports: [CommonModule, FormsModule],\r\n template: `\r\n <!-- Host theme overrides -->\r\n <div class=\"iq-theme-host\" [ngStyle]=\"themeStyles()\">\r\n\r\n <!-- Floating Bubble Button (hidden when expanded) -->\r\n @if (!isExpanded()) {\r\n <button\r\n class=\"iq-bubble\"\r\n [class.iq-bottom-left]=\"resolvedConfig().position === 'bottom-left'\"\r\n [class.iq-open]=\"isOpen()\"\r\n [style.position]=\"resolvedConfig().stickyBubble ? 'fixed' : 'absolute'\"\r\n (click)=\"toggleChat()\"\r\n [attr.aria-label]=\"isOpen() ? 'Cerrar chat' : 'Abrir chat'\"\r\n >\r\n @if (isOpen()) {\r\n <span class=\"iq-bubble-icon\">✕</span>\r\n } @else {\r\n @switch (resolvedConfig().bubbleIconType) {\r\n @case ('image') {\r\n <img [src]=\"resolvedConfig().bubbleImageUrl\" alt=\"Chat\" class=\"iq-bubble-img\" />\r\n }\r\n @case ('svg') {\r\n <span class=\"iq-bubble-svg\" [innerHTML]=\"sanitizedBubbleSvg()\"></span>\r\n }\r\n @default {\r\n <span class=\"iq-bubble-icon\">{{ resolvedConfig().bubbleIcon }}</span>\r\n }\r\n }\r\n }\r\n </button>\r\n }\r\n\r\n <!-- Chat Panel -->\r\n @if (isOpen()) {\r\n <div\r\n class=\"iq-panel\"\r\n [class.iq-bottom-left]=\"resolvedConfig().position === 'bottom-left'\"\r\n [class.iq-expanded]=\"isExpanded()\"\r\n [class]=\"resolvedConfig().themeClass || ''\"\r\n [style.position]=\"resolvedConfig().stickyBubble ? 'fixed' : 'absolute'\"\r\n >\r\n <!-- Header -->\r\n <div class=\"iq-header\">\r\n <span class=\"iq-header-title\">{{ resolvedConfig().title }}</span>\r\n <div class=\"iq-header-actions\">\r\n <button class=\"iq-header-btn\" (click)=\"clearChat()\" title=\"Limpiar chat\">🗑️</button>\r\n @if (resolvedConfig().allowExpand) {\r\n <button class=\"iq-header-btn iq-btn-expand\" (click)=\"toggleExpand()\" [title]=\"isExpanded() ? 'Contraer' : 'Expandir'\">\r\n {{ isExpanded() ? '⊡' : '⛶' }}\r\n </button>\r\n }\r\n <button class=\"iq-header-btn\" (click)=\"isExpanded() ? toggleExpand() : toggleChat()\">✕</button>\r\n </div>\r\n </div>\r\n\r\n <!-- Auth Error Banner -->\r\n @if (authError()) {\r\n <div class=\"iq-auth-error\">\r\n <span>🔒</span>\r\n <span>{{ authError() }}</span>\r\n </div>\r\n }\r\n\r\n <!-- Messages -->\r\n <div class=\"iq-messages\" #chatContainer>\r\n @if (messages().length === 0 && !authError()) {\r\n <div class=\"iq-empty\">\r\n <div class=\"iq-empty-icon\">\r\n @switch (resolvedConfig().bubbleIconType) {\r\n @case ('image') {\r\n <img [src]=\"resolvedConfig().bubbleImageUrl\" alt=\"\" class=\"iq-empty-img\" />\r\n }\r\n @case ('svg') {\r\n <span class=\"iq-empty-svg\" [innerHTML]=\"sanitizedBubbleSvg()\"></span>\r\n }\r\n @default {\r\n <span>{{ resolvedConfig().bubbleIcon }}</span>\r\n }\r\n }\r\n </div>\r\n <p>{{ resolvedConfig().welcomeTitle }}</p>\r\n <p class=\"iq-text-muted\">{{ resolvedConfig().welcomeSubtitle }}</p>\r\n </div>\r\n }\r\n\r\n @for (msg of messages(); track msg.id) {\r\n <div class=\"iq-msg\" [class.iq-msg-user]=\"msg.sender === 'user'\" [class.iq-msg-bot]=\"msg.sender === 'bot'\">\r\n <div class=\"iq-msg-content\">\r\n @if (msg.sender === 'bot') {\r\n <div class=\"iq-md\" [innerHTML]=\"renderMarkdown(msg.text)\" (click)=\"onMessageClick($event)\"></div>\r\n } @else {\r\n <p>{{ msg.text }}</p>\r\n }\r\n <span class=\"iq-msg-time\">{{ formatTime(msg.timestamp) }}</span>\r\n </div>\r\n @if (msg.sender === 'bot' && msg.traceData && resolvedConfig().showTrace) {\r\n <button class=\"iq-btn-trace\" (click)=\"showTrace(msg)\">🔍 Ver Traza</button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Pipeline progress -->\r\n @if (isLoading()) {\r\n <div class=\"iq-msg iq-msg-bot\">\r\n <div class=\"iq-msg-content iq-pipeline\">\r\n <span class=\"iq-dot\"></span>\r\n <span class=\"iq-pipeline-text\">{{ pipelineStep }}</span>\r\n <button class=\"iq-cancel-btn\" (click)=\"cancelQuery()\" title=\"Cancelar consulta\">✕</button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Input -->\r\n <form class=\"iq-input-bar\" (ngSubmit)=\"sendMessage()\">\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"inputText\"\r\n name=\"message\"\r\n [placeholder]=\"resolvedConfig().placeholder!\"\r\n [disabled]=\"isLoading() || !!authError()\"\r\n autocomplete=\"off\"\r\n />\r\n <button type=\"submit\" class=\"iq-btn-send\" [disabled]=\"isLoading() || !inputText.trim() || !!authError()\">\r\n ➤\r\n </button>\r\n </form>\r\n </div>\r\n }\r\n\r\n <!-- Trace Modal Overlay -->\r\n @if (selectedTrace()) {\r\n <div class=\"iq-trace-overlay\" (click)=\"closeTrace()\">\r\n <div class=\"iq-trace-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"iq-trace-header\">\r\n <h3>🔍 Detalle de Traza</h3>\r\n <button class=\"iq-header-btn\" (click)=\"closeTrace()\">✕</button>\r\n </div>\r\n <div class=\"iq-trace-body\">\r\n @if (selectedTrace()?.fromCache !== undefined) {\r\n <div class=\"iq-trace-item\">\r\n <label>Origen</label>\r\n <code [class.iq-cache-hit]=\"selectedTrace()?.fromCache\">{{ selectedTrace()?.fromCache ? '📚 Desde Caché' : '🤖 Generado por GPT' }}</code>\r\n </div>\r\n }\r\n @if (selectedTrace()?.query) {\r\n <div class=\"iq-trace-item\">\r\n <label>Query Generada</label>\r\n <pre class=\"iq-query-code\">{{ selectedTrace()?.query }}</pre>\r\n </div>\r\n }\r\n @if (selectedTrace()?.explanation) {\r\n <div class=\"iq-trace-item\">\r\n <label>Explicación</label>\r\n <code>{{ selectedTrace()?.explanation }}</code>\r\n </div>\r\n }\r\n @if (selectedTrace()?.traceId) {\r\n <div class=\"iq-trace-item\">\r\n <label>Trace ID</label>\r\n <code>{{ selectedTrace()?.traceId }}</code>\r\n </div>\r\n }\r\n @if (selectedTrace()?.data) {\r\n <div class=\"iq-trace-item\">\r\n <label>Datos Retornados</label>\r\n <pre>{{ selectedTrace()?.data | json }}</pre>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Link Modal Overlay -->\r\n @if (modalUrl()) {\r\n <div class=\"iq-link-overlay\" (click)=\"closeLinkModal()\">\r\n <div class=\"iq-link-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"iq-link-header\">\r\n @if (showHomeBtn()) {\r\n <button class=\"iq-header-btn iq-back-btn\" (click)=\"iframeGoHome()\" title=\"Volver al inicio\">🏠</button>\r\n }\r\n <span class=\"iq-link-title\" [title]=\"modalUrl()!\">{{ modalUrl() }}</span>\r\n <div class=\"iq-link-actions\">\r\n <a [href]=\"modalUrl()!\" target=\"_blank\" rel=\"noopener\" class=\"iq-header-btn\" title=\"Abrir en nueva pestaña\">↗</a>\r\n <button class=\"iq-header-btn\" (click)=\"closeLinkModal()\">✕</button>\r\n </div>\r\n </div>\r\n <div class=\"iq-iframe-wrapper\">\r\n @if (isModalImage()) {\r\n <img [src]=\"modalUrl()!\" class=\"iq-modal-img\" alt=\"Imagen\" />\r\n } @else {\r\n @if (modalLoading()) {\r\n <div class=\"iq-iframe-loader\">\r\n <div class=\"iq-spinner\"></div>\r\n <span class=\"iq-loader-text\">Cargando...</span>\r\n </div>\r\n }\r\n <iframe #linkIframe [src]=\"sanitizedModalUrl()\" class=\"iq-link-iframe\"\r\n [class.iq-iframe-hidden]=\"modalLoading()\"\r\n (load)=\"onIframeLoaded()\"></iframe>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n </div><!-- /iq-theme-host -->\r\n `,\r\n styles: [`\r\n /* ========= CSS Custom Properties (overridable by host) ========= */\r\n :host {\r\n --iq-primary: #1a3a5c;\r\n --iq-primary-light: #2a5a8c;\r\n --iq-accent: #00d4aa;\r\n --iq-accent-light: #33e0be;\r\n --iq-bg: #1e1e2f;\r\n --iq-bg-card: #252538;\r\n --iq-bg-tertiary: #35354a;\r\n --iq-text: #ffffff;\r\n --iq-text-secondary: #a0a0b0;\r\n --iq-text-muted: #6c6c7c;\r\n --iq-border: #3a3a4d;\r\n --iq-radius: 12px;\r\n --iq-bubble-size: 56px;\r\n --iq-panel-width: 400px;\r\n --iq-panel-height: 520px;\r\n --iq-z: 10000;\r\n --iq-font: 'Inter', 'Roboto', -apple-system, BlinkMacSystemFont, sans-serif;\r\n font-family: var(--iq-font);\r\n }\r\n\r\n /* ========= Bubble ========= */\r\n .iq-bubble {\r\n position: fixed;\r\n bottom: 24px;\r\n right: 24px;\r\n z-index: var(--iq-z);\r\n width: var(--iq-bubble-size);\r\n height: var(--iq-bubble-size);\r\n border-radius: 50%;\r\n border: none;\r\n background: linear-gradient(135deg, var(--iq-accent), var(--iq-accent-light));\r\n color: var(--iq-bg);\r\n font-size: 1.6rem;\r\n cursor: pointer;\r\n box-shadow: 0 4px 16px rgba(0, 212, 170, 0.4);\r\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n .iq-bubble:hover {\r\n transform: scale(1.1);\r\n box-shadow: 0 6px 24px rgba(0, 212, 170, 0.5);\r\n }\r\n .iq-bubble .iq-bubble-icon {\r\n font-size: 1.5rem;\r\n pointer-events: none;\r\n }\r\n\r\n .iq-bubble-img {\r\n width: 60%; height: 60%;\r\n object-fit: contain; border-radius: 50%;\r\n pointer-events: none;\r\n }\r\n\r\n .iq-bubble-svg {\r\n width: 60%; height: 60%;\r\n display: flex; align-items: center; justify-content: center;\r\n pointer-events: none;\r\n }\r\n .iq-bubble-svg :deep(svg) { width: 100%; height: 100%; }\r\n\r\n .iq-bubble.iq-open {\r\n background: var(--iq-bg-tertiary);\r\n color: var(--iq-text);\r\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\r\n font-size: 1.2rem;\r\n }\r\n .iq-bubble.iq-bottom-left {\r\n right: auto;\r\n left: 24px;\r\n }\r\n .iq-bubble-icon { line-height: 1; }\r\n\r\n /* ========= Panel ========= */\r\n .iq-panel {\r\n position: fixed;\r\n bottom: 92px;\r\n right: 24px;\r\n z-index: var(--iq-z);\r\n width: var(--iq-panel-width);\r\n height: var(--iq-panel-height);\r\n background: var(--iq-bg);\r\n border: 1px solid var(--iq-border);\r\n border-radius: var(--iq-radius);\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n box-shadow: 0 12px 40px rgba(0,0,0,0.5);\r\n animation: iq-slide-up 0.3s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n .iq-panel.iq-bottom-left {\r\n right: auto;\r\n left: 24px;\r\n }\r\n /* ========= Expanded / Fullscreen ========= */\r\n .iq-panel.iq-expanded {\r\n width: 100vw !important;\r\n height: 100vh !important;\r\n top: 0 !important;\r\n left: 0 !important;\r\n right: 0 !important;\r\n bottom: 0 !important;\r\n border: none;\r\n border-radius: 0;\r\n overflow: clip;\r\n z-index: calc(var(--iq-z) + 5);\r\n animation: iq-expand 0.3s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n .iq-btn-expand {\r\n font-size: 1.1rem !important;\r\n }\r\n @keyframes iq-expand {\r\n from { opacity: 0.8; transform: scale(0.95); }\r\n to { opacity: 1; transform: scale(1); }\r\n }\r\n @keyframes iq-slide-up {\r\n from { opacity: 0; transform: translateY(16px) scale(0.96); }\r\n to { opacity: 1; transform: translateY(0) scale(1); }\r\n }\r\n\r\n /* ========= Header ========= */\r\n .iq-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--iq-border);\r\n background: var(--iq-bg-card);\r\n }\r\n .iq-header-title {\r\n font-weight: 600;\r\n font-size: 0.95rem;\r\n color: var(--iq-text);\r\n }\r\n .iq-header-actions {\r\n display: flex;\r\n gap: 4px;\r\n }\r\n .iq-header-btn {\r\n background: none;\r\n border: none;\r\n color: var(--iq-text-muted);\r\n cursor: pointer;\r\n font-size: 1rem;\r\n padding: 4px 6px;\r\n border-radius: 4px;\r\n transition: all 0.15s;\r\n }\r\n .iq-header-btn:hover {\r\n color: var(--iq-text);\r\n background: rgba(255,255,255,0.08);\r\n }\r\n\r\n /* ========= Auth Error ========= */\r\n .iq-auth-error {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 10px 16px;\r\n background: rgba(220, 53, 69, 0.15);\r\n color: #ff6b7a;\r\n font-size: 0.8rem;\r\n border-bottom: 1px solid rgba(220, 53, 69, 0.25);\r\n }\r\n\r\n /* ========= Messages ========= */\r\n .iq-messages {\r\n flex: 1;\r\n min-height: 0;\r\n overflow-y: auto;\r\n padding: 12px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 10px;\r\n }\r\n\r\n .iq-empty {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n text-align: center;\r\n color: var(--iq-text-secondary);\r\n }\r\n .iq-empty-icon { font-size: 3rem; margin-bottom: 8px; display: flex; align-items: center; justify-content: center; }\r\n .iq-empty-img { width: 48px; height: 48px; object-fit: contain; border-radius: 8px; }\r\n .iq-empty-svg { width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; }\r\n .iq-empty-svg :deep(svg) { width: 100%; height: 100%; }\r\n .iq-empty p { font-size: 0.95rem; margin: 2px 0; }\r\n .iq-text-muted { color: var(--iq-text-muted) !important; font-size: 0.8rem !important; }\r\n\r\n .iq-msg { display: flex; flex-direction: column; max-width: 85%; }\r\n .iq-msg-user { align-self: flex-end; }\r\n .iq-msg-bot { align-self: flex-start; max-width: 100%; }\r\n\r\n .iq-msg-user .iq-msg-content {\r\n background: linear-gradient(135deg, var(--iq-primary), var(--iq-primary-light));\r\n border-radius: 12px 12px 0 12px;\r\n }\r\n .iq-msg-bot .iq-msg-content {\r\n background: var(--iq-bg-tertiary);\r\n border-radius: 12px 12px 12px 0;\r\n }\r\n .iq-msg-content {\r\n padding: 10px 14px;\r\n color: var(--iq-text);\r\n font-size: 0.85rem;\r\n line-height: 1.45;\r\n }\r\n .iq-msg-content p { margin: 0; white-space: pre-wrap; }\r\n .iq-msg-time {\r\n display: block;\r\n margin-top: 4px;\r\n font-size: 0.65rem;\r\n color: rgba(255,255,255,0.5);\r\n }\r\n\r\n /* Markdown rendered content */\r\n .iq-md { line-height: 1.5; overflow-x: auto; max-width: 100%; }\r\n .iq-md :first-child { margin-top: 0; }\r\n .iq-md :last-child { margin-bottom: 0; }\r\n .iq-md p { margin: 0 0 0.4em 0; }\r\n .iq-md p:last-child { margin-bottom: 0; }\r\n .iq-md strong { color: var(--iq-accent); }\r\n .iq-md ul, .iq-md ol { margin: 0.3em 0; padding-left: 1.2em; }\r\n .iq-md li { margin: 0.15em 0; }\r\n .iq-md code {\r\n background: rgba(0,0,0,0.3);\r\n padding: 0.15em 0.4em;\r\n border-radius: 3px;\r\n font-size: 0.82em;\r\n }\r\n .iq-md pre {\r\n background: rgba(0,0,0,0.3);\r\n padding: 0.8em;\r\n border-radius: 6px;\r\n overflow-x: auto;\r\n font-size: 0.78em;\r\n margin: 0.4em 0;\r\n }\r\n .iq-md pre code { background: none; padding: 0; }\r\n .iq-md table {\r\n width: max-content; min-width: 100%;\r\n border-collapse: separate; border-spacing: 0;\r\n margin: 0.5em 0; font-size: 0.75rem;\r\n border-radius: 6px; overflow: hidden;\r\n }\r\n .iq-md thead th {\r\n background: rgba(99,102,241,0.18); color: #a5b4fc;\r\n font-weight: 600; text-align: left;\r\n padding: 0.5em 0.8em; border-bottom: 2px solid rgba(99,102,241,0.3);\r\n white-space: nowrap; font-size: 0.7rem;\r\n text-transform: uppercase; letter-spacing: 0.05em;\r\n }\r\n .iq-md tbody td {\r\n padding: 0.4em 0.8em; border-bottom: 1px solid rgba(255,255,255,0.06);\r\n white-space: nowrap; color: var(--iq-text-secondary);\r\n }\r\n .iq-md tbody tr:hover { background: rgba(99,102,241,0.08); }\r\n\r\n /* Inline images in bot messages – small thumbnails, click to enlarge */\r\n .iq-md img {\r\n max-height: 80px; max-width: 120px; object-fit: cover;\r\n border-radius: 8px; margin: 6px 4px 6px 0;\r\n display: inline-block; vertical-align: middle;\r\n border: 1px solid rgba(255,255,255,0.15);\r\n box-shadow: 0 1px 4px rgba(0,0,0,0.25);\r\n cursor: pointer; transition: transform 0.15s, box-shadow 0.15s;\r\n }\r\n .iq-md img:hover {\r\n transform: scale(1.05);\r\n box-shadow: 0 3px 12px rgba(99,102,241,0.35);\r\n border-color: var(--iq-accent);\r\n }\r\n .iq-md img[alt*=\"logo\"], .iq-md img[alt*=\"marca\"] {\r\n max-height: 28px; max-width: 90px; object-fit: contain;\r\n border: none; box-shadow: none; border-radius: 4px;\r\n background: rgba(255,255,255,0.9); padding: 2px 6px;\r\n }\r\n /* Trace button */\r\n .iq-btn-trace {\r\n align-self: flex-start; margin-top: 4px;\r\n background: transparent; border: 1px solid var(--iq-border);\r\n color: var(--iq-text-secondary); font-size: 0.7rem;\r\n padding: 3px 8px; border-radius: 4px; cursor: pointer;\r\n transition: all 0.15s;\r\n }\r\n .iq-btn-trace:hover { border-color: var(--iq-accent); color: var(--iq-accent); }\r\n\r\n /* Pipeline loading indicator */\r\n .iq-pipeline {\r\n display: flex; align-items: center; gap: 8px;\r\n animation: iq-fade-in 0.3s ease-out;\r\n }\r\n .iq-dot {\r\n width: 8px; height: 8px; border-radius: 50%;\r\n background: var(--iq-accent);\r\n animation: iq-pulse 1s ease-in-out infinite;\r\n }\r\n .iq-pipeline-text {\r\n font-size: 0.8rem; color: var(--iq-text-muted); font-style: italic;\r\n flex: 1;\r\n }\r\n .iq-cancel-btn {\r\n background: transparent; border: 1px solid var(--iq-border);\r\n color: var(--iq-text-muted); font-size: 0.7rem;\r\n padding: 2px 8px; border-radius: 4px; cursor: pointer;\r\n transition: all 0.15s; flex-shrink: 0;\r\n }\r\n .iq-cancel-btn:hover {\r\n border-color: #ff6b6b; color: #ff6b6b; background: rgba(255, 107, 107, 0.1);\r\n }\r\n @keyframes iq-pulse {\r\n 0%, 100% { opacity: 1; transform: scale(1); }\r\n 50% { opacity: 0.4; transform: scale(0.7); }\r\n }\r\n @keyframes iq-fade-in {\r\n from { opacity: 0; transform: translateX(-6px); }\r\n to { opacity: 1; transform: translateX(0); }\r\n }\r\n\r\n /* ========= Input Bar ========= */\r\n .iq-input-bar {\r\n display: flex; gap: 8px;\r\n padding: 10px 12px;\r\n border-top: 1px solid var(--iq-border);\r\n background: var(--iq-bg-card);\r\n }\r\n .iq-input-bar input {\r\n flex: 1; padding: 8px 12px;\r\n background: var(--iq-bg-tertiary);\r\n border: 1px solid var(--iq-border);\r\n border-radius: 8px;\r\n color: var(--iq-text);\r\n font-size: 0.85rem;\r\n font-family: var(--iq-font);\r\n outline: none;\r\n transition: border-color 0.15s;\r\n }\r\n .iq-input-bar input:focus { border-color: var(--iq-accent); }\r\n .iq-input-bar input::placeholder { color: var(--iq-text-muted); }\r\n .iq-input-bar input:disabled { opacity: 0.5; }\r\n .iq-btn-send {\r\n width: 36px; height: 36px;\r\n border-radius: 8px; border: none;\r\n background: linear-gradient(135deg, var(--iq-accent), var(--iq-accent-light));\r\n color: var(--iq-bg); font-size: 1rem;\r\n cursor: pointer; transition: all 0.2s;\r\n display: flex; align-items: center; justify-content: center;\r\n }\r\n .iq-btn-send:hover:not(:disabled) { box-shadow: 0 0 12px rgba(0,212,170,0.4); transform: translateY(-1px); }\r\n .iq-btn-send:disabled { opacity: 0.4; cursor: not-allowed; }\r\n\r\n /* ========= Trace Modal ========= */\r\n .iq-trace-overlay {\r\n position: fixed; inset: 0;\r\n z-index: calc(var(--iq-z) + 10);\r\n background: rgba(0,0,0,0.6);\r\n display: flex; align-items: center; justify-content: center;\r\n animation: iq-fade-in 0.2s ease-out;\r\n }\r\n .iq-trace-modal {\r\n width: 90%; max-width: 520px; max-height: 80vh;\r\n background: var(--iq-bg); border: 1px solid var(--iq-border);\r\n border-radius: var(--iq-radius);\r\n display: flex; flex-direction: column; overflow: hidden;\r\n box-shadow: 0 20px 50px rgba(0,0,0,0.6);\r\n }\r\n .iq-trace-header {\r\n display: flex; align-items: center; justify-content: space-between;\r\n padding: 14px 16px; border-bottom: 1px solid var(--iq-border);\r\n }\r\n .iq-trace-header h3 { margin: 0; font-size: 0.95rem; color: var(--iq-text); }\r\n .iq-trace-body {\r\n flex: 1; overflow-y: auto; padding: 16px;\r\n display: flex; flex-direction: column; gap: 12px;\r\n }\r\n .iq-trace-item label {\r\n display: block; font-size: 0.7rem; color: var(--iq-text-muted);\r\n margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.05em;\r\n }\r\n .iq-trace-item code {\r\n display: block; padding: 8px;\r\n background: var(--iq-bg-tertiary); border-radius: 4px;\r\n font-family: monospace; font-size: 0.8rem; color: var(--iq-accent);\r\n word-break: break-all;\r\n }\r\n .iq-trace-item pre {\r\n margin: 0; padding: 8px;\r\n background: var(--iq-bg-tertiary); border-radius: 4px;\r\n font-family: monospace; font-size: 0.7rem;\r\n overflow-x: auto; max-height: 180px; color: var(--iq-text-secondary);\r\n }\r\n .iq-cache-hit { background: rgba(16,185,129,0.15) !important; color: #10b981 !important; }\r\n .iq-query-code { color: var(--iq-accent) !important; }\r\n\r\n /* ========= Link Modal ========= */\r\n .iq-link-overlay {\r\n position: fixed; inset: 0;\r\n z-index: calc(var(--iq-z) + 20);\r\n background: rgba(0,0,0,0.7);\r\n display: flex; align-items: center; justify-content: center;\r\n animation: iq-fade-in 0.2s ease-out;\r\n backdrop-filter: blur(4px);\r\n }\r\n .iq-link-modal {\r\n width: 94vw; height: 92vh;\r\n background: var(--iq-bg); border: 1px solid var(--iq-border);\r\n border-radius: var(--iq-radius);\r\n display: flex; flex-direction: column; overflow: hidden;\r\n box-shadow: 0 24px 60px rgba(0,0,0,0.7);\r\n animation: iq-expand 0.25s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n .iq-link-header {\r\n display: flex; align-items: center; justify-content: space-between;\r\n padding: 10px 16px; border-bottom: 1px solid var(--iq-border);\r\n background: var(--iq-bg-card); gap: 12px; min-height: 44px;\r\n }\r\n .iq-link-title {\r\n flex: 1; font-size: 0.78rem; color: var(--iq-text-secondary);\r\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\r\n font-family: monospace;\r\n }\r\n .iq-link-actions {\r\n display: flex; gap: 4px; flex-shrink: 0;\r\n }\r\n .iq-link-actions a {\r\n text-decoration: none;\r\n }\r\n .iq-back-btn {\r\n flex-shrink: 0; font-size: 1.1rem;\r\n transition: transform 0.15s ease;\r\n }\r\n .iq-back-btn:hover {\r\n transform: translateX(-2px);\r\n }\r\n .iq-iframe-wrapper {\r\n flex: 1; position: relative; overflow: hidden;\r\n }\r\n .iq-link-iframe {\r\n width: 100%; height: 100%; border: none;\r\n background: #fff;\r\n transition: opacity 0.3s ease;\r\n }\r\n .iq-iframe-hidden {\r\n opacity: 0;\r\n }\r\n .iq-modal-img {\r\n width: 100%; height: 100%;\r\n object-fit: contain;\r\n background: #1a1a2e;\r\n }\r\n .iq-iframe-loader {\r\n position: absolute; inset: 0;\r\n display: flex; flex-direction: column;\r\n align-items: center; justify-content: center;\r\n background: var(--iq-bg);\r\n gap: 16px; z-index: 2;\r\n }\r\n .iq-spinner {\r\n width: 40px; height: 40px;\r\n border: 3px solid var(--iq-border);\r\n border-top-color: var(--iq-accent);\r\n border-radius: 50%;\r\n animation: iq-spin 0.8s linear infinite;\r\n }\r\n .iq-loader-text {\r\n font-size: 0.85rem; color: var(--iq-text-secondary);\r\n font-weight: 500;\r\n }\r\n @keyframes iq-spin {\r\n to { transform: rotate(360deg); }\r\n }\r\n\r\n /* ========= Link Modal — markdown link styling ========= */\r\n .iq-md a {\r\n color: var(--iq-accent); text-decoration: underline;\r\n cursor: pointer; transition: color 0.15s;\r\n }\r\n .iq-md a:hover {\r\n color: var(--iq-accent-light);\r\n }\r\n\r\n @media (max-width: 480px) {\r\n .iq-link-modal {\r\n width: 100vw; height: 100dvh;\r\n border-radius: 0;\r\n }\r\n .iq-link-header { padding: 8px 12px; }\r\n .iq-link-title { font-size: 0.7rem; }\r\n }\r\n\r\n /* ========= Scrollbar ========= */\r\n .iq-messages::-webkit-scrollbar { width: 5px; }\r\n .iq-messages::-webkit-scrollbar-track { background: transparent; }\r\n .iq-messages::-webkit-scrollbar-thumb { background: var(--iq-border); border-radius: 4px; }\r\n .iq-trace-body::-webkit-scrollbar { width: 5px; }\r\n .iq-trace-body::-webkit-scrollbar-track { background: transparent; }\r\n .iq-trace-body::-webkit-scrollbar-thumb { background: var(--iq-border); border-radius: 4px; }\r\n /* Wider scrollbar in fullscreen for easier grabbing */\r\n .iq-expanded .iq-messages::-webkit-scrollbar { width: 8px; }\r\n .iq-expanded .iq-messages { scrollbar-gutter: stable; }\r\n\r\n /* ========= Mobile Small Screens ========= */\r\n @media (max-width: 480px) {\r\n .iq-bubble {\r\n bottom: 16px;\r\n right: 16px;\r\n width: 48px;\r\n height: 48px;\r\n font-size: 1.3rem;\r\n }\r\n .iq-bubble.iq-bottom-left {\r\n left: 16px;\r\n }\r\n .iq-bubble .iq-bubble-icon { font-size: 1.2rem; }\r\n\r\n .iq-panel {\r\n right: 8px;\r\n left: 8px;\r\n bottom: 72px;\r\n width: auto !important;\r\n max-width: calc(100vw - 16px);\r\n height: calc(100dvh - 90px);\r\n max-height: calc(100dvh - 90px);\r\n }\r\n .iq-panel.iq-bottom-left {\r\n left: 8px;\r\n right: 8px;\r\n }\r\n .iq-panel.iq-expanded {\r\n top: 0 !important;\r\n left: 0 !important;\r\n right: 0 !important;\r\n bottom: 0 !important;\r\n width: 100vw !important;\r\n height: 100dvh !important;\r\n max-height: 100dvh !important;\r\n max-width: 100vw !important;\r\n border-radius: 0;\r\n }\r\n\r\n .iq-header {\r\n padding: 10px 12px;\r\n }\r\n .iq-header-title { font-size: 0.85rem; }\r\n .iq-header-btn { padding: 6px 8px; min-width: 32px; min-height: 32px; }\r\n\r\n .iq-messages { padding: 8px; gap: 8px; }\r\n\r\n .iq-msg { max-width: 92%; }\r\n .iq-msg-bot { max-width: 100%; }\r\n .iq-msg-content { padding: 8px 10px; font-size: 0.8rem; }\r\n\r\n .iq-md { overflow-x: auto; -webkit-overflow-scrolling: touch; }\r\n .iq-md table { font-size: 0.65rem; min-width: unset; }\r\n .iq-md thead th { padding: 0.35em 0.5em; font-size: 0.6rem; }\r\n .iq-md tbody td { padding: 0.3em 0.5em; font-size: 0.65rem; }\r\n\r\n .iq-empty-icon { font-size: 2.5rem; }\r\n .iq-empty p { font-size: 0.85rem; }\r\n\r\n .iq-input-bar { padding: 8px 10px; gap: 6px; }\r\n .iq-input-bar input { font-size: 16px; padding: 8px 10px; }\r\n .iq-btn-send { width: 38px; height: 38px; flex-shrink: 0; }\r\n\r\n .iq-trace-modal {\r\n width: calc(100vw - 24px);\r\n max-height: 90dvh;\r\n }\r\n .iq-trace-header { padding: 12px; }\r\n .iq-trace-header h3 { font-size: 0.85rem; }\r\n .iq-trace-body { padding: 12px; }\r\n .iq-trace-item pre { font-size: 0.65rem; max-height: 140px; }\r\n }\r\n\r\n /* ========= Landscape Mobile — fit floating panel ========= */\r\n @media (max-height: 500px) and (orientation: landscape) {\r\n .iq-bubble {\r\n bottom: 8px;\r\n right: 8px;\r\n width: 44px;\r\n height: 44px;\r\n font-size: 1.1rem;\r\n }\r\n .iq-bubble.iq-bottom-left { left: 8px; }\r\n\r\n .iq-panel {\r\n right: 60px;\r\n left: 8px;\r\n bottom: 8px;\r\n top: 8px;\r\n width: auto !important;\r\n max-width: calc(100vw - 76px);\r\n height: auto !important;\r\n max-height: calc(100dvh - 16px);\r\n border-radius: var(--iq-radius);\r\n }\r\n .iq-panel.iq-bottom-left {\r\n left: 60px;\r\n right: 8px;\r\n }\r\n .iq-panel.iq-expanded {\r\n top: 0 !important;\r\n left: 0 !important;\r\n right: 0 !important;\r\n bottom: 0 !important;\r\n width: 100vw !important;\r\n height: 100dvh !important;\r\n max-height: 100dvh !important;\r\n max-width: 100vw !important;\r\n border-radius: 0;\r\n }\r\n\r\n .iq-header { padding: 6px 12px; }\r\n .iq-header-title { font-size: 0.8rem; }\r\n .iq-messages { padding: 6px 10px; gap: 6px; }\r\n .iq-empty-icon { font-size: 1.8rem; margin-bottom: 4px; }\r\n .iq-empty p { font-size: 0.78rem; margin: 1px 0; }\r\n .iq-input-bar { padding: 6px 10px; }\r\n .iq-input-bar input { font-size: 16px; padding: 6px 10px; }\r\n .iq-btn-send { width: 32px; height: 32px; }\r\n }\r\n `]\r\n})\r\nexport class IntelligentChatPluginComponent implements AfterViewChecked, OnChanges, OnInit, OnDestroy {\r\n @ViewChild('chatContainer') private chatContainer!: ElementRef;\r\n\r\n @Input() config!: IntelligentChatConfig;\r\n\r\n private chatService = inject(IntelligentChatService);\r\n private hostEl = inject(ElementRef);\r\n\r\n // State\r\n isOpen = signal(false);\r\n isExpanded = signal(false);\r\n messages = signal<ChatMessage[]>([]);\r\n isLoading = signal(false);\r\n selectedTrace = signal<any>(null);\r\n authError = signal<string | null>(null);\r\n modalUrl = signal<string | null>(null);\r\n isModalImage = computed(() => {\r\n const url = this.modalUrl();\r\n if (!url) return false;\r\n return /\\.(jpg|jpeg|png|gif|webp|svg|bmp)(\\?.*)?$/i.test(url);\r\n });\r\n modalLoading = signal(false);\r\n showHomeBtn = signal(false);\r\n private originalModalUrl = '';\r\n private modalReadyForNav = false;\r\n private navReadyTimer: any = null;\r\n inputText = '';\r\n private currentSubscription?: Subscription;\r\n\r\n // Pipeline step (driven by real SSE events from backend)\r\n pipelineStep = '';\r\n\r\n private messageId = 0;\r\n private shouldScroll = false;\r\n\r\n // ─── Session Persistence ──────────────────────────\r\n private readonly STORAGE_PREFIX = 'iq_chat_session_';\r\n private sessionKey = '';\r\n private storageListener = (e: StorageEvent) => this.onStorageChange(e);\r\n\r\n /** Resolved config with defaults applied */\r\n private sanitizer = inject(DomSanitizer);\r\n\r\n resolvedConfig = signal<Required<IntelligentChatConfig>>({\r\n apiUrl: '',\r\n systemId: '',\r\n token: '',\r\n useIntelligentQuery: true,\r\n skipPatterns: true,\r\n baseContext: '',\r\n showTrace: false,\r\n showPipelineSteps: true,\r\n preferTableFormat: true,\r\n title: 'Maquito Chat',\r\n placeholder: 'Escribe tu consulta aquí...',\r\n welcomeTitle: '¡Hola! Soy Maquito.',\r\n welcomeSubtitle: 'Escribe tu consulta para comenzar.',\r\n position: 'bottom-right',\r\n bubbleIcon: '🤖',\r\n bubbleIconType: 'emoji',\r\n bubbleImageUrl: '',\r\n bubbleSvg: '',\r\n themeClass: '',\r\n stickyBubble: true,\r\n allowExpand: false,\r\n theme: {},\r\n userName: '',\r\n personality: ''\r\n });\r\n\r\n /** Map theme object → CSS variable overrides */\r\n themeStyles = computed(() => {\r\n const t = this.resolvedConfig().theme || {};\r\n const map: Record<string, string> = {};\r\n const pairs: [keyof PluginTheme, string][] = [\r\n ['primary', '--iq-primary'], ['primaryLight', '--iq-primary-light'],\r\n ['accent', '--iq-accent'], ['accentLight', '--iq-accent-light'],\r\n ['bg', '--iq-bg'], ['bgCard', '--iq-bg-card'], ['bgTertiary', '--iq-bg-tertiary'],\r\n ['text', '--iq-text'], ['textSecondary', '--iq-text-secondary'],\r\n ['textMuted', '--iq-text-muted'], ['border', '--iq-border']\r\n ];\r\n for (const [key, cssVar] of pairs) {\r\n if (t[key]) map[cssVar] = t[key]!;\r\n }\r\n return map;\r\n });\r\n\r\n /** Sanitised SVG HTML for bubble */\r\n sanitizedBubbleSvg = computed<SafeHtml>(() => {\r\n const raw = this.resolvedConfig().bubbleSvg || '';\r\n return this.sanitizer.bypassSecurityTrustHtml(raw);\r\n });\r\n\r\n /** Sanitised URL for the link modal iframe */\r\n sanitizedModalUrl = computed<SafeResourceUrl>(() => {\r\n const url = this.modalUrl() || '';\r\n return this.sanitizer.bypassSecurityTrustResourceUrl(url);\r\n });\r\n\r\n ngOnInit(): void {\r\n window.addEventListener('storage', this.storageListener);\r\n }\r\n\r\n ngOnDestroy(): void {\r\n window.removeEventListener('storage', this.storageListener);\r\n this.cancelQuery();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['config'] && this.config) {\r\n this.resolvedConfig.set({\r\n apiUrl: this.config.apiUrl || '',\r\n systemId: this.config.systemId || '',\r\n token: this.config.token || '',\r\n useIntelligentQuery: this.config.useIntelligentQuery ?? true,\r\n skipPatterns: this.config.skipPatterns ?? true,\r\n baseContext: this.config.baseContext || '',\r\n showTrace: this.config.showTrace ?? false,\r\n showPipelineSteps: this.config.showPipelineSteps ?? true,\r\n preferTableFormat: this.config.preferTableFormat ?? true,\r\n title: this.config.title || 'Maquito Chat',\r\n placeholder: this.config.placeholder || 'Escribe tu consulta aquí...',\r\n welcomeTitle: this.config.welcomeTitle || '¡Hola! Soy Maquito.',\r\n welcomeSubtitle: this.config.welcomeSubtitle || 'Escribe tu consulta para comenzar.',\r\n position: this.config.position || 'bottom-right',\r\n bubbleIcon: this.config.bubbleIcon || '🤖',\r\n bubbleIconType: this.config.bubbleIconType || 'emoji',\r\n bubbleImageUrl: this.config.bubbleImageUrl || '',\r\n bubbleSvg: this.config.bubbleSvg || '',\r\n themeClass: this.config.themeClass || '',\r\n stickyBubble: this.config.stickyBubble ?? true,\r\n allowExpand: this.config.allowExpand ?? false,\r\n theme: this.config.theme || {},\r\n userName: this.config.userName || '',\r\n personality: this.config.personality || ''\r\n });\r\n // Cancel any in-flight query when config changes\r\n this.cancelQuery();\r\n // Rebuild session key when config changes\r\n const newKey = this.buildSessionKey();\r\n if (newKey !== this.sessionKey) {\r\n this.sessionKey = newKey;\r\n this.loadSession();\r\n }\r\n // Clear auth error when config changes (user may be testing a new token)\r\n this.authError.set(null);\r\n }\r\n }\r\n\r\n ngAfterViewChecked(): void {\r\n if (this.shouldScroll) {\r\n this.scrollToBottom();\r\n this.shouldScroll = false;\r\n }\r\n }\r\n\r\n toggleChat(): void {\r\n this.isOpen.update(v => !v);\r\n if (!this.isOpen()) {\r\n this.isExpanded.set(false);\r\n this.setHostScrollLock(false);\r\n }\r\n if (this.isOpen()) this.shouldScroll = true;\r\n }\r\n\r\n toggleExpand(): void {\r\n this.isExpanded.update(v => !v);\r\n this.setHostScrollLock(this.isExpanded());\r\n }\r\n\r\n /** Lock/unlock the host page scroll to prevent its scrollbar from overlapping ours */\r\n private setHostScrollLock(lock: boolean): void {\r\n document.body.style.overflow = lock ? 'hidden' : '';\r\n // Also target common host containers\r\n const mc = document.querySelector('.main-container') as HTMLElement;\r\n if (mc) mc.style.overflow = lock ? 'hidden' : '';\r\n }\r\n\r\n sendMessage(): void {\r\n const text = this.inputText.trim();\r\n if (!text) return;\r\n\r\n const cfg = this.resolvedConfig();\r\n\r\n // Validate required config\r\n if (!cfg.token) {\r\n this.authError.set('Token no configurado. El plugin requiere un token técnico válido.');\r\n return;\r\n }\r\n if (!cfg.apiUrl) {\r\n this.authError.set('API URL no configurada.');\r\n return;\r\n }\r\n\r\n this.authError.set(null);\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text,\r\n sender: 'user',\r\n timestamp: new Date()\r\n }]);\r\n this.saveSession();\r\n this.shouldScroll = true;\r\n this.inputText = '';\r\n this.isLoading.set(true);\r\n\r\n if (cfg.showPipelineSteps) {\r\n this.pipelineStep = '⏳ Procesando...';\r\n } else {\r\n this.pipelineStep = '⏳ Procesando...';\r\n }\r\n\r\n if (cfg.useIntelligentQuery && cfg.systemId) {\r\n // Build conversation history from previous messages (last 6 pairs)\r\n const history = this.messages()\r\n .filter(m => m.sender === 'user' || m.sender === 'bot')\r\n .slice(-12)\r\n .map(msg => ({\r\n role: msg.sender === 'user' ? 'user' : 'assistant',\r\n content: msg.text\r\n }));\r\n\r\n const ctx = cfg.baseContext?.trim() || undefined;\r\n\r\n if (cfg.showPipelineSteps) {\r\n // Use SSE streaming for real-time pipeline progress\r\n this.currentSubscription = this.chatService.executeIntelligentQueryStream(\r\n cfg.apiUrl, cfg.token, cfg.systemId, text, history, ctx, cfg.skipPatterns, cfg.preferTableFormat,\r\n cfg.userName || undefined, cfg.personality || undefined\r\n ).subscribe({\r\n next: (event) => {\r\n if (event.type === 'progress') {\r\n this.pipelineStep = event.message || '';\r\n } else if (event.type === 'result') {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n const response = event.data;\r\n const responseText = response.success\r\n ? (response.response || 'Consulta ejecutada correctamente')\r\n : (response.error || 'Error en la consulta');\r\n\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text: responseText,\r\n sender: 'bot',\r\n timestamp: new Date(),\r\n traceData: {\r\n traceId: response.traceId,\r\n fromCache: response.fromCache,\r\n fromContext: response.fromContext,\r\n query: response.query,\r\n explanation: response.explanation,\r\n patternId: response.patternId,\r\n data: response.data\r\n }\r\n }]);\r\n this.saveSession();\r\n this.shouldScroll = true;\r\n }\r\n },\r\n error: (error) => {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n this.setHostScrollLock(false);\r\n this.handleError(error);\r\n }\r\n });\r\n } else {\r\n // Fallback: use standard non-streaming endpoint\r\n this.currentSubscription = this.chatService.executeIntelligentQuery(\r\n cfg.apiUrl, cfg.token, cfg.systemId, text, history, ctx, cfg.skipPatterns, cfg.preferTableFormat,\r\n cfg.userName || undefined, cfg.personality || undefined\r\n ).subscribe({\r\n next: (response: any) => {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n const responseText = response.success\r\n ? (response.response || 'Consulta ejecutada correctamente')\r\n : (response.error || 'Error en la consulta');\r\n\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text: responseText,\r\n sender: 'bot',\r\n timestamp: new Date(),\r\n traceData: {\r\n traceId: response.traceId,\r\n fromCache: response.fromCache,\r\n fromContext: response.fromContext,\r\n query: response.query,\r\n explanation: response.explanation,\r\n patternId: response.patternId,\r\n data: response.data\r\n }\r\n }]);\r\n this.saveSession();\r\n this.shouldScroll = true;\r\n },\r\n error: (error) => {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n this.setHostScrollLock(false);\r\n this.handleError(error);\r\n }\r\n });\r\n }\r\n } else {\r\n // Standard orchestration (non-intelligent)\r\n this.currentSubscription = this.chatService.ask(cfg.apiUrl, cfg.token, text).subscribe({\r\n next: (response) => {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text: response.data?.response || 'Sin respuesta',\r\n sender: 'bot',\r\n timestamp: new Date(),\r\n traceData: {\r\n traceId: response.traceId,\r\n responseTime: response.data?.processingTime,\r\n appliedRules: response.data?.appliedRules,\r\n decisions: response.data?.decisions\r\n }\r\n }]);\r\n this.saveSession();\r\n this.shouldScroll = true;\r\n },\r\n error: (error) => {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n this.setHostScrollLock(false);\r\n this.handleError(error);\r\n }\r\n });\r\n }\r\n }\r\n\r\n cancelQuery(): void {\r\n this.currentSubscription?.unsubscribe();\r\n this.currentSubscription = undefined;\r\n this.isLoading.set(false);\r\n this.pipelineStep = '';\r\n this.setHostScrollLock(false);\r\n }\r\n\r\n clearChat(): void {\r\n this.messages.set([]);\r\n this.selectedTrace.set(null);\r\n this.authError.set(null);\r\n this.clearSession();\r\n }\r\n\r\n showTrace(msg: ChatMessage): void {\r\n this.selectedTrace.set(msg.traceData);\r\n }\r\n\r\n closeTrace(): void {\r\n this.selectedTrace.set(null);\r\n }\r\n\r\n // ─── Link Modal ────────────────────────────────\r\n openLinkModal(url: string): void {\r\n this.modalLoading.set(true);\r\n this.showHomeBtn.set(false);\r\n this.modalReadyForNav = false;\r\n clearTimeout(this.navReadyTimer);\r\n this.originalModalUrl = url;\r\n this.modalUrl.set(url);\r\n }\r\n\r\n closeLinkModal(): void {\r\n this.modalUrl.set(null);\r\n this.modalLoading.set(false);\r\n this.showHomeBtn.set(false);\r\n this.modalReadyForNav = false;\r\n clearTimeout(this.navReadyTimer);\r\n this.originalModalUrl = '';\r\n }\r\n\r\n onIframeLoaded(): void {\r\n this.modalLoading.set(false);\r\n if (this.modalReadyForNav) {\r\n // A load AFTER the initial page settled = real navigation\r\n this.showHomeBtn.set(true);\r\n } else {\r\n // Initial page load (may fire multiple times for SPAs/redirects)\r\n // Wait 1s of stability before treating next loads as navigation\r\n clearTimeout(this.navReadyTimer);\r\n this.navReadyTimer = setTimeout(() => { this.modalReadyForNav = true; }, 1000);\r\n }\r\n }\r\n\r\n iframeGoHome(): void {\r\n const iframe = this.hostEl.nativeElement.querySelector('.iq-link-iframe') as HTMLIFrameElement;\r\n if (iframe && this.originalModalUrl) {\r\n this.modalLoading.set(true);\r\n this.showHomeBtn.set(false);\r\n this.modalReadyForNav = false;\r\n clearTimeout(this.navReadyTimer);\r\n iframe.src = this.originalModalUrl;\r\n }\r\n }\r\n\r\n /** Intercept clicks on <a> and <img> tags inside rendered markdown */\r\n onMessageClick(event: MouseEvent): void {\r\n const target = event.target as HTMLElement;\r\n\r\n // Clicking an image opens it full-size in the modal\r\n if (target.tagName === 'IMG') {\r\n const src = (target as HTMLImageElement).src;\r\n if (src) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.openLinkModal(src);\r\n return;\r\n }\r\n }\r\n\r\n const anchor = target.closest('a') as HTMLAnchorElement | null;\r\n if (anchor && anchor.href) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.openLinkModal(anchor.href);\r\n }\r\n }\r\n\r\n formatTime(date: Date): string {\r\n return date.toLocaleTimeString('es-CL', { hour: '2-digit', minute: '2-digit' });\r\n }\r\n\r\n renderMarkdown(text: string): SafeHtml {\r\n if (!text) return '';\r\n try {\r\n let preprocessed = this.preprocessMarkdownTable(text);\r\n // Encode spaces in markdown image & link URLs:  and [text](url)\r\n preprocessed = preprocessed.replace(\r\n /(!?\\[[^\\]]*\\])\\(([^)]+)\\)/g,\r\n (_match: string, bracket: string, url: string) => `${bracket}(${url.replace(/ /g, '%20')})`\r\n );\r\n let html = marked.parse(preprocessed, { breaks: true }) as string;\r\n // Inject inline styles + onerror on <img> to force small thumbnails & hide broken ones\r\n const imgStyle = `style=\"max-height:48px;max-width:100px;object-fit:contain;border-radius:6px;cursor:pointer;display:inline-block;vertical-align:middle;margin:2px 4px;border:1px solid rgba(255,255,255,0.15);box-shadow:0 1px 3px rgba(0,0,0,0.2);\"`;\r\n html = html.replace(/<img /g, `<img ${imgStyle} onerror=\"this.style.display='none'\" `);\r\n return this.sanitizer.bypassSecurityTrustHtml(html);\r\n } catch {\r\n return text;\r\n }\r\n }\r\n\r\n /**\r\n * Pre-process text to ensure pipe-delimited tables render as HTML tables.\r\n *\r\n * The API often returns header + separator + data on ONE line, e.g.:\r\n * \"| Col1 | Col2 | |---|---| | Val1 | Val2 |\"\r\n *\r\n * Step 1: Find the dash-separator pattern (|---|---|) and break the line\r\n * around it so each part (header / separator / data rows) is its\r\n * own line.\r\n * Step 2: Line-by-line cleanup — ensure a blank line exists before the\r\n * first pipe-row and inject a separator if one is still missing.\r\n */\r\n private preprocessMarkdownTable(text: string): string {\r\n // ── Step 1: Break inline separator onto its own line ───────────\r\n // Pattern: the separator row consists only of |, -, :, and spaces.\r\n // We insert \\n before and after it.\r\n text = text.replace(\r\n /\\s*(\\|(?:\\s*:?-{2,}:?\\s*\\|){2,})\\s*/g,\r\n '\\n$1\\n'\r\n );\r\n // Clean up excess blank lines created by step 1\r\n text = text.replace(/\\n{3,}/g, '\\n\\n');\r\n\r\n // ── Step 2: Line-by-line processing ───────────────────────────\r\n const lines = text.split('\\n');\r\n const result: string[] = [];\r\n let inTable = false;\r\n\r\n const isPipeLine = (l: string) => {\r\n const t = l.trim();\r\n return t.startsWith('|') && t.split('|').length > 3;\r\n };\r\n const isSepLine = (l: string) =>\r\n /^\\|(?:\\s*:?-{2,}:?\\s*\\|){2,}\\s*$/.test(l.trim());\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n const trimmed = line.trim();\r\n\r\n if (isPipeLine(trimmed) && !isSepLine(trimmed)) {\r\n if (!inTable) {\r\n inTable = true;\r\n // Insert blank line before table if preceded by non-empty text\r\n if (result.length > 0 && result[result.length - 1].trim() !== '') {\r\n result.push('');\r\n }\r\n result.push(line);\r\n // Inject separator if the next line isn't one\r\n const next = (i + 1 < lines.length) ? lines[i + 1] : '';\r\n if (!isSepLine(next)) {\r\n const cols = trimmed.split('|').filter(c => c.trim() !== '').length;\r\n result.push('| ' + Array(cols).fill('---').join(' | ') + ' |');\r\n }\r\n } else {\r\n result.push(line); // data row\r\n }\r\n } else if (isSepLine(trimmed)) {\r\n if (!inTable) inTable = true; // edge-case: separator before header\r\n result.push(line);\r\n } else {\r\n inTable = false;\r\n result.push(line);\r\n }\r\n }\r\n\r\n return result.join('\\n');\r\n }\r\n\r\n // ─── Private ───────────────────────────────────────────\r\n\r\n private handleError(error: any): void {\r\n const status = error?.status;\r\n if (status === 401 || status === 403) {\r\n const msg = status === 401 ? 'Token inválido o expirado' : 'Sin permisos para este sistema';\r\n this.authError.set(`🔒 ${msg}`);\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text: `⚠️ ${msg}. Verifica el token y el systemId configurados.`,\r\n sender: 'bot',\r\n timestamp: new Date()\r\n }]);\r\n } else {\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text: `Error: ${error.error?.message || error.error?.error || 'No se pudo procesar la consulta'}`,\r\n sender: 'bot',\r\n timestamp: new Date()\r\n }]);\r\n }\r\n this.saveSession();\r\n this.shouldScroll = true;\r\n }\r\n\r\n private stopPipelineSteps(): void {\r\n this.pipelineStep = '';\r\n }\r\n\r\n private scrollToBottom(): void {\r\n if (this.chatContainer) {\r\n const el = this.chatContainer.nativeElement;\r\n el.scrollTop = el.scrollHeight;\r\n }\r\n }\r\n\r\n // ─── Session Persistence ──────────────────────────\r\n\r\n private buildSessionKey(): string {\r\n const cfg = this.resolvedConfig();\r\n if (!cfg.token || !cfg.systemId) return '';\r\n // Simple hash-like key from systemId + first 8 chars of token\r\n const tokenPrefix = cfg.token.substring(0, 8);\r\n return `${this.STORAGE_PREFIX}${cfg.systemId}_${tokenPrefix}`;\r\n }\r\n\r\n private saveSession(): void {\r\n if (!this.sessionKey) return;\r\n try {\r\n const data = this.messages().map(m => ({\r\n id: m.id,\r\n text: m.text,\r\n sender: m.sender,\r\n timestamp: m.timestamp,\r\n traceData: m.traceData\r\n }));\r\n localStorage.setItem(this.sessionKey, JSON.stringify(data));\r\n } catch { /* ignore quota errors */ }\r\n }\r\n\r\n private loadSession(): void {\r\n if (!this.sessionKey) return;\r\n try {\r\n const raw = localStorage.getItem(this.sessionKey);\r\n if (!raw) { this.messages.set([]); return; }\r\n const data: any[] = JSON.parse(raw);\r\n const msgs: ChatMessage[] = data.map(m => ({\r\n ...m,\r\n timestamp: new Date(m.timestamp)\r\n }));\r\n this.messages.set(msgs);\r\n this.messageId = msgs.length > 0 ? Math.max(...msgs.map(m => m.id)) + 1 : 0;\r\n this.shouldScroll = true;\r\n } catch { this.messages.set([]); }\r\n }\r\n\r\n private clearSession(): void {\r\n if (this.sessionKey) {\r\n try { localStorage.removeItem(this.sessionKey); } catch {}\r\n }\r\n }\r\n\r\n /** Called when another tab modifies localStorage */\r\n private onStorageChange(e: StorageEvent): void {\r\n if (!this.sessionKey || e.key !== this.sessionKey) return;\r\n if (e.newValue === null) {\r\n // Session was cleared in another tab\r\n this.messages.set([]);\r\n } else {\r\n this.loadSession();\r\n }\r\n this.shouldScroll = true;\r\n }\r\n}\r\n","/*\r\n * Public API Surface of maquito-chat-plugin\r\n */\r\n\r\nexport type { IntelligentChatConfig, ChatMessage, PluginTheme } from './lib/intelligent-chat.models';\r\nexport { IntelligentChatService } from './lib/intelligent-chat.service';\r\nexport { IntelligentChatPluginComponent } from './lib/intelligent-chat-plugin.component';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"maquito-chat-plugin.mjs","sources":["../../../frontend/maquito-chat-plugin/src/lib/intelligent-chat.service.ts","../../../frontend/maquito-chat-plugin/src/lib/intelligent-chat-plugin.component.ts","../../../frontend/maquito-chat-plugin/src/public-api.ts","../../../frontend/maquito-chat-plugin/src/maquito-chat-plugin.ts"],"sourcesContent":["import { Injectable, inject } from '@angular/core';\r\nimport { HttpClient, HttpHeaders } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\n\r\n/**\r\n * Standalone HTTP service for the Maquito Chat Plugin.\r\n * Decoupled from any host app service — uses apiUrl + token from config.\r\n * Replicates exactly the same endpoints used by the Maquito Core API.\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class IntelligentChatService {\r\n\r\n private http = inject(HttpClient);\r\n\r\n /**\r\n * Execute an intelligent query (POST /api/query).\r\n * Auth via X-Api-Key header.\r\n */\r\n executeIntelligentQuery(\r\n apiUrl: string,\r\n token: string,\r\n systemId: string,\r\n question: string,\r\n conversationHistory: { role: string; content: string }[] = [],\r\n baseContext?: string,\r\n skipPatternCache?: boolean,\r\n preferTableFormat?: boolean,\r\n userName?: string,\r\n personality?: string\r\n ): Observable<any> {\r\n const headers = this.buildHeaders(token);\r\n const body: any = { systemId, question, conversationHistory };\r\n if (baseContext) body.baseContext = baseContext;\r\n if (skipPatternCache) body.skipPatternCache = skipPatternCache;\r\n if (preferTableFormat !== undefined) body.preferTableFormat = preferTableFormat;\r\n if (userName) body.userName = userName;\r\n if (personality) body.personality = personality;\r\n return this.http.post<any>(`${apiUrl}/query`, body, { headers });\r\n }\r\n\r\n /**\r\n * Execute an intelligent query with SSE streaming progress.\r\n * Emits: { type: 'progress', step: string, message: string }\r\n * { type: 'result', data: any }\r\n */\r\n executeIntelligentQueryStream(\r\n apiUrl: string,\r\n token: string,\r\n systemId: string,\r\n question: string,\r\n conversationHistory: { role: string; content: string }[] = [],\r\n baseContext?: string,\r\n skipPatternCache?: boolean,\r\n preferTableFormat?: boolean,\r\n userName?: string,\r\n personality?: string\r\n ): Observable<{ type: 'progress' | 'result'; step?: string; message?: string; data?: any }> {\r\n const body: any = { systemId, question, conversationHistory };\r\n if (baseContext) body.baseContext = baseContext;\r\n if (skipPatternCache) body.skipPatternCache = skipPatternCache;\r\n if (preferTableFormat !== undefined) body.preferTableFormat = preferTableFormat;\r\n if (userName) body.userName = userName;\r\n if (personality) body.personality = personality;\r\n\r\n const FETCH_TIMEOUT_MS = 120_000; // 2 min max for the entire request\r\n const INACTIVITY_TIMEOUT_MS = 60_000; // 60s without data = abort\r\n\r\n return new Observable(observer => {\r\n const abortController = new AbortController();\r\n\r\n // Combine user abort + global timeout\r\n let signal: AbortSignal;\r\n if (typeof AbortSignal.any === 'function') {\r\n signal = AbortSignal.any([abortController.signal, AbortSignal.timeout(FETCH_TIMEOUT_MS)]);\r\n } else {\r\n // Fallback for older browsers\r\n signal = abortController.signal;\r\n setTimeout(() => abortController.abort(), FETCH_TIMEOUT_MS);\r\n }\r\n\r\n fetch(`${apiUrl}/query/stream`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json', 'X-Api-Key': token },\r\n body: JSON.stringify(body),\r\n signal\r\n }).then(async response => {\r\n if (!response.ok || !response.body) {\r\n observer.error(new Error(`HTTP ${response.status}`));\r\n return;\r\n }\r\n const reader = response.body.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = '';\r\n let lastDataTime = Date.now();\r\n\r\n while (true) {\r\n // Race reader vs inactivity timeout\r\n const readPromise = reader.read();\r\n const timeoutPromise = new Promise<never>((_, reject) => {\r\n const elapsed = Date.now() - lastDataTime;\r\n const remaining = Math.max(INACTIVITY_TIMEOUT_MS - elapsed, 100);\r\n setTimeout(() => reject(new Error('SSE inactivity timeout: no data received for 60s')), remaining);\r\n });\r\n\r\n let result: ReadableStreamReadResult<Uint8Array>;\r\n try {\r\n result = await Promise.race([readPromise, timeoutPromise]);\r\n } catch (err) {\r\n reader.cancel();\r\n abortController.abort();\r\n observer.error(err);\r\n return;\r\n }\r\n\r\n const { done, value } = result;\r\n if (done) break;\r\n lastDataTime = Date.now();\r\n buffer += decoder.decode(value, { stream: true });\r\n\r\n const parts = buffer.split('\\n\\n');\r\n buffer = parts.pop() || '';\r\n for (const part of parts) {\r\n const lines = part.split('\\n');\r\n let eventType = '';\r\n let eventData = '';\r\n for (const line of lines) {\r\n if (line.startsWith('event: ')) eventType = line.slice(7);\r\n else if (line.startsWith('data: ')) eventData = line.slice(6);\r\n }\r\n if (!eventType || !eventData) continue;\r\n try {\r\n const parsed = JSON.parse(eventData);\r\n if (eventType === 'progress') {\r\n observer.next({ type: 'progress', step: parsed.step, message: parsed.message });\r\n } else if (eventType === 'result') {\r\n observer.next({ type: 'result', data: parsed });\r\n observer.complete();\r\n } else if (eventType === 'error') {\r\n observer.error(parsed);\r\n }\r\n } catch { /* skip malformed JSON */ }\r\n }\r\n }\r\n if (!observer.closed) observer.complete();\r\n }).catch(err => {\r\n if (err.name !== 'AbortError') observer.error(err);\r\n });\r\n\r\n return () => abortController.abort();\r\n });\r\n }\r\n\r\n /**\r\n * Standard orchestration ask (POST /api/cortex/ask).\r\n * Used when intelligent query mode is disabled.\r\n */\r\n ask(apiUrl: string, token: string, text: string): Observable<any> {\r\n const headers = this.buildHeaders(token);\r\n return this.http.post<any>(`${apiUrl}/cortex/ask`, { text }, { headers });\r\n }\r\n\r\n private buildHeaders(token: string): HttpHeaders {\r\n return new HttpHeaders({ 'X-Api-Key': token });\r\n }\r\n}\r\n","import {\r\n Component, Input, inject, signal, computed, ViewChild, ElementRef,\r\n AfterViewChecked, OnChanges, OnInit, OnDestroy, SimpleChanges, HostListener\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { DomSanitizer, SafeHtml, SafeResourceUrl } from '@angular/platform-browser';\r\nimport { marked } from 'marked';\r\nimport { Subscription } from 'rxjs';\r\nimport { IntelligentChatConfig, ChatMessage, PluginTheme } from './intelligent-chat.models';\r\nimport { IntelligentChatService } from './intelligent-chat.service';\r\n\r\n@Component({\r\n selector: 'intelligent-chat-plugin',\r\n standalone: true,\r\n imports: [CommonModule, FormsModule],\r\n template: `\r\n <!-- Host theme overrides -->\r\n <div class=\"iq-theme-host\" [ngStyle]=\"themeStyles()\">\r\n\r\n <!-- Floating Bubble Button (hidden when expanded) -->\r\n @if (!isExpanded()) {\r\n <button\r\n class=\"iq-bubble\"\r\n [class.iq-bottom-left]=\"resolvedConfig().position === 'bottom-left'\"\r\n [class.iq-open]=\"isOpen()\"\r\n [style.position]=\"resolvedConfig().stickyBubble ? 'fixed' : 'absolute'\"\r\n (click)=\"toggleChat()\"\r\n [attr.aria-label]=\"isOpen() ? 'Cerrar chat' : 'Abrir chat'\"\r\n >\r\n @if (isOpen()) {\r\n <span class=\"iq-bubble-icon\">✕</span>\r\n } @else {\r\n @switch (resolvedConfig().bubbleIconType) {\r\n @case ('image') {\r\n <img [src]=\"resolvedConfig().bubbleImageUrl\" alt=\"Chat\" class=\"iq-bubble-img\" />\r\n }\r\n @case ('svg') {\r\n <span class=\"iq-bubble-svg\" [innerHTML]=\"sanitizedBubbleSvg()\"></span>\r\n }\r\n @default {\r\n <span class=\"iq-bubble-icon\">{{ resolvedConfig().bubbleIcon }}</span>\r\n }\r\n }\r\n }\r\n </button>\r\n }\r\n\r\n <!-- Chat Panel -->\r\n @if (isOpen()) {\r\n <div\r\n class=\"iq-panel\"\r\n [class.iq-bottom-left]=\"resolvedConfig().position === 'bottom-left'\"\r\n [class.iq-expanded]=\"isExpanded()\"\r\n [class]=\"resolvedConfig().themeClass || ''\"\r\n [style.position]=\"resolvedConfig().stickyBubble ? 'fixed' : 'absolute'\"\r\n >\r\n <!-- Header -->\r\n <div class=\"iq-header\">\r\n <span class=\"iq-header-title\">{{ resolvedConfig().title }}</span>\r\n <div class=\"iq-header-actions\">\r\n <button class=\"iq-header-btn\" (click)=\"clearChat()\" title=\"Limpiar chat\">🗑️</button>\r\n @if (resolvedConfig().allowExpand) {\r\n <button class=\"iq-header-btn iq-btn-expand\" (click)=\"toggleExpand()\" [title]=\"isExpanded() ? 'Contraer' : 'Expandir'\">\r\n {{ isExpanded() ? '⊡' : '⛶' }}\r\n </button>\r\n }\r\n <button class=\"iq-header-btn\" (click)=\"isExpanded() ? toggleExpand() : toggleChat()\">✕</button>\r\n </div>\r\n </div>\r\n\r\n <!-- Auth Error Banner -->\r\n @if (authError()) {\r\n <div class=\"iq-auth-error\">\r\n <span>🔒</span>\r\n <span>{{ authError() }}</span>\r\n </div>\r\n }\r\n\r\n <!-- Messages -->\r\n <div class=\"iq-messages\" #chatContainer>\r\n @if (messages().length === 0 && !authError()) {\r\n <div class=\"iq-empty\">\r\n <div class=\"iq-empty-icon\">\r\n @switch (resolvedConfig().bubbleIconType) {\r\n @case ('image') {\r\n <img [src]=\"resolvedConfig().bubbleImageUrl\" alt=\"\" class=\"iq-empty-img\" />\r\n }\r\n @case ('svg') {\r\n <span class=\"iq-empty-svg\" [innerHTML]=\"sanitizedBubbleSvg()\"></span>\r\n }\r\n @default {\r\n <span>{{ resolvedConfig().bubbleIcon }}</span>\r\n }\r\n }\r\n </div>\r\n <p>{{ resolvedConfig().welcomeTitle }}</p>\r\n <p class=\"iq-text-muted\">{{ resolvedConfig().welcomeSubtitle }}</p>\r\n </div>\r\n }\r\n\r\n @for (msg of messages(); track msg.id) {\r\n <div class=\"iq-msg\" [class.iq-msg-user]=\"msg.sender === 'user'\" [class.iq-msg-bot]=\"msg.sender === 'bot'\">\r\n <div class=\"iq-msg-content\">\r\n @if (msg.sender === 'bot') {\r\n <div class=\"iq-md\" [innerHTML]=\"renderMarkdown(msg.text)\" (click)=\"onMessageClick($event)\"></div>\r\n } @else {\r\n <p>{{ msg.text }}</p>\r\n }\r\n <span class=\"iq-msg-time\">{{ formatTime(msg.timestamp) }}</span>\r\n </div>\r\n @if (msg.sender === 'bot' && msg.traceData && resolvedConfig().showTrace) {\r\n <button class=\"iq-btn-trace\" (click)=\"showTrace(msg)\">🔍 Ver Traza</button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Pipeline progress -->\r\n @if (isLoading()) {\r\n <div class=\"iq-msg iq-msg-bot\">\r\n <div class=\"iq-msg-content iq-pipeline\">\r\n <span class=\"iq-dot\"></span>\r\n <span class=\"iq-pipeline-text\">{{ pipelineStep }}</span>\r\n <button class=\"iq-cancel-btn\" (click)=\"cancelQuery()\" title=\"Cancelar consulta\">✕</button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Input -->\r\n <form class=\"iq-input-bar\" (ngSubmit)=\"sendMessage()\">\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"inputText\"\r\n name=\"message\"\r\n [placeholder]=\"resolvedConfig().placeholder!\"\r\n [disabled]=\"isLoading() || !!authError()\"\r\n autocomplete=\"off\"\r\n />\r\n <button type=\"submit\" class=\"iq-btn-send\" [disabled]=\"isLoading() || !inputText.trim() || !!authError()\">\r\n ➤\r\n </button>\r\n </form>\r\n </div>\r\n }\r\n\r\n <!-- Trace Modal Overlay -->\r\n @if (selectedTrace()) {\r\n <div class=\"iq-trace-overlay\" (click)=\"closeTrace()\">\r\n <div class=\"iq-trace-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"iq-trace-header\">\r\n <h3>🔍 Detalle de Traza</h3>\r\n <button class=\"iq-header-btn\" (click)=\"closeTrace()\">✕</button>\r\n </div>\r\n <div class=\"iq-trace-body\">\r\n @if (selectedTrace()?.fromCache !== undefined) {\r\n <div class=\"iq-trace-item\">\r\n <label>Origen</label>\r\n <code [class.iq-cache-hit]=\"selectedTrace()?.fromCache\">{{ selectedTrace()?.fromCache ? '📚 Desde Caché' : '🤖 Generado por GPT' }}</code>\r\n </div>\r\n }\r\n @if (selectedTrace()?.query) {\r\n <div class=\"iq-trace-item\">\r\n <label>Query Generada</label>\r\n <pre class=\"iq-query-code\">{{ selectedTrace()?.query }}</pre>\r\n </div>\r\n }\r\n @if (selectedTrace()?.explanation) {\r\n <div class=\"iq-trace-item\">\r\n <label>Explicación</label>\r\n <code>{{ selectedTrace()?.explanation }}</code>\r\n </div>\r\n }\r\n @if (selectedTrace()?.traceId) {\r\n <div class=\"iq-trace-item\">\r\n <label>Trace ID</label>\r\n <code>{{ selectedTrace()?.traceId }}</code>\r\n </div>\r\n }\r\n @if (selectedTrace()?.data) {\r\n <div class=\"iq-trace-item\">\r\n <label>Datos Retornados</label>\r\n <pre>{{ selectedTrace()?.data | json }}</pre>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Link Modal Overlay -->\r\n @if (modalUrl()) {\r\n <div class=\"iq-link-overlay\" (click)=\"closeLinkModal()\">\r\n <div class=\"iq-link-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"iq-link-header\">\r\n @if (showHomeBtn()) {\r\n <button class=\"iq-header-btn iq-back-btn\" (click)=\"iframeGoHome()\" title=\"Volver al inicio\">🏠</button>\r\n }\r\n <span class=\"iq-link-title\" [title]=\"modalUrl()!\">{{ modalUrl() }}</span>\r\n <div class=\"iq-link-actions\">\r\n <a [href]=\"modalUrl()!\" target=\"_blank\" rel=\"noopener\" class=\"iq-header-btn\" title=\"Abrir en nueva pestaña\">↗</a>\r\n <button class=\"iq-header-btn\" (click)=\"closeLinkModal()\">✕</button>\r\n </div>\r\n </div>\r\n <div class=\"iq-iframe-wrapper\">\r\n @if (isModalImage()) {\r\n <img [src]=\"modalUrl()!\" class=\"iq-modal-img\" alt=\"Imagen\" />\r\n } @else {\r\n @if (modalLoading()) {\r\n <div class=\"iq-iframe-loader\">\r\n <div class=\"iq-spinner\"></div>\r\n <span class=\"iq-loader-text\">Cargando...</span>\r\n </div>\r\n }\r\n <iframe #linkIframe [src]=\"sanitizedModalUrl()\" class=\"iq-link-iframe\"\r\n [class.iq-iframe-hidden]=\"modalLoading()\"\r\n (load)=\"onIframeLoaded()\"></iframe>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n </div><!-- /iq-theme-host -->\r\n `,\r\n styles: [`\r\n /* ========= CSS Custom Properties (overridable by host) ========= */\r\n :host {\r\n --iq-primary: #1a3a5c;\r\n --iq-primary-light: #2a5a8c;\r\n --iq-accent: #00d4aa;\r\n --iq-accent-light: #33e0be;\r\n --iq-bg: #1e1e2f;\r\n --iq-bg-card: #252538;\r\n --iq-bg-tertiary: #35354a;\r\n --iq-text: #ffffff;\r\n --iq-text-secondary: #a0a0b0;\r\n --iq-text-muted: #6c6c7c;\r\n --iq-border: #3a3a4d;\r\n --iq-radius: 12px;\r\n --iq-bubble-size: 56px;\r\n --iq-panel-width: 400px;\r\n --iq-panel-height: 520px;\r\n --iq-z: 10000;\r\n --iq-font: 'Inter', 'Roboto', -apple-system, BlinkMacSystemFont, sans-serif;\r\n font-family: var(--iq-font);\r\n }\r\n\r\n /* ========= Bubble ========= */\r\n .iq-bubble {\r\n position: fixed;\r\n bottom: 24px;\r\n right: 24px;\r\n z-index: var(--iq-z);\r\n width: var(--iq-bubble-size);\r\n height: var(--iq-bubble-size);\r\n border-radius: 50%;\r\n border: none;\r\n background: linear-gradient(135deg, var(--iq-accent), var(--iq-accent-light));\r\n color: var(--iq-bg);\r\n font-size: 1.6rem;\r\n cursor: pointer;\r\n box-shadow: 0 4px 16px rgba(0, 212, 170, 0.4);\r\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n .iq-bubble:hover {\r\n transform: scale(1.1);\r\n box-shadow: 0 6px 24px rgba(0, 212, 170, 0.5);\r\n }\r\n .iq-bubble .iq-bubble-icon {\r\n font-size: 1.5rem;\r\n pointer-events: none;\r\n }\r\n\r\n .iq-bubble-img {\r\n width: 60%; height: 60%;\r\n object-fit: contain; border-radius: 50%;\r\n pointer-events: none;\r\n }\r\n\r\n .iq-bubble-svg {\r\n width: 60%; height: 60%;\r\n display: flex; align-items: center; justify-content: center;\r\n pointer-events: none;\r\n }\r\n .iq-bubble-svg :deep(svg) { width: 100%; height: 100%; }\r\n\r\n .iq-bubble.iq-open {\r\n background: var(--iq-bg-tertiary);\r\n color: var(--iq-text);\r\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\r\n font-size: 1.2rem;\r\n }\r\n .iq-bubble.iq-bottom-left {\r\n right: auto;\r\n left: 24px;\r\n }\r\n .iq-bubble-icon { line-height: 1; }\r\n\r\n /* ========= Panel ========= */\r\n .iq-panel {\r\n position: fixed;\r\n bottom: 92px;\r\n right: 24px;\r\n z-index: var(--iq-z);\r\n width: var(--iq-panel-width);\r\n height: var(--iq-panel-height);\r\n background: var(--iq-bg);\r\n border: 1px solid var(--iq-border);\r\n border-radius: var(--iq-radius);\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n box-shadow: 0 12px 40px rgba(0,0,0,0.5);\r\n animation: iq-slide-up 0.3s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n .iq-panel.iq-bottom-left {\r\n right: auto;\r\n left: 24px;\r\n }\r\n /* ========= Expanded / Fullscreen ========= */\r\n .iq-panel.iq-expanded {\r\n width: 100vw !important;\r\n height: 100vh !important;\r\n top: 0 !important;\r\n left: 0 !important;\r\n right: 0 !important;\r\n bottom: 0 !important;\r\n border: none;\r\n border-radius: 0;\r\n overflow: clip;\r\n z-index: calc(var(--iq-z) + 5);\r\n animation: iq-expand 0.3s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n .iq-btn-expand {\r\n font-size: 1.1rem !important;\r\n }\r\n @keyframes iq-expand {\r\n from { opacity: 0.8; transform: scale(0.95); }\r\n to { opacity: 1; transform: scale(1); }\r\n }\r\n @keyframes iq-slide-up {\r\n from { opacity: 0; transform: translateY(16px) scale(0.96); }\r\n to { opacity: 1; transform: translateY(0) scale(1); }\r\n }\r\n\r\n /* ========= Header ========= */\r\n .iq-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--iq-border);\r\n background: var(--iq-bg-card);\r\n }\r\n .iq-header-title {\r\n font-weight: 600;\r\n font-size: 0.95rem;\r\n color: var(--iq-text);\r\n }\r\n .iq-header-actions {\r\n display: flex;\r\n gap: 4px;\r\n }\r\n .iq-header-btn {\r\n background: none;\r\n border: none;\r\n color: var(--iq-text-muted);\r\n cursor: pointer;\r\n font-size: 1rem;\r\n padding: 4px 6px;\r\n border-radius: 4px;\r\n transition: all 0.15s;\r\n }\r\n .iq-header-btn:hover {\r\n color: var(--iq-text);\r\n background: rgba(255,255,255,0.08);\r\n }\r\n\r\n /* ========= Auth Error ========= */\r\n .iq-auth-error {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 10px 16px;\r\n background: rgba(220, 53, 69, 0.15);\r\n color: #ff6b7a;\r\n font-size: 0.8rem;\r\n border-bottom: 1px solid rgba(220, 53, 69, 0.25);\r\n }\r\n\r\n /* ========= Messages ========= */\r\n .iq-messages {\r\n flex: 1;\r\n min-height: 0;\r\n overflow-y: auto;\r\n padding: 12px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 10px;\r\n }\r\n\r\n .iq-empty {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n text-align: center;\r\n color: var(--iq-text-secondary);\r\n }\r\n .iq-empty-icon { font-size: 3rem; margin-bottom: 8px; display: flex; align-items: center; justify-content: center; }\r\n .iq-empty-img { width: 48px; height: 48px; object-fit: contain; border-radius: 8px; }\r\n .iq-empty-svg { width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; }\r\n .iq-empty-svg :deep(svg) { width: 100%; height: 100%; }\r\n .iq-empty p { font-size: 0.95rem; margin: 2px 0; }\r\n .iq-text-muted { color: var(--iq-text-muted) !important; font-size: 0.8rem !important; }\r\n\r\n .iq-msg { display: flex; flex-direction: column; max-width: 85%; }\r\n .iq-msg-user { align-self: flex-end; }\r\n .iq-msg-bot { align-self: flex-start; max-width: 100%; }\r\n\r\n .iq-msg-user .iq-msg-content {\r\n background: linear-gradient(135deg, var(--iq-primary), var(--iq-primary-light));\r\n border-radius: 12px 12px 0 12px;\r\n }\r\n .iq-msg-bot .iq-msg-content {\r\n background: var(--iq-bg-tertiary);\r\n border-radius: 12px 12px 12px 0;\r\n }\r\n .iq-msg-content {\r\n padding: 10px 14px;\r\n color: var(--iq-text);\r\n font-size: 0.85rem;\r\n line-height: 1.45;\r\n }\r\n .iq-msg-content p { margin: 0; white-space: pre-wrap; }\r\n .iq-msg-time {\r\n display: block;\r\n margin-top: 4px;\r\n font-size: 0.65rem;\r\n color: rgba(255,255,255,0.5);\r\n }\r\n\r\n /* Markdown rendered content */\r\n .iq-md { line-height: 1.5; overflow-x: auto; max-width: 100%; }\r\n .iq-md :first-child { margin-top: 0; }\r\n .iq-md :last-child { margin-bottom: 0; }\r\n .iq-md p { margin: 0 0 0.4em 0; }\r\n .iq-md p:last-child { margin-bottom: 0; }\r\n .iq-md strong { color: var(--iq-accent); }\r\n .iq-md ul, .iq-md ol { margin: 0.3em 0; padding-left: 1.2em; }\r\n .iq-md li { margin: 0.15em 0; }\r\n .iq-md code {\r\n background: rgba(0,0,0,0.3);\r\n padding: 0.15em 0.4em;\r\n border-radius: 3px;\r\n font-size: 0.82em;\r\n }\r\n .iq-md pre {\r\n background: rgba(0,0,0,0.3);\r\n padding: 0.8em;\r\n border-radius: 6px;\r\n overflow-x: auto;\r\n font-size: 0.78em;\r\n margin: 0.4em 0;\r\n }\r\n .iq-md pre code { background: none; padding: 0; }\r\n .iq-md table {\r\n width: max-content; min-width: 100%;\r\n border-collapse: separate; border-spacing: 0;\r\n margin: 0.5em 0; font-size: 0.75rem;\r\n border-radius: 6px; overflow: hidden;\r\n }\r\n .iq-md thead th {\r\n background: rgba(99,102,241,0.18); color: #a5b4fc;\r\n font-weight: 600; text-align: left;\r\n padding: 0.5em 0.8em; border-bottom: 2px solid rgba(99,102,241,0.3);\r\n white-space: nowrap; font-size: 0.7rem;\r\n text-transform: uppercase; letter-spacing: 0.05em;\r\n }\r\n .iq-md tbody td {\r\n padding: 0.4em 0.8em; border-bottom: 1px solid rgba(255,255,255,0.06);\r\n white-space: nowrap; color: var(--iq-text-secondary);\r\n }\r\n .iq-md tbody tr:hover { background: rgba(99,102,241,0.08); }\r\n\r\n /* Inline images in bot messages – small thumbnails, click to enlarge */\r\n .iq-md img {\r\n max-height: 80px; max-width: 120px; object-fit: cover;\r\n border-radius: 8px; margin: 6px 4px 6px 0;\r\n display: inline-block; vertical-align: middle;\r\n border: 1px solid rgba(255,255,255,0.15);\r\n box-shadow: 0 1px 4px rgba(0,0,0,0.25);\r\n cursor: pointer; transition: transform 0.15s, box-shadow 0.15s;\r\n }\r\n .iq-md img:hover {\r\n transform: scale(1.05);\r\n box-shadow: 0 3px 12px rgba(99,102,241,0.35);\r\n border-color: var(--iq-accent);\r\n }\r\n .iq-md img[alt*=\"logo\"], .iq-md img[alt*=\"marca\"] {\r\n max-height: 28px; max-width: 90px; object-fit: contain;\r\n border: none; box-shadow: none; border-radius: 4px;\r\n background: rgba(255,255,255,0.9); padding: 2px 6px;\r\n }\r\n /* Trace button */\r\n .iq-btn-trace {\r\n align-self: flex-start; margin-top: 4px;\r\n background: transparent; border: 1px solid var(--iq-border);\r\n color: var(--iq-text-secondary); font-size: 0.7rem;\r\n padding: 3px 8px; border-radius: 4px; cursor: pointer;\r\n transition: all 0.15s;\r\n }\r\n .iq-btn-trace:hover { border-color: var(--iq-accent); color: var(--iq-accent); }\r\n\r\n /* Pipeline loading indicator */\r\n .iq-pipeline {\r\n display: flex; align-items: center; gap: 8px;\r\n animation: iq-fade-in 0.3s ease-out;\r\n }\r\n .iq-dot {\r\n width: 8px; height: 8px; border-radius: 50%;\r\n background: var(--iq-accent);\r\n animation: iq-pulse 1s ease-in-out infinite;\r\n }\r\n .iq-pipeline-text {\r\n font-size: 0.8rem; color: var(--iq-text-muted); font-style: italic;\r\n flex: 1;\r\n }\r\n .iq-cancel-btn {\r\n background: transparent; border: 1px solid var(--iq-border);\r\n color: var(--iq-text-muted); font-size: 0.7rem;\r\n padding: 2px 8px; border-radius: 4px; cursor: pointer;\r\n transition: all 0.15s; flex-shrink: 0;\r\n }\r\n .iq-cancel-btn:hover {\r\n border-color: #ff6b6b; color: #ff6b6b; background: rgba(255, 107, 107, 0.1);\r\n }\r\n @keyframes iq-pulse {\r\n 0%, 100% { opacity: 1; transform: scale(1); }\r\n 50% { opacity: 0.4; transform: scale(0.7); }\r\n }\r\n @keyframes iq-fade-in {\r\n from { opacity: 0; transform: translateX(-6px); }\r\n to { opacity: 1; transform: translateX(0); }\r\n }\r\n\r\n /* ========= Input Bar ========= */\r\n .iq-input-bar {\r\n display: flex; gap: 8px;\r\n padding: 10px 12px;\r\n border-top: 1px solid var(--iq-border);\r\n background: var(--iq-bg-card);\r\n }\r\n .iq-input-bar input {\r\n flex: 1; padding: 8px 12px;\r\n background: var(--iq-bg-tertiary);\r\n border: 1px solid var(--iq-border);\r\n border-radius: 8px;\r\n color: var(--iq-text);\r\n font-size: 0.85rem;\r\n font-family: var(--iq-font);\r\n outline: none;\r\n transition: border-color 0.15s;\r\n }\r\n .iq-input-bar input:focus { border-color: var(--iq-accent); }\r\n .iq-input-bar input::placeholder { color: var(--iq-text-muted); }\r\n .iq-input-bar input:disabled { opacity: 0.5; }\r\n .iq-btn-send {\r\n width: 36px; height: 36px;\r\n border-radius: 8px; border: none;\r\n background: linear-gradient(135deg, var(--iq-accent), var(--iq-accent-light));\r\n color: var(--iq-bg); font-size: 1rem;\r\n cursor: pointer; transition: all 0.2s;\r\n display: flex; align-items: center; justify-content: center;\r\n }\r\n .iq-btn-send:hover:not(:disabled) { box-shadow: 0 0 12px rgba(0,212,170,0.4); transform: translateY(-1px); }\r\n .iq-btn-send:disabled { opacity: 0.4; cursor: not-allowed; }\r\n\r\n /* ========= Trace Modal ========= */\r\n .iq-trace-overlay {\r\n position: fixed; inset: 0;\r\n z-index: calc(var(--iq-z) + 10);\r\n background: rgba(0,0,0,0.6);\r\n display: flex; align-items: center; justify-content: center;\r\n animation: iq-fade-in 0.2s ease-out;\r\n }\r\n .iq-trace-modal {\r\n width: 90%; max-width: 520px; max-height: 80vh;\r\n background: var(--iq-bg); border: 1px solid var(--iq-border);\r\n border-radius: var(--iq-radius);\r\n display: flex; flex-direction: column; overflow: hidden;\r\n box-shadow: 0 20px 50px rgba(0,0,0,0.6);\r\n }\r\n .iq-trace-header {\r\n display: flex; align-items: center; justify-content: space-between;\r\n padding: 14px 16px; border-bottom: 1px solid var(--iq-border);\r\n }\r\n .iq-trace-header h3 { margin: 0; font-size: 0.95rem; color: var(--iq-text); }\r\n .iq-trace-body {\r\n flex: 1; overflow-y: auto; padding: 16px;\r\n display: flex; flex-direction: column; gap: 12px;\r\n }\r\n .iq-trace-item label {\r\n display: block; font-size: 0.7rem; color: var(--iq-text-muted);\r\n margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.05em;\r\n }\r\n .iq-trace-item code {\r\n display: block; padding: 8px;\r\n background: var(--iq-bg-tertiary); border-radius: 4px;\r\n font-family: monospace; font-size: 0.8rem; color: var(--iq-accent);\r\n word-break: break-all;\r\n }\r\n .iq-trace-item pre {\r\n margin: 0; padding: 8px;\r\n background: var(--iq-bg-tertiary); border-radius: 4px;\r\n font-family: monospace; font-size: 0.7rem;\r\n overflow-x: auto; max-height: 180px; color: var(--iq-text-secondary);\r\n }\r\n .iq-cache-hit { background: rgba(16,185,129,0.15) !important; color: #10b981 !important; }\r\n .iq-query-code { color: var(--iq-accent) !important; }\r\n\r\n /* ========= Link Modal ========= */\r\n .iq-link-overlay {\r\n position: fixed; inset: 0;\r\n z-index: calc(var(--iq-z) + 20);\r\n background: rgba(0,0,0,0.7);\r\n display: flex; align-items: center; justify-content: center;\r\n animation: iq-fade-in 0.2s ease-out;\r\n backdrop-filter: blur(4px);\r\n }\r\n .iq-link-modal {\r\n width: 94vw; height: 92vh;\r\n background: var(--iq-bg); border: 1px solid var(--iq-border);\r\n border-radius: var(--iq-radius);\r\n display: flex; flex-direction: column; overflow: hidden;\r\n box-shadow: 0 24px 60px rgba(0,0,0,0.7);\r\n animation: iq-expand 0.25s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n .iq-link-header {\r\n display: flex; align-items: center; justify-content: space-between;\r\n padding: 10px 16px; border-bottom: 1px solid var(--iq-border);\r\n background: var(--iq-bg-card); gap: 12px; min-height: 44px;\r\n }\r\n .iq-link-title {\r\n flex: 1; font-size: 0.78rem; color: var(--iq-text-secondary);\r\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\r\n font-family: monospace;\r\n }\r\n .iq-link-actions {\r\n display: flex; gap: 4px; flex-shrink: 0;\r\n }\r\n .iq-link-actions a {\r\n text-decoration: none;\r\n }\r\n .iq-back-btn {\r\n flex-shrink: 0; font-size: 1.1rem;\r\n transition: transform 0.15s ease;\r\n }\r\n .iq-back-btn:hover {\r\n transform: translateX(-2px);\r\n }\r\n .iq-iframe-wrapper {\r\n flex: 1; position: relative; overflow: hidden;\r\n }\r\n .iq-link-iframe {\r\n width: 100%; height: 100%; border: none;\r\n background: #fff;\r\n transition: opacity 0.3s ease;\r\n }\r\n .iq-iframe-hidden {\r\n opacity: 0;\r\n }\r\n .iq-modal-img {\r\n width: 100%; height: 100%;\r\n object-fit: contain;\r\n background: #1a1a2e;\r\n }\r\n .iq-iframe-loader {\r\n position: absolute; inset: 0;\r\n display: flex; flex-direction: column;\r\n align-items: center; justify-content: center;\r\n background: var(--iq-bg);\r\n gap: 16px; z-index: 2;\r\n }\r\n .iq-spinner {\r\n width: 40px; height: 40px;\r\n border: 3px solid var(--iq-border);\r\n border-top-color: var(--iq-accent);\r\n border-radius: 50%;\r\n animation: iq-spin 0.8s linear infinite;\r\n }\r\n .iq-loader-text {\r\n font-size: 0.85rem; color: var(--iq-text-secondary);\r\n font-weight: 500;\r\n }\r\n @keyframes iq-spin {\r\n to { transform: rotate(360deg); }\r\n }\r\n\r\n /* ========= Link Modal — markdown link styling ========= */\r\n .iq-md a {\r\n color: var(--iq-accent); text-decoration: underline;\r\n cursor: pointer; transition: color 0.15s;\r\n }\r\n .iq-md a:hover {\r\n color: var(--iq-accent-light);\r\n }\r\n\r\n @media (max-width: 480px) {\r\n .iq-link-modal {\r\n width: 100vw; height: 100dvh;\r\n border-radius: 0;\r\n }\r\n .iq-link-header { padding: 8px 12px; }\r\n .iq-link-title { font-size: 0.7rem; }\r\n }\r\n\r\n /* ========= Scrollbar ========= */\r\n .iq-messages::-webkit-scrollbar { width: 5px; }\r\n .iq-messages::-webkit-scrollbar-track { background: transparent; }\r\n .iq-messages::-webkit-scrollbar-thumb { background: var(--iq-border); border-radius: 4px; }\r\n .iq-trace-body::-webkit-scrollbar { width: 5px; }\r\n .iq-trace-body::-webkit-scrollbar-track { background: transparent; }\r\n .iq-trace-body::-webkit-scrollbar-thumb { background: var(--iq-border); border-radius: 4px; }\r\n /* Wider scrollbar in fullscreen for easier grabbing */\r\n .iq-expanded .iq-messages::-webkit-scrollbar { width: 8px; }\r\n .iq-expanded .iq-messages { scrollbar-gutter: stable; }\r\n\r\n /* ========= Mobile Small Screens ========= */\r\n @media (max-width: 480px) {\r\n .iq-bubble {\r\n bottom: 16px;\r\n right: 16px;\r\n width: 48px;\r\n height: 48px;\r\n font-size: 1.3rem;\r\n }\r\n .iq-bubble.iq-bottom-left {\r\n left: 16px;\r\n }\r\n .iq-bubble .iq-bubble-icon { font-size: 1.2rem; }\r\n\r\n .iq-panel {\r\n right: 8px;\r\n left: 8px;\r\n bottom: 72px;\r\n width: auto !important;\r\n max-width: calc(100vw - 16px);\r\n height: calc(100dvh - 90px);\r\n max-height: calc(100dvh - 90px);\r\n }\r\n .iq-panel.iq-bottom-left {\r\n left: 8px;\r\n right: 8px;\r\n }\r\n .iq-panel.iq-expanded {\r\n top: 0 !important;\r\n left: 0 !important;\r\n right: 0 !important;\r\n bottom: 0 !important;\r\n width: 100vw !important;\r\n height: 100dvh !important;\r\n max-height: 100dvh !important;\r\n max-width: 100vw !important;\r\n border-radius: 0;\r\n }\r\n\r\n .iq-header {\r\n padding: 10px 12px;\r\n }\r\n .iq-header-title { font-size: 0.85rem; }\r\n .iq-header-btn { padding: 6px 8px; min-width: 32px; min-height: 32px; }\r\n\r\n .iq-messages { padding: 8px; gap: 8px; }\r\n\r\n .iq-msg { max-width: 92%; }\r\n .iq-msg-bot { max-width: 100%; }\r\n .iq-msg-content { padding: 8px 10px; font-size: 0.8rem; }\r\n\r\n .iq-md { overflow-x: auto; -webkit-overflow-scrolling: touch; }\r\n .iq-md table { font-size: 0.65rem; min-width: unset; }\r\n .iq-md thead th { padding: 0.35em 0.5em; font-size: 0.6rem; }\r\n .iq-md tbody td { padding: 0.3em 0.5em; font-size: 0.65rem; }\r\n\r\n .iq-empty-icon { font-size: 2.5rem; }\r\n .iq-empty p { font-size: 0.85rem; }\r\n\r\n .iq-input-bar { padding: 8px 10px; gap: 6px; }\r\n .iq-input-bar input { font-size: 16px; padding: 8px 10px; }\r\n .iq-btn-send { width: 38px; height: 38px; flex-shrink: 0; }\r\n\r\n .iq-trace-modal {\r\n width: calc(100vw - 24px);\r\n max-height: 90dvh;\r\n }\r\n .iq-trace-header { padding: 12px; }\r\n .iq-trace-header h3 { font-size: 0.85rem; }\r\n .iq-trace-body { padding: 12px; }\r\n .iq-trace-item pre { font-size: 0.65rem; max-height: 140px; }\r\n }\r\n\r\n /* ========= Landscape Mobile — fit floating panel ========= */\r\n @media (max-height: 500px) and (orientation: landscape) {\r\n .iq-bubble {\r\n bottom: 8px;\r\n right: 8px;\r\n width: 44px;\r\n height: 44px;\r\n font-size: 1.1rem;\r\n }\r\n .iq-bubble.iq-bottom-left { left: 8px; }\r\n\r\n .iq-panel {\r\n right: 60px;\r\n left: 8px;\r\n bottom: 8px;\r\n top: 8px;\r\n width: auto !important;\r\n max-width: calc(100vw - 76px);\r\n height: auto !important;\r\n max-height: calc(100dvh - 16px);\r\n border-radius: var(--iq-radius);\r\n }\r\n .iq-panel.iq-bottom-left {\r\n left: 60px;\r\n right: 8px;\r\n }\r\n .iq-panel.iq-expanded {\r\n top: 0 !important;\r\n left: 0 !important;\r\n right: 0 !important;\r\n bottom: 0 !important;\r\n width: 100vw !important;\r\n height: 100dvh !important;\r\n max-height: 100dvh !important;\r\n max-width: 100vw !important;\r\n border-radius: 0;\r\n }\r\n\r\n .iq-header { padding: 6px 12px; }\r\n .iq-header-title { font-size: 0.8rem; }\r\n .iq-messages { padding: 6px 10px; gap: 6px; }\r\n .iq-empty-icon { font-size: 1.8rem; margin-bottom: 4px; }\r\n .iq-empty p { font-size: 0.78rem; margin: 1px 0; }\r\n .iq-input-bar { padding: 6px 10px; }\r\n .iq-input-bar input { font-size: 16px; padding: 6px 10px; }\r\n .iq-btn-send { width: 32px; height: 32px; }\r\n }\r\n `]\r\n})\r\nexport class IntelligentChatPluginComponent implements AfterViewChecked, OnChanges, OnInit, OnDestroy {\r\n @ViewChild('chatContainer') private chatContainer!: ElementRef;\r\n\r\n @Input() config!: IntelligentChatConfig;\r\n\r\n private chatService = inject(IntelligentChatService);\r\n private hostEl = inject(ElementRef);\r\n\r\n // State\r\n isOpen = signal(false);\r\n isExpanded = signal(false);\r\n messages = signal<ChatMessage[]>([]);\r\n isLoading = signal(false);\r\n selectedTrace = signal<any>(null);\r\n authError = signal<string | null>(null);\r\n modalUrl = signal<string | null>(null);\r\n isModalImage = computed(() => {\r\n const url = this.modalUrl();\r\n if (!url) return false;\r\n return /\\.(jpg|jpeg|png|gif|webp|svg|bmp)(\\?.*)?$/i.test(url);\r\n });\r\n modalLoading = signal(false);\r\n showHomeBtn = signal(false);\r\n private originalModalUrl = '';\r\n private modalReadyForNav = false;\r\n private navReadyTimer: any = null;\r\n inputText = '';\r\n private currentSubscription?: Subscription;\r\n\r\n // Pipeline step (driven by real SSE events from backend)\r\n pipelineStep = '';\r\n\r\n private messageId = 0;\r\n private shouldScroll = false;\r\n\r\n // ─── Session Persistence ──────────────────────────\r\n private readonly STORAGE_PREFIX = 'iq_chat_session_';\r\n private sessionKey = '';\r\n private storageListener = (e: StorageEvent) => this.onStorageChange(e);\r\n\r\n /** Resolved config with defaults applied */\r\n private sanitizer = inject(DomSanitizer);\r\n\r\n resolvedConfig = signal<Required<IntelligentChatConfig>>({\r\n apiUrl: '',\r\n systemId: '',\r\n token: '',\r\n useIntelligentQuery: true,\r\n skipPatterns: true,\r\n baseContext: '',\r\n showTrace: false,\r\n showPipelineSteps: true,\r\n preferTableFormat: true,\r\n title: 'Maquito Chat',\r\n placeholder: 'Escribe tu consulta aquí...',\r\n welcomeTitle: '¡Hola! Soy Maquito.',\r\n welcomeSubtitle: 'Escribe tu consulta para comenzar.',\r\n position: 'bottom-right',\r\n bubbleIcon: '🤖',\r\n bubbleIconType: 'emoji',\r\n bubbleImageUrl: '',\r\n bubbleSvg: '',\r\n themeClass: '',\r\n stickyBubble: true,\r\n allowExpand: false,\r\n theme: {},\r\n userName: '',\r\n personality: ''\r\n });\r\n\r\n /** Map theme object → CSS variable overrides */\r\n themeStyles = computed(() => {\r\n const t = this.resolvedConfig().theme || {};\r\n const map: Record<string, string> = {};\r\n const pairs: [keyof PluginTheme, string][] = [\r\n ['primary', '--iq-primary'], ['primaryLight', '--iq-primary-light'],\r\n ['accent', '--iq-accent'], ['accentLight', '--iq-accent-light'],\r\n ['bg', '--iq-bg'], ['bgCard', '--iq-bg-card'], ['bgTertiary', '--iq-bg-tertiary'],\r\n ['text', '--iq-text'], ['textSecondary', '--iq-text-secondary'],\r\n ['textMuted', '--iq-text-muted'], ['border', '--iq-border']\r\n ];\r\n for (const [key, cssVar] of pairs) {\r\n if (t[key]) map[cssVar] = t[key]!;\r\n }\r\n return map;\r\n });\r\n\r\n /** Sanitised SVG HTML for bubble */\r\n sanitizedBubbleSvg = computed<SafeHtml>(() => {\r\n const raw = this.resolvedConfig().bubbleSvg || '';\r\n return this.sanitizer.bypassSecurityTrustHtml(raw);\r\n });\r\n\r\n /** Sanitised URL for the link modal iframe */\r\n sanitizedModalUrl = computed<SafeResourceUrl>(() => {\r\n const url = this.modalUrl() || '';\r\n return this.sanitizer.bypassSecurityTrustResourceUrl(url);\r\n });\r\n\r\n ngOnInit(): void {\r\n window.addEventListener('storage', this.storageListener);\r\n // Self-heal: always reset transient state on init to prevent\r\n // corrupted sessions from freezing the page\r\n this.isLoading.set(false);\r\n this.pipelineStep = '';\r\n this.isExpanded.set(false);\r\n this.setHostScrollLock(false);\r\n this.currentSubscription?.unsubscribe();\r\n this.currentSubscription = undefined;\r\n }\r\n\r\n ngOnDestroy(): void {\r\n window.removeEventListener('storage', this.storageListener);\r\n this.cancelQuery();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['config'] && this.config) {\r\n this.resolvedConfig.set({\r\n apiUrl: this.config.apiUrl || '',\r\n systemId: this.config.systemId || '',\r\n token: this.config.token || '',\r\n useIntelligentQuery: this.config.useIntelligentQuery ?? true,\r\n skipPatterns: this.config.skipPatterns ?? true,\r\n baseContext: this.config.baseContext || '',\r\n showTrace: this.config.showTrace ?? false,\r\n showPipelineSteps: this.config.showPipelineSteps ?? true,\r\n preferTableFormat: this.config.preferTableFormat ?? true,\r\n title: this.config.title || 'Maquito Chat',\r\n placeholder: this.config.placeholder || 'Escribe tu consulta aquí...',\r\n welcomeTitle: this.config.welcomeTitle || '¡Hola! Soy Maquito.',\r\n welcomeSubtitle: this.config.welcomeSubtitle || 'Escribe tu consulta para comenzar.',\r\n position: this.config.position || 'bottom-right',\r\n bubbleIcon: this.config.bubbleIcon || '🤖',\r\n bubbleIconType: this.config.bubbleIconType || 'emoji',\r\n bubbleImageUrl: this.config.bubbleImageUrl || '',\r\n bubbleSvg: this.config.bubbleSvg || '',\r\n themeClass: this.config.themeClass || '',\r\n stickyBubble: this.config.stickyBubble ?? true,\r\n allowExpand: this.config.allowExpand ?? false,\r\n theme: this.config.theme || {},\r\n userName: this.config.userName || '',\r\n personality: this.config.personality || ''\r\n });\r\n // Cancel any in-flight query when config changes\r\n this.cancelQuery();\r\n // Rebuild session key when config changes\r\n const newKey = this.buildSessionKey();\r\n if (newKey !== this.sessionKey) {\r\n this.sessionKey = newKey;\r\n this.loadSession();\r\n }\r\n // Clear auth error when config changes (user may be testing a new token)\r\n this.authError.set(null);\r\n }\r\n }\r\n\r\n ngAfterViewChecked(): void {\r\n if (this.shouldScroll) {\r\n this.scrollToBottom();\r\n this.shouldScroll = false;\r\n }\r\n }\r\n\r\n toggleChat(): void {\r\n this.isOpen.update(v => !v);\r\n if (!this.isOpen()) {\r\n this.isExpanded.set(false);\r\n this.setHostScrollLock(false);\r\n this.cancelQuery();\r\n }\r\n if (this.isOpen()) this.shouldScroll = true;\r\n }\r\n\r\n toggleExpand(): void {\r\n this.isExpanded.update(v => !v);\r\n this.setHostScrollLock(this.isExpanded());\r\n }\r\n\r\n /** Lock/unlock the host page scroll to prevent its scrollbar from overlapping ours */\r\n private setHostScrollLock(lock: boolean): void {\r\n document.body.style.overflow = lock ? 'hidden' : '';\r\n // Also target common host containers\r\n const mc = document.querySelector('.main-container') as HTMLElement;\r\n if (mc) mc.style.overflow = lock ? 'hidden' : '';\r\n }\r\n\r\n sendMessage(): void {\r\n const text = this.inputText.trim();\r\n if (!text) return;\r\n\r\n const cfg = this.resolvedConfig();\r\n\r\n // Validate required config\r\n if (!cfg.token) {\r\n this.authError.set('Token no configurado. El plugin requiere un token técnico válido.');\r\n return;\r\n }\r\n if (!cfg.apiUrl) {\r\n this.authError.set('API URL no configurada.');\r\n return;\r\n }\r\n\r\n this.authError.set(null);\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text,\r\n sender: 'user',\r\n timestamp: new Date()\r\n }]);\r\n this.saveSession();\r\n this.shouldScroll = true;\r\n this.inputText = '';\r\n this.isLoading.set(true);\r\n\r\n if (cfg.showPipelineSteps) {\r\n this.pipelineStep = '⏳ Procesando...';\r\n } else {\r\n this.pipelineStep = '⏳ Procesando...';\r\n }\r\n\r\n if (cfg.useIntelligentQuery && cfg.systemId) {\r\n // Build conversation history from previous messages (last 6 pairs)\r\n const history = this.messages()\r\n .filter(m => m.sender === 'user' || m.sender === 'bot')\r\n .slice(-12)\r\n .map(msg => ({\r\n role: msg.sender === 'user' ? 'user' : 'assistant',\r\n content: msg.text\r\n }));\r\n\r\n const ctx = cfg.baseContext?.trim() || undefined;\r\n\r\n if (cfg.showPipelineSteps) {\r\n // Use SSE streaming for real-time pipeline progress\r\n this.currentSubscription = this.chatService.executeIntelligentQueryStream(\r\n cfg.apiUrl, cfg.token, cfg.systemId, text, history, ctx, cfg.skipPatterns, cfg.preferTableFormat,\r\n cfg.userName || undefined, cfg.personality || undefined\r\n ).subscribe({\r\n next: (event) => {\r\n if (event.type === 'progress') {\r\n this.pipelineStep = event.message || '';\r\n } else if (event.type === 'result') {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n const response = event.data;\r\n const responseText = response.success\r\n ? (response.response || 'Consulta ejecutada correctamente')\r\n : (response.error || 'Error en la consulta');\r\n\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text: responseText,\r\n sender: 'bot',\r\n timestamp: new Date(),\r\n traceData: {\r\n traceId: response.traceId,\r\n fromCache: response.fromCache,\r\n fromContext: response.fromContext,\r\n query: response.query,\r\n explanation: response.explanation,\r\n patternId: response.patternId,\r\n data: response.data\r\n }\r\n }]);\r\n this.saveSession();\r\n this.shouldScroll = true;\r\n }\r\n },\r\n error: (error) => {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n this.setHostScrollLock(false);\r\n this.handleError(error);\r\n }\r\n });\r\n } else {\r\n // Fallback: use standard non-streaming endpoint\r\n this.currentSubscription = this.chatService.executeIntelligentQuery(\r\n cfg.apiUrl, cfg.token, cfg.systemId, text, history, ctx, cfg.skipPatterns, cfg.preferTableFormat,\r\n cfg.userName || undefined, cfg.personality || undefined\r\n ).subscribe({\r\n next: (response: any) => {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n const responseText = response.success\r\n ? (response.response || 'Consulta ejecutada correctamente')\r\n : (response.error || 'Error en la consulta');\r\n\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text: responseText,\r\n sender: 'bot',\r\n timestamp: new Date(),\r\n traceData: {\r\n traceId: response.traceId,\r\n fromCache: response.fromCache,\r\n fromContext: response.fromContext,\r\n query: response.query,\r\n explanation: response.explanation,\r\n patternId: response.patternId,\r\n data: response.data\r\n }\r\n }]);\r\n this.saveSession();\r\n this.shouldScroll = true;\r\n },\r\n error: (error) => {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n this.setHostScrollLock(false);\r\n this.handleError(error);\r\n }\r\n });\r\n }\r\n } else {\r\n // Standard orchestration (non-intelligent)\r\n this.currentSubscription = this.chatService.ask(cfg.apiUrl, cfg.token, text).subscribe({\r\n next: (response) => {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text: response.data?.response || 'Sin respuesta',\r\n sender: 'bot',\r\n timestamp: new Date(),\r\n traceData: {\r\n traceId: response.traceId,\r\n responseTime: response.data?.processingTime,\r\n appliedRules: response.data?.appliedRules,\r\n decisions: response.data?.decisions\r\n }\r\n }]);\r\n this.saveSession();\r\n this.shouldScroll = true;\r\n },\r\n error: (error) => {\r\n this.pipelineStep = '';\r\n this.isLoading.set(false);\r\n this.setHostScrollLock(false);\r\n this.handleError(error);\r\n }\r\n });\r\n }\r\n }\r\n\r\n cancelQuery(): void {\r\n this.currentSubscription?.unsubscribe();\r\n this.currentSubscription = undefined;\r\n this.isLoading.set(false);\r\n this.pipelineStep = '';\r\n this.setHostScrollLock(false);\r\n }\r\n\r\n clearChat(): void {\r\n this.messages.set([]);\r\n this.selectedTrace.set(null);\r\n this.authError.set(null);\r\n this.clearSession();\r\n }\r\n\r\n showTrace(msg: ChatMessage): void {\r\n this.selectedTrace.set(msg.traceData);\r\n }\r\n\r\n closeTrace(): void {\r\n this.selectedTrace.set(null);\r\n }\r\n\r\n // ─── Link Modal ────────────────────────────────\r\n openLinkModal(url: string): void {\r\n this.modalLoading.set(true);\r\n this.showHomeBtn.set(false);\r\n this.modalReadyForNav = false;\r\n clearTimeout(this.navReadyTimer);\r\n this.originalModalUrl = url;\r\n this.modalUrl.set(url);\r\n }\r\n\r\n closeLinkModal(): void {\r\n this.modalUrl.set(null);\r\n this.modalLoading.set(false);\r\n this.showHomeBtn.set(false);\r\n this.modalReadyForNav = false;\r\n clearTimeout(this.navReadyTimer);\r\n this.originalModalUrl = '';\r\n }\r\n\r\n onIframeLoaded(): void {\r\n this.modalLoading.set(false);\r\n if (this.modalReadyForNav) {\r\n // A load AFTER the initial page settled = real navigation\r\n this.showHomeBtn.set(true);\r\n } else {\r\n // Initial page load (may fire multiple times for SPAs/redirects)\r\n // Wait 1s of stability before treating next loads as navigation\r\n clearTimeout(this.navReadyTimer);\r\n this.navReadyTimer = setTimeout(() => { this.modalReadyForNav = true; }, 1000);\r\n }\r\n }\r\n\r\n iframeGoHome(): void {\r\n const iframe = this.hostEl.nativeElement.querySelector('.iq-link-iframe') as HTMLIFrameElement;\r\n if (iframe && this.originalModalUrl) {\r\n this.modalLoading.set(true);\r\n this.showHomeBtn.set(false);\r\n this.modalReadyForNav = false;\r\n clearTimeout(this.navReadyTimer);\r\n iframe.src = this.originalModalUrl;\r\n }\r\n }\r\n\r\n /** Intercept clicks on <a> and <img> tags inside rendered markdown */\r\n onMessageClick(event: MouseEvent): void {\r\n const target = event.target as HTMLElement;\r\n\r\n // Clicking an image opens it full-size in the modal\r\n if (target.tagName === 'IMG') {\r\n const src = (target as HTMLImageElement).src;\r\n if (src) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.openLinkModal(src);\r\n return;\r\n }\r\n }\r\n\r\n const anchor = target.closest('a') as HTMLAnchorElement | null;\r\n if (anchor && anchor.href) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.openLinkModal(anchor.href);\r\n }\r\n }\r\n\r\n formatTime(date: Date): string {\r\n return date.toLocaleTimeString('es-CL', { hour: '2-digit', minute: '2-digit' });\r\n }\r\n\r\n renderMarkdown(text: string): SafeHtml {\r\n if (!text) return '';\r\n try {\r\n // Safety valve: if text is extremely long, skip regex-heavy preprocessing\r\n // to avoid catastrophic backtracking that freezes the browser\r\n let preprocessed = text.length < 100_000 ? this.preprocessMarkdownTable(text) : text;\r\n // Encode spaces in markdown image & link URLs:  and [text](url)\r\n if (preprocessed.length < 100_000) {\r\n preprocessed = preprocessed.replace(\r\n /(!?\\[[^\\]]*\\])\\(([^)]+)\\)/g,\r\n (_match: string, bracket: string, url: string) => `${bracket}(${url.replace(/ /g, '%20')})`\r\n );\r\n }\r\n let html = marked.parse(preprocessed, { breaks: true }) as string;\r\n // Inject inline styles + onerror on <img> to force small thumbnails & hide broken ones\r\n const imgStyle = `style=\"max-height:48px;max-width:100px;object-fit:contain;border-radius:6px;cursor:pointer;display:inline-block;vertical-align:middle;margin:2px 4px;border:1px solid rgba(255,255,255,0.15);box-shadow:0 1px 3px rgba(0,0,0,0.2);\"`;\r\n html = html.replace(/<img /g, `<img ${imgStyle} onerror=\"this.style.display='none'\" `);\r\n return this.sanitizer.bypassSecurityTrustHtml(html);\r\n } catch {\r\n return text;\r\n }\r\n }\r\n\r\n /**\r\n * Pre-process text to ensure pipe-delimited tables render as HTML tables.\r\n *\r\n * The API often returns header + separator + data on ONE line, e.g.:\r\n * \"| Col1 | Col2 | |---|---| | Val1 | Val2 |\"\r\n *\r\n * Step 1: Find the dash-separator pattern (|---|---|) and break the line\r\n * around it so each part (header / separator / data rows) is its\r\n * own line.\r\n * Step 2: Line-by-line cleanup — ensure a blank line exists before the\r\n * first pipe-row and inject a separator if one is still missing.\r\n */\r\n private preprocessMarkdownTable(text: string): string {\r\n // ── Step 1: Break inline separator onto its own line ───────────\r\n // Pattern: the separator row consists only of |, -, :, and spaces.\r\n // We insert \\n before and after it.\r\n text = text.replace(\r\n /\\s*(\\|(?:\\s*:?-{2,}:?\\s*\\|){2,})\\s*/g,\r\n '\\n$1\\n'\r\n );\r\n // Clean up excess blank lines created by step 1\r\n text = text.replace(/\\n{3,}/g, '\\n\\n');\r\n\r\n // ── Step 2: Line-by-line processing ───────────────────────────\r\n const lines = text.split('\\n');\r\n const result: string[] = [];\r\n let inTable = false;\r\n\r\n const isPipeLine = (l: string) => {\r\n const t = l.trim();\r\n return t.startsWith('|') && t.split('|').length > 3;\r\n };\r\n const isSepLine = (l: string) =>\r\n /^\\|(?:\\s*:?-{2,}:?\\s*\\|){2,}\\s*$/.test(l.trim());\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n const trimmed = line.trim();\r\n\r\n if (isPipeLine(trimmed) && !isSepLine(trimmed)) {\r\n if (!inTable) {\r\n inTable = true;\r\n // Insert blank line before table if preceded by non-empty text\r\n if (result.length > 0 && result[result.length - 1].trim() !== '') {\r\n result.push('');\r\n }\r\n result.push(line);\r\n // Inject separator if the next line isn't one\r\n const next = (i + 1 < lines.length) ? lines[i + 1] : '';\r\n if (!isSepLine(next)) {\r\n const cols = trimmed.split('|').filter(c => c.trim() !== '').length;\r\n result.push('| ' + Array(cols).fill('---').join(' | ') + ' |');\r\n }\r\n } else {\r\n result.push(line); // data row\r\n }\r\n } else if (isSepLine(trimmed)) {\r\n if (!inTable) inTable = true; // edge-case: separator before header\r\n result.push(line);\r\n } else {\r\n inTable = false;\r\n result.push(line);\r\n }\r\n }\r\n\r\n return result.join('\\n');\r\n }\r\n\r\n // ─── Private ───────────────────────────────────────────\r\n\r\n private handleError(error: any): void {\r\n const status = error?.status;\r\n if (status === 401 || status === 403) {\r\n const msg = status === 401 ? 'Token inválido o expirado' : 'Sin permisos para este sistema';\r\n this.authError.set(`🔒 ${msg}`);\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text: `⚠️ ${msg}. Verifica el token y el systemId configurados.`,\r\n sender: 'bot',\r\n timestamp: new Date()\r\n }]);\r\n } else {\r\n this.messages.update(msgs => [...msgs, {\r\n id: this.messageId++,\r\n text: `Error: ${error.error?.message || error.error?.error || 'No se pudo procesar la consulta'}`,\r\n sender: 'bot',\r\n timestamp: new Date()\r\n }]);\r\n }\r\n this.saveSession();\r\n this.shouldScroll = true;\r\n }\r\n\r\n private stopPipelineSteps(): void {\r\n this.pipelineStep = '';\r\n }\r\n\r\n private scrollToBottom(): void {\r\n if (this.chatContainer) {\r\n const el = this.chatContainer.nativeElement;\r\n el.scrollTop = el.scrollHeight;\r\n }\r\n }\r\n\r\n // ─── Session Persistence ──────────────────────────\r\n\r\n private buildSessionKey(): string {\r\n const cfg = this.resolvedConfig();\r\n if (!cfg.token || !cfg.systemId) return '';\r\n // Simple hash-like key from systemId + first 8 chars of token\r\n const tokenPrefix = cfg.token.substring(0, 8);\r\n return `${this.STORAGE_PREFIX}${cfg.systemId}_${tokenPrefix}`;\r\n }\r\n\r\n private saveSession(): void {\r\n if (!this.sessionKey) return;\r\n try {\r\n const data = this.messages().map(m => ({\r\n id: m.id,\r\n text: m.text,\r\n sender: m.sender,\r\n timestamp: m.timestamp,\r\n traceData: m.traceData\r\n }));\r\n localStorage.setItem(this.sessionKey, JSON.stringify(data));\r\n } catch { /* ignore quota errors */ }\r\n }\r\n\r\n private loadSession(): void {\r\n if (!this.sessionKey) return;\r\n try {\r\n const raw = localStorage.getItem(this.sessionKey);\r\n if (!raw) { this.messages.set([]); return; }\r\n const data: any[] = JSON.parse(raw);\r\n // Validate data is an array of valid message objects\r\n if (!Array.isArray(data) || data.length === 0) {\r\n this.messages.set([]);\r\n return;\r\n }\r\n const msgs: ChatMessage[] = data\r\n .filter(m => m && typeof m.text === 'string' && typeof m.sender === 'string')\r\n .map(m => ({\r\n ...m,\r\n timestamp: new Date(m.timestamp)\r\n }));\r\n this.messages.set(msgs);\r\n this.messageId = msgs.length > 0 ? Math.max(...msgs.map(m => m.id)) + 1 : 0;\r\n this.shouldScroll = true;\r\n } catch {\r\n // Corrupted session data — wipe it and start fresh\r\n try { localStorage.removeItem(this.sessionKey); } catch { /* ignore */ }\r\n this.messages.set([]);\r\n }\r\n }\r\n\r\n private clearSession(): void {\r\n if (this.sessionKey) {\r\n try { localStorage.removeItem(this.sessionKey); } catch {}\r\n }\r\n }\r\n\r\n /** Called when another tab modifies localStorage */\r\n private onStorageChange(e: StorageEvent): void {\r\n if (!this.sessionKey || e.key !== this.sessionKey) return;\r\n if (e.newValue === null) {\r\n // Session was cleared in another tab\r\n this.messages.set([]);\r\n } else {\r\n this.loadSession();\r\n }\r\n this.shouldScroll = true;\r\n }\r\n}\r\n","/*\r\n * Public API Surface of maquito-chat-plugin\r\n */\r\n\r\nexport type { IntelligentChatConfig, ChatMessage, PluginTheme } from './lib/intelligent-chat.models';\r\nexport { IntelligentChatService } from './lib/intelligent-chat.service';\r\nexport { IntelligentChatPluginComponent } from './lib/intelligent-chat-plugin.component';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|