@vanira/sdk 0.0.1 → 0.0.2

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.
@@ -50,7 +50,11 @@ export declare class WebRTCClient {
50
50
  * Silently update the AI's context with what the user is currently viewing.
51
51
  * Does NOT interrupt the AI's current speech.
52
52
  */
53
- sendSilentContext(context: string): void;
53
+ sendContextUpdate(context: Record<string, any>): void;
54
+ /**
55
+ * Trigger a client-side action — forces the AI to react to a UI event.
56
+ */
57
+ sendActionTrigger(actionName: string, data?: Record<string, any>): void;
54
58
  /**
55
59
  * Trigger a client-side interrupt — cuts AI audio and forces it to react to a UI event.
56
60
  */
@@ -14,6 +14,7 @@ export declare const icons: {
14
14
  minimize2: string;
15
15
  user: string;
16
16
  keyboard: string;
17
+ voice_orb: string;
17
18
  };
18
19
  export declare const industryIcons: Record<string, string>;
19
20
  export declare const widgetIcons: Record<string, string>;
@@ -1 +1 @@
1
- export declare const keyframes = "\n @keyframes fadeInScale {\n from { opacity: 0; transform: scale(0.8); }\n to { opacity: 1; transform: scale(1); }\n }\n\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n @keyframes wave {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-4px); }\n }\n\n @keyframes wave-rotate-1 {\n 0% { transform: rotate(0deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n 25% { transform: rotate(90deg) scale(1.02); border-radius: 30% 60% 70% 40% / 50% 60% 30% 60%; }\n 50% { transform: rotate(180deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n 75% { transform: rotate(270deg) scale(0.98); border-radius: 40% 60% 70% 30% / 40% 40% 60% 50%; }\n 100% { transform: rotate(360deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n }\n\n @keyframes wave-rotate-2 {\n 0% { transform: rotate(60deg) scale(1.02); border-radius: 40% 60% 60% 40% / 60% 40% 60% 40%; }\n 33% { transform: rotate(180deg) scale(0.98); border-radius: 60% 40% 40% 60% / 40% 60% 40% 60%; }\n 66% { transform: rotate(300deg) scale(1.02); border-radius: 50% 50% 40% 60% / 60% 40% 50% 50%; }\n 100% { transform: rotate(420deg) scale(1.02); border-radius: 40% 60% 60% 40% / 60% 40% 60% 40%; }\n }\n\n @keyframes wave-rotate-3 {\n 0% { transform: rotate(120deg) scale(1); border-radius: 50% 50% 50% 50%; }\n 50% { transform: rotate(300deg) scale(1.05); border-radius: 40% 60% 50% 50% / 50% 50% 60% 40%; }\n 100% { transform: rotate(480deg) scale(1); border-radius: 50% 50% 50% 50%; }\n }\n\n @keyframes clickBounce {\n 0% { transform: scale(1); }\n 25% { transform: scale(0.9) rotate(-5deg); }\n 50% { transform: scale(1.15) rotate(5deg); }\n 75% { transform: scale(0.95) rotate(-2deg); }\n 100% { transform: scale(1) rotate(0deg); }\n }\n\n @keyframes pulseGlow {\n 0%, 100% { box-shadow: 0 4px 16px rgba(239, 68, 68, 0.4); }\n 50% { box-shadow: 0 4px 24px rgba(239, 68, 68, 0.6), 0 0 32px rgba(239, 68, 68, 0.3); }\n }\n\n @keyframes typingBounce {\n 0%, 80%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-6px); }\n }\n\n @keyframes floatOrb {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-10px); }\n }\n\n @keyframes pulseGlowIdle {\n 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.4; }\n 50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.2; }\n }\n\n @keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n";
1
+ export declare const keyframes = "\n @keyframes fadeInScale {\n from { opacity: 0; transform: scale(0.8); }\n to { opacity: 1; transform: scale(1); }\n }\n\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n @keyframes wave {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-4px); }\n }\n\n @keyframes wave-rotate-1 {\n 0% { transform: rotate(0deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n 25% { transform: rotate(90deg) scale(1.02); border-radius: 30% 60% 70% 40% / 50% 60% 30% 60%; }\n 50% { transform: rotate(180deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n 75% { transform: rotate(270deg) scale(0.98); border-radius: 40% 60% 70% 30% / 40% 40% 60% 50%; }\n 100% { transform: rotate(360deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n }\n\n @keyframes wave-rotate-2 {\n 0% { transform: rotate(60deg) scale(1.02); border-radius: 40% 60% 60% 40% / 60% 40% 60% 40%; }\n 33% { transform: rotate(180deg) scale(0.98); border-radius: 60% 40% 40% 60% / 40% 60% 40% 60%; }\n 66% { transform: rotate(300deg) scale(1.02); border-radius: 50% 50% 40% 60% / 60% 40% 50% 50%; }\n 100% { transform: rotate(420deg) scale(1.02); border-radius: 40% 60% 60% 40% / 60% 40% 60% 40%; }\n }\n\n @keyframes wave-rotate-3 {\n 0% { transform: rotate(120deg) scale(1); border-radius: 50% 50% 50% 50%; }\n 50% { transform: rotate(300deg) scale(1.05); border-radius: 40% 60% 50% 50% / 50% 50% 60% 40%; }\n 100% { transform: rotate(480deg) scale(1); border-radius: 50% 50% 50% 50%; }\n }\n\n @keyframes clickBounce {\n 0% { transform: scale(1); }\n 25% { transform: scale(0.9) rotate(-5deg); }\n 50% { transform: scale(1.15) rotate(5deg); }\n 75% { transform: scale(0.95) rotate(-2deg); }\n 100% { transform: scale(1) rotate(0deg); }\n }\n\n @keyframes pulseGlow {\n 0%, 100% { box-shadow: 0 4px 16px rgba(239, 68, 68, 0.4); }\n 50% { box-shadow: 0 4px 24px rgba(239, 68, 68, 0.6), 0 0 32px rgba(239, 68, 68, 0.3); }\n }\n\n @keyframes typingBounce {\n 0%, 80%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-6px); }\n }\n\n @keyframes floatOrb {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-10px); }\n }\n\n @keyframes pulseGlowIdle {\n 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.4; }\n 50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.2; }\n }\n\n @keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n @keyframes voice-bars-orb {\n 0%, 100% { transform: scaleY(1); opacity: 0.7; }\n 50% { transform: scaleY(1.8); opacity: 1; }\n }\n";
@@ -1 +1 @@
1
- export declare const widgetStyles = "\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n box-sizing: border-box;\n \n /* Default Theme Variables */\n --primary: #6366f1;\n --primary-hover: #4f46e5;\n --bg: #ffffff;\n --text: #1f2937;\n --text-muted: #6b7280;\n --border: #e5e7eb;\n --shadow: 0 10px 40px rgba(0, 0, 0, 0.1);\n --shadow-lg: 0 20px 60px rgba(0, 0, 0, 0.15);\n }\n\n :host * {\n box-sizing: border-box;\n }\n\n \n @keyframes fadeInScale {\n from { opacity: 0; transform: scale(0.8); }\n to { opacity: 1; transform: scale(1); }\n }\n\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n @keyframes wave {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-4px); }\n }\n\n @keyframes wave-rotate-1 {\n 0% { transform: rotate(0deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n 25% { transform: rotate(90deg) scale(1.02); border-radius: 30% 60% 70% 40% / 50% 60% 30% 60%; }\n 50% { transform: rotate(180deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n 75% { transform: rotate(270deg) scale(0.98); border-radius: 40% 60% 70% 30% / 40% 40% 60% 50%; }\n 100% { transform: rotate(360deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n }\n\n @keyframes wave-rotate-2 {\n 0% { transform: rotate(60deg) scale(1.02); border-radius: 40% 60% 60% 40% / 60% 40% 60% 40%; }\n 33% { transform: rotate(180deg) scale(0.98); border-radius: 60% 40% 40% 60% / 40% 60% 40% 60%; }\n 66% { transform: rotate(300deg) scale(1.02); border-radius: 50% 50% 40% 60% / 60% 40% 50% 50%; }\n 100% { transform: rotate(420deg) scale(1.02); border-radius: 40% 60% 60% 40% / 60% 40% 60% 40%; }\n }\n\n @keyframes wave-rotate-3 {\n 0% { transform: rotate(120deg) scale(1); border-radius: 50% 50% 50% 50%; }\n 50% { transform: rotate(300deg) scale(1.05); border-radius: 40% 60% 50% 50% / 50% 50% 60% 40%; }\n 100% { transform: rotate(480deg) scale(1); border-radius: 50% 50% 50% 50%; }\n }\n\n @keyframes clickBounce {\n 0% { transform: scale(1); }\n 25% { transform: scale(0.9) rotate(-5deg); }\n 50% { transform: scale(1.15) rotate(5deg); }\n 75% { transform: scale(0.95) rotate(-2deg); }\n 100% { transform: scale(1) rotate(0deg); }\n }\n\n @keyframes pulseGlow {\n 0%, 100% { box-shadow: 0 4px 16px rgba(239, 68, 68, 0.4); }\n 50% { box-shadow: 0 4px 24px rgba(239, 68, 68, 0.6), 0 0 32px rgba(239, 68, 68, 0.3); }\n }\n\n @keyframes typingBounce {\n 0%, 80%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-6px); }\n }\n\n @keyframes floatOrb {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-10px); }\n }\n\n @keyframes pulseGlowIdle {\n 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.4; }\n 50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.2; }\n }\n\n @keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n\n .widget-fab {\n position: fixed;\n z-index: 9999;\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--primary) 0%, var(--primary-hover) 100%);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: var(--shadow);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n animation: fadeInScale 0.4s ease-out;\n }\n\n .widget-fab:hover {\n transform: scale(1.1);\n box-shadow: var(--shadow-lg);\n }\n\n .widget-fab:active {\n transform: scale(0.95);\n }\n\n .widget-fab svg {\n width: 28px;\n height: 28px;\n color: white;\n }\n\n .widget-panel {\n position: fixed;\n z-index: 10000; /* Higher than FAB */\n background: rgba(255, 255, 255, 0.98);\n backdrop-filter: blur(20px);\n -webkit-backdrop-filter: blur(20px);\n border: 1px solid #d1d5db; /* Solid light gray border for better differentiation */\n border-radius: 28px;\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.5s cubic-bezier(0.19, 1, 0.22, 1);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n \n /* Default Dimensions */\n width: 400px;\n height: 600px;\n max-height: 90vh;\n max-width: 95vw;\n }\n\n .widget-panel.maximized {\n width: 90vw !important;\n height: 90vh !important;\n top: 5vh !important;\n left: 5vw !important;\n right: 5vw !important;\n bottom: 5vh !important;\n margin: auto;\n }\n\n .widget-panel.maximized {\n width: 800px;\n max-width: calc(100vw - 40px);\n height: 80vh;\n }\n\n .widget-body {\n padding: 0;\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n }\n\n .widget-panel.hidden {\n opacity: 0;\n pointer-events: none;\n transform: translateY(20px) scale(0.95);\n }\n/* ... rest of the content is redundant if I use replace or overwrite, but I will overwrite to include everything properly */\n .widget-header {\n background: #1f2937;\n color: white;\n padding: 14px 20px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n\n .widget-title {\n font-size: 18px;\n font-weight: 600;\n margin: 0;\n letter-spacing: 0.3px;\n }\n\n .close-btn {\n background: rgba(255, 255, 255, 0.15);\n border: none;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s;\n backdrop-filter: blur(10px);\n }\n\n .close-btn:hover {\n background: rgba(255, 255, 255, 0.25);\n transform: scale(1.1);\n }\n\n .close-btn.maximize-btn {\n display: flex;\n }\n\n .close-btn svg {\n width: 18px;\n height: 18px;\n color: white;\n flex-shrink: 0;\n }\n\n .widget-body {\n padding: 0;\n flex: 1;\n display: flex;\n flex-direction: column;\n }\n\n .status-indicator {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: #f9fafb;\n border-radius: 12px;\n margin-bottom: 20px;\n }\n\n .status-dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #10b981;\n animation: pulse 2s infinite;\n }\n\n .status-text {\n font-size: 14px;\n color: var(--text-muted);\n margin: 0;\n }\n\n .controls {\n display: flex;\n gap: 12px;\n justify-content: center;\n }\n\n .control-btn {\n flex: 1;\n padding: 14px 20px;\n border: none;\n border-radius: 12px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n }\n\n .control-btn svg {\n width: 18px;\n height: 18px;\n }\n\n .control-btn.primary {\n background: #1f2937;\n color: white;\n }\n\n .control-btn.primary:hover {\n background: #374151;\n }\n\n .control-btn.danger {\n background: #ef4444;\n color: white;\n }\n\n .control-btn.danger:hover {\n background: #dc2626;\n }\n\n .voice-mode-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding-bottom: 0;\n }\n\n .central-orb-container {\n position: relative;\n width: 120px;\n height: 120px;\n margin-bottom: 32px;\n cursor: pointer;\n }\n\n .central-orb {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n position: relative;\n z-index: 10;\n box-shadow: 0 10px 30px rgba(99, 102, 241, 0.3);\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .central-orb.active {\n animation: pulse 2s infinite;\n }\n \n .central-orb.idle {\n animation: floatOrb 4s ease-in-out infinite;\n cursor: pointer;\n }\n\n .central-orb.idle:hover {\n transform: scale(1.05);\n }\n\n .central-orb-glow {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 140%;\n height: 140%;\n background: radial-gradient(circle, rgba(99, 102, 241, 0.2) 0%, transparent 70%);\n animation: pulseGlowIdle 4s ease-in-out infinite;\n z-index: -1;\n pointer-events: none;\n }\n\n .central-orb svg {\n width: 24px;\n height: 24px;\n }\n\n .voice-status-text {\n font-size: 20px;\n font-weight: 600;\n color: var(--text);\n margin-bottom: 8px;\n text-align: center;\n }\n\n .voice-status-subtext {\n font-size: 14px;\n color: var(--text-muted);\n text-align: center;\n }\n\n /* Chat Mode Styles */\n .chat-messages {\n flex: 1;\n min-height: 0; /* Crucial for scrolling in flex column */\n overflow-y: auto;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n background: #f9fafb; \n \n /* Scrollbar Styling */\n scrollbar-width: thin;\n scrollbar-color: rgba(156, 163, 175, 0.5) transparent;\n }\n\n .chat-messages::-webkit-scrollbar {\n width: 6px;\n }\n\n .chat-messages::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .chat-messages::-webkit-scrollbar-thumb {\n background-color: rgba(156, 163, 175, 0.5);\n border-radius: 3px;\n }\n\n .chat-messages::-webkit-scrollbar-thumb:hover {\n background-color: rgba(107, 114, 128, 0.8);\n }\n\n .chat-message {\n max-width: 85%;\n padding: 12px 16px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n }\n\n .chat-message.user {\n align-self: flex-end;\n background: #000000;\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .chat-message.assistant {\n align-self: flex-start;\n background: #ffffff;\n border: 1px solid #e5e7eb;\n color: var(--text);\n border-bottom-left-radius: 4px;\n box-shadow: 0 1px 2px rgba(0,0,0,0.05);\n }\n\n .chat-input-area {\n padding: 20px;\n border-top: 1px solid rgba(0, 0, 0, 0.05);\n display: flex;\n gap: 10px;\n align-items: center;\n background: white;\n z-index: 30;\n position: relative;\n border-bottom-left-radius: 28px;\n border-bottom-right-radius: 28px;\n }\n\n .chat-input {\n flex: 1;\n padding: 14px 20px;\n border: 1px solid #e5e7eb;\n border-radius: 28px;\n font-size: 15px;\n outline: none;\n transition: all 0.3s;\n background: #f3f4f6;\n color: #1f2937;\n }\n\n .chat-input:focus {\n border-color: var(--primary);\n background: white;\n box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.1);\n }\n\n .chat-send-btn {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: var(--primary);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);\n flex-shrink: 0;\n }\n\n .chat-send-btn:hover {\n transform: scale(1.05) rotate(-10deg);\n background: var(--primary-hover);\n box-shadow: 0 6px 16px rgba(99, 102, 241, 0.4);\n }\n\n .chat-send-btn:active {\n transform: scale(0.95);\n }\n\n .chat-send-btn svg {\n width: 22px;\n height: 22px;\n color: white;\n margin-left: 2px;\n }\n\n /* Avatar Container */\n .avatar-container {\n background: transparent;\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n overflow: hidden;\n }\n \n /* Avatar Video */\n .avatar-video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n /* Voice Button (Simple) in Chat */\n .voice-btn-simple {\n position: relative;\n width: 44px; /* Matching send-btn size for symmetry */\n height: 44px;\n border-radius: 50%;\n border: 1.5px solid #e5e7eb;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.3s;\n overflow: visible;\n background: white;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n }\n\n .voice-btn-simple:hover {\n transform: scale(1.05);\n background: #f9fafb;\n border-color: #9ca3af;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);\n }\n\n .voice-btn-simple:active {\n animation: clickBounce 0.4s ease-out;\n }\n\n .voice-btn-icon {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #4b5563;\n }\n\n .voice-btn-icon svg {\n width: 20px;\n height: 20px;\n stroke-width: 2px;\n }\n\n /* Utility Classes */\n .absolute { position: absolute; }\n .relative { position: relative; }\n .rounded-full { border-radius: 9999px; }\n .flex { display: flex; }\n .items-center { align-items: center; }\n .justify-center { justify-content: center; }\n .w-full { width: 100%; }\n .h-full { height: 100%; }\n .z-50 { z-index: 50; }\n\n .branding-footer {\n display: flex;\n justify-content: center;\n padding: 4px 0 8px 0;\n background-color: #f9fafb;\n font-size: 10px;\n color: #9ca3af;\n font-weight: 500;\n letter-spacing: 0.025em;\n }\n\n .branding-footer b {\n color: #3b82f6;\n font-weight: 700;\n margin-left: 4px;\n }\n\n @media (max-width: 640px) {\n .widget-panel {\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n border-radius: 0 !important;\n margin: 0 !important;\n }\n\n .widget-fab {\n width: 56px;\n height: 56px;\n bottom: 16px !important;\n right: 16px !important;\n }\n\n :host(.vanira-panel-open) .widget-fab {\n display: none !important;\n }\n\n .close-btn.maximize-btn {\n display: none !important;\n }\n\n .widget-header {\n padding: 12px 16px;\n }\n\n .widget-title {\n font-size: 16px;\n }\n\n .chat-input-area {\n padding: 12px;\n padding-bottom: env(safe-area-inset-bottom, 12px);\n }\n }\n";
1
+ export declare const widgetStyles = "\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n box-sizing: border-box;\n \n /* Default Theme Variables */\n --primary: #6366f1;\n --primary-hover: #4f46e5;\n --bg: #ffffff;\n --text: #1f2937;\n --text-muted: #6b7280;\n --border: #e5e7eb;\n --shadow: 0 10px 40px rgba(0, 0, 0, 0.1);\n --shadow-lg: 0 20px 60px rgba(0, 0, 0, 0.15);\n }\n\n :host * {\n box-sizing: border-box;\n }\n\n \n @keyframes fadeInScale {\n from { opacity: 0; transform: scale(0.8); }\n to { opacity: 1; transform: scale(1); }\n }\n\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n @keyframes wave {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-4px); }\n }\n\n @keyframes wave-rotate-1 {\n 0% { transform: rotate(0deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n 25% { transform: rotate(90deg) scale(1.02); border-radius: 30% 60% 70% 40% / 50% 60% 30% 60%; }\n 50% { transform: rotate(180deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n 75% { transform: rotate(270deg) scale(0.98); border-radius: 40% 60% 70% 30% / 40% 40% 60% 50%; }\n 100% { transform: rotate(360deg) scale(1); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }\n }\n\n @keyframes wave-rotate-2 {\n 0% { transform: rotate(60deg) scale(1.02); border-radius: 40% 60% 60% 40% / 60% 40% 60% 40%; }\n 33% { transform: rotate(180deg) scale(0.98); border-radius: 60% 40% 40% 60% / 40% 60% 40% 60%; }\n 66% { transform: rotate(300deg) scale(1.02); border-radius: 50% 50% 40% 60% / 60% 40% 50% 50%; }\n 100% { transform: rotate(420deg) scale(1.02); border-radius: 40% 60% 60% 40% / 60% 40% 60% 40%; }\n }\n\n @keyframes wave-rotate-3 {\n 0% { transform: rotate(120deg) scale(1); border-radius: 50% 50% 50% 50%; }\n 50% { transform: rotate(300deg) scale(1.05); border-radius: 40% 60% 50% 50% / 50% 50% 60% 40%; }\n 100% { transform: rotate(480deg) scale(1); border-radius: 50% 50% 50% 50%; }\n }\n\n @keyframes clickBounce {\n 0% { transform: scale(1); }\n 25% { transform: scale(0.9) rotate(-5deg); }\n 50% { transform: scale(1.15) rotate(5deg); }\n 75% { transform: scale(0.95) rotate(-2deg); }\n 100% { transform: scale(1) rotate(0deg); }\n }\n\n @keyframes pulseGlow {\n 0%, 100% { box-shadow: 0 4px 16px rgba(239, 68, 68, 0.4); }\n 50% { box-shadow: 0 4px 24px rgba(239, 68, 68, 0.6), 0 0 32px rgba(239, 68, 68, 0.3); }\n }\n\n @keyframes typingBounce {\n 0%, 80%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-6px); }\n }\n\n @keyframes floatOrb {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-10px); }\n }\n\n @keyframes pulseGlowIdle {\n 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.4; }\n 50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.2; }\n }\n\n @keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n @keyframes voice-bars-orb {\n 0%, 100% { transform: scaleY(1); opacity: 0.7; }\n 50% { transform: scaleY(1.8); opacity: 1; }\n }\n\n\n .widget-fab {\n position: fixed;\n z-index: 9999;\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--primary) 0%, var(--primary-hover) 100%);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: var(--shadow);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n animation: fadeInScale 0.4s ease-out;\n }\n\n .widget-fab:hover {\n transform: scale(1.1);\n box-shadow: var(--shadow-lg);\n }\n\n .widget-fab:active {\n transform: scale(0.95);\n }\n\n .widget-fab svg {\n width: 28px;\n height: 28px;\n color: white;\n }\n\n .widget-panel {\n position: fixed;\n z-index: 10000; /* Higher than FAB */\n background: rgba(255, 255, 255, 0.98);\n backdrop-filter: blur(20px);\n -webkit-backdrop-filter: blur(20px);\n border: 1px solid #d1d5db; /* Solid light gray border for better differentiation */\n border-radius: 28px;\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.5s cubic-bezier(0.19, 1, 0.22, 1);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n \n /* Default Dimensions */\n width: 400px;\n height: 600px;\n max-height: 90vh;\n max-width: 95vw;\n }\n\n .widget-panel.maximized {\n width: 90vw !important;\n height: 90vh !important;\n top: 5vh !important;\n left: 5vw !important;\n right: 5vw !important;\n bottom: 5vh !important;\n margin: auto;\n }\n\n .widget-panel.maximized {\n width: 800px;\n max-width: calc(100vw - 40px);\n height: 80vh;\n }\n\n .widget-body {\n padding: 0;\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n }\n\n .widget-panel.hidden {\n opacity: 0;\n pointer-events: none;\n transform: translateY(20px) scale(0.95);\n }\n/* ... rest of the content is redundant if I use replace or overwrite, but I will overwrite to include everything properly */\n .widget-header {\n background: #1f2937;\n color: white;\n padding: 14px 20px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n\n .widget-title {\n font-size: 18px;\n font-weight: 600;\n margin: 0;\n letter-spacing: 0.3px;\n }\n\n .close-btn {\n background: rgba(255, 255, 255, 0.15);\n border: none;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s;\n backdrop-filter: blur(10px);\n }\n\n .close-btn:hover {\n background: rgba(255, 255, 255, 0.25);\n transform: scale(1.1);\n }\n\n .close-btn.maximize-btn {\n display: flex;\n }\n\n .close-btn svg {\n width: 18px;\n height: 18px;\n color: white;\n flex-shrink: 0;\n }\n\n .widget-body {\n padding: 0;\n flex: 1;\n display: flex;\n flex-direction: column;\n }\n\n .status-indicator {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: #f9fafb;\n border-radius: 12px;\n margin-bottom: 20px;\n }\n\n .status-dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #10b981;\n animation: pulse 2s infinite;\n }\n\n .status-text {\n font-size: 14px;\n color: var(--text-muted);\n margin: 0;\n }\n\n .controls {\n display: flex;\n gap: 12px;\n justify-content: center;\n }\n\n .control-btn {\n flex: 1;\n padding: 14px 20px;\n border: none;\n border-radius: 12px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n }\n\n .control-btn svg {\n width: 18px;\n height: 18px;\n }\n\n .control-btn.primary {\n background: #1f2937;\n color: white;\n }\n\n .control-btn.primary:hover {\n background: #374151;\n }\n\n .control-btn.danger {\n background: #ef4444;\n color: white;\n }\n\n .control-btn.danger:hover {\n background: #dc2626;\n }\n\n .voice-mode-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding-bottom: 0;\n }\n\n .central-orb-container {\n position: relative;\n width: 120px;\n height: 120px;\n margin-bottom: 32px;\n cursor: pointer;\n }\n\n .central-orb {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n position: relative;\n z-index: 10;\n box-shadow: 0 10px 30px rgba(99, 102, 241, 0.3);\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .central-orb.active {\n animation: pulse 2s infinite;\n }\n \n .central-orb.idle {\n animation: floatOrb 4s ease-in-out infinite;\n cursor: pointer;\n }\n\n .central-orb.idle:hover {\n transform: scale(1.05);\n }\n\n .central-orb-glow {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 140%;\n height: 140%;\n background: radial-gradient(circle, rgba(99, 102, 241, 0.2) 0%, transparent 70%);\n animation: pulseGlowIdle 4s ease-in-out infinite;\n z-index: -1;\n pointer-events: none;\n }\n\n .central-orb svg {\n width: 24px;\n height: 24px;\n }\n\n .voice-status-text {\n font-size: 20px;\n font-weight: 600;\n color: var(--text);\n margin-bottom: 8px;\n text-align: center;\n }\n\n .voice-status-subtext {\n font-size: 14px;\n color: var(--text-muted);\n text-align: center;\n }\n\n /* Chat Mode Styles */\n .chat-messages {\n flex: 1;\n min-height: 0; /* Crucial for scrolling in flex column */\n overflow-y: auto;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n background: #f9fafb; \n \n /* Scrollbar Styling */\n scrollbar-width: thin;\n scrollbar-color: rgba(156, 163, 175, 0.5) transparent;\n }\n\n .chat-messages::-webkit-scrollbar {\n width: 6px;\n }\n\n .chat-messages::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .chat-messages::-webkit-scrollbar-thumb {\n background-color: rgba(156, 163, 175, 0.5);\n border-radius: 3px;\n }\n\n .chat-messages::-webkit-scrollbar-thumb:hover {\n background-color: rgba(107, 114, 128, 0.8);\n }\n\n .chat-message {\n max-width: 85%;\n padding: 12px 16px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n }\n\n .chat-message.user {\n align-self: flex-end;\n background: #000000;\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .chat-message.assistant {\n align-self: flex-start;\n background: #ffffff;\n border: 1px solid #e5e7eb;\n color: var(--text);\n border-bottom-left-radius: 4px;\n box-shadow: 0 1px 2px rgba(0,0,0,0.05);\n }\n\n .chat-input-area {\n padding: 20px;\n border-top: 1px solid rgba(0, 0, 0, 0.05);\n display: flex;\n gap: 10px;\n align-items: center;\n background: white;\n z-index: 30;\n position: relative;\n border-bottom-left-radius: 28px;\n border-bottom-right-radius: 28px;\n }\n\n .chat-input {\n flex: 1;\n padding: 14px 20px;\n border: 1px solid #e5e7eb;\n border-radius: 28px;\n font-size: 15px;\n outline: none;\n transition: all 0.3s;\n background: #f3f4f6;\n color: #1f2937;\n }\n\n .chat-input:focus {\n border-color: var(--primary);\n background: white;\n box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.1);\n }\n\n .chat-send-btn {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: var(--primary);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);\n flex-shrink: 0;\n }\n\n .chat-send-btn:hover {\n transform: scale(1.05) rotate(-10deg);\n background: var(--primary-hover);\n box-shadow: 0 6px 16px rgba(99, 102, 241, 0.4);\n }\n\n .chat-send-btn:active {\n transform: scale(0.95);\n }\n\n .chat-send-btn svg {\n width: 22px;\n height: 22px;\n color: white;\n margin-left: 2px;\n }\n\n /* Avatar Container */\n .avatar-container {\n background: transparent;\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n overflow: hidden;\n }\n \n /* Avatar Video */\n .avatar-video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n /* Voice Button (Simple) in Chat */\n .voice-btn-simple {\n position: relative;\n width: 44px; /* Matching send-btn size for symmetry */\n height: 44px;\n border-radius: 50%;\n border: 1.5px solid #e5e7eb;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.3s;\n overflow: visible;\n background: white;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n }\n\n .voice-btn-simple:hover {\n transform: scale(1.05);\n background: #f9fafb;\n border-color: #9ca3af;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);\n }\n\n .voice-btn-simple:active {\n animation: clickBounce 0.4s ease-out;\n }\n\n .voice-btn-icon {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #4b5563;\n }\n\n .voice-btn-icon svg {\n width: 20px;\n height: 20px;\n stroke-width: 2px;\n }\n\n /* Utility Classes */\n .absolute { position: absolute; }\n .relative { position: relative; }\n .rounded-full { border-radius: 9999px; }\n .flex { display: flex; }\n .items-center { align-items: center; }\n .justify-center { justify-content: center; }\n .w-full { width: 100%; }\n .h-full { height: 100%; }\n .z-50 { z-index: 50; }\n\n .branding-footer {\n display: flex;\n justify-content: center;\n padding: 4px 0 8px 0;\n background-color: #f9fafb;\n font-size: 10px;\n color: #9ca3af;\n font-weight: 500;\n letter-spacing: 0.025em;\n }\n\n .branding-footer b {\n color: #3b82f6;\n font-weight: 700;\n margin-left: 4px;\n }\n\n @media (max-width: 640px) {\n .widget-panel {\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n border-radius: 0 !important;\n margin: 0 !important;\n }\n\n .widget-fab {\n width: 56px;\n height: 56px;\n bottom: 16px !important;\n right: 16px !important;\n }\n\n :host(.vanira-panel-open) .widget-fab {\n display: none !important;\n }\n\n .close-btn.maximize-btn {\n display: none !important;\n }\n\n .widget-header {\n padding: 12px 16px;\n }\n\n .widget-title {\n font-size: 16px;\n }\n\n .chat-input-area {\n padding: 12px;\n padding-bottom: env(safe-area-inset-bottom, 12px);\n }\n }\n";
@@ -1,11 +1,11 @@
1
- (function(f,y){typeof exports=="object"&&typeof module<"u"?y(exports):typeof define=="function"&&define.amd?define(["exports"],y):(f=typeof globalThis<"u"?globalThis:f||self,y(f.VaniraAI={}))})(this,function(f){"use strict";var pe=Object.defineProperty;var we=(f,y,B)=>y in f?pe(f,y,{enumerable:!0,configurable:!0,writable:!0,value:B}):f[y]=B;var n=(f,y,B)=>we(f,typeof y!="symbol"?y+"":y,B);var y=typeof document<"u"?document.currentScript:null;class B{constructor(e){n(this,"serverUrl");n(this,"agentId");n(this,"callId");n(this,"onConnected");n(this,"onDisconnected");n(this,"onError");n(this,"onTranscription");n(this,"onRemoteTrack");n(this,"onClientToolCall");n(this,"pc",null);n(this,"dataChannel",null);n(this,"audioElement",null);n(this,"connected",!1);n(this,"iceServers");n(this,"token");if(!e.serverUrl)throw new Error("serverUrl is required");if(!e.agentId)throw new Error("agentId is required");this.serverUrl=e.serverUrl.replace(/\/$/,""),this.agentId=e.agentId,this.callId=e.callId||this.generateCallId(),this.iceServers=e.iceServers,this.token=e.token,this.onConnected=e.onConnected||(()=>{}),this.onDisconnected=e.onDisconnected||(()=>{}),this.onError=e.onError||(t=>console.error("[WebRTC]",t)),this.onTranscription=e.onTranscription||(()=>{}),this.onRemoteTrack=e.onRemoteTrack||(()=>{}),this.onClientToolCall=e.onClientToolCall||(()=>{})}async connect(){console.log("🔵 [WebRTC] Starting connection...");try{if(!this.iceServers&&this.token)try{this.iceServers=await B.fetchIceServers(this.token)}catch(a){console.warn("⚠️ [WebRTC] Failed to fetch ICE servers:",a)}this.pc=new RTCPeerConnection({iceServers:this.iceServers||[{urls:"stun:global.relay.metered.ca:80"},{urls:["turns:global.relay.metered.ca:443?transport=tcp","turn:global.relay.metered.ca:80?transport=tcp","turn:global.relay.metered.ca:443?transport=tcp"],username:"fa97658be3343d21da3b65e6",credential:"HXHDoqeHbvZrmCuf"}]}),this.pc.addTransceiver("video",{direction:"recvonly"});const e=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,sampleRate:{ideal:16e3},channelCount:1}});if(console.log("🎤 [WebRTC] Microphone access granted"),!this.pc){console.log("[WebRTC] Connection aborted: peer connection closed during setup"),e.getTracks().forEach(a=>a.stop());return}if(e.getTracks().forEach(a=>{var r;(r=this.pc)==null||r.addTrack(a,e)}),!this.pc)throw new Error("RTCPeerConnection was closed unexpectedly");this.dataChannel=this.pc.createDataChannel("control"),this.dataChannel.onopen=()=>console.log("📡 [WebRTC] DataChannel opened"),this.dataChannel.onmessage=a=>{if(typeof a.data=="string")try{this.handleControlEvent(JSON.parse(a.data))}catch{console.warn("[WebRTC] Failed to parse message:",a.data)}else if(a.data instanceof ArrayBuffer)try{const r=new TextDecoder().decode(a.data);try{const l=JSON.parse(r);l&&typeof l=="object"&&l.event==="client_tool_call"?(console.log("[VaniraAI] Safely decoding binary tool_call to JSON:",l),this.handleControlEvent(l)):console.log("[VaniraAI] Decoded JSON from binary (inspect only):",l)}catch{console.log("[VaniraAI] Decoded String from binary:",r)}}catch{console.log("[VaniraAI] Received binary data:",a.data.byteLength,"bytes (not decodable)")}else a.data instanceof Blob&&a.data.text().then(r=>{try{this.handleControlEvent(JSON.parse(r))}catch{console.warn("[WebRTC] Failed to parse blob data:",r)}})},this.dataChannel.onerror=a=>console.error("❌ [WebRTC] DataChannel error:",a),this.pc.ontrack=a=>{const r=a.track,l=a.streams[0];console.log(`📥 [WebRTC] Received ${r.kind} track`),r.kind==="audio"?(console.log("🔊 [WebRTC] Received audio track from server"),this.audioElement=new Audio,this.audioElement.srcObject=l,this.audioElement.play().catch(c=>console.warn("Audio autoplay blocked:",c)),this.audioElement.onended=()=>{this.sendEvent("playedStream"),console.log("✅ [WebRTC] TTS playback complete")}):r.kind==="video"&&(console.log("📹 [WebRTC] Video track received"),this.onRemoteTrack(r,l))};const t=()=>{var l,c,A,d,w,u,g,C,p,v,x;console.log("🔄 [WebRTC] State:",(l=this.pc)==null?void 0:l.connectionState,"| ICE:",(c=this.pc)==null?void 0:c.iceConnectionState);const a=((A=this.pc)==null?void 0:A.connectionState)==="connected"||((d=this.pc)==null?void 0:d.iceConnectionState)==="connected"||((w=this.pc)==null?void 0:w.iceConnectionState)==="completed",r=((u=this.pc)==null?void 0:u.connectionState)==="failed"||((g=this.pc)==null?void 0:g.iceConnectionState)==="failed"||((C=this.pc)==null?void 0:C.connectionState)==="closed"||((p=this.pc)==null?void 0:p.iceConnectionState)==="closed"||((v=this.pc)==null?void 0:v.connectionState)==="disconnected"||((x=this.pc)==null?void 0:x.iceConnectionState)==="disconnected";a&&!this.connected?(this.connected=!0,this.onConnected()):r&&this.connected&&(this.connected=!1,this.onDisconnected())};this.pc.onconnectionstatechange=t,this.pc.oniceconnectionstatechange=t;const i=await this.pc.createOffer();await this.pc.setLocalDescription(i),console.log("📝 [WebRTC] Created offer, waiting for ICE gathering..."),await this.waitForIceGathering(),console.log("🧊 [WebRTC] ICE gathering complete"),console.log("📤 [WebRTC] Sending offer via HTTP...");const s=await fetch(`${this.serverUrl}/webrtc?agent=${this.agentId}_${this.callId}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({offer:this.pc.localDescription,agentId:this.agentId,callId:this.callId})});if(!s.ok){const a=await s.json();throw new Error(a.error||`HTTP ${s.status}`)}const{answer:o}=await s.json();console.log("📥 [WebRTC] Received answer from server"),await this.pc.setRemoteDescription(o),console.log("✅ [WebRTC] Connection established!")}catch(e){throw console.error("❌ [WebRTC] Connection failed:",e),this.disconnect(),this.onError(e.message||e),e}}waitForIceGathering(){return new Promise(e=>{if(!this.pc)return e();if(this.pc.iceGatheringState==="complete")e();else{const t=()=>{var i,s;((i=this.pc)==null?void 0:i.iceGatheringState)==="complete"&&((s=this.pc)==null||s.removeEventListener("icegatheringstatechange",t),e())};this.pc.addEventListener("icegatheringstatechange",t),setTimeout(()=>{var i;(i=this.pc)==null||i.removeEventListener("icegatheringstatechange",t),console.warn("⚠️ [WebRTC] ICE gathering timeout, proceeding anyway"),e()},5e3)}})}sendEvent(e,t={}){var i;((i=this.dataChannel)==null?void 0:i.readyState)==="open"&&this.dataChannel.send(JSON.stringify({event:e,...t}))}handleControlEvent(e){switch(e.event){case"clearAudio":console.log("🛑 [WebRTC] Interrupt: clearAudio received (levanirag stream unpaused)");break;case"transcription":console.log("📝 [WebRTC] Transcription:",e.text),this.onTranscription(e.text,e.isFinal);break;case"mark":console.log("🏷️ [WebRTC] Mark:",e.name);break;case"client_tool_call":console.log("🛠️ [VaniraAI] Client Tool Call:",e),this.onClientToolCall(e.tool_call||e.data||e);break;default:console.log("ℹ️ [WebRTC] Unknown event:",e.event)}}disconnect(){console.log("🔴 [WebRTC] Disconnecting..."),this.audioElement&&(this.audioElement.pause(),this.audioElement.srcObject=null),this.dataChannel&&(this.dataChannel.close(),this.dataChannel=null),this.pc&&(this.pc.getSenders().forEach(e=>{e.track&&e.track.stop()}),this.pc.close(),this.pc=null),this.connected=!1,this.onDisconnected()}generateCallId(){return"web_"+Date.now()+"_"+Math.random().toString(36).substr(2,8)}sendToolResult(e,t){this.sendEvent("client_tool_result",{call_id:e,result:t})}sendSilentContext(e){this.sendEvent("silent_context",{context:e})}triggerActionInterrupt(){this.sendEvent("action_interrupt"),console.log("🛑 [VaniraAI] Triggered client-side action interrupt")}static async fetchIceServers(e,t="https://coredb.travelr.club/v1/graphql"){var i;try{const o=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json",Authorization:e},body:JSON.stringify({query:`
1
+ (function(f,y){typeof exports=="object"&&typeof module<"u"?y(exports):typeof define=="function"&&define.amd?define(["exports"],y):(f=typeof globalThis<"u"?globalThis:f||self,y(f.VaniraAI={}))})(this,function(f){"use strict";var pe=Object.defineProperty;var we=(f,y,b)=>y in f?pe(f,y,{enumerable:!0,configurable:!0,writable:!0,value:b}):f[y]=b;var n=(f,y,b)=>we(f,typeof y!="symbol"?y+"":y,b);var y=typeof document<"u"?document.currentScript:null;class b{constructor(e){n(this,"serverUrl");n(this,"agentId");n(this,"callId");n(this,"onConnected");n(this,"onDisconnected");n(this,"onError");n(this,"onTranscription");n(this,"onRemoteTrack");n(this,"onClientToolCall");n(this,"pc",null);n(this,"dataChannel",null);n(this,"audioElement",null);n(this,"connected",!1);n(this,"iceServers");n(this,"token");if(!e.serverUrl)throw new Error("serverUrl is required");if(!e.agentId)throw new Error("agentId is required");this.serverUrl=e.serverUrl.replace(/\/$/,""),this.agentId=e.agentId,this.callId=e.callId||this.generateCallId(),this.iceServers=e.iceServers,this.token=e.token,this.onConnected=e.onConnected||(()=>{}),this.onDisconnected=e.onDisconnected||(()=>{}),this.onError=e.onError||(t=>console.error("[WebRTC]",t)),this.onTranscription=e.onTranscription||(()=>{}),this.onRemoteTrack=e.onRemoteTrack||(()=>{}),this.onClientToolCall=e.onClientToolCall||(()=>{})}async connect(){console.log("🔵 [WebRTC] Starting connection...");try{if(!this.iceServers&&this.token)try{this.iceServers=await b.fetchIceServers(this.token)}catch(a){console.warn("⚠️ [WebRTC] Failed to fetch ICE servers:",a)}this.pc=new RTCPeerConnection({iceServers:this.iceServers||[{urls:"stun:global.relay.metered.ca:80"},{urls:["turns:global.relay.metered.ca:443?transport=tcp","turn:global.relay.metered.ca:80?transport=tcp","turn:global.relay.metered.ca:443?transport=tcp"],username:"fa97658be3343d21da3b65e6",credential:"HXHDoqeHbvZrmCuf"}]}),this.pc.addTransceiver("video",{direction:"recvonly"});const e=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,sampleRate:{ideal:16e3},channelCount:1}});if(console.log("🎤 [WebRTC] Microphone access granted"),!this.pc){console.log("[WebRTC] Connection aborted: peer connection closed during setup"),e.getTracks().forEach(a=>a.stop());return}if(e.getTracks().forEach(a=>{var r;(r=this.pc)==null||r.addTrack(a,e)}),!this.pc)throw new Error("RTCPeerConnection was closed unexpectedly");this.dataChannel=this.pc.createDataChannel("control"),this.dataChannel.onopen=()=>console.log("📡 [WebRTC] DataChannel opened"),this.dataChannel.onmessage=a=>{if(typeof a.data=="string")try{this.handleControlEvent(JSON.parse(a.data))}catch{console.warn("[WebRTC] Failed to parse message:",a.data)}else if(a.data instanceof ArrayBuffer)try{const r=new TextDecoder().decode(a.data);try{const l=JSON.parse(r);l&&typeof l=="object"&&l.event==="client_tool_call"?(console.log("[VaniraAI] Safely decoding binary tool_call to JSON:",l),this.handleControlEvent(l)):console.log("[VaniraAI] Decoded JSON from binary (inspect only):",l)}catch{console.log("[VaniraAI] Decoded String from binary:",r)}}catch{console.log("[VaniraAI] Received binary data:",a.data.byteLength,"bytes (not decodable)")}else a.data instanceof Blob&&a.data.text().then(r=>{try{this.handleControlEvent(JSON.parse(r))}catch{console.warn("[WebRTC] Failed to parse blob data:",r)}})},this.dataChannel.onerror=a=>console.error("❌ [WebRTC] DataChannel error:",a),this.pc.ontrack=a=>{const r=a.track,l=a.streams[0];console.log(`📥 [WebRTC] Received ${r.kind} track`),r.kind==="audio"?(console.log("🔊 [WebRTC] Received audio track from server"),this.audioElement=new Audio,this.audioElement.srcObject=l,this.audioElement.play().catch(c=>console.warn("Audio autoplay blocked:",c)),this.audioElement.onended=()=>{this.sendEvent("playedStream"),console.log("✅ [WebRTC] TTS playback complete")}):r.kind==="video"&&(console.log("📹 [WebRTC] Video track received"),this.onRemoteTrack(r,l))};const t=()=>{var l,c,A,d,w,u,g,C,p,v,x;console.log("🔄 [WebRTC] State:",(l=this.pc)==null?void 0:l.connectionState,"| ICE:",(c=this.pc)==null?void 0:c.iceConnectionState);const a=((A=this.pc)==null?void 0:A.connectionState)==="connected"||((d=this.pc)==null?void 0:d.iceConnectionState)==="connected"||((w=this.pc)==null?void 0:w.iceConnectionState)==="completed",r=((u=this.pc)==null?void 0:u.connectionState)==="failed"||((g=this.pc)==null?void 0:g.iceConnectionState)==="failed"||((C=this.pc)==null?void 0:C.connectionState)==="closed"||((p=this.pc)==null?void 0:p.iceConnectionState)==="closed"||((v=this.pc)==null?void 0:v.connectionState)==="disconnected"||((x=this.pc)==null?void 0:x.iceConnectionState)==="disconnected";a&&!this.connected?(this.connected=!0,this.onConnected()):r&&this.connected&&(this.connected=!1,this.onDisconnected())};this.pc.onconnectionstatechange=t,this.pc.oniceconnectionstatechange=t;const i=await this.pc.createOffer();await this.pc.setLocalDescription(i),console.log("📝 [WebRTC] Created offer, waiting for ICE gathering..."),await this.waitForIceGathering(),console.log("🧊 [WebRTC] ICE gathering complete"),console.log("📤 [WebRTC] Sending offer via HTTP...");const s=await fetch(`${this.serverUrl}/webrtc?agent=${this.agentId}_${this.callId}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({offer:this.pc.localDescription,agentId:this.agentId,callId:this.callId})});if(!s.ok){const a=await s.json();throw new Error(a.error||`HTTP ${s.status}`)}const{answer:o}=await s.json();console.log("📥 [WebRTC] Received answer from server"),await this.pc.setRemoteDescription(o),console.log("✅ [WebRTC] Connection established!")}catch(e){throw console.error("❌ [WebRTC] Connection failed:",e),this.disconnect(),this.onError(e.message||e),e}}waitForIceGathering(){return new Promise(e=>{if(!this.pc)return e();if(this.pc.iceGatheringState==="complete")e();else{const t=()=>{var i,s;((i=this.pc)==null?void 0:i.iceGatheringState)==="complete"&&((s=this.pc)==null||s.removeEventListener("icegatheringstatechange",t),e())};this.pc.addEventListener("icegatheringstatechange",t),setTimeout(()=>{var i;(i=this.pc)==null||i.removeEventListener("icegatheringstatechange",t),console.warn("⚠️ [WebRTC] ICE gathering timeout, proceeding anyway"),e()},5e3)}})}sendEvent(e,t={}){var i;((i=this.dataChannel)==null?void 0:i.readyState)==="open"&&this.dataChannel.send(JSON.stringify({event:e,...t}))}handleControlEvent(e){switch(e.event){case"clearAudio":console.log("🛑 [WebRTC] Interrupt: clearAudio received (leaving stream unpaused)");break;case"transcription":console.log("📝 [WebRTC] Transcription:",e.text),this.onTranscription(e.text,e.isFinal);break;case"mark":console.log("🏷️ [WebRTC] Mark:",e.name);break;case"client_tool_call":console.log("🛠️ [VaniraAI] Client Tool Call:",e),this.onClientToolCall(e.tool_call||e.data||e);break;default:console.log("ℹ️ [WebRTC] Unknown event:",e.event)}}disconnect(){console.log("🔴 [WebRTC] Disconnecting..."),this.audioElement&&(this.audioElement.pause(),this.audioElement.srcObject=null),this.dataChannel&&(this.dataChannel.close(),this.dataChannel=null),this.pc&&(this.pc.getSenders().forEach(e=>{e.track&&e.track.stop()}),this.pc.close(),this.pc=null),this.connected=!1,this.onDisconnected()}generateCallId(){return"web_"+Date.now()+"_"+Math.random().toString(36).substr(2,8)}sendToolResult(e,t){this.sendEvent("client_tool_result",{call_id:e,result:t})}sendContextUpdate(e){this.sendEvent("client_context_update",{data:{context:e}})}sendActionTrigger(e,t={}){this.sendEvent("client_action_trigger",{data:{action_name:e,data:t}})}triggerActionInterrupt(){this.sendEvent("action_interrupt"),console.log("🛑 [VaniraAI] Triggered client-side action interrupt")}static async fetchIceServers(e,t="https://coredb.travelr.club/v1/graphql"){var i;try{const o=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json",Authorization:e},body:JSON.stringify({query:`
2
2
  query GetIceServers {
3
3
  ice_servers(where: {enabled: {_eq: true}}) {
4
4
  urls
5
5
  username
6
6
  credential
7
7
  }
8
- }`})});if(!o.ok)throw new Error("Failed to fetch ICE servers");return((i=(await o.json()).data)==null?void 0:i.ice_servers)||[]}catch(s){throw console.error("[WebRTC] Failed to fetch ICE servers:",s),s}}}const q={};class Y{constructor(e){n(this,"config");n(this,"_status","idle");n(this,"client",null);n(this,"listeners",new Map);if(!e.agentId)throw new Error("[VaniraAI] agentId is required");this.config=e}get status(){return this._status}get isConnected(){return this._status==="connected"}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),this}off(e,t){var i;return(i=this.listeners.get(e))==null||i.delete(t),this}emit(e,t){var i;(i=this.listeners.get(e))==null||i.forEach(s=>s(t))}async start(){if(this._status==="connecting"||this._status==="connected"){console.warn("[VaniraAI] Already connecting or connected. Call stop() first.");return}this._setStatus("connecting");const e=this.config.serverUrl||this._inferServerUrl();try{this.client=new B({serverUrl:e,agentId:this.config.agentId,callId:this.config.callId,token:this.config.token,iceServers:this.config.iceServers,onConnected:()=>{this._setStatus("connected"),this.emit("connected")},onDisconnected:()=>{this._setStatus("disconnected"),this.emit("disconnected")},onError:t=>{this._setStatus("error"),this.emit("error",typeof t=="string"?t:(t==null?void 0:t.message)||"Connection failed")},onTranscription:(t,i)=>{this.emit("transcription",{text:t,isFinal:i})},onClientToolCall:t=>{const i=(t==null?void 0:t.data)||t,s={name:i.name||i.tool_name||"",arguments:i.arguments||i.args||{},tool_call_id:i.tool_call_id||i.call_id||"",execution_mode:i.execution_mode||"fire_and_forget"};this.emit("tool_call",s)},onRemoteTrack:(t,i)=>{this.emit("track",{track:t,stream:i})}}),await this.client.connect()}catch(t){throw this._setStatus("error"),this.emit("error",(t==null?void 0:t.message)||"Failed to start call"),t}}stop(){this.client&&(this.client.disconnect(),this.client=null),this._setStatus("disconnected")}sendToolResult(e,t){this._assertConnected("sendToolResult"),this.client.sendToolResult(e,t)}sendToolError(e,t){this._assertConnected("sendToolError"),this.client.sendEvent("client_tool_result",{call_id:e,result:{status:"error",error:t}})}updateContext(e){this._assertConnected("updateContext"),this.client.sendEvent("client_context_update",{data:{context:e}})}triggerInterrupt(e,t={}){this._assertConnected("triggerInterrupt"),this.client.triggerActionInterrupt(),this.client.sendEvent("client_action_trigger",{data:{action_name:e,data:t}})}_setStatus(e){this._status=e}_inferServerUrl(){return(typeof{url:typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:y&&y.tagName.toUpperCase()==="SCRIPT"&&y.src||new URL("vanira-sdk.es.js",document.baseURI).href}<"u"&&q||{}).VITE_WEBRTC_SERVER_URL||"https://in-godspeed.travelr.club"}_assertConnected(e){if(!this.client||!this.isConnected)throw new Error(`[VaniraAI] Cannot call ${e}() when not connected. Call start() first.`)}}const G="https://coredb.travelr.club/v1/graphql";class H{static async fetchWidgetConfig(e){var i,s;const t=`
8
+ }`})});if(!o.ok)throw new Error("Failed to fetch ICE servers");return((i=(await o.json()).data)==null?void 0:i.ice_servers)||[]}catch(s){throw console.error("[WebRTC] Failed to fetch ICE servers:",s),s}}}const q={};class Y{constructor(e){n(this,"config");n(this,"_status","idle");n(this,"client",null);n(this,"listeners",new Map);if(!e.agentId)throw new Error("[VaniraAI] agentId is required");this.config=e}get status(){return this._status}get isConnected(){return this._status==="connected"}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),this}off(e,t){var i;return(i=this.listeners.get(e))==null||i.delete(t),this}emit(e,t){var i;(i=this.listeners.get(e))==null||i.forEach(s=>s(t))}async start(){if(this._status==="connecting"||this._status==="connected"){console.warn("[VaniraAI] Already connecting or connected. Call stop() first.");return}this._setStatus("connecting");const e=this.config.serverUrl||this._inferServerUrl();try{this.client=new b({serverUrl:e,agentId:this.config.agentId,callId:this.config.callId,token:this.config.token,iceServers:this.config.iceServers,onConnected:()=>{this._setStatus("connected"),this.emit("connected")},onDisconnected:()=>{this._setStatus("disconnected"),this.emit("disconnected")},onError:t=>{this._setStatus("error"),this.emit("error",typeof t=="string"?t:(t==null?void 0:t.message)||"Connection failed")},onTranscription:(t,i)=>{this.emit("transcription",{text:t,isFinal:i})},onClientToolCall:t=>{const i=(t==null?void 0:t.data)||t,s={name:i.name||i.tool_name||"",arguments:i.arguments||i.args||{},tool_call_id:i.tool_call_id||i.call_id||"",execution_mode:i.execution_mode||"fire_and_forget"};this.emit("tool_call",s)},onRemoteTrack:(t,i)=>{this.emit("track",{track:t,stream:i})}}),await this.client.connect()}catch(t){throw this._setStatus("error"),this.emit("error",(t==null?void 0:t.message)||"Failed to start call"),t}}stop(){this.client&&(this.client.disconnect(),this.client=null),this._setStatus("disconnected")}sendToolResult(e,t){this._assertConnected("sendToolResult"),this.client.sendToolResult(e,t)}sendToolError(e,t){this._assertConnected("sendToolError"),this.client.sendEvent("client_tool_result",{call_id:e,result:{status:"error",error:t}})}updateContext(e){this._assertConnected("updateContext"),this.client.sendContextUpdate(e)}triggerInterrupt(e,t={}){this._assertConnected("triggerInterrupt"),this.client.triggerActionInterrupt(),this.client.sendActionTrigger(e,t)}_setStatus(e){this._status=e}_inferServerUrl(){return(typeof{url:typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:y&&y.tagName.toUpperCase()==="SCRIPT"&&y.src||new URL("vanira-sdk.es.js",document.baseURI).href}<"u"&&q||{}).VITE_WEBRTC_SERVER_URL||"https://in-godspeed.travelr.club"}_assertConnected(e){if(!this.client||!this.isConnected)throw new Error(`[VaniraAI] Cannot call ${e}() when not connected. Call start() first.`)}}const G="https://coredb.travelr.club/v1/graphql";class H{static async fetchWidgetConfig(e){var i,s;const t=`
9
9
  query GetWidgetConfig($id: uuid!) {
10
10
  app_widget_by_pk(id: $id) {
11
11
  agent_id
@@ -29,7 +29,7 @@
29
29
  base_prospect_group_id
30
30
  }
31
31
  }
32
- `,variables:{id:r.client_id}})})).json();(s=A.data)!=null&&s.client_by_pk&&(r.client=A.data.client_by_pk)}return r}catch(o){throw console.error("[VaniraAI] Failed to fetch widget config:",o),o}}}const Z="https://coredb.travelr.club/v1/graphql";let D="https://inboxapi.travelr.club";class b{static setChatUrl(e){D=e}static async createChatProspect(e){var i,s;const t=`
32
+ `,variables:{id:r.client_id}})})).json();(s=A.data)!=null&&s.client_by_pk&&(r.client=A.data.client_by_pk)}return r}catch(o){throw console.error("[VaniraAI] Failed to fetch widget config:",o),o}}}const Z="https://coredb.travelr.club/v1/graphql";let D="https://inboxapi.travelr.club";class B{static setChatUrl(e){D=e}static async createChatProspect(e){var i,s;const t=`
33
33
  mutation CreateChatProspect($prospectGroupId: uuid!, $name: String!) {
34
34
  insert_prospects_one(object: {prospect_group_id: $prospectGroupId, name: $name, source: "widget"}) {
35
35
  id
@@ -131,6 +131,11 @@
131
131
  to { transform: rotate(360deg); }
132
132
  }
133
133
 
134
+ @keyframes voice-bars-orb {
135
+ 0%, 100% { transform: scaleY(1); opacity: 0.7; }
136
+ 50% { transform: scaleY(1.8); opacity: 1; }
137
+ }
138
+
134
139
 
135
140
  .widget-fab {
136
141
  position: fixed;
@@ -715,6 +720,14 @@
715
720
  <line x1="14" y1="10" x2="21" y2="3"/>
716
721
  <line x1="3" y1="21" x2="10" y2="14"/>
717
722
  </svg>
723
+ `,voice_orb:`
724
+ <div style="display: flex; align-items: center; justify-content: center; gap: 3px; height: 100%; width: 100%;">
725
+ <div style="width: 3px; height: 10px; background: white; border-radius: 10px; animation: voice-bars-orb 1.2s infinite ease-in-out; animation-delay: 0s;"></div>
726
+ <div style="width: 3px; height: 18px; background: white; border-radius: 10px; animation: voice-bars-orb 1.2s infinite ease-in-out; animation-delay: 0.2s;"></div>
727
+ <div style="width: 3px; height: 14px; background: white; border-radius: 10px; animation: voice-bars-orb 1.2s infinite ease-in-out; animation-delay: 0.4s;"></div>
728
+ <div style="width: 3px; height: 22px; background: white; border-radius: 10px; animation: voice-bars-orb 1.2s infinite ease-in-out; animation-delay: 0.1s;"></div>
729
+ <div style="width: 3px; height: 12px; background: white; border-radius: 10px; animation: voice-bars-orb 1.2s infinite ease-in-out; animation-delay: 0.3s;"></div>
730
+ </div>
718
731
  `},J={automotive:`
719
732
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
720
733
  <path d="M19 17h2c.6 0 1-.4 1-1v-3c0-.9-.7-1.7-1.5-1.9C18.7 10.6 16 10 16 10s-1.3-1.4-2.2-2.3c-.5-.4-1.1-.7-1.8-.7H5c-.6 0-1.1.4-1.4.9l-1.4 2.9A3.7 3.7 0 0 0 2 12v4c0 .6.4 1 1 1h2"/>
@@ -829,7 +842,7 @@
829
842
  <rect width="18" height="12" x="3" y="4" rx="2" ry="2"/>
830
843
  <line x1="2" x2="22" y1="20" y2="20"/>
831
844
  </svg>
832
- `},T={...J,default_chat:m.chat,default_voice:m.mic,male:`<img src="${z}" style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block;" />`,female:`<img src="${L}" style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block;" />`};Object.entries(J).forEach(([h,e])=>{T[`male_${h} `]=`
845
+ `},T={...J,default_chat:m.chat,default_voice:m.mic,voice_orb:m.voice_orb,male:`<img src="${z}" style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block;" />`,female:`<img src="${L}" style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block;" />`};Object.entries(J).forEach(([h,e])=>{T[`male_${h} `]=`
833
846
  < div style = "position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: white; border-radius: 50%;" >
834
847
  <div style="width: 60%; height: 60%; color: #6366f1;" >
835
848
  ${e}
@@ -991,7 +1004,7 @@ overflow: hidden;
991
1004
  cursor: pointer; pointer-events: auto;
992
1005
  transition: background-color 0.2s;
993
1006
  box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1);
994
- `,this.hangupBtn.onmouseover=()=>this.hangupBtn.style.backgroundColor="#dc2626",this.hangupBtn.onmouseout=()=>this.hangupBtn.style.backgroundColor="#ef4444",this.hangupBtn.onclick=()=>{const w=this.callStartedAt?Date.now()-this.callStartedAt:0,u=this.callStartedAt??Date.now();this.onCallEnded&&w>0&&this.onCallEnded(w,u),this.onHangup()},d.appendChild(this.hangupBtn),this.element.appendChild(d)}getElement(){return this.element}setMode(e){this.isAvatarMode=e==="avatar"}setVideoTrack(e){if(this.isAvatarMode=!0,e.kind==="video"&&this.videoElement){const t=new MediaStream([e]);this.videoElement.srcObject=t,this.videoContainer.style.display="block",this.orbWrapper.style.display="none",this.connectingLabel.style.display="none",this.timerEl.style.display="none",this.videoElement.onplaying=()=>{this.prepareBadge.style.display="none",this.statusBadge.style.display="flex"},this.videoElement.play().catch(i=>console.warn("Video play error",i))}}setStatus(e){if(e==="connecting")this.centerIcon.style.background="#4b5563",this.centerIcon.innerHTML='<div style="width:18px;height:18px;border:2px solid #ffffff;border-top-color:transparent;border-radius:50%;animation:spin 1s linear infinite;"></div>',this.isAvatarMode?(this.videoContainer.style.display="block",this.orbWrapper.style.display="none",this.prepareBadge.textContent="CONNECTING...",this.prepareBadge.style.display="block",this.statusBadge.style.display="none",this.connectingLabel.style.display="none"):(this.orbWrapper.style.display="flex",this.videoContainer.style.display="none",this.connectingRing.style.display="block",this.errorRing.style.display="none",this.waveLayers.forEach(t=>t.style.display="none"),this.connectingLabel.style.display="block",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="none",this.retryBtn.style.display="none"),this.stopTimer();else if(e==="connected"){this.centerIcon.style.background="#1f2937",this.centerIcon.innerHTML=m.phone;const t=this.centerIcon.querySelector("svg");t&&(t.style.cssText="width:20px;height:20px;"),this.isAvatarMode?this.videoElement&&!this.videoElement.paused&&this.videoElement.readyState>2?(this.prepareBadge.style.display="none",this.statusBadge.style.display="flex"):(this.prepareBadge.textContent="AGENT IS ON THE WAY...",this.prepareBadge.style.display="block",setTimeout(()=>{this.prepareBadge.style.display!=="none"&&(this.prepareBadge.style.display="none",this.statusBadge.style.display="flex")},5e3)):(this.connectingRing.style.display="none",this.errorRing.style.display="none",this.waveLayers.forEach(i=>i.style.display="flex"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="flex",this.timerEl.style.display="block",this.errorLabel.style.display="none",this.retryBtn.style.display="none",this.startTimer())}else e==="error"&&(this.centerIcon.style.background="#dc2626",this.centerIcon.innerHTML=m.phone,this.connectingRing.style.display="none",this.errorRing.style.display="block",this.waveLayers.forEach(t=>t.style.display="none"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="block",this.retryBtn.style.display="block",this.stopTimer())}setTranscription(e,t){this.transcriptionEl.textContent=`"${e}"`,this.transcriptionEl.style.color=t?"#1f2937":"#9ca3af",this.transcriptionEl.style.fontStyle=t?"normal":"italic"}show(){this.callStartedAt=Date.now(),this.element.style.display="flex",this.setStatus("connecting")}hide(){this.element.style.display="none",this.reset()}reset(){this.videoElement&&(this.videoElement.srcObject=null),this.isAvatarMode=!1,this.callStartedAt=null,this.stopTimer(),this.transcriptionEl.textContent="",this.videoContainer.style.display="none",this.orbWrapper.style.display="flex",this.connectingRing.style.display="none",this.errorRing.style.display="none",this.waveLayers.forEach(t=>t.style.display="none"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="none",this.retryBtn.style.display="none",this.prepareBadge.style.display="none",this.statusBadge.style.display="none",this.centerIcon.style.background="#374151",this.centerIcon.innerHTML=m.phone;const e=this.centerIcon.querySelector("svg");e&&(e.style.cssText="width:20px;height:20px;")}startTimer(){this.timerInterval&&clearInterval(this.timerInterval),this.startTime=Date.now(),this.timerEl.textContent="00:00",this.timerInterval=setInterval(()=>{if(!this.startTime)return;const e=Math.floor((Date.now()-this.startTime)/1e3),t=Math.floor(e/60).toString().padStart(2,"0"),i=(e%60).toString().padStart(2,"0");this.timerEl.textContent=`${t}:${i}`},1e3)}stopTimer(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null),this.timerEl.textContent=""}setFullScreen(e){e?(this.videoContainer.style.position="absolute",this.videoContainer.style.top="0",this.videoContainer.style.left="0",this.videoContainer.style.width="100%",this.videoContainer.style.height="100%",this.videoContainer.style.maxWidth="none",this.videoContainer.style.borderRadius="0",this.videoContainer.style.margin="0",this.videoContainer.style.zIndex="0"):(this.videoContainer.style.position="relative",this.videoContainer.style.width="100%",this.videoContainer.style.maxWidth="260px",this.videoContainer.style.height="auto",this.videoContainer.style.aspectRatio="1/1",this.videoContainer.style.borderRadius="16px",this.videoContainer.style.marginBottom="16px")}}class O{constructor(e){n(this,"element");n(this,"messageContainer");n(this,"inputArea");n(this,"input");n(this,"sendBtn");n(this,"typingIndicator",null);this.onSend=e,this.element=document.createElement("div"),this.element.style.display="flex",this.element.style.flexDirection="column",this.element.style.flex="1",this.element.style.overflow="hidden",this.element.style.minHeight="0",this.messageContainer=document.createElement("div"),this.messageContainer.className="chat-messages",this.inputArea=document.createElement("div"),this.inputArea.className="chat-input-area",this.input=document.createElement("input"),this.input.className="chat-input",this.input.placeholder="Type a message...",this.input.addEventListener("keypress",i=>{i.key==="Enter"&&this.handleSend()}),this.sendBtn=document.createElement("button"),this.sendBtn.className="chat-send-btn",this.sendBtn.innerHTML=m.send,this.sendBtn.onclick=()=>this.handleSend(),this.inputArea.appendChild(this.input),this.inputArea.appendChild(this.sendBtn);const t=document.createElement("div");t.className="branding-footer",t.innerHTML="Technology Powered by <b>Vanira AI</b>",this.element.appendChild(this.messageContainer),this.element.appendChild(this.inputArea),this.element.appendChild(t)}getElement(){return this.element}formatTime(e=new Date){return e.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}addMessage(e,t,i){const s=document.createElement("div");s.style.cssText=`
1007
+ `,this.hangupBtn.onmouseover=()=>this.hangupBtn.style.backgroundColor="#dc2626",this.hangupBtn.onmouseout=()=>this.hangupBtn.style.backgroundColor="#ef4444",this.hangupBtn.onclick=()=>{const w=this.callStartedAt?Date.now()-this.callStartedAt:0,u=this.callStartedAt??Date.now();this.onCallEnded&&w>0&&this.onCallEnded(w,u),this.onHangup()},d.appendChild(this.hangupBtn),this.element.appendChild(d)}getElement(){return this.element}setMode(e){this.isAvatarMode=e==="avatar"}setVideoTrack(e){if(this.isAvatarMode=!0,e.kind==="video"&&this.videoElement){const t=new MediaStream([e]);this.videoElement.srcObject=t,this.videoContainer.style.display="block",this.orbWrapper.style.display="none",this.connectingLabel.style.display="none",this.timerEl.style.display="none",this.videoElement.onplaying=()=>{this.prepareBadge.style.display="none",this.statusBadge.style.display="flex"},this.videoElement.play().catch(i=>console.warn("Video play error",i))}}setStatus(e){if(e==="connecting")this.centerIcon.style.background="#4b5563",this.centerIcon.innerHTML='<div style="width:18px;height:18px;border:2px solid #ffffff;border-top-color:transparent;border-radius:50%;animation:spin 1s linear infinite;"></div>',this.isAvatarMode?(this.videoContainer.style.display="block",this.orbWrapper.style.display="none",this.prepareBadge.textContent="CONNECTING...",this.prepareBadge.style.display="block",this.statusBadge.style.display="none",this.connectingLabel.style.display="none"):(this.orbWrapper.style.display="flex",this.videoContainer.style.display="none",this.connectingRing.style.display="block",this.errorRing.style.display="none",this.waveLayers.forEach(t=>t.style.display="none"),this.connectingLabel.style.display="block",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="none",this.retryBtn.style.display="none"),this.stopTimer();else if(e==="connected"){this.centerIcon.style.background="#1f2937",this.centerIcon.innerHTML=m.phone;const t=this.centerIcon.querySelector("svg");t&&(t.style.cssText="width:20px;height:20px;"),this.isAvatarMode?this.videoElement&&!this.videoElement.paused&&this.videoElement.readyState>2?(this.prepareBadge.style.display="none",this.statusBadge.style.display="flex"):(this.prepareBadge.textContent="AGENT IS ON THE WAY...",this.prepareBadge.style.display="block",setTimeout(()=>{this.prepareBadge.style.display!=="none"&&(this.prepareBadge.style.display="none",this.statusBadge.style.display="flex")},5e3)):(this.connectingRing.style.display="none",this.errorRing.style.display="none",this.waveLayers.forEach(i=>i.style.display="flex"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="flex",this.timerEl.style.display="block",this.errorLabel.style.display="none",this.retryBtn.style.display="none",this.startTimer())}else e==="error"&&(this.centerIcon.style.background="#dc2626",this.centerIcon.innerHTML=m.phone,this.connectingRing.style.display="none",this.errorRing.style.display="block",this.waveLayers.forEach(t=>t.style.display="none"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="block",this.retryBtn.style.display="block",this.stopTimer())}setTranscription(e,t){this.transcriptionEl.textContent=`"${e}"`,this.transcriptionEl.style.color=t?"#1f2937":"#9ca3af",this.transcriptionEl.style.fontStyle=t?"normal":"italic"}show(){this.callStartedAt=Date.now(),this.element.style.display="flex",this.setStatus("connecting")}hide(){this.element.style.display="none",this.reset()}reset(){this.videoElement&&(this.videoElement.srcObject=null),this.isAvatarMode=!1,this.callStartedAt=null,this.stopTimer(),this.transcriptionEl.textContent="",this.videoContainer.style.display="none",this.orbWrapper.style.display="flex",this.connectingRing.style.display="none",this.errorRing.style.display="none",this.waveLayers.forEach(t=>t.style.display="none"),this.connectingLabel.style.display="none",this.connectedBadge.style.display="none",this.timerEl.style.display="none",this.errorLabel.style.display="none",this.retryBtn.style.display="none",this.prepareBadge.style.display="none",this.statusBadge.style.display="none",this.centerIcon.style.background="#374151",this.centerIcon.innerHTML=m.phone;const e=this.centerIcon.querySelector("svg");e&&(e.style.cssText="width:20px;height:20px;")}startTimer(){this.timerInterval&&clearInterval(this.timerInterval),this.startTime=Date.now(),this.timerEl.textContent="00:00",this.timerInterval=setInterval(()=>{if(!this.startTime)return;const e=Math.floor((Date.now()-this.startTime)/1e3),t=Math.floor(e/60).toString().padStart(2,"0"),i=(e%60).toString().padStart(2,"0");this.timerEl.textContent=`${t}:${i}`},1e3)}stopTimer(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null),this.timerEl.textContent=""}setFullScreen(e){e?(this.videoContainer.style.position="absolute",this.videoContainer.style.top="0",this.videoContainer.style.left="0",this.videoContainer.style.width="100%",this.videoContainer.style.height="100%",this.videoContainer.style.maxWidth="none",this.videoContainer.style.borderRadius="0",this.videoContainer.style.margin="0",this.videoContainer.style.zIndex="0"):(this.videoContainer.style.position="relative",this.videoContainer.style.width="100%",this.videoContainer.style.maxWidth="260px",this.videoContainer.style.height="auto",this.videoContainer.style.aspectRatio="1/1",this.videoContainer.style.borderRadius="16px",this.videoContainer.style.marginBottom="16px")}}class U{constructor(e){n(this,"element");n(this,"messageContainer");n(this,"inputArea");n(this,"input");n(this,"sendBtn");n(this,"typingIndicator",null);this.onSend=e,this.element=document.createElement("div"),this.element.style.display="flex",this.element.style.flexDirection="column",this.element.style.flex="1",this.element.style.overflow="hidden",this.element.style.minHeight="0",this.messageContainer=document.createElement("div"),this.messageContainer.className="chat-messages",this.inputArea=document.createElement("div"),this.inputArea.className="chat-input-area",this.input=document.createElement("input"),this.input.className="chat-input",this.input.placeholder="Type a message...",this.input.addEventListener("keypress",i=>{i.key==="Enter"&&this.handleSend()}),this.sendBtn=document.createElement("button"),this.sendBtn.className="chat-send-btn",this.sendBtn.innerHTML=m.send,this.sendBtn.onclick=()=>this.handleSend(),this.inputArea.appendChild(this.input),this.inputArea.appendChild(this.sendBtn);const t=document.createElement("div");t.className="branding-footer",t.innerHTML="Technology Powered by <b>Vanira AI</b>",this.element.appendChild(this.messageContainer),this.element.appendChild(this.inputArea),this.element.appendChild(t)}getElement(){return this.element}formatTime(e=new Date){return e.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}addMessage(e,t,i){const s=document.createElement("div");s.style.cssText=`
995
1008
  display: flex;
996
1009
  flex-direction: column;
997
1010
  align-items: ${e==="user"?"flex-end":"flex-start"};
@@ -1032,7 +1045,7 @@ overflow: hidden;
1032
1045
  </div>
1033
1046
  <div class="voice-status-text">Tap to speak</div>
1034
1047
  <div class="voice-status-subtext">Start a conversation</div>
1035
- `;const t=this.element.querySelector(".central-orb-container");t&&(t.onclick=this.onClick)}getElement(){return this.element}}class U{constructor(e){n(this,"element");n(this,"chips",[]);this.onChipClick=e,this.element=document.createElement("div"),this.element.className="welcome-chips-container"}setChips(e){this.chips=e,this.render()}getElement(){return this.element}setPosition(e){let t=e;t.includes("bottom:")?t=t.replace(/bottom:\s*[\d]+px/,"bottom: 100px"):t.includes("top:")&&(t=t.replace(/top:\s*[\d]+px/,"top: 100px")),this.element.setAttribute("style",t)}render(){this.element.innerHTML="",this.chips.forEach((e,t)=>{const i=document.createElement("button");i.className="welcome-chip-btn",i.textContent=e.title,i.onclick=s=>{s.stopPropagation(),this.onChipClick(e.title)},i.style.animationDelay=`${t*.1}s`,this.element.appendChild(i)})}static get styles(){return`
1048
+ `;const t=this.element.querySelector(".central-orb-container");t&&(t.onclick=this.onClick)}getElement(){return this.element}}class O{constructor(e){n(this,"element");n(this,"chips",[]);this.onChipClick=e,this.element=document.createElement("div"),this.element.className="welcome-chips-container"}setChips(e){this.chips=e,this.render()}getElement(){return this.element}setPosition(e){let t=e;t.includes("bottom:")?t=t.replace(/bottom:\s*[\d]+px/,"bottom: 100px"):t.includes("top:")&&(t=t.replace(/top:\s*[\d]+px/,"top: 100px")),this.element.setAttribute("style",t)}render(){this.element.innerHTML="",this.chips.forEach((e,t)=>{const i=document.createElement("button");i.className="welcome-chip-btn",i.textContent=e.title,i.onclick=s=>{s.stopPropagation(),this.onChipClick(e.title)},i.style.animationDelay=`${t*.1}s`,this.element.appendChild(i)})}static get styles(){return`
1036
1049
  .welcome-chips-container {
1037
1050
  position: fixed;
1038
1051
  z-index: 9998;
@@ -1088,7 +1101,7 @@ overflow: hidden;
1088
1101
  transform: translateY(0);
1089
1102
  }
1090
1103
  }
1091
- `}}class V{constructor(e,t,i="#6366f1",s="#a855f7",o){n(this,"element");n(this,"overlay");n(this,"onStartCall");n(this,"onHangup");n(this,"primaryColor");n(this,"secondaryColor");n(this,"onCallEnded");this.onStartCall=e,this.onHangup=t,this.primaryColor=i,this.secondaryColor=s,this.onCallEnded=o,this.element=document.createElement("div"),this.element.style.height="100%",this.element.style.position="relative"}initOverlay(){this.overlay=new N(()=>this.onHangup(),this.primaryColor,this.secondaryColor,this.onCallEnded),this.element.appendChild(this.overlay.getElement())}getElement(){return this.element}setCallActive(e){e?this.overlay.show():this.overlay.hide()}setStatus(e){this.overlay.setStatus(e)}setTranscription(e,t){this.overlay.setTranscription(e,t)}setVideoTrack(e){this.overlay.setVideoTrack(e)}}class se extends V{constructor(t,i,s="#6366f1",o="#a855f7",a){super(t,i,s,o,a);n(this,"voiceOrb");this.element.style.background="#f9fafb",this.voiceOrb=new ie(()=>this.onStartCall()),this.element.appendChild(this.voiceOrb.getElement()),this.initOverlay()}}class ne{constructor(e){n(this,"element");n(this,"chatWindow");this.onSendMessage=e,this.element=document.createElement("div"),this.element.style.flex="1",this.element.style.width="100%",this.element.style.minHeight="0",this.element.style.display="flex",this.element.style.flexDirection="column",this.chatWindow=new O(t=>this.onSendMessage(t)),this.element.appendChild(this.chatWindow.getElement())}getElement(){return this.element}getChatWindow(){return this.chatWindow}}class W{constructor(e,t,i,s="#6366f1",o="#a855f7",a){n(this,"element");n(this,"chatWindow");n(this,"overlay");n(this,"voiceTrigger");this.onSendMessage=e,this.onStartCall=t,this.onHangup=i,this.primaryColor=s,this.secondaryColor=o,this.onCallEnded=a,this.element=document.createElement("div"),this.element.style.flex="1",this.element.style.display="flex",this.element.style.flexDirection="column",this.element.style.minHeight="0",this.element.style.position="relative"}setupChat(){this.chatWindow=new O(t=>this.onSendMessage(t));const e=this.chatWindow.getElement();e.style.flex="1",this.element.appendChild(e),this.injectVoiceTrigger(),this.overlay=new N(()=>this.onHangup(),this.primaryColor,this.secondaryColor,this.onCallEnded),this.element.appendChild(this.overlay.getElement())}injectVoiceTrigger(){const e=document.createElement("button");this.voiceTrigger=e,e.className="voice-btn-simple",e.innerHTML=`<div class="voice-btn-icon">${m.audioLines}</div>`,e.onclick=()=>this.onStartCall();const t=this.chatWindow.getElement().querySelector(".chat-input-area");t?t.insertBefore(this.voiceTrigger,t.firstChild):console.warn("VaniraSDK: Failed to inject voice trigger",{inputArea:t})}getElement(){return this.element}getChatWindow(){return this.chatWindow}setCallActive(e){e?(this.overlay.show(),this.chatWindow&&(this.chatWindow.getElement().style.display="none")):(this.overlay.hide(),this.chatWindow&&(this.chatWindow.getElement().style.display="flex"))}setStatus(e){this.overlay.setStatus(e)}setTranscription(e,t){this.overlay.setTranscription(e,t)}setVideoTrack(e){this.overlay.setVideoTrack(e)}}class oe extends W{constructor(e,t,i,s="#6366f1",o="#a855f7",a){super(e,t,i,s,o,a),this.setupChat()}}class ae extends V{constructor(t,i,s="#6366f1",o="#a855f7",a){super(t,i,s,o,a);n(this,"avatarView");n(this,"startCallBtn");n(this,"controlsContainer");this.element.style.display="flex",this.element.style.flexDirection="column",this.avatarView=new te;const r=this.avatarView.getElement();r.style.width="100%",r.style.maxWidth="300px",r.style.aspectRatio="1/1",r.style.borderRadius="16px",r.style.overflow="hidden",r.style.margin="auto",r.style.position="relative",this.element.appendChild(r),this.controlsContainer=document.createElement("div"),this.controlsContainer.className="widget-body",this.controlsContainer.style.position="absolute",this.controlsContainer.style.bottom="20px",this.controlsContainer.style.width="100%",this.controlsContainer.style.zIndex="10";const l=document.createElement("div");l.className="controls",this.startCallBtn=document.createElement("button"),this.startCallBtn.className="control-btn primary",this.startCallBtn.innerHTML=`${m.phone} <span>Start Call</span>`,this.startCallBtn.onclick=()=>this.onStartCall(),l.appendChild(this.startCallBtn),this.controlsContainer.appendChild(l),this.element.appendChild(this.controlsContainer),this.initOverlay(),this.overlay.setMode("avatar")}getAvatarView(){return this.avatarView}setCallActive(t){t&&this.overlay.setMode("avatar"),super.setCallActive(t),t?this.controlsContainer.style.display="none":this.controlsContainer.style.display="block"}}class re extends W{constructor(e,t,i,s="#6366f1",o="#a855f7",a){super(e,t,i,s,o,a),this.setupChat(),this.overlay.setMode("avatar")}injectVoiceTrigger(){const e=document.createElement("button");this.voiceTrigger=e,e.className="voice-btn-simple",e.style.overflow="hidden",e.style.padding="0",e.style.border="1.5px solid #e5e7eb",e.innerHTML=`
1104
+ `}}class V{constructor(e,t,i="#6366f1",s="#a855f7",o){n(this,"element");n(this,"overlay");n(this,"onStartCall");n(this,"onHangup");n(this,"primaryColor");n(this,"secondaryColor");n(this,"onCallEnded");this.onStartCall=e,this.onHangup=t,this.primaryColor=i,this.secondaryColor=s,this.onCallEnded=o,this.element=document.createElement("div"),this.element.style.height="100%",this.element.style.position="relative"}initOverlay(){this.overlay=new N(()=>this.onHangup(),this.primaryColor,this.secondaryColor,this.onCallEnded),this.element.appendChild(this.overlay.getElement())}getElement(){return this.element}setCallActive(e){e?this.overlay.show():this.overlay.hide()}setStatus(e){this.overlay.setStatus(e)}setTranscription(e,t){this.overlay.setTranscription(e,t)}setVideoTrack(e){this.overlay.setVideoTrack(e)}}class se extends V{constructor(t,i,s="#6366f1",o="#a855f7",a){super(t,i,s,o,a);n(this,"voiceOrb");this.element.style.background="#f9fafb",this.voiceOrb=new ie(()=>this.onStartCall()),this.element.appendChild(this.voiceOrb.getElement()),this.initOverlay()}}class ne{constructor(e){n(this,"element");n(this,"chatWindow");this.onSendMessage=e,this.element=document.createElement("div"),this.element.style.flex="1",this.element.style.width="100%",this.element.style.minHeight="0",this.element.style.display="flex",this.element.style.flexDirection="column",this.chatWindow=new U(t=>this.onSendMessage(t)),this.element.appendChild(this.chatWindow.getElement())}getElement(){return this.element}getChatWindow(){return this.chatWindow}}class W{constructor(e,t,i,s="#6366f1",o="#a855f7",a){n(this,"element");n(this,"chatWindow");n(this,"overlay");n(this,"voiceTrigger");this.onSendMessage=e,this.onStartCall=t,this.onHangup=i,this.primaryColor=s,this.secondaryColor=o,this.onCallEnded=a,this.element=document.createElement("div"),this.element.style.flex="1",this.element.style.display="flex",this.element.style.flexDirection="column",this.element.style.minHeight="0",this.element.style.position="relative"}setupChat(){this.chatWindow=new U(t=>this.onSendMessage(t));const e=this.chatWindow.getElement();e.style.flex="1",this.element.appendChild(e),this.injectVoiceTrigger(),this.overlay=new N(()=>this.onHangup(),this.primaryColor,this.secondaryColor,this.onCallEnded),this.element.appendChild(this.overlay.getElement())}injectVoiceTrigger(){const e=document.createElement("button");this.voiceTrigger=e,e.className="voice-btn-simple",e.innerHTML=`<div class="voice-btn-icon">${m.audioLines}</div>`,e.onclick=()=>this.onStartCall();const t=this.chatWindow.getElement().querySelector(".chat-input-area");t?t.insertBefore(this.voiceTrigger,t.firstChild):console.warn("VaniraSDK: Failed to inject voice trigger",{inputArea:t})}getElement(){return this.element}getChatWindow(){return this.chatWindow}setCallActive(e){e?(this.overlay.show(),this.chatWindow&&(this.chatWindow.getElement().style.display="none")):(this.overlay.hide(),this.chatWindow&&(this.chatWindow.getElement().style.display="flex"))}setStatus(e){this.overlay.setStatus(e)}setTranscription(e,t){this.overlay.setTranscription(e,t)}setVideoTrack(e){this.overlay.setVideoTrack(e)}}class oe extends W{constructor(e,t,i,s="#6366f1",o="#a855f7",a){super(e,t,i,s,o,a),this.setupChat()}}class ae extends V{constructor(t,i,s="#6366f1",o="#a855f7",a){super(t,i,s,o,a);n(this,"avatarView");n(this,"startCallBtn");n(this,"controlsContainer");this.element.style.display="flex",this.element.style.flexDirection="column",this.avatarView=new te;const r=this.avatarView.getElement();r.style.width="100%",r.style.maxWidth="300px",r.style.aspectRatio="1/1",r.style.borderRadius="16px",r.style.overflow="hidden",r.style.margin="auto",r.style.position="relative",this.element.appendChild(r),this.controlsContainer=document.createElement("div"),this.controlsContainer.className="widget-body",this.controlsContainer.style.position="absolute",this.controlsContainer.style.bottom="20px",this.controlsContainer.style.width="100%",this.controlsContainer.style.zIndex="10";const l=document.createElement("div");l.className="controls",this.startCallBtn=document.createElement("button"),this.startCallBtn.className="control-btn primary",this.startCallBtn.innerHTML=`${m.phone} <span>Start Call</span>`,this.startCallBtn.onclick=()=>this.onStartCall(),l.appendChild(this.startCallBtn),this.controlsContainer.appendChild(l),this.element.appendChild(this.controlsContainer),this.initOverlay(),this.overlay.setMode("avatar")}getAvatarView(){return this.avatarView}setCallActive(t){t&&this.overlay.setMode("avatar"),super.setCallActive(t),t?this.controlsContainer.style.display="none":this.controlsContainer.style.display="block"}}class re extends W{constructor(e,t,i,s="#6366f1",o="#a855f7",a){super(e,t,i,s,o,a),this.setupChat(),this.overlay.setMode("avatar")}injectVoiceTrigger(){const e=document.createElement("button");this.voiceTrigger=e,e.className="voice-btn-simple",e.style.overflow="hidden",e.style.padding="0",e.style.border="1.5px solid #e5e7eb",e.innerHTML=`
1092
1105
  <video
1093
1106
  src="https://www.simli.com/jenna.mp4"
1094
1107
  autoplay loop muted pip="false" playsinline
@@ -1097,14 +1110,14 @@ overflow: hidden;
1097
1110
  <div style="position: absolute; bottom: -2px; right: -2px; background: white; border-radius: 50%; padding: 2px; box-shadow: 0 1px 2px rgba(0,0,0,0.1);">
1098
1111
  ${m.audioLines.replace('width="24"','width="12"').replace('height="24"','height="12"')}
1099
1112
  </div>
1100
- `;const t=e.querySelector("div");if(t){const o=t.querySelector("svg");o&&(o.style.width="12px",o.style.height="12px")}e.onclick=()=>this.onStartCall();const i=this.chatWindow.getElement().querySelector(".chat-input-area"),s=i==null?void 0:i.querySelector(".chat-send-btn");i&&s?i.insertBefore(this.voiceTrigger,s):console.warn("VaniraSDK: Failed to inject voice trigger",{inputArea:i,sendBtn:s})}}class le{async sendMessage(e,t,i,s,o,a,r,l){return b.sendChatMessage(t,i,e,s,c=>{a&&a(c)},o,c=>{r&&c&&r(c)},l)}async sendFile(e){throw console.warn("sendFile not implemented for VaniraChatAdapter yet - Incompatible function adapted",e),new Error("Method not implemented.")}async likeDislike(e,t){console.warn("likeDislike not implemented for VaniraChatAdapter yet - Incompatible function adapted",e,t)}}const Q=class Q extends _{constructor(t){super(t);n(this,"vaniraClient",null);n(this,"currentView",null);n(this,"isPanelOpen",!1);n(this,"callActive",!1);n(this,"eventSource",null);n(this,"floatingButton",null);n(this,"floatingWelcomeChips",null);n(this,"panel",null);n(this,"welcomeChipsData",[]);n(this,"chatAdapter");n(this,"sessionManager",null);n(this,"sessionActive",!1);n(this,"widgetMode","voice_only");n(this,"agentId","");n(this,"prospectGroupId","");n(this,"chatServerUrl","");n(this,"prospectId","");n(this,"chatId",null);n(this,"widgetId","");n(this,"primaryColor","#6366f1");n(this,"secondaryColor","#4f46e5");n(this,"gradient",null);n(this,"position","bottom-right");n(this,"widgetIcon",null);this.chatAdapter=new le,this.processConfig(t)}initSessionManager(){const t=this.widgetId||this.agentId||"default";this.sessionManager=new k(t),this.sessionManager.on("tab_took_over",()=>{console.warn("[VaniraAI] Session taken over by another tab."),this.sessionActive=!1,this.showTabConflictBanner("taken_over")}),this.sessionManager.on("session_cleared",()=>{console.log("[VaniraAI] Session cleared externally.")});const i=this.sessionManager.claimSession();return this.sessionActive=i,i}restoreSessionMessages(){var l,c,A;const t=(l=this.sessionManager)==null?void 0:l.getSession();if(!t)return;const i=(A=(c=this.currentView)==null?void 0:c.getChatWindow)==null?void 0:A.call(c);if(!i)return;const s=t.messages.filter(d=>d.content.trim()!==""),o=`vanira_calls_${this.widgetId||this.agentId}`,a=JSON.parse(localStorage.getItem(o)||"[]");if(s.length===0&&a.length===0)return;i.clearMessages();const r=[...s.map((d,w)=>({type:"msg",role:d.role,content:d.content,ts:d.timestamp??w})),...a.map(d=>({type:"call",durationMs:d.durationMs,startedAt:d.startedAt,ts:d.startedAt}))];r.sort((d,w)=>d.ts-w.ts),r.forEach(d=>{d.type==="msg"?i.addMessage(d.role,d.content,d.ts):i.addCallRecord(d.durationMs,d.startedAt)}),console.log(`[VaniraAI] Restored ${s.length} messages + ${a.length} call records from session.`)}showTabConflictBanner(t){var i,s;this.root&&((i=this.root.querySelector(".vanira-tab-conflict-banner"))==null||i.remove(),t==="conflict"&&((s=this.sessionManager)==null||s.forceClaimSession(),this.sessionActive=!0,this.widgetMode.includes("chat")&&this.initializeChatSession(!1)))}playMessageSound(t){try{if(!Q.audioContext){const r=window.AudioContext||window.webkitAudioContext;if(!r)return;Q.audioContext=new r}const i=Q.audioContext;i.state==="suspended"&&i.resume().catch(()=>{});const s=i.createOscillator(),o=i.createGain();s.connect(o),o.connect(i.destination);const a=i.currentTime;t==="send"?(s.type="sine",s.frequency.setValueAtTime(300,a),s.frequency.exponentialRampToValueAtTime(500,a+.05),o.gain.setValueAtTime(0,a),o.gain.linearRampToValueAtTime(.1,a+.01),o.gain.exponentialRampToValueAtTime(.001,a+.1),s.start(a),s.stop(a+.1)):(s.type="sine",s.frequency.setValueAtTime(500,a),s.frequency.exponentialRampToValueAtTime(800,a+.1),o.gain.setValueAtTime(0,a),o.gain.linearRampToValueAtTime(.15,a+.02),o.gain.exponentialRampToValueAtTime(.001,a+.2),s.start(a),s.stop(a+.2))}catch(i){console.warn("[VaniraAI] Audio feedback failed",i)}}async initializeChatSession(t=!1){var i,s,o,a,r,l,c,A,d,w;if(this.sessionActive)try{b.setChatUrl(this.chatServerUrl);const u=(i=this.sessionManager)==null?void 0:i.getSession();if(!t&&(u!=null&&u.prospectId)){this.prospectId=u.prospectId,this.chatId=u.chatId,console.log(`[VaniraAI] Session restored — tab: ${(s=this.sessionManager)==null?void 0:s.getTabId()}, prospect: ${this.prospectId}`),this.restoreSessionMessages(),this.chatId&&!this.eventSource&&(this.eventSource=b.listenForAdminReplies(this.chatId,this.prospectId,C=>{var p,v,x;(v=(p=this.currentView)==null?void 0:p.getChatWindow)==null||v.call(p).addMessage("assistant",C),(x=this.sessionManager)==null||x.pushMessage("assistant",C),this.playMessageSound("receive")}));return}this.prospectGroupId?this.prospectId=await b.createChatProspect(this.prospectGroupId):this.prospectId=`anon_${Date.now()}_${Math.random().toString(36).substr(2,9)}`;const g=await b.fetchWelcomeMessage(this.agentId,this.prospectId,this.widgetId||void 0);if(g!=null&&g.chatId&&!this.chatId&&(this.chatId=g.chatId,this.eventSource||(this.eventSource=b.listenForAdminReplies(this.chatId,this.prospectId,C=>{var p,v,x;(v=(p=this.currentView)==null?void 0:p.getChatWindow)==null||v.call(p).addMessage("assistant",C),(x=this.sessionManager)==null||x.pushMessage("assistant",C),this.playMessageSound("receive")}))),(o=this.sessionManager)==null||o.saveIds(this.prospectId,this.chatId),g&&((a=this.currentView)!=null&&a.getChatWindow)){const C=this.currentView.getChatWindow();if(C.clearMessages(),g.widget)try{const p=JSON.parse(g.content),v=p.text||"";C.addMessage(g.role,v),(r=this.sessionManager)==null||r.pushMessage(g.role,v),p.buttons&&Array.isArray(p.buttons)&&(C.addButtons(p.buttons),this.welcomeChipsData=p.buttons),this.updateWelcomeChipsVisibility()}catch(p){console.error("Failed to parse welcome widget content",p),C.addMessage(g.role,g.content),(l=this.sessionManager)==null||l.pushMessage(g.role,g.content)}else C.addMessage(g.role,g.content),(c=this.sessionManager)==null||c.pushMessage(g.role,g.content)}}catch(u){console.error("[VaniraAI] Chat init failed",u);const g="Hello! How can I help you today?";(d=(A=this.currentView)==null?void 0:A.getChatWindow)==null||d.call(A).addMessage("assistant",g),(w=this.sessionManager)==null||w.pushMessage("assistant",g)}}async initialize(t){await super.initialize(t),this.processConfig(t),this.root&&this.ui_renderer(this.root)}processConfig(t){var i;this.widgetId=t.widgetId||t.widget_id||"",this.agentId=t.agentId||t.agent_id||"",this.prospectGroupId=t.prospectGroupId||((i=t.client)==null?void 0:i.base_prospect_group_id)||"",this.widgetMode=t.widgetMode||t.mode||"voice_only",this.widgetId=t.widgetId||t.widget_id||"",this.primaryColor=t.primaryColor||"#6366f1",this.secondaryColor=t.secondaryColor||t.primaryColor||"#4f46e5",this.gradient=t.gradient||null,this.position=t.position||"bottom-right",this.widgetIcon=t.widgetIcon||t.icon||null,this.chatServerUrl=t.serverUrl||t.chatServerUrl||"https://inboxapi.travelr.club"}async create_call(){var t;if(!(this.callActive||!this.agentId)){this.sessionActive||((t=this.sessionManager)==null||t.forceClaimSession(),this.sessionActive=!0);try{this.callActive=!0,this.updateViewCallState(!0),this.updateViewStatus("connecting");const i=await b.createCall(this.agentId,null,this.prospectId||null,this.widgetMode),s=new Y({agentId:this.agentId,callId:i.callId,serverUrl:i.workerUrl});s.on("connected",()=>this.updateViewStatus("connected")).on("disconnected",()=>this.end_call()).on("error",o=>{console.error("[VaniraAI Widget] Call error:",o),this.updateViewStatus("error")}).on("transcription",({text:o,isFinal:a})=>{var r,l;(l=(r=this.currentView)==null?void 0:r.setTranscription)==null||l.call(r,o,a)}).on("track",({track:o})=>{var a;this.widgetMode.includes("avatar")&&o.kind==="video"&&((a=this.currentView)!=null&&a.setVideoTrack)&&this.currentView.setVideoTrack(o)}).on("tool_call",o=>{var r,l;const a=new CustomEvent("vaniraai:tool_call",{detail:o,bubbles:!0,composed:!0});(l=(r=this.root)==null?void 0:r.host)==null||l.dispatchEvent(a),console.log("[VaniraAI Widget] Tool call dispatched:",o.name,o.arguments),o.execution_mode}),this.vaniraClient=s,await s.start()}catch(i){console.error("[VaniraAI Widget] Call failed",i),this.updateViewStatus("error")}}}end_call(){this.callActive=!1;const t=this.vaniraClient;this.vaniraClient=null,t&&t.stop(),this.updateViewCallState(!1)}updateViewCallState(t){var i;(i=this.currentView)!=null&&i.setCallActive&&this.currentView.setCallActive(t)}updateViewStatus(t){var i;(i=this.currentView)!=null&&i.setStatus&&this.currentView.setStatus(t)}ui_renderer(t){this.root=t,this.root.innerHTML="";const i=document.createElement("style");i.textContent=`@keyframes vanira-slide-up {
1113
+ `;const t=e.querySelector("div");if(t){const o=t.querySelector("svg");o&&(o.style.width="12px",o.style.height="12px")}e.onclick=()=>this.onStartCall();const i=this.chatWindow.getElement().querySelector(".chat-input-area"),s=i==null?void 0:i.querySelector(".chat-send-btn");i&&s?i.insertBefore(this.voiceTrigger,s):console.warn("VaniraSDK: Failed to inject voice trigger",{inputArea:i,sendBtn:s})}}class le{async sendMessage(e,t,i,s,o,a,r,l){return B.sendChatMessage(t,i,e,s,c=>{a&&a(c)},o,c=>{r&&c&&r(c)},l)}async sendFile(e){throw console.warn("sendFile not implemented for VaniraChatAdapter yet - Incompatible function adapted",e),new Error("Method not implemented.")}async likeDislike(e,t){console.warn("likeDislike not implemented for VaniraChatAdapter yet - Incompatible function adapted",e,t)}}const Q=class Q extends _{constructor(t){super(t);n(this,"vaniraClient",null);n(this,"currentView",null);n(this,"isPanelOpen",!1);n(this,"callActive",!1);n(this,"eventSource",null);n(this,"floatingButton",null);n(this,"floatingWelcomeChips",null);n(this,"panel",null);n(this,"welcomeChipsData",[]);n(this,"chatAdapter");n(this,"sessionManager",null);n(this,"sessionActive",!1);n(this,"widgetMode","voice_only");n(this,"agentId","");n(this,"prospectGroupId","");n(this,"chatServerUrl","");n(this,"prospectId","");n(this,"chatId",null);n(this,"widgetId","");n(this,"primaryColor","#6366f1");n(this,"secondaryColor","#4f46e5");n(this,"gradient",null);n(this,"position","bottom-right");n(this,"widgetIcon",null);this.chatAdapter=new le,this.processConfig(t)}initSessionManager(){const t=this.widgetId||this.agentId||"default";this.sessionManager=new k(t),this.sessionManager.on("tab_took_over",()=>{console.warn("[VaniraAI] Session taken over by another tab."),this.sessionActive=!1,this.showTabConflictBanner("taken_over")}),this.sessionManager.on("session_cleared",()=>{console.log("[VaniraAI] Session cleared externally.")});const i=this.sessionManager.claimSession();return this.sessionActive=i,i}restoreSessionMessages(){var l,c,A;const t=(l=this.sessionManager)==null?void 0:l.getSession();if(!t)return;const i=(A=(c=this.currentView)==null?void 0:c.getChatWindow)==null?void 0:A.call(c);if(!i)return;const s=t.messages.filter(d=>d.content.trim()!==""),o=`vanira_calls_${this.widgetId||this.agentId}`,a=JSON.parse(localStorage.getItem(o)||"[]");if(s.length===0&&a.length===0)return;i.clearMessages();const r=[...s.map((d,w)=>({type:"msg",role:d.role,content:d.content,ts:d.timestamp??w})),...a.map(d=>({type:"call",durationMs:d.durationMs,startedAt:d.startedAt,ts:d.startedAt}))];r.sort((d,w)=>d.ts-w.ts),r.forEach(d=>{d.type==="msg"?i.addMessage(d.role,d.content,d.ts):i.addCallRecord(d.durationMs,d.startedAt)}),console.log(`[VaniraAI] Restored ${s.length} messages + ${a.length} call records from session.`)}showTabConflictBanner(t){var i,s;this.root&&((i=this.root.querySelector(".vanira-tab-conflict-banner"))==null||i.remove(),t==="conflict"&&((s=this.sessionManager)==null||s.forceClaimSession(),this.sessionActive=!0,this.widgetMode.includes("chat")&&this.initializeChatSession(!1)))}playMessageSound(t){try{if(!Q.audioContext){const r=window.AudioContext||window.webkitAudioContext;if(!r)return;Q.audioContext=new r}const i=Q.audioContext;i.state==="suspended"&&i.resume().catch(()=>{});const s=i.createOscillator(),o=i.createGain();s.connect(o),o.connect(i.destination);const a=i.currentTime;t==="send"?(s.type="sine",s.frequency.setValueAtTime(300,a),s.frequency.exponentialRampToValueAtTime(500,a+.05),o.gain.setValueAtTime(0,a),o.gain.linearRampToValueAtTime(.1,a+.01),o.gain.exponentialRampToValueAtTime(.001,a+.1),s.start(a),s.stop(a+.1)):(s.type="sine",s.frequency.setValueAtTime(500,a),s.frequency.exponentialRampToValueAtTime(800,a+.1),o.gain.setValueAtTime(0,a),o.gain.linearRampToValueAtTime(.15,a+.02),o.gain.exponentialRampToValueAtTime(.001,a+.2),s.start(a),s.stop(a+.2))}catch(i){console.warn("[VaniraAI] Audio feedback failed",i)}}async initializeChatSession(t=!1){var i,s,o,a,r,l,c,A,d,w;if(this.sessionActive)try{B.setChatUrl(this.chatServerUrl);const u=(i=this.sessionManager)==null?void 0:i.getSession();if(!t&&(u!=null&&u.prospectId)){this.prospectId=u.prospectId,this.chatId=u.chatId,console.log(`[VaniraAI] Session restored — tab: ${(s=this.sessionManager)==null?void 0:s.getTabId()}, prospect: ${this.prospectId}`),this.restoreSessionMessages(),this.chatId&&!this.eventSource&&(this.eventSource=B.listenForAdminReplies(this.chatId,this.prospectId,C=>{var p,v,x;(v=(p=this.currentView)==null?void 0:p.getChatWindow)==null||v.call(p).addMessage("assistant",C),(x=this.sessionManager)==null||x.pushMessage("assistant",C),this.playMessageSound("receive")}));return}this.prospectGroupId?this.prospectId=await B.createChatProspect(this.prospectGroupId):this.prospectId=`anon_${Date.now()}_${Math.random().toString(36).substr(2,9)}`;const g=await B.fetchWelcomeMessage(this.agentId,this.prospectId,this.widgetId||void 0);if(g!=null&&g.chatId&&!this.chatId&&(this.chatId=g.chatId,this.eventSource||(this.eventSource=B.listenForAdminReplies(this.chatId,this.prospectId,C=>{var p,v,x;(v=(p=this.currentView)==null?void 0:p.getChatWindow)==null||v.call(p).addMessage("assistant",C),(x=this.sessionManager)==null||x.pushMessage("assistant",C),this.playMessageSound("receive")}))),(o=this.sessionManager)==null||o.saveIds(this.prospectId,this.chatId),g&&((a=this.currentView)!=null&&a.getChatWindow)){const C=this.currentView.getChatWindow();if(C.clearMessages(),g.widget)try{const p=JSON.parse(g.content),v=p.text||"";C.addMessage(g.role,v),(r=this.sessionManager)==null||r.pushMessage(g.role,v),p.buttons&&Array.isArray(p.buttons)&&(C.addButtons(p.buttons),this.welcomeChipsData=p.buttons),this.updateWelcomeChipsVisibility()}catch(p){console.error("Failed to parse welcome widget content",p),C.addMessage(g.role,g.content),(l=this.sessionManager)==null||l.pushMessage(g.role,g.content)}else C.addMessage(g.role,g.content),(c=this.sessionManager)==null||c.pushMessage(g.role,g.content)}}catch(u){console.error("[VaniraAI] Chat init failed",u);const g="Hello! How can I help you today?";(d=(A=this.currentView)==null?void 0:A.getChatWindow)==null||d.call(A).addMessage("assistant",g),(w=this.sessionManager)==null||w.pushMessage("assistant",g)}}async initialize(t){await super.initialize(t),this.processConfig(t),this.root&&this.ui_renderer(this.root)}processConfig(t){var i;this.widgetId=t.widgetId||t.widget_id||"",this.agentId=t.agentId||t.agent_id||"",this.prospectGroupId=t.prospectGroupId||((i=t.client)==null?void 0:i.base_prospect_group_id)||"",this.widgetMode=t.widgetMode||t.mode||"voice_only",this.widgetId=t.widgetId||t.widget_id||"",this.primaryColor=t.primaryColor||"#6366f1",this.secondaryColor=t.secondaryColor||t.primaryColor||"#4f46e5",this.gradient=t.gradient||null,this.position=t.position||"bottom-right",this.widgetIcon=t.widgetIcon||t.icon||null,this.chatServerUrl=t.serverUrl||t.chatServerUrl||"https://inboxapi.travelr.club"}async create_call(){var t;if(!(this.callActive||!this.agentId)){this.sessionActive||((t=this.sessionManager)==null||t.forceClaimSession(),this.sessionActive=!0);try{this.callActive=!0,this.updateViewCallState(!0),this.updateViewStatus("connecting");const i=await B.createCall(this.agentId,null,this.prospectId||null,this.widgetMode),s=new Y({agentId:this.agentId,callId:i.callId,serverUrl:i.workerUrl});s.on("connected",()=>this.updateViewStatus("connected")).on("disconnected",()=>this.end_call()).on("error",o=>{console.error("[VaniraAI Widget] Call error:",o),this.updateViewStatus("error")}).on("transcription",({text:o,isFinal:a})=>{var r,l;(l=(r=this.currentView)==null?void 0:r.setTranscription)==null||l.call(r,o,a)}).on("track",({track:o})=>{var a;this.widgetMode.includes("avatar")&&o.kind==="video"&&((a=this.currentView)!=null&&a.setVideoTrack)&&this.currentView.setVideoTrack(o)}).on("tool_call",o=>{var r,l;const a=new CustomEvent("vaniraai:tool_call",{detail:o,bubbles:!0,composed:!0});(l=(r=this.root)==null?void 0:r.host)==null||l.dispatchEvent(a),console.log("[VaniraAI Widget] Tool call dispatched:",o.name,o.arguments),o.execution_mode}),this.vaniraClient=s,await s.start()}catch(i){console.error("[VaniraAI Widget] Call failed",i),this.updateViewStatus("error")}}}end_call(){this.callActive=!1;const t=this.vaniraClient;this.vaniraClient=null,t&&t.stop(),this.updateViewCallState(!1)}updateViewCallState(t){var i;(i=this.currentView)!=null&&i.setCallActive&&this.currentView.setCallActive(t)}updateViewStatus(t){var i;(i=this.currentView)!=null&&i.setStatus&&this.currentView.setStatus(t)}ui_renderer(t){this.root=t,this.root.innerHTML="";const i=document.createElement("style");i.textContent=`@keyframes vanira-slide-up {
1101
1114
  from { opacity:0; transform:translateY(16px); }
1102
1115
  to { opacity:1; transform:translateY(0); }
1103
1116
  }`,this.root.appendChild(i);const s=document.createElement("style");s.textContent=`
1104
1117
  ${ee}
1105
1118
  :host { ${$(this.primaryColor,this.secondaryColor)} }
1106
1119
  ${R.styles}
1107
- ${U.styles}
1120
+ ${O.styles}
1108
1121
  ${j.styles}
1109
1122
  ${this.gradient?`.widget-fab { background: ${this.gradient} !important; }`:""}
1110
- `,this.root.appendChild(s),this.floatingButton=new R(()=>this.togglePanel()),this.floatingButton.setIcon(this.getFabIcon()),this.floatingButton.setPosition(this.getPosStyle()),this.floatingWelcomeChips=new U(a=>this.handleFloatingChipClick(a)),this.floatingWelcomeChips.setPosition(this.getPosStyle()),this.panel=new j(()=>this.closePanel(),this.getPanelTitle()),this.root.appendChild(this.floatingWelcomeChips.getElement()),this.root.appendChild(this.floatingButton.getElement()),this.root.appendChild(this.panel.getElement()),this.setupPanelContent(),this.initSessionManager()?this.widgetMode.includes("chat")&&this.initializeChatSession():this.showTabConflictBanner("conflict")}getFabIcon(){return this.widgetIcon&&T[this.widgetIcon]?T[this.widgetIcon]:this.widgetMode.includes("chat")?m.chat:m.audioLines}getPanelTitle(){return"Assistant"}getPosStyle(){const t={"bottom-right":"bottom: 24px; right: 24px;","bottom-left":"bottom: 24px; left: 24px;","top-right":"top: 24px; right: 24px;","top-left":"top: 24px; left: 24px;"};return t[this.position]||t["bottom-right"]}setupPanelContent(){const t=(i,s)=>{var l,c;const o=(c=(l=this.currentView)==null?void 0:l.getChatWindow)==null?void 0:c.call(l);o&&o.addCallRecord(i,s);const a=`vanira_calls_${this.widgetId||this.agentId}`,r=JSON.parse(localStorage.getItem(a)||"[]");r.push({durationMs:i,startedAt:s}),r.length>50&&r.splice(0,r.length-50),localStorage.setItem(a,JSON.stringify(r))};switch(this.widgetMode){case"chat_only":this.currentView=new ne(i=>this.handleChatSend(i));break;case"chat_voice":this.currentView=new oe(i=>this.handleChatSend(i),()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,t);break;case"avatar_only":this.currentView=new ae(()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,t);break;case"chat_avatar":this.currentView=new re(i=>this.handleChatSend(i),()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,t);break;case"voice_only":default:this.currentView=new se(()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,t);break}this.currentView&&this.panel&&this.panel.setContent(this.currentView.getElement())}async handleChatSend(t){var s,o,a,r,l;if(!t)return;this.sessionActive||((s=this.sessionManager)==null||s.forceClaimSession(),this.sessionActive=!0,this.widgetMode.includes("chat")&&await this.initializeChatSession(!1));const i=(a=(o=this.currentView)==null?void 0:o.getChatWindow)==null?void 0:a.call(o);if(i){this.chatId&&!this.eventSource&&(this.eventSource=b.listenForAdminReplies(this.chatId,this.prospectId,c=>{var A,d,w;(d=(A=this.currentView)==null?void 0:A.getChatWindow)==null||d.call(A).addMessage("assistant",c),(w=this.sessionManager)==null||w.pushMessage("assistant",c),this.playMessageSound("receive")})),i.addMessage("user",t),(r=this.sessionManager)==null||r.pushMessage("user",t),i.setTyping(!0),(l=this.sessionManager)==null||l.pushMessage("assistant","");try{let c=!1;await this.chatAdapter.sendMessage(t,this.agentId,this.prospectId,this.chatId,A=>{var d;c||(this.playMessageSound("receive"),c=!0),i.setTyping(!1),(A==null?void 0:A.type)==="button_list"&&((d=A.data)!=null&&d.buttons)&&(i.addButtons(A.data.buttons),this.welcomeChipsData=A.data.buttons,this.updateWelcomeChipsVisibility())},A=>{var d;c||(this.playMessageSound("receive"),c=!0),i.setTyping(!1),i.updateLastAssistantMessage(A),(d=this.sessionManager)==null||d.updateLastAssistantMessage(A)},A=>{var d;A&&(this.chatId=A,(d=this.sessionManager)==null||d.saveIds(this.prospectId,A))})}catch(c){i.setTyping(!1),console.error("[VaniraAI] Send message failed",c),i.addMessage("assistant","Error sending message.")}}}togglePanel(){this.isPanelOpen?this.closePanel():this.openPanel()}openPanel(){var t,i;this.isPanelOpen=!0,this.updateWelcomeChipsVisibility(),(t=this.panel)==null||t.open({bottom:this.position.includes("bottom")?"100px":void 0,top:this.position.includes("top")?"100px":void 0,right:this.position.includes("right")?"24px":void 0,left:this.position.includes("left")?"24px":void 0}),(i=this.root)!=null&&i.host&&this.root.host.classList.add("vanira-panel-open")}closePanel(){var t,i;this.isPanelOpen=!1,this.updateWelcomeChipsVisibility(),(t=this.panel)==null||t.close(),(i=this.root)!=null&&i.host&&this.root.host.classList.remove("vanira-panel-open")}updateWelcomeChipsVisibility(){this.floatingWelcomeChips&&(!this.isPanelOpen&&this.welcomeChipsData.length>0?(this.floatingWelcomeChips.setChips(this.welcomeChipsData),this.floatingWelcomeChips.getElement().style.display="flex"):this.floatingWelcomeChips.getElement().style.display="none")}handleFloatingChipClick(t){this.openPanel(),this.handleChatSend(t)}};n(Q,"audioContext",null);let S=Q;class Ae{static getProvider(e){return new S(e)}}class ce extends HTMLElement{constructor(){super();n(this,"shadow");n(this,"provider",null);n(this,"widgetId","");n(this,"agentId","");n(this,"serverUrl","https://inboxapi.travelr.club");n(this,"position","bottom-right");n(this,"primaryColor","#6366f1");n(this,"secondaryColor","#4f46e5");n(this,"gradient",null);this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["widget-id","agent-id","position","primary-color","secondary-color","server-url","gradient"]}connectedCallback(){console.log("[VaniraAI Widget] Initializing..."),this.readAttributes();const t={widgetId:this.widgetId,agentId:this.agentId,serverUrl:this.serverUrl,position:this.position,primaryColor:this.primaryColor,secondaryColor:this.secondaryColor,gradient:this.gradient};this.provider=Ae.getProvider(t),this.provider&&this.provider.ui_renderer(this.shadow),this.widgetId&&!this.agentId&&this.initializeExpandedConfig()}readAttributes(){this.widgetId=this.getAttribute("widget-id")||"",this.agentId=this.getAttribute("agent-id")||"",this.serverUrl=this.getAttribute("server-url")||"https://inboxapi.travelr.club",this.position=this.getAttribute("position")||"bottom-right",this.primaryColor=this.getAttribute("primary-color")||"#6366f1",this.secondaryColor=this.getAttribute("secondary-color")||this.primaryColor,this.gradient=this.getAttribute("gradient")}async initializeExpandedConfig(){try{const t=await H.fetchWidgetConfig(this.widgetId);this.provider&&await this.provider.initialize(t)}catch(t){console.error("[VaniraAI Widget] Config failed:",t)}}}f.ChatService=b,f.ConfigService=H,f.SessionManager=k,f.VaniraAI=Y,f.VaniraWidget=ce,f.WebRTCClient=B,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});
1123
+ `,this.root.appendChild(s),this.floatingButton=new R(()=>this.togglePanel()),this.floatingButton.setIcon(this.getFabIcon()),this.floatingButton.setPosition(this.getPosStyle()),this.floatingWelcomeChips=new O(a=>this.handleFloatingChipClick(a)),this.floatingWelcomeChips.setPosition(this.getPosStyle()),this.panel=new j(()=>this.closePanel(),this.getPanelTitle()),this.root.appendChild(this.floatingWelcomeChips.getElement()),this.root.appendChild(this.floatingButton.getElement()),this.root.appendChild(this.panel.getElement()),this.setupPanelContent(),this.initSessionManager()?this.widgetMode.includes("chat")&&this.initializeChatSession():this.showTabConflictBanner("conflict")}getFabIcon(){return this.widgetIcon&&T[this.widgetIcon]?T[this.widgetIcon]:this.widgetMode.includes("chat")?m.chat:m.voice_orb}getPanelTitle(){return"Assistant"}getPosStyle(){const t={"bottom-right":"bottom: 24px; right: 24px;","bottom-left":"bottom: 24px; left: 24px;","top-right":"top: 24px; right: 24px;","top-left":"top: 24px; left: 24px;"};return t[this.position]||t["bottom-right"]}setupPanelContent(){const t=(i,s)=>{var l,c;const o=(c=(l=this.currentView)==null?void 0:l.getChatWindow)==null?void 0:c.call(l);o&&o.addCallRecord(i,s);const a=`vanira_calls_${this.widgetId||this.agentId}`,r=JSON.parse(localStorage.getItem(a)||"[]");r.push({durationMs:i,startedAt:s}),r.length>50&&r.splice(0,r.length-50),localStorage.setItem(a,JSON.stringify(r))};switch(this.widgetMode){case"chat_only":this.currentView=new ne(i=>this.handleChatSend(i));break;case"chat_voice":this.currentView=new oe(i=>this.handleChatSend(i),()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,t);break;case"avatar_only":this.currentView=new ae(()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,t);break;case"chat_avatar":this.currentView=new re(i=>this.handleChatSend(i),()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,t);break;case"voice_only":default:this.currentView=new se(()=>this.create_call(),()=>this.end_call(),this.primaryColor,this.secondaryColor,t);break}this.currentView&&this.panel&&this.panel.setContent(this.currentView.getElement())}async handleChatSend(t){var s,o,a,r,l;if(!t)return;this.sessionActive||((s=this.sessionManager)==null||s.forceClaimSession(),this.sessionActive=!0,this.widgetMode.includes("chat")&&await this.initializeChatSession(!1));const i=(a=(o=this.currentView)==null?void 0:o.getChatWindow)==null?void 0:a.call(o);if(i){this.chatId&&!this.eventSource&&(this.eventSource=B.listenForAdminReplies(this.chatId,this.prospectId,c=>{var A,d,w;(d=(A=this.currentView)==null?void 0:A.getChatWindow)==null||d.call(A).addMessage("assistant",c),(w=this.sessionManager)==null||w.pushMessage("assistant",c),this.playMessageSound("receive")})),i.addMessage("user",t),(r=this.sessionManager)==null||r.pushMessage("user",t),i.setTyping(!0),(l=this.sessionManager)==null||l.pushMessage("assistant","");try{let c=!1;await this.chatAdapter.sendMessage(t,this.agentId,this.prospectId,this.chatId,A=>{var d;c||(this.playMessageSound("receive"),c=!0),i.setTyping(!1),(A==null?void 0:A.type)==="button_list"&&((d=A.data)!=null&&d.buttons)&&(i.addButtons(A.data.buttons),this.welcomeChipsData=A.data.buttons,this.updateWelcomeChipsVisibility())},A=>{var d;c||(this.playMessageSound("receive"),c=!0),i.setTyping(!1),i.updateLastAssistantMessage(A),(d=this.sessionManager)==null||d.updateLastAssistantMessage(A)},A=>{var d;A&&(this.chatId=A,(d=this.sessionManager)==null||d.saveIds(this.prospectId,A))})}catch(c){i.setTyping(!1),console.error("[VaniraAI] Send message failed",c),i.addMessage("assistant","Error sending message.")}}}togglePanel(){this.isPanelOpen?this.closePanel():this.openPanel()}openPanel(){var t,i;this.isPanelOpen=!0,this.updateWelcomeChipsVisibility(),(t=this.panel)==null||t.open({bottom:this.position.includes("bottom")?"100px":void 0,top:this.position.includes("top")?"100px":void 0,right:this.position.includes("right")?"24px":void 0,left:this.position.includes("left")?"24px":void 0}),(i=this.root)!=null&&i.host&&this.root.host.classList.add("vanira-panel-open")}closePanel(){var t,i;this.isPanelOpen=!1,this.updateWelcomeChipsVisibility(),(t=this.panel)==null||t.close(),(i=this.root)!=null&&i.host&&this.root.host.classList.remove("vanira-panel-open")}updateWelcomeChipsVisibility(){this.floatingWelcomeChips&&(!this.isPanelOpen&&this.welcomeChipsData.length>0?(this.floatingWelcomeChips.setChips(this.welcomeChipsData),this.floatingWelcomeChips.getElement().style.display="flex"):this.floatingWelcomeChips.getElement().style.display="none")}handleFloatingChipClick(t){this.openPanel(),this.handleChatSend(t)}};n(Q,"audioContext",null);let S=Q;class Ae{static getProvider(e){return new S(e)}}class ce extends HTMLElement{constructor(){super();n(this,"shadow");n(this,"provider",null);n(this,"widgetId","");n(this,"agentId","");n(this,"serverUrl","https://inboxapi.travelr.club");n(this,"position","bottom-right");n(this,"primaryColor","#6366f1");n(this,"secondaryColor","#4f46e5");n(this,"gradient",null);this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["widget-id","agent-id","position","primary-color","secondary-color","server-url","gradient"]}connectedCallback(){console.log("[VaniraAI Widget] Initializing..."),this.readAttributes();const t={widgetId:this.widgetId,agentId:this.agentId,serverUrl:this.serverUrl,position:this.position,primaryColor:this.primaryColor,secondaryColor:this.secondaryColor,gradient:this.gradient};this.provider=Ae.getProvider(t),this.provider&&this.provider.ui_renderer(this.shadow),this.widgetId&&!this.agentId&&this.initializeExpandedConfig()}readAttributes(){this.widgetId=this.getAttribute("widget-id")||"",this.agentId=this.getAttribute("agent-id")||"",this.serverUrl=this.getAttribute("server-url")||"https://inboxapi.travelr.club",this.position=this.getAttribute("position")||"bottom-right",this.primaryColor=this.getAttribute("primary-color")||"#6366f1",this.secondaryColor=this.getAttribute("secondary-color")||this.primaryColor,this.gradient=this.getAttribute("gradient")}async initializeExpandedConfig(){try{const t=await H.fetchWidgetConfig(this.widgetId);this.provider&&await this.provider.initialize(t)}catch(t){console.error("[VaniraAI Widget] Config failed:",t)}}}f.ChatService=B,f.ConfigService=H,f.SessionManager=k,f.VaniraAI=Y,f.VaniraWidget=ce,f.WebRTCClient=b,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});