guideai-app 0.2.9 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"GuideAI.js","mappings":"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","sources":["webpack://GuideAI/webpack/universalModuleDefinition","webpack://GuideAI/./src/styles/GuideAI.styles.ts","webpack://GuideAI/./src/utils/messageStorage.ts","webpack://GuideAI/./src/utils/constants.ts","webpack://GuideAI/external umd {\"commonjs\":\"react\",\"commonjs2\":\"react\",\"amd\":\"React\",\"root\":\"React\"}","webpack://GuideAI/./src/utils/api.ts","webpack://GuideAI/./src/GuideAI.tsx","webpack://GuideAI/./src/utils/ui.ts","webpack://GuideAI/./src/components/TranscriptBox.tsx","webpack://GuideAI/./src/components/Onboarding.tsx","webpack://GuideAI/./src/components/WelcomeBubble.tsx","webpack://GuideAI/./src/metric/event-listner.tsx","webpack://GuideAI/./src/utils/highlight.ts","webpack://GuideAI/./src/metric/metadata-tracker.tsx","webpack://GuideAI/./src/metric/index.tsx","webpack://GuideAI/webpack/bootstrap","webpack://GuideAI/webpack/startup"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"react\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"React\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"GuideAI\"] = factory(require(\"react\"));\n\telse\n\t\troot[\"GuideAI\"] = factory(root[\"React\"]);\n})(this, (__WEBPACK_EXTERNAL_MODULE__156__) => {\nreturn ","export const guideAIStyles = `\n.guideai-main-ui {\n position: relative;\n}\n\n.guideai-main-controls {\n display: flex;\n align-items: center;\n gap: 12px;\n position: relative;\n}\n\n.guideai-welcome-bubble {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n background: #0066ff;\n color: white;\n padding: 10px 16px;\n border-radius: 20px;\n font-size: 14px;\n white-space: normal;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n animation: bubble-pulse 2s infinite;\n max-width: 280px;\n min-width: 200px;\n text-align: center;\n line-height: 1.3;\n}\n\n.guideai-welcome-bubble.above {\n bottom: calc(100% + 10px);\n}\n\n.guideai-welcome-bubble.below {\n top: calc(100% + 10px);\n}\n\n.guideai-welcome-bubble.above::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-top: 8px solid #0066ff;\n}\n\n.guideai-welcome-bubble.below::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid #0066ff;\n}\n\n@keyframes bubble-pulse {\n 0% { transform: translateX(-50%) scale(1); }\n 50% { transform: translateX(-50%) scale(1.05); }\n 100% { transform: translateX(-50%) scale(1); }\n}\n\n.guideai-icon-wrapper {\n width: 50px;\n height: 50px;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255, 0.9);\n border: 2px solid transparent;\n border-radius: 50%;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.guideai-icon-wrapper:not(.initializing):hover {\n transform: scale(1.1);\n}\n\n.guideai-icon-wrapper.initializing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(128, 128, 128, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: guideai-spin 1.5s linear infinite;\n opacity: 0.7;\n cursor: default;\n}\n\n.guideai-icon-wrapper.recording {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: guideai-pulse 1s infinite alternate;\n}\n\n.guideai-icon-wrapper.processing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(255, 165, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: guideai-spin 1s linear infinite;\n}\n\n.guideai-icon-wrapper.playing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(0, 128, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n}\n\n@keyframes guideai-pulse {\n 0% { transform: scale(1); }\n 100% { transform: scale(1.05); }\n}\n\n@keyframes guideai-spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n@keyframes click-ripple-animation {\n 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }\n 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.6; }\n 100% { transform: translate(-50%, -50%) scale(2.5); opacity: 0; }\n}\n\n@keyframes click-dot-animation {\n 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }\n 60% { transform: translate(-50%, -50%) scale(1); opacity: 1; }\n 100% { transform: translate(-50%, -50%) scale(1); opacity: 0; }\n}\n\n@keyframes cursor-jiggle {\n 0% { transform: translate(-50%, 0) scale(1); }\n 25% { transform: translate(-50%, -5px) scale(1.1); }\n 50% { transform: translate(-50%, 0) scale(1); }\n 75% { transform: translate(-50%, 5px) scale(1.1); }\n 100% { transform: translate(-50%, 0) scale(1); filter: drop-shadow(0 0 8px #0066ff); }\n}\n\n.guideai-icon {\n width: 60%;\n height: 60%;\n min-width: 16px;\n min-height: 16px;\n max-width: 40px;\n max-height: 40px;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n\n.guideai-icon.initializing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"%23808080\" d=\"M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z\"/></svg>');\n}\n\n.guideai-icon.microphone {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 352 512\"><path fill=\"%230000FF\" d=\"M176 352c53.02 0 96-42.98 96-96V96c0-53.02-42.98-96-96-96S80 42.98 80 96v160c0 53.02 42.98 96 96 96zm160-160h-16c-8.84 0-16 7.16-16 16v48c0 74.8-64.49 134.82-140.79 127.38C96.71 376.89 48 317.11 48 250.3V208c0-8.84-7.16-16-16-16H16c-8.84 0-16 7.16-16 16v40.16c0 89.64 63.97 169.55 152 181.69V464H96c-8.84 0-16 7.16-16 16v16c0 8.84 7.16 16 16 16h160c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16h-56v-33.77C285.71 418.47 352 344.9 352 256v-48c0-8.84-7.16-16-16-16z\"/></svg>');\n}\n\n.guideai-icon.recording {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><circle cx=\"256\" cy=\"256\" r=\"128\" fill=\"%23FF0000\"/><circle cx=\"256\" cy=\"256\" r=\"200\" stroke=\"%23FF0000\" stroke-width=\"20\" fill=\"none\"/></svg>');\n}\n\n.guideai-icon.processing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"%23FFA500\" d=\"M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z\"/></svg>');\n}\n\n.guideai-icon.playing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"%23008000\" d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/></svg>');\n}\n\n.guideai-icon.text-mode {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"%230066ff\" d=\"M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4l4 4 4-4h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM7 10v2h2v-2H7zm6 2h-2v-2h2v2zm4 0h-2v-2h2v2z\"/></svg>');\n}\n\n.guideai-icon.voice-mode {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 352 512\"><path fill=\"%23008000\" d=\"M176 352c53.02 0 96-42.98 96-96V96c0-53.02-42.98-96-96-96S80 42.98 80 96v160c0 53.02 42.98 96 96 96zm160-160h-16c-8.84 0-16 7.16-16 16v48c0 74.8-64.49 134.82-140.79 127.38C96.71 376.89 48 317.11 48 250.3V208c0-8.84-7.16-16-16-16H16c-8.84 0-16 7.16-16 16v40.16c0 89.64 63.97 169.55 152 181.69V464H96c-8.84 0-16 7.16-16 16v16c0 8.84 7.16 16 16 16h160c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16h-56v-33.77C285.71 418.47 352 344.9 352 256v-48c0-8.84-7.16-16-16-16z\"/></svg>');\n}\n\n\n/* Onboarding styles */\n.guideai-onboarding {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n width: 300px;\n max-width: 90vw;\n z-index: 1002;\n animation: onboarding-fade-in 0.3s ease-out;\n}\n\n.guideai-onboarding.above {\n bottom: calc(100% + 15px);\n}\n\n.guideai-onboarding.below {\n top: calc(100% + 15px);\n}\n\n.guideai-onboarding.above::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-top: 8px solid white;\n filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));\n}\n\n.guideai-onboarding.below::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid white;\n filter: drop-shadow(0 -2px 4px rgba(0, 0, 0, 0.1));\n}\n\n@keyframes onboarding-fade-in {\n from { opacity: 0; transform: translateX(-50%) translateY(-10px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n}\n\n.guideai-onboarding-content {\n padding: 16px;\n position: relative;\n}\n\n.guideai-onboarding-close {\n position: absolute;\n top: 10px;\n right: 10px;\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #999;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n}\n\n.guideai-onboarding-close:hover {\n background: #f5f5f5;\n color: #333;\n}\n\n.guideai-onboarding-step {\n text-align: center;\n margin-bottom: 12px;\n}\n\n.guideai-onboarding-icon {\n font-size: 32px;\n margin-bottom: 8px;\n display: inline-block;\n}\n\n.guideai-onboarding-step h3 {\n margin: 0 0 8px;\n font-size: 16px;\n color: #333;\n font-weight: 600;\n}\n\n.guideai-onboarding-step p {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.4;\n}\n\n.guideai-onboarding-dots {\n display: flex;\n justify-content: center;\n margin: 12px 0;\n}\n\n.guideai-onboarding-dots .dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #ddd;\n margin: 0 4px;\n transition: all 0.3s ease;\n}\n\n.guideai-onboarding-dots .dot.active {\n background: #0066ff;\n transform: scale(1.2);\n}\n\n.guideai-onboarding-next {\n display: block;\n width: 100%;\n padding: 10px;\n background: #0066ff;\n color: white;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.guideai-onboarding-next:hover {\n background: #0055cc;\n}\n\n/* Transcript Box Styles */\n.guideai-transcript-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: transparent;\n display: flex;\n justify-content: flex-end;\n align-items: flex-end;\n padding-bottom: 40px;\n padding-right: 40px;\n z-index: 10000;\n animation: transcript-fade-in 0.3s ease-out;\n pointer-events: none;\n}\n\n.guideai-transcript-box {\n background: rgba(40, 44, 52, 0.85);\n backdrop-filter: blur(20px);\n -webkit-backdrop-filter: blur(20px);\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-radius: 16px;\n box-shadow: \n 0 8px 32px rgba(0, 0, 0, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n inset 0 -1px 0 rgba(0, 0, 0, 0.1);\n width: 280px;\n max-height: 280px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: transcript-slide-up 0.4s ease-out;\n pointer-events: auto;\n margin-right: 60px;\n position: relative;\n}\n\n.guideai-transcript-box::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 1px;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);\n border-radius: 16px 16px 0 0;\n}\n\n\n\n.guideai-transcript-messages {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n max-height: 200px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar {\n width: 6px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar-track {\n background: rgba(0, 0, 0, 0.05);\n border-radius: 3px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar-thumb:hover {\n background: rgba(0, 0, 0, 0.3);\n}\n\n.guideai-transcript-empty {\n text-align: center;\n padding: 20px 12px;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.guideai-transcript-empty-icon {\n font-size: 24px;\n margin-bottom: 8px;\n opacity: 0.5;\n}\n\n.guideai-transcript-empty p {\n margin: 0;\n font-size: 11px;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.guideai-transcript-message {\n margin-bottom: 8px;\n animation: message-fade-in 0.3s ease-out;\n}\n\n.guideai-transcript-message.human {\n text-align: right;\n}\n\n.guideai-transcript-message.guideai {\n text-align: left;\n}\n\n.guideai-transcript-message-content {\n display: inline-block;\n max-width: 85%;\n padding: 6px 10px;\n border-radius: 12px;\n position: relative;\n}\n\n.guideai-transcript-message.human .guideai-transcript-message-content {\n background: rgba(255, 255, 255, 0.15);\n color: rgba(255, 255, 255, 0.95);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-bottom-right-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.guideai-transcript-message.guideai .guideai-transcript-message-content {\n background: rgba(0, 0, 0, 0.1);\n color: rgba(255, 255, 255, 0.9);\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-bottom-left-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.guideai-transcript-message-sender {\n font-size: 9px;\n font-weight: 600;\n margin-bottom: 2px;\n opacity: 0.8;\n}\n\n.guideai-transcript-message-text {\n font-size: 11px;\n line-height: 1.3;\n word-wrap: break-word;\n}\n\n.guideai-transcript-message-time {\n font-size: 8px;\n opacity: 0.6;\n margin-top: 2px;\n}\n\n\n\n@keyframes transcript-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes transcript-slide-up {\n from { \n opacity: 0; \n transform: translateX(40px) scale(0.95); \n }\n to { \n opacity: 1; \n transform: translateX(0) scale(1); \n }\n}\n\n@keyframes message-fade-in {\n from { \n opacity: 0; \n transform: translateY(10px); \n }\n to { \n opacity: 1; \n transform: translateY(0); \n }\n}\n\n/* Transcript Toggle Button Styles - positioned at top of transcript area */\n.guideai-transcript-toggle-button {\n position: fixed;\n bottom: 60px;\n right: 40px;\n width: 36px;\n height: 36px;\n background: rgba(40, 44, 52, 0.9);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border: 1px solid rgba(255, 255, 255, 0.15);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);\n transition: all 0.2s ease;\n z-index: 10001;\n font-size: 14px;\n padding: 0;\n color: rgba(255, 255, 255, 0.9);\n animation: toggle-fade-in 0.3s ease-out;\n}\n\n.guideai-transcript-toggle-button:hover {\n background: rgba(40, 44, 52, 1);\n transform: scale(1.1);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);\n}\n\n.guideai-transcript-toggle-button:active {\n transform: scale(0.95);\n}\n\n.guideai-transcript-toggle-icon {\n display: inline-block;\n transition: all 0.2s ease;\n filter: none;\n}\n\n/* Position transcript toggle button based on transcript position */\n.guideai-transcript-overlay {\n pointer-events: none;\n}\n\n.guideai-transcript-toggle-button {\n pointer-events: auto;\n}\n\n/* Input Options Container - Two Stage Layout */\n.guideai-input-options {\n display: flex;\n align-items: center;\n gap: 12px;\n position: relative;\n animation: options-slide-in 0.4s ease-out;\n}\n\n@keyframes options-slide-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n/* Individual Input Option Button */\n.guideai-input-option {\n width: 50px;\n height: 50px;\n background: rgba(255, 255, 255, 0.9);\n border: 2px solid rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n transition: all 0.3s ease;\n font-size: 18px;\n padding: 0;\n position: relative;\n}\n\n.guideai-input-option:hover:not(:disabled) {\n background: rgba(255, 255, 255, 1);\n transform: scale(1.1);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n}\n\n.guideai-input-option:active:not(:disabled) {\n transform: scale(0.95);\n}\n\n.guideai-input-option:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n}\n\n/* Voice Option Specific Styling */\n.guideai-input-option.voice-option {\n background: linear-gradient(135deg, rgba(76, 175, 80, 0.1), rgba(139, 195, 74, 0.1));\n border-color: rgba(76, 175, 80, 0.3);\n}\n\n.guideai-input-option.voice-option:hover:not(:disabled) {\n background: linear-gradient(135deg, rgba(76, 175, 80, 0.2), rgba(139, 195, 74, 0.2));\n border-color: rgba(76, 175, 80, 0.5);\n}\n\n/* Text Option Specific Styling */\n.guideai-input-option.text-option {\n background: linear-gradient(135deg, rgba(33, 150, 243, 0.1), rgba(63, 81, 181, 0.1));\n border-color: rgba(33, 150, 243, 0.3);\n}\n\n.guideai-input-option.text-option:hover:not(:disabled) {\n background: linear-gradient(135deg, rgba(33, 150, 243, 0.2), rgba(63, 81, 181, 0.2));\n border-color: rgba(33, 150, 243, 0.5);\n}\n\n.guideai-input-option-icon {\n display: inline-block;\n transition: all 0.2s ease;\n filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));\n}\n\n/* Text Input integrated into Transcript Box */\n.guideai-transcript-text-input {\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n padding: 12px;\n display: flex;\n gap: 8px;\n align-items: flex-end;\n background: rgba(0, 0, 0, 0.02);\n border-radius: 0 0 16px 16px;\n animation: text-input-fade-in 0.3s ease-out;\n}\n\n.guideai-transcript-input-field {\n flex: 1;\n background: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 8px;\n padding: 8px 12px;\n color: rgba(255, 255, 255, 0.95);\n font-size: 12px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n resize: none;\n outline: none;\n transition: all 0.2s ease;\n min-height: 32px;\n}\n\n.guideai-transcript-input-field::placeholder {\n color: rgba(255, 255, 255, 0.6);\n}\n\n.guideai-transcript-input-field:focus {\n border-color: rgba(255, 255, 255, 0.4);\n background: rgba(255, 255, 255, 0.2);\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.2);\n}\n\n.guideai-transcript-send-button {\n background: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 6px;\n padding: 6px 10px;\n color: rgba(255, 255, 255, 0.9);\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 36px;\n height: 32px;\n}\n\n.guideai-transcript-send-button:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.25);\n border-color: rgba(255, 255, 255, 0.3);\n transform: translateY(-1px);\n}\n\n.guideai-transcript-send-button:active:not(:disabled) {\n transform: translateY(0);\n}\n\n.guideai-transcript-send-button:disabled {\n background: rgba(255, 255, 255, 0.05);\n border-color: rgba(255, 255, 255, 0.1);\n color: rgba(255, 255, 255, 0.4);\n cursor: not-allowed;\n transform: none;\n}\n\n.guideai-transcript-send-icon {\n font-size: 11px;\n}\n\n/* Animation for text input appearance */\n@keyframes text-input-fade-in {\n from { \n opacity: 0; \n transform: translateY(10px); \n }\n to { \n opacity: 1; \n transform: translateY(0); \n }\n}\n\n@keyframes toggle-fade-in {\n from { \n opacity: 0; \n transform: scale(0.8); \n }\n to { \n opacity: 1; \n transform: scale(1); \n }\n}\n\n\n`; ","// Storage data structures for conversation persistence\nexport interface StoredMessage {\n content: string;\n sender: 'GUIDEAI' | 'HUMAN';\n timestamp: number;\n}\n\nexport interface StoredConversation {\n conversationId: string;\n messages: StoredMessage[];\n timestamp: number;\n organizationKey: string;\n}\n\nexport const CONVERSATION_STORAGE_KEY = 'guideai_conversation';\nexport const CONVERSATION_EXPIRY_MINUTES = 30;\nexport const MAX_STORED_MESSAGES = 100; // Increased to keep more conversation history\n\nexport const isLocalStorageAvailable = (): boolean => {\n try {\n const testKey = '__storage_test__';\n localStorage.setItem(testKey, testKey);\n localStorage.removeItem(testKey);\n return true;\n } catch (e) {\n return false;\n }\n};\n\nconst isValidConversation = (data: any): data is StoredConversation => {\n return (\n data &&\n typeof data === 'object' &&\n typeof data.conversationId === 'string' &&\n Array.isArray(data.messages) &&\n typeof data.timestamp === 'number' &&\n typeof data.organizationKey === 'string' &&\n data.messages.every((msg: any) => (\n typeof msg === 'object' &&\n typeof msg.content === 'string' &&\n (msg.sender === 'HUMAN' || msg.sender === 'GUIDEAI') &&\n typeof msg.timestamp === 'number'\n ))\n );\n};\n\nexport const isConversationExpired = (conversation: StoredConversation): boolean => {\n const expiryTime = CONVERSATION_EXPIRY_MINUTES * 60 * 1000; // convert to milliseconds\n const now = Date.now();\n return (now - conversation.timestamp) > expiryTime;\n};\n\nconst handleStorageError = (error: unknown, operation: string): void => {\n console.error(`Storage error during ${operation}:`, error);\n \n // Check if it's a quota exceeded error\n if (error instanceof DOMException && \n (error.name === 'QuotaExceededError' || \n error.name === 'NS_ERROR_DOM_QUOTA_REACHED')) {\n \n // Try to free up space by removing oldest messages instead of clearing everything\n try {\n const conversation = loadConversationFromStorage();\n if (conversation && conversation.messages.length > 5) {\n // Remove oldest 5 messages\n conversation.messages = conversation.messages.slice(5);\n saveConversationToStorage(conversation);\n console.warn('Storage quota exceeded. Removed oldest 5 messages to free space.');\n } else if (conversation) {\n // If less than 5 messages, clear everything\n clearConversationStorage();\n console.warn('Storage quota exceeded. Cleared conversation data.');\n }\n } catch (cleanupError) {\n console.error('Failed to clean up storage:', cleanupError);\n }\n }\n};\n\nexport const saveConversationToStorage = (conversation: StoredConversation): void => {\n if (!isLocalStorageAvailable()) {\n console.warn('localStorage is not available. Conversation persistence disabled.');\n return;\n }\n \n try {\n // Limit to last MAX_STORED_MESSAGES\n if (conversation.messages.length > MAX_STORED_MESSAGES) {\n conversation.messages = conversation.messages.slice(-MAX_STORED_MESSAGES);\n }\n \n // Update timestamp\n conversation.timestamp = Date.now();\n \n localStorage.setItem(CONVERSATION_STORAGE_KEY, JSON.stringify(conversation));\n } catch (error) {\n handleStorageError(error, 'save');\n }\n};\n\nexport const loadConversationFromStorage = (): StoredConversation | null => {\n if (!isLocalStorageAvailable()) {\n console.warn('localStorage is not available. Conversation persistence disabled.');\n return null;\n }\n \n try {\n const storedData = localStorage.getItem(CONVERSATION_STORAGE_KEY);\n if (!storedData) return null;\n \n const parsedData = JSON.parse(storedData);\n \n // Validate the data structure\n if (!isValidConversation(parsedData)) {\n console.warn('Corrupted conversation data found. Clearing storage.');\n clearConversationStorage();\n return null;\n }\n \n return parsedData;\n } catch (error) {\n handleStorageError(error, 'load');\n // Clear corrupted data on any parsing errors\n clearConversationStorage();\n return null;\n }\n};\n\nexport const clearConversationStorage = (): void => {\n if (!isLocalStorageAvailable()) {\n return;\n }\n \n try {\n localStorage.removeItem(CONVERSATION_STORAGE_KEY);\n } catch (error) {\n handleStorageError(error, 'clear');\n }\n};\n\nexport const addMessageToStorage = (message: StoredMessage, conversationId: string, organizationKey: string): void => {\n if (!isLocalStorageAvailable()) {\n console.warn('localStorage is not available. Message persistence disabled.');\n return;\n }\n \n try {\n let conversation = loadConversationFromStorage();\n \n if (!conversation) {\n conversation = {\n conversationId,\n messages: [],\n timestamp: Date.now(),\n organizationKey\n };\n }\n \n // Check for duplicate messages to prevent adding the same message twice\n const isDuplicate = conversation.messages.some(existingMsg => \n existingMsg.content === message.content && \n existingMsg.sender === message.sender &&\n Math.abs(existingMsg.timestamp - message.timestamp) < 5000 // Within 5 seconds\n );\n \n if (!isDuplicate) {\n conversation.messages.push(message);\n conversation.conversationId = conversationId;\n conversation.organizationKey = organizationKey;\n \n saveConversationToStorage(conversation);\n } else {\n console.log('Duplicate message detected, skipping:', message.content.substring(0, 50));\n }\n } catch (error) {\n console.error('Error adding message to storage:', error);\n }\n};\n\nexport const checkForStoredConversation = (currentOrganizationKey: string): {\n shouldRestore: boolean;\n conversationId: string | null;\n messages: StoredMessage[] | null;\n} => {\n const storedConversation = loadConversationFromStorage();\n \n if (!storedConversation) {\n return { shouldRestore: false, conversationId: null, messages: null };\n }\n \n // Check if conversation is expired - if so, clear it automatically\n if (isConversationExpired(storedConversation)) {\n clearConversationStorage();\n return { shouldRestore: false, conversationId: null, messages: null };\n }\n \n // Check if organization key matches\n if (storedConversation.organizationKey !== currentOrganizationKey) {\n return { shouldRestore: false, conversationId: null, messages: null };\n }\n \n return {\n shouldRestore: true,\n conversationId: storedConversation.conversationId,\n messages: storedConversation.messages\n };\n};\n\nexport const formatConversationContext = (messages: StoredMessage[], maxMessages: number = 10): string => {\n // Take only the last N messages to avoid context length issues\n const recentMessages = messages.slice(-maxMessages);\n \n if (recentMessages.length === 0) {\n return '';\n }\n \n // Filter out very short or empty messages\n const meaningfulMessages = recentMessages.filter(msg => \n msg.content && msg.content.trim().length > 3\n );\n \n if (meaningfulMessages.length === 0) {\n return '';\n }\n \n // Format messages into a readable context string\n const formattedMessages = meaningfulMessages.map(msg => {\n const sender = msg.sender === 'HUMAN' ? 'User' : 'Assistant';\n return `${sender}: ${msg.content.trim()}`;\n }).join('\\n');\n \n return formattedMessages;\n}; ","// Default prompt for Guide AI\nexport const DEFAULT_PROMPT = `you are Guide AI.\n Your role is to answer any question directly and succinctly that a user has. NEVER DIRECTLY MENTION THE SCREENSHOT, but use its information as much as possible to target your responses.\n If nothing is asked, then your goal is to generally assist them.\n IMPORTANT: NEVER answer in more than 10 words. Always be concise and limit answers to 1 sentence maximum. Be simple and as short as possible.\n Your job is to help them get it done through asking more and more targeted specific questions.`;\n\n// WebRTC message types to ignore in logging\nexport const IGNORE_MESSAGE_TYPES = [\n \"delta\", \n \"rate_limits\", \n \"input_audio_buffer\",\n \"response.audio.done\", \n \"response.output_item\", \n \"response.content_part\", \n \"output_audio_buffer\",\n \"response.created\", \n \"session.created\",\n \"conversation.item.truncated\"\n];\n\n// API endpoints\nexport const GUIDE_AI_API_BASE = 'https://www.getguide.ai/api';\n// export const GUIDE_AI_API_BASE = 'http://localhost:3001/api';\nexport const OPENAI_REALTIME_BASE = 'https://api.openai.com/v1/realtime';\nexport const OPENAI_REALTIME_MODEL = \"gpt-4o-realtime-preview-2024-12-17\";\n\n// Gemini API - Note: This should be moved to environment variables in production\nexport const GEMINI_API_KEY = 'AIzaSyBiFyzjYVupLyk8BdmfWzBL1GbzX8OUdPc';\nexport const GEMINI_API_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent'; ","module.exports = __WEBPACK_EXTERNAL_MODULE__156__;","import { StoredMessage, addMessageToStorage } from './messageStorage';\nimport { GUIDE_AI_API_BASE } from './constants';\nimport { UserMetadata, MetadataUpdate } from '../types/metadata.types';\n\n// Type for the conversation creation response (now includes token and prompt)\ninterface ConversationData {\n id: string;\n ephemeralToken: string;\n prompt: string;\n}\n\n// Create a new conversation (now also returns ephemeral token + prompt)\nexport const createNewConversation = async (\n organizationKey: string,\n onError: (error: Error, context: string) => void\n): Promise<ConversationData | null> => {\n try {\n const now = new Date();\n const response = await fetch(`${GUIDE_AI_API_BASE}/initialize-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n organizationKey,\n userId: 'anonymous',\n date: now.toISOString().split('T')[0],\n time: now.toTimeString().split(' ')[0],\n messages: []\n })\n });\n \n if (!response.ok) {\n const errorText = await response.text().catch(() => 'No error details available');\n console.error(`Conversation creation failed with status ${response.status}:`, errorText);\n throw new Error(`Failed to create conversation: ${response.status} - ${errorText}`);\n }\n \n const conversationData = await response.json();\n console.log('Conversation created:', conversationData.id);\n return conversationData;\n } catch (error) {\n console.error('Error creating conversation:', error);\n onError(error as Error, 'Creating conversation');\n return null;\n }\n};\n\n// Log a message to the conversation via API and local storage\nexport const logMessage = async (\n content: string, \n sender: 'GUIDEAI' | 'HUMAN',\n conversationId: string | null,\n organizationKey: string,\n onError: (error: Error, context: string) => void\n): Promise<void> => {\n if (!conversationId) return;\n \n try {\n const response = await fetch(`${GUIDE_AI_API_BASE}/conversations/${conversationId}/messages`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({ content, sender })\n });\n \n if (!response.ok) {\n throw new Error(`Failed to log message: ${response.status} ${response.statusText}`);\n }\n \n const message: StoredMessage = {\n content,\n sender,\n timestamp: Date.now()\n };\n \n addMessageToStorage(message, conversationId, organizationKey);\n } catch (error) {\n console.error('Error logging message:', error);\n onError(error as Error, 'Logging message');\n }\n};\n\n// Send user metadata to the backend\nexport const sendUserMetadata = async (\n metadata: UserMetadata,\n organizationKey: string,\n onError: (error: Error, context: string) => void\n): Promise<boolean> => {\n try {\n const response = await fetch(`${GUIDE_AI_API_BASE}/user-metadata`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n organizationKey,\n metadata,\n timestamp: Date.now()\n })\n });\n\n if (!response.ok) {\n throw new Error(`Failed to send metadata: ${response.status} ${response.statusText}`);\n }\n\n console.log('User metadata sent successfully');\n return true;\n } catch (error) {\n console.error('Error sending user metadata:', error);\n onError(error as Error, 'Sending user metadata');\n return false;\n }\n};\n\n// Send metadata updates in batch\nexport const sendMetadataUpdates = async (\n updates: MetadataUpdate[],\n organizationKey: string,\n onError: (error: Error, context: string) => void\n): Promise<boolean> => {\n if (updates.length === 0) return true;\n\n try {\n const response = await fetch(`${GUIDE_AI_API_BASE}/metadata-updates`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n organizationKey,\n updates,\n batchTimestamp: Date.now(),\n updateCount: updates.length\n })\n });\n\n if (!response.ok) {\n throw new Error(`Failed to send metadata updates: ${response.status} ${response.statusText}`);\n }\n\n console.log(`Sent ${updates.length} metadata updates successfully`);\n return true;\n } catch (error) {\n console.error('Error sending metadata updates:', error);\n onError(error as Error, 'Sending metadata updates');\n return false;\n }\n};\n\n// Update user metadata for a specific user\nexport const updateUserMetadata = async (\n userId: string,\n metadataUpdate: Partial<UserMetadata>,\n organizationKey: string,\n onError: (error: Error, context: string) => void\n): Promise<boolean> => {\n try {\n const response = await fetch(`${GUIDE_AI_API_BASE}/users/${userId}/metadata`, {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n organizationKey,\n metadata: metadataUpdate,\n timestamp: Date.now()\n })\n });\n\n if (!response.ok) {\n throw new Error(`Failed to update user metadata: ${response.status} ${response.statusText}`);\n }\n\n console.log('User metadata updated successfully for user:', userId);\n return true;\n } catch (error) {\n console.error('Error updating user metadata:', error);\n onError(error as Error, 'Updating user metadata');\n return false;\n }\n}; ","// Import React normally, but use a helper function to handle possible duplicates\nimport React from 'react';\nimport { \n StoredMessage, \n addMessageToStorage,\n clearConversationStorage,\n checkForStoredConversation, \n formatConversationContext \n} from './utils/messageStorage';\n\n// Import our refactored modules\nimport { GuideAIProps, RecordingStatus, UseStateHook, UseEffectHook, UseRefHook, UseCallbackHook, PopupPosition } from './types/GuideAI.types';\nimport { DEFAULT_PROMPT, IGNORE_MESSAGE_TYPES, GUIDE_AI_API_BASE, OPENAI_REALTIME_BASE, OPENAI_REALTIME_MODEL, GEMINI_API_KEY, GEMINI_API_ENDPOINT } from './utils/constants';\nimport { injectStyles, calculateOptimalPosition } from './utils/ui';\nimport { highlightElement } from './utils/highlight';\nimport { createNewConversation, logMessage } from './utils/api';\nimport WelcomeBubble from './components/WelcomeBubble';\nimport Onboarding from './components/Onboarding';\nimport TranscriptBox from './components/TranscriptBox';\nimport { guideAIStyles } from './styles/GuideAI.styles';\nimport { EventTracker, UserMetadataTracker, UserMetadata } from './metric';\nimport { sendMetadataUpdates } from './utils/api';\n\n// Global flag to prevent multiple GuideAI instances from initializing simultaneously\nlet globalInitializationInProgress = false;\n\n// Get React hooks safely, avoiding duplicate React issues\nconst getReactHooks = () => {\n // Try to use the React instance from window if available (for react-scripts)\n if (typeof window !== 'undefined' && (window as any).React) {\n return {\n useState: (window as any).React.useState as UseStateHook,\n useEffect: (window as any).React.useEffect as UseEffectHook,\n useRef: (window as any).React.useRef as UseRefHook,\n useMemo: (window as any).React.useMemo,\n useCallback: (window as any).React.useCallback as UseCallbackHook\n };\n }\n // Otherwise use the imported React\n return {\n useState: React.useState,\n useEffect: React.useEffect,\n useRef: React.useRef,\n useMemo: React.useMemo,\n useCallback: React.useCallback as UseCallbackHook\n };\n};\n\nconst GuideAI = (props: GuideAIProps) => {\n const {\n organizationKey,\n position,\n onError = console.error,\n metadata: metadataOptions,\n transcript: transcriptOptions,\n input: inputOptions\n } = props;\n\n // Memoize the React hooks to ensure consistent instances\n const hooks = React.useMemo(() => getReactHooks(), []);\n\n const [status, setStatus] = hooks.useState<RecordingStatus>('idle');\n const [isClient, setIsClient] = hooks.useState(false);\n const [componentPosition] = hooks.useState(position);\n const [isHighlighting, setIsHighlighting] = hooks.useState(false);\n const [hasInteracted, setHasInteracted] = hooks.useState(false);\n const [prompt, setPrompt] = hooks.useState<string | null>(null);\n const [isSessionReady, setIsSessionReady] = hooks.useState(false);\n const [isConnecting, setIsConnecting] = hooks.useState(false);\n const [showOnboarding, setShowOnboarding] = hooks.useState(false);\n const [popupPosition, setPopupPosition] = hooks.useState<PopupPosition>('above');\n const conversationIdRef = hooks.useRef<string | null>(null);\n\n const componentRef = hooks.useRef<HTMLDivElement>(null);\n const peerConnectionRef = hooks.useRef<RTCPeerConnection | null>(null);\n const dataChannelRef = hooks.useRef<RTCDataChannel | null>(null);\n const hasCreatedConversationRef = hooks.useRef(false);\n const mediaStreamRef = hooks.useRef<MediaStream | null>(null);\n const audioElementRef = hooks.useRef<HTMLAudioElement | null>(null);\n const [ephemeralToken, setEphemeralToken] = hooks.useState<string | null>(null);\n const hasInitializedRef = hooks.useRef(false);\n const initializationInProgressRef = hooks.useRef(false);\n const isUnmountingRef = hooks.useRef(false);\n const [isConversationActive, setIsConversationActive] = hooks.useState(false);\n const [restoredMessages, setRestoredMessages] = hooks.useState<StoredMessage[]>([]);\n const [showTranscript, setShowTranscript] = hooks.useState(\n transcriptOptions?.enabled !== false // Default to true unless explicitly disabled\n );\n const [allMessages, setAllMessages] = hooks.useState<StoredMessage[]>([]);\n const [inputMode, setInputMode] = hooks.useState<'voice' | 'text'>(\n inputOptions?.defaultMode || 'voice'\n );\n const [textInput, setTextInput] = hooks.useState('');\n const [showTextInput, setShowTextInput] = hooks.useState(false);\n\n const hasAttemptedAutoStartRef = hooks.useRef(false);\n const eventTracker = hooks.useMemo(() => {\n let customerId: string | undefined;\n let organizationId: string | undefined;\n let customerType: string | undefined;\n try {\n const raw = typeof window !== 'undefined' ? localStorage.getItem('user') : null;\n if (raw) {\n const parsed = JSON.parse(raw);\n const idVal = parsed?.customer?.id;\n if (idVal != null) customerId = String(idVal);\n const orgVal = parsed?.customer.organizationId;\n if (orgVal != null) organizationId = String(orgVal);\n const typeName = parsed?.customer?.customerTypeName;\n if (typeof typeName === 'string') customerType = typeName;\n console.log(\"raw\", customerId,organizationId,customerType);\n }\n } catch (_err) {\n // ignore\n }\n return new EventTracker({ customerId, organizationId, customerType, organizationKey });\n }, [organizationKey]);\n\n const metadataTracker = hooks.useMemo(() => \n new UserMetadataTracker(organizationKey, metadataOptions?.config || {}, onError), \n [organizationKey, metadataOptions?.config, onError]\n );\n \n // ===== API & EXTERNAL CALLS =====\n \n // Call Gemini Flash API to validate and fix JSON\n const geminiFlash = async (prompt: string): Promise<string> => {\n const response = await fetch(`${GEMINI_API_ENDPOINT}?key=${GEMINI_API_KEY}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n contents: [\n {\n parts: [\n {\n text: prompt\n }\n ]\n }\n ]\n })\n });\n \n const responseJson = await response.json();\n const content = responseJson.candidates[0].content;\n const responseText = content.parts[0].text;\n return responseText;\n };\n\n // ===== COMPONENT WRAPPER FUNCTIONS =====\n \n // Wrapper functions to maintain original signatures\n const handleCreateNewConversation = async () => {\n if (hasCreatedConversationRef.current) return null;\n hasCreatedConversationRef.current = true;\n \n const conversationData = await createNewConversation(organizationKey, onError);\n if (conversationData) {\n conversationIdRef.current = conversationData.id;\n setEphemeralToken(conversationData.ephemeralToken);\n setPrompt(conversationData.prompt);\n return conversationData;\n }\n return null;\n };\n\n const handleLogMessage = async (content: string, sender: 'GUIDEAI' | 'HUMAN') => {\n await logMessage(content, sender, conversationIdRef.current, organizationKey, onError);\n \n // Add message to local state for transcript\n const newMessage: StoredMessage = {\n content,\n sender,\n timestamp: Date.now()\n };\n setAllMessages(prev => [...prev, newMessage]);\n };\n\n const handleHighlightElement = async (selector: string | string[]) => {\n return highlightElement(selector, isHighlighting, setIsHighlighting, handleLogMessage);\n };\n\n // ===== UI UTILITIES & POSITION =====\n \n // Calculate optimal position for popups based on component location\n const getOptimalPosition = hooks.useCallback((elementHeight: number = 240, spacing: number = 15): PopupPosition => {\n if (!componentRef.current) return 'above';\n \n const rect = componentRef.current.getBoundingClientRect();\n return calculateOptimalPosition(rect, elementHeight, spacing);\n }, []);\n\n // ===== WEBRTC MANAGEMENT =====\n \n const sendMessage = (message: any) => {\n if (dataChannelRef.current?.readyState === 'open') {\n // console.log('sending message', message);\n dataChannelRef.current.send(JSON.stringify(message));\n } else {\n console.error('Data channel not open, cannot send message');\n setStatus('idle');\n }\n };\n \n const cleanupWebRTC = hooks.useCallback(() => {\n if (mediaStreamRef.current) {\n // Stop tracks completely instead of just disabling them\n mediaStreamRef.current.getAudioTracks().forEach(track => {\n track.stop();\n });\n mediaStreamRef.current = null;\n }\n \n if (dataChannelRef.current) {\n dataChannelRef.current.close();\n dataChannelRef.current = null;\n }\n \n if (peerConnectionRef.current) {\n peerConnectionRef.current.close();\n peerConnectionRef.current = null;\n }\n \n if (audioElementRef.current) {\n audioElementRef.current.srcObject = null;\n }\n \n // Reset session ready state\n setIsSessionReady(false);\n }, []);\n\n const initializeWebRTC = async (audioStream: MediaStream | null): Promise<boolean> => {\n try {\n const pc = new RTCPeerConnection();\n peerConnectionRef.current = pc;\n \n // Only add audio tracks if audioStream is provided (for voice mode)\n if (audioStream) {\n audioStream.getAudioTracks().forEach(track => {\n pc.addTrack(track, audioStream);\n });\n }\n \n // Only create audio element if we have an audio stream (voice mode)\n if (audioStream && !audioElementRef.current) {\n const audioEl = document.createElement('audio');\n audioEl.autoplay = true;\n document.body.appendChild(audioEl);\n audioElementRef.current = audioEl;\n }\n \n pc.ontrack = (e) => {\n if (audioElementRef.current && e.track.kind === 'audio') {\n const stream = new MediaStream([e.track]);\n audioElementRef.current.srcObject = stream;\n }\n };\n \n const dc = pc.createDataChannel('oai-events');\n dataChannelRef.current = dc;\n \n dc.onopen = () => { \n // Configure session based on whether we have audio stream (voice vs text mode)\n const sessionConfig: any = {\n tools: [{\n type: \"function\",\n name: \"highlight\",\n description: \"Highlight specific elements on the page to guide the user's attention\",\n parameters: {\n type: \"object\",\n properties: {\n selector: {\n oneOf: [\n {\n type: \"string\",\n description: \"CSS selector or XPath for the element to highlight (e.g., '#search-bar')\"\n },\n {\n type: \"array\",\n items: {\n type: \"string\"\n },\n description: \"List of CSS selectors or XPaths to highlight in sequence (e.g., ['#first-button', '#second-button'])\"\n }\n ],\n description: \"CSS selector(s) or XPath(s) for the element(s) to highlight. Can be a single selector string or an array of selectors to process sequentially.\"\n }\n },\n required: [\"selector\"]\n }\n }],\n tool_choice: \"auto\"\n };\n\n // Only add audio-specific config if we have an audio stream\n if (audioStream) {\n sessionConfig.turn_detection = {\n type: \"semantic_vad\",\n create_response: true,\n interrupt_response: false\n };\n sessionConfig.input_audio_transcription = {\n model: \"gpt-4o-mini-transcribe\",\n language: \"en\",\n };\n }\n\n sendMessage({\n type: \"session.update\",\n session: sessionConfig\n });\n };\n \n dc.onmessage = (e) => {\n try {\n const message = JSON.parse(e.data);\n\n switch (message.type) { \n case 'session.updated':\n // console.log('session.updated', message);\n setIsSessionReady(true);\n setIsConnecting(false);\n \n // If we have restored messages, send conversation context to AI now that session is ready\n if (restoredMessages.length > 0) {\n const conversationContext = formatConversationContext(restoredMessages, 5); // Reduce to 5 messages\n \n // Send as system context instead of user input to avoid confusion\n sendMessage({\n type: \"conversation.item.create\",\n item: {\n type: \"message\",\n role: \"system\",\n content: [{\n type: \"input_text\",\n text: `This is context from a previous conversation session. The user is continuing an existing conversation. Previous context: ${conversationContext}`\n }]\n }\n });\n \n console.log('Sent conversation context with', restoredMessages.length, 'restored messages');\n }\n break;\n\n case 'session.transcript_disabled':\n if (message.text && message.text.trim()) {\n console.log('Session transcript:', message.text);\n handleLogMessage(message.text, 'HUMAN');\n }\n break;\n \n case 'conversation.item.input_audio_transcription.completed':\n if (message.transcript && message.transcript.trim()) {\n console.log('User transcript:', message.transcript);\n // Only log if it's different from the last message to avoid duplicates\n if (allMessages.length === 0 || \n allMessages[allMessages.length - 1].content !== message.transcript) {\n handleLogMessage(message.transcript, 'HUMAN');\n }\n }\n break;\n\n case 'response.audio_transcript.done':\n if (message.transcript && message.transcript.trim()) {\n console.log('Assistant message:', message.transcript);\n // Only log if it's different from the last assistant message to avoid duplicates\n const lastMessage = allMessages[allMessages.length - 1];\n if (!lastMessage || \n lastMessage.sender !== 'GUIDEAI' ||\n lastMessage.content !== message.transcript) {\n handleLogMessage(message.transcript, 'GUIDEAI');\n }\n }\n break;\n \n case \"conversation.item.created\":\n // console.log('conversation.item.created', message);\n break;\n\n case \"input_audio_buffer.speech_started\":\n // console.log('User speaking started');\n setStatus('recording');\n break;\n\n case \"input_audio_buffer.speech_stopped\":\n // console.log('User speaking stopped');\n setStatus('processing');\n break;\n\n case 'response.done':\n // console.log('response.done', message);\n for (const out of message.response.output) {\n switch (out.type) {\n case \"message\":\n // console.log('Assistant message:', out.text);\n break;\n \n case \"function_call\":\n // console.log('function_call', out);\n if (out.name === 'highlight' && out.arguments) {\n // console.log('Tool call:', out.arguments);\n try {\n let argsToUse = out.arguments;\n // Check if the JSON string is missing a closing quote\n // try {\n // console.log(\"argsToUse\", argsToUse);\n // const parsedArgs = JSON.parse(argsToUse);\n // console.log(\"parsedArgs\", parsedArgs);\n // highlightElement(parsedArgs.selector);\n // } catch (error) {\n // console.log(\"errored, argsToUse\", argsToUse);\n const prompt = `\n Validate the following JSON string and return ONLY a correct JSON object:\n Note: The selector(s) should be either a css selector or an xpath, so modify those if invalid.\n Also, [url=''] is a valid css selector, so do not modify it if it's present.\n Do not add any other text or newlines to the response.\n It should be of the following format:\n { \"selector\": \"string\" }\n or\n { \"selector\": [\"string\", ...] }\n DO NOT add any other text or newlines to the response, it should begin and end with curly braces.\n DO NOT add '''json to the response.\n The JSON string is:\n ${argsToUse}\n `\n geminiFlash(prompt).then(response => {\n response = response.replace(\"```json\", \"\").replace(\"```\", \"\").trim();\n // console.log(\"response\", response);\n const parsedArgs = JSON.parse(response);\n handleHighlightElement(parsedArgs.selector);\n }).catch(err => {\n console.error(\"Error calling Gemini:\", err);\n });\n // }\n\n\n } catch (error) {\n console.error('Error parsing function arguments:', error);\n console.log(out.arguments);\n handleLogMessage('Error parsing function arguments: ' + out.arguments, 'GUIDEAI');\n }\n }\n \n sendMessage({\n type: \"conversation.item.create\",\n item: {\n type: \"function_call_output\",\n call_id: out.call_id,\n output: JSON.stringify(true)\n }\n });\n\n sendMessage({\n type: 'response.create',\n });\n break;\n }\n }\n \n break;\n\n case \"response.function_call_arguments.delta\":\n // console.log('response.function_call_arguments.delta', message);\n break;\n\n case \"response.function_call_arguments.done\":\n // console.log('response.function_call_arguments.done', message);\n break;\n\n case \"output_audio_buffer.started\":\n setStatus('playing');\n break;\n\n case \"output_audio_buffer.stopped\":\n // console.log('output_audio_buffer.stopped');\n setStatus('recording');\n \n break;\n\n case 'error':\n if (message.error.code === 'session_expired') {\n console.error('Session expired:', message);\n setStatus('idle');\n setIsConnecting(false);\n setIsConversationActive(false);\n setEphemeralToken(null); // Clear expired token so reconnection gets fresh one\n hasCreatedConversationRef.current = false; // Allow creating new conversation\n break;\n }\n console.error('OpenAI API error:', message);\n onError(new Error(message.error.message || 'Unknown API error'), 'OpenAI API error');\n setStatus('idle');\n setIsConnecting(false);\n setIsConversationActive(false);\n setEphemeralToken(null); // Clear token in case of auth-related errors\n hasCreatedConversationRef.current = false; // Allow creating new conversation\n break;\n \n default:\n if (!IGNORE_MESSAGE_TYPES.some(fragment => message.type.includes(fragment))) {\n console.log('Unhandled:', message.type, message);\n }\n }\n } catch (error) {\n console.error('Error handling WebRTC message:', error);\n setStatus('idle');\n setIsConversationActive(false);\n }\n };\n \n // Start the session using SDP\n const offer = await pc.createOffer();\n await pc.setLocalDescription(offer);\n \n if (!pc.localDescription || !pc.localDescription.sdp) {\n throw new Error('Failed to create local SDP offer');\n }\n \n const baseUrl = OPENAI_REALTIME_BASE;\n const model = OPENAI_REALTIME_MODEL;\n \n \n const sdpResponse = await fetch(`${baseUrl}?model=${model}`, {\n method: 'POST',\n body: pc.localDescription.sdp,\n headers: {\n Authorization: `Bearer ${ephemeralToken}`,\n 'Content-Type': 'application/sdp'\n },\n });\n \n if (!sdpResponse.ok) {\n const errorText = await sdpResponse.text().catch(() => 'No error details available');\n console.error('WebRTC connection failed with status:', sdpResponse.status);\n console.error('Error details:', errorText);\n \n // Clear token on authentication failures\n if (sdpResponse.status === 401 || sdpResponse.status === 403) {\n setEphemeralToken(null);\n }\n \n throw new Error(`Failed to connect to OpenAI WebRTC: ${sdpResponse.status} - ${errorText}`);\n }\n \n const answerSdp = await sdpResponse.text();\n \n const answer = {\n type: 'answer',\n sdp: answerSdp,\n };\n \n await pc.setRemoteDescription(answer as RTCSessionDescriptionInit);\n \n return true;\n } catch (error) {\n console.error('Error initializing WebRTC:', error);\n onError(error as Error, 'WebRTC initialization failed');\n setIsConnecting(false);\n return false;\n }\n };\n\n // ===== SESSION MANAGEMENT =====\n \n const startConversationSession = hooks.useCallback(async () => {\n try {\n setStatus('processing');\n \n if (peerConnectionRef.current && dataChannelRef.current?.readyState === 'open' && mediaStreamRef.current) {\n mediaStreamRef.current.getAudioTracks().forEach(track => {\n track.enabled = true;\n });\n setStatus('recording');\n return true;\n } else {\n cleanupWebRTC();\n \n try {\n setIsConnecting(true);\n \n // Ensure we have a valid token (get fresh one if needed)\n if (!ephemeralToken) {\n console.log('No token available, getting fresh token...');\n const conversationData = await handleCreateNewConversation();\n if (!conversationData) {\n console.error('Failed to get fresh token');\n setIsConnecting(false);\n setStatus('idle');\n return false;\n }\n }\n \n let audioStream: MediaStream | null = null;\n \n // Only request microphone access if text input is not enabled or if voice is the default mode\n if (inputOptions?.enableTextInput === false || inputOptions?.defaultMode === 'voice') {\n try {\n audioStream = await navigator.mediaDevices.getUserMedia({ \n audio: {\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n channelCount: 1,\n sampleRate: 48000,\n }\n });\n mediaStreamRef.current = audioStream;\n } catch (micError) {\n console.log('Microphone access denied or failed, falling back to text-only mode');\n // Continue without microphone for text-only mode\n }\n }\n \n const initialized = await initializeWebRTC(audioStream);\n \n if (!initialized) {\n // Clean up if initialization fails\n if (audioStream) {\n audioStream.getAudioTracks().forEach(track => {\n track.stop();\n });\n mediaStreamRef.current = null;\n }\n setStatus('idle');\n setIsConnecting(false);\n return false;\n }\n \n // Set appropriate status based on whether we have audio\n if (audioStream) {\n setStatus('recording');\n } else {\n setStatus('idle'); // Text-only mode, no recording status needed\n }\n return true;\n } catch (error) {\n console.error('Error during conversation setup:', error);\n onError(error as Error, 'Microphone or WebRTC setup failed');\n setStatus('idle');\n setIsConnecting(false);\n return false;\n }\n }\n } catch (error) {\n setStatus('idle');\n setIsConnecting(false);\n onError(error as Error, 'Starting conversation failed');\n return false;\n }\n }, [ephemeralToken, onError]);\n\n const endConversationSession = hooks.useCallback(() => {\n if (!isClient) return;\n \n if (mediaStreamRef.current) {\n mediaStreamRef.current.getAudioTracks().forEach(track => {\n track.stop();\n });\n }\n \n cleanupWebRTC();\n setStatus('idle');\n \n // Clear localStorage when conversation is explicitly ended\n clearConversationStorage();\n \n // Reset restored messages state\n setRestoredMessages([]);\n \n // Reset auto-start flag to allow future auto-starts\n hasAttemptedAutoStartRef.current = false;\n }, [isClient]);\n\n // ===== UI EVENT HANDLERS =====\n \n const handleToggleConversation = async () => {\n if (!isClient) return;\n \n if (!hasInteracted) {\n setHasInteracted(true);\n localStorage.setItem('guideAI_hasInteracted', 'true');\n \n // Show onboarding on first interaction\n setShowOnboarding(true);\n return;\n }\n \n if (!isConversationActive) {\n const success = await startConversationSession();\n if (success) {\n setIsConversationActive(true);\n // Always show transcript when conversation starts\n if (transcriptOptions?.enabled !== false) {\n setShowTranscript(true);\n }\n // Show text input option by default (unless explicitly disabled)\n if (inputOptions?.enableTextInput !== false) {\n setShowTextInput(true);\n }\n }\n } else {\n endConversationSession();\n setIsConversationActive(false);\n // Hide transcript and text input when conversation ends\n if (transcriptOptions?.enabled !== false) {\n setShowTranscript(false);\n }\n setShowTextInput(false);\n }\n };\n\n const handleToggleTranscript = () => {\n setShowTranscript(prev => !prev);\n };\n\n const handleToggleInputMode = () => {\n setInputMode(prev => {\n const newMode = prev === 'voice' ? 'text' : 'voice';\n // Update text input visibility based on new mode\n if (newMode === 'text' && isConversationActive) {\n setShowTextInput(true);\n } else {\n setShowTextInput(false);\n }\n return newMode;\n });\n };\n\n\n\n const handleTextSubmit = async () => {\n if (!textInput.trim() || !isConversationActive) return;\n\n // Log the user's text message\n handleLogMessage(textInput.trim(), 'HUMAN');\n\n // Send text message to AI via WebRTC data channel\n if (dataChannelRef.current?.readyState === 'open') {\n const message = {\n type: \"conversation.item.create\",\n item: {\n type: \"message\",\n role: \"user\",\n content: [{\n type: \"input_text\",\n text: textInput.trim()\n }]\n }\n };\n \n dataChannelRef.current.send(JSON.stringify(message));\n\n // Trigger response generation\n const responseMessage = {\n type: \"response.create\"\n };\n dataChannelRef.current.send(JSON.stringify(responseMessage));\n }\n\n // Clear the input\n setTextInput('');\n };\n\n const handleTextKeyPress = (event: React.KeyboardEvent) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n handleTextSubmit();\n }\n };\n\n const handleOnboardingComplete = async () => {\n setShowOnboarding(false);\n \n // Start the conversation session when onboarding is completed\n const success = await startConversationSession();\n if (success) {\n setIsConversationActive(true);\n // Only auto-show transcript if enabled in options\n if (transcriptOptions?.enabled !== false) {\n setShowTranscript(true);\n }\n }\n };\n\n const handleOnboardingClose = () => {\n setShowOnboarding(false);\n };\n\n const handleCloseTranscript = () => {\n setShowTranscript(false);\n };\n\n // ===== REACT EFFECTS & LIFECYCLE ===== \n \n // CSS styles injection effect\n hooks.useEffect(() => {\n injectStyles(guideAIStyles, 'guide-ai-styles');\n }, [guideAIStyles]);\n \n // Metadata initialization effect\n hooks.useEffect(() => {\n eventTracker.initialize();\n if (metadataOptions?.initialUserData) {\n metadataTracker.updateUserInfo(metadataOptions.initialUserData);\n }\n }, [eventTracker, metadataTracker, metadataOptions?.initialUserData]);\n \n // Component initialization effect\n hooks.useEffect(() => {\n console.log('GuideAI: Component mounting - initialization started', { \n hasInitialized: hasInitializedRef.current,\n initializationInProgress: initializationInProgressRef.current,\n organizationKey,\n timestamp: Date.now()\n });\n \n // Double-check to prevent race conditions\n if (hasInitializedRef.current || initializationInProgressRef.current || isUnmountingRef.current || globalInitializationInProgress) {\n console.log('GuideAI: Already initialized, initialization in progress, unmounting, or global initialization in progress, skipping');\n return;\n }\n \n // Set flags immediately to prevent concurrent initialization\n hasInitializedRef.current = true;\n initializationInProgressRef.current = true;\n globalInitializationInProgress = true;\n \n setIsClient(true);\n setIsConnecting(true); // Show loading state during initialization\n \n // Check for stored conversation before initializing\n const { shouldRestore, conversationId, messages } = checkForStoredConversation(organizationKey);\n \n if (shouldRestore && conversationId && messages) {\n // Store the restored messages to use as context\n setRestoredMessages(messages);\n } else {\n // No valid conversation to restore\n setRestoredMessages([]);\n }\n \n // Create new conversation (gets conversation + token + prompt)\n handleCreateNewConversation().then(conversationData => {\n if (!isUnmountingRef.current) {\n setIsConnecting(false); // Hide loading state when done\n globalInitializationInProgress = false; // Release global flag\n }\n }).catch(error => {\n if (!isUnmountingRef.current) {\n setIsConnecting(false); // Hide loading state on error\n console.error('Failed to create conversation:', error);\n globalInitializationInProgress = false; // Release global flag\n }\n });\n \n const hasInteractedBefore = localStorage.getItem('guideAI_hasInteracted');\n if (!hasInteractedBefore) {\n setHasInteracted(false);\n } else {\n setHasInteracted(true);\n }\n }, [organizationKey, handleCreateNewConversation, checkForStoredConversation]);\n \n // Component cleanup effect\n hooks.useEffect(() => {\n return () => {\n console.log('GuideAI: Component unmounting - cleanup triggered', { \n hasInitialized: hasInitializedRef.current,\n initializationInProgress: initializationInProgressRef.current,\n isUnmounting: isUnmountingRef.current,\n timestamp: Date.now()\n });\n \n // Set unmounting flag to prevent any new initialization\n isUnmountingRef.current = true;\n cleanupWebRTC();\n \n if (audioElementRef.current) {\n audioElementRef.current.srcObject = null;\n audioElementRef.current.remove();\n audioElementRef.current = null;\n }\n \n // Stop event tracking on cleanup\n if (eventTracker) {\n eventTracker.stopTracking();\n }\n \n // Stop metadata tracking and sync any pending updates\n if (metadataTracker) {\n metadataTracker.destroy();\n }\n \n // Reset flags on cleanup\n hasInitializedRef.current = false;\n initializationInProgressRef.current = false;\n isUnmountingRef.current = false;\n hasAttemptedAutoStartRef.current = false;\n globalInitializationInProgress = false;\n };\n }, [cleanupWebRTC, eventTracker, metadataTracker]);\n\n // Metadata sync effect - periodically sync metadata updates to backend\n hooks.useEffect(() => {\n const syncInterval = metadataOptions?.config?.syncInterval || 30000; // 30 seconds default\n \n const syncTimer = setInterval(async () => {\n if (metadataTracker) {\n const pendingUpdates = metadataTracker.syncNow();\n if (pendingUpdates.length > 0) {\n try {\n await sendMetadataUpdates(pendingUpdates, organizationKey, onError);\n \n // Notify parent component of metadata updates if callback provided\n if (metadataOptions?.onMetadataUpdate) {\n metadataOptions.onMetadataUpdate(metadataTracker.getMetadata());\n }\n } catch (error) {\n console.error('Failed to sync metadata updates:', error);\n }\n }\n }\n }, syncInterval);\n\n return () => {\n clearInterval(syncTimer);\n };\n }, [organizationKey, metadataOptions?.config?.syncInterval, metadataOptions?.onMetadataUpdate]);\n\n // Auto-restart effect - handles reconnection when token and restored messages are ready\n hooks.useEffect(() => {\n if (ephemeralToken && restoredMessages.length > 0 && !hasAttemptedAutoStartRef.current) {\n console.log('Auto-restarting conversation with', restoredMessages.length, 'restored messages');\n hasAttemptedAutoStartRef.current = true;\n \n startConversationSession().then(success => {\n if (success) {\n setIsConversationActive(true);\n setHasInteracted(true);\n localStorage.setItem('guideAI_hasInteracted', 'true');\n }\n });\n }\n }, [ephemeralToken, restoredMessages, startConversationSession]);\n\n // Load restored messages into allMessages state\n hooks.useEffect(() => {\n if (restoredMessages.length > 0 && allMessages.length === 0) {\n setAllMessages(restoredMessages);\n }\n }, [restoredMessages, allMessages.length]);\n\n // Update popup position when needed\n hooks.useEffect(() => {\n if (showOnboarding || (!hasInteracted && ephemeralToken)) {\n // Use onboarding dimensions if onboarding is shown, otherwise welcome bubble dimensions\n const height = showOnboarding ? 240 : 50;\n const spacing = showOnboarding ? 20 : 15;\n setPopupPosition(getOptimalPosition(height, spacing));\n }\n }, [showOnboarding, hasInteracted, ephemeralToken, getOptimalPosition]);\n\n // ===== METADATA HELPER FUNCTIONS =====\n \n // Expose metadata tracking methods globally on window for external access\n hooks.useEffect(() => {\n if (typeof window !== 'undefined') {\n // Create global GuideAI metadata API\n (window as any).GuideAI = {\n ...(window as any).GuideAI,\n metadata: {\n // Track user login\n trackLogin: (additionalInfo?: Partial<UserMetadata>) => {\n metadataTracker?.trackLogin(additionalInfo);\n },\n \n // Update user information\n updateUserInfo: (userInfo: Partial<UserMetadata>) => {\n metadataTracker?.updateUserInfo(userInfo);\n },\n \n // Track custom events\n trackCustomEvent: (eventType: string, customData: Record<string, any>) => {\n metadataTracker?.trackCustomEvent(eventType, customData);\n },\n \n // Get current metadata\n getMetadata: () => {\n return metadataTracker?.getMetadata() || null;\n },\n \n // Force sync metadata now\n syncMetadata: async () => {\n if (metadataTracker) {\n const updates = metadataTracker.syncNow();\n if (updates.length > 0) {\n return await sendMetadataUpdates(updates, organizationKey, onError);\n }\n }\n return true;\n }\n },\n transcript: {\n // Toggle transcript visibility\n toggle: () => {\n setShowTranscript(prev => !prev);\n },\n \n // Show transcript\n show: () => {\n setShowTranscript(true);\n },\n \n // Hide transcript\n hide: () => {\n setShowTranscript(false);\n },\n \n // Get current transcript visibility\n isVisible: () => {\n return showTranscript;\n }\n },\n input: {\n // Toggle input mode between voice and text\n toggleMode: () => {\n handleToggleInputMode();\n },\n \n // Set input mode\n setMode: (mode: 'voice' | 'text') => {\n setInputMode(mode);\n if (mode === 'text' && inputOptions?.enableTextInput !== false && isConversationActive) {\n setShowTextInput(true);\n } else {\n setShowTextInput(false);\n }\n },\n \n // Get current input mode\n getMode: () => {\n return inputMode;\n },\n \n // Send text message programmatically\n sendText: (text: string) => {\n if (text.trim() && isConversationActive) {\n setTextInput(text);\n handleTextSubmit();\n }\n }\n }\n };\n }\n }, [organizationKey, metadataTracker, showTranscript, inputMode, isConversationActive]);\n\n if (!isClient) {\n return null;\n }\n\n // Determine if we should use fixed positioning (when position props are provided)\n const shouldUseFixedPosition = componentPosition && Object.keys(componentPosition).length > 0;\n \n // Base styles for the component\n const baseStyles: React.CSSProperties = {\n position: shouldUseFixedPosition ? 'fixed' : 'relative',\n zIndex: shouldUseFixedPosition ? 1000 : 'auto',\n ...(shouldUseFixedPosition ? componentPosition : {}),\n };\n\n return (\n <>\n <div\n ref={componentRef}\n style={baseStyles}\n >\n <div className=\"guideai-main-ui\">\n {!hasInteracted && ephemeralToken && (\n <WelcomeBubble position={popupPosition} />\n )}\n \n <Onboarding \n position={popupPosition}\n isVisible={showOnboarding}\n onComplete={handleOnboardingComplete}\n onClose={handleOnboardingClose}\n />\n \n <div className=\"guideai-main-controls\">\n <div \n className={`guideai-icon-wrapper ${isConnecting ? 'initializing' : status}`}\n onClick={isConnecting ? undefined : handleToggleConversation}\n style={isConnecting ? { cursor: 'default' } : undefined}\n title={isConnecting ? 'Initializing...' : \n status === 'idle' ? 'Click to start conversation' : \n status === 'recording' ? 'Click to end conversation' : \n status === 'processing' ? 'Processing your message...' : \n 'AI is speaking, click to end conversation'}\n >\n {isConnecting && <i className=\"guideai-icon initializing\" />}\n {!isConnecting && status === 'idle' && <i className=\"guideai-icon microphone\" />}\n {!isConnecting && status === 'recording' && <i className=\"guideai-icon recording\" />}\n {!isConnecting && status === 'processing' && <i className=\"guideai-icon processing\" />}\n {!isConnecting && status === 'playing' && <i className=\"guideai-icon playing\" />}\n </div>\n \n </div>\n \n </div>\n </div>\n \n {/* Transcript Box */}\n <TranscriptBox\n messages={allMessages}\n isVisible={showTranscript}\n onClose={handleCloseTranscript}\n showToggleButton={transcriptOptions?.showToggleButton !== false && isConversationActive}\n onToggle={handleToggleTranscript}\n showTextInput={isConversationActive && inputOptions?.enableTextInput !== false}\n textInput={textInput}\n onTextInputChange={setTextInput}\n onTextSubmit={handleTextSubmit}\n onTextKeyPress={handleTextKeyPress}\n textPlaceholder={inputOptions?.placeholder || \"Type your message...\"}\n />\n </>\n );\n};\n\nexport default GuideAI;","import { PopupPosition } from '../types/GuideAI.types';\n\n// Function to inject CSS styles into the document head\nexport const injectStyles = (css: string, id: string) => {\n if (typeof document === 'undefined') return; // SSR safety\n \n // Check if styles are already injected\n if (document.getElementById(id)) return;\n \n const styleElement = document.createElement('style');\n styleElement.id = id;\n styleElement.textContent = css;\n document.head.appendChild(styleElement);\n};\n\n// Calculate optimal position for popups based on component location\nexport const calculateOptimalPosition = (\n componentRect: DOMRect, \n elementHeight: number = 240, \n spacing: number = 15\n): PopupPosition => {\n const viewportHeight = window.innerHeight;\n \n const spaceAbove = componentRect.top;\n const spaceBelow = viewportHeight - componentRect.bottom;\n \n const canFitBelow = spaceBelow >= (elementHeight + spacing);\n const canFitAbove = spaceAbove >= (elementHeight + spacing);\n \n if (canFitBelow) {\n return 'below';\n } else if (canFitAbove) {\n return 'above';\n } else {\n return spaceBelow > spaceAbove ? 'below' : 'above';\n }\n}; ","import React from 'react';\nimport { StoredMessage } from '../utils/messageStorage';\n\ninterface TranscriptBoxProps {\n messages: StoredMessage[];\n isVisible: boolean;\n onClose: () => void;\n showToggleButton?: boolean;\n onToggle?: () => void;\n showTextInput?: boolean;\n textInput?: string;\n onTextInputChange?: (value: string) => void;\n onTextSubmit?: () => void;\n onTextKeyPress?: (event: React.KeyboardEvent) => void;\n textPlaceholder?: string;\n}\n\nconst TranscriptBox: React.FC<TranscriptBoxProps> = ({ \n messages, \n isVisible, \n onClose, \n showToggleButton = true, \n onToggle,\n showTextInput = false,\n textInput = '',\n onTextInputChange,\n onTextSubmit,\n onTextKeyPress,\n textPlaceholder = \"Type your message...\"\n}) => {\n const formatTime = (timestamp: number) => {\n return new Date(timestamp).toLocaleTimeString([], { \n hour: '2-digit', \n minute: '2-digit' \n });\n };\n\n const scrollToBottom = (element: HTMLDivElement) => {\n element.scrollTop = element.scrollHeight;\n };\n\n React.useEffect(() => {\n const transcriptContainer = document.getElementById('guideai-transcript-container');\n if (transcriptContainer) {\n scrollToBottom(transcriptContainer as HTMLDivElement);\n }\n }, [messages]);\n\n // Show toggle button if there are messages and toggle is enabled, even when transcript is hidden\n const shouldShowToggleButton = showToggleButton && messages.length > 0;\n \n // Show transcript if visible OR if text input should be shown\n const shouldShowTranscript = isVisible || showTextInput;\n \n // Don't render anything if no messages, no toggle button, and no text input\n if (messages.length === 0 && !shouldShowToggleButton && !showTextInput) return null;\n\n return (\n <div className=\"guideai-transcript-overlay\">\n {/* Toggle Button - shows even when transcript is hidden */}\n {shouldShowToggleButton && (\n <button\n className=\"guideai-transcript-toggle-button\"\n onClick={onToggle}\n title={isVisible ? 'Hide Transcript' : 'Show Transcript'}\n >\n <span className=\"guideai-transcript-toggle-icon\">\n {isVisible ? '📄' : '📋'}\n </span>\n </button>\n )}\n \n {/* Transcript Box - show when visible or when text input is needed */}\n {shouldShowTranscript && (\n <div className=\"guideai-transcript-box\">\n {/* Messages Container - only show when transcript is visible */}\n {isVisible && (\n <div \n id=\"guideai-transcript-container\"\n className=\"guideai-transcript-messages\"\n >\n {messages.length === 0 ? (\n <div className=\"guideai-transcript-empty\">\n <div className=\"guideai-transcript-empty-icon\">🎤</div>\n <p>Start a conversation to see the transcript here</p>\n </div>\n ) : (\n messages.map((message, index) => (\n <div \n key={`${message.timestamp}-${index}`}\n className={`guideai-transcript-message ${message.sender.toLowerCase()}`}\n >\n <div className=\"guideai-transcript-message-content\">\n <div className=\"guideai-transcript-message-sender\">\n {message.sender === 'HUMAN' ? 'You' : 'GuideAI'}\n </div>\n <div className=\"guideai-transcript-message-text\">\n {message.content}\n </div>\n <div className=\"guideai-transcript-message-time\">\n {formatTime(message.timestamp)}\n </div>\n </div>\n </div>\n ))\n )}\n </div>\n )}\n \n {/* Text Input - show when in text mode */}\n {showTextInput && (\n <div className=\"guideai-transcript-text-input\">\n <textarea\n className=\"guideai-transcript-input-field\"\n value={textInput}\n onChange={(e) => onTextInputChange?.(e.target.value)}\n onKeyPress={onTextKeyPress}\n placeholder={textPlaceholder}\n rows={2}\n />\n <button\n className=\"guideai-transcript-send-button\"\n onClick={onTextSubmit}\n disabled={!textInput.trim()}\n title=\"Send Message\"\n >\n <span className=\"guideai-transcript-send-icon\">📤</span>\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default TranscriptBox; ","import React, { useState } from 'react';\nimport { PopupPosition } from '../types/GuideAI.types';\n\ninterface OnboardingProps {\n position: PopupPosition;\n isVisible: boolean;\n onComplete: () => void; // Called when user completes onboarding and wants to start conversation\n onClose: () => void; // Called when user closes onboarding without completing\n}\n\nconst Onboarding: React.FC<OnboardingProps> = ({ position, isVisible, onComplete, onClose }) => {\n const [step, setStep] = useState(1);\n\n const handleNext = () => {\n if (step < 3) {\n setStep(step + 1);\n } else {\n // Reset step and complete onboarding\n setStep(1);\n onComplete();\n }\n };\n\n const handleClose = () => {\n // Reset step when closing\n setStep(1);\n onClose();\n };\n\n if (!isVisible) {\n return null;\n }\n\n return (\n <div className={`guideai-onboarding ${position}`}>\n <div className=\"guideai-onboarding-content\">\n <button className=\"guideai-onboarding-close\" onClick={handleClose}>×</button>\n \n {step === 1 && (\n <div className=\"guideai-onboarding-step\">\n <div className=\"guideai-onboarding-icon volume-icon\">🔊</div>\n <h3>Turn on your volume</h3>\n <p>Make sure your device's volume is turned on so you can hear Guide AI's responses.</p>\n </div>\n )}\n \n {step === 2 && (\n <div className=\"guideai-onboarding-step\">\n <div className=\"guideai-onboarding-icon mic-icon\">🎤</div>\n <h3>Allow microphone access</h3>\n <p>When prompted, click \"Allow\" to let Guide AI access your microphone.</p>\n </div>\n )}\n \n {step === 3 && (\n <div className=\"guideai-onboarding-step\">\n <div className=\"guideai-onboarding-icon ready-icon\">✅</div>\n <h3>You're all set!</h3>\n <p>Click the microphone icon to start asking questions.</p>\n </div>\n )}\n \n <div className=\"guideai-onboarding-dots\">\n <span className={`dot ${step === 1 ? 'active' : ''}`}></span>\n <span className={`dot ${step === 2 ? 'active' : ''}`}></span>\n <span className={`dot ${step === 3 ? 'active' : ''}`}></span>\n </div>\n \n <button className=\"guideai-onboarding-next\" onClick={handleNext}>\n {step < 3 ? 'Next' : 'Get Started'}\n </button>\n </div>\n </div>\n );\n};\n\nexport default Onboarding; ","import React from 'react';\nimport { PopupPosition } from '../types/GuideAI.types';\n\ninterface WelcomeBubbleProps {\n position: PopupPosition;\n}\n\nconst WelcomeBubble: React.FC<WelcomeBubbleProps> = ({ position }) => {\n return (\n <div className={`guideai-welcome-bubble ${position}`}>\n Stuck? Click here and ask me a question\n </div>\n );\n};\n\nexport default WelcomeBubble; ","// Event tracking system for GuideAI\n// Tracks click, focus, change, and submit events on all relevant elements\n\ninterface EventData {\n type: 'click' | 'focus' | 'change' | 'submit' | 'route_change';\n element?: Element;\n tagName?: string;\n className?: string;\n id?: string;\n textContent?: string;\n value?: string;\n formData?: FormData;\n timestamp: number;\n url: string;\n previousUrl?: string;\n event?: Event;\n // Customer metadata\n customerId?: string;\n customerType?: string;\n customerSegment?: string;\n // Session metadata\n sessionId?: string;\n deviceType?: 'desktop' | 'mobile' | 'tablet';\n userAgent?: string;\n screenResolution?: string;\n // Application context\n currentPage?: string;\n userRole?: string;\n organizationId?: string;\n // Geographic and timezone\n timezone?: string;\n locale?: string;\n}\n\nclass EventTracker {\n private isTracking: boolean = false;\n private eventData: EventData[] = [];\n private batchSize: number = 10; // Emit every 10 events\n private batchTimeout: number = 5000; // Emit every 5 seconds\n private batchTimer: NodeJS.Timeout | null = null;\n private pendingEvents: EventData[] = [];\n private currentUrl: string = '';\n private organizationKey?: string;\n\n // Customer metadata storage\n private customerMetadata: {\n customerId?: string;\n customerType?: string;\n customerSegment?: string;\n userRole?: string;\n organizationId?: string;\n } = {};\n\n constructor(options?: { customerId?: string; customerType?: string; organizationId?: string; organizationKey?: string; }) {\n if (options?.customerId) {\n this.customerMetadata.customerId = String(options.customerId);\n }\n if (options?.customerType) {\n this.customerMetadata.customerType = options.customerType;\n }\n if (options?.organizationId) {\n this.customerMetadata.organizationId = String(options.organizationId);\n }\n if (options?.organizationKey) {\n this.organizationKey = options.organizationKey;\n }\n // Do not auto-initialize on server; caller should invoke initialize() on client\n }\n\n\n\n // Method to set customer metadata\n public setCustomerMetadata(metadata: Partial<typeof this.customerMetadata>): void {\n // All remaining metadata is safe to collect\n this.customerMetadata = { ...this.customerMetadata, ...metadata };\n }\n\n // Method to get customer metadata\n public getCustomerMetadata(): typeof this.customerMetadata {\n return { ...this.customerMetadata };\n }\n\n // Method to clear customer metadata\n public clearCustomerMetadata(): void {\n this.customerMetadata = {};\n }\n\n public initialize(): void {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n // Start tracking when DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => this.startTracking());\n } else {\n this.startTracking();\n }\n }\n\n // Helper method to enrich event data with customer metadat\n private enrichEventData(baseEventData: Omit<EventData, 'customerId' | 'customerType' | 'customerSegment' | 'sessionId' | 'deviceType' | 'userAgent' | 'screenResolution' | 'currentPage' | 'userRole' | 'organizationId' | 'timezone' | 'locale'>): EventData {\n const enrichedData = {\n ...baseEventData,\n // Customer metadata\n customerId: this.customerMetadata.customerId,\n customerType: this.customerMetadata.customerType,\n customerSegment: this.customerMetadata.customerSegment,\n organizationKey: this.organizationKey,\n // Session metadata\n sessionId: this.getSessionId(),\n deviceType: this.getDeviceType(),\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : undefined,\n screenResolution: typeof screen !== 'undefined' ? `${screen.width}x${screen.height}` : undefined,\n // Application context\n currentPage: window.location.pathname,\n userRole: this.customerMetadata.userRole,\n organizationId: this.customerMetadata.organizationId,\n // Geographic and timezone\n timezone: typeof Intl !== 'undefined' && typeof Intl.DateTimeFormat !== 'undefined'\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefined,\n locale: navigator.language,\n };\n\n return enrichedData;\n }\n\n\n\n // Helper method to get or create session ID\n private getSessionId(): string {\n let sessionId = sessionStorage.getItem('eventTracker_sessionId');\n if (!sessionId) {\n sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n sessionStorage.setItem('eventTracker_sessionId', sessionId);\n }\n return sessionId;\n }\n\n // Helper method to detect device type\n private getDeviceType(): 'desktop' | 'mobile' | 'tablet' {\n if (typeof navigator === 'undefined') {\n return 'desktop';\n }\n const userAgent = navigator.userAgent.toLowerCase();\n if (/tablet|ipad|playbook|silk/i.test(userAgent)) {\n return 'tablet';\n }\n if (/mobile|android|iphone|ipod|blackberry|opera mini|iemobile/i.test(userAgent)) {\n return 'mobile';\n }\n return 'desktop';\n }\n\n public startTracking(): void {\n if (this.isTracking) return;\n\n this.isTracking = true;\n console.log('EventTracker: Started tracking events');\n\n // Track click events on all elements\n this.trackClickEvents();\n\n // Track focus events on focusable elements\n this.trackFocusEvents();\n\n // Track change events on form elements\n this.trackChangeEvents();\n\n // Track submit events on forms\n this.trackSubmitEvents();\n\n // Track route changes\n this.trackRouteChanges();\n }\n\n public stopTracking(): void {\n if (!this.isTracking) return;\n\n this.isTracking = false;\n console.log('EventTracker: Stopped tracking events');\n\n // Emit any pending events before stopping\n this.emitBatch();\n\n // Remove all event listeners\n document.removeEventListener('click', this.handleClick, true);\n document.removeEventListener('focus', this.handleFocus, true);\n document.removeEventListener('change', this.handleChange, true);\n document.removeEventListener('submit', this.handleSubmit, true);\n window.removeEventListener('popstate', this.handlePopstate);\n window.removeEventListener('hashchange', this.handleHashChange);\n }\n\n private trackClickEvents(): void {\n document.addEventListener('click', this.handleClick, true);\n }\n\n private trackFocusEvents(): void {\n document.addEventListener('focus', this.handleFocus, true);\n }\n\n private trackChangeEvents(): void {\n document.addEventListener('change', this.handleChange, true);\n }\n\n private trackSubmitEvents(): void {\n document.addEventListener('submit', this.handleSubmit, true);\n }\n\n private trackRouteChanges(): void {\n // Track browser back/forward navigation\n window.addEventListener('popstate', this.handlePopstate);\n\n // Track hash changes\n window.addEventListener('hashchange', this.handleHashChange);\n\n // Track History API changes (pushState, replaceState)\n this.interceptHistoryAPI();\n }\n\n private handleClick = (event: Event): void => {\n if (!this.isTracking) return;\n\n const target = event.target as Element;\n const baseEventData = {\n type: 'click' as const,\n element: target,\n tagName: target.tagName,\n className: target.className,\n id: target.id,\n textContent: target.textContent?.substring(0, 100),\n value: this.getSafeValue(target),\n timestamp: Date.now(),\n url: window.location.href,\n event: event\n };\n\n this.logEvent(baseEventData);\n };\n\n private handleFocus = (event: Event): void => {\n if (!this.isTracking) return;\n\n const target = event.target as Element;\n\n // Only track focus on focusable elements\n if (this.isFocusable(target)) {\n const baseEventData = {\n type: 'focus' as const,\n element: target,\n tagName: target.tagName,\n className: target.className,\n id: target.id,\n textContent: target.textContent?.substring(0, 100),\n value: this.getSafeValue(target),\n timestamp: Date.now(),\n url: window.location.href,\n event: event\n };\n\n this.logEvent(baseEventData);\n }\n };\n\n private handleChange = (event: Event): void => {\n if (!this.isTracking) return;\n\n const target = event.target as Element;\n\n // Only track change on form elements\n if (this.isFormElement(target)) {\n const baseEventData = {\n type: 'change' as const,\n element: target,\n tagName: target.tagName,\n className: target.className,\n id: target.id,\n textContent: target.textContent?.substring(0, 100),\n value: this.getSafeValue(target),\n timestamp: Date.now(),\n url: window.location.href,\n event: event\n };\n\n this.logEvent(baseEventData);\n }\n };\n\n private handleSubmit = (event: Event): void => {\n if (!this.isTracking) return;\n\n const target = event.target as Element;\n\n // Only track submit on form elements\n if (target.tagName === 'FORM') {\n const form = target as HTMLFormElement;\n const formData = new FormData(form);\n\n const baseEventData = {\n type: 'submit' as const,\n element: target,\n tagName: target.tagName,\n className: target.className,\n id: target.id,\n textContent: target.textContent?.substring(0, 100),\n formData: formData,\n timestamp: Date.now(),\n url: window.location.href,\n event: event\n };\n\n this.logEvent(baseEventData);\n }\n };\n\n private handlePopstate = (event: PopStateEvent): void => {\n if (!this.isTracking) return;\n\n const baseEventData = {\n type: 'route_change' as const,\n timestamp: Date.now(),\n url: window.location.href,\n previousUrl: this.getPreviousUrl(),\n event: event\n };\n\n this.logEvent(baseEventData);\n };\n\n private handleHashChange = (event: HashChangeEvent): void => {\n if (!this.isTracking) return;\n\n const baseEventData = {\n type: 'route_change' as const,\n timestamp: Date.now(),\n url: window.location.href,\n previousUrl: event.oldURL,\n event: event\n };\n\n this.logEvent(baseEventData);\n };\n\n private interceptHistoryAPI(): void {\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n\n // Store the current URL before interception\n this.currentUrl = window.location.href;\n\n // Intercept pushState\n history.pushState = (...args) => {\n const previousUrl = this.currentUrl;\n const result = originalPushState.apply(history, args);\n this.currentUrl = window.location.href;\n\n if (this.isTracking) {\n const baseEventData = {\n type: 'route_change' as const,\n timestamp: Date.now(),\n url: window.location.href,\n previousUrl: previousUrl\n };\n this.logEvent(baseEventData);\n }\n\n return result;\n };\n\n // Intercept replaceState\n history.replaceState = (...args) => {\n const previousUrl = this.currentUrl;\n const result = originalReplaceState.apply(history, args);\n this.currentUrl = window.location.href;\n\n if (this.isTracking) {\n const baseEventData = {\n type: 'route_change' as const,\n timestamp: Date.now(),\n url: window.location.href,\n previousUrl: previousUrl\n };\n this.logEvent(baseEventData);\n }\n\n return result;\n };\n }\n\n private getPreviousUrl(): string {\n return this.currentUrl || window.location.href;\n }\n\n private getSafeValue(element: Element): string | undefined {\n const tagName = element.tagName.toLowerCase();\n const inputElement = element as HTMLInputElement;\n const selectElement = element as HTMLSelectElement;\n\n // Only collect values for elements that are typically useful for targeting\n switch (tagName) {\n case 'button':\n return inputElement.value || inputElement.textContent?.trim();\n\n case 'select':\n return `${selectElement.name || ''}|${selectElement.type || ''}|${selectElement.selectedIndex || 0}`;\n\n case 'textarea':\n return inputElement.name || inputElement.type || '';\n\n case 'input':\n const inputType = inputElement.type;\n // Only collect value for button-like input types\n if (inputType === 'submit' || inputType === 'button' || inputType === 'reset') {\n return `${inputElement.name || ''}|${inputType}|${inputElement.value || ''}`;\n }\n // For other input types, only collect name and type, not the actual value\n return `${inputElement.name || ''}|${inputType}`;\n\n default:\n return undefined;\n }\n }\n\n private isFocusable(element: Element): boolean {\n const focusableSelectors = [\n 'input:not([type=\"hidden\"])',\n 'select',\n 'textarea',\n 'button',\n 'a[href]',\n 'area[href]',\n 'iframe',\n 'object',\n 'embed',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]'\n ];\n\n return focusableSelectors.some(selector => element.matches(selector));\n }\n\n private isFormElement(element: Element): boolean {\n const formElementTags = ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'];\n return formElementTags.includes(element.tagName);\n }\n\n private logEvent(baseEventData: Omit<EventData, 'customerType' | 'customerSegment' | 'sessionId' | 'deviceType' | 'currentPage' | 'userRole' | 'locale'>): void {\n // Enrich the event data with customer metadata\n const enrichedEventData = this.enrichEventData(baseEventData);\n\n // Store event data for historical access\n this.eventData.push(enrichedEventData);\n\n // Add to pending batch\n this.pendingEvents.push(enrichedEventData);\n\n // Check if we should emit based on batch size\n if (this.pendingEvents.length >= this.batchSize) {\n this.emitBatch();\n } else {\n // Start or reset the timeout for time-based emission\n this.startBatchTimer();\n }\n }\n\n private startBatchTimer(): void {\n // Clear existing timer\n if (this.batchTimer) {\n clearTimeout(this.batchTimer);\n }\n\n // Start new timer\n this.batchTimer = setTimeout(() => {\n this.emitBatch();\n }, this.batchTimeout);\n }\n\n private emitBatch(): void {\n if (this.pendingEvents.length === 0) return;\n\n // Create batch payload\n const batchPayload = {\n events: [...this.pendingEvents],\n batchSize: this.pendingEvents.length,\n timestamp: Date.now(),\n\n };\n\n // Console log the batch (for now)\n console.log('EventTracker Batch:', batchPayload);\n\n // Emit custom event for metadata tracking integration\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('guideai:event_batch', {\n detail: batchPayload\n }));\n }\n\n\n\n // Clear pending events\n this.pendingEvents = [];\n\n // Clear timer\n if (this.batchTimer) {\n clearTimeout(this.batchTimer);\n this.batchTimer = null;\n }\n }\n\n public getEventData(): EventData[] {\n return [...this.eventData];\n }\n\n public clearEventData(): void {\n this.eventData = [];\n }\n\n public getEventDataByType(type: EventData['type']): EventData[] {\n return this.eventData.filter(event => event.type === type);\n }\n\n public getEventDataByElement(tagName: string): EventData[] {\n return this.eventData.filter(event => event.tagName === tagName.toUpperCase());\n }\n\n public getEventDataByUrl(url: string): EventData[] {\n return this.eventData.filter(event => event.url.includes(url));\n }\n\n public emitPendingEvents(): void {\n this.emitBatch();\n }\n\n public setBatchConfig(batchSize: number, batchTimeout: number): void {\n this.batchSize = batchSize;\n this.batchTimeout = batchTimeout;\n }\n\n public getPendingEventsCount(): number {\n return this.pendingEvents.length;\n }\n\n // Customer analytics methods\n public getCustomerAnalytics(): {\n totalEvents: number;\n eventsByCustomer: Record<string, number>;\n eventsByType: Record<string, number>;\n eventsByPage: Record<string, number>;\n eventsByDevice: Record<string, number>;\n sessionDuration: number;\n lastActivity: number;\n } {\n const now = Date.now();\n const sessionStart = this.getSessionStartTime();\n const sessionDuration = now - sessionStart;\n\n const analytics = {\n totalEvents: this.eventData.length,\n eventsByCustomer: {} as Record<string, number>,\n eventsByType: {} as Record<string, number>,\n eventsByPage: {} as Record<string, number>,\n eventsByDevice: {} as Record<string, number>,\n sessionDuration,\n lastActivity: this.eventData.length > 0 ? this.eventData[this.eventData.length - 1].timestamp : now\n };\n\n // Group events by customer\n this.eventData.forEach(event => {\n if (event.customerId) {\n analytics.eventsByCustomer[event.customerId] = (analytics.eventsByCustomer[event.customerId] || 0) + 1;\n }\n\n // Group events by type\n analytics.eventsByType[event.type] = (analytics.eventsByType[event.type] || 0) + 1;\n\n // Group events by page\n if (event.currentPage) {\n analytics.eventsByPage[event.currentPage] = (analytics.eventsByPage[event.currentPage] || 0) + 1;\n }\n\n // Group events by device\n if (event.deviceType) {\n analytics.eventsByDevice[event.deviceType] = (analytics.eventsByDevice[event.deviceType] || 0) + 1;\n }\n });\n\n return analytics;\n }\n\n // Get session start time\n private getSessionStartTime(): number {\n const sessionStart = sessionStorage.getItem('eventTracker_sessionStart');\n if (!sessionStart) {\n const startTime = Date.now();\n sessionStorage.setItem('eventTracker_sessionStart', startTime.toString());\n return startTime;\n }\n return parseInt(sessionStart, 10);\n }\n\n // Method to identify customer from DOM or context\n public identifyCustomerFromContext(): void {\n // Try to find customer information from the current page context\n // This could be from meta tags, data attributes, or other DOM elements\n\n\n\n // Check for user role in meta tags\n const userRoleMeta = document.querySelector('meta[name=\"user-role\"]');\n if (userRoleMeta) {\n this.setCustomerMetadata({ userRole: userRoleMeta.getAttribute('content') || undefined });\n }\n\n\n\n // Try to infer customer type from URL or page context\n const pathname = window.location.pathname;\n if (pathname.includes('/admin/')) {\n this.setCustomerMetadata({ customerType: 'admin' });\n } else if (pathname.includes('/agent/')) {\n this.setCustomerMetadata({ customerType: 'agent' });\n } else if (pathname.includes('/business/')) {\n this.setCustomerMetadata({ customerType: 'business' });\n } else if (pathname.includes('/individual/')) {\n this.setCustomerMetadata({ customerType: 'individual' });\n }\n }\n\n // Method to set customer metadata from external source (e.g., authentication system)\n public setCustomerFromAuth(authData: {\n id?: string;\n role?: string;\n customerType?: 'individual' | 'business' | 'agent' | 'admin';\n customerSegment?: string;\n }): void {\n this.setCustomerMetadata({\n userRole: authData.role,\n customerType: authData.customerType,\n customerSegment: authData.customerSegment\n });\n }\n\n\n}\n\nexport default EventTracker;\nexport type { EventData };\n\n// Export customer metadata types for external use\nexport interface CustomerMetadata {\n customerId?: string;\n customerType?: 'individual' | 'business' | 'agent' | 'admin';\n customerSegment?: string;\n userRole?: string;\n}\n\nexport interface CustomerAnalytics {\n totalEvents: number;\n eventsByCustomer: Record<string, number>;\n eventsByType: Record<string, number>;\n eventsByPage: Record<string, number>;\n eventsByDevice: Record<string, number>;\n sessionDuration: number;\n lastActivity: number;\n}\n","// Create click effects and dispatch click event on an element\nexport const clickElement = async (element: Element, rect: DOMRect): Promise<void> => {\n return new Promise<void>((resolve) => {\n setTimeout(() => {\n const clickEffectContainer = document.createElement('div');\n clickEffectContainer.style.cssText = `\n position: fixed;\n left: ${rect.left + rect.width / 2}px;\n top: ${rect.top + rect.height / 2}px;\n width: 60px;\n height: 60px;\n z-index: 1000;\n pointer-events: none;\n transform: translate(-50%, -50%);\n `;\n document.body.appendChild(clickEffectContainer);\n \n for (let j = 0; j < 3; j++) {\n const clickRipple = document.createElement('div');\n clickRipple.style.cssText = `\n position: absolute;\n left: 50%;\n top: 50%;\n width: 40px;\n height: 40px;\n border: 2px solid rgba(0, 102, 255, ${0.7 - (j * 0.2)});\n border-radius: 50%;\n transform: translate(-50%, -50%) scale(0);\n opacity: 1;\n animation: click-ripple-animation 0.8s ease-out ${j * 0.15}s forwards;\n box-shadow: 0 0 8px rgba(0, 102, 255, 0.4);\n `;\n clickEffectContainer.appendChild(clickRipple);\n }\n \n const clickDot = document.createElement('div');\n clickDot.style.cssText = `\n position: absolute;\n left: 50%;\n top: 50%;\n width: 12px;\n height: 12px;\n background: rgba(0, 102, 255, 0.9);\n border-radius: 50%;\n transform: translate(-50%, -50%) scale(0);\n animation: click-dot-animation 0.4s ease-out forwards;\n box-shadow: 0 0 5px rgba(0, 102, 255, 0.8);\n `;\n clickEffectContainer.appendChild(clickDot);\n \n const clickEvent = new MouseEvent('click', {\n view: window,\n bubbles: true,\n cancelable: true,\n });\n\n // Check for clickable subelements (links, buttons, inputs)\n const clickableElements = element.querySelectorAll('a, button, input[type=\"button\"], input[type=\"submit\"]');\n const clickableElement = clickableElements.length > 0 ? clickableElements[0] as HTMLElement : element as HTMLElement;\n console.log('Clicking element:', clickableElement);\n clickableElement.dispatchEvent(clickEvent);\n\n const originalBoxShadow = clickableElement.style.boxShadow;\n const originalTransition = clickableElement.style.transition;\n const originalZIndex = clickableElement.style.zIndex;\n\n clickableElement.style.transition = 'all 0.3s ease-out';\n clickableElement.style.boxShadow = '0 0 0 2px rgba(0, 102, 255, 0.5), 0 0 10px rgba(0, 102, 255, 0.3)';\n clickableElement.style.zIndex = '999';\n\n setTimeout(() => {\n clickableElement.style.boxShadow = originalBoxShadow;\n clickableElement.style.transition = originalTransition;\n clickableElement.style.zIndex = originalZIndex;\n\n clickEffectContainer.remove(); \n resolve();\n }, 1000);\n\n }, 1500);\n });\n};\n\n// Highlight elements on the page with animated cursor and click effects\nexport const highlightElement = async (\n selector: string | string[],\n isHighlighting: boolean,\n setIsHighlighting: (highlighting: boolean) => void,\n logMessage: (content: string, sender: 'GUIDEAI' | 'HUMAN') => void\n): Promise<boolean> => {\n if (isHighlighting) return false;\n \n const selectors = Array.isArray(selector) ? selector : [selector];\n if (selectors.length === 0) return false;\n \n console.log('Moving cursor to elements:', selectors);\n \n let cursorElement: HTMLElement | null = null;\n try {\n setIsHighlighting(true);\n \n for (let i = 0; i < selectors.length; i++) {\n const currentSelector = selectors[i];\n \n if (i > 0) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n }\n \n let element;\n if (currentSelector.startsWith('//')) {\n const node = document.evaluate(currentSelector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\n if (!(node instanceof Element)) {\n console.log('XPath returned a non-Element node:', currentSelector);\n console.log(node);\n logMessage('XPath returned a non-Element node: ' + currentSelector, 'GUIDEAI');\n break;\n }\n element = node as Element;\n } else {\n element = document.querySelector(currentSelector);\n }\n \n if (!element) {\n console.log('Element not found:', currentSelector);\n logMessage('Element not found: ' + currentSelector, 'GUIDEAI');\n break;\n }\n \n const rect = element.getBoundingClientRect();\n \n // Create cursor if it's the first element, or reuse existing cursor\n if (!cursorElement) {\n cursorElement = document.createElement('div');\n cursorElement.id = 'guide-ai-cursor';\n \n const blueCursorSvg = `\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill=\"#0066ff\" d=\"M7,2l12,11.2l-5.8,0.5l3.3,7.3l-2.2,1l-3.2-7.4L7,18.5V2\" />\n </svg>\n `;\n \n cursorElement.innerHTML = blueCursorSvg;\n cursorElement.style.cssText = `\n position: fixed;\n width: 64px;\n height: 64px;\n pointer-events: none;\n z-index: 9999;\n transition: all 0.8s ease-in-out;\n transform: translate(-50%, 0);\n filter: drop-shadow(0 0 4px rgba(0, 102, 255, 0.8));\n `;\n \n document.body.appendChild(cursorElement);\n \n // First element starts from center of viewport\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n cursorElement.style.left = `${viewportWidth / 2}px`;\n cursorElement.style.top = `${viewportHeight / 2}px`;\n }\n \n // Force reflow to ensure transition works\n cursorElement!.offsetHeight;\n \n await new Promise<void>(resolve => {\n setTimeout(() => {\n cursorElement!.style.left = `${rect.left + rect.width / 2}px`;\n cursorElement!.style.top = `${rect.top + rect.height / 2 - 10}px`;\n \n setTimeout(() => {\n cursorElement!.style.animation = 'cursor-jiggle 0.5s ease-in-out infinite';\n resolve();\n }, 800);\n }, 100);\n });\n \n await clickElement(element, rect);\n }\n\n setTimeout(() => {\n cursorElement?.remove();\n setIsHighlighting(false);\n }, 1000);\n \n return true;\n } catch (error) {\n console.error('Error moving cursor:', error);\n cursorElement?.remove();\n setIsHighlighting(false);\n return false;\n }\n}; ","// User metadata tracking system for GuideAI\n// Tracks user visits, logins, and other metadata for Overproof integration\n\nimport { \n UserMetadata, \n MetadataConfig, \n MetadataStorageData, \n MetadataEvent, \n MetadataEventType,\n MetadataUpdate \n} from '../types/metadata.types';\nimport { sendMetadataUpdates } from '../utils/api';\n\nconst METADATA_STORAGE_KEY = 'guideai_user_metadata';\nconst METADATA_VERSION = '1.0.0';\n\nclass UserMetadataTracker {\n private config: Required<MetadataConfig>;\n private metadata: UserMetadata;\n private syncTimer: NodeJS.Timeout | null = null;\n private pendingUpdates: MetadataUpdate[] = [];\n private isInitialized: boolean = false;\n private onError?: (error: Error, context: string) => void;\n\n constructor(organizationKey: string, config: MetadataConfig = {}, onError?: (error: Error, context: string) => void) {\n this.config = {\n trackVisits: true,\n trackLogins: true,\n syncInterval: 30000, // 30 seconds\n storage: 'localStorage',\n customFields: [],\n collectBrowserInfo: true,\n collectUserAgent: true,\n ...config\n };\n\n this.metadata = {\n organizationKey,\n visitCount: 0,\n loginCount: 0\n };\n \n this.onError = onError;\n\n this.init();\n }\n\n private init(): void {\n if (this.isInitialized) return;\n\n // Load existing metadata from storage\n this.loadMetadata();\n\n // Collect browser info if enabled\n if (this.config.collectBrowserInfo) {\n this.collectBrowserInfo();\n }\n\n // Track initial visit if enabled\n if (this.config.trackVisits) {\n this.trackVisit();\n }\n\n // Start sync timer\n this.startSyncTimer();\n\n // Listen for EventTracker events to detect user interactions\n this.setupEventTrackerIntegration();\n\n this.isInitialized = true;\n console.log('UserMetadataTracker: Initialized', this.metadata);\n }\n\n public updateUserInfo(userInfo: Partial<UserMetadata>): void {\n const timestamp = Date.now();\n \n // Update metadata\n this.metadata = {\n ...this.metadata,\n ...userInfo,\n lastVisit: timestamp\n };\n\n // Add to pending updates\n this.pendingUpdates.push({\n type: 'user_info',\n timestamp,\n data: userInfo\n });\n\n // Save to storage\n this.saveMetadata();\n\n console.log('UserMetadataTracker: User info updated', userInfo);\n }\n\n public trackLogin(additionalInfo?: Partial<UserMetadata>): void {\n if (!this.config.trackLogins) return;\n\n const timestamp = Date.now();\n \n this.metadata = {\n ...this.metadata,\n ...additionalInfo,\n loginCount: (this.metadata.loginCount || 0) + 1,\n lastLogin: timestamp,\n lastVisit: timestamp\n };\n\n this.pendingUpdates.push({\n type: 'login',\n timestamp,\n data: {\n loginCount: this.metadata.loginCount,\n lastLogin: timestamp,\n ...additionalInfo\n }\n });\n\n this.saveMetadata();\n console.log('UserMetadataTracker: Login tracked', this.metadata.loginCount);\n }\n\n public trackVisit(): void {\n if (!this.config.trackVisits) return;\n\n const timestamp = Date.now();\n const isFirstVisit = !this.metadata.firstVisit;\n\n this.metadata = {\n ...this.metadata,\n firstVisit: this.metadata.firstVisit || timestamp,\n lastVisit: timestamp,\n visitCount: (this.metadata.visitCount || 0) + 1\n };\n\n this.pendingUpdates.push({\n type: 'visit',\n timestamp,\n data: {\n firstVisit: this.metadata.firstVisit,\n lastVisit: this.metadata.lastVisit,\n visitCount: this.metadata.visitCount\n }\n });\n\n this.saveMetadata();\n \n console.log(`UserMetadataTracker: ${isFirstVisit ? 'First' : 'Return'} visit tracked`, {\n visitCount: this.metadata.visitCount,\n firstVisit: this.metadata.firstVisit,\n lastVisit: this.metadata.lastVisit\n });\n }\n\n public trackCustomEvent(eventType: string, customData: Record<string, any>): void {\n const timestamp = Date.now();\n\n // Update custom fields if they're in the config\n const customFields = { ...this.metadata.customFields };\n for (const [key, value] of Object.entries(customData)) {\n if (this.config.customFields.includes(key)) {\n customFields[key] = value;\n }\n }\n\n this.metadata = {\n ...this.metadata,\n customFields,\n lastVisit: timestamp\n };\n\n this.pendingUpdates.push({\n type: 'custom',\n timestamp,\n data: { customFields }\n });\n\n this.saveMetadata();\n console.log('UserMetadataTracker: Custom event tracked', eventType, customData);\n }\n\n public getMetadata(): UserMetadata {\n return { ...this.metadata };\n }\n\n public getPendingUpdates(): MetadataUpdate[] {\n return [...this.pendingUpdates];\n }\n\n public clearPendingUpdates(): void {\n this.pendingUpdates = [];\n }\n\n public syncNow(): MetadataUpdate[] {\n const updates = [...this.pendingUpdates];\n this.clearPendingUpdates();\n return updates;\n }\n\n private loadMetadata(): void {\n try {\n const storageData = this.getFromStorage();\n if (storageData && storageData.metadata) {\n // Merge stored metadata with current metadata\n this.metadata = {\n ...this.metadata,\n ...storageData.metadata\n };\n console.log('UserMetadataTracker: Loaded metadata from storage', this.metadata);\n }\n } catch (error) {\n console.warn('UserMetadataTracker: Failed to load metadata from storage', error);\n // Clear corrupted data\n this.clearStorage();\n }\n }\n\n private saveMetadata(): void {\n try {\n const storageData: MetadataStorageData = {\n metadata: this.metadata,\n lastUpdated: Date.now(),\n version: METADATA_VERSION\n };\n\n this.setToStorage(storageData);\n } catch (error) {\n console.warn('UserMetadataTracker: Failed to save metadata to storage', error);\n }\n }\n\n private collectBrowserInfo(): void {\n if (typeof window === 'undefined') return;\n\n const userAgent = navigator.userAgent;\n const browserInfo = this.parseBrowserInfo(userAgent);\n\n this.metadata = {\n ...this.metadata,\n userAgent: this.config.collectUserAgent ? userAgent : undefined,\n browserInfo\n };\n }\n\n private parseBrowserInfo(userAgent: string): UserMetadata['browserInfo'] {\n // Simple browser detection - could be enhanced with a proper library\n let name = 'Unknown';\n let version = 'Unknown';\n let platform = 'Unknown';\n\n // Detect browser\n if (userAgent.includes('Chrome') && !userAgent.includes('Edg')) {\n name = 'Chrome';\n const match = userAgent.match(/Chrome\\/([0-9.]+)/);\n version = match ? match[1] : 'Unknown';\n } else if (userAgent.includes('Firefox')) {\n name = 'Firefox';\n const match = userAgent.match(/Firefox\\/([0-9.]+)/);\n version = match ? match[1] : 'Unknown';\n } else if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) {\n name = 'Safari';\n const match = userAgent.match(/Version\\/([0-9.]+)/);\n version = match ? match[1] : 'Unknown';\n } else if (userAgent.includes('Edg')) {\n name = 'Edge';\n const match = userAgent.match(/Edg\\/([0-9.]+)/);\n version = match ? match[1] : 'Unknown';\n }\n\n // Detect platform\n if (userAgent.includes('Win')) platform = 'Windows';\n else if (userAgent.includes('Mac')) platform = 'macOS';\n else if (userAgent.includes('Linux')) platform = 'Linux';\n else if (userAgent.includes('Android')) platform = 'Android';\n else if (userAgent.includes('iOS')) platform = 'iOS';\n\n return { name, version, platform };\n }\n\n private startSyncTimer(): void {\n if (this.syncTimer) return;\n\n this.syncTimer = setInterval(() => {\n if (this.pendingUpdates.length > 0) {\n this.emitPendingUpdates();\n }\n }, this.config.syncInterval);\n }\n\n private setupEventTrackerIntegration(): void {\n if (typeof window === 'undefined') return;\n\n // Listen for EventTracker batches to detect user interactions\n const handleEventBatch = (event: Event) => {\n const customEvent = event as CustomEvent;\n const batchData = customEvent.detail;\n if (batchData && batchData.events) {\n // Look for login-related events (form submissions, clicks on login buttons, etc.)\n const hasLoginEvent = batchData.events.some((evt: any) => \n evt.type === 'submit' || \n (evt.type === 'click' && (\n evt.textContent?.toLowerCase().includes('login') ||\n evt.textContent?.toLowerCase().includes('sign in') ||\n evt.className?.toLowerCase().includes('login') ||\n evt.id?.toLowerCase().includes('login')\n ))\n );\n\n if (hasLoginEvent) {\n console.log('UserMetadataTracker: Detected potential login event from EventTracker');\n // Note: We don't automatically track login here as it requires explicit confirmation\n // This is just for detecting potential login scenarios\n }\n\n // Track general user activity\n const timestamp = Date.now();\n this.metadata = {\n ...this.metadata,\n lastVisit: timestamp\n };\n }\n };\n\n window.addEventListener('guideai:event_batch', handleEventBatch);\n \n // Store the listener for cleanup\n (this as any)._eventTrackerListener = handleEventBatch;\n }\n\n private stopSyncTimer(): void {\n if (this.syncTimer) {\n clearInterval(this.syncTimer);\n this.syncTimer = null;\n }\n }\n\n private async emitPendingUpdates(): Promise<void> {\n if (this.pendingUpdates.length === 0) return;\n\n const updates = [...this.pendingUpdates];\n \n // Emit the updates (integrate with existing event system)\n console.log('UserMetadataTracker: Emitting metadata updates', {\n updateCount: updates.length,\n updates,\n currentMetadata: this.metadata\n });\n\n // Send to backend API\n try {\n if (this.onError) {\n await sendMetadataUpdates(updates, this.metadata.organizationKey, this.onError);\n }\n \n // Clear pending updates after successful emission\n this.clearPendingUpdates();\n } catch (error) {\n console.warn('UserMetadataTracker: Failed to send metadata updates, will retry later', error);\n // Don't clear pending updates so they can be retried\n }\n }\n\n private getFromStorage(): MetadataStorageData | null {\n try {\n const key = `${METADATA_STORAGE_KEY}_${this.metadata.organizationKey}`;\n let data: string | null = null;\n\n switch (this.config.storage) {\n case 'localStorage':\n data = typeof window !== 'undefined' ? localStorage.getItem(key) : null;\n break;\n case 'sessionStorage':\n data = typeof window !== 'undefined' ? sessionStorage.getItem(key) : null;\n break;\n case 'memory':\n // For memory storage, we don't persist across sessions\n return null;\n }\n\n return data ? JSON.parse(data) : null;\n } catch (error) {\n console.warn('UserMetadataTracker: Error reading from storage', error);\n return null;\n }\n }\n\n private setToStorage(data: MetadataStorageData): void {\n try {\n const key = `${METADATA_STORAGE_KEY}_${this.metadata.organizationKey}`;\n const serialized = JSON.stringify(data);\n\n switch (this.config.storage) {\n case 'localStorage':\n if (typeof window !== 'undefined') {\n localStorage.setItem(key, serialized);\n }\n break;\n case 'sessionStorage':\n if (typeof window !== 'undefined') {\n sessionStorage.setItem(key, serialized);\n }\n break;\n case 'memory':\n // For memory storage, we don't persist\n break;\n }\n } catch (error) {\n console.warn('UserMetadataTracker: Error writing to storage', error);\n }\n }\n\n private clearStorage(): void {\n try {\n const key = `${METADATA_STORAGE_KEY}_${this.metadata.organizationKey}`;\n\n switch (this.config.storage) {\n case 'localStorage':\n if (typeof window !== 'undefined') {\n localStorage.removeItem(key);\n }\n break;\n case 'sessionStorage':\n if (typeof window !== 'undefined') {\n sessionStorage.removeItem(key);\n }\n break;\n case 'memory':\n // Nothing to clear for memory storage\n break;\n }\n } catch (error) {\n console.warn('UserMetadataTracker: Error clearing storage', error);\n }\n }\n\n public destroy(): void {\n // Emit any pending updates before destroying\n this.emitPendingUpdates();\n \n // Stop sync timer\n this.stopSyncTimer();\n \n // Remove event listener\n if (typeof window !== 'undefined' && (this as any)._eventTrackerListener) {\n window.removeEventListener('guideai:event_batch', (this as any)._eventTrackerListener);\n }\n \n // Clear state\n this.isInitialized = false;\n this.pendingUpdates = [];\n \n console.log('UserMetadataTracker: Destroyed');\n }\n}\n\nexport default UserMetadataTracker;\nexport type { UserMetadata, MetadataConfig, MetadataUpdate };\n","// Metric exports\nexport { default as EventTracker } from './event-listner';\nexport type { EventData } from './event-listner';\nexport { default as UserMetadataTracker } from './metadata-tracker';\nexport type { UserMetadata, MetadataConfig, MetadataUpdate } from './metadata-tracker';","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(258);\n"],"names":["root","factory","exports","module","require","define","amd","this","__WEBPACK_EXTERNAL_MODULE__156__","guideAIStyles","CONVERSATION_STORAGE_KEY","CONVERSATION_EXPIRY_MINUTES","MAX_STORED_MESSAGES","isLocalStorageAvailable","testKey","localStorage","setItem","removeItem","e","isConversationExpired","conversation","expiryTime","Date","now","timestamp","handleStorageError","error","operation","console","DOMException","name","loadConversationFromStorage","messages","length","slice","saveConversationToStorage","warn","clearConversationStorage","cleanupError","JSON","stringify","storedData","getItem","parsedData","parse","data","conversationId","Array","isArray","organizationKey","every","msg","content","sender","addMessageToStorage","message","some","existingMsg","Math","abs","log","substring","push","checkForStoredConversation","currentOrganizationKey","storedConversation","shouldRestore","formatConversationContext","maxMessages","recentMessages","meaningfulMessages","filter","trim","map","join","DEFAULT_PROMPT","IGNORE_MESSAGE_TYPES","GUIDE_AI_API_BASE","OPENAI_REALTIME_BASE","OPENAI_REALTIME_MODEL","GEMINI_API_KEY","GEMINI_API_ENDPOINT","createNewConversation","onError","fetch","method","headers","body","userId","date","toISOString","split","time","toTimeString","response","ok","text","catch","errorText","status","Error","json","conversationData","id","logMessage","statusText","sendUserMetadata","metadata","sendMetadataUpdates","updates","batchTimestamp","updateCount","updateUserMetadata","metadataUpdate","globalInitializationInProgress","props","position","metadataOptions","transcriptOptions","inputOptions","hooks","useMemo","window","React","useState","useEffect","useRef","useCallback","setStatus","isClient","setIsClient","componentPosition","isHighlighting","setIsHighlighting","hasInteracted","setHasInteracted","setPrompt","setIsSessionReady","isConnecting","setIsConnecting","showOnboarding","setShowOnboarding","popupPosition","setPopupPosition","conversationIdRef","componentRef","peerConnectionRef","dataChannelRef","hasCreatedConversationRef","mediaStreamRef","audioElementRef","ephemeralToken","setEphemeralToken","hasInitializedRef","initializationInProgressRef","isUnmountingRef","isConversationActive","setIsConversationActive","restoredMessages","setRestoredMessages","enabled","showTranscript","setShowTranscript","allMessages","setAllMessages","defaultMode","inputMode","setInputMode","textInput","setTextInput","setShowTextInput","hasAttemptedAutoStartRef","eventTracker","customerId","organizationId","customerType","raw","parsed","idVal","customer","String","orgVal","typeName","customerTypeName","_err","EventTracker","metadataTracker","UserMetadataTracker","config","geminiFlash","prompt","contents","parts","responseJson","candidates","handleCreateNewConversation","current","handleLogMessage","newMessage","prev","getOptimalPosition","elementHeight","spacing","rect","getBoundingClientRect","calculateOptimalPosition","sendMessage","readyState","send","cleanupWebRTC","getAudioTracks","forEach","track","stop","close","srcObject","initializeWebRTC","audioStream","RTCPeerConnection","addTrack","audioEl","document","createElement","autoplay","appendChild","ontrack","kind","stream","MediaStream","dc","createDataChannel","onopen","sessionConfig","tools","type","description","parameters","properties","selector","oneOf","items","required","tool_choice","turn_detection","create_response","interrupt_response","input_audio_transcription","model","language","session","onmessage","conversationContext","item","role","transcript","lastMessage","output","out","arguments","argsToUse","then","replace","parsedArgs","highlightElement","err","call_id","code","fragment","includes","createOffer","offer","setLocalDescription","localDescription","sdp","baseUrl","Authorization","sdpResponse","answerSdp","answer","setRemoteDescription","startConversationSession","enableTextInput","navigator","mediaDevices","getUserMedia","audio","echoCancellation","noiseSuppression","autoGainControl","channelCount","sampleRate","endConversationSession","handleTextSubmit","responseMessage","injectStyles","initialize","initialUserData","updateUserInfo","hasInitialized","initializationInProgress","hasInteractedBefore","isUnmounting","remove","stopTracking","destroy","syncInterval","syncTimer","setInterval","pendingUpdates","syncNow","onMetadataUpdate","getMetadata","clearInterval","success","GuideAI","trackLogin","additionalInfo","userInfo","trackCustomEvent","eventType","customData","syncMetadata","toggle","show","hide","isVisible","input","toggleMode","newMode","setMode","mode","getMode","sendText","shouldUseFixedPosition","Object","keys","baseStyles","zIndex","ref","style","className","onComplete","onClose","onClick","undefined","cursor","title","showToggleButton","onToggle","showTextInput","onTextInputChange","onTextSubmit","onTextKeyPress","event","key","shiftKey","preventDefault","textPlaceholder","placeholder","css","getElementById","styleElement","textContent","head","componentRect","viewportHeight","innerHeight","spaceAbove","top","spaceBelow","bottom","element","transcriptContainer","scrollTop","scrollHeight","shouldShowToggleButton","shouldShowTranscript","index","toLowerCase","toLocaleTimeString","hour","minute","value","onChange","target","onKeyPress","rows","disabled","step","setStep","options","isTracking","eventData","batchSize","batchTimeout","batchTimer","pendingEvents","currentUrl","customerMetadata","handleClick","baseEventData","tagName","getSafeValue","url","location","href","logEvent","handleFocus","isFocusable","handleChange","isFormElement","handleSubmit","formData","FormData","handlePopstate","previousUrl","getPreviousUrl","handleHashChange","oldURL","setCustomerMetadata","getCustomerMetadata","clearCustomerMetadata","addEventListener","startTracking","enrichEventData","customerSegment","sessionId","getSessionId","deviceType","getDeviceType","userAgent","screenResolution","screen","width","height","currentPage","pathname","userRole","timezone","Intl","DateTimeFormat","resolvedOptions","timeZone","locale","sessionStorage","random","toString","substr","test","trackClickEvents","trackFocusEvents","trackChangeEvents","trackSubmitEvents","trackRouteChanges","emitBatch","removeEventListener","interceptHistoryAPI","originalPushState","history","pushState","originalReplaceState","replaceState","result","apply","args","inputElement","selectElement","selectedIndex","inputType","matches","enrichedEventData","startBatchTimer","clearTimeout","setTimeout","batchPayload","events","dispatchEvent","CustomEvent","detail","getEventData","clearEventData","getEventDataByType","getEventDataByElement","toUpperCase","getEventDataByUrl","emitPendingEvents","setBatchConfig","getPendingEventsCount","getCustomerAnalytics","sessionDuration","getSessionStartTime","analytics","totalEvents","eventsByCustomer","eventsByType","eventsByPage","eventsByDevice","lastActivity","sessionStart","startTime","parseInt","identifyCustomerFromContext","userRoleMeta","querySelector","getAttribute","setCustomerFromAuth","authData","clickElement","Promise","resolve","clickEffectContainer","cssText","left","j","clickRipple","clickDot","clickEvent","MouseEvent","view","bubbles","cancelable","clickableElements","querySelectorAll","clickableElement","originalBoxShadow","boxShadow","originalTransition","transition","originalZIndex","selectors","cursorElement","i","currentSelector","startsWith","node","evaluate","XPathResult","FIRST_ORDERED_NODE_TYPE","singleNodeValue","Element","innerHTML","viewportWidth","innerWidth","offsetHeight","animation","METADATA_STORAGE_KEY","isInitialized","trackVisits","trackLogins","storage","customFields","collectBrowserInfo","collectUserAgent","visitCount","loginCount","init","loadMetadata","trackVisit","startSyncTimer","setupEventTrackerIntegration","lastVisit","saveMetadata","lastLogin","isFirstVisit","firstVisit","entries","getPendingUpdates","clearPendingUpdates","storageData","getFromStorage","clearStorage","lastUpdated","version","setToStorage","browserInfo","parseBrowserInfo","platform","match","emitPendingUpdates","handleEventBatch","batchData","evt","_eventTrackerListener","stopSyncTimer","currentMetadata","serialized","default","__webpack_module_cache__","__webpack_exports__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","call"],"sourceRoot":""}
1
+ {"version":3,"file":"GuideAI.js","mappings":"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","sources":["webpack://GuideAI/webpack/universalModuleDefinition","webpack://GuideAI/./src/styles/GuideAI.styles.ts","webpack://GuideAI/./src/utils/messageStorage.ts","webpack://GuideAI/./src/utils/constants.ts","webpack://GuideAI/external umd {\"commonjs\":\"react\",\"commonjs2\":\"react\",\"amd\":\"React\",\"root\":\"React\"}","webpack://GuideAI/./src/utils/api.ts","webpack://GuideAI/./src/GuideAI.tsx","webpack://GuideAI/./src/utils/ui.ts","webpack://GuideAI/./src/components/TranscriptBox.tsx","webpack://GuideAI/./src/components/Onboarding.tsx","webpack://GuideAI/./src/components/WelcomeBubble.tsx","webpack://GuideAI/./src/metric/event-listner.tsx","webpack://GuideAI/./src/utils/highlight.ts","webpack://GuideAI/./src/metric/metadata-tracker.tsx","webpack://GuideAI/./src/metric/index.tsx","webpack://GuideAI/webpack/bootstrap","webpack://GuideAI/webpack/startup"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"react\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"React\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"GuideAI\"] = factory(require(\"react\"));\n\telse\n\t\troot[\"GuideAI\"] = factory(root[\"React\"]);\n})(this, (__WEBPACK_EXTERNAL_MODULE__156__) => {\nreturn ","export const guideAIStyles = `\n.guideai-main-ui {\n position: relative;\n}\n\n.guideai-main-controls {\n display: flex;\n align-items: center;\n gap: 12px;\n position: relative;\n}\n\n.guideai-welcome-bubble {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n background: #0066ff;\n color: white;\n padding: 10px 16px;\n border-radius: 20px;\n font-size: 14px;\n white-space: normal;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n animation: bubble-pulse 2s infinite;\n max-width: 280px;\n min-width: 200px;\n text-align: center;\n line-height: 1.3;\n}\n\n.guideai-welcome-bubble.above {\n bottom: calc(100% + 10px);\n}\n\n.guideai-welcome-bubble.below {\n top: calc(100% + 10px);\n}\n\n.guideai-welcome-bubble.above::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-top: 8px solid #0066ff;\n}\n\n.guideai-welcome-bubble.below::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid #0066ff;\n}\n\n@keyframes bubble-pulse {\n 0% { transform: translateX(-50%) scale(1); }\n 50% { transform: translateX(-50%) scale(1.05); }\n 100% { transform: translateX(-50%) scale(1); }\n}\n\n.guideai-icon-wrapper {\n width: 50px;\n height: 50px;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255, 0.9);\n border: 2px solid transparent;\n border-radius: 50%;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.guideai-icon-wrapper:not(.initializing):hover {\n transform: scale(1.1);\n}\n\n.guideai-icon-wrapper.initializing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(128, 128, 128, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: guideai-spin 1.5s linear infinite;\n opacity: 0.7;\n cursor: default;\n}\n\n.guideai-icon-wrapper.recording {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: guideai-pulse 1s infinite alternate;\n}\n\n.guideai-icon-wrapper.processing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(255, 165, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n animation: guideai-spin 1s linear infinite;\n}\n\n.guideai-icon-wrapper.playing {\n background-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 2px rgba(0, 128, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);\n}\n\n@keyframes guideai-pulse {\n 0% { transform: scale(1); }\n 100% { transform: scale(1.05); }\n}\n\n@keyframes guideai-spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n@keyframes click-ripple-animation {\n 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }\n 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.6; }\n 100% { transform: translate(-50%, -50%) scale(2.5); opacity: 0; }\n}\n\n@keyframes click-dot-animation {\n 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }\n 60% { transform: translate(-50%, -50%) scale(1); opacity: 1; }\n 100% { transform: translate(-50%, -50%) scale(1); opacity: 0; }\n}\n\n@keyframes cursor-jiggle {\n 0% { transform: translate(-50%, 0) scale(1); }\n 25% { transform: translate(-50%, -5px) scale(1.1); }\n 50% { transform: translate(-50%, 0) scale(1); }\n 75% { transform: translate(-50%, 5px) scale(1.1); }\n 100% { transform: translate(-50%, 0) scale(1); filter: drop-shadow(0 0 8px #0066ff); }\n}\n\n.guideai-icon {\n width: 60%;\n height: 60%;\n min-width: 16px;\n min-height: 16px;\n max-width: 40px;\n max-height: 40px;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n}\n\n.guideai-icon.initializing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"%23808080\" d=\"M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z\"/></svg>');\n}\n\n.guideai-icon.microphone {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 352 512\"><path fill=\"%230000FF\" d=\"M176 352c53.02 0 96-42.98 96-96V96c0-53.02-42.98-96-96-96S80 42.98 80 96v160c0 53.02 42.98 96 96 96zm160-160h-16c-8.84 0-16 7.16-16 16v48c0 74.8-64.49 134.82-140.79 127.38C96.71 376.89 48 317.11 48 250.3V208c0-8.84-7.16-16-16-16H16c-8.84 0-16 7.16-16 16v40.16c0 89.64 63.97 169.55 152 181.69V464H96c-8.84 0-16 7.16-16 16v16c0 8.84 7.16 16 16 16h160c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16h-56v-33.77C285.71 418.47 352 344.9 352 256v-48c0-8.84-7.16-16-16-16z\"/></svg>');\n}\n\n.guideai-icon.recording {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><circle cx=\"256\" cy=\"256\" r=\"128\" fill=\"%23FF0000\"/><circle cx=\"256\" cy=\"256\" r=\"200\" stroke=\"%23FF0000\" stroke-width=\"20\" fill=\"none\"/></svg>');\n}\n\n.guideai-icon.processing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"%23FFA500\" d=\"M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z\"/></svg>');\n}\n\n.guideai-icon.playing {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"%23008000\" d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/></svg>');\n}\n\n.guideai-icon.text-mode {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"%230066ff\" d=\"M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4l4 4 4-4h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM7 10v2h2v-2H7zm6 2h-2v-2h2v2zm4 0h-2v-2h2v2z\"/></svg>');\n}\n\n.guideai-icon.voice-mode {\n background-image: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 352 512\"><path fill=\"%23008000\" d=\"M176 352c53.02 0 96-42.98 96-96V96c0-53.02-42.98-96-96-96S80 42.98 80 96v160c0 53.02 42.98 96 96 96zm160-160h-16c-8.84 0-16 7.16-16 16v48c0 74.8-64.49 134.82-140.79 127.38C96.71 376.89 48 317.11 48 250.3V208c0-8.84-7.16-16-16-16H16c-8.84 0-16 7.16-16 16v40.16c0 89.64 63.97 169.55 152 181.69V464H96c-8.84 0-16 7.16-16 16v16c0 8.84 7.16 16 16 16h160c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16h-56v-33.77C285.71 418.47 352 344.9 352 256v-48c0-8.84-7.16-16-16-16z\"/></svg>');\n}\n\n\n/* Onboarding styles */\n.guideai-onboarding {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n width: 300px;\n max-width: 90vw;\n z-index: 1002;\n animation: onboarding-fade-in 0.3s ease-out;\n}\n\n.guideai-onboarding.above {\n bottom: calc(100% + 15px);\n}\n\n.guideai-onboarding.below {\n top: calc(100% + 15px);\n}\n\n.guideai-onboarding.above::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-top: 8px solid white;\n filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));\n}\n\n.guideai-onboarding.below::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid white;\n filter: drop-shadow(0 -2px 4px rgba(0, 0, 0, 0.1));\n}\n\n@keyframes onboarding-fade-in {\n from { opacity: 0; transform: translateX(-50%) translateY(-10px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n}\n\n.guideai-onboarding-content {\n padding: 16px;\n position: relative;\n}\n\n.guideai-onboarding-close {\n position: absolute;\n top: 10px;\n right: 10px;\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #999;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n}\n\n.guideai-onboarding-close:hover {\n background: #f5f5f5;\n color: #333;\n}\n\n.guideai-onboarding-step {\n text-align: center;\n margin-bottom: 12px;\n}\n\n.guideai-onboarding-icon {\n font-size: 32px;\n margin-bottom: 8px;\n display: inline-block;\n}\n\n.guideai-onboarding-step h3 {\n margin: 0 0 8px;\n font-size: 16px;\n color: #333;\n font-weight: 600;\n}\n\n.guideai-onboarding-step p {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.4;\n}\n\n.guideai-onboarding-dots {\n display: flex;\n justify-content: center;\n margin: 12px 0;\n}\n\n.guideai-onboarding-dots .dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #ddd;\n margin: 0 4px;\n transition: all 0.3s ease;\n}\n\n.guideai-onboarding-dots .dot.active {\n background: #0066ff;\n transform: scale(1.2);\n}\n\n.guideai-onboarding-next {\n display: block;\n width: 100%;\n padding: 10px;\n background: #0066ff;\n color: white;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.guideai-onboarding-next:hover {\n background: #0055cc;\n}\n\n/* Transcript Box Styles */\n.guideai-transcript-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: transparent;\n display: flex;\n justify-content: flex-end;\n align-items: flex-end;\n padding-bottom: 40px;\n padding-right: 40px;\n z-index: 10000;\n animation: transcript-fade-in 0.3s ease-out;\n pointer-events: none;\n}\n\n.guideai-transcript-box {\n background: rgba(40, 44, 52, 0.85);\n backdrop-filter: blur(20px);\n -webkit-backdrop-filter: blur(20px);\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-radius: 16px;\n box-shadow: \n 0 8px 32px rgba(0, 0, 0, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n inset 0 -1px 0 rgba(0, 0, 0, 0.1);\n width: 280px;\n max-height: 280px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: transcript-slide-up 0.4s ease-out;\n pointer-events: auto;\n margin-right: 60px;\n position: relative;\n}\n\n.guideai-transcript-box::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 1px;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);\n border-radius: 16px 16px 0 0;\n}\n\n\n\n.guideai-transcript-messages {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n max-height: 200px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar {\n width: 6px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar-track {\n background: rgba(0, 0, 0, 0.05);\n border-radius: 3px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n}\n\n.guideai-transcript-messages::-webkit-scrollbar-thumb:hover {\n background: rgba(0, 0, 0, 0.3);\n}\n\n.guideai-transcript-empty {\n text-align: center;\n padding: 20px 12px;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.guideai-transcript-empty-icon {\n font-size: 24px;\n margin-bottom: 8px;\n opacity: 0.5;\n}\n\n.guideai-transcript-empty p {\n margin: 0;\n font-size: 11px;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.guideai-transcript-message {\n margin-bottom: 8px;\n animation: message-fade-in 0.3s ease-out;\n}\n\n.guideai-transcript-message.human {\n text-align: right;\n}\n\n.guideai-transcript-message.guideai {\n text-align: left;\n}\n\n.guideai-transcript-message-content {\n display: inline-block;\n max-width: 85%;\n padding: 6px 10px;\n border-radius: 12px;\n position: relative;\n}\n\n.guideai-transcript-message.human .guideai-transcript-message-content {\n background: rgba(255, 255, 255, 0.15);\n color: rgba(255, 255, 255, 0.95);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-bottom-right-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.guideai-transcript-message.guideai .guideai-transcript-message-content {\n background: rgba(0, 0, 0, 0.1);\n color: rgba(255, 255, 255, 0.9);\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-bottom-left-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.guideai-transcript-message-sender {\n font-size: 9px;\n font-weight: 600;\n margin-bottom: 2px;\n opacity: 0.8;\n}\n\n.guideai-transcript-message-text {\n font-size: 11px;\n line-height: 1.3;\n word-wrap: break-word;\n}\n\n.guideai-transcript-message-time {\n font-size: 8px;\n opacity: 0.6;\n margin-top: 2px;\n}\n\n\n\n@keyframes transcript-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes transcript-slide-up {\n from { \n opacity: 0; \n transform: translateX(40px) scale(0.95); \n }\n to { \n opacity: 1; \n transform: translateX(0) scale(1); \n }\n}\n\n@keyframes message-fade-in {\n from { \n opacity: 0; \n transform: translateY(10px); \n }\n to { \n opacity: 1; \n transform: translateY(0); \n }\n}\n\n/* Transcript Toggle Button Styles - positioned at top of transcript area */\n.guideai-transcript-toggle-button {\n position: fixed;\n bottom: 60px;\n right: 40px;\n width: 36px;\n height: 36px;\n background: rgba(40, 44, 52, 0.9);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border: 1px solid rgba(255, 255, 255, 0.15);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);\n transition: all 0.2s ease;\n z-index: 10001;\n font-size: 14px;\n padding: 0;\n color: rgba(255, 255, 255, 0.9);\n animation: toggle-fade-in 0.3s ease-out;\n}\n\n.guideai-transcript-toggle-button:hover {\n background: rgba(40, 44, 52, 1);\n transform: scale(1.1);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);\n}\n\n.guideai-transcript-toggle-button:active {\n transform: scale(0.95);\n}\n\n.guideai-transcript-toggle-icon {\n display: inline-block;\n transition: all 0.2s ease;\n filter: none;\n}\n\n/* Position transcript toggle button based on transcript position */\n.guideai-transcript-overlay {\n pointer-events: none;\n}\n\n.guideai-transcript-toggle-button {\n pointer-events: auto;\n}\n\n/* Input Options Container - Two Stage Layout */\n.guideai-input-options {\n display: flex;\n align-items: center;\n gap: 12px;\n position: relative;\n animation: options-slide-in 0.4s ease-out;\n}\n\n@keyframes options-slide-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n/* Individual Input Option Button */\n.guideai-input-option {\n width: 50px;\n height: 50px;\n background: rgba(255, 255, 255, 0.9);\n border: 2px solid rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n transition: all 0.3s ease;\n font-size: 18px;\n padding: 0;\n position: relative;\n}\n\n.guideai-input-option:hover:not(:disabled) {\n background: rgba(255, 255, 255, 1);\n transform: scale(1.1);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n}\n\n.guideai-input-option:active:not(:disabled) {\n transform: scale(0.95);\n}\n\n.guideai-input-option:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n}\n\n/* Voice Option Specific Styling */\n.guideai-input-option.voice-option {\n background: linear-gradient(135deg, rgba(76, 175, 80, 0.1), rgba(139, 195, 74, 0.1));\n border-color: rgba(76, 175, 80, 0.3);\n}\n\n.guideai-input-option.voice-option:hover:not(:disabled) {\n background: linear-gradient(135deg, rgba(76, 175, 80, 0.2), rgba(139, 195, 74, 0.2));\n border-color: rgba(76, 175, 80, 0.5);\n}\n\n/* Text Option Specific Styling */\n.guideai-input-option.text-option {\n background: linear-gradient(135deg, rgba(33, 150, 243, 0.1), rgba(63, 81, 181, 0.1));\n border-color: rgba(33, 150, 243, 0.3);\n}\n\n.guideai-input-option.text-option:hover:not(:disabled) {\n background: linear-gradient(135deg, rgba(33, 150, 243, 0.2), rgba(63, 81, 181, 0.2));\n border-color: rgba(33, 150, 243, 0.5);\n}\n\n.guideai-input-option-icon {\n display: inline-block;\n transition: all 0.2s ease;\n filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));\n}\n\n/* Text Input integrated into Transcript Box */\n.guideai-transcript-text-input {\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n padding: 12px;\n display: flex;\n gap: 8px;\n align-items: flex-end;\n background: rgba(0, 0, 0, 0.02);\n border-radius: 0 0 16px 16px;\n animation: text-input-fade-in 0.3s ease-out;\n}\n\n.guideai-transcript-input-field {\n flex: 1;\n background: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 8px;\n padding: 8px 12px;\n color: rgba(255, 255, 255, 0.95);\n font-size: 12px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n resize: none;\n outline: none;\n transition: all 0.2s ease;\n min-height: 32px;\n}\n\n.guideai-transcript-input-field::placeholder {\n color: rgba(255, 255, 255, 0.6);\n}\n\n.guideai-transcript-input-field:focus {\n border-color: rgba(255, 255, 255, 0.4);\n background: rgba(255, 255, 255, 0.2);\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.2);\n}\n\n.guideai-transcript-send-button {\n background: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 6px;\n padding: 6px 10px;\n color: rgba(255, 255, 255, 0.9);\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 36px;\n height: 32px;\n}\n\n.guideai-transcript-send-button:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.25);\n border-color: rgba(255, 255, 255, 0.3);\n transform: translateY(-1px);\n}\n\n.guideai-transcript-send-button:active:not(:disabled) {\n transform: translateY(0);\n}\n\n.guideai-transcript-send-button:disabled {\n background: rgba(255, 255, 255, 0.05);\n border-color: rgba(255, 255, 255, 0.1);\n color: rgba(255, 255, 255, 0.4);\n cursor: not-allowed;\n transform: none;\n}\n\n.guideai-transcript-send-icon {\n font-size: 11px;\n}\n\n/* Animation for text input appearance */\n@keyframes text-input-fade-in {\n from { \n opacity: 0; \n transform: translateY(10px); \n }\n to { \n opacity: 1; \n transform: translateY(0); \n }\n}\n\n@keyframes toggle-fade-in {\n from { \n opacity: 0; \n transform: scale(0.8); \n }\n to { \n opacity: 1; \n transform: scale(1); \n }\n}\n\n\n`; ","// Storage data structures for conversation persistence\nexport interface StoredMessage {\n content: string;\n sender: 'GUIDEAI' | 'HUMAN';\n timestamp: number;\n}\n\nexport interface StoredConversation {\n conversationId: string;\n messages: StoredMessage[];\n timestamp: number;\n organizationKey: string;\n}\n\nexport const CONVERSATION_STORAGE_KEY = 'guideai_conversation';\nexport const CONVERSATION_EXPIRY_MINUTES = 30;\nexport const MAX_STORED_MESSAGES = 100; // Increased to keep more conversation history\n\nexport const isLocalStorageAvailable = (): boolean => {\n try {\n const testKey = '__storage_test__';\n localStorage.setItem(testKey, testKey);\n localStorage.removeItem(testKey);\n return true;\n } catch (e) {\n return false;\n }\n};\n\nconst isValidConversation = (data: any): data is StoredConversation => {\n return (\n data &&\n typeof data === 'object' &&\n typeof data.conversationId === 'string' &&\n Array.isArray(data.messages) &&\n typeof data.timestamp === 'number' &&\n typeof data.organizationKey === 'string' &&\n data.messages.every((msg: any) => (\n typeof msg === 'object' &&\n typeof msg.content === 'string' &&\n (msg.sender === 'HUMAN' || msg.sender === 'GUIDEAI') &&\n typeof msg.timestamp === 'number'\n ))\n );\n};\n\nexport const isConversationExpired = (conversation: StoredConversation): boolean => {\n const expiryTime = CONVERSATION_EXPIRY_MINUTES * 60 * 1000; // convert to milliseconds\n const now = Date.now();\n return (now - conversation.timestamp) > expiryTime;\n};\n\nconst handleStorageError = (error: unknown, operation: string): void => {\n console.error(`Storage error during ${operation}:`, error);\n \n // Check if it's a quota exceeded error\n if (error instanceof DOMException && \n (error.name === 'QuotaExceededError' || \n error.name === 'NS_ERROR_DOM_QUOTA_REACHED')) {\n \n // Try to free up space by removing oldest messages instead of clearing everything\n try {\n const conversation = loadConversationFromStorage();\n if (conversation && conversation.messages.length > 5) {\n // Remove oldest 5 messages\n conversation.messages = conversation.messages.slice(5);\n saveConversationToStorage(conversation);\n console.warn('Storage quota exceeded. Removed oldest 5 messages to free space.');\n } else if (conversation) {\n // If less than 5 messages, clear everything\n clearConversationStorage();\n console.warn('Storage quota exceeded. Cleared conversation data.');\n }\n } catch (cleanupError) {\n console.error('Failed to clean up storage:', cleanupError);\n }\n }\n};\n\nexport const saveConversationToStorage = (conversation: StoredConversation): void => {\n if (!isLocalStorageAvailable()) {\n console.warn('localStorage is not available. Conversation persistence disabled.');\n return;\n }\n \n try {\n // Limit to last MAX_STORED_MESSAGES\n if (conversation.messages.length > MAX_STORED_MESSAGES) {\n conversation.messages = conversation.messages.slice(-MAX_STORED_MESSAGES);\n }\n \n // Update timestamp\n conversation.timestamp = Date.now();\n \n localStorage.setItem(CONVERSATION_STORAGE_KEY, JSON.stringify(conversation));\n } catch (error) {\n handleStorageError(error, 'save');\n }\n};\n\nexport const loadConversationFromStorage = (): StoredConversation | null => {\n if (!isLocalStorageAvailable()) {\n console.warn('localStorage is not available. Conversation persistence disabled.');\n return null;\n }\n \n try {\n const storedData = localStorage.getItem(CONVERSATION_STORAGE_KEY);\n if (!storedData) return null;\n \n const parsedData = JSON.parse(storedData);\n \n // Validate the data structure\n if (!isValidConversation(parsedData)) {\n console.warn('Corrupted conversation data found. Clearing storage.');\n clearConversationStorage();\n return null;\n }\n \n return parsedData;\n } catch (error) {\n handleStorageError(error, 'load');\n // Clear corrupted data on any parsing errors\n clearConversationStorage();\n return null;\n }\n};\n\nexport const clearConversationStorage = (): void => {\n if (!isLocalStorageAvailable()) {\n return;\n }\n \n try {\n localStorage.removeItem(CONVERSATION_STORAGE_KEY);\n } catch (error) {\n handleStorageError(error, 'clear');\n }\n};\n\nexport const addMessageToStorage = (message: StoredMessage, conversationId: string, organizationKey: string): void => {\n if (!isLocalStorageAvailable()) {\n console.warn('localStorage is not available. Message persistence disabled.');\n return;\n }\n \n try {\n let conversation = loadConversationFromStorage();\n \n if (!conversation) {\n conversation = {\n conversationId,\n messages: [],\n timestamp: Date.now(),\n organizationKey\n };\n }\n \n // Check for duplicate messages to prevent adding the same message twice\n const isDuplicate = conversation.messages.some(existingMsg => \n existingMsg.content === message.content && \n existingMsg.sender === message.sender &&\n Math.abs(existingMsg.timestamp - message.timestamp) < 5000 // Within 5 seconds\n );\n \n if (!isDuplicate) {\n conversation.messages.push(message);\n conversation.conversationId = conversationId;\n conversation.organizationKey = organizationKey;\n \n saveConversationToStorage(conversation);\n } else {\n console.log('Duplicate message detected, skipping:', message.content.substring(0, 50));\n }\n } catch (error) {\n console.error('Error adding message to storage:', error);\n }\n};\n\nexport const checkForStoredConversation = (currentOrganizationKey: string): {\n shouldRestore: boolean;\n conversationId: string | null;\n messages: StoredMessage[] | null;\n} => {\n const storedConversation = loadConversationFromStorage();\n \n if (!storedConversation) {\n return { shouldRestore: false, conversationId: null, messages: null };\n }\n \n // Check if conversation is expired - if so, clear it automatically\n if (isConversationExpired(storedConversation)) {\n clearConversationStorage();\n return { shouldRestore: false, conversationId: null, messages: null };\n }\n \n // Check if organization key matches\n if (storedConversation.organizationKey !== currentOrganizationKey) {\n return { shouldRestore: false, conversationId: null, messages: null };\n }\n \n return {\n shouldRestore: true,\n conversationId: storedConversation.conversationId,\n messages: storedConversation.messages\n };\n};\n\nexport const formatConversationContext = (messages: StoredMessage[], maxMessages: number = 10): string => {\n // Take only the last N messages to avoid context length issues\n const recentMessages = messages.slice(-maxMessages);\n \n if (recentMessages.length === 0) {\n return '';\n }\n \n // Filter out very short or empty messages\n const meaningfulMessages = recentMessages.filter(msg => \n msg.content && msg.content.trim().length > 3\n );\n \n if (meaningfulMessages.length === 0) {\n return '';\n }\n \n // Format messages into a readable context string\n const formattedMessages = meaningfulMessages.map(msg => {\n const sender = msg.sender === 'HUMAN' ? 'User' : 'Assistant';\n return `${sender}: ${msg.content.trim()}`;\n }).join('\\n');\n \n return formattedMessages;\n}; ","// Default prompt for Guide AI\nexport const DEFAULT_PROMPT = `you are Guide AI.\n Your role is to answer any question directly and succinctly that a user has. NEVER DIRECTLY MENTION THE SCREENSHOT, but use its information as much as possible to target your responses.\n If nothing is asked, then your goal is to generally assist them.\n IMPORTANT: NEVER answer in more than 10 words. Always be concise and limit answers to 1 sentence maximum. Be simple and as short as possible.\n Your job is to help them get it done through asking more and more targeted specific questions.`;\n\n// WebRTC message types to ignore in logging\nexport const IGNORE_MESSAGE_TYPES = [\n \"delta\", \n \"rate_limits\", \n \"input_audio_buffer\",\n \"response.audio.done\", \n \"response.output_item\", \n \"response.content_part\", \n \"output_audio_buffer\",\n \"response.created\", \n \"session.created\",\n \"conversation.item.truncated\"\n];\n\n// API endpoints\nexport const GUIDE_AI_API_BASE = 'https://www.getguide.ai/api';\n// export const GUIDE_AI_API_BASE = 'http://localhost:3001/api';\nexport const OPENAI_REALTIME_BASE = 'https://api.openai.com/v1/realtime';\nexport const OPENAI_REALTIME_MODEL = \"gpt-4o-realtime-preview-2024-12-17\";\n\n// Gemini API - Note: This should be moved to environment variables in production\nexport const GEMINI_API_KEY = 'AIzaSyBiFyzjYVupLyk8BdmfWzBL1GbzX8OUdPc';\nexport const GEMINI_API_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent'; ","module.exports = __WEBPACK_EXTERNAL_MODULE__156__;","import { StoredMessage, addMessageToStorage } from './messageStorage';\nimport { GUIDE_AI_API_BASE } from './constants';\nimport { UserMetadata, MetadataUpdate } from '../types/metadata.types';\n\n// Type for the conversation creation response (now includes token and prompt)\ninterface ConversationData {\n id: string;\n ephemeralToken: string;\n prompt: string;\n}\n\n// Create a new conversation (now also returns ephemeral token + prompt)\nexport const createNewConversation = async (\n organizationKey: string,\n onError: (error: Error, context: string) => void\n): Promise<ConversationData | null> => {\n try {\n const now = new Date();\n const response = await fetch(`${GUIDE_AI_API_BASE}/initialize-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n organizationKey,\n userId: 'anonymous',\n date: now.toISOString().split('T')[0],\n time: now.toTimeString().split(' ')[0],\n messages: []\n })\n });\n \n if (!response.ok) {\n const errorText = await response.text().catch(() => 'No error details available');\n console.error(`Conversation creation failed with status ${response.status}:`, errorText);\n throw new Error(`Failed to create conversation: ${response.status} - ${errorText}`);\n }\n \n const conversationData = await response.json();\n console.log('Conversation created:', conversationData.id);\n return conversationData;\n } catch (error) {\n console.error('Error creating conversation:', error);\n onError(error as Error, 'Creating conversation');\n return null;\n }\n};\n\n// Log a message to the conversation via API and local storage\nexport const logMessage = async (\n content: string, \n sender: 'GUIDEAI' | 'HUMAN',\n conversationId: string | null,\n organizationKey: string,\n onError: (error: Error, context: string) => void\n): Promise<void> => {\n if (!conversationId) return;\n \n try {\n const response = await fetch(`${GUIDE_AI_API_BASE}/conversations/${conversationId}/messages`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({ content, sender })\n });\n \n if (!response.ok) {\n throw new Error(`Failed to log message: ${response.status} ${response.statusText}`);\n }\n \n const message: StoredMessage = {\n content,\n sender,\n timestamp: Date.now()\n };\n \n addMessageToStorage(message, conversationId, organizationKey);\n } catch (error) {\n console.error('Error logging message:', error);\n onError(error as Error, 'Logging message');\n }\n};\n\n// Send metadata updates in batch\nexport const sendMetadataUpdates = async (\n updates: MetadataUpdate[],\n organizationKey: string,\n onError: (error: Error, context: string) => void\n): Promise<boolean> => {\n if (updates.length === 0) return true;\n\n try {\n const response = await fetch(`${GUIDE_AI_API_BASE}/metadata-updates`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n organizationKey,\n updates,\n batchTimestamp: Date.now(),\n updateCount: updates.length\n })\n });\n\n if (!response.ok) {\n throw new Error(`Failed to send metadata updates: ${response.status} ${response.statusText}`);\n }\n\n console.log(`Sent ${updates.length} metadata updates successfully`);\n return true;\n } catch (error) {\n console.error('Error sending metadata updates:', error);\n onError(error as Error, 'Sending metadata updates');\n return false;\n }\n}; ","// Import React normally, but use a helper function to handle possible duplicates\nimport React from 'react';\nimport { \n StoredMessage, \n addMessageToStorage,\n clearConversationStorage,\n checkForStoredConversation, \n formatConversationContext \n} from './utils/messageStorage';\n\n// Import our refactored modules\nimport { GuideAIProps, RecordingStatus, UseStateHook, UseEffectHook, UseRefHook, UseCallbackHook, PopupPosition } from './types/GuideAI.types';\nimport { DEFAULT_PROMPT, IGNORE_MESSAGE_TYPES, GUIDE_AI_API_BASE, OPENAI_REALTIME_BASE, OPENAI_REALTIME_MODEL, GEMINI_API_KEY, GEMINI_API_ENDPOINT } from './utils/constants';\nimport { injectStyles, calculateOptimalPosition } from './utils/ui';\nimport { highlightElement } from './utils/highlight';\nimport { createNewConversation, logMessage } from './utils/api';\nimport WelcomeBubble from './components/WelcomeBubble';\nimport Onboarding from './components/Onboarding';\nimport TranscriptBox from './components/TranscriptBox';\nimport { guideAIStyles } from './styles/GuideAI.styles';\nimport { EventTracker, UserMetadataTracker, UserMetadata } from './metric';\nimport { sendMetadataUpdates } from './utils/api';\n\n// Global flag to prevent multiple GuideAI instances from initializing simultaneously\nlet globalInitializationInProgress = false;\n\n// Get React hooks safely, avoiding duplicate React issues\nconst getReactHooks = () => {\n // Try to use the React instance from window if available (for react-scripts)\n if (typeof window !== 'undefined' && (window as any).React) {\n return {\n useState: (window as any).React.useState as UseStateHook,\n useEffect: (window as any).React.useEffect as UseEffectHook,\n useRef: (window as any).React.useRef as UseRefHook,\n useMemo: (window as any).React.useMemo,\n useCallback: (window as any).React.useCallback as UseCallbackHook\n };\n }\n // Otherwise use the imported React\n return {\n useState: React.useState,\n useEffect: React.useEffect,\n useRef: React.useRef,\n useMemo: React.useMemo,\n useCallback: React.useCallback as UseCallbackHook\n };\n};\n\nconst GuideAI = (props: GuideAIProps) => {\n const {\n organizationKey,\n position,\n onError = console.error,\n metadata: metadataOptions,\n transcript: transcriptOptions,\n input: inputOptions\n } = props;\n\n // Memoize the React hooks to ensure consistent instances\n const hooks = React.useMemo(() => getReactHooks(), []);\n\n const [status, setStatus] = hooks.useState<RecordingStatus>('idle');\n const [isClient, setIsClient] = hooks.useState(false);\n const [componentPosition] = hooks.useState(position);\n const [isHighlighting, setIsHighlighting] = hooks.useState(false);\n const [hasInteracted, setHasInteracted] = hooks.useState(false);\n const [prompt, setPrompt] = hooks.useState<string | null>(null);\n const [isSessionReady, setIsSessionReady] = hooks.useState(false);\n const [isConnecting, setIsConnecting] = hooks.useState(false);\n const [showOnboarding, setShowOnboarding] = hooks.useState(false);\n const [popupPosition, setPopupPosition] = hooks.useState<PopupPosition>('above');\n const conversationIdRef = hooks.useRef<string | null>(null);\n\n const componentRef = hooks.useRef<HTMLDivElement>(null);\n const peerConnectionRef = hooks.useRef<RTCPeerConnection | null>(null);\n const dataChannelRef = hooks.useRef<RTCDataChannel | null>(null);\n const hasCreatedConversationRef = hooks.useRef(false);\n const mediaStreamRef = hooks.useRef<MediaStream | null>(null);\n const audioElementRef = hooks.useRef<HTMLAudioElement | null>(null);\n const [ephemeralToken, setEphemeralToken] = hooks.useState<string | null>(null);\n const hasInitializedRef = hooks.useRef(false);\n const initializationInProgressRef = hooks.useRef(false);\n const isUnmountingRef = hooks.useRef(false);\n const [isConversationActive, setIsConversationActive] = hooks.useState(false);\n const [restoredMessages, setRestoredMessages] = hooks.useState<StoredMessage[]>([]);\n const [showTranscript, setShowTranscript] = hooks.useState(\n transcriptOptions?.enabled !== false // Default to true unless explicitly disabled\n );\n const [allMessages, setAllMessages] = hooks.useState<StoredMessage[]>([]);\n const [inputMode, setInputMode] = hooks.useState<'voice' | 'text'>(\n inputOptions?.defaultMode || 'voice'\n );\n const [textInput, setTextInput] = hooks.useState('');\n const [showTextInput, setShowTextInput] = hooks.useState(false);\n\n const hasAttemptedAutoStartRef = hooks.useRef(false);\n const eventTracker = hooks.useMemo(() => {\n let customerId: string | undefined;\n let organizationId: string | undefined;\n let customerType: string | undefined;\n try {\n const raw = typeof window !== 'undefined' ? localStorage.getItem('user') : null;\n if (raw) {\n const parsed = JSON.parse(raw);\n const idVal = parsed?.customer?.id;\n if (idVal != null) customerId = String(idVal);\n const orgVal = parsed?.customer.organizationId;\n if (orgVal != null) organizationId = String(orgVal);\n const typeName = parsed?.customer?.customerTypeName;\n if (typeof typeName === 'string') customerType = typeName;\n console.log(\"raw\", customerId,organizationId,customerType);\n }\n } catch (_err) {\n // ignore\n }\n return new EventTracker({ customerId, organizationId, customerType, organizationKey });\n }, [organizationKey]);\n\n const metadataTracker = hooks.useMemo(() => \n new UserMetadataTracker(organizationKey, metadataOptions?.config || {}, onError), \n [organizationKey, metadataOptions?.config, onError]\n );\n \n // ===== API & EXTERNAL CALLS =====\n \n // Call Gemini Flash API to validate and fix JSON\n const geminiFlash = async (prompt: string): Promise<string> => {\n const response = await fetch(`${GEMINI_API_ENDPOINT}?key=${GEMINI_API_KEY}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n contents: [\n {\n parts: [\n {\n text: prompt\n }\n ]\n }\n ]\n })\n });\n \n const responseJson = await response.json();\n const content = responseJson.candidates[0].content;\n const responseText = content.parts[0].text;\n return responseText;\n };\n\n // ===== COMPONENT WRAPPER FUNCTIONS =====\n \n // Wrapper functions to maintain original signatures\n const handleCreateNewConversation = async () => {\n if (hasCreatedConversationRef.current) return null;\n hasCreatedConversationRef.current = true;\n \n const conversationData = await createNewConversation(organizationKey, onError);\n if (conversationData) {\n conversationIdRef.current = conversationData.id;\n setEphemeralToken(conversationData.ephemeralToken);\n setPrompt(conversationData.prompt);\n return conversationData;\n }\n return null;\n };\n\n const handleLogMessage = async (content: string, sender: 'GUIDEAI' | 'HUMAN') => {\n await logMessage(content, sender, conversationIdRef.current, organizationKey, onError);\n \n // Add message to local state for transcript\n const newMessage: StoredMessage = {\n content,\n sender,\n timestamp: Date.now()\n };\n setAllMessages(prev => [...prev, newMessage]);\n };\n\n const handleHighlightElement = async (selector: string | string[]) => {\n return highlightElement(selector, isHighlighting, setIsHighlighting, handleLogMessage);\n };\n\n // ===== UI UTILITIES & POSITION =====\n \n // Calculate optimal position for popups based on component location\n const getOptimalPosition = hooks.useCallback((elementHeight: number = 240, spacing: number = 15): PopupPosition => {\n if (!componentRef.current) return 'above';\n \n const rect = componentRef.current.getBoundingClientRect();\n return calculateOptimalPosition(rect, elementHeight, spacing);\n }, []);\n\n // ===== WEBRTC MANAGEMENT =====\n \n const sendMessage = (message: any) => {\n if (dataChannelRef.current?.readyState === 'open') {\n // console.log('sending message', message);\n dataChannelRef.current.send(JSON.stringify(message));\n } else {\n console.error('Data channel not open, cannot send message');\n setStatus('idle');\n }\n };\n \n const cleanupWebRTC = hooks.useCallback(() => {\n if (mediaStreamRef.current) {\n // Stop tracks completely instead of just disabling them\n mediaStreamRef.current.getAudioTracks().forEach(track => {\n track.stop();\n });\n mediaStreamRef.current = null;\n }\n \n if (dataChannelRef.current) {\n dataChannelRef.current.close();\n dataChannelRef.current = null;\n }\n \n if (peerConnectionRef.current) {\n peerConnectionRef.current.close();\n peerConnectionRef.current = null;\n }\n \n if (audioElementRef.current) {\n audioElementRef.current.srcObject = null;\n }\n \n // Reset session ready state\n setIsSessionReady(false);\n }, []);\n\n const initializeWebRTC = async (audioStream: MediaStream | null): Promise<boolean> => {\n try {\n const pc = new RTCPeerConnection();\n peerConnectionRef.current = pc;\n \n // Only add audio tracks if audioStream is provided (for voice mode)\n if (audioStream) {\n audioStream.getAudioTracks().forEach(track => {\n pc.addTrack(track, audioStream);\n });\n }\n \n // Only create audio element if we have an audio stream (voice mode)\n if (audioStream && !audioElementRef.current) {\n const audioEl = document.createElement('audio');\n audioEl.autoplay = true;\n document.body.appendChild(audioEl);\n audioElementRef.current = audioEl;\n }\n \n pc.ontrack = (e) => {\n if (audioElementRef.current && e.track.kind === 'audio') {\n const stream = new MediaStream([e.track]);\n audioElementRef.current.srcObject = stream;\n }\n };\n \n const dc = pc.createDataChannel('oai-events');\n dataChannelRef.current = dc;\n \n dc.onopen = () => { \n // Configure session based on whether we have audio stream (voice vs text mode)\n const sessionConfig: any = {\n tools: [{\n type: \"function\",\n name: \"highlight\",\n description: \"Highlight specific elements on the page to guide the user's attention\",\n parameters: {\n type: \"object\",\n properties: {\n selector: {\n oneOf: [\n {\n type: \"string\",\n description: \"CSS selector or XPath for the element to highlight (e.g., '#search-bar')\"\n },\n {\n type: \"array\",\n items: {\n type: \"string\"\n },\n description: \"List of CSS selectors or XPaths to highlight in sequence (e.g., ['#first-button', '#second-button'])\"\n }\n ],\n description: \"CSS selector(s) or XPath(s) for the element(s) to highlight. Can be a single selector string or an array of selectors to process sequentially.\"\n }\n },\n required: [\"selector\"]\n }\n }],\n tool_choice: \"auto\"\n };\n\n // Only add audio-specific config if we have an audio stream\n if (audioStream) {\n sessionConfig.turn_detection = {\n type: \"semantic_vad\",\n create_response: true,\n interrupt_response: false\n };\n sessionConfig.input_audio_transcription = {\n model: \"gpt-4o-mini-transcribe\",\n language: \"en\",\n };\n }\n\n sendMessage({\n type: \"session.update\",\n session: sessionConfig\n });\n };\n \n dc.onmessage = (e) => {\n try {\n const message = JSON.parse(e.data);\n\n switch (message.type) { \n case 'session.updated':\n // console.log('session.updated', message);\n setIsSessionReady(true);\n setIsConnecting(false);\n \n // If we have restored messages, send conversation context to AI now that session is ready\n if (restoredMessages.length > 0) {\n const conversationContext = formatConversationContext(restoredMessages, 5); // Reduce to 5 messages\n \n // Send as system context instead of user input to avoid confusion\n sendMessage({\n type: \"conversation.item.create\",\n item: {\n type: \"message\",\n role: \"system\",\n content: [{\n type: \"input_text\",\n text: `This is context from a previous conversation session. The user is continuing an existing conversation. Previous context: ${conversationContext}`\n }]\n }\n });\n \n console.log('Sent conversation context with', restoredMessages.length, 'restored messages');\n }\n break;\n\n case 'session.transcript_disabled':\n if (message.text && message.text.trim()) {\n console.log('Session transcript:', message.text);\n handleLogMessage(message.text, 'HUMAN');\n }\n break;\n \n case 'conversation.item.input_audio_transcription.completed':\n if (message.transcript && message.transcript.trim()) {\n console.log('User transcript:', message.transcript);\n // Only log if it's different from the last message to avoid duplicates\n if (allMessages.length === 0 || \n allMessages[allMessages.length - 1].content !== message.transcript) {\n handleLogMessage(message.transcript, 'HUMAN');\n }\n }\n break;\n\n case 'response.audio_transcript.done':\n if (message.transcript && message.transcript.trim()) {\n console.log('Assistant message:', message.transcript);\n // Only log if it's different from the last assistant message to avoid duplicates\n const lastMessage = allMessages[allMessages.length - 1];\n if (!lastMessage || \n lastMessage.sender !== 'GUIDEAI' ||\n lastMessage.content !== message.transcript) {\n handleLogMessage(message.transcript, 'GUIDEAI');\n }\n }\n break;\n \n case \"conversation.item.created\":\n // console.log('conversation.item.created', message);\n break;\n\n case \"input_audio_buffer.speech_started\":\n // console.log('User speaking started');\n setStatus('recording');\n break;\n\n case \"input_audio_buffer.speech_stopped\":\n // console.log('User speaking stopped');\n setStatus('processing');\n break;\n\n case 'response.done':\n // console.log('response.done', message);\n for (const out of message.response.output) {\n switch (out.type) {\n case \"message\":\n // console.log('Assistant message:', out.text);\n break;\n \n case \"function_call\":\n // console.log('function_call', out);\n if (out.name === 'highlight' && out.arguments) {\n // console.log('Tool call:', out.arguments);\n try {\n let argsToUse = out.arguments;\n // Check if the JSON string is missing a closing quote\n // try {\n // console.log(\"argsToUse\", argsToUse);\n // const parsedArgs = JSON.parse(argsToUse);\n // console.log(\"parsedArgs\", parsedArgs);\n // highlightElement(parsedArgs.selector);\n // } catch (error) {\n // console.log(\"errored, argsToUse\", argsToUse);\n const prompt = `\n Validate the following JSON string and return ONLY a correct JSON object:\n Note: The selector(s) should be either a css selector or an xpath, so modify those if invalid.\n Also, [url=''] is a valid css selector, so do not modify it if it's present.\n Do not add any other text or newlines to the response.\n It should be of the following format:\n { \"selector\": \"string\" }\n or\n { \"selector\": [\"string\", ...] }\n DO NOT add any other text or newlines to the response, it should begin and end with curly braces.\n DO NOT add '''json to the response.\n The JSON string is:\n ${argsToUse}\n `\n geminiFlash(prompt).then(response => {\n response = response.replace(\"```json\", \"\").replace(\"```\", \"\").trim();\n // console.log(\"response\", response);\n const parsedArgs = JSON.parse(response);\n handleHighlightElement(parsedArgs.selector);\n }).catch(err => {\n console.error(\"Error calling Gemini:\", err);\n });\n // }\n\n\n } catch (error) {\n console.error('Error parsing function arguments:', error);\n console.log(out.arguments);\n handleLogMessage('Error parsing function arguments: ' + out.arguments, 'GUIDEAI');\n }\n }\n \n sendMessage({\n type: \"conversation.item.create\",\n item: {\n type: \"function_call_output\",\n call_id: out.call_id,\n output: JSON.stringify(true)\n }\n });\n\n sendMessage({\n type: 'response.create',\n });\n break;\n }\n }\n \n break;\n\n case \"response.function_call_arguments.delta\":\n // console.log('response.function_call_arguments.delta', message);\n break;\n\n case \"response.function_call_arguments.done\":\n // console.log('response.function_call_arguments.done', message);\n break;\n\n case \"output_audio_buffer.started\":\n setStatus('playing');\n break;\n\n case \"output_audio_buffer.stopped\":\n // console.log('output_audio_buffer.stopped');\n setStatus('recording');\n \n break;\n\n case 'error':\n if (message.error.code === 'session_expired') {\n console.error('Session expired:', message);\n setStatus('idle');\n setIsConnecting(false);\n setIsConversationActive(false);\n setEphemeralToken(null); // Clear expired token so reconnection gets fresh one\n hasCreatedConversationRef.current = false; // Allow creating new conversation\n break;\n }\n console.error('OpenAI API error:', message);\n onError(new Error(message.error.message || 'Unknown API error'), 'OpenAI API error');\n setStatus('idle');\n setIsConnecting(false);\n setIsConversationActive(false);\n setEphemeralToken(null); // Clear token in case of auth-related errors\n hasCreatedConversationRef.current = false; // Allow creating new conversation\n break;\n \n default:\n if (!IGNORE_MESSAGE_TYPES.some(fragment => message.type.includes(fragment))) {\n console.log('Unhandled:', message.type, message);\n }\n }\n } catch (error) {\n console.error('Error handling WebRTC message:', error);\n setStatus('idle');\n setIsConversationActive(false);\n }\n };\n \n // Start the session using SDP\n const offer = await pc.createOffer();\n await pc.setLocalDescription(offer);\n \n if (!pc.localDescription || !pc.localDescription.sdp) {\n throw new Error('Failed to create local SDP offer');\n }\n \n const baseUrl = OPENAI_REALTIME_BASE;\n const model = OPENAI_REALTIME_MODEL;\n \n \n const sdpResponse = await fetch(`${baseUrl}?model=${model}`, {\n method: 'POST',\n body: pc.localDescription.sdp,\n headers: {\n Authorization: `Bearer ${ephemeralToken}`,\n 'Content-Type': 'application/sdp'\n },\n });\n \n if (!sdpResponse.ok) {\n const errorText = await sdpResponse.text().catch(() => 'No error details available');\n console.error('WebRTC connection failed with status:', sdpResponse.status);\n console.error('Error details:', errorText);\n \n // Clear token on authentication failures\n if (sdpResponse.status === 401 || sdpResponse.status === 403) {\n setEphemeralToken(null);\n }\n \n throw new Error(`Failed to connect to OpenAI WebRTC: ${sdpResponse.status} - ${errorText}`);\n }\n \n const answerSdp = await sdpResponse.text();\n \n const answer = {\n type: 'answer',\n sdp: answerSdp,\n };\n \n await pc.setRemoteDescription(answer as RTCSessionDescriptionInit);\n \n return true;\n } catch (error) {\n console.error('Error initializing WebRTC:', error);\n onError(error as Error, 'WebRTC initialization failed');\n setIsConnecting(false);\n return false;\n }\n };\n\n // ===== SESSION MANAGEMENT =====\n \n const startConversationSession = hooks.useCallback(async () => {\n try {\n setStatus('processing');\n \n if (peerConnectionRef.current && dataChannelRef.current?.readyState === 'open' && mediaStreamRef.current) {\n mediaStreamRef.current.getAudioTracks().forEach(track => {\n track.enabled = true;\n });\n setStatus('recording');\n return true;\n } else {\n cleanupWebRTC();\n \n try {\n setIsConnecting(true);\n \n // Ensure we have a valid token (get fresh one if needed)\n if (!ephemeralToken) {\n console.log('No token available, getting fresh token...');\n const conversationData = await handleCreateNewConversation();\n if (!conversationData) {\n console.error('Failed to get fresh token');\n setIsConnecting(false);\n setStatus('idle');\n return false;\n }\n }\n \n let audioStream: MediaStream | null = null;\n \n // Always attempt microphone access for voice functionality\n if (true) {\n try {\n audioStream = await navigator.mediaDevices.getUserMedia({ \n audio: {\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n channelCount: 1,\n sampleRate: 48000,\n }\n });\n mediaStreamRef.current = audioStream;\n console.log('Microphone access granted - audio tracks:', audioStream.getAudioTracks().length);\n } catch (micError) {\n console.error('Microphone access failed:', micError);\n console.log('Voice functionality will not be available - continuing with text-only mode');\n // Continue without microphone for text-only mode\n }\n }\n \n const initialized = await initializeWebRTC(audioStream);\n \n if (!initialized) {\n // Clean up if initialization fails\n if (audioStream) {\n audioStream.getAudioTracks().forEach(track => {\n track.stop();\n });\n mediaStreamRef.current = null;\n }\n setStatus('idle');\n setIsConnecting(false);\n return false;\n }\n \n // Set appropriate status based on whether we have audio\n if (audioStream) {\n setStatus('recording');\n } else {\n setStatus('idle'); // Text-only mode, no recording status needed\n }\n return true;\n } catch (error) {\n console.error('Error during conversation setup:', error);\n onError(error as Error, 'Microphone or WebRTC setup failed');\n setStatus('idle');\n setIsConnecting(false);\n return false;\n }\n }\n } catch (error) {\n setStatus('idle');\n setIsConnecting(false);\n onError(error as Error, 'Starting conversation failed');\n return false;\n }\n }, [ephemeralToken, onError]);\n\n const endConversationSession = hooks.useCallback(() => {\n if (!isClient) return;\n \n if (mediaStreamRef.current) {\n mediaStreamRef.current.getAudioTracks().forEach(track => {\n track.stop();\n });\n }\n \n cleanupWebRTC();\n setStatus('idle');\n \n // Clear localStorage when conversation is explicitly ended\n clearConversationStorage();\n \n // Reset restored messages state\n setRestoredMessages([]);\n \n // Reset auto-start flag to allow future auto-starts\n hasAttemptedAutoStartRef.current = false;\n }, [isClient]);\n\n // ===== UI EVENT HANDLERS =====\n \n const handleToggleConversation = async () => {\n if (!isClient) return;\n \n if (!hasInteracted) {\n setHasInteracted(true);\n localStorage.setItem('guideAI_hasInteracted', 'true');\n \n // Show onboarding on first interaction\n setShowOnboarding(true);\n return;\n }\n \n if (!isConversationActive) {\n const success = await startConversationSession();\n if (success) {\n setIsConversationActive(true);\n // Always show transcript when conversation starts\n if (transcriptOptions?.enabled !== false) {\n setShowTranscript(true);\n }\n // Show text input option by default (unless explicitly disabled)\n if (inputOptions?.enableTextInput !== false) {\n setShowTextInput(true);\n }\n }\n } else {\n endConversationSession();\n setIsConversationActive(false);\n // Hide transcript and text input when conversation ends\n if (transcriptOptions?.enabled !== false) {\n setShowTranscript(false);\n }\n setShowTextInput(false);\n }\n };\n\n const handleToggleTranscript = () => {\n setShowTranscript(prev => !prev);\n };\n\n const handleToggleInputMode = () => {\n setInputMode(prev => {\n const newMode = prev === 'voice' ? 'text' : 'voice';\n // Update text input visibility based on new mode\n if (newMode === 'text' && isConversationActive) {\n setShowTextInput(true);\n } else {\n setShowTextInput(false);\n }\n return newMode;\n });\n };\n\n\n\n const handleTextSubmit = async () => {\n if (!textInput.trim() || !isConversationActive) return;\n\n // Log the user's text message\n handleLogMessage(textInput.trim(), 'HUMAN');\n\n // Send text message to AI via WebRTC data channel\n if (dataChannelRef.current?.readyState === 'open') {\n const message = {\n type: \"conversation.item.create\",\n item: {\n type: \"message\",\n role: \"user\",\n content: [{\n type: \"input_text\",\n text: textInput.trim()\n }]\n }\n };\n \n dataChannelRef.current.send(JSON.stringify(message));\n\n // Trigger response generation\n const responseMessage = {\n type: \"response.create\"\n };\n dataChannelRef.current.send(JSON.stringify(responseMessage));\n }\n\n // Clear the input\n setTextInput('');\n };\n\n const handleTextKeyPress = (event: React.KeyboardEvent) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n handleTextSubmit();\n }\n };\n\n const handleOnboardingComplete = async () => {\n setShowOnboarding(false);\n \n // Start the conversation session when onboarding is completed\n const success = await startConversationSession();\n if (success) {\n setIsConversationActive(true);\n // Only auto-show transcript if enabled in options\n if (transcriptOptions?.enabled !== false) {\n setShowTranscript(true);\n }\n }\n };\n\n const handleOnboardingClose = () => {\n setShowOnboarding(false);\n };\n\n const handleCloseTranscript = () => {\n setShowTranscript(false);\n };\n\n // ===== REACT EFFECTS & LIFECYCLE ===== \n \n // CSS styles injection effect\n hooks.useEffect(() => {\n injectStyles(guideAIStyles, 'guide-ai-styles');\n }, [guideAIStyles]);\n \n // Metadata initialization effect\n hooks.useEffect(() => {\n eventTracker.initialize();\n if (metadataOptions?.initialUserData) {\n metadataTracker.updateUserInfo(metadataOptions.initialUserData);\n }\n }, [eventTracker, metadataTracker, metadataOptions?.initialUserData]);\n \n // Component initialization effect\n hooks.useEffect(() => {\n console.log('GuideAI: Component mounting - initialization started', { \n hasInitialized: hasInitializedRef.current,\n initializationInProgress: initializationInProgressRef.current,\n organizationKey,\n timestamp: Date.now()\n });\n \n // Double-check to prevent race conditions\n if (hasInitializedRef.current || initializationInProgressRef.current || isUnmountingRef.current || globalInitializationInProgress) {\n console.log('GuideAI: Already initialized, initialization in progress, unmounting, or global initialization in progress, skipping');\n return;\n }\n \n // Set flags immediately to prevent concurrent initialization\n hasInitializedRef.current = true;\n initializationInProgressRef.current = true;\n globalInitializationInProgress = true;\n \n setIsClient(true);\n setIsConnecting(true); // Show loading state during initialization\n \n // Check for stored conversation before initializing\n const { shouldRestore, conversationId, messages } = checkForStoredConversation(organizationKey);\n \n if (shouldRestore && conversationId && messages) {\n // Store the restored messages to use as context\n setRestoredMessages(messages);\n } else {\n // No valid conversation to restore\n setRestoredMessages([]);\n }\n \n // Create new conversation (gets conversation + token + prompt)\n handleCreateNewConversation().then(conversationData => {\n if (!isUnmountingRef.current) {\n setIsConnecting(false); // Hide loading state when done\n globalInitializationInProgress = false; // Release global flag\n }\n }).catch(error => {\n if (!isUnmountingRef.current) {\n setIsConnecting(false); // Hide loading state on error\n console.error('Failed to create conversation:', error);\n globalInitializationInProgress = false; // Release global flag\n }\n });\n \n const hasInteractedBefore = localStorage.getItem('guideAI_hasInteracted');\n if (!hasInteractedBefore) {\n setHasInteracted(false);\n } else {\n setHasInteracted(true);\n }\n }, [organizationKey, handleCreateNewConversation, checkForStoredConversation]);\n \n // Component cleanup effect\n hooks.useEffect(() => {\n return () => {\n console.log('GuideAI: Component unmounting - cleanup triggered', { \n hasInitialized: hasInitializedRef.current,\n initializationInProgress: initializationInProgressRef.current,\n isUnmounting: isUnmountingRef.current,\n timestamp: Date.now()\n });\n \n // Set unmounting flag to prevent any new initialization\n isUnmountingRef.current = true;\n cleanupWebRTC();\n \n if (audioElementRef.current) {\n audioElementRef.current.srcObject = null;\n audioElementRef.current.remove();\n audioElementRef.current = null;\n }\n \n // Stop event tracking on cleanup\n if (eventTracker) {\n eventTracker.stopTracking();\n }\n \n // Stop metadata tracking and sync any pending updates\n if (metadataTracker) {\n metadataTracker.destroy();\n }\n \n // Reset flags on cleanup\n hasInitializedRef.current = false;\n initializationInProgressRef.current = false;\n isUnmountingRef.current = false;\n hasAttemptedAutoStartRef.current = false;\n globalInitializationInProgress = false;\n };\n }, [cleanupWebRTC, eventTracker, metadataTracker]);\n\n // Metadata sync effect - periodically sync metadata updates to backend\n hooks.useEffect(() => {\n const syncInterval = metadataOptions?.config?.syncInterval || 30000; // 30 seconds default\n \n const syncTimer = setInterval(async () => {\n if (metadataTracker) {\n const pendingUpdates = metadataTracker.syncNow();\n if (pendingUpdates.length > 0) {\n try {\n await sendMetadataUpdates(pendingUpdates, organizationKey, onError);\n \n // Notify parent component of metadata updates if callback provided\n if (metadataOptions?.onMetadataUpdate) {\n metadataOptions.onMetadataUpdate(metadataTracker.getMetadata());\n }\n } catch (error) {\n console.error('Failed to sync metadata updates:', error);\n }\n }\n }\n }, syncInterval);\n\n return () => {\n clearInterval(syncTimer);\n };\n }, [organizationKey, metadataOptions?.config?.syncInterval, metadataOptions?.onMetadataUpdate]);\n\n // Auto-restart effect - handles reconnection when token and restored messages are ready\n hooks.useEffect(() => {\n if (ephemeralToken && restoredMessages.length > 0 && !hasAttemptedAutoStartRef.current) {\n console.log('Auto-restarting conversation with', restoredMessages.length, 'restored messages');\n hasAttemptedAutoStartRef.current = true;\n \n startConversationSession().then(success => {\n if (success) {\n setIsConversationActive(true);\n setHasInteracted(true);\n localStorage.setItem('guideAI_hasInteracted', 'true');\n }\n });\n }\n }, [ephemeralToken, restoredMessages, startConversationSession]);\n\n // Load restored messages into allMessages state\n hooks.useEffect(() => {\n if (restoredMessages.length > 0 && allMessages.length === 0) {\n setAllMessages(restoredMessages);\n }\n }, [restoredMessages, allMessages.length]);\n\n // Update popup position when needed\n hooks.useEffect(() => {\n if (showOnboarding || (!hasInteracted && ephemeralToken)) {\n // Use onboarding dimensions if onboarding is shown, otherwise welcome bubble dimensions\n const height = showOnboarding ? 240 : 50;\n const spacing = showOnboarding ? 20 : 15;\n setPopupPosition(getOptimalPosition(height, spacing));\n }\n }, [showOnboarding, hasInteracted, ephemeralToken, getOptimalPosition]);\n\n // ===== METADATA HELPER FUNCTIONS =====\n \n // Expose metadata tracking methods globally on window for external access\n hooks.useEffect(() => {\n if (typeof window !== 'undefined') {\n // Create global GuideAI metadata API\n (window as any).GuideAI = {\n ...(window as any).GuideAI,\n metadata: {\n // Track user login\n trackLogin: (additionalInfo?: Partial<UserMetadata>) => {\n metadataTracker?.trackLogin(additionalInfo);\n },\n \n // Update user information\n updateUserInfo: (userInfo: Partial<UserMetadata>) => {\n metadataTracker?.updateUserInfo(userInfo);\n },\n \n // Track custom events\n trackCustomEvent: (eventType: string, customData: Record<string, any>) => {\n metadataTracker?.trackCustomEvent(eventType, customData);\n },\n \n // Get current metadata\n getMetadata: () => {\n return metadataTracker?.getMetadata() || null;\n },\n \n // Force sync metadata now\n syncMetadata: async () => {\n if (metadataTracker) {\n const updates = metadataTracker.syncNow();\n if (updates.length > 0) {\n return await sendMetadataUpdates(updates, organizationKey, onError);\n }\n }\n return true;\n }\n },\n transcript: {\n // Toggle transcript visibility\n toggle: () => {\n setShowTranscript(prev => !prev);\n },\n \n // Show transcript\n show: () => {\n setShowTranscript(true);\n },\n \n // Hide transcript\n hide: () => {\n setShowTranscript(false);\n },\n \n // Get current transcript visibility\n isVisible: () => {\n return showTranscript;\n }\n },\n input: {\n // Toggle input mode between voice and text\n toggleMode: () => {\n handleToggleInputMode();\n },\n \n // Set input mode\n setMode: (mode: 'voice' | 'text') => {\n setInputMode(mode);\n if (mode === 'text' && inputOptions?.enableTextInput !== false && isConversationActive) {\n setShowTextInput(true);\n } else {\n setShowTextInput(false);\n }\n },\n \n // Get current input mode\n getMode: () => {\n return inputMode;\n },\n \n // Send text message programmatically\n sendText: (text: string) => {\n if (text.trim() && isConversationActive) {\n setTextInput(text);\n handleTextSubmit();\n }\n }\n }\n };\n }\n }, [organizationKey, metadataTracker, showTranscript, inputMode, isConversationActive]);\n\n if (!isClient) {\n return null;\n }\n\n // Determine if we should use fixed positioning (when position props are provided)\n const shouldUseFixedPosition = componentPosition && Object.keys(componentPosition).length > 0;\n \n // Base styles for the component\n const baseStyles: React.CSSProperties = {\n position: shouldUseFixedPosition ? 'fixed' : 'relative',\n zIndex: shouldUseFixedPosition ? 1000 : 'auto',\n ...(shouldUseFixedPosition ? componentPosition : {}),\n };\n\n return (\n <>\n <div\n ref={componentRef}\n style={baseStyles}\n >\n <div className=\"guideai-main-ui\">\n {!hasInteracted && ephemeralToken && (\n <WelcomeBubble position={popupPosition} />\n )}\n \n <Onboarding \n position={popupPosition}\n isVisible={showOnboarding}\n onComplete={handleOnboardingComplete}\n onClose={handleOnboardingClose}\n />\n \n <div className=\"guideai-main-controls\">\n <div \n className={`guideai-icon-wrapper ${isConnecting ? 'initializing' : status}`}\n onClick={isConnecting ? undefined : handleToggleConversation}\n style={isConnecting ? { cursor: 'default' } : undefined}\n title={isConnecting ? 'Initializing...' : \n status === 'idle' ? 'Click to start conversation' : \n status === 'recording' ? 'Click to end conversation' : \n status === 'processing' ? 'Processing your message...' : \n 'AI is speaking, click to end conversation'}\n >\n {isConnecting && <i className=\"guideai-icon initializing\" />}\n {!isConnecting && status === 'idle' && <i className=\"guideai-icon microphone\" />}\n {!isConnecting && status === 'recording' && <i className=\"guideai-icon recording\" />}\n {!isConnecting && status === 'processing' && <i className=\"guideai-icon processing\" />}\n {!isConnecting && status === 'playing' && <i className=\"guideai-icon playing\" />}\n </div>\n \n </div>\n \n </div>\n </div>\n \n {/* Transcript Box */}\n <TranscriptBox\n messages={allMessages}\n isVisible={showTranscript}\n onClose={handleCloseTranscript}\n showToggleButton={transcriptOptions?.showToggleButton !== false && isConversationActive}\n onToggle={handleToggleTranscript}\n showTextInput={isConversationActive && inputOptions?.enableTextInput !== false}\n textInput={textInput}\n onTextInputChange={setTextInput}\n onTextSubmit={handleTextSubmit}\n onTextKeyPress={handleTextKeyPress}\n textPlaceholder={inputOptions?.placeholder || \"Type your message...\"}\n />\n </>\n );\n};\n\nexport default GuideAI;","import { PopupPosition } from '../types/GuideAI.types';\n\n// Function to inject CSS styles into the document head\nexport const injectStyles = (css: string, id: string) => {\n if (typeof document === 'undefined') return; // SSR safety\n \n // Check if styles are already injected\n if (document.getElementById(id)) return;\n \n const styleElement = document.createElement('style');\n styleElement.id = id;\n styleElement.textContent = css;\n document.head.appendChild(styleElement);\n};\n\n// Calculate optimal position for popups based on component location\nexport const calculateOptimalPosition = (\n componentRect: DOMRect, \n elementHeight: number = 240, \n spacing: number = 15\n): PopupPosition => {\n const viewportHeight = window.innerHeight;\n \n const spaceAbove = componentRect.top;\n const spaceBelow = viewportHeight - componentRect.bottom;\n \n const canFitBelow = spaceBelow >= (elementHeight + spacing);\n const canFitAbove = spaceAbove >= (elementHeight + spacing);\n \n if (canFitBelow) {\n return 'below';\n } else if (canFitAbove) {\n return 'above';\n } else {\n return spaceBelow > spaceAbove ? 'below' : 'above';\n }\n}; ","import React from 'react';\nimport { StoredMessage } from '../utils/messageStorage';\n\ninterface TranscriptBoxProps {\n messages: StoredMessage[];\n isVisible: boolean;\n onClose: () => void;\n showToggleButton?: boolean;\n onToggle?: () => void;\n showTextInput?: boolean;\n textInput?: string;\n onTextInputChange?: (value: string) => void;\n onTextSubmit?: () => void;\n onTextKeyPress?: (event: React.KeyboardEvent) => void;\n textPlaceholder?: string;\n}\n\nconst TranscriptBox: React.FC<TranscriptBoxProps> = ({ \n messages, \n isVisible, \n onClose, \n showToggleButton = true, \n onToggle,\n showTextInput = false,\n textInput = '',\n onTextInputChange,\n onTextSubmit,\n onTextKeyPress,\n textPlaceholder = \"Type your message...\"\n}) => {\n const formatTime = (timestamp: number) => {\n return new Date(timestamp).toLocaleTimeString([], { \n hour: '2-digit', \n minute: '2-digit' \n });\n };\n\n const scrollToBottom = (element: HTMLDivElement) => {\n element.scrollTop = element.scrollHeight;\n };\n\n React.useEffect(() => {\n const transcriptContainer = document.getElementById('guideai-transcript-container');\n if (transcriptContainer) {\n scrollToBottom(transcriptContainer as HTMLDivElement);\n }\n }, [messages]);\n\n // Show toggle button if there are messages and toggle is enabled, even when transcript is hidden\n const shouldShowToggleButton = showToggleButton && messages.length > 0;\n \n // Show transcript if visible OR if text input should be shown\n const shouldShowTranscript = isVisible || showTextInput;\n \n // Don't render anything if no messages, no toggle button, and no text input\n if (messages.length === 0 && !shouldShowToggleButton && !showTextInput) return null;\n\n return (\n <div className=\"guideai-transcript-overlay\">\n {/* Toggle Button - shows even when transcript is hidden */}\n {shouldShowToggleButton && (\n <button\n className=\"guideai-transcript-toggle-button\"\n onClick={onToggle}\n title={isVisible ? 'Hide Transcript' : 'Show Transcript'}\n >\n <span className=\"guideai-transcript-toggle-icon\">\n {isVisible ? '📄' : '📋'}\n </span>\n </button>\n )}\n \n {/* Transcript Box - show when visible or when text input is needed */}\n {shouldShowTranscript && (\n <div className=\"guideai-transcript-box\">\n {/* Messages Container - only show when transcript is visible */}\n {isVisible && (\n <div \n id=\"guideai-transcript-container\"\n className=\"guideai-transcript-messages\"\n >\n {messages.length === 0 ? (\n <div className=\"guideai-transcript-empty\">\n <div className=\"guideai-transcript-empty-icon\">🎤</div>\n <p>Start a conversation to see the transcript here</p>\n </div>\n ) : (\n messages.map((message, index) => (\n <div \n key={`${message.timestamp}-${index}`}\n className={`guideai-transcript-message ${message.sender.toLowerCase()}`}\n >\n <div className=\"guideai-transcript-message-content\">\n <div className=\"guideai-transcript-message-sender\">\n {message.sender === 'HUMAN' ? 'You' : 'GuideAI'}\n </div>\n <div className=\"guideai-transcript-message-text\">\n {message.content}\n </div>\n <div className=\"guideai-transcript-message-time\">\n {formatTime(message.timestamp)}\n </div>\n </div>\n </div>\n ))\n )}\n </div>\n )}\n \n {/* Text Input - show when in text mode */}\n {showTextInput && (\n <div className=\"guideai-transcript-text-input\">\n <textarea\n className=\"guideai-transcript-input-field\"\n value={textInput}\n onChange={(e) => onTextInputChange?.(e.target.value)}\n onKeyPress={onTextKeyPress}\n placeholder={textPlaceholder}\n rows={2}\n />\n <button\n className=\"guideai-transcript-send-button\"\n onClick={onTextSubmit}\n disabled={!textInput.trim()}\n title=\"Send Message\"\n >\n <span className=\"guideai-transcript-send-icon\">📤</span>\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default TranscriptBox; ","import React, { useState } from 'react';\nimport { PopupPosition } from '../types/GuideAI.types';\n\ninterface OnboardingProps {\n position: PopupPosition;\n isVisible: boolean;\n onComplete: () => void; // Called when user completes onboarding and wants to start conversation\n onClose: () => void; // Called when user closes onboarding without completing\n}\n\nconst Onboarding: React.FC<OnboardingProps> = ({ position, isVisible, onComplete, onClose }) => {\n const [step, setStep] = useState(1);\n\n const handleNext = () => {\n if (step < 3) {\n setStep(step + 1);\n } else {\n // Reset step and complete onboarding\n setStep(1);\n onComplete();\n }\n };\n\n const handleClose = () => {\n // Reset step when closing\n setStep(1);\n onClose();\n };\n\n if (!isVisible) {\n return null;\n }\n\n return (\n <div className={`guideai-onboarding ${position}`}>\n <div className=\"guideai-onboarding-content\">\n <button className=\"guideai-onboarding-close\" onClick={handleClose}>×</button>\n \n {step === 1 && (\n <div className=\"guideai-onboarding-step\">\n <div className=\"guideai-onboarding-icon volume-icon\">🔊</div>\n <h3>Turn on your volume</h3>\n <p>Make sure your device's volume is turned on so you can hear Guide AI's responses.</p>\n </div>\n )}\n \n {step === 2 && (\n <div className=\"guideai-onboarding-step\">\n <div className=\"guideai-onboarding-icon mic-icon\">🎤</div>\n <h3>Allow microphone access</h3>\n <p>When prompted, click \"Allow\" to let Guide AI access your microphone.</p>\n </div>\n )}\n \n {step === 3 && (\n <div className=\"guideai-onboarding-step\">\n <div className=\"guideai-onboarding-icon ready-icon\">✅</div>\n <h3>You're all set!</h3>\n <p>Click the microphone icon to start asking questions.</p>\n </div>\n )}\n \n <div className=\"guideai-onboarding-dots\">\n <span className={`dot ${step === 1 ? 'active' : ''}`}></span>\n <span className={`dot ${step === 2 ? 'active' : ''}`}></span>\n <span className={`dot ${step === 3 ? 'active' : ''}`}></span>\n </div>\n \n <button className=\"guideai-onboarding-next\" onClick={handleNext}>\n {step < 3 ? 'Next' : 'Get Started'}\n </button>\n </div>\n </div>\n );\n};\n\nexport default Onboarding; ","import React from 'react';\nimport { PopupPosition } from '../types/GuideAI.types';\n\ninterface WelcomeBubbleProps {\n position: PopupPosition;\n}\n\nconst WelcomeBubble: React.FC<WelcomeBubbleProps> = ({ position }) => {\n return (\n <div className={`guideai-welcome-bubble ${position}`}>\n Stuck? Click here and ask me a question\n </div>\n );\n};\n\nexport default WelcomeBubble; ","// Event tracking system for GuideAI\n// Tracks click, focus, change, and submit events on all relevant elements\n\ninterface EventData {\n type: 'click' | 'focus' | 'change' | 'submit' | 'route_change';\n element?: Element;\n tagName?: string;\n className?: string;\n id?: string;\n textContent?: string;\n value?: string;\n formData?: FormData;\n timestamp: number;\n url: string;\n previousUrl?: string;\n event?: Event;\n // Customer metadata\n customerId?: string;\n customerType?: string;\n customerSegment?: string;\n // Session metadata\n sessionId?: string;\n deviceType?: 'desktop' | 'mobile' | 'tablet';\n userAgent?: string;\n screenResolution?: string;\n // Application context\n currentPage?: string;\n userRole?: string;\n organizationId?: string;\n // Geographic and timezone\n timezone?: string;\n locale?: string;\n}\n\nclass EventTracker {\n private isTracking: boolean = false;\n private eventData: EventData[] = [];\n private batchSize: number = 10; // Emit every 10 events\n private batchTimeout: number = 5000; // Emit every 5 seconds\n private batchTimer: NodeJS.Timeout | null = null;\n private pendingEvents: EventData[] = [];\n private currentUrl: string = '';\n private organizationKey?: string;\n\n // Customer metadata storage\n private customerMetadata: {\n customerId?: string;\n customerType?: string;\n customerSegment?: string;\n userRole?: string;\n organizationId?: string;\n } = {};\n\n constructor(options?: { customerId?: string; customerType?: string; organizationId?: string; organizationKey?: string; }) {\n if (options?.customerId) {\n this.customerMetadata.customerId = String(options.customerId);\n }\n if (options?.customerType) {\n this.customerMetadata.customerType = options.customerType;\n }\n if (options?.organizationId) {\n this.customerMetadata.organizationId = String(options.organizationId);\n }\n if (options?.organizationKey) {\n this.organizationKey = options.organizationKey;\n }\n // Do not auto-initialize on server; caller should invoke initialize() on client\n }\n\n\n\n // Method to set customer metadata\n public setCustomerMetadata(metadata: Partial<typeof this.customerMetadata>): void {\n // All remaining metadata is safe to collect\n this.customerMetadata = { ...this.customerMetadata, ...metadata };\n }\n\n // Method to get customer metadata\n public getCustomerMetadata(): typeof this.customerMetadata {\n return { ...this.customerMetadata };\n }\n\n // Method to clear customer metadata\n public clearCustomerMetadata(): void {\n this.customerMetadata = {};\n }\n\n public initialize(): void {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n // Start tracking when DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => this.startTracking());\n } else {\n this.startTracking();\n }\n }\n\n // Helper method to enrich event data with customer metadat\n private enrichEventData(baseEventData: Omit<EventData, 'customerId' | 'customerType' | 'customerSegment' | 'sessionId' | 'deviceType' | 'userAgent' | 'screenResolution' | 'currentPage' | 'userRole' | 'organizationId' | 'timezone' | 'locale'>): EventData {\n const enrichedData = {\n ...baseEventData,\n // Customer metadata\n customerId: this.customerMetadata.customerId,\n customerType: this.customerMetadata.customerType,\n customerSegment: this.customerMetadata.customerSegment,\n organizationKey: this.organizationKey,\n // Session metadata\n sessionId: this.getSessionId(),\n deviceType: this.getDeviceType(),\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : undefined,\n screenResolution: typeof screen !== 'undefined' ? `${screen.width}x${screen.height}` : undefined,\n // Application context\n currentPage: window.location.pathname,\n userRole: this.customerMetadata.userRole,\n organizationId: this.customerMetadata.organizationId,\n // Geographic and timezone\n timezone: typeof Intl !== 'undefined' && typeof Intl.DateTimeFormat !== 'undefined'\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefined,\n locale: navigator.language,\n };\n\n return enrichedData;\n }\n\n\n\n // Helper method to get or create session ID\n private getSessionId(): string {\n let sessionId = sessionStorage.getItem('eventTracker_sessionId');\n if (!sessionId) {\n sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n sessionStorage.setItem('eventTracker_sessionId', sessionId);\n }\n return sessionId;\n }\n\n // Helper method to detect device type\n private getDeviceType(): 'desktop' | 'mobile' | 'tablet' {\n if (typeof navigator === 'undefined') {\n return 'desktop';\n }\n const userAgent = navigator.userAgent.toLowerCase();\n if (/tablet|ipad|playbook|silk/i.test(userAgent)) {\n return 'tablet';\n }\n if (/mobile|android|iphone|ipod|blackberry|opera mini|iemobile/i.test(userAgent)) {\n return 'mobile';\n }\n return 'desktop';\n }\n\n public startTracking(): void {\n if (this.isTracking) return;\n\n this.isTracking = true;\n console.log('EventTracker: Started tracking events');\n\n // Track click events on all elements\n this.trackClickEvents();\n\n // Track focus events on focusable elements\n this.trackFocusEvents();\n\n // Track change events on form elements\n this.trackChangeEvents();\n\n // Track submit events on forms\n this.trackSubmitEvents();\n\n // Track route changes\n this.trackRouteChanges();\n }\n\n public stopTracking(): void {\n if (!this.isTracking) return;\n\n this.isTracking = false;\n console.log('EventTracker: Stopped tracking events');\n\n // Emit any pending events before stopping\n this.emitBatch();\n\n // Remove all event listeners\n document.removeEventListener('click', this.handleClick, true);\n document.removeEventListener('focus', this.handleFocus, true);\n document.removeEventListener('change', this.handleChange, true);\n document.removeEventListener('submit', this.handleSubmit, true);\n window.removeEventListener('popstate', this.handlePopstate);\n window.removeEventListener('hashchange', this.handleHashChange);\n }\n\n private trackClickEvents(): void {\n document.addEventListener('click', this.handleClick, true);\n }\n\n private trackFocusEvents(): void {\n document.addEventListener('focus', this.handleFocus, true);\n }\n\n private trackChangeEvents(): void {\n document.addEventListener('change', this.handleChange, true);\n }\n\n private trackSubmitEvents(): void {\n document.addEventListener('submit', this.handleSubmit, true);\n }\n\n private trackRouteChanges(): void {\n // Track browser back/forward navigation\n window.addEventListener('popstate', this.handlePopstate);\n\n // Track hash changes\n window.addEventListener('hashchange', this.handleHashChange);\n\n // Track History API changes (pushState, replaceState)\n this.interceptHistoryAPI();\n }\n\n private handleClick = (event: Event): void => {\n if (!this.isTracking) return;\n\n const target = event.target as Element;\n const baseEventData = {\n type: 'click' as const,\n element: target,\n tagName: target.tagName,\n className: target.className,\n id: target.id,\n textContent: target.textContent?.substring(0, 100),\n value: this.getSafeValue(target),\n timestamp: Date.now(),\n url: window.location.href,\n event: event\n };\n\n this.logEvent(baseEventData);\n };\n\n private handleFocus = (event: Event): void => {\n if (!this.isTracking) return;\n\n const target = event.target as Element;\n\n // Only track focus on focusable elements\n if (this.isFocusable(target)) {\n const baseEventData = {\n type: 'focus' as const,\n element: target,\n tagName: target.tagName,\n className: target.className,\n id: target.id,\n textContent: target.textContent?.substring(0, 100),\n value: this.getSafeValue(target),\n timestamp: Date.now(),\n url: window.location.href,\n event: event\n };\n\n this.logEvent(baseEventData);\n }\n };\n\n private handleChange = (event: Event): void => {\n if (!this.isTracking) return;\n\n const target = event.target as Element;\n\n // Only track change on form elements\n if (this.isFormElement(target)) {\n const baseEventData = {\n type: 'change' as const,\n element: target,\n tagName: target.tagName,\n className: target.className,\n id: target.id,\n textContent: target.textContent?.substring(0, 100),\n value: this.getSafeValue(target),\n timestamp: Date.now(),\n url: window.location.href,\n event: event\n };\n\n this.logEvent(baseEventData);\n }\n };\n\n private handleSubmit = (event: Event): void => {\n if (!this.isTracking) return;\n\n const target = event.target as Element;\n\n // Only track submit on form elements\n if (target.tagName === 'FORM') {\n const form = target as HTMLFormElement;\n const formData = new FormData(form);\n\n const baseEventData = {\n type: 'submit' as const,\n element: target,\n tagName: target.tagName,\n className: target.className,\n id: target.id,\n textContent: target.textContent?.substring(0, 100),\n formData: formData,\n timestamp: Date.now(),\n url: window.location.href,\n event: event\n };\n\n this.logEvent(baseEventData);\n }\n };\n\n private handlePopstate = (event: PopStateEvent): void => {\n if (!this.isTracking) return;\n\n const baseEventData = {\n type: 'route_change' as const,\n timestamp: Date.now(),\n url: window.location.href,\n previousUrl: this.getPreviousUrl(),\n event: event\n };\n\n this.logEvent(baseEventData);\n };\n\n private handleHashChange = (event: HashChangeEvent): void => {\n if (!this.isTracking) return;\n\n const baseEventData = {\n type: 'route_change' as const,\n timestamp: Date.now(),\n url: window.location.href,\n previousUrl: event.oldURL,\n event: event\n };\n\n this.logEvent(baseEventData);\n };\n\n private interceptHistoryAPI(): void {\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n\n // Store the current URL before interception\n this.currentUrl = window.location.href;\n\n // Intercept pushState\n history.pushState = (...args) => {\n const previousUrl = this.currentUrl;\n const result = originalPushState.apply(history, args);\n this.currentUrl = window.location.href;\n\n if (this.isTracking) {\n const baseEventData = {\n type: 'route_change' as const,\n timestamp: Date.now(),\n url: window.location.href,\n previousUrl: previousUrl\n };\n this.logEvent(baseEventData);\n }\n\n return result;\n };\n\n // Intercept replaceState\n history.replaceState = (...args) => {\n const previousUrl = this.currentUrl;\n const result = originalReplaceState.apply(history, args);\n this.currentUrl = window.location.href;\n\n if (this.isTracking) {\n const baseEventData = {\n type: 'route_change' as const,\n timestamp: Date.now(),\n url: window.location.href,\n previousUrl: previousUrl\n };\n this.logEvent(baseEventData);\n }\n\n return result;\n };\n }\n\n private getPreviousUrl(): string {\n return this.currentUrl || window.location.href;\n }\n\n private getSafeValue(element: Element): string | undefined {\n const tagName = element.tagName.toLowerCase();\n const inputElement = element as HTMLInputElement;\n const selectElement = element as HTMLSelectElement;\n\n // Only collect values for elements that are typically useful for targeting\n switch (tagName) {\n case 'button':\n return inputElement.value || inputElement.textContent?.trim();\n\n case 'select':\n return `${selectElement.name || ''}|${selectElement.type || ''}|${selectElement.selectedIndex || 0}`;\n\n case 'textarea':\n return inputElement.name || inputElement.type || '';\n\n case 'input':\n const inputType = inputElement.type;\n // Only collect value for button-like input types\n if (inputType === 'submit' || inputType === 'button' || inputType === 'reset') {\n return `${inputElement.name || ''}|${inputType}|${inputElement.value || ''}`;\n }\n // For other input types, only collect name and type, not the actual value\n return `${inputElement.name || ''}|${inputType}`;\n\n default:\n return undefined;\n }\n }\n\n private isFocusable(element: Element): boolean {\n const focusableSelectors = [\n 'input:not([type=\"hidden\"])',\n 'select',\n 'textarea',\n 'button',\n 'a[href]',\n 'area[href]',\n 'iframe',\n 'object',\n 'embed',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]'\n ];\n\n return focusableSelectors.some(selector => element.matches(selector));\n }\n\n private isFormElement(element: Element): boolean {\n const formElementTags = ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'];\n return formElementTags.includes(element.tagName);\n }\n\n private logEvent(baseEventData: Omit<EventData, 'customerType' | 'customerSegment' | 'sessionId' | 'deviceType' | 'currentPage' | 'userRole' | 'locale'>): void {\n // Enrich the event data with customer metadata\n const enrichedEventData = this.enrichEventData(baseEventData);\n\n // Store event data for historical access\n this.eventData.push(enrichedEventData);\n\n // Add to pending batch\n this.pendingEvents.push(enrichedEventData);\n\n // Check if we should emit based on batch size\n if (this.pendingEvents.length >= this.batchSize) {\n this.emitBatch();\n } else {\n // Start or reset the timeout for time-based emission\n this.startBatchTimer();\n }\n }\n\n private startBatchTimer(): void {\n // Clear existing timer\n if (this.batchTimer) {\n clearTimeout(this.batchTimer);\n }\n\n // Start new timer\n this.batchTimer = setTimeout(() => {\n this.emitBatch();\n }, this.batchTimeout);\n }\n\n private emitBatch(): void {\n if (this.pendingEvents.length === 0) return;\n\n // Create batch payload\n const batchPayload = {\n events: [...this.pendingEvents],\n batchSize: this.pendingEvents.length,\n timestamp: Date.now(),\n\n };\n\n // Console log the batch (for now)\n console.log('EventTracker Batch:', batchPayload);\n\n // Emit custom event for metadata tracking integration\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('guideai:event_batch', {\n detail: batchPayload\n }));\n }\n\n\n\n // Clear pending events\n this.pendingEvents = [];\n\n // Clear timer\n if (this.batchTimer) {\n clearTimeout(this.batchTimer);\n this.batchTimer = null;\n }\n }\n\n public getEventData(): EventData[] {\n return [...this.eventData];\n }\n\n public clearEventData(): void {\n this.eventData = [];\n }\n\n public getEventDataByType(type: EventData['type']): EventData[] {\n return this.eventData.filter(event => event.type === type);\n }\n\n public getEventDataByElement(tagName: string): EventData[] {\n return this.eventData.filter(event => event.tagName === tagName.toUpperCase());\n }\n\n public getEventDataByUrl(url: string): EventData[] {\n return this.eventData.filter(event => event.url.includes(url));\n }\n\n public emitPendingEvents(): void {\n this.emitBatch();\n }\n\n public setBatchConfig(batchSize: number, batchTimeout: number): void {\n this.batchSize = batchSize;\n this.batchTimeout = batchTimeout;\n }\n\n public getPendingEventsCount(): number {\n return this.pendingEvents.length;\n }\n\n // Customer analytics methods\n public getCustomerAnalytics(): {\n totalEvents: number;\n eventsByCustomer: Record<string, number>;\n eventsByType: Record<string, number>;\n eventsByPage: Record<string, number>;\n eventsByDevice: Record<string, number>;\n sessionDuration: number;\n lastActivity: number;\n } {\n const now = Date.now();\n const sessionStart = this.getSessionStartTime();\n const sessionDuration = now - sessionStart;\n\n const analytics = {\n totalEvents: this.eventData.length,\n eventsByCustomer: {} as Record<string, number>,\n eventsByType: {} as Record<string, number>,\n eventsByPage: {} as Record<string, number>,\n eventsByDevice: {} as Record<string, number>,\n sessionDuration,\n lastActivity: this.eventData.length > 0 ? this.eventData[this.eventData.length - 1].timestamp : now\n };\n\n // Group events by customer\n this.eventData.forEach(event => {\n if (event.customerId) {\n analytics.eventsByCustomer[event.customerId] = (analytics.eventsByCustomer[event.customerId] || 0) + 1;\n }\n\n // Group events by type\n analytics.eventsByType[event.type] = (analytics.eventsByType[event.type] || 0) + 1;\n\n // Group events by page\n if (event.currentPage) {\n analytics.eventsByPage[event.currentPage] = (analytics.eventsByPage[event.currentPage] || 0) + 1;\n }\n\n // Group events by device\n if (event.deviceType) {\n analytics.eventsByDevice[event.deviceType] = (analytics.eventsByDevice[event.deviceType] || 0) + 1;\n }\n });\n\n return analytics;\n }\n\n // Get session start time\n private getSessionStartTime(): number {\n const sessionStart = sessionStorage.getItem('eventTracker_sessionStart');\n if (!sessionStart) {\n const startTime = Date.now();\n sessionStorage.setItem('eventTracker_sessionStart', startTime.toString());\n return startTime;\n }\n return parseInt(sessionStart, 10);\n }\n\n // Method to identify customer from DOM or context\n public identifyCustomerFromContext(): void {\n // Try to find customer information from the current page context\n // This could be from meta tags, data attributes, or other DOM elements\n\n\n\n // Check for user role in meta tags\n const userRoleMeta = document.querySelector('meta[name=\"user-role\"]');\n if (userRoleMeta) {\n this.setCustomerMetadata({ userRole: userRoleMeta.getAttribute('content') || undefined });\n }\n\n\n\n // Try to infer customer type from URL or page context\n const pathname = window.location.pathname;\n if (pathname.includes('/admin/')) {\n this.setCustomerMetadata({ customerType: 'admin' });\n } else if (pathname.includes('/agent/')) {\n this.setCustomerMetadata({ customerType: 'agent' });\n } else if (pathname.includes('/business/')) {\n this.setCustomerMetadata({ customerType: 'business' });\n } else if (pathname.includes('/individual/')) {\n this.setCustomerMetadata({ customerType: 'individual' });\n }\n }\n\n // Method to set customer metadata from external source (e.g., authentication system)\n public setCustomerFromAuth(authData: {\n id?: string;\n role?: string;\n customerType?: 'individual' | 'business' | 'agent' | 'admin';\n customerSegment?: string;\n }): void {\n this.setCustomerMetadata({\n userRole: authData.role,\n customerType: authData.customerType,\n customerSegment: authData.customerSegment\n });\n }\n\n\n}\n\nexport default EventTracker;\nexport type { EventData };\n\n// Export customer metadata types for external use\nexport interface CustomerMetadata {\n customerId?: string;\n customerType?: 'individual' | 'business' | 'agent' | 'admin';\n customerSegment?: string;\n userRole?: string;\n}\n\nexport interface CustomerAnalytics {\n totalEvents: number;\n eventsByCustomer: Record<string, number>;\n eventsByType: Record<string, number>;\n eventsByPage: Record<string, number>;\n eventsByDevice: Record<string, number>;\n sessionDuration: number;\n lastActivity: number;\n}\n","// Create click effects and dispatch click event on an element\nexport const clickElement = async (element: Element, rect: DOMRect): Promise<void> => {\n return new Promise<void>((resolve) => {\n setTimeout(() => {\n const clickEffectContainer = document.createElement('div');\n clickEffectContainer.style.cssText = `\n position: fixed;\n left: ${rect.left + rect.width / 2}px;\n top: ${rect.top + rect.height / 2}px;\n width: 60px;\n height: 60px;\n z-index: 1000;\n pointer-events: none;\n transform: translate(-50%, -50%);\n `;\n document.body.appendChild(clickEffectContainer);\n \n for (let j = 0; j < 3; j++) {\n const clickRipple = document.createElement('div');\n clickRipple.style.cssText = `\n position: absolute;\n left: 50%;\n top: 50%;\n width: 40px;\n height: 40px;\n border: 2px solid rgba(0, 102, 255, ${0.7 - (j * 0.2)});\n border-radius: 50%;\n transform: translate(-50%, -50%) scale(0);\n opacity: 1;\n animation: click-ripple-animation 0.8s ease-out ${j * 0.15}s forwards;\n box-shadow: 0 0 8px rgba(0, 102, 255, 0.4);\n `;\n clickEffectContainer.appendChild(clickRipple);\n }\n \n const clickDot = document.createElement('div');\n clickDot.style.cssText = `\n position: absolute;\n left: 50%;\n top: 50%;\n width: 12px;\n height: 12px;\n background: rgba(0, 102, 255, 0.9);\n border-radius: 50%;\n transform: translate(-50%, -50%) scale(0);\n animation: click-dot-animation 0.4s ease-out forwards;\n box-shadow: 0 0 5px rgba(0, 102, 255, 0.8);\n `;\n clickEffectContainer.appendChild(clickDot);\n \n const clickEvent = new MouseEvent('click', {\n view: window,\n bubbles: true,\n cancelable: true,\n });\n\n // Check for clickable subelements (links, buttons, inputs)\n const clickableElements = element.querySelectorAll('a, button, input[type=\"button\"], input[type=\"submit\"]');\n const clickableElement = clickableElements.length > 0 ? clickableElements[0] as HTMLElement : element as HTMLElement;\n console.log('Clicking element:', clickableElement);\n clickableElement.dispatchEvent(clickEvent);\n\n const originalBoxShadow = clickableElement.style.boxShadow;\n const originalTransition = clickableElement.style.transition;\n const originalZIndex = clickableElement.style.zIndex;\n\n clickableElement.style.transition = 'all 0.3s ease-out';\n clickableElement.style.boxShadow = '0 0 0 2px rgba(0, 102, 255, 0.5), 0 0 10px rgba(0, 102, 255, 0.3)';\n clickableElement.style.zIndex = '999';\n\n setTimeout(() => {\n clickableElement.style.boxShadow = originalBoxShadow;\n clickableElement.style.transition = originalTransition;\n clickableElement.style.zIndex = originalZIndex;\n\n clickEffectContainer.remove(); \n resolve();\n }, 1000);\n\n }, 1500);\n });\n};\n\n// Highlight elements on the page with animated cursor and click effects\nexport const highlightElement = async (\n selector: string | string[],\n isHighlighting: boolean,\n setIsHighlighting: (highlighting: boolean) => void,\n logMessage: (content: string, sender: 'GUIDEAI' | 'HUMAN') => void\n): Promise<boolean> => {\n if (isHighlighting) return false;\n \n const selectors = Array.isArray(selector) ? selector : [selector];\n if (selectors.length === 0) return false;\n \n console.log('Moving cursor to elements:', selectors);\n \n let cursorElement: HTMLElement | null = null;\n try {\n setIsHighlighting(true);\n \n for (let i = 0; i < selectors.length; i++) {\n const currentSelector = selectors[i];\n \n if (i > 0) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n }\n \n let element;\n if (currentSelector.startsWith('//')) {\n const node = document.evaluate(currentSelector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\n if (!(node instanceof Element)) {\n console.log('XPath returned a non-Element node:', currentSelector);\n console.log(node);\n logMessage('XPath returned a non-Element node: ' + currentSelector, 'GUIDEAI');\n break;\n }\n element = node as Element;\n } else {\n element = document.querySelector(currentSelector);\n }\n \n if (!element) {\n console.log('Element not found:', currentSelector);\n logMessage('Element not found: ' + currentSelector, 'GUIDEAI');\n break;\n }\n \n const rect = element.getBoundingClientRect();\n \n // Create cursor if it's the first element, or reuse existing cursor\n if (!cursorElement) {\n cursorElement = document.createElement('div');\n cursorElement.id = 'guide-ai-cursor';\n \n const blueCursorSvg = `\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill=\"#0066ff\" d=\"M7,2l12,11.2l-5.8,0.5l3.3,7.3l-2.2,1l-3.2-7.4L7,18.5V2\" />\n </svg>\n `;\n \n cursorElement.innerHTML = blueCursorSvg;\n cursorElement.style.cssText = `\n position: fixed;\n width: 64px;\n height: 64px;\n pointer-events: none;\n z-index: 9999;\n transition: all 0.8s ease-in-out;\n transform: translate(-50%, 0);\n filter: drop-shadow(0 0 4px rgba(0, 102, 255, 0.8));\n `;\n \n document.body.appendChild(cursorElement);\n \n // First element starts from center of viewport\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n cursorElement.style.left = `${viewportWidth / 2}px`;\n cursorElement.style.top = `${viewportHeight / 2}px`;\n }\n \n // Force reflow to ensure transition works\n cursorElement!.offsetHeight;\n \n await new Promise<void>(resolve => {\n setTimeout(() => {\n cursorElement!.style.left = `${rect.left + rect.width / 2}px`;\n cursorElement!.style.top = `${rect.top + rect.height / 2 - 10}px`;\n \n setTimeout(() => {\n cursorElement!.style.animation = 'cursor-jiggle 0.5s ease-in-out infinite';\n resolve();\n }, 800);\n }, 100);\n });\n \n await clickElement(element, rect);\n }\n\n setTimeout(() => {\n cursorElement?.remove();\n setIsHighlighting(false);\n }, 1000);\n \n return true;\n } catch (error) {\n console.error('Error moving cursor:', error);\n cursorElement?.remove();\n setIsHighlighting(false);\n return false;\n }\n}; ","// User metadata tracking system for GuideAI\n// Tracks user visits, logins, and other metadata for Overproof integration\n\nimport { \n UserMetadata, \n MetadataConfig, \n MetadataStorageData, \n MetadataEvent, \n MetadataEventType,\n MetadataUpdate \n} from '../types/metadata.types';\nimport { sendMetadataUpdates } from '../utils/api';\n\nconst METADATA_STORAGE_KEY = 'guideai_user_metadata';\nconst METADATA_VERSION = '1.0.0';\n\nclass UserMetadataTracker {\n private config: Required<MetadataConfig>;\n private metadata: UserMetadata;\n private syncTimer: NodeJS.Timeout | null = null;\n private pendingUpdates: MetadataUpdate[] = [];\n private isInitialized: boolean = false;\n private onError?: (error: Error, context: string) => void;\n\n constructor(organizationKey: string, config: MetadataConfig = {}, onError?: (error: Error, context: string) => void) {\n this.config = {\n trackVisits: true,\n trackLogins: true,\n syncInterval: 30000, // 30 seconds\n storage: 'localStorage',\n customFields: [],\n collectBrowserInfo: true,\n collectUserAgent: true,\n ...config\n };\n\n this.metadata = {\n organizationKey,\n visitCount: 0,\n loginCount: 0\n };\n \n this.onError = onError;\n\n this.init();\n }\n\n private init(): void {\n if (this.isInitialized) return;\n\n // Load existing metadata from storage\n this.loadMetadata();\n\n // Collect browser info if enabled\n if (this.config.collectBrowserInfo) {\n this.collectBrowserInfo();\n }\n\n // Track initial visit if enabled\n if (this.config.trackVisits) {\n this.trackVisit();\n }\n\n // Start sync timer\n this.startSyncTimer();\n\n // Listen for EventTracker events to detect user interactions\n this.setupEventTrackerIntegration();\n\n this.isInitialized = true;\n console.log('UserMetadataTracker: Initialized', this.metadata);\n }\n\n public updateUserInfo(userInfo: Partial<UserMetadata>): void {\n const timestamp = Date.now();\n \n // Update metadata\n this.metadata = {\n ...this.metadata,\n ...userInfo,\n lastVisit: timestamp\n };\n\n // Add to pending updates\n this.pendingUpdates.push({\n type: 'user_info',\n timestamp,\n data: userInfo\n });\n\n // Save to storage\n this.saveMetadata();\n\n console.log('UserMetadataTracker: User info updated', userInfo);\n }\n\n public trackLogin(additionalInfo?: Partial<UserMetadata>): void {\n if (!this.config.trackLogins) return;\n\n const timestamp = Date.now();\n \n this.metadata = {\n ...this.metadata,\n ...additionalInfo,\n loginCount: (this.metadata.loginCount || 0) + 1,\n lastLogin: timestamp,\n lastVisit: timestamp\n };\n\n this.pendingUpdates.push({\n type: 'login',\n timestamp,\n data: {\n loginCount: this.metadata.loginCount,\n lastLogin: timestamp,\n ...additionalInfo\n }\n });\n\n this.saveMetadata();\n console.log('UserMetadataTracker: Login tracked', this.metadata.loginCount);\n }\n\n public trackVisit(): void {\n if (!this.config.trackVisits) return;\n\n const timestamp = Date.now();\n const isFirstVisit = !this.metadata.firstVisit;\n\n this.metadata = {\n ...this.metadata,\n firstVisit: this.metadata.firstVisit || timestamp,\n lastVisit: timestamp,\n visitCount: (this.metadata.visitCount || 0) + 1\n };\n\n this.pendingUpdates.push({\n type: 'visit',\n timestamp,\n data: {\n firstVisit: this.metadata.firstVisit,\n lastVisit: this.metadata.lastVisit,\n visitCount: this.metadata.visitCount\n }\n });\n\n this.saveMetadata();\n \n console.log(`UserMetadataTracker: ${isFirstVisit ? 'First' : 'Return'} visit tracked`, {\n visitCount: this.metadata.visitCount,\n firstVisit: this.metadata.firstVisit,\n lastVisit: this.metadata.lastVisit\n });\n }\n\n public trackCustomEvent(eventType: string, customData: Record<string, any>): void {\n const timestamp = Date.now();\n\n // Update custom fields if they're in the config\n const customFields = { ...this.metadata.customFields };\n for (const [key, value] of Object.entries(customData)) {\n if (this.config.customFields.includes(key)) {\n customFields[key] = value;\n }\n }\n\n this.metadata = {\n ...this.metadata,\n customFields,\n lastVisit: timestamp\n };\n\n this.pendingUpdates.push({\n type: 'custom',\n timestamp,\n data: { customFields }\n });\n\n this.saveMetadata();\n console.log('UserMetadataTracker: Custom event tracked', eventType, customData);\n }\n\n public getMetadata(): UserMetadata {\n return { ...this.metadata };\n }\n\n public getPendingUpdates(): MetadataUpdate[] {\n return [...this.pendingUpdates];\n }\n\n public clearPendingUpdates(): void {\n this.pendingUpdates = [];\n }\n\n public syncNow(): MetadataUpdate[] {\n const updates = [...this.pendingUpdates];\n this.clearPendingUpdates();\n return updates;\n }\n\n private loadMetadata(): void {\n try {\n const storageData = this.getFromStorage();\n if (storageData && storageData.metadata) {\n // Merge stored metadata with current metadata\n this.metadata = {\n ...this.metadata,\n ...storageData.metadata\n };\n console.log('UserMetadataTracker: Loaded metadata from storage', this.metadata);\n }\n } catch (error) {\n console.warn('UserMetadataTracker: Failed to load metadata from storage', error);\n // Clear corrupted data\n this.clearStorage();\n }\n }\n\n private saveMetadata(): void {\n try {\n const storageData: MetadataStorageData = {\n metadata: this.metadata,\n lastUpdated: Date.now(),\n version: METADATA_VERSION\n };\n\n this.setToStorage(storageData);\n } catch (error) {\n console.warn('UserMetadataTracker: Failed to save metadata to storage', error);\n }\n }\n\n private collectBrowserInfo(): void {\n if (typeof window === 'undefined') return;\n\n const userAgent = navigator.userAgent;\n const browserInfo = this.parseBrowserInfo(userAgent);\n\n this.metadata = {\n ...this.metadata,\n userAgent: this.config.collectUserAgent ? userAgent : undefined,\n browserInfo\n };\n }\n\n private parseBrowserInfo(userAgent: string): UserMetadata['browserInfo'] {\n // Simple browser detection - could be enhanced with a proper library\n let name = 'Unknown';\n let version = 'Unknown';\n let platform = 'Unknown';\n\n // Detect browser\n if (userAgent.includes('Chrome') && !userAgent.includes('Edg')) {\n name = 'Chrome';\n const match = userAgent.match(/Chrome\\/([0-9.]+)/);\n version = match ? match[1] : 'Unknown';\n } else if (userAgent.includes('Firefox')) {\n name = 'Firefox';\n const match = userAgent.match(/Firefox\\/([0-9.]+)/);\n version = match ? match[1] : 'Unknown';\n } else if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) {\n name = 'Safari';\n const match = userAgent.match(/Version\\/([0-9.]+)/);\n version = match ? match[1] : 'Unknown';\n } else if (userAgent.includes('Edg')) {\n name = 'Edge';\n const match = userAgent.match(/Edg\\/([0-9.]+)/);\n version = match ? match[1] : 'Unknown';\n }\n\n // Detect platform\n if (userAgent.includes('Win')) platform = 'Windows';\n else if (userAgent.includes('Mac')) platform = 'macOS';\n else if (userAgent.includes('Linux')) platform = 'Linux';\n else if (userAgent.includes('Android')) platform = 'Android';\n else if (userAgent.includes('iOS')) platform = 'iOS';\n\n return { name, version, platform };\n }\n\n private startSyncTimer(): void {\n if (this.syncTimer) return;\n\n this.syncTimer = setInterval(() => {\n if (this.pendingUpdates.length > 0) {\n this.emitPendingUpdates();\n }\n }, this.config.syncInterval);\n }\n\n private setupEventTrackerIntegration(): void {\n if (typeof window === 'undefined') return;\n\n // Listen for EventTracker batches to detect user interactions\n const handleEventBatch = (event: Event) => {\n const customEvent = event as CustomEvent;\n const batchData = customEvent.detail;\n if (batchData && batchData.events) {\n // Look for login-related events (form submissions, clicks on login buttons, etc.)\n const hasLoginEvent = batchData.events.some((evt: any) => \n evt.type === 'submit' || \n (evt.type === 'click' && (\n evt.textContent?.toLowerCase().includes('login') ||\n evt.textContent?.toLowerCase().includes('sign in') ||\n evt.className?.toLowerCase().includes('login') ||\n evt.id?.toLowerCase().includes('login')\n ))\n );\n\n if (hasLoginEvent) {\n console.log('UserMetadataTracker: Detected potential login event from EventTracker');\n // Note: We don't automatically track login here as it requires explicit confirmation\n // This is just for detecting potential login scenarios\n }\n\n // Track general user activity\n const timestamp = Date.now();\n this.metadata = {\n ...this.metadata,\n lastVisit: timestamp\n };\n }\n };\n\n window.addEventListener('guideai:event_batch', handleEventBatch);\n \n // Store the listener for cleanup\n (this as any)._eventTrackerListener = handleEventBatch;\n }\n\n private stopSyncTimer(): void {\n if (this.syncTimer) {\n clearInterval(this.syncTimer);\n this.syncTimer = null;\n }\n }\n\n private async emitPendingUpdates(): Promise<void> {\n if (this.pendingUpdates.length === 0) return;\n\n const updates = [...this.pendingUpdates];\n \n // Emit the updates (integrate with existing event system)\n console.log('UserMetadataTracker: Emitting metadata updates', {\n updateCount: updates.length,\n updates,\n currentMetadata: this.metadata\n });\n\n // Send to backend API\n try {\n if (this.onError) {\n await sendMetadataUpdates(updates, this.metadata.organizationKey, this.onError);\n }\n \n // Clear pending updates after successful emission\n this.clearPendingUpdates();\n } catch (error) {\n console.warn('UserMetadataTracker: Failed to send metadata updates, will retry later', error);\n // Don't clear pending updates so they can be retried\n }\n }\n\n private getFromStorage(): MetadataStorageData | null {\n try {\n const key = `${METADATA_STORAGE_KEY}_${this.metadata.organizationKey}`;\n let data: string | null = null;\n\n switch (this.config.storage) {\n case 'localStorage':\n data = typeof window !== 'undefined' ? localStorage.getItem(key) : null;\n break;\n case 'sessionStorage':\n data = typeof window !== 'undefined' ? sessionStorage.getItem(key) : null;\n break;\n case 'memory':\n // For memory storage, we don't persist across sessions\n return null;\n }\n\n return data ? JSON.parse(data) : null;\n } catch (error) {\n console.warn('UserMetadataTracker: Error reading from storage', error);\n return null;\n }\n }\n\n private setToStorage(data: MetadataStorageData): void {\n try {\n const key = `${METADATA_STORAGE_KEY}_${this.metadata.organizationKey}`;\n const serialized = JSON.stringify(data);\n\n switch (this.config.storage) {\n case 'localStorage':\n if (typeof window !== 'undefined') {\n localStorage.setItem(key, serialized);\n }\n break;\n case 'sessionStorage':\n if (typeof window !== 'undefined') {\n sessionStorage.setItem(key, serialized);\n }\n break;\n case 'memory':\n // For memory storage, we don't persist\n break;\n }\n } catch (error) {\n console.warn('UserMetadataTracker: Error writing to storage', error);\n }\n }\n\n private clearStorage(): void {\n try {\n const key = `${METADATA_STORAGE_KEY}_${this.metadata.organizationKey}`;\n\n switch (this.config.storage) {\n case 'localStorage':\n if (typeof window !== 'undefined') {\n localStorage.removeItem(key);\n }\n break;\n case 'sessionStorage':\n if (typeof window !== 'undefined') {\n sessionStorage.removeItem(key);\n }\n break;\n case 'memory':\n // Nothing to clear for memory storage\n break;\n }\n } catch (error) {\n console.warn('UserMetadataTracker: Error clearing storage', error);\n }\n }\n\n public destroy(): void {\n // Emit any pending updates before destroying\n this.emitPendingUpdates();\n \n // Stop sync timer\n this.stopSyncTimer();\n \n // Remove event listener\n if (typeof window !== 'undefined' && (this as any)._eventTrackerListener) {\n window.removeEventListener('guideai:event_batch', (this as any)._eventTrackerListener);\n }\n \n // Clear state\n this.isInitialized = false;\n this.pendingUpdates = [];\n \n console.log('UserMetadataTracker: Destroyed');\n }\n}\n\nexport default UserMetadataTracker;\nexport type { UserMetadata, MetadataConfig, MetadataUpdate };\n","// Metric exports\nexport { default as EventTracker } from './event-listner';\nexport type { EventData } from './event-listner';\nexport { default as UserMetadataTracker } from './metadata-tracker';\nexport type { UserMetadata, MetadataConfig, MetadataUpdate } from './metadata-tracker';","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(258);\n"],"names":["root","factory","exports","module","require","define","amd","this","__WEBPACK_EXTERNAL_MODULE__156__","guideAIStyles","CONVERSATION_STORAGE_KEY","CONVERSATION_EXPIRY_MINUTES","MAX_STORED_MESSAGES","isLocalStorageAvailable","testKey","localStorage","setItem","removeItem","e","isConversationExpired","conversation","expiryTime","Date","now","timestamp","handleStorageError","error","operation","console","DOMException","name","loadConversationFromStorage","messages","length","slice","saveConversationToStorage","warn","clearConversationStorage","cleanupError","JSON","stringify","storedData","getItem","parsedData","parse","data","conversationId","Array","isArray","organizationKey","every","msg","content","sender","addMessageToStorage","message","some","existingMsg","Math","abs","log","substring","push","checkForStoredConversation","currentOrganizationKey","storedConversation","shouldRestore","formatConversationContext","maxMessages","recentMessages","meaningfulMessages","filter","trim","map","join","DEFAULT_PROMPT","IGNORE_MESSAGE_TYPES","GUIDE_AI_API_BASE","OPENAI_REALTIME_BASE","OPENAI_REALTIME_MODEL","GEMINI_API_KEY","GEMINI_API_ENDPOINT","createNewConversation","onError","fetch","method","headers","body","userId","date","toISOString","split","time","toTimeString","response","ok","text","catch","errorText","status","Error","json","conversationData","id","logMessage","statusText","sendMetadataUpdates","updates","batchTimestamp","updateCount","globalInitializationInProgress","props","position","metadataOptions","transcriptOptions","inputOptions","hooks","useMemo","window","React","useState","useEffect","useRef","useCallback","setStatus","isClient","setIsClient","componentPosition","isHighlighting","setIsHighlighting","hasInteracted","setHasInteracted","setPrompt","setIsSessionReady","isConnecting","setIsConnecting","showOnboarding","setShowOnboarding","popupPosition","setPopupPosition","conversationIdRef","componentRef","peerConnectionRef","dataChannelRef","hasCreatedConversationRef","mediaStreamRef","audioElementRef","ephemeralToken","setEphemeralToken","hasInitializedRef","initializationInProgressRef","isUnmountingRef","isConversationActive","setIsConversationActive","restoredMessages","setRestoredMessages","enabled","showTranscript","setShowTranscript","allMessages","setAllMessages","defaultMode","inputMode","setInputMode","textInput","setTextInput","setShowTextInput","hasAttemptedAutoStartRef","eventTracker","customerId","organizationId","customerType","raw","parsed","idVal","customer","String","orgVal","typeName","customerTypeName","_err","EventTracker","metadataTracker","UserMetadataTracker","config","geminiFlash","prompt","contents","parts","responseJson","candidates","handleCreateNewConversation","current","handleLogMessage","newMessage","prev","getOptimalPosition","elementHeight","spacing","rect","getBoundingClientRect","calculateOptimalPosition","sendMessage","readyState","send","cleanupWebRTC","getAudioTracks","forEach","track","stop","close","srcObject","initializeWebRTC","audioStream","RTCPeerConnection","addTrack","audioEl","document","createElement","autoplay","appendChild","ontrack","kind","stream","MediaStream","dc","createDataChannel","onopen","sessionConfig","tools","type","description","parameters","properties","selector","oneOf","items","required","tool_choice","turn_detection","create_response","interrupt_response","input_audio_transcription","model","language","session","onmessage","conversationContext","item","role","transcript","lastMessage","output","out","arguments","argsToUse","then","replace","parsedArgs","highlightElement","err","call_id","code","fragment","includes","createOffer","offer","setLocalDescription","localDescription","sdp","baseUrl","Authorization","sdpResponse","answerSdp","answer","setRemoteDescription","startConversationSession","navigator","mediaDevices","getUserMedia","audio","echoCancellation","noiseSuppression","autoGainControl","channelCount","sampleRate","endConversationSession","handleTextSubmit","responseMessage","injectStyles","initialize","initialUserData","updateUserInfo","hasInitialized","initializationInProgress","hasInteractedBefore","isUnmounting","remove","stopTracking","destroy","syncInterval","syncTimer","setInterval","pendingUpdates","syncNow","onMetadataUpdate","getMetadata","clearInterval","success","GuideAI","metadata","trackLogin","additionalInfo","userInfo","trackCustomEvent","eventType","customData","syncMetadata","toggle","show","hide","isVisible","input","toggleMode","newMode","setMode","mode","enableTextInput","getMode","sendText","shouldUseFixedPosition","Object","keys","baseStyles","zIndex","ref","style","className","onComplete","onClose","onClick","undefined","cursor","title","showToggleButton","onToggle","showTextInput","onTextInputChange","onTextSubmit","onTextKeyPress","event","key","shiftKey","preventDefault","textPlaceholder","placeholder","css","getElementById","styleElement","textContent","head","componentRect","viewportHeight","innerHeight","spaceAbove","top","spaceBelow","bottom","element","transcriptContainer","scrollTop","scrollHeight","shouldShowToggleButton","shouldShowTranscript","index","toLowerCase","toLocaleTimeString","hour","minute","value","onChange","target","onKeyPress","rows","disabled","step","setStep","options","isTracking","eventData","batchSize","batchTimeout","batchTimer","pendingEvents","currentUrl","customerMetadata","handleClick","baseEventData","tagName","getSafeValue","url","location","href","logEvent","handleFocus","isFocusable","handleChange","isFormElement","handleSubmit","formData","FormData","handlePopstate","previousUrl","getPreviousUrl","handleHashChange","oldURL","setCustomerMetadata","getCustomerMetadata","clearCustomerMetadata","addEventListener","startTracking","enrichEventData","customerSegment","sessionId","getSessionId","deviceType","getDeviceType","userAgent","screenResolution","screen","width","height","currentPage","pathname","userRole","timezone","Intl","DateTimeFormat","resolvedOptions","timeZone","locale","sessionStorage","random","toString","substr","test","trackClickEvents","trackFocusEvents","trackChangeEvents","trackSubmitEvents","trackRouteChanges","emitBatch","removeEventListener","interceptHistoryAPI","originalPushState","history","pushState","originalReplaceState","replaceState","result","apply","args","inputElement","selectElement","selectedIndex","inputType","matches","enrichedEventData","startBatchTimer","clearTimeout","setTimeout","batchPayload","events","dispatchEvent","CustomEvent","detail","getEventData","clearEventData","getEventDataByType","getEventDataByElement","toUpperCase","getEventDataByUrl","emitPendingEvents","setBatchConfig","getPendingEventsCount","getCustomerAnalytics","sessionDuration","getSessionStartTime","analytics","totalEvents","eventsByCustomer","eventsByType","eventsByPage","eventsByDevice","lastActivity","sessionStart","startTime","parseInt","identifyCustomerFromContext","userRoleMeta","querySelector","getAttribute","setCustomerFromAuth","authData","clickElement","Promise","resolve","clickEffectContainer","cssText","left","j","clickRipple","clickDot","clickEvent","MouseEvent","view","bubbles","cancelable","clickableElements","querySelectorAll","clickableElement","originalBoxShadow","boxShadow","originalTransition","transition","originalZIndex","selectors","cursorElement","i","currentSelector","startsWith","node","evaluate","XPathResult","FIRST_ORDERED_NODE_TYPE","singleNodeValue","Element","innerHTML","viewportWidth","innerWidth","offsetHeight","animation","METADATA_STORAGE_KEY","isInitialized","trackVisits","trackLogins","storage","customFields","collectBrowserInfo","collectUserAgent","visitCount","loginCount","init","loadMetadata","trackVisit","startSyncTimer","setupEventTrackerIntegration","lastVisit","saveMetadata","lastLogin","isFirstVisit","firstVisit","entries","getPendingUpdates","clearPendingUpdates","storageData","getFromStorage","clearStorage","lastUpdated","version","setToStorage","browserInfo","parseBrowserInfo","platform","match","emitPendingUpdates","handleEventBatch","batchData","evt","_eventTrackerListener","stopSyncTimer","currentMetadata","serialized","default","__webpack_module_cache__","__webpack_exports__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","call"],"sourceRoot":""}