maquito-chat-plugin 1.1.5 → 1.1.6
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, NgZone, Injectable, ElementRef, signal, computed, Input, ViewChild, Component } from '@angular/core';
|
|
2
|
+
import { inject, NgZone, Injectable, ElementRef, signal, computed, HostListener, Input, ViewChild, Component } from '@angular/core';
|
|
3
3
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
|
4
4
|
import { Observable } from 'rxjs';
|
|
5
5
|
import * as i1 from '@angular/common';
|
|
@@ -218,6 +218,11 @@ class IntelligentChatPluginComponent {
|
|
|
218
218
|
STORAGE_PREFIX = 'iq_chat_session_';
|
|
219
219
|
sessionKey = '';
|
|
220
220
|
storageListener = (e) => this.onStorageChange(e);
|
|
221
|
+
// ─── Debug Menu ──────────────────────────────────
|
|
222
|
+
showDebugMenu = signal(false, ...(ngDevMode ? [{ debugName: "showDebugMenu" }] : []));
|
|
223
|
+
titleTouchTimer = null;
|
|
224
|
+
shakeHandler = null;
|
|
225
|
+
lastShakeTime = 0;
|
|
221
226
|
/** Resolved config with defaults applied */
|
|
222
227
|
sanitizer = inject(DomSanitizer);
|
|
223
228
|
resolvedConfig = signal({
|
|
@@ -244,7 +249,9 @@ class IntelligentChatPluginComponent {
|
|
|
244
249
|
allowExpand: false,
|
|
245
250
|
theme: {},
|
|
246
251
|
userName: '',
|
|
247
|
-
personality: ''
|
|
252
|
+
personality: '',
|
|
253
|
+
enableDebugMenu: false,
|
|
254
|
+
debugKeyCombo: 'ctrl+shift+d'
|
|
248
255
|
}, ...(ngDevMode ? [{ debugName: "resolvedConfig" }] : []));
|
|
249
256
|
/** Map theme object → CSS variable overrides */
|
|
250
257
|
themeStyles = computed(() => {
|
|
@@ -283,10 +290,13 @@ class IntelligentChatPluginComponent {
|
|
|
283
290
|
this.setHostScrollLock(false);
|
|
284
291
|
this.currentSubscription?.unsubscribe();
|
|
285
292
|
this.currentSubscription = undefined;
|
|
293
|
+
// Setup shake detection for mobile debug log download
|
|
294
|
+
this.setupShakeDetection();
|
|
286
295
|
}
|
|
287
296
|
ngOnDestroy() {
|
|
288
297
|
window.removeEventListener('storage', this.storageListener);
|
|
289
|
-
this.
|
|
298
|
+
this.currentSubscription?.unsubscribe();
|
|
299
|
+
this.teardownShakeDetection();
|
|
290
300
|
}
|
|
291
301
|
ngOnChanges(changes) {
|
|
292
302
|
if (changes['config'] && this.config) {
|
|
@@ -314,7 +324,9 @@ class IntelligentChatPluginComponent {
|
|
|
314
324
|
allowExpand: this.config.allowExpand ?? false,
|
|
315
325
|
theme: this.config.theme || {},
|
|
316
326
|
userName: this.config.userName || '',
|
|
317
|
-
personality: this.config.personality || ''
|
|
327
|
+
personality: this.config.personality || '',
|
|
328
|
+
enableDebugMenu: this.config.enableDebugMenu ?? false,
|
|
329
|
+
debugKeyCombo: this.config.debugKeyCombo || 'ctrl+shift+d'
|
|
318
330
|
});
|
|
319
331
|
// Cancel any in-flight query when config changes
|
|
320
332
|
this.cancelQuery();
|
|
@@ -535,6 +547,166 @@ class IntelligentChatPluginComponent {
|
|
|
535
547
|
closeTrace() {
|
|
536
548
|
this.selectedTrace.set(null);
|
|
537
549
|
}
|
|
550
|
+
/** Split combined multi-model query into labeled sections */
|
|
551
|
+
getQuerySections() {
|
|
552
|
+
const raw = this.selectedTrace()?.query;
|
|
553
|
+
if (!raw)
|
|
554
|
+
return [];
|
|
555
|
+
// Multi-model queries are separated by "-- [ModelName]" headers
|
|
556
|
+
const parts = raw.split(/^-- \[(.+?)\]$/m);
|
|
557
|
+
if (parts.length <= 1) {
|
|
558
|
+
// Single query, no model headers
|
|
559
|
+
return [{ model: null, query: raw.trim() }];
|
|
560
|
+
}
|
|
561
|
+
const sections = [];
|
|
562
|
+
// parts = ["", "MaquitoFactura", "\nSELECT...", "MaquitoPedido", "\nSELECT..."]
|
|
563
|
+
for (let i = 1; i < parts.length; i += 2) {
|
|
564
|
+
const modelName = parts[i]?.trim();
|
|
565
|
+
const queryText = parts[i + 1]?.trim();
|
|
566
|
+
if (modelName && queryText) {
|
|
567
|
+
sections.push({ model: modelName, query: queryText });
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return sections.length > 0 ? sections : [{ model: null, query: raw.trim() }];
|
|
571
|
+
}
|
|
572
|
+
// ─── Debug Menu & Log Download ────────────────────
|
|
573
|
+
toggleDebugMenu() {
|
|
574
|
+
this.showDebugMenu.set(!this.showDebugMenu());
|
|
575
|
+
}
|
|
576
|
+
/** Secret keyboard shortcut — works even if debug menu is disabled */
|
|
577
|
+
onDebugKeydown(event) {
|
|
578
|
+
const combo = (this.resolvedConfig().debugKeyCombo || 'ctrl+shift+d').toLowerCase();
|
|
579
|
+
const parts = combo.split('+');
|
|
580
|
+
const needCtrl = parts.includes('ctrl');
|
|
581
|
+
const needShift = parts.includes('shift');
|
|
582
|
+
const needAlt = parts.includes('alt');
|
|
583
|
+
const key = parts.filter(p => !['ctrl', 'shift', 'alt'].includes(p))[0];
|
|
584
|
+
if ((!needCtrl || event.ctrlKey) &&
|
|
585
|
+
(!needShift || event.shiftKey) &&
|
|
586
|
+
(!needAlt || event.altKey) &&
|
|
587
|
+
event.key.toLowerCase() === key) {
|
|
588
|
+
event.preventDefault();
|
|
589
|
+
this.downloadConversationLog();
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
/** Long-press on title (mobile) — 3 seconds */
|
|
593
|
+
onTitleTouchStart(event) {
|
|
594
|
+
this.titleTouchTimer = setTimeout(() => {
|
|
595
|
+
this.downloadConversationLog();
|
|
596
|
+
}, 3000);
|
|
597
|
+
}
|
|
598
|
+
onTitleTouchEnd() {
|
|
599
|
+
if (this.titleTouchTimer) {
|
|
600
|
+
clearTimeout(this.titleTouchTimer);
|
|
601
|
+
this.titleTouchTimer = null;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
/** Setup device shake detection for mobile */
|
|
605
|
+
setupShakeDetection() {
|
|
606
|
+
if (typeof DeviceMotionEvent === 'undefined')
|
|
607
|
+
return;
|
|
608
|
+
const SHAKE_THRESHOLD = 25;
|
|
609
|
+
let lastX = 0, lastY = 0, lastZ = 0;
|
|
610
|
+
let lastUpdate = 0;
|
|
611
|
+
this.shakeHandler = (event) => {
|
|
612
|
+
const acc = event.accelerationIncludingGravity;
|
|
613
|
+
if (!acc || acc.x == null || acc.y == null || acc.z == null)
|
|
614
|
+
return;
|
|
615
|
+
const now = Date.now();
|
|
616
|
+
if ((now - lastUpdate) < 100)
|
|
617
|
+
return;
|
|
618
|
+
const diffTime = now - lastUpdate;
|
|
619
|
+
lastUpdate = now;
|
|
620
|
+
const speed = Math.abs(acc.x + acc.y + acc.z - lastX - lastY - lastZ) / diffTime * 10000;
|
|
621
|
+
lastX = acc.x;
|
|
622
|
+
lastY = acc.y;
|
|
623
|
+
lastZ = acc.z;
|
|
624
|
+
if (speed > SHAKE_THRESHOLD && (now - this.lastShakeTime) > 5000) {
|
|
625
|
+
this.lastShakeTime = now;
|
|
626
|
+
this.downloadConversationLog();
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
window.addEventListener('devicemotion', this.shakeHandler);
|
|
630
|
+
}
|
|
631
|
+
teardownShakeDetection() {
|
|
632
|
+
if (this.shakeHandler) {
|
|
633
|
+
window.removeEventListener('devicemotion', this.shakeHandler);
|
|
634
|
+
this.shakeHandler = null;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
/** Generate and download a comprehensive conversation log as .txt */
|
|
638
|
+
downloadConversationLog() {
|
|
639
|
+
const cfg = this.resolvedConfig();
|
|
640
|
+
const msgs = this.messages();
|
|
641
|
+
const now = new Date();
|
|
642
|
+
const pad = (n) => n.toString().padStart(2, '0');
|
|
643
|
+
const ts = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
|
644
|
+
let log = '';
|
|
645
|
+
log += '═══════════════════════════════════════════════════\n';
|
|
646
|
+
log += ' MAQUITO CHAT — LOG DE CONVERSACIÓN\n';
|
|
647
|
+
log += ` Fecha de descarga: ${ts}\n`;
|
|
648
|
+
log += ` Sistema: ${cfg.systemId}\n`;
|
|
649
|
+
log += ` Session Key: ${this.sessionKey || 'N/A'}\n`;
|
|
650
|
+
log += ` Título: ${cfg.title}\n`;
|
|
651
|
+
log += ` Total Mensajes: ${msgs.length}\n`;
|
|
652
|
+
if (cfg.userName)
|
|
653
|
+
log += ` Usuario: ${cfg.userName}\n`;
|
|
654
|
+
if (cfg.baseContext)
|
|
655
|
+
log += ` Contexto Base: ${cfg.baseContext.substring(0, 100)}...\n`;
|
|
656
|
+
log += '═══════════════════════════════════════════════════\n\n';
|
|
657
|
+
for (const msg of msgs) {
|
|
658
|
+
const t = new Date(msg.timestamp);
|
|
659
|
+
const time = `${pad(t.getHours())}:${pad(t.getMinutes())}:${pad(t.getSeconds())}`;
|
|
660
|
+
const icon = msg.sender === 'user' ? '👤 USUARIO' : '🤖 BOT';
|
|
661
|
+
log += `[${time}] ${icon}:\n`;
|
|
662
|
+
// Strip HTML tags for plain text
|
|
663
|
+
const plainText = msg.text.replace(/<[^>]*>/g, '').trim();
|
|
664
|
+
log += `${plainText}\n`;
|
|
665
|
+
// Include trace data if available (bot messages)
|
|
666
|
+
if (msg.traceData && msg.sender === 'bot') {
|
|
667
|
+
log += ' ┌─── Traza ───────────────────────\n';
|
|
668
|
+
const td = msg.traceData;
|
|
669
|
+
if (td.traceId)
|
|
670
|
+
log += ` │ TraceId: ${td.traceId}\n`;
|
|
671
|
+
if (td.origin)
|
|
672
|
+
log += ` │ Origen: ${td.origin}\n`;
|
|
673
|
+
if (td.query)
|
|
674
|
+
log += ` │ Query: ${td.query}\n`;
|
|
675
|
+
if (td.model)
|
|
676
|
+
log += ` │ Modelo: ${td.model}\n`;
|
|
677
|
+
if (td.rowCount !== undefined)
|
|
678
|
+
log += ` │ Filas: ${td.rowCount}\n`;
|
|
679
|
+
if (td.explanation)
|
|
680
|
+
log += ` │ Explicación: ${td.explanation}\n`;
|
|
681
|
+
if (td.durationMs)
|
|
682
|
+
log += ` │ Duración: ${td.durationMs}ms\n`;
|
|
683
|
+
// Include full raw trace for deep debugging
|
|
684
|
+
try {
|
|
685
|
+
const raw = JSON.stringify(td, null, 2);
|
|
686
|
+
log += ` │ Raw Trace:\n`;
|
|
687
|
+
for (const line of raw.split('\n')) {
|
|
688
|
+
log += ` │ ${line}\n`;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
catch { }
|
|
692
|
+
log += ' └─────────────────────────────────\n';
|
|
693
|
+
}
|
|
694
|
+
log += '\n';
|
|
695
|
+
}
|
|
696
|
+
log += '═══════════════════════════════════════════════════\n';
|
|
697
|
+
log += ` FIN DEL LOG — ${msgs.length} mensajes\n`;
|
|
698
|
+
log += '═══════════════════════════════════════════════════\n';
|
|
699
|
+
// Download as .txt file
|
|
700
|
+
const blob = new Blob([log], { type: 'text/plain;charset=utf-8' });
|
|
701
|
+
const url = URL.createObjectURL(blob);
|
|
702
|
+
const a = document.createElement('a');
|
|
703
|
+
a.href = url;
|
|
704
|
+
a.download = `maquito-chat-log_${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}_${pad(now.getHours())}${pad(now.getMinutes())}.txt`;
|
|
705
|
+
document.body.appendChild(a);
|
|
706
|
+
a.click();
|
|
707
|
+
document.body.removeChild(a);
|
|
708
|
+
URL.revokeObjectURL(url);
|
|
709
|
+
}
|
|
538
710
|
// ─── Link Modal ────────────────────────────────
|
|
539
711
|
openLinkModal(url) {
|
|
540
712
|
this.modalLoading.set(true);
|
|
@@ -800,7 +972,7 @@ class IntelligentChatPluginComponent {
|
|
|
800
972
|
this.shouldScroll = true;
|
|
801
973
|
}
|
|
802
974
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: IntelligentChatPluginComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
803
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: IntelligentChatPluginComponent, isStandalone: true, selector: "intelligent-chat-plugin", inputs: { config: "config" }, viewQueries: [{ propertyName: "chatContainer", first: true, predicate: ["chatContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
975
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: IntelligentChatPluginComponent, isStandalone: true, selector: "intelligent-chat-plugin", inputs: { config: "config" }, host: { listeners: { "window:keydown": "onDebugKeydown($event)" } }, viewQueries: [{ propertyName: "chatContainer", first: true, predicate: ["chatContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
804
976
|
<!-- Host theme overrides -->
|
|
805
977
|
<div class="iq-theme-host" [ngStyle]="themeStyles()">
|
|
806
978
|
|
|
@@ -843,8 +1015,24 @@ class IntelligentChatPluginComponent {
|
|
|
843
1015
|
>
|
|
844
1016
|
<!-- Header -->
|
|
845
1017
|
<div class="iq-header">
|
|
846
|
-
<span class="iq-header-title"
|
|
1018
|
+
<span class="iq-header-title"
|
|
1019
|
+
(touchstart)="onTitleTouchStart($event)"
|
|
1020
|
+
(touchend)="onTitleTouchEnd()"
|
|
1021
|
+
(touchcancel)="onTitleTouchEnd()"
|
|
1022
|
+
>{{ resolvedConfig().title }}</span>
|
|
847
1023
|
<div class="iq-header-actions">
|
|
1024
|
+
@if (resolvedConfig().enableDebugMenu) {
|
|
1025
|
+
<div class="iq-debug-menu-wrapper">
|
|
1026
|
+
<button class="iq-header-btn" (click)="toggleDebugMenu()" title="Opciones">⋯</button>
|
|
1027
|
+
@if (showDebugMenu()) {
|
|
1028
|
+
<div class="iq-debug-dropdown">
|
|
1029
|
+
<button class="iq-debug-option" (click)="downloadConversationLog(); toggleDebugMenu()">
|
|
1030
|
+
📥 Descargar Log
|
|
1031
|
+
</button>
|
|
1032
|
+
</div>
|
|
1033
|
+
}
|
|
1034
|
+
</div>
|
|
1035
|
+
}
|
|
848
1036
|
<button class="iq-header-btn" (click)="clearChat()" title="Limpiar chat">🗑️</button>
|
|
849
1037
|
@if (resolvedConfig().allowExpand) {
|
|
850
1038
|
<button class="iq-header-btn iq-btn-expand" (click)="toggleExpand()" [title]="isExpanded() ? 'Contraer' : 'Expandir'">
|
|
@@ -947,8 +1135,13 @@ class IntelligentChatPluginComponent {
|
|
|
947
1135
|
}
|
|
948
1136
|
@if (selectedTrace()?.query) {
|
|
949
1137
|
<div class="iq-trace-item">
|
|
950
|
-
<label>Query Generada</label>
|
|
951
|
-
|
|
1138
|
+
<label>{{ getQuerySections().length > 1 ? 'Queries Generadas (' + getQuerySections().length + ')' : 'Query Generada' }}</label>
|
|
1139
|
+
@for (section of getQuerySections(); track $index) {
|
|
1140
|
+
@if (section.model) {
|
|
1141
|
+
<div style="color: #4ecdc4; font-size: 11px; font-weight: bold; margin-top: 8px;">📋 {{ section.model }}</div>
|
|
1142
|
+
}
|
|
1143
|
+
<pre class="iq-query-code" style="margin-top: 4px;">{{ section.query }}</pre>
|
|
1144
|
+
}
|
|
952
1145
|
</div>
|
|
953
1146
|
}
|
|
954
1147
|
@if (selectedTrace()?.explanation) {
|
|
@@ -1008,7 +1201,7 @@ class IntelligentChatPluginComponent {
|
|
|
1008
1201
|
}
|
|
1009
1202
|
|
|
1010
1203
|
</div><!-- /iq-theme-host -->
|
|
1011
|
-
`, isInline: true, styles: [":host{--iq-primary: #1a3a5c;--iq-primary-light: #2a5a8c;--iq-accent: #00d4aa;--iq-accent-light: #33e0be;--iq-bg: #1e1e2f;--iq-bg-card: #252538;--iq-bg-tertiary: #35354a;--iq-text: #ffffff;--iq-text-secondary: #a0a0b0;--iq-text-muted: #6c6c7c;--iq-border: #3a3a4d;--iq-radius: 12px;--iq-bubble-size: 56px;--iq-panel-width: 400px;--iq-panel-height: 520px;--iq-z: 10000;--iq-font: \"Inter\", \"Roboto\", -apple-system, BlinkMacSystemFont, sans-serif;font-family:var(--iq-font)}.iq-bubble{position:fixed;bottom:24px;right:24px;z-index:var(--iq-z);width:var(--iq-bubble-size);height:var(--iq-bubble-size);border-radius:50%;border:none;background:linear-gradient(135deg,var(--iq-accent),var(--iq-accent-light));color:var(--iq-bg);font-size:1.6rem;cursor:pointer;box-shadow:0 4px 16px #00d4aa66;transition:all .3s cubic-bezier(.4,0,.2,1);display:flex;align-items:center;justify-content:center}.iq-bubble:hover{transform:scale(1.1);box-shadow:0 6px 24px #00d4aa80}.iq-bubble .iq-bubble-icon{font-size:1.5rem;pointer-events:none}.iq-bubble-img{width:60%;height:60%;object-fit:contain;border-radius:50%;pointer-events:none}.iq-bubble-svg{width:60%;height:60%;display:flex;align-items:center;justify-content:center;pointer-events:none}.iq-bubble-svg :deep(svg){width:100%;height:100%}.iq-bubble.iq-open{background:var(--iq-bg-tertiary);color:var(--iq-text);box-shadow:0 4px 12px #0000004d;font-size:1.2rem}.iq-bubble.iq-bottom-left{right:auto;left:24px}.iq-bubble-icon{line-height:1}.iq-panel{position:fixed;bottom:92px;right:24px;z-index:var(--iq-z);width:var(--iq-panel-width);height:var(--iq-panel-height);background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 12px 40px #00000080;animation:iq-slide-up .3s cubic-bezier(.4,0,.2,1)}.iq-panel.iq-bottom-left{right:auto;left:24px}.iq-panel.iq-expanded{width:100vw!important;height:100vh!important;inset:0!important;border:none;border-radius:0;overflow:clip;z-index:calc(var(--iq-z) + 5);animation:iq-expand .3s cubic-bezier(.4,0,.2,1)}.iq-btn-expand{font-size:1.1rem!important}@keyframes iq-expand{0%{opacity:.8;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes iq-slide-up{0%{opacity:0;transform:translateY(16px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.iq-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--iq-border);background:var(--iq-bg-card)}.iq-header-title{font-weight:600;font-size:.95rem;color:var(--iq-text)}.iq-header-actions{display:flex;gap:4px}.iq-header-btn{background:none;border:none;color:var(--iq-text-muted);cursor:pointer;font-size:1rem;padding:4px 6px;border-radius:4px;transition:all .15s}.iq-header-btn:hover{color:var(--iq-text);background:#ffffff14}.iq-auth-error{display:flex;align-items:center;gap:8px;padding:10px 16px;background:#dc354526;color:#ff6b7a;font-size:.8rem;border-bottom:1px solid rgba(220,53,69,.25)}.iq-messages{flex:1;min-height:0;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:10px}.iq-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:var(--iq-text-secondary)}.iq-empty-icon{font-size:3rem;margin-bottom:8px;display:flex;align-items:center;justify-content:center}.iq-empty-img{width:48px;height:48px;object-fit:contain;border-radius:8px}.iq-empty-svg{width:48px;height:48px;display:flex;align-items:center;justify-content:center}.iq-empty-svg :deep(svg){width:100%;height:100%}.iq-empty p{font-size:.95rem;margin:2px 0}.iq-text-muted{color:var(--iq-text-muted)!important;font-size:.8rem!important}.iq-msg{display:flex;flex-direction:column;max-width:85%}.iq-msg-user{align-self:flex-end}.iq-msg-bot{align-self:flex-start;max-width:100%}.iq-msg-user .iq-msg-content{background:linear-gradient(135deg,var(--iq-primary),var(--iq-primary-light));border-radius:12px 12px 0}.iq-msg-bot .iq-msg-content{background:var(--iq-bg-tertiary);border-radius:12px 12px 12px 0}.iq-msg-content{padding:10px 14px;color:var(--iq-text);font-size:.85rem;line-height:1.45}.iq-msg-content p{margin:0;white-space:pre-wrap}.iq-msg-time{display:block;margin-top:4px;font-size:.65rem;color:#ffffff80}.iq-md{line-height:1.5;overflow-x:auto;max-width:100%}.iq-md :first-child{margin-top:0}.iq-md :last-child{margin-bottom:0}.iq-md p{margin:0 0 .4em}.iq-md p:last-child{margin-bottom:0}.iq-md strong{color:var(--iq-accent)}.iq-md ul,.iq-md ol{margin:.3em 0;padding-left:1.2em}.iq-md li{margin:.15em 0}.iq-md code{background:#0000004d;padding:.15em .4em;border-radius:3px;font-size:.82em}.iq-md pre{background:#0000004d;padding:.8em;border-radius:6px;overflow-x:auto;font-size:.78em;margin:.4em 0}.iq-md pre code{background:none;padding:0}.iq-md table{width:max-content;min-width:100%;border-collapse:separate;border-spacing:0;margin:.5em 0;font-size:.75rem;border-radius:6px;overflow:hidden}.iq-md thead th{background:#6366f12e;color:#a5b4fc;font-weight:600;text-align:left;padding:.5em .8em;border-bottom:2px solid rgba(99,102,241,.3);white-space:nowrap;font-size:.7rem;text-transform:uppercase;letter-spacing:.05em}.iq-md tbody td{padding:.4em .8em;border-bottom:1px solid rgba(255,255,255,.06);white-space:nowrap;color:var(--iq-text-secondary)}.iq-md tbody tr:hover{background:#6366f114}.iq-md img{max-height:80px;max-width:120px;object-fit:cover;border-radius:8px;margin:6px 4px 6px 0;display:inline-block;vertical-align:middle;border:1px solid rgba(255,255,255,.15);box-shadow:0 1px 4px #00000040;cursor:pointer;transition:transform .15s,box-shadow .15s}.iq-md img:hover{transform:scale(1.05);box-shadow:0 3px 12px #6366f159;border-color:var(--iq-accent)}.iq-md img[alt*=logo],.iq-md img[alt*=marca]{max-height:28px;max-width:90px;object-fit:contain;border:none;box-shadow:none;border-radius:4px;background:#ffffffe6;padding:2px 6px}.iq-btn-trace{align-self:flex-start;margin-top:4px;background:transparent;border:1px solid var(--iq-border);color:var(--iq-text-secondary);font-size:.7rem;padding:3px 8px;border-radius:4px;cursor:pointer;transition:all .15s}.iq-btn-trace:hover{border-color:var(--iq-accent);color:var(--iq-accent)}.iq-pipeline{display:flex;align-items:center;gap:8px;animation:iq-fade-in .3s ease-out}.iq-dot{width:8px;height:8px;border-radius:50%;background:var(--iq-accent);animation:iq-pulse 1s ease-in-out infinite}.iq-pipeline-text{font-size:.8rem;color:var(--iq-text-muted);font-style:italic;flex:1}.iq-cancel-btn{background:transparent;border:1px solid var(--iq-border);color:var(--iq-text-muted);font-size:.7rem;padding:2px 8px;border-radius:4px;cursor:pointer;transition:all .15s;flex-shrink:0}.iq-cancel-btn:hover{border-color:#ff6b6b;color:#ff6b6b;background:#ff6b6b1a}@keyframes iq-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.7)}}@keyframes iq-fade-in{0%{opacity:0;transform:translate(-6px)}to{opacity:1;transform:translate(0)}}.iq-input-bar{display:flex;gap:8px;padding:10px 12px;border-top:1px solid var(--iq-border);background:var(--iq-bg-card)}.iq-input-bar input{flex:1;padding:8px 12px;background:var(--iq-bg-tertiary);border:1px solid var(--iq-border);border-radius:8px;color:var(--iq-text);font-size:.85rem;font-family:var(--iq-font);outline:none;transition:border-color .15s}.iq-input-bar input:focus{border-color:var(--iq-accent)}.iq-input-bar input::placeholder{color:var(--iq-text-muted)}.iq-input-bar input:disabled{opacity:.5}.iq-btn-send{width:36px;height:36px;border-radius:8px;border:none;background:linear-gradient(135deg,var(--iq-accent),var(--iq-accent-light));color:var(--iq-bg);font-size:1rem;cursor:pointer;transition:all .2s;display:flex;align-items:center;justify-content:center}.iq-btn-send:hover:not(:disabled){box-shadow:0 0 12px #00d4aa66;transform:translateY(-1px)}.iq-btn-send:disabled{opacity:.4;cursor:not-allowed}.iq-trace-overlay{position:fixed;inset:0;z-index:calc(var(--iq-z) + 10);background:#0009;display:flex;align-items:center;justify-content:center;animation:iq-fade-in .2s ease-out}.iq-trace-modal{width:90%;max-width:520px;max-height:80vh;background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 20px 50px #0009}.iq-trace-header{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--iq-border)}.iq-trace-header h3{margin:0;font-size:.95rem;color:var(--iq-text)}.iq-trace-body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px}.iq-trace-item label{display:block;font-size:.7rem;color:var(--iq-text-muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.05em}.iq-trace-item code{display:block;padding:8px;background:var(--iq-bg-tertiary);border-radius:4px;font-family:monospace;font-size:.8rem;color:var(--iq-accent);word-break:break-all}.iq-trace-item pre{margin:0;padding:8px;background:var(--iq-bg-tertiary);border-radius:4px;font-family:monospace;font-size:.7rem;overflow-x:auto;max-height:180px;color:var(--iq-text-secondary)}.iq-cache-hit{background:#10b98126!important;color:#10b981!important}.iq-query-code{color:var(--iq-accent)!important}.iq-link-overlay{position:fixed;inset:0;z-index:calc(var(--iq-z) + 20);background:#000000b3;display:flex;align-items:center;justify-content:center;animation:iq-fade-in .2s ease-out;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.iq-link-modal{width:94vw;height:92vh;background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 60px #000000b3;animation:iq-expand .25s cubic-bezier(.4,0,.2,1)}.iq-link-header{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--iq-border);background:var(--iq-bg-card);gap:12px;min-height:44px}.iq-link-title{flex:1;font-size:.78rem;color:var(--iq-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:monospace}.iq-link-actions{display:flex;gap:4px;flex-shrink:0}.iq-link-actions a{text-decoration:none}.iq-back-btn{flex-shrink:0;font-size:1.1rem;transition:transform .15s ease}.iq-back-btn:hover{transform:translate(-2px)}.iq-iframe-wrapper{flex:1;position:relative;overflow:hidden}.iq-link-iframe{width:100%;height:100%;border:none;background:#fff;transition:opacity .3s ease}.iq-iframe-hidden{opacity:0}.iq-modal-img{width:100%;height:100%;object-fit:contain;background:#1a1a2e}.iq-iframe-loader{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:var(--iq-bg);gap:16px;z-index:2}.iq-spinner{width:40px;height:40px;border:3px solid var(--iq-border);border-top-color:var(--iq-accent);border-radius:50%;animation:iq-spin .8s linear infinite}.iq-loader-text{font-size:.85rem;color:var(--iq-text-secondary);font-weight:500}@keyframes iq-spin{to{transform:rotate(360deg)}}.iq-md a{color:var(--iq-accent);text-decoration:underline;cursor:pointer;transition:color .15s}.iq-md a:hover{color:var(--iq-accent-light)}@media(max-width:480px){.iq-link-modal{width:100vw;height:100dvh;border-radius:0}.iq-link-header{padding:8px 12px}.iq-link-title{font-size:.7rem}}.iq-messages::-webkit-scrollbar{width:5px}.iq-messages::-webkit-scrollbar-track{background:transparent}.iq-messages::-webkit-scrollbar-thumb{background:var(--iq-border);border-radius:4px}.iq-trace-body::-webkit-scrollbar{width:5px}.iq-trace-body::-webkit-scrollbar-track{background:transparent}.iq-trace-body::-webkit-scrollbar-thumb{background:var(--iq-border);border-radius:4px}.iq-expanded .iq-messages::-webkit-scrollbar{width:8px}.iq-expanded .iq-messages{scrollbar-gutter:stable}@media(max-width:480px){.iq-bubble{bottom:16px;right:16px;width:48px;height:48px;font-size:1.3rem}.iq-bubble.iq-bottom-left{left:16px}.iq-bubble .iq-bubble-icon{font-size:1.2rem}.iq-panel{right:8px;left:8px;bottom:72px;width:auto!important;max-width:calc(100vw - 16px);height:calc(100dvh - 90px);max-height:calc(100dvh - 90px)}.iq-panel.iq-bottom-left{left:8px;right:8px}.iq-panel.iq-expanded{inset:0!important;width:100vw!important;height:100dvh!important;max-height:100dvh!important;max-width:100vw!important;border-radius:0}.iq-header{padding:10px 12px}.iq-header-title{font-size:.85rem}.iq-header-btn{padding:6px 8px;min-width:32px;min-height:32px}.iq-messages{padding:8px;gap:8px}.iq-msg{max-width:92%}.iq-msg-bot{max-width:100%}.iq-msg-content{padding:8px 10px;font-size:.8rem}.iq-md{overflow-x:auto;-webkit-overflow-scrolling:touch}.iq-md table{font-size:.65rem;min-width:unset}.iq-md thead th{padding:.35em .5em;font-size:.6rem}.iq-md tbody td{padding:.3em .5em;font-size:.65rem}.iq-empty-icon{font-size:2.5rem}.iq-empty p{font-size:.85rem}.iq-input-bar{padding:8px 10px;gap:6px}.iq-input-bar input{font-size:16px;padding:8px 10px}.iq-btn-send{width:38px;height:38px;flex-shrink:0}.iq-trace-modal{width:calc(100vw - 24px);max-height:90dvh}.iq-trace-header{padding:12px}.iq-trace-header h3{font-size:.85rem}.iq-trace-body{padding:12px}.iq-trace-item pre{font-size:.65rem;max-height:140px}}@media(max-height:500px)and (orientation:landscape){.iq-bubble{bottom:8px;right:8px;width:44px;height:44px;font-size:1.1rem}.iq-bubble.iq-bottom-left{left:8px}.iq-panel{inset:8px 60px 8px 8px;width:auto!important;max-width:calc(100vw - 76px);height:auto!important;max-height:calc(100dvh - 16px);border-radius:var(--iq-radius)}.iq-panel.iq-bottom-left{left:60px;right:8px}.iq-panel.iq-expanded{inset:0!important;width:100vw!important;height:100dvh!important;max-height:100dvh!important;max-width:100vw!important;border-radius:0}.iq-header{padding:6px 12px}.iq-header-title{font-size:.8rem}.iq-messages{padding:6px 10px;gap:6px}.iq-empty-icon{font-size:1.8rem;margin-bottom:4px}.iq-empty p{font-size:.78rem;margin:1px 0}.iq-input-bar{padding:6px 10px}.iq-input-bar input{font-size:16px;padding:6px 10px}.iq-btn-send{width:32px;height:32px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: i1.JsonPipe, name: "json" }] });
|
|
1204
|
+
`, isInline: true, styles: [":host{--iq-primary: #1a3a5c;--iq-primary-light: #2a5a8c;--iq-accent: #00d4aa;--iq-accent-light: #33e0be;--iq-bg: #1e1e2f;--iq-bg-card: #252538;--iq-bg-tertiary: #35354a;--iq-text: #ffffff;--iq-text-secondary: #a0a0b0;--iq-text-muted: #6c6c7c;--iq-border: #3a3a4d;--iq-radius: 12px;--iq-bubble-size: 56px;--iq-panel-width: 400px;--iq-panel-height: 520px;--iq-z: 10000;--iq-font: \"Inter\", \"Roboto\", -apple-system, BlinkMacSystemFont, sans-serif;font-family:var(--iq-font)}.iq-bubble{position:fixed;bottom:24px;right:24px;z-index:var(--iq-z);width:var(--iq-bubble-size);height:var(--iq-bubble-size);border-radius:50%;border:none;background:linear-gradient(135deg,var(--iq-accent),var(--iq-accent-light));color:var(--iq-bg);font-size:1.6rem;cursor:pointer;box-shadow:0 4px 16px #00d4aa66;transition:all .3s cubic-bezier(.4,0,.2,1);display:flex;align-items:center;justify-content:center}.iq-bubble:hover{transform:scale(1.1);box-shadow:0 6px 24px #00d4aa80}.iq-bubble .iq-bubble-icon{font-size:1.5rem;pointer-events:none}.iq-bubble-img{width:60%;height:60%;object-fit:contain;border-radius:50%;pointer-events:none}.iq-bubble-svg{width:60%;height:60%;display:flex;align-items:center;justify-content:center;pointer-events:none}.iq-bubble-svg :deep(svg){width:100%;height:100%}.iq-bubble.iq-open{background:var(--iq-bg-tertiary);color:var(--iq-text);box-shadow:0 4px 12px #0000004d;font-size:1.2rem}.iq-bubble.iq-bottom-left{right:auto;left:24px}.iq-bubble-icon{line-height:1}.iq-panel{position:fixed;bottom:92px;right:24px;z-index:var(--iq-z);width:var(--iq-panel-width);height:var(--iq-panel-height);background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 12px 40px #00000080;animation:iq-slide-up .3s cubic-bezier(.4,0,.2,1)}.iq-panel.iq-bottom-left{right:auto;left:24px}.iq-panel.iq-expanded{width:100vw!important;height:100vh!important;inset:0!important;border:none;border-radius:0;overflow:clip;z-index:calc(var(--iq-z) + 5);animation:iq-expand .3s cubic-bezier(.4,0,.2,1)}.iq-btn-expand{font-size:1.1rem!important}@keyframes iq-expand{0%{opacity:.8;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes iq-slide-up{0%{opacity:0;transform:translateY(16px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.iq-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--iq-border);background:var(--iq-bg-card)}.iq-header-title{font-weight:600;font-size:.95rem;color:var(--iq-text)}.iq-header-actions{display:flex;gap:4px}.iq-header-btn{background:none;border:none;color:var(--iq-text-muted);cursor:pointer;font-size:1rem;padding:4px 6px;border-radius:4px;transition:all .15s}.iq-header-btn:hover{color:var(--iq-text);background:#ffffff14}.iq-debug-menu-wrapper{position:relative}.iq-debug-dropdown{position:absolute;top:100%;right:0;margin-top:4px;min-width:180px;background:var(--iq-bg-card);border:1px solid var(--iq-border);border-radius:8px;box-shadow:0 8px 24px #0006;z-index:calc(var(--iq-z) + 10);padding:4px;animation:iq-dropdown-in .15s ease-out}@keyframes iq-dropdown-in{0%{opacity:0;transform:translateY(-4px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.iq-debug-option{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;background:none;border:none;color:var(--iq-text);font-size:.85rem;cursor:pointer;border-radius:6px;transition:background .15s;text-align:left}.iq-debug-option:hover{background:#ffffff14}.iq-auth-error{display:flex;align-items:center;gap:8px;padding:10px 16px;background:#dc354526;color:#ff6b7a;font-size:.8rem;border-bottom:1px solid rgba(220,53,69,.25)}.iq-messages{flex:1;min-height:0;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:10px}.iq-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:var(--iq-text-secondary)}.iq-empty-icon{font-size:3rem;margin-bottom:8px;display:flex;align-items:center;justify-content:center}.iq-empty-img{width:48px;height:48px;object-fit:contain;border-radius:8px}.iq-empty-svg{width:48px;height:48px;display:flex;align-items:center;justify-content:center}.iq-empty-svg :deep(svg){width:100%;height:100%}.iq-empty p{font-size:.95rem;margin:2px 0}.iq-text-muted{color:var(--iq-text-muted)!important;font-size:.8rem!important}.iq-msg{display:flex;flex-direction:column;max-width:85%}.iq-msg-user{align-self:flex-end}.iq-msg-bot{align-self:flex-start;max-width:100%}.iq-msg-user .iq-msg-content{background:linear-gradient(135deg,var(--iq-primary),var(--iq-primary-light));border-radius:12px 12px 0}.iq-msg-bot .iq-msg-content{background:var(--iq-bg-tertiary);border-radius:12px 12px 12px 0}.iq-msg-content{padding:10px 14px;color:var(--iq-text);font-size:.85rem;line-height:1.45}.iq-msg-content p{margin:0;white-space:pre-wrap}.iq-msg-time{display:block;margin-top:4px;font-size:.65rem;color:#ffffff80}.iq-md{line-height:1.5;overflow-x:auto;max-width:100%}.iq-md :first-child{margin-top:0}.iq-md :last-child{margin-bottom:0}.iq-md p{margin:0 0 .4em}.iq-md p:last-child{margin-bottom:0}.iq-md strong{color:var(--iq-accent)}.iq-md ul,.iq-md ol{margin:.3em 0;padding-left:1.2em}.iq-md li{margin:.15em 0}.iq-md code{background:#0000004d;padding:.15em .4em;border-radius:3px;font-size:.82em}.iq-md pre{background:#0000004d;padding:.8em;border-radius:6px;overflow-x:auto;font-size:.78em;margin:.4em 0}.iq-md pre code{background:none;padding:0}.iq-md table{width:max-content;min-width:100%;border-collapse:separate;border-spacing:0;margin:.5em 0;font-size:.75rem;border-radius:6px;overflow:hidden}.iq-md thead th{background:#6366f12e;color:#a5b4fc;font-weight:600;text-align:left;padding:.5em .8em;border-bottom:2px solid rgba(99,102,241,.3);white-space:nowrap;font-size:.7rem;text-transform:uppercase;letter-spacing:.05em}.iq-md tbody td{padding:.4em .8em;border-bottom:1px solid rgba(255,255,255,.06);white-space:nowrap;color:var(--iq-text-secondary)}.iq-md tbody tr:hover{background:#6366f114}.iq-md img{max-height:80px;max-width:120px;object-fit:cover;border-radius:8px;margin:6px 4px 6px 0;display:inline-block;vertical-align:middle;border:1px solid rgba(255,255,255,.15);box-shadow:0 1px 4px #00000040;cursor:pointer;transition:transform .15s,box-shadow .15s}.iq-md img:hover{transform:scale(1.05);box-shadow:0 3px 12px #6366f159;border-color:var(--iq-accent)}.iq-md img[alt*=logo],.iq-md img[alt*=marca]{max-height:28px;max-width:90px;object-fit:contain;border:none;box-shadow:none;border-radius:4px;background:#ffffffe6;padding:2px 6px}.iq-btn-trace{align-self:flex-start;margin-top:4px;background:transparent;border:1px solid var(--iq-border);color:var(--iq-text-secondary);font-size:.7rem;padding:3px 8px;border-radius:4px;cursor:pointer;transition:all .15s}.iq-btn-trace:hover{border-color:var(--iq-accent);color:var(--iq-accent)}.iq-pipeline{display:flex;align-items:center;gap:8px;animation:iq-fade-in .3s ease-out}.iq-dot{width:8px;height:8px;border-radius:50%;background:var(--iq-accent);animation:iq-pulse 1s ease-in-out infinite}.iq-pipeline-text{font-size:.8rem;color:var(--iq-text-muted);font-style:italic;flex:1}.iq-cancel-btn{background:transparent;border:1px solid var(--iq-border);color:var(--iq-text-muted);font-size:.7rem;padding:2px 8px;border-radius:4px;cursor:pointer;transition:all .15s;flex-shrink:0}.iq-cancel-btn:hover{border-color:#ff6b6b;color:#ff6b6b;background:#ff6b6b1a}@keyframes iq-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.7)}}@keyframes iq-fade-in{0%{opacity:0;transform:translate(-6px)}to{opacity:1;transform:translate(0)}}.iq-input-bar{display:flex;gap:8px;padding:10px 12px;border-top:1px solid var(--iq-border);background:var(--iq-bg-card)}.iq-input-bar input{flex:1;padding:8px 12px;background:var(--iq-bg-tertiary);border:1px solid var(--iq-border);border-radius:8px;color:var(--iq-text);font-size:.85rem;font-family:var(--iq-font);outline:none;transition:border-color .15s}.iq-input-bar input:focus{border-color:var(--iq-accent)}.iq-input-bar input::placeholder{color:var(--iq-text-muted)}.iq-input-bar input:disabled{opacity:.5}.iq-btn-send{width:36px;height:36px;border-radius:8px;border:none;background:linear-gradient(135deg,var(--iq-accent),var(--iq-accent-light));color:var(--iq-bg);font-size:1rem;cursor:pointer;transition:all .2s;display:flex;align-items:center;justify-content:center}.iq-btn-send:hover:not(:disabled){box-shadow:0 0 12px #00d4aa66;transform:translateY(-1px)}.iq-btn-send:disabled{opacity:.4;cursor:not-allowed}.iq-trace-overlay{position:fixed;inset:0;z-index:calc(var(--iq-z) + 10);background:#0009;display:flex;align-items:center;justify-content:center;animation:iq-fade-in .2s ease-out}.iq-trace-modal{width:90%;max-width:520px;max-height:80vh;background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 20px 50px #0009}.iq-trace-header{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--iq-border)}.iq-trace-header h3{margin:0;font-size:.95rem;color:var(--iq-text)}.iq-trace-body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px}.iq-trace-item label{display:block;font-size:.7rem;color:var(--iq-text-muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.05em}.iq-trace-item code{display:block;padding:8px;background:var(--iq-bg-tertiary);border-radius:4px;font-family:monospace;font-size:.8rem;color:var(--iq-accent);word-break:break-all}.iq-trace-item pre{margin:0;padding:8px;background:var(--iq-bg-tertiary);border-radius:4px;font-family:monospace;font-size:.7rem;overflow-x:auto;max-height:180px;color:var(--iq-text-secondary)}.iq-cache-hit{background:#10b98126!important;color:#10b981!important}.iq-query-code{color:var(--iq-accent)!important}.iq-link-overlay{position:fixed;inset:0;z-index:calc(var(--iq-z) + 20);background:#000000b3;display:flex;align-items:center;justify-content:center;animation:iq-fade-in .2s ease-out;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.iq-link-modal{width:94vw;height:92vh;background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 60px #000000b3;animation:iq-expand .25s cubic-bezier(.4,0,.2,1)}.iq-link-header{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--iq-border);background:var(--iq-bg-card);gap:12px;min-height:44px}.iq-link-title{flex:1;font-size:.78rem;color:var(--iq-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:monospace}.iq-link-actions{display:flex;gap:4px;flex-shrink:0}.iq-link-actions a{text-decoration:none}.iq-back-btn{flex-shrink:0;font-size:1.1rem;transition:transform .15s ease}.iq-back-btn:hover{transform:translate(-2px)}.iq-iframe-wrapper{flex:1;position:relative;overflow:hidden}.iq-link-iframe{width:100%;height:100%;border:none;background:#fff;transition:opacity .3s ease}.iq-iframe-hidden{opacity:0}.iq-modal-img{width:100%;height:100%;object-fit:contain;background:#1a1a2e}.iq-iframe-loader{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:var(--iq-bg);gap:16px;z-index:2}.iq-spinner{width:40px;height:40px;border:3px solid var(--iq-border);border-top-color:var(--iq-accent);border-radius:50%;animation:iq-spin .8s linear infinite}.iq-loader-text{font-size:.85rem;color:var(--iq-text-secondary);font-weight:500}@keyframes iq-spin{to{transform:rotate(360deg)}}.iq-md a{color:var(--iq-accent);text-decoration:underline;cursor:pointer;transition:color .15s}.iq-md a:hover{color:var(--iq-accent-light)}@media(max-width:480px){.iq-link-modal{width:100vw;height:100dvh;border-radius:0}.iq-link-header{padding:8px 12px}.iq-link-title{font-size:.7rem}}.iq-messages::-webkit-scrollbar{width:5px}.iq-messages::-webkit-scrollbar-track{background:transparent}.iq-messages::-webkit-scrollbar-thumb{background:var(--iq-border);border-radius:4px}.iq-trace-body::-webkit-scrollbar{width:5px}.iq-trace-body::-webkit-scrollbar-track{background:transparent}.iq-trace-body::-webkit-scrollbar-thumb{background:var(--iq-border);border-radius:4px}.iq-expanded .iq-messages::-webkit-scrollbar{width:8px}.iq-expanded .iq-messages{scrollbar-gutter:stable}@media(max-width:480px){.iq-bubble{bottom:16px;right:16px;width:48px;height:48px;font-size:1.3rem}.iq-bubble.iq-bottom-left{left:16px}.iq-bubble .iq-bubble-icon{font-size:1.2rem}.iq-panel{right:8px;left:8px;bottom:72px;width:auto!important;max-width:calc(100vw - 16px);height:calc(100dvh - 90px);max-height:calc(100dvh - 90px)}.iq-panel.iq-bottom-left{left:8px;right:8px}.iq-panel.iq-expanded{inset:0!important;width:100vw!important;height:100dvh!important;max-height:100dvh!important;max-width:100vw!important;border-radius:0}.iq-header{padding:10px 12px}.iq-header-title{font-size:.85rem}.iq-header-btn{padding:6px 8px;min-width:32px;min-height:32px}.iq-messages{padding:8px;gap:8px}.iq-msg{max-width:92%}.iq-msg-bot{max-width:100%}.iq-msg-content{padding:8px 10px;font-size:.8rem}.iq-md{overflow-x:auto;-webkit-overflow-scrolling:touch}.iq-md table{font-size:.65rem;min-width:unset}.iq-md thead th{padding:.35em .5em;font-size:.6rem}.iq-md tbody td{padding:.3em .5em;font-size:.65rem}.iq-empty-icon{font-size:2.5rem}.iq-empty p{font-size:.85rem}.iq-input-bar{padding:8px 10px;gap:6px}.iq-input-bar input{font-size:16px;padding:8px 10px}.iq-btn-send{width:38px;height:38px;flex-shrink:0}.iq-trace-modal{width:calc(100vw - 24px);max-height:90dvh}.iq-trace-header{padding:12px}.iq-trace-header h3{font-size:.85rem}.iq-trace-body{padding:12px}.iq-trace-item pre{font-size:.65rem;max-height:140px}}@media(max-height:500px)and (orientation:landscape){.iq-bubble{bottom:8px;right:8px;width:44px;height:44px;font-size:1.1rem}.iq-bubble.iq-bottom-left{left:8px}.iq-panel{inset:8px 60px 8px 8px;width:auto!important;max-width:calc(100vw - 76px);height:auto!important;max-height:calc(100dvh - 16px);border-radius:var(--iq-radius)}.iq-panel.iq-bottom-left{left:60px;right:8px}.iq-panel.iq-expanded{inset:0!important;width:100vw!important;height:100dvh!important;max-height:100dvh!important;max-width:100vw!important;border-radius:0}.iq-header{padding:6px 12px}.iq-header-title{font-size:.8rem}.iq-messages{padding:6px 10px;gap:6px}.iq-empty-icon{font-size:1.8rem;margin-bottom:4px}.iq-empty p{font-size:.78rem;margin:1px 0}.iq-input-bar{padding:6px 10px}.iq-input-bar input{font-size:16px;padding:6px 10px}.iq-btn-send{width:32px;height:32px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: i1.JsonPipe, name: "json" }] });
|
|
1012
1205
|
}
|
|
1013
1206
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: IntelligentChatPluginComponent, decorators: [{
|
|
1014
1207
|
type: Component,
|
|
@@ -1055,8 +1248,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImpor
|
|
|
1055
1248
|
>
|
|
1056
1249
|
<!-- Header -->
|
|
1057
1250
|
<div class="iq-header">
|
|
1058
|
-
<span class="iq-header-title"
|
|
1251
|
+
<span class="iq-header-title"
|
|
1252
|
+
(touchstart)="onTitleTouchStart($event)"
|
|
1253
|
+
(touchend)="onTitleTouchEnd()"
|
|
1254
|
+
(touchcancel)="onTitleTouchEnd()"
|
|
1255
|
+
>{{ resolvedConfig().title }}</span>
|
|
1059
1256
|
<div class="iq-header-actions">
|
|
1257
|
+
@if (resolvedConfig().enableDebugMenu) {
|
|
1258
|
+
<div class="iq-debug-menu-wrapper">
|
|
1259
|
+
<button class="iq-header-btn" (click)="toggleDebugMenu()" title="Opciones">⋯</button>
|
|
1260
|
+
@if (showDebugMenu()) {
|
|
1261
|
+
<div class="iq-debug-dropdown">
|
|
1262
|
+
<button class="iq-debug-option" (click)="downloadConversationLog(); toggleDebugMenu()">
|
|
1263
|
+
📥 Descargar Log
|
|
1264
|
+
</button>
|
|
1265
|
+
</div>
|
|
1266
|
+
}
|
|
1267
|
+
</div>
|
|
1268
|
+
}
|
|
1060
1269
|
<button class="iq-header-btn" (click)="clearChat()" title="Limpiar chat">🗑️</button>
|
|
1061
1270
|
@if (resolvedConfig().allowExpand) {
|
|
1062
1271
|
<button class="iq-header-btn iq-btn-expand" (click)="toggleExpand()" [title]="isExpanded() ? 'Contraer' : 'Expandir'">
|
|
@@ -1159,8 +1368,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImpor
|
|
|
1159
1368
|
}
|
|
1160
1369
|
@if (selectedTrace()?.query) {
|
|
1161
1370
|
<div class="iq-trace-item">
|
|
1162
|
-
<label>Query Generada</label>
|
|
1163
|
-
|
|
1371
|
+
<label>{{ getQuerySections().length > 1 ? 'Queries Generadas (' + getQuerySections().length + ')' : 'Query Generada' }}</label>
|
|
1372
|
+
@for (section of getQuerySections(); track $index) {
|
|
1373
|
+
@if (section.model) {
|
|
1374
|
+
<div style="color: #4ecdc4; font-size: 11px; font-weight: bold; margin-top: 8px;">📋 {{ section.model }}</div>
|
|
1375
|
+
}
|
|
1376
|
+
<pre class="iq-query-code" style="margin-top: 4px;">{{ section.query }}</pre>
|
|
1377
|
+
}
|
|
1164
1378
|
</div>
|
|
1165
1379
|
}
|
|
1166
1380
|
@if (selectedTrace()?.explanation) {
|
|
@@ -1220,12 +1434,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImpor
|
|
|
1220
1434
|
}
|
|
1221
1435
|
|
|
1222
1436
|
</div><!-- /iq-theme-host -->
|
|
1223
|
-
`, styles: [":host{--iq-primary: #1a3a5c;--iq-primary-light: #2a5a8c;--iq-accent: #00d4aa;--iq-accent-light: #33e0be;--iq-bg: #1e1e2f;--iq-bg-card: #252538;--iq-bg-tertiary: #35354a;--iq-text: #ffffff;--iq-text-secondary: #a0a0b0;--iq-text-muted: #6c6c7c;--iq-border: #3a3a4d;--iq-radius: 12px;--iq-bubble-size: 56px;--iq-panel-width: 400px;--iq-panel-height: 520px;--iq-z: 10000;--iq-font: \"Inter\", \"Roboto\", -apple-system, BlinkMacSystemFont, sans-serif;font-family:var(--iq-font)}.iq-bubble{position:fixed;bottom:24px;right:24px;z-index:var(--iq-z);width:var(--iq-bubble-size);height:var(--iq-bubble-size);border-radius:50%;border:none;background:linear-gradient(135deg,var(--iq-accent),var(--iq-accent-light));color:var(--iq-bg);font-size:1.6rem;cursor:pointer;box-shadow:0 4px 16px #00d4aa66;transition:all .3s cubic-bezier(.4,0,.2,1);display:flex;align-items:center;justify-content:center}.iq-bubble:hover{transform:scale(1.1);box-shadow:0 6px 24px #00d4aa80}.iq-bubble .iq-bubble-icon{font-size:1.5rem;pointer-events:none}.iq-bubble-img{width:60%;height:60%;object-fit:contain;border-radius:50%;pointer-events:none}.iq-bubble-svg{width:60%;height:60%;display:flex;align-items:center;justify-content:center;pointer-events:none}.iq-bubble-svg :deep(svg){width:100%;height:100%}.iq-bubble.iq-open{background:var(--iq-bg-tertiary);color:var(--iq-text);box-shadow:0 4px 12px #0000004d;font-size:1.2rem}.iq-bubble.iq-bottom-left{right:auto;left:24px}.iq-bubble-icon{line-height:1}.iq-panel{position:fixed;bottom:92px;right:24px;z-index:var(--iq-z);width:var(--iq-panel-width);height:var(--iq-panel-height);background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 12px 40px #00000080;animation:iq-slide-up .3s cubic-bezier(.4,0,.2,1)}.iq-panel.iq-bottom-left{right:auto;left:24px}.iq-panel.iq-expanded{width:100vw!important;height:100vh!important;inset:0!important;border:none;border-radius:0;overflow:clip;z-index:calc(var(--iq-z) + 5);animation:iq-expand .3s cubic-bezier(.4,0,.2,1)}.iq-btn-expand{font-size:1.1rem!important}@keyframes iq-expand{0%{opacity:.8;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes iq-slide-up{0%{opacity:0;transform:translateY(16px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.iq-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--iq-border);background:var(--iq-bg-card)}.iq-header-title{font-weight:600;font-size:.95rem;color:var(--iq-text)}.iq-header-actions{display:flex;gap:4px}.iq-header-btn{background:none;border:none;color:var(--iq-text-muted);cursor:pointer;font-size:1rem;padding:4px 6px;border-radius:4px;transition:all .15s}.iq-header-btn:hover{color:var(--iq-text);background:#ffffff14}.iq-auth-error{display:flex;align-items:center;gap:8px;padding:10px 16px;background:#dc354526;color:#ff6b7a;font-size:.8rem;border-bottom:1px solid rgba(220,53,69,.25)}.iq-messages{flex:1;min-height:0;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:10px}.iq-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:var(--iq-text-secondary)}.iq-empty-icon{font-size:3rem;margin-bottom:8px;display:flex;align-items:center;justify-content:center}.iq-empty-img{width:48px;height:48px;object-fit:contain;border-radius:8px}.iq-empty-svg{width:48px;height:48px;display:flex;align-items:center;justify-content:center}.iq-empty-svg :deep(svg){width:100%;height:100%}.iq-empty p{font-size:.95rem;margin:2px 0}.iq-text-muted{color:var(--iq-text-muted)!important;font-size:.8rem!important}.iq-msg{display:flex;flex-direction:column;max-width:85%}.iq-msg-user{align-self:flex-end}.iq-msg-bot{align-self:flex-start;max-width:100%}.iq-msg-user .iq-msg-content{background:linear-gradient(135deg,var(--iq-primary),var(--iq-primary-light));border-radius:12px 12px 0}.iq-msg-bot .iq-msg-content{background:var(--iq-bg-tertiary);border-radius:12px 12px 12px 0}.iq-msg-content{padding:10px 14px;color:var(--iq-text);font-size:.85rem;line-height:1.45}.iq-msg-content p{margin:0;white-space:pre-wrap}.iq-msg-time{display:block;margin-top:4px;font-size:.65rem;color:#ffffff80}.iq-md{line-height:1.5;overflow-x:auto;max-width:100%}.iq-md :first-child{margin-top:0}.iq-md :last-child{margin-bottom:0}.iq-md p{margin:0 0 .4em}.iq-md p:last-child{margin-bottom:0}.iq-md strong{color:var(--iq-accent)}.iq-md ul,.iq-md ol{margin:.3em 0;padding-left:1.2em}.iq-md li{margin:.15em 0}.iq-md code{background:#0000004d;padding:.15em .4em;border-radius:3px;font-size:.82em}.iq-md pre{background:#0000004d;padding:.8em;border-radius:6px;overflow-x:auto;font-size:.78em;margin:.4em 0}.iq-md pre code{background:none;padding:0}.iq-md table{width:max-content;min-width:100%;border-collapse:separate;border-spacing:0;margin:.5em 0;font-size:.75rem;border-radius:6px;overflow:hidden}.iq-md thead th{background:#6366f12e;color:#a5b4fc;font-weight:600;text-align:left;padding:.5em .8em;border-bottom:2px solid rgba(99,102,241,.3);white-space:nowrap;font-size:.7rem;text-transform:uppercase;letter-spacing:.05em}.iq-md tbody td{padding:.4em .8em;border-bottom:1px solid rgba(255,255,255,.06);white-space:nowrap;color:var(--iq-text-secondary)}.iq-md tbody tr:hover{background:#6366f114}.iq-md img{max-height:80px;max-width:120px;object-fit:cover;border-radius:8px;margin:6px 4px 6px 0;display:inline-block;vertical-align:middle;border:1px solid rgba(255,255,255,.15);box-shadow:0 1px 4px #00000040;cursor:pointer;transition:transform .15s,box-shadow .15s}.iq-md img:hover{transform:scale(1.05);box-shadow:0 3px 12px #6366f159;border-color:var(--iq-accent)}.iq-md img[alt*=logo],.iq-md img[alt*=marca]{max-height:28px;max-width:90px;object-fit:contain;border:none;box-shadow:none;border-radius:4px;background:#ffffffe6;padding:2px 6px}.iq-btn-trace{align-self:flex-start;margin-top:4px;background:transparent;border:1px solid var(--iq-border);color:var(--iq-text-secondary);font-size:.7rem;padding:3px 8px;border-radius:4px;cursor:pointer;transition:all .15s}.iq-btn-trace:hover{border-color:var(--iq-accent);color:var(--iq-accent)}.iq-pipeline{display:flex;align-items:center;gap:8px;animation:iq-fade-in .3s ease-out}.iq-dot{width:8px;height:8px;border-radius:50%;background:var(--iq-accent);animation:iq-pulse 1s ease-in-out infinite}.iq-pipeline-text{font-size:.8rem;color:var(--iq-text-muted);font-style:italic;flex:1}.iq-cancel-btn{background:transparent;border:1px solid var(--iq-border);color:var(--iq-text-muted);font-size:.7rem;padding:2px 8px;border-radius:4px;cursor:pointer;transition:all .15s;flex-shrink:0}.iq-cancel-btn:hover{border-color:#ff6b6b;color:#ff6b6b;background:#ff6b6b1a}@keyframes iq-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.7)}}@keyframes iq-fade-in{0%{opacity:0;transform:translate(-6px)}to{opacity:1;transform:translate(0)}}.iq-input-bar{display:flex;gap:8px;padding:10px 12px;border-top:1px solid var(--iq-border);background:var(--iq-bg-card)}.iq-input-bar input{flex:1;padding:8px 12px;background:var(--iq-bg-tertiary);border:1px solid var(--iq-border);border-radius:8px;color:var(--iq-text);font-size:.85rem;font-family:var(--iq-font);outline:none;transition:border-color .15s}.iq-input-bar input:focus{border-color:var(--iq-accent)}.iq-input-bar input::placeholder{color:var(--iq-text-muted)}.iq-input-bar input:disabled{opacity:.5}.iq-btn-send{width:36px;height:36px;border-radius:8px;border:none;background:linear-gradient(135deg,var(--iq-accent),var(--iq-accent-light));color:var(--iq-bg);font-size:1rem;cursor:pointer;transition:all .2s;display:flex;align-items:center;justify-content:center}.iq-btn-send:hover:not(:disabled){box-shadow:0 0 12px #00d4aa66;transform:translateY(-1px)}.iq-btn-send:disabled{opacity:.4;cursor:not-allowed}.iq-trace-overlay{position:fixed;inset:0;z-index:calc(var(--iq-z) + 10);background:#0009;display:flex;align-items:center;justify-content:center;animation:iq-fade-in .2s ease-out}.iq-trace-modal{width:90%;max-width:520px;max-height:80vh;background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 20px 50px #0009}.iq-trace-header{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--iq-border)}.iq-trace-header h3{margin:0;font-size:.95rem;color:var(--iq-text)}.iq-trace-body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px}.iq-trace-item label{display:block;font-size:.7rem;color:var(--iq-text-muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.05em}.iq-trace-item code{display:block;padding:8px;background:var(--iq-bg-tertiary);border-radius:4px;font-family:monospace;font-size:.8rem;color:var(--iq-accent);word-break:break-all}.iq-trace-item pre{margin:0;padding:8px;background:var(--iq-bg-tertiary);border-radius:4px;font-family:monospace;font-size:.7rem;overflow-x:auto;max-height:180px;color:var(--iq-text-secondary)}.iq-cache-hit{background:#10b98126!important;color:#10b981!important}.iq-query-code{color:var(--iq-accent)!important}.iq-link-overlay{position:fixed;inset:0;z-index:calc(var(--iq-z) + 20);background:#000000b3;display:flex;align-items:center;justify-content:center;animation:iq-fade-in .2s ease-out;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.iq-link-modal{width:94vw;height:92vh;background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 60px #000000b3;animation:iq-expand .25s cubic-bezier(.4,0,.2,1)}.iq-link-header{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--iq-border);background:var(--iq-bg-card);gap:12px;min-height:44px}.iq-link-title{flex:1;font-size:.78rem;color:var(--iq-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:monospace}.iq-link-actions{display:flex;gap:4px;flex-shrink:0}.iq-link-actions a{text-decoration:none}.iq-back-btn{flex-shrink:0;font-size:1.1rem;transition:transform .15s ease}.iq-back-btn:hover{transform:translate(-2px)}.iq-iframe-wrapper{flex:1;position:relative;overflow:hidden}.iq-link-iframe{width:100%;height:100%;border:none;background:#fff;transition:opacity .3s ease}.iq-iframe-hidden{opacity:0}.iq-modal-img{width:100%;height:100%;object-fit:contain;background:#1a1a2e}.iq-iframe-loader{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:var(--iq-bg);gap:16px;z-index:2}.iq-spinner{width:40px;height:40px;border:3px solid var(--iq-border);border-top-color:var(--iq-accent);border-radius:50%;animation:iq-spin .8s linear infinite}.iq-loader-text{font-size:.85rem;color:var(--iq-text-secondary);font-weight:500}@keyframes iq-spin{to{transform:rotate(360deg)}}.iq-md a{color:var(--iq-accent);text-decoration:underline;cursor:pointer;transition:color .15s}.iq-md a:hover{color:var(--iq-accent-light)}@media(max-width:480px){.iq-link-modal{width:100vw;height:100dvh;border-radius:0}.iq-link-header{padding:8px 12px}.iq-link-title{font-size:.7rem}}.iq-messages::-webkit-scrollbar{width:5px}.iq-messages::-webkit-scrollbar-track{background:transparent}.iq-messages::-webkit-scrollbar-thumb{background:var(--iq-border);border-radius:4px}.iq-trace-body::-webkit-scrollbar{width:5px}.iq-trace-body::-webkit-scrollbar-track{background:transparent}.iq-trace-body::-webkit-scrollbar-thumb{background:var(--iq-border);border-radius:4px}.iq-expanded .iq-messages::-webkit-scrollbar{width:8px}.iq-expanded .iq-messages{scrollbar-gutter:stable}@media(max-width:480px){.iq-bubble{bottom:16px;right:16px;width:48px;height:48px;font-size:1.3rem}.iq-bubble.iq-bottom-left{left:16px}.iq-bubble .iq-bubble-icon{font-size:1.2rem}.iq-panel{right:8px;left:8px;bottom:72px;width:auto!important;max-width:calc(100vw - 16px);height:calc(100dvh - 90px);max-height:calc(100dvh - 90px)}.iq-panel.iq-bottom-left{left:8px;right:8px}.iq-panel.iq-expanded{inset:0!important;width:100vw!important;height:100dvh!important;max-height:100dvh!important;max-width:100vw!important;border-radius:0}.iq-header{padding:10px 12px}.iq-header-title{font-size:.85rem}.iq-header-btn{padding:6px 8px;min-width:32px;min-height:32px}.iq-messages{padding:8px;gap:8px}.iq-msg{max-width:92%}.iq-msg-bot{max-width:100%}.iq-msg-content{padding:8px 10px;font-size:.8rem}.iq-md{overflow-x:auto;-webkit-overflow-scrolling:touch}.iq-md table{font-size:.65rem;min-width:unset}.iq-md thead th{padding:.35em .5em;font-size:.6rem}.iq-md tbody td{padding:.3em .5em;font-size:.65rem}.iq-empty-icon{font-size:2.5rem}.iq-empty p{font-size:.85rem}.iq-input-bar{padding:8px 10px;gap:6px}.iq-input-bar input{font-size:16px;padding:8px 10px}.iq-btn-send{width:38px;height:38px;flex-shrink:0}.iq-trace-modal{width:calc(100vw - 24px);max-height:90dvh}.iq-trace-header{padding:12px}.iq-trace-header h3{font-size:.85rem}.iq-trace-body{padding:12px}.iq-trace-item pre{font-size:.65rem;max-height:140px}}@media(max-height:500px)and (orientation:landscape){.iq-bubble{bottom:8px;right:8px;width:44px;height:44px;font-size:1.1rem}.iq-bubble.iq-bottom-left{left:8px}.iq-panel{inset:8px 60px 8px 8px;width:auto!important;max-width:calc(100vw - 76px);height:auto!important;max-height:calc(100dvh - 16px);border-radius:var(--iq-radius)}.iq-panel.iq-bottom-left{left:60px;right:8px}.iq-panel.iq-expanded{inset:0!important;width:100vw!important;height:100dvh!important;max-height:100dvh!important;max-width:100vw!important;border-radius:0}.iq-header{padding:6px 12px}.iq-header-title{font-size:.8rem}.iq-messages{padding:6px 10px;gap:6px}.iq-empty-icon{font-size:1.8rem;margin-bottom:4px}.iq-empty p{font-size:.78rem;margin:1px 0}.iq-input-bar{padding:6px 10px}.iq-input-bar input{font-size:16px;padding:6px 10px}.iq-btn-send{width:32px;height:32px}}\n"] }]
|
|
1437
|
+
`, styles: [":host{--iq-primary: #1a3a5c;--iq-primary-light: #2a5a8c;--iq-accent: #00d4aa;--iq-accent-light: #33e0be;--iq-bg: #1e1e2f;--iq-bg-card: #252538;--iq-bg-tertiary: #35354a;--iq-text: #ffffff;--iq-text-secondary: #a0a0b0;--iq-text-muted: #6c6c7c;--iq-border: #3a3a4d;--iq-radius: 12px;--iq-bubble-size: 56px;--iq-panel-width: 400px;--iq-panel-height: 520px;--iq-z: 10000;--iq-font: \"Inter\", \"Roboto\", -apple-system, BlinkMacSystemFont, sans-serif;font-family:var(--iq-font)}.iq-bubble{position:fixed;bottom:24px;right:24px;z-index:var(--iq-z);width:var(--iq-bubble-size);height:var(--iq-bubble-size);border-radius:50%;border:none;background:linear-gradient(135deg,var(--iq-accent),var(--iq-accent-light));color:var(--iq-bg);font-size:1.6rem;cursor:pointer;box-shadow:0 4px 16px #00d4aa66;transition:all .3s cubic-bezier(.4,0,.2,1);display:flex;align-items:center;justify-content:center}.iq-bubble:hover{transform:scale(1.1);box-shadow:0 6px 24px #00d4aa80}.iq-bubble .iq-bubble-icon{font-size:1.5rem;pointer-events:none}.iq-bubble-img{width:60%;height:60%;object-fit:contain;border-radius:50%;pointer-events:none}.iq-bubble-svg{width:60%;height:60%;display:flex;align-items:center;justify-content:center;pointer-events:none}.iq-bubble-svg :deep(svg){width:100%;height:100%}.iq-bubble.iq-open{background:var(--iq-bg-tertiary);color:var(--iq-text);box-shadow:0 4px 12px #0000004d;font-size:1.2rem}.iq-bubble.iq-bottom-left{right:auto;left:24px}.iq-bubble-icon{line-height:1}.iq-panel{position:fixed;bottom:92px;right:24px;z-index:var(--iq-z);width:var(--iq-panel-width);height:var(--iq-panel-height);background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 12px 40px #00000080;animation:iq-slide-up .3s cubic-bezier(.4,0,.2,1)}.iq-panel.iq-bottom-left{right:auto;left:24px}.iq-panel.iq-expanded{width:100vw!important;height:100vh!important;inset:0!important;border:none;border-radius:0;overflow:clip;z-index:calc(var(--iq-z) + 5);animation:iq-expand .3s cubic-bezier(.4,0,.2,1)}.iq-btn-expand{font-size:1.1rem!important}@keyframes iq-expand{0%{opacity:.8;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes iq-slide-up{0%{opacity:0;transform:translateY(16px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.iq-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--iq-border);background:var(--iq-bg-card)}.iq-header-title{font-weight:600;font-size:.95rem;color:var(--iq-text)}.iq-header-actions{display:flex;gap:4px}.iq-header-btn{background:none;border:none;color:var(--iq-text-muted);cursor:pointer;font-size:1rem;padding:4px 6px;border-radius:4px;transition:all .15s}.iq-header-btn:hover{color:var(--iq-text);background:#ffffff14}.iq-debug-menu-wrapper{position:relative}.iq-debug-dropdown{position:absolute;top:100%;right:0;margin-top:4px;min-width:180px;background:var(--iq-bg-card);border:1px solid var(--iq-border);border-radius:8px;box-shadow:0 8px 24px #0006;z-index:calc(var(--iq-z) + 10);padding:4px;animation:iq-dropdown-in .15s ease-out}@keyframes iq-dropdown-in{0%{opacity:0;transform:translateY(-4px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.iq-debug-option{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;background:none;border:none;color:var(--iq-text);font-size:.85rem;cursor:pointer;border-radius:6px;transition:background .15s;text-align:left}.iq-debug-option:hover{background:#ffffff14}.iq-auth-error{display:flex;align-items:center;gap:8px;padding:10px 16px;background:#dc354526;color:#ff6b7a;font-size:.8rem;border-bottom:1px solid rgba(220,53,69,.25)}.iq-messages{flex:1;min-height:0;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:10px}.iq-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:var(--iq-text-secondary)}.iq-empty-icon{font-size:3rem;margin-bottom:8px;display:flex;align-items:center;justify-content:center}.iq-empty-img{width:48px;height:48px;object-fit:contain;border-radius:8px}.iq-empty-svg{width:48px;height:48px;display:flex;align-items:center;justify-content:center}.iq-empty-svg :deep(svg){width:100%;height:100%}.iq-empty p{font-size:.95rem;margin:2px 0}.iq-text-muted{color:var(--iq-text-muted)!important;font-size:.8rem!important}.iq-msg{display:flex;flex-direction:column;max-width:85%}.iq-msg-user{align-self:flex-end}.iq-msg-bot{align-self:flex-start;max-width:100%}.iq-msg-user .iq-msg-content{background:linear-gradient(135deg,var(--iq-primary),var(--iq-primary-light));border-radius:12px 12px 0}.iq-msg-bot .iq-msg-content{background:var(--iq-bg-tertiary);border-radius:12px 12px 12px 0}.iq-msg-content{padding:10px 14px;color:var(--iq-text);font-size:.85rem;line-height:1.45}.iq-msg-content p{margin:0;white-space:pre-wrap}.iq-msg-time{display:block;margin-top:4px;font-size:.65rem;color:#ffffff80}.iq-md{line-height:1.5;overflow-x:auto;max-width:100%}.iq-md :first-child{margin-top:0}.iq-md :last-child{margin-bottom:0}.iq-md p{margin:0 0 .4em}.iq-md p:last-child{margin-bottom:0}.iq-md strong{color:var(--iq-accent)}.iq-md ul,.iq-md ol{margin:.3em 0;padding-left:1.2em}.iq-md li{margin:.15em 0}.iq-md code{background:#0000004d;padding:.15em .4em;border-radius:3px;font-size:.82em}.iq-md pre{background:#0000004d;padding:.8em;border-radius:6px;overflow-x:auto;font-size:.78em;margin:.4em 0}.iq-md pre code{background:none;padding:0}.iq-md table{width:max-content;min-width:100%;border-collapse:separate;border-spacing:0;margin:.5em 0;font-size:.75rem;border-radius:6px;overflow:hidden}.iq-md thead th{background:#6366f12e;color:#a5b4fc;font-weight:600;text-align:left;padding:.5em .8em;border-bottom:2px solid rgba(99,102,241,.3);white-space:nowrap;font-size:.7rem;text-transform:uppercase;letter-spacing:.05em}.iq-md tbody td{padding:.4em .8em;border-bottom:1px solid rgba(255,255,255,.06);white-space:nowrap;color:var(--iq-text-secondary)}.iq-md tbody tr:hover{background:#6366f114}.iq-md img{max-height:80px;max-width:120px;object-fit:cover;border-radius:8px;margin:6px 4px 6px 0;display:inline-block;vertical-align:middle;border:1px solid rgba(255,255,255,.15);box-shadow:0 1px 4px #00000040;cursor:pointer;transition:transform .15s,box-shadow .15s}.iq-md img:hover{transform:scale(1.05);box-shadow:0 3px 12px #6366f159;border-color:var(--iq-accent)}.iq-md img[alt*=logo],.iq-md img[alt*=marca]{max-height:28px;max-width:90px;object-fit:contain;border:none;box-shadow:none;border-radius:4px;background:#ffffffe6;padding:2px 6px}.iq-btn-trace{align-self:flex-start;margin-top:4px;background:transparent;border:1px solid var(--iq-border);color:var(--iq-text-secondary);font-size:.7rem;padding:3px 8px;border-radius:4px;cursor:pointer;transition:all .15s}.iq-btn-trace:hover{border-color:var(--iq-accent);color:var(--iq-accent)}.iq-pipeline{display:flex;align-items:center;gap:8px;animation:iq-fade-in .3s ease-out}.iq-dot{width:8px;height:8px;border-radius:50%;background:var(--iq-accent);animation:iq-pulse 1s ease-in-out infinite}.iq-pipeline-text{font-size:.8rem;color:var(--iq-text-muted);font-style:italic;flex:1}.iq-cancel-btn{background:transparent;border:1px solid var(--iq-border);color:var(--iq-text-muted);font-size:.7rem;padding:2px 8px;border-radius:4px;cursor:pointer;transition:all .15s;flex-shrink:0}.iq-cancel-btn:hover{border-color:#ff6b6b;color:#ff6b6b;background:#ff6b6b1a}@keyframes iq-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.7)}}@keyframes iq-fade-in{0%{opacity:0;transform:translate(-6px)}to{opacity:1;transform:translate(0)}}.iq-input-bar{display:flex;gap:8px;padding:10px 12px;border-top:1px solid var(--iq-border);background:var(--iq-bg-card)}.iq-input-bar input{flex:1;padding:8px 12px;background:var(--iq-bg-tertiary);border:1px solid var(--iq-border);border-radius:8px;color:var(--iq-text);font-size:.85rem;font-family:var(--iq-font);outline:none;transition:border-color .15s}.iq-input-bar input:focus{border-color:var(--iq-accent)}.iq-input-bar input::placeholder{color:var(--iq-text-muted)}.iq-input-bar input:disabled{opacity:.5}.iq-btn-send{width:36px;height:36px;border-radius:8px;border:none;background:linear-gradient(135deg,var(--iq-accent),var(--iq-accent-light));color:var(--iq-bg);font-size:1rem;cursor:pointer;transition:all .2s;display:flex;align-items:center;justify-content:center}.iq-btn-send:hover:not(:disabled){box-shadow:0 0 12px #00d4aa66;transform:translateY(-1px)}.iq-btn-send:disabled{opacity:.4;cursor:not-allowed}.iq-trace-overlay{position:fixed;inset:0;z-index:calc(var(--iq-z) + 10);background:#0009;display:flex;align-items:center;justify-content:center;animation:iq-fade-in .2s ease-out}.iq-trace-modal{width:90%;max-width:520px;max-height:80vh;background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 20px 50px #0009}.iq-trace-header{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--iq-border)}.iq-trace-header h3{margin:0;font-size:.95rem;color:var(--iq-text)}.iq-trace-body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px}.iq-trace-item label{display:block;font-size:.7rem;color:var(--iq-text-muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.05em}.iq-trace-item code{display:block;padding:8px;background:var(--iq-bg-tertiary);border-radius:4px;font-family:monospace;font-size:.8rem;color:var(--iq-accent);word-break:break-all}.iq-trace-item pre{margin:0;padding:8px;background:var(--iq-bg-tertiary);border-radius:4px;font-family:monospace;font-size:.7rem;overflow-x:auto;max-height:180px;color:var(--iq-text-secondary)}.iq-cache-hit{background:#10b98126!important;color:#10b981!important}.iq-query-code{color:var(--iq-accent)!important}.iq-link-overlay{position:fixed;inset:0;z-index:calc(var(--iq-z) + 20);background:#000000b3;display:flex;align-items:center;justify-content:center;animation:iq-fade-in .2s ease-out;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.iq-link-modal{width:94vw;height:92vh;background:var(--iq-bg);border:1px solid var(--iq-border);border-radius:var(--iq-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 60px #000000b3;animation:iq-expand .25s cubic-bezier(.4,0,.2,1)}.iq-link-header{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--iq-border);background:var(--iq-bg-card);gap:12px;min-height:44px}.iq-link-title{flex:1;font-size:.78rem;color:var(--iq-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:monospace}.iq-link-actions{display:flex;gap:4px;flex-shrink:0}.iq-link-actions a{text-decoration:none}.iq-back-btn{flex-shrink:0;font-size:1.1rem;transition:transform .15s ease}.iq-back-btn:hover{transform:translate(-2px)}.iq-iframe-wrapper{flex:1;position:relative;overflow:hidden}.iq-link-iframe{width:100%;height:100%;border:none;background:#fff;transition:opacity .3s ease}.iq-iframe-hidden{opacity:0}.iq-modal-img{width:100%;height:100%;object-fit:contain;background:#1a1a2e}.iq-iframe-loader{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:var(--iq-bg);gap:16px;z-index:2}.iq-spinner{width:40px;height:40px;border:3px solid var(--iq-border);border-top-color:var(--iq-accent);border-radius:50%;animation:iq-spin .8s linear infinite}.iq-loader-text{font-size:.85rem;color:var(--iq-text-secondary);font-weight:500}@keyframes iq-spin{to{transform:rotate(360deg)}}.iq-md a{color:var(--iq-accent);text-decoration:underline;cursor:pointer;transition:color .15s}.iq-md a:hover{color:var(--iq-accent-light)}@media(max-width:480px){.iq-link-modal{width:100vw;height:100dvh;border-radius:0}.iq-link-header{padding:8px 12px}.iq-link-title{font-size:.7rem}}.iq-messages::-webkit-scrollbar{width:5px}.iq-messages::-webkit-scrollbar-track{background:transparent}.iq-messages::-webkit-scrollbar-thumb{background:var(--iq-border);border-radius:4px}.iq-trace-body::-webkit-scrollbar{width:5px}.iq-trace-body::-webkit-scrollbar-track{background:transparent}.iq-trace-body::-webkit-scrollbar-thumb{background:var(--iq-border);border-radius:4px}.iq-expanded .iq-messages::-webkit-scrollbar{width:8px}.iq-expanded .iq-messages{scrollbar-gutter:stable}@media(max-width:480px){.iq-bubble{bottom:16px;right:16px;width:48px;height:48px;font-size:1.3rem}.iq-bubble.iq-bottom-left{left:16px}.iq-bubble .iq-bubble-icon{font-size:1.2rem}.iq-panel{right:8px;left:8px;bottom:72px;width:auto!important;max-width:calc(100vw - 16px);height:calc(100dvh - 90px);max-height:calc(100dvh - 90px)}.iq-panel.iq-bottom-left{left:8px;right:8px}.iq-panel.iq-expanded{inset:0!important;width:100vw!important;height:100dvh!important;max-height:100dvh!important;max-width:100vw!important;border-radius:0}.iq-header{padding:10px 12px}.iq-header-title{font-size:.85rem}.iq-header-btn{padding:6px 8px;min-width:32px;min-height:32px}.iq-messages{padding:8px;gap:8px}.iq-msg{max-width:92%}.iq-msg-bot{max-width:100%}.iq-msg-content{padding:8px 10px;font-size:.8rem}.iq-md{overflow-x:auto;-webkit-overflow-scrolling:touch}.iq-md table{font-size:.65rem;min-width:unset}.iq-md thead th{padding:.35em .5em;font-size:.6rem}.iq-md tbody td{padding:.3em .5em;font-size:.65rem}.iq-empty-icon{font-size:2.5rem}.iq-empty p{font-size:.85rem}.iq-input-bar{padding:8px 10px;gap:6px}.iq-input-bar input{font-size:16px;padding:8px 10px}.iq-btn-send{width:38px;height:38px;flex-shrink:0}.iq-trace-modal{width:calc(100vw - 24px);max-height:90dvh}.iq-trace-header{padding:12px}.iq-trace-header h3{font-size:.85rem}.iq-trace-body{padding:12px}.iq-trace-item pre{font-size:.65rem;max-height:140px}}@media(max-height:500px)and (orientation:landscape){.iq-bubble{bottom:8px;right:8px;width:44px;height:44px;font-size:1.1rem}.iq-bubble.iq-bottom-left{left:8px}.iq-panel{inset:8px 60px 8px 8px;width:auto!important;max-width:calc(100vw - 76px);height:auto!important;max-height:calc(100dvh - 16px);border-radius:var(--iq-radius)}.iq-panel.iq-bottom-left{left:60px;right:8px}.iq-panel.iq-expanded{inset:0!important;width:100vw!important;height:100dvh!important;max-height:100dvh!important;max-width:100vw!important;border-radius:0}.iq-header{padding:6px 12px}.iq-header-title{font-size:.8rem}.iq-messages{padding:6px 10px;gap:6px}.iq-empty-icon{font-size:1.8rem;margin-bottom:4px}.iq-empty p{font-size:.78rem;margin:1px 0}.iq-input-bar{padding:6px 10px}.iq-input-bar input{font-size:16px;padding:6px 10px}.iq-btn-send{width:32px;height:32px}}\n"] }]
|
|
1224
1438
|
}], propDecorators: { chatContainer: [{
|
|
1225
1439
|
type: ViewChild,
|
|
1226
1440
|
args: ['chatContainer']
|
|
1227
1441
|
}], config: [{
|
|
1228
1442
|
type: Input
|
|
1443
|
+
}], onDebugKeydown: [{
|
|
1444
|
+
type: HostListener,
|
|
1445
|
+
args: ['window:keydown', ['$event']]
|
|
1229
1446
|
}] } });
|
|
1230
1447
|
|
|
1231
1448
|
/*
|
|
@@ -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, NgZone } 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 * IMPORTANT: The SSE streaming method runs OUTSIDE Angular Zone to prevent\r\n * change detection storms that freeze the host application's UI.\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class IntelligentChatService {\r\n\r\n private http = inject(HttpClient);\r\n private ngZone = inject(NgZone);\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 * The fetch + reader loop runs OUTSIDE Angular Zone to avoid\r\n * triggering change detection on every microtask (which would\r\n * freeze the host app). Emissions re-enter the zone via ngZone.run().\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 const zone = this.ngZone;\r\n\r\n return new Observable(observer => {\r\n const abortController = new AbortController();\r\n\r\n // Run the entire fetch + SSE loop OUTSIDE Angular Zone\r\n // to prevent change detection storms that freeze the UI\r\n zone.runOutsideAngular(() => {\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 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 zone.run(() => 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 zone.run(() => 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 // Emit progress WITHOUT re-entering Angular zone.\r\n // The component debounces these via requestAnimationFrame.\r\n observer.next({ type: 'progress', step: parsed.step, message: parsed.message });\r\n } else if (eventType === 'result') {\r\n zone.run(() => {\r\n observer.next({ type: 'result', data: parsed });\r\n observer.complete();\r\n });\r\n } else if (eventType === 'error') {\r\n zone.run(() => observer.error(parsed));\r\n }\r\n } catch { /* skip malformed JSON */ }\r\n }\r\n }\r\n if (!observer.closed) {\r\n zone.run(() => observer.complete());\r\n }\r\n }).catch(err => {\r\n if (err.name !== 'AbortError') {\r\n zone.run(() => observer.error(err));\r\n }\r\n });\r\n }); // end runOutsideAngular\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 // ─── Markdown Cache (avoids re-parsing on every CD cycle) ────\r\n private mdCache = new Map<string, SafeHtml>();\r\n // ─── Debounce progress updates to avoid CD storms ────\r\n private pendingPipelineStep: string | null = null;\r\n private rafId: number | null = null;\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 // Debounce progress updates — queue for next animation frame\r\n // to avoid triggering Angular CD on every SSE chunk\r\n this.pendingPipelineStep = event.message || '';\r\n if (this.rafId === null) {\r\n this.rafId = requestAnimationFrame(() => {\r\n this.rafId = null;\r\n if (this.pendingPipelineStep !== null) {\r\n this.pipelineStep = this.pendingPipelineStep;\r\n this.pendingPipelineStep = null;\r\n }\r\n });\r\n }\r\n return;\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\r\n // Return cached result if available (avoids re-parsing on every CD cycle)\r\n const cached = this.mdCache.get(text);\r\n if (cached) return cached;\r\n\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\r\n // Encode spaces in markdown image & link URLs:  and [text](url)\r\n if (preprocessed.length < 100_000) {\r\n preprocessed = preprocessed.replace(/(!?\\[[^\\]]*\\])\\(([^)]+)\\)/g,\r\n (_match, bracket, url) => `${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 const result = this.sanitizer.bypassSecurityTrustHtml(html);\r\n this.mdCache.set(text, result);\r\n return result;\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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"}
|
|
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, NgZone } 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 * IMPORTANT: The SSE streaming method runs OUTSIDE Angular Zone to prevent\r\n * change detection storms that freeze the host application's UI.\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class IntelligentChatService {\r\n\r\n private http = inject(HttpClient);\r\n private ngZone = inject(NgZone);\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 * The fetch + reader loop runs OUTSIDE Angular Zone to avoid\r\n * triggering change detection on every microtask (which would\r\n * freeze the host app). Emissions re-enter the zone via ngZone.run().\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 const zone = this.ngZone;\r\n\r\n return new Observable(observer => {\r\n const abortController = new AbortController();\r\n\r\n // Run the entire fetch + SSE loop OUTSIDE Angular Zone\r\n // to prevent change detection storms that freeze the UI\r\n zone.runOutsideAngular(() => {\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 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 zone.run(() => 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 zone.run(() => 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 // Emit progress WITHOUT re-entering Angular zone.\r\n // The component debounces these via requestAnimationFrame.\r\n observer.next({ type: 'progress', step: parsed.step, message: parsed.message });\r\n } else if (eventType === 'result') {\r\n zone.run(() => {\r\n observer.next({ type: 'result', data: parsed });\r\n observer.complete();\r\n });\r\n } else if (eventType === 'error') {\r\n zone.run(() => observer.error(parsed));\r\n }\r\n } catch { /* skip malformed JSON */ }\r\n }\r\n }\r\n if (!observer.closed) {\r\n zone.run(() => observer.complete());\r\n }\r\n }).catch(err => {\r\n if (err.name !== 'AbortError') {\r\n zone.run(() => observer.error(err));\r\n }\r\n });\r\n }); // end runOutsideAngular\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\"\r\n (touchstart)=\"onTitleTouchStart($event)\"\r\n (touchend)=\"onTitleTouchEnd()\"\r\n (touchcancel)=\"onTitleTouchEnd()\"\r\n >{{ resolvedConfig().title }}</span>\r\n <div class=\"iq-header-actions\">\r\n @if (resolvedConfig().enableDebugMenu) {\r\n <div class=\"iq-debug-menu-wrapper\">\r\n <button class=\"iq-header-btn\" (click)=\"toggleDebugMenu()\" title=\"Opciones\">⋯</button>\r\n @if (showDebugMenu()) {\r\n <div class=\"iq-debug-dropdown\">\r\n <button class=\"iq-debug-option\" (click)=\"downloadConversationLog(); toggleDebugMenu()\">\r\n 📥 Descargar Log\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\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>{{ getQuerySections().length > 1 ? 'Queries Generadas (' + getQuerySections().length + ')' : 'Query Generada' }}</label>\r\n @for (section of getQuerySections(); track $index) {\r\n @if (section.model) {\r\n <div style=\"color: #4ecdc4; font-size: 11px; font-weight: bold; margin-top: 8px;\">📋 {{ section.model }}</div>\r\n }\r\n <pre class=\"iq-query-code\" style=\"margin-top: 4px;\">{{ section.query }}</pre>\r\n }\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 /* ========= Debug Menu ========= */\r\n .iq-debug-menu-wrapper {\r\n position: relative;\r\n }\r\n .iq-debug-dropdown {\r\n position: absolute;\r\n top: 100%;\r\n right: 0;\r\n margin-top: 4px;\r\n min-width: 180px;\r\n background: var(--iq-bg-card);\r\n border: 1px solid var(--iq-border);\r\n border-radius: 8px;\r\n box-shadow: 0 8px 24px rgba(0,0,0,0.4);\r\n z-index: calc(var(--iq-z) + 10);\r\n padding: 4px;\r\n animation: iq-dropdown-in 0.15s ease-out;\r\n }\r\n @keyframes iq-dropdown-in {\r\n from { opacity: 0; transform: translateY(-4px) scale(0.95); }\r\n to { opacity: 1; transform: translateY(0) scale(1); }\r\n }\r\n .iq-debug-option {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n width: 100%;\r\n padding: 8px 12px;\r\n background: none;\r\n border: none;\r\n color: var(--iq-text);\r\n font-size: 0.85rem;\r\n cursor: pointer;\r\n border-radius: 6px;\r\n transition: background 0.15s;\r\n text-align: left;\r\n }\r\n .iq-debug-option:hover {\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 // ─── Markdown Cache (avoids re-parsing on every CD cycle) ────\r\n private mdCache = new Map<string, SafeHtml>();\r\n // ─── Debounce progress updates to avoid CD storms ────\r\n private pendingPipelineStep: string | null = null;\r\n private rafId: number | null = null;\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 // ─── Debug Menu ──────────────────────────────────\r\n showDebugMenu = signal(false);\r\n private titleTouchTimer: any = null;\r\n private shakeHandler: ((e: DeviceMotionEvent) => void) | null = null;\r\n private lastShakeTime = 0;\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 enableDebugMenu: false,\r\n debugKeyCombo: 'ctrl+shift+d'\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 // Setup shake detection for mobile debug log download\r\n this.setupShakeDetection();\r\n }\r\n\r\n ngOnDestroy(): void {\r\n window.removeEventListener('storage', this.storageListener);\r\n this.currentSubscription?.unsubscribe();\r\n this.teardownShakeDetection();\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 enableDebugMenu: this.config.enableDebugMenu ?? false,\r\n debugKeyCombo: this.config.debugKeyCombo || 'ctrl+shift+d'\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 // Debounce progress updates — queue for next animation frame\r\n // to avoid triggering Angular CD on every SSE chunk\r\n this.pendingPipelineStep = event.message || '';\r\n if (this.rafId === null) {\r\n this.rafId = requestAnimationFrame(() => {\r\n this.rafId = null;\r\n if (this.pendingPipelineStep !== null) {\r\n this.pipelineStep = this.pendingPipelineStep;\r\n this.pendingPipelineStep = null;\r\n }\r\n });\r\n }\r\n return;\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 /** Split combined multi-model query into labeled sections */\r\n getQuerySections(): { model: string | null; query: string }[] {\r\n const raw = this.selectedTrace()?.query;\r\n if (!raw) return [];\r\n\r\n // Multi-model queries are separated by \"-- [ModelName]\" headers\r\n const parts = raw.split(/^-- \\[(.+?)\\]$/m);\r\n if (parts.length <= 1) {\r\n // Single query, no model headers\r\n return [{ model: null, query: raw.trim() }];\r\n }\r\n\r\n const sections: { model: string | null; query: string }[] = [];\r\n // parts = [\"\", \"MaquitoFactura\", \"\\nSELECT...\", \"MaquitoPedido\", \"\\nSELECT...\"]\r\n for (let i = 1; i < parts.length; i += 2) {\r\n const modelName = parts[i]?.trim();\r\n const queryText = parts[i + 1]?.trim();\r\n if (modelName && queryText) {\r\n sections.push({ model: modelName, query: queryText });\r\n }\r\n }\r\n return sections.length > 0 ? sections : [{ model: null, query: raw.trim() }];\r\n }\r\n\r\n // ─── Debug Menu & Log Download ────────────────────\r\n\r\n toggleDebugMenu(): void {\r\n this.showDebugMenu.set(!this.showDebugMenu());\r\n }\r\n\r\n /** Secret keyboard shortcut — works even if debug menu is disabled */\r\n @HostListener('window:keydown', ['$event'])\r\n onDebugKeydown(event: KeyboardEvent): void {\r\n const combo = (this.resolvedConfig().debugKeyCombo || 'ctrl+shift+d').toLowerCase();\r\n const parts = combo.split('+');\r\n const needCtrl = parts.includes('ctrl');\r\n const needShift = parts.includes('shift');\r\n const needAlt = parts.includes('alt');\r\n const key = parts.filter(p => !['ctrl', 'shift', 'alt'].includes(p))[0];\r\n if ((!needCtrl || event.ctrlKey) &&\r\n (!needShift || event.shiftKey) &&\r\n (!needAlt || event.altKey) &&\r\n event.key.toLowerCase() === key) {\r\n event.preventDefault();\r\n this.downloadConversationLog();\r\n }\r\n }\r\n\r\n /** Long-press on title (mobile) — 3 seconds */\r\n onTitleTouchStart(event: TouchEvent): void {\r\n this.titleTouchTimer = setTimeout(() => {\r\n this.downloadConversationLog();\r\n }, 3000);\r\n }\r\n\r\n onTitleTouchEnd(): void {\r\n if (this.titleTouchTimer) {\r\n clearTimeout(this.titleTouchTimer);\r\n this.titleTouchTimer = null;\r\n }\r\n }\r\n\r\n /** Setup device shake detection for mobile */\r\n private setupShakeDetection(): void {\r\n if (typeof DeviceMotionEvent === 'undefined') return;\r\n const SHAKE_THRESHOLD = 25;\r\n let lastX = 0, lastY = 0, lastZ = 0;\r\n let lastUpdate = 0;\r\n\r\n this.shakeHandler = (event: DeviceMotionEvent) => {\r\n const acc = event.accelerationIncludingGravity;\r\n if (!acc || acc.x == null || acc.y == null || acc.z == null) return;\r\n const now = Date.now();\r\n if ((now - lastUpdate) < 100) return;\r\n const diffTime = now - lastUpdate;\r\n lastUpdate = now;\r\n const speed = Math.abs(acc.x + acc.y + acc.z - lastX - lastY - lastZ) / diffTime * 10000;\r\n lastX = acc.x; lastY = acc.y; lastZ = acc.z;\r\n if (speed > SHAKE_THRESHOLD && (now - this.lastShakeTime) > 5000) {\r\n this.lastShakeTime = now;\r\n this.downloadConversationLog();\r\n }\r\n };\r\n window.addEventListener('devicemotion', this.shakeHandler);\r\n }\r\n\r\n private teardownShakeDetection(): void {\r\n if (this.shakeHandler) {\r\n window.removeEventListener('devicemotion', this.shakeHandler);\r\n this.shakeHandler = null;\r\n }\r\n }\r\n\r\n /** Generate and download a comprehensive conversation log as .txt */\r\n downloadConversationLog(): void {\r\n const cfg = this.resolvedConfig();\r\n const msgs = this.messages();\r\n const now = new Date();\r\n const pad = (n: number) => n.toString().padStart(2, '0');\r\n const ts = `${now.getFullYear()}-${pad(now.getMonth()+1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;\r\n\r\n let log = '';\r\n log += '═══════════════════════════════════════════════════\\n';\r\n log += ' MAQUITO CHAT — LOG DE CONVERSACIÓN\\n';\r\n log += ` Fecha de descarga: ${ts}\\n`;\r\n log += ` Sistema: ${cfg.systemId}\\n`;\r\n log += ` Session Key: ${this.sessionKey || 'N/A'}\\n`;\r\n log += ` Título: ${cfg.title}\\n`;\r\n log += ` Total Mensajes: ${msgs.length}\\n`;\r\n if (cfg.userName) log += ` Usuario: ${cfg.userName}\\n`;\r\n if (cfg.baseContext) log += ` Contexto Base: ${cfg.baseContext.substring(0, 100)}...\\n`;\r\n log += '═══════════════════════════════════════════════════\\n\\n';\r\n\r\n for (const msg of msgs) {\r\n const t = new Date(msg.timestamp);\r\n const time = `${pad(t.getHours())}:${pad(t.getMinutes())}:${pad(t.getSeconds())}`;\r\n const icon = msg.sender === 'user' ? '👤 USUARIO' : '🤖 BOT';\r\n log += `[${time}] ${icon}:\\n`;\r\n // Strip HTML tags for plain text\r\n const plainText = msg.text.replace(/<[^>]*>/g, '').trim();\r\n log += `${plainText}\\n`;\r\n\r\n // Include trace data if available (bot messages)\r\n if (msg.traceData && msg.sender === 'bot') {\r\n log += ' ┌─── Traza ───────────────────────\\n';\r\n const td = msg.traceData;\r\n if (td.traceId) log += ` │ TraceId: ${td.traceId}\\n`;\r\n if (td.origin) log += ` │ Origen: ${td.origin}\\n`;\r\n if (td.query) log += ` │ Query: ${td.query}\\n`;\r\n if (td.model) log += ` │ Modelo: ${td.model}\\n`;\r\n if (td.rowCount !== undefined) log += ` │ Filas: ${td.rowCount}\\n`;\r\n if (td.explanation) log += ` │ Explicación: ${td.explanation}\\n`;\r\n if (td.durationMs) log += ` │ Duración: ${td.durationMs}ms\\n`;\r\n // Include full raw trace for deep debugging\r\n try {\r\n const raw = JSON.stringify(td, null, 2);\r\n log += ` │ Raw Trace:\\n`;\r\n for (const line of raw.split('\\n')) {\r\n log += ` │ ${line}\\n`;\r\n }\r\n } catch {}\r\n log += ' └─────────────────────────────────\\n';\r\n }\r\n log += '\\n';\r\n }\r\n\r\n log += '═══════════════════════════════════════════════════\\n';\r\n log += ` FIN DEL LOG — ${msgs.length} mensajes\\n`;\r\n log += '═══════════════════════════════════════════════════\\n';\r\n\r\n // Download as .txt file\r\n const blob = new Blob([log], { type: 'text/plain;charset=utf-8' });\r\n const url = URL.createObjectURL(blob);\r\n const a = document.createElement('a');\r\n a.href = url;\r\n a.download = `maquito-chat-log_${now.getFullYear()}${pad(now.getMonth()+1)}${pad(now.getDate())}_${pad(now.getHours())}${pad(now.getMinutes())}.txt`;\r\n document.body.appendChild(a);\r\n a.click();\r\n document.body.removeChild(a);\r\n URL.revokeObjectURL(url);\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\r\n // Return cached result if available (avoids re-parsing on every CD cycle)\r\n const cached = this.mdCache.get(text);\r\n if (cached) return cached;\r\n\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\r\n // Encode spaces in markdown image & link URLs:  and [text](url)\r\n if (preprocessed.length < 100_000) {\r\n preprocessed = preprocessed.replace(/(!?\\[[^\\]]*\\])\\(([^)]+)\\)/g,\r\n (_match, bracket, url) => `${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 const result = this.sanitizer.bypassSecurityTrustHtml(html);\r\n this.mdCache.set(text, result);\r\n return result;\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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"}
|
package/package.json
CHANGED
|
@@ -58,6 +58,10 @@ interface IntelligentChatConfig {
|
|
|
58
58
|
userName?: string;
|
|
59
59
|
/** AI personality instructions (e.g. "Eres Maquito de Tagler Maq...") */
|
|
60
60
|
personality?: string;
|
|
61
|
+
/** Show debug menu (⋯) in the header with "Download Log" option. Default: false */
|
|
62
|
+
enableDebugMenu?: boolean;
|
|
63
|
+
/** Keyboard shortcut to download conversation log (works even if debug menu is hidden). Default: 'ctrl+shift+d' */
|
|
64
|
+
debugKeyCombo?: string;
|
|
61
65
|
}
|
|
62
66
|
/** All customisable plugin colours (map 1-to-1 to --iq-* CSS vars) */
|
|
63
67
|
interface PluginTheme {
|
|
@@ -158,6 +162,10 @@ declare class IntelligentChatPluginComponent implements AfterViewChecked, OnChan
|
|
|
158
162
|
private readonly STORAGE_PREFIX;
|
|
159
163
|
private sessionKey;
|
|
160
164
|
private storageListener;
|
|
165
|
+
showDebugMenu: _angular_core.WritableSignal<boolean>;
|
|
166
|
+
private titleTouchTimer;
|
|
167
|
+
private shakeHandler;
|
|
168
|
+
private lastShakeTime;
|
|
161
169
|
/** Resolved config with defaults applied */
|
|
162
170
|
private sanitizer;
|
|
163
171
|
resolvedConfig: _angular_core.WritableSignal<Required<IntelligentChatConfig>>;
|
|
@@ -180,6 +188,22 @@ declare class IntelligentChatPluginComponent implements AfterViewChecked, OnChan
|
|
|
180
188
|
clearChat(): void;
|
|
181
189
|
showTrace(msg: ChatMessage): void;
|
|
182
190
|
closeTrace(): void;
|
|
191
|
+
/** Split combined multi-model query into labeled sections */
|
|
192
|
+
getQuerySections(): {
|
|
193
|
+
model: string | null;
|
|
194
|
+
query: string;
|
|
195
|
+
}[];
|
|
196
|
+
toggleDebugMenu(): void;
|
|
197
|
+
/** Secret keyboard shortcut — works even if debug menu is disabled */
|
|
198
|
+
onDebugKeydown(event: KeyboardEvent): void;
|
|
199
|
+
/** Long-press on title (mobile) — 3 seconds */
|
|
200
|
+
onTitleTouchStart(event: TouchEvent): void;
|
|
201
|
+
onTitleTouchEnd(): void;
|
|
202
|
+
/** Setup device shake detection for mobile */
|
|
203
|
+
private setupShakeDetection;
|
|
204
|
+
private teardownShakeDetection;
|
|
205
|
+
/** Generate and download a comprehensive conversation log as .txt */
|
|
206
|
+
downloadConversationLog(): void;
|
|
183
207
|
openLinkModal(url: string): void;
|
|
184
208
|
closeLinkModal(): void;
|
|
185
209
|
onIframeLoaded(): void;
|