{"version":3,"sources":["../src/index.ts","../src/popup.ts","../src/websocket-client.ts","../src/posthog-integration.ts","../src/auto-tracker.ts","../src/sse-client.ts"],"sourcesContent":["import {\n  enableAutoTracker,\n  disableAutoTracker,\n  identify as identifyUser,\n  reset as resetUser,\n  getTrackerStatus,\n  resetTracker,\n  type UserProperties,\n  type AutoTrackerOptions,\n  getWebSocketClient,\n  updateWebSocketSessionId,\n  setWebSocketAutoHandlePopup,\n  getWebSocketAutoHandlePopup,\n  isIdentified\n} from \"./auto-tracker\";\n\n// 简单的运行时守卫以避免 SSR 崩溃\nconst isBrowser =\n  typeof window !== \"undefined\" && typeof document !== \"undefined\";\n\n// 导出 auto-tracker 的所有功能\nexport * from \"./auto-tracker\";\n\n// 导出 popup 功能\nexport { showPopup, hidePopup, showPopupFromStrategy, type PopupButton, type PopupPayload, type PopupOptions } from \"./popup\";\n\n// 导出 SSE 客户端\nexport { SSEClient, type SSEConfig } from \"./sse-client\";\n\n// 导出 PostHog 集成\nexport * from \"./posthog-integration\";\nexport {\n  capturePageView,\n  capturePostHogEvent,\n  capturePostHogEventBeacon as trackBeacon,\n  capturePostHogEventBeacon,\n  flushPostHogEvents as flush,\n  flushPostHogEvents,\n  setPostHogUserProperties,\n  getPostHogInstance\n} from \"./posthog-integration\";\n\n// 导出 WebSocket 客户端\nexport { WebSocketClient, type WebSocketConfig } from \"./websocket-client\";\n\n// 组合默认导出\nexport type XDTracker = {\n  enableAutoTracker: typeof enableAutoTracker;\n  disableAutoTracker: typeof disableAutoTracker;\n  identify: typeof identifyUser;\n  reset: typeof resetUser;\n  getTrackerStatus: typeof getTrackerStatus;\n  resetTracker: typeof resetTracker;\n  getWebSocketClient: typeof getWebSocketClient;\n  updateWebSocketSessionId: typeof updateWebSocketSessionId;\n  setWebSocketAutoHandlePopup: typeof setWebSocketAutoHandlePopup;\n  getWebSocketAutoHandlePopup: typeof getWebSocketAutoHandlePopup;\n  isIdentified: typeof isIdentified;\n};\n\n// 导出用户属性接口和配置接口\nexport type { UserProperties, AutoTrackerOptions };\n\n// 创建默认导出对象\nconst xdTracker: XDTracker = {\n  enableAutoTracker,\n  disableAutoTracker,\n  identify: identifyUser,\n  reset: resetUser,\n  getTrackerStatus,\n  resetTracker,\n  getWebSocketClient,\n  updateWebSocketSessionId,\n  setWebSocketAutoHandlePopup,\n  getWebSocketAutoHandlePopup,\n  isIdentified\n};\n\nexport default xdTracker;\n","const isBrowser = typeof window !== \"undefined\" && typeof document !== \"undefined\";\n\nexport interface PopupButton {\n  text: string;\n  url: string;\n  target?: string;\n  rel?: string;\n}\n\nexport interface PopupPayload {\n  title: string;\n  body: string;\n  // 兼容旧字段（单按钮）\n  buttonText?: string;\n  buttonUrl?: string;\n  // 新增：支持多按钮\n  buttons?: PopupButton[];\n  // 新增：支持新的策略结构\n  link?: string;\n}\n\nexport type PopupPosition = 'center' | 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\n\nexport interface PopupOptions {\n  containerId?: string;\n  overlayClosable?: boolean;\n  zIndex?: number;\n  position?: PopupPosition;\n  showOverlay?: boolean;\n  persistent?: boolean;\n  persistentKey?: string;\n  expiresInSeconds?: number;\n}\n\nconst DEFAULT_CONTAINER_ID = \"xd-post-popup\";\nconst STYLE_ID = \"xd-post-popup-style\";\nconst PERSISTENCE_PREFIX = \"xd-post-popup-\";\n\nfunction setPersistentData(key: string, data: any, expiresInSeconds?: number): void {\n  if (!isBrowser) return;\n  try {\n    const item = {\n      data,\n      timestamp: Date.now(),\n      expires: expiresInSeconds ? Date.now() + expiresInSeconds * 1000 : null\n    };\n    localStorage.setItem(PERSISTENCE_PREFIX + key, JSON.stringify(item));\n  } catch (e) {\n    console.warn('Failed to persist popup data:', e);\n  }\n}\n\nfunction getPersistentData(key: string): any {\n  if (!isBrowser) return null;\n  try {\n    const item = localStorage.getItem(PERSISTENCE_PREFIX + key);\n    if (!item) return null;\n    \n    const parsed = JSON.parse(item);\n    if (parsed.expires && Date.now() > parsed.expires) {\n      localStorage.removeItem(PERSISTENCE_PREFIX + key);\n      return null;\n    }\n    return parsed.data;\n  } catch (e) {\n    console.warn('Failed to retrieve persistent popup data:', e);\n    return null;\n  }\n}\n\nfunction clearPersistentData(key: string): void {\n  if (!isBrowser) return;\n  try {\n    localStorage.removeItem(PERSISTENCE_PREFIX + key);\n  } catch (e) {\n    console.warn('Failed to clear persistent popup data:', e);\n  }\n}\n\nfunction ensureStylesInjected(zIndex: number): void {\n  if (!isBrowser) return;\n  const existing = document.getElementById(STYLE_ID);\n  if (existing) return;\n\n  const style = document.createElement(\"style\");\n  style.id = STYLE_ID;\n  style.textContent = `\n  @keyframes xdp-fade-in {\n    from { opacity: 0; }\n    to { opacity: 1; }\n  }\n  \n  @keyframes xdp-slide-up {\n    from { \n      opacity: 0;\n      transform: translateY(20px);\n    }\n    to { \n      opacity: 1;\n      transform: translateY(0);\n    }\n  }\n  \n  .xdp-overlay {\n    position: fixed;\n    z-index: ${zIndex};\n    inset: 0;\n    background: rgba(0, 0, 0, 0.6);\n    backdrop-filter: blur(4px);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    padding: 20px;\n    animation: xdp-fade-in 0.3s ease-out;\n    pointer-events: none; /* 不影响页面点击 */\n  }\n  \n  .xdp-overlay.xdp-has-overlay {\n    pointer-events: auto; /* 当显示遮罩时才捕获事件 */\n  }\n  \n  .xdp-dialog {\n    background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);\n    border-radius: 16px;\n    box-shadow: \n      0 20px 60px rgba(0, 0, 0, 0.3),\n      0 0 0 1px rgba(255, 255, 255, 0.1);\n    max-width: 480px;\n    width: 100%;\n    padding: 32px;\n    position: relative;\n    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n    color: #1a1a1a;\n    animation: xdp-slide-up 0.4s ease-out;\n    border: 1px solid rgba(255, 255, 255, 0.2);\n    pointer-events: auto; /* 弹窗可以接收点击事件 */\n  }\n  \n  /* Position styles */\n  .xdp-position-center {\n    align-items: center;\n    justify-content: center;\n  }\n  \n  .xdp-position-bottom-right {\n    align-items: flex-end;\n    justify-content: flex-end;\n    padding: 20px;\n  }\n  \n  .xdp-position-bottom-left {\n    align-items: flex-end;\n    justify-content: flex-start;\n    padding: 20px;\n  }\n  \n  .xdp-position-top-right {\n    align-items: flex-start;\n    justify-content: flex-end;\n    padding: 20px;\n  }\n  \n  .xdp-position-top-left {\n    align-items: flex-start;\n    justify-content: flex-start;\n    padding: 20px;\n  }\n  \n  /* Adjust dialog for corner positions */\n  .xdp-position-bottom-right .xdp-dialog,\n  .xdp-position-bottom-left .xdp-dialog,\n  .xdp-position-top-right .xdp-dialog,\n  .xdp-position-top-left .xdp-dialog {\n    max-width: 380px;\n    margin: 0;\n  }\n  \n  /* Slide animations for different positions */\n  @keyframes xdp-slide-up-right {\n    from { \n      opacity: 0;\n      transform: translate(20px, 20px);\n    }\n    to { \n      opacity: 1;\n      transform: translate(0, 0);\n    }\n  }\n  \n  @keyframes xdp-slide-up-left {\n    from { \n      opacity: 0;\n      transform: translate(-20px, 20px);\n    }\n    to { \n      opacity: 1;\n      transform: translate(0, 0);\n    }\n  }\n  \n  @keyframes xdp-slide-down-right {\n    from { \n      opacity: 0;\n      transform: translate(20px, -20px);\n    }\n    to { \n      opacity: 1;\n      transform: translate(0, 0);\n    }\n  }\n  \n  @keyframes xdp-slide-down-left {\n    from { \n      opacity: 0;\n      transform: translate(-20px, -20px);\n    }\n    to { \n      opacity: 1;\n      transform: translate(0, 0);\n    }\n  }\n  \n  .xdp-position-bottom-right .xdp-dialog {\n    animation: xdp-slide-up-right 0.4s ease-out;\n  }\n  \n  .xdp-position-bottom-left .xdp-dialog {\n    animation: xdp-slide-up-left 0.4s ease-out;\n  }\n  \n  .xdp-position-top-right .xdp-dialog {\n    animation: xdp-slide-down-right 0.4s ease-out;\n  }\n  \n  .xdp-position-top-left .xdp-dialog {\n    animation: xdp-slide-down-left 0.4s ease-out;\n  }\n  \n  .xdp-title {\n    margin: 0 0 16px 0;\n    font-size: 24px;\n    font-weight: 700;\n    line-height: 1.3;\n    color: #1a1a1a;\n    letter-spacing: -0.02em;\n  }\n  \n  .xdp-body {\n    margin: 0 0 24px 0;\n    font-size: 16px;\n    line-height: 1.6;\n    color: #4a4a4a;\n    white-space: pre-wrap;\n  }\n  \n  .xdp-actions {\n    display: flex;\n    gap: 12px;\n    justify-content: flex-start;\n    flex-wrap: wrap;\n  }\n  \n  .xdp-cta {\n    appearance: none;\n    border: none;\n    border-radius: 12px;\n    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n    color: #ffffff;\n    padding: 14px 28px;\n    font-size: 16px;\n    font-weight: 600;\n    cursor: pointer;\n    text-decoration: none;\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    transition: all 0.3s ease;\n    box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);\n    position: relative;\n    overflow: hidden;\n  }\n  \n  .xdp-cta:hover {\n    transform: translateY(-2px);\n    box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);\n  }\n  \n  .xdp-cta:active {\n    transform: translateY(0);\n  }\n  \n  .xdp-close {\n    position: absolute;\n    right: 16px;\n    top: 16px;\n    width: 40px;\n    height: 40px;\n    border: none;\n    background: rgba(0, 0, 0, 0.05);\n    border-radius: 50%;\n    font-size: 20px;\n    line-height: 1;\n    cursor: pointer;\n    color: #666;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    transition: all 0.2s ease;\n  }\n  \n  .xdp-close:hover {\n    background: rgba(0, 0, 0, 0.1);\n    color: #333;\n    transform: rotate(90deg);\n  }\n  \n  .xdp-root {\n    // position: fixed;\n    // inset: 0;\n    // z-index: ${zIndex};\n  }\n  \n  @media (max-width: 640px) {\n    .xdp-dialog {\n      margin: 16px;\n      padding: 24px;\n      border-radius: 12px;\n    }\n    \n    .xdp-title {\n      font-size: 20px;\n    }\n    \n    .xdp-body {\n      font-size: 15px;\n    }\n    \n    .xdp-cta {\n      padding: 12px 24px;\n      font-size: 15px;\n      width: 100%;\n    }\n    \n    .xdp-actions {\n      flex-direction: column;\n    }\n  }\n  `;\n  document.head.appendChild(style);\n}\n\nfunction createRoot(containerId: string, zIndex: number): HTMLDivElement {\n  const root = document.createElement(\"div\");\n  root.id = containerId;\n  root.className = \"xdp-root\";\n  root.style.zIndex = String(zIndex);\n  return root;\n}\n\nfunction removeRoot(containerId: string): void {\n  if (!isBrowser) return;\n  const exist = document.getElementById(containerId);\n  if (exist && exist.parentNode) exist.parentNode.removeChild(exist);\n}\n\nexport function isPopupVisible(containerId: string = DEFAULT_CONTAINER_ID): boolean {\n  if (!isBrowser) return false;\n  const el = document.getElementById(containerId);\n  return !!el;\n}\n\nexport function hidePopup(containerId: string = DEFAULT_CONTAINER_ID, persistentKey?: string): void {\n  if (persistentKey) {\n    setPersistentData(persistentKey, { hidden: true, timestamp: Date.now() });\n  }\n  removeRoot(containerId);\n}\n\n// 新增：检查持久化弹窗是否应该显示\nexport function shouldShowPersistentPopup(persistentKey: string): boolean {\n  return !getPersistentData(persistentKey);\n}\n\n// 新增：清除持久化数据\nexport function clearPersistentPopup(persistentKey: string): void {\n  clearPersistentData(persistentKey);\n}\n\n// 新增：从策略结构创建弹窗的便捷方法\nexport interface PopupStrategy {\n  method: 'POPUP';\n  timing: 'IMMEDIATE' | 'DELAYED';\n  content: {\n    title: string;\n    body: string;\n    link: string;\n    buttonText: string;\n  };\n}\n\nexport function showPopupFromStrategy(strategy: PopupStrategy, options: PopupOptions = {}): HTMLDivElement | null {\n  const { content } = strategy;\n  return showPopup({\n    title: content.title,\n    body: content.body,\n    buttonText: content.buttonText,\n    link: content.link\n  }, options);\n}\n\nexport function showPopup(payload: PopupPayload, options: PopupOptions = {}): HTMLDivElement | null {\n  if (!isBrowser) return null;\n\n  const { title, body, buttonText, buttonUrl, link } = payload;\n  const containerId = options.containerId || DEFAULT_CONTAINER_ID;\n  const zIndex = options.zIndex ?? 2147483000;\n  const overlayClosable = options.overlayClosable ?? false;\n  const position = options.position ?? 'bottom-right';\n  const showOverlay = options.showOverlay ?? false;\n  const persistent = options.persistent ?? false;\n  const persistentKey = options.persistentKey;\n  const expiresInSeconds = options.expiresInSeconds;\n\n  // Check if this popup should be shown (for persistent popups)\n  if (persistent && persistentKey) {\n    const existingData = getPersistentData(persistentKey);\n    if (existingData) {\n      return null; // Don't show if already shown and persistent\n    }\n  }\n\n  // 归一化按钮：优先使用 buttons，其次兼容新结构的 link 和 buttonText，最后兼容旧字段\n  const normalizedButtons: PopupButton[] = (Array.isArray(payload.buttons) && payload.buttons.length > 0)\n    ? payload.buttons\n    : ((link && buttonText)\n        ? [{ text: String(buttonText), url: String(link) }]\n        : ((buttonText || buttonUrl)\n            ? [{ text: String(buttonText || \"\"), url: String(buttonUrl || link || \"#\") }]\n            : []));\n\n  ensureStylesInjected(zIndex);\n\n  // If exists, replace content\n  removeRoot(containerId);\n  const root = createRoot(containerId, zIndex);\n\n  const overlay = document.createElement(\"div\");\n  overlay.className = `xdp-overlay xdp-position-${position}`;\n  overlay.style.background = showOverlay ? 'rgba(0, 0, 0, 0.6)' : 'transparent';\n  overlay.style.backdropFilter = showOverlay ? 'blur(4px)' : 'none';\n  if (overlayClosable && showOverlay) overlay.addEventListener(\"click\", () => hidePopup(containerId, persistentKey));\n\n  const dialog = document.createElement(\"div\");\n  dialog.className = \"xdp-dialog\";\n  dialog.addEventListener(\"click\", (e) => e.stopPropagation());\n\n  const closeBtn = document.createElement(\"button\");\n  closeBtn.className = \"xdp-close\";\n  closeBtn.setAttribute(\"aria-label\", \"Close\");\n  closeBtn.textContent = \"×\";\n  closeBtn.addEventListener(\"click\", () => hidePopup(containerId, persistentKey));\n\n  const titleEl = document.createElement(\"h3\");\n  titleEl.className = \"xdp-title\";\n  titleEl.textContent = String(title || \"\");\n\n  const bodyEl = document.createElement(\"div\");\n  bodyEl.className = \"xdp-body\";\n  bodyEl.textContent = String(body || \"\");\n\n  const actions = document.createElement(\"div\");\n  actions.className = \"xdp-actions\";\n\n  // 渲染按钮（可能为多个）\n  for (const btn of normalizedButtons) {\n    const anchor = document.createElement(\"a\");\n    anchor.className = \"xdp-cta\";\n    anchor.textContent = String(btn.text || \"\");\n    anchor.href = String(btn.url || \"#\");\n    anchor.target = btn.target ?? \"_blank\";\n    anchor.rel = btn.rel ?? \"noopener noreferrer\";\n    actions.appendChild(anchor);\n  }\n\n  dialog.appendChild(closeBtn);\n  dialog.appendChild(titleEl);\n  dialog.appendChild(bodyEl);\n  dialog.appendChild(actions);\n  overlay.appendChild(dialog);\n  root.appendChild(overlay);\n\n  document.body.appendChild(root);\n  return root;\n} ","import { showPopup, PopupPayload } from \"./popup\";\r\n\r\nexport interface WebSocketConfig {\r\n  url: string;\r\n  sessionId?: string;\r\n  headers?: Record<string, string>;\r\n  onOpen?: () => void;\r\n  onClose?: () => void;\r\n  onError?: (error: Event) => void;\r\n  onMessage?: (data: any) => void;\r\n  retryInterval?: number;\r\n  maxRetryAttempts?: number;\r\n  autoHandlePopup?: boolean; // 是否自动处理弹窗消息，默认 true\r\n}\r\n\r\nexport interface PopupMessage {\r\n  type: \"popup\";\r\n  payload: PopupPayload;\r\n  strategy: any;\r\n  options?: {\r\n    containerId?: string;\r\n    overlayClosable?: boolean;\r\n    zIndex?: number;\r\n  };\r\n}\r\n\r\nexport class WebSocketClient {\r\n  private websocket: WebSocket | null = null;\r\n  private config: WebSocketConfig;\r\n  private retryAttempts = 0;\r\n  private retryTimer: NodeJS.Timeout | null = null;\r\n  private isConnecting = false;\r\n  private heartbeatTimer: NodeJS.Timeout | null = null;\r\n  private heartbeatInterval = 30000; // 30秒心跳间隔\r\n\r\n  constructor(config: WebSocketConfig) {\r\n    this.config = {\r\n      retryInterval: 3000,\r\n      maxRetryAttempts: 5,\r\n      autoHandlePopup: true,\r\n      ...config,\r\n    };\r\n  }\r\n\r\n  connect(): void {\r\n    if (this.isConnecting || this.websocket?.readyState === WebSocket.OPEN) {\r\n      return;\r\n    }\r\n\r\n    this.isConnecting = true;\r\n\r\n    try {\r\n      // 构建 WebSocket URL，添加 sessionId 参数\r\n      let url = this.config.url;\r\n      if (this.config.sessionId) {\r\n        const separator = url.includes(\"?\") ? \"&\" : \"?\";\r\n        url = `${url}/${encodeURIComponent(this.config.sessionId)}`;\r\n      }\r\n\r\n      // 如果是 http/https 协议，转换为 ws/wss\r\n      if (url.startsWith(\"http://\")) {\r\n        url = url.replace(\"http://\", \"ws://\");\r\n      } else if (url.startsWith(\"https://\")) {\r\n        url = url.replace(\"https://\", \"wss://\");\r\n      }\r\n\r\n      // 创建 WebSocket 实例\r\n      this.websocket = new WebSocket(url);\r\n\r\n      this.setupEventHandlers();\r\n    } catch (error) {\r\n      console.error(\"WebSocket connection failed:\", error);\r\n      this.isConnecting = false;\r\n      this.handleRetry();\r\n    }\r\n  }\r\n\r\n  private setupEventHandlers(): void {\r\n    if (!this.websocket) return;\r\n\r\n    this.websocket.onopen = () => {\r\n      console.log(\"WebSocket connected\");\r\n      this.isConnecting = false;\r\n      this.retryAttempts = 0;\r\n\r\n      // 启动心跳机制\r\n      this.startHeartbeat();\r\n\r\n      this.config.onOpen?.();\r\n    };\r\n\r\n    this.websocket.onerror = (error) => {\r\n      console.error(\"WebSocket error:\", error);\r\n      this.isConnecting = false;\r\n      this.config.onError?.(error);\r\n\r\n      // 处理重连\r\n      this.handleRetry();\r\n    };\r\n\r\n    this.websocket.onclose = (event) => {\r\n      console.log(\"WebSocket closed:\", event.code, event.reason);\r\n      this.isConnecting = false;\r\n\r\n      // 清理心跳\r\n      this.stopHeartbeat();\r\n\r\n      this.config.onClose?.();\r\n\r\n      // 如果不是主动关闭，尝试重连\r\n      if (!event.wasClean) {\r\n        this.handleRetry();\r\n      }\r\n    };\r\n\r\n    this.websocket.onmessage = (event) => {\r\n      try {\r\n        const data = JSON.parse(event.data);\r\n        this.handleMessage(data);\r\n        // 调用外部回调\r\n        this.config.onMessage?.(data);\r\n      } catch (error) {\r\n        console.error(\"[WebSocket] Failed to parse message:\", error);\r\n      }\r\n    };\r\n  }\r\n\r\n  private startHeartbeat(): void {\r\n    this.stopHeartbeat();\r\n\r\n    this.heartbeatTimer = setInterval(() => {\r\n      if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {\r\n        // 发送心跳消息\r\n        this.websocket.send(JSON.stringify({ type: \"ping\" }));\r\n      }\r\n    }, this.heartbeatInterval);\r\n  }\r\n\r\n  private stopHeartbeat(): void {\r\n    if (this.heartbeatTimer) {\r\n      clearInterval(this.heartbeatTimer);\r\n      this.heartbeatTimer = null;\r\n    }\r\n  }\r\n\r\n  private handleMessage(data: any): void {\r\n    try {\r\n      // 处理弹窗消息\r\n      if (data.type === \"success\") {\r\n        const message = JSON.parse(data.message);\r\n        this.handlePopupMessage(message);\r\n        return;\r\n      } else {\r\n        console.log(\"[WebSocket] 收到消息:\", data);\r\n      }\r\n    } catch (error) {\r\n      console.log(\"[WebSocket] error:\", error);\r\n    }\r\n  }\r\n\r\n  private handlePopupMessage(data: any): void {\r\n    if (this.config.autoHandlePopup) {\r\n      const popupMessage = data as PopupMessage;\r\n      showPopup(popupMessage.strategy.content, popupMessage.options);\r\n      console.log(\"[WebSocket] 自动显示弹窗:\", popupMessage.payload.title);\r\n    }\r\n  }\r\n\r\n  private handleRetry(): void {\r\n    if (this.retryAttempts >= (this.config.maxRetryAttempts || 5)) {\r\n      console.error(\"Max retry attempts reached\");\r\n      this.config.onError?.(new Event(\"Max retry attempts reached\"));\r\n      return;\r\n    }\r\n\r\n    this.retryAttempts++;\r\n    const delay = this.calculateRetryDelay();\r\n    console.log(\r\n      `Attempting to retry WebSocket connection in ${delay}ms... (${this.retryAttempts}/${this.config.maxRetryAttempts})`\r\n    );\r\n\r\n    this.retryTimer = setTimeout(() => {\r\n      this.connect();\r\n    }, delay);\r\n  }\r\n\r\n  private calculateRetryDelay(): number {\r\n    // 指数退避策略：基础延迟 * 2^(重试次数-1)，最大延迟为30秒\r\n    const baseDelay = this.config.retryInterval || 3000;\r\n    const maxDelay = 30000;\r\n    const delay = Math.min(\r\n      baseDelay * Math.pow(2, this.retryAttempts - 1),\r\n      maxDelay\r\n    );\r\n\r\n    // 添加随机抖动，避免多个客户端同时重连\r\n    const jitter = Math.random() * 1000;\r\n    return delay + jitter;\r\n  }\r\n\r\n  // 手动触发重连\r\n  reconnect(): void {\r\n    if (this.retryTimer) {\r\n      clearTimeout(this.retryTimer);\r\n      this.retryTimer = null;\r\n    }\r\n    this.retryAttempts = 0;\r\n    this.connect();\r\n  }\r\n\r\n  // 重置重试计数\r\n  resetRetryAttempts(): void {\r\n    this.retryAttempts = 0;\r\n    if (this.retryTimer) {\r\n      clearTimeout(this.retryTimer);\r\n      this.retryTimer = null;\r\n    }\r\n  }\r\n\r\n  disconnect(): void {\r\n    if (this.retryTimer) {\r\n      clearTimeout(this.retryTimer);\r\n      this.retryTimer = null;\r\n    }\r\n\r\n    // 停止心跳\r\n    this.stopHeartbeat();\r\n\r\n    if (this.websocket) {\r\n      // 先关闭 WebSocket\r\n      this.websocket.close(1000, \"Client disconnect\");\r\n      this.websocket = null;\r\n    }\r\n\r\n    this.isConnecting = false;\r\n    this.retryAttempts = 0;\r\n  }\r\n\r\n  isConnected(): boolean {\r\n    return this.websocket?.readyState === WebSocket.OPEN;\r\n  }\r\n\r\n  getReadyState(): number {\r\n    return this.websocket?.readyState || WebSocket.CLOSED;\r\n  }\r\n\r\n  // 获取连接状态描述\r\n  getReadyStateText(): string {\r\n    const state = this.getReadyState();\r\n    switch (state) {\r\n      case WebSocket.CONNECTING:\r\n        return \"CONNECTING\";\r\n      case WebSocket.OPEN:\r\n        return \"OPEN\";\r\n      case WebSocket.CLOSING:\r\n        return \"CLOSING\";\r\n      case WebSocket.CLOSED:\r\n        return \"CLOSED\";\r\n      default:\r\n        return \"UNKNOWN\";\r\n    }\r\n  }\r\n\r\n  // 发送消息\r\n  send(data: any): boolean {\r\n    if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {\r\n      try {\r\n        this.websocket.send(data);\r\n        return true;\r\n      } catch (error) {\r\n        console.error(\"Failed to send WebSocket message:\", error);\r\n        return false;\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  // 更新 sessionId 并重新连接\r\n  updateSessionId(sessionId: string): void {\r\n    this.config.sessionId = sessionId;\r\n    if (this.isConnected()) {\r\n      // 如果已连接，需要重新连接以应用新的 sessionId\r\n      this.disconnect();\r\n      this.connect();\r\n    }\r\n  }\r\n\r\n  // 获取当前 sessionId\r\n  getSessionId(): string | undefined {\r\n    return this.config.sessionId;\r\n  }\r\n\r\n  // 获取当前 URL\r\n  getUrl(): string {\r\n    return this.config.url;\r\n  }\r\n\r\n  // 设置是否自动处理弹窗\r\n  setAutoHandlePopup(enabled: boolean): void {\r\n    this.config.autoHandlePopup = enabled;\r\n  }\r\n\r\n  // 获取当前自动处理弹窗设置\r\n  getAutoHandlePopup(): boolean {\r\n    return this.config.autoHandlePopup ?? true;\r\n  }\r\n}\r\n","/**\r\n * PostHog Integration Module\r\n * 将事件自动上报到 PostHog\r\n */\r\n\r\nimport posthog, { PostHog } from \"posthog-js\";\r\n\r\nexport interface PostHogConfig {\r\n  apiKey: string;\r\n  host: string; // 上报地址，例如：/quote/api/v1/events/behavior\r\n  enabled?: boolean;\r\n  autocapture?: boolean;\r\n  capture_pageview?: boolean;\r\n  capture_pageleave?: boolean;\r\n  persistence?: \"localStorage\" | \"cookie\" | \"memory\";\r\n  session_recording?: {\r\n    enabled?: boolean;\r\n  };\r\n  batch_mode?: boolean; // 是否使用批量模式（统一为对象数组），默认 true\r\n  batch_size?: number; // 批量大小，默认 10\r\n  batch_interval?: number; // 批量发送间隔（毫秒），默认 1000\r\n}\r\n\r\nlet isPostHogInitialized = false;\r\nlet postHogConfig: PostHogConfig | null = null;\r\nlet originalFetch: typeof fetch;\r\n\r\n/**\r\n * 拦截 PostHog 请求，确保数据格式统一为对象数组\r\n */\r\nfunction interceptPostHogRequests(): void {\r\n  if (typeof window === \"undefined\" || !window.fetch) return;\r\n\r\n  // 保存原始 fetch\r\n  if (!originalFetch) {\r\n    originalFetch = window.fetch;\r\n  }\r\n\r\n  // 重写 fetch\r\n  window.fetch = async function (\r\n    input: RequestInfo | URL,\r\n    init?: RequestInit\r\n  ): Promise<Response> {\r\n    // 检查是否是 PostHog 请求\r\n    const url =\r\n      typeof input === \"string\"\r\n        ? input\r\n        : input instanceof URL\r\n        ? input.href\r\n        : input.url;\r\n    const isPostHogRequest =\r\n      url.includes(postHogConfig?.host || \"\") ||\r\n      url.includes(\"posthog\") ||\r\n      url.includes(\"/batch\") ||\r\n      url.includes(\"/capture\") ||\r\n      url.includes(\"/decide\");\r\n\r\n    if (isPostHogRequest && init?.body) {\r\n      try {\r\n        const body =\r\n          typeof init.body === \"string\" ? JSON.parse(init.body) : init.body;\r\n\r\n        // 确保 batch 字段是数组\r\n        if (body.batch && !Array.isArray(body.batch)) {\r\n          console.log(\"[PostHog] Converting single event to batch array\");\r\n          body.batch = [body.batch];\r\n          init.body = JSON.stringify(body);\r\n        }\r\n\r\n        // 如果是单个事件，包装成批量格��\r\n        if (body.event && !body.batch) {\r\n          console.log(\"[PostHog] Converting single event to batch format\");\r\n          const batchBody = {\r\n            api_key: body.api_key || postHogConfig?.apiKey,\r\n            batch: [body],\r\n          };\r\n          init.body = JSON.stringify(batchBody);\r\n        }\r\n\r\n        console.log(\"[PostHog] Request body (unified to array):\", init.body);\r\n      } catch (error) {\r\n        console.error(\"[PostHog] Failed to intercept request:\", error);\r\n      }\r\n    }\r\n\r\n    return originalFetch.call(window, input, init);\r\n  };\r\n\r\n  console.log(\r\n    \"[PostHog] Request interceptor installed - all events will be sent as arrays\"\r\n  );\r\n}\r\n\r\n/**\r\n * 检查 PostHog 是否已初始化且启用\r\n */\r\nexport function isPostHogEnabled(): boolean {\r\n  return isPostHogInitialized && (postHogConfig?.enabled ?? true);\r\n}\r\n\r\n/**\r\n * 手动触发 PageView 事件\r\n */\r\nexport function capturePageView(properties?: Record<string, any>): void {\r\n  if (!isPostHogEnabled()) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    const pageProps = {\r\n      $current_url: window.location.href,\r\n      $pathname: window.location.pathname,\r\n      $title: document.title,\r\n      ...properties,\r\n    };\r\n    posthog.capture(\"$pageview\", pageProps);\r\n    console.log(\"[PostHog] PageView captured:\", pageProps);\r\n  } catch (error) {\r\n    console.error(\"[PostHog] Failed to capture pageview:\", error);\r\n  }\r\n}\r\n\r\n/**\r\n * 初始化 PostHog\r\n * @returns Promise<string> 返回 PostHog 的 distinct_id\r\n */\r\nexport function initializePostHog(config: PostHogConfig): Promise<string> {\r\n  return new Promise((resolve, reject) => {\r\n    if (isPostHogInitialized) {\r\n      console.warn(\"[PostHog] Already initialized\");\r\n      resolve(posthog.get_distinct_id?.() || \"\");\r\n      return;\r\n    }\r\n\r\n    if (!config.apiKey) {\r\n      console.error(\"[PostHog] API key is required\");\r\n      reject(new Error(\"[PostHog] API key is required\"));\r\n      return;\r\n    }\r\n\r\n    postHogConfig = config;\r\n\r\n    try {\r\n      const initOptions: any = {\r\n        api_host: config.host,\r\n        autocapture: config.autocapture ?? true, // 默认启用 PostHog 原生自动采集\r\n        capture_pageview: \"history_change\", // 默认启用页面浏览自动追踪\r\n        capture_pageleave: config.capture_pageleave ?? true, // 默认启用页面离开自动追踪\r\n        persistence: config.persistence || \"localStorage\",\r\n        disable_compression: true,\r\n\r\n        // 批量模式配置（统一为对象数组格式）\r\n        batch_events: config.batch_mode ?? false, // 默认启用批量模式\r\n        batch_size: config.batch_size ?? 10, // 批量大小\r\n        batch_interval_ms: config.batch_interval ?? 1000, // 批量发送间隔（毫秒）\r\n\r\n        loaded: (posthog: any) => {\r\n          isPostHogInitialized = true;\r\n          localStorage.setItem(\"isPostHogInitialized\", \"1\");\r\n\r\n          // 拦截请求，确保所有数据都是对象数组格式\r\n          if (initOptions.batch_events !== false) {\r\n            interceptPostHogRequests();\r\n          }\r\n\r\n          // 返回 distinct_id\r\n          const distinctId = posthog.get_distinct_id?.() || \"\";\r\n          resolve(distinctId);\r\n        },\r\n      };\r\n\r\n      // 只有在明确启用时才添加 session_recording 配置\r\n      if (config.session_recording?.enabled) {\r\n        initOptions.session_recording = config.session_recording;\r\n      }\r\n\r\n      posthog.init(config.apiKey, initOptions);\r\n      posthog.register({\r\n        cusEventType: \"2\",\r\n      });\r\n    } catch (error) {\r\n      console.error(\"[PostHog] Initialization failed:\", error);\r\n      reject(error);\r\n    }\r\n  });\r\n}\r\n\r\n/**\r\n * 发送事件到 PostHog\r\n */\r\nexport function capturePostHogEvent(\r\n  eventName: string,\r\n  properties?: Record<string, any>\r\n): void {\r\n  if (!isPostHogEnabled()) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    posthog.capture(eventName, properties);\r\n  } catch (error) {\r\n    console.error(\"[PostHog] Failed to capture event:\", error);\r\n  }\r\n}\r\n\r\nexport function capturePostHogEventBeacon(\r\n  eventName: string,\r\n  properties?: Record<string, any>\r\n): void {\r\n  if (!isPostHogEnabled() || !postHogConfig) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    const eventData = {\r\n      api_key: postHogConfig.apiKey,\r\n      batch: [\r\n        {\r\n          event: eventName,\r\n          properties: {\r\n            ...properties,\r\n            distinct_id: posthog.get_distinct_id?.() || \"anonymous\",\r\n            $lib: \"web\",\r\n            $lib_version: \"1.0.0\",\r\n          },\r\n          timestamp: new Date().toISOString(),\r\n        },\r\n      ],\r\n    };\r\n\r\n    const blob = new Blob([JSON.stringify(eventData)], {\r\n      type: \"application/json\",\r\n    });\r\n\r\n    // 使用 sendBeacon API，保证在页面卸载时也能发送\r\n    const sent = navigator.sendBeacon(postHogConfig.host, blob);\r\n\r\n    if (sent) {\r\n      console.log(\"[PostHog] Event sent via sendBeacon:\", eventName);\r\n    } else {\r\n      console.warn(\r\n        \"[PostHog] sendBeacon failed, event may not be sent:\",\r\n        eventName\r\n      );\r\n    }\r\n  } catch (error) {\r\n    console.error(\"[PostHog] Failed to send event via sendBeacon:\", error);\r\n  }\r\n}\r\n\r\n/**\r\n * 立即刷新批量队列，强制发送所有待发送的事件\r\n * 适用于页面跳转前确保事件已发送\r\n */\r\nexport function flushPostHogEvents(): void {\r\n  if (!isPostHogEnabled()) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    // PostHog 没有公开的 flush 方法，但我们可以尝试访问内部方法\r\n    const posthogInstance = posthog as any;\r\n    if (typeof posthogInstance._flush === \"function\") {\r\n      posthogInstance._flush();\r\n      console.log(\"[PostHog] Events flushed\");\r\n    } else if (typeof posthogInstance.flush === \"function\") {\r\n      posthogInstance.flush();\r\n      console.log(\"[PostHog] Events flushed\");\r\n    } else {\r\n      console.warn(\"[PostHog] Flush method not available\");\r\n    }\r\n  } catch (error) {\r\n    console.error(\"[PostHog] Failed to flush events:\", error);\r\n  }\r\n}\r\n\r\n/**\r\n * 识别用户\r\n */\r\nexport function identifyPostHogUser(\r\n  userId: string,\r\n  properties?: Record<string, any>\r\n): void {\r\n  if (!isPostHogEnabled()) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    posthog.identify(userId, properties);\r\n  } catch (error) {\r\n    console.error(\"[PostHog] Failed to identify user:\", error);\r\n  }\r\n}\r\n\r\n/**\r\n * 重置用户\r\n */\r\nexport function resetPostHogUser(): void {\r\n  if (!isPostHogEnabled()) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    posthog.reset();\r\n  } catch (error) {\r\n    console.error(\"[PostHog] Failed to reset user:\", error);\r\n  }\r\n}\r\n\r\n/**\r\n * 设置用户属性\r\n */\r\nexport function setPostHogUserProperties(\r\n  properties: Record<string, any>\r\n): void {\r\n  if (!isPostHogEnabled()) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    posthog.people.set(properties);\r\n  } catch (error) {\r\n    console.error(\"[PostHog] Failed to set user properties:\", error);\r\n  }\r\n}\r\n\r\n/**\r\n * 获取 PostHog 实例（用于高级操作）\r\n */\r\nexport function getPostHogInstance() {\r\n  return posthog;\r\n}\r\n\r\n/**\r\n * 关闭 PostHog\r\n */\r\nexport function shutdownPostHog(): void {\r\n  if (!isPostHogInitialized) {\r\n    return;\r\n  }\r\n\r\n  try {\r\n    // PostHog 没有官方的 shutdown 方法，但我们可以标记为未初始化\r\n    isPostHogInitialized = false;\r\n    postHogConfig = null;\r\n    console.log(\"[PostHog] Shutdown complete\");\r\n  } catch (error) {\r\n    console.error(\"[PostHog] Failed to shutdown:\", error);\r\n  }\r\n}\r\n","/*\r\n * Auto Tracker: PostHog 集成 + WebSocket 支持\r\n * 只使用 PostHog 原生自动采集，不进行自定义事件上报\r\n */\r\n\r\nimport { WebSocketClient } from \"./websocket-client\";\r\nimport {\r\n  initializePostHog,\r\n  identifyPostHogUser,\r\n  resetPostHogUser,\r\n  capturePageView,\r\n  getPostHogInstance,\r\n  capturePostHogEvent,\r\n} from \"./posthog-integration\";\r\n\r\n// 导出 capturePageView 供外部使用\r\nexport { capturePageView };\r\n\r\nexport type XDEventType =\r\n  | \"PageView\" // 页面访问\r\n  | \"PageLeave\" // 页面离开\r\n  | \"ScrollDepth\" // 页面滚动深度\r\n  | \"Click\" // 点击行为\r\n  | \"ViewProduct\" // 查看商品\r\n  | \"AddToCart\" // 加入购物车\r\n  | \"RemoveFromCart\" // 从购物车移除\r\n  | \"StartCheckout\" // 开始结账\r\n  | \"CompletePurchase\" // 完成购买\r\n  | \"UserRegister\" // 用户注册\r\n  | \"UserLogin\" // 用户登录\r\n  | \"SubmitForm\" // 提交表单\r\n  | \"Search\" // 执行搜索\r\n  | \"PageDwellTime\"; // 页面停留时间\r\n\r\n// =============================================================================\r\n// 类型定义\r\n// =============================================================================\r\n\r\n// 用户属性接口\r\nexport interface UserProperties {\r\n  id?: string;\r\n  userId?: string;\r\n  email?: string;\r\n  phone?: string;\r\n  userName?: string;\r\n  [key: string]: any; // 允许其他自定义属性\r\n}\r\n\r\nexport interface AutoTrackerOptions {\r\n  // PostHog 集成配置（使用 PostHog 原生自动采集）\r\n  posthog: {\r\n    enabled?: boolean; // 是否启用 PostHog，默认 true\r\n    apiKey: string; // PostHog API Key（必填）\r\n    host: string; // PostHog 上报地址（必填），例如：/quote/api/v1/events/behavior\r\n    autocapture?: boolean; // 是否启用 PostHog 原生自动采集，默认 true\r\n    capture_pageview?: boolean; // 是否启用 PostHog 原生页面浏览追踪，默认 true\r\n    capture_pageleave?: boolean; // 是否启用 PostHog 原生页面离开追踪，默认 true\r\n    session_recording?: {\r\n      enabled?: boolean; // 是否启用会话录制，默认 false\r\n    };\r\n  };\r\n  // WebSocket 配置（可选）\r\n  websocketUrl?: string; // WebSocket 连接地址\r\n  sessionId?: string; // 如果不传，则生成 uuid 并持久化\r\n  // 存储配置\r\n  storageKeyUserId?: string; // 默认 \"user_id\"\r\n  // 用户属性\r\n  userProperties?: UserProperties; // 用户属性\r\n}\r\n\r\n// =============================================================================\r\n// 工具函数\r\n// =============================================================================\r\n\r\nconst isBrowser =\r\n  typeof window !== \"undefined\" && typeof document !== \"undefined\";\r\n\r\nfunction generateUUID(): string {\r\n  if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\r\n    try {\r\n      return (crypto as any).randomUUID();\r\n    } catch (_) {}\r\n  }\r\n  const tpl = \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\";\r\n  return tpl.replace(/[xy]/g, (c) => {\r\n    const r = (Math.random() * 16) | 0;\r\n    const v = c === \"x\" ? r : (r & 0x3) | 0x8;\r\n    return v.toString(16);\r\n  });\r\n}\r\n\r\n// =============================================================================\r\n// 存储管理\r\n// =============================================================================\r\n\r\nfunction ensureUserId(storageKey: string, provided?: string): string {\r\n  if (!isBrowser) return provided || generateUUID();\r\n  try {\r\n    if (provided && provided.trim()) {\r\n      localStorage.setItem(storageKey, provided);\r\n      return provided;\r\n    }\r\n    const existing = localStorage.getItem(storageKey);\r\n    if (existing && existing.trim()) return existing;\r\n    const id = generateUUID();\r\n    localStorage.setItem(storageKey, id);\r\n    return id;\r\n  } catch (_) {\r\n    return provided || generateUUID();\r\n  }\r\n}\r\n\r\n// =============================================================================\r\n// 状态管理\r\n// =============================================================================\r\n\r\nlet trackerEnabled = false;\r\nlet trackerOptions: AutoTrackerOptions | null = null;\r\nlet persistedUserId: string | null = null;\r\nlet userProperties: UserProperties = {};\r\nlet websocketClient: WebSocketClient | null = null;\r\n\r\n// For cleanup\r\nlet removeListeners: Array<() => void> = [];\r\n\r\n// WebSocket 连接初始化\r\nfunction initializeWebSocketConnection(sessionId: string): void {\r\n  if (!trackerOptions || !trackerOptions.websocketUrl) return;\r\n\r\n  try {\r\n    // 如果已存在 WebSocket 客户端，检查是否需要更新\r\n    if (websocketClient) {\r\n      const currentSessionId = websocketClient.getSessionId();\r\n      const currentUrl = websocketClient.getUrl();\r\n\r\n      // 检查是否需要更新配置\r\n      const needsReconnect =\r\n        currentUrl !== trackerOptions.websocketUrl ||\r\n        currentSessionId !== trackerOptions.sessionId ||\r\n        !websocketClient.isConnected();\r\n\r\n      if (!needsReconnect) {\r\n        console.log(\"[XD-Tracker] WebSocket 连接已存在且配置未变化\");\r\n        return;\r\n      }\r\n\r\n      // 如果 URL 变化，需要重新创建连接\r\n      if (currentUrl !== trackerOptions.websocketUrl) {\r\n        console.log(\"[XD-Tracker] WebSocket URL 变化，重新创建连接\");\r\n        websocketClient.disconnect();\r\n        websocketClient = null;\r\n      }\r\n      // 如果只是 sessionId 变化，使用 updateSessionId\r\n      else if (\r\n        currentSessionId !== trackerOptions.sessionId &&\r\n        websocketClient.isConnected()\r\n      ) {\r\n        console.log(\"[XD-Tracker] 更新 WebSocket 连接的 sessionId\");\r\n        websocketClient.updateSessionId(trackerOptions.sessionId!);\r\n        return;\r\n      }\r\n      // 如果连接��开，尝试重连\r\n      else if (!websocketClient.isConnected()) {\r\n        console.log(\"[XD-Tracker] WebSocket 连接断开，尝试重连\");\r\n        websocketClient.reconnect();\r\n        return;\r\n      }\r\n    }\r\n\r\n    // 创建新的 WebSocket 客户端\r\n    console.log(\"[XD-Tracker] 创建新的 WebSocket 连接\");\r\n    websocketClient = new WebSocketClient({\r\n      url: trackerOptions.websocketUrl,\r\n      sessionId,\r\n      autoHandlePopup: true,\r\n      onOpen: () => {\r\n        console.log(\"[XD-Tracker] WebSocket 连接已建立\");\r\n      },\r\n      onClose: () => {\r\n        console.log(\"[XD-Tracker] WebSocket 连接已关闭\");\r\n      },\r\n      onError: (error) => {\r\n        console.error(\"[XD-Tracker] WebSocket 连接错误:\", error);\r\n      },\r\n    });\r\n\r\n    // 建立连接\r\n    websocketClient.connect();\r\n\r\n    // 将清理函数添加到列表中\r\n    removeListeners.push(() => {\r\n      if (websocketClient) {\r\n        websocketClient.disconnect();\r\n        websocketClient = null;\r\n      }\r\n    });\r\n  } catch (error) {\r\n    console.error(\"[XD-Tracker] WebSocket 初始化失败:\", error);\r\n  }\r\n}\r\n\r\n// =============================================================================\r\n// 公共 API\r\n// =============================================================================\r\n\r\nexport async function enableAutoTracker(\r\n  options: AutoTrackerOptions\r\n): Promise<void> {\r\n  if (!isBrowser) return;\r\n\r\n  // 验证必填参数\r\n  if (!options.posthog || !options.posthog.apiKey || !options.posthog.host) {\r\n    throw new Error(\r\n      \"[XD-Tracker] posthog.apiKey and posthog.host are required\"\r\n    );\r\n  }\r\n\r\n  // 如果已经启用，先清理之前的状态\r\n  if (trackerEnabled) {\r\n    console.log(\"[XD-Tracker] 重新初始化\");\r\n    trackerEnabled = false;\r\n  }\r\n\r\n  trackerOptions = options;\r\n  userProperties = { ...options.userProperties };\r\n\r\n  // 初始化 PostHog（使用原生自动采集）并获取 distinct_id\r\n  const distinctId = await initializePostHog({\r\n    apiKey: options.posthog.apiKey,\r\n    host: options.posthog.host,\r\n    enabled: options.posthog.enabled ?? true,\r\n    autocapture: options.posthog.autocapture ?? true,\r\n    capture_pageview: options.posthog.capture_pageview ?? true,\r\n    capture_pageleave: options.posthog.capture_pageleave ?? true,\r\n    session_recording: options.posthog.session_recording,\r\n  });\r\n\r\n  if (!distinctId) {\r\n    return;\r\n  }\r\n\r\n  // 使用 PostHog 返回的 distinct_id 作为 persistedUserId\r\n  persistedUserId = distinctId;\r\n\r\n  trackerEnabled = true;\r\n\r\n  // 初始化 WebSocket 连接（如果配置了）\r\n  if (trackerOptions.websocketUrl) {\r\n    initializeWebSocketConnection(persistedUserId);\r\n  }\r\n}\r\n\r\nexport function disableAutoTracker(fullReset?: boolean): void {\r\n  trackerEnabled = false;\r\n\r\n  // 执行所有清理函数\r\n  for (const fn of removeListeners.splice(0, removeListeners.length)) {\r\n    try {\r\n      fn();\r\n    } catch (_) {}\r\n  }\r\n\r\n  console.log(\"[XD-Tracker] 已禁用\");\r\n}\r\n\r\n/**\r\n * 获取跟踪器当前状态\r\n */\r\nexport function getTrackerStatus(): {\r\n  enabled: boolean;\r\n  sessionId: string | null;\r\n  userProperties: UserProperties;\r\n  websocketConnected: boolean;\r\n  websocketUrl?: string;\r\n  posthogHost?: string;\r\n} {\r\n  return {\r\n    enabled: trackerEnabled,\r\n    sessionId: persistedUserId,\r\n    userProperties,\r\n    websocketConnected: websocketClient?.isConnected() || false,\r\n    websocketUrl: trackerOptions?.websocketUrl,\r\n    posthogHost: trackerOptions?.posthog?.host,\r\n  };\r\n}\r\n\r\n/**\r\n * 重置跟踪器状态\r\n */\r\nexport function resetTracker(): void {\r\n  disableAutoTracker(true);\r\n}\r\n\r\n/**\r\n * 获取 WebSocket 客户端实例\r\n */\r\nexport function getWebSocketClient(): WebSocketClient | null {\r\n  return websocketClient;\r\n}\r\n\r\n/**\r\n * 更新 WebSocket 连接的 sessionId\r\n */\r\nexport function updateWebSocketSessionId(sessionId: string): void {\r\n  if (websocketClient) {\r\n    websocketClient.updateSessionId(sessionId);\r\n  }\r\n  // 同时更新 trackerOptions 中的 sessionId\r\n  if (trackerOptions) {\r\n    trackerOptions.sessionId = sessionId;\r\n  }\r\n}\r\n\r\n/**\r\n * 设置 WebSocket 是否自动处理弹窗\r\n */\r\nexport function setWebSocketAutoHandlePopup(enabled: boolean): void {\r\n  if (websocketClient) {\r\n    websocketClient.setAutoHandlePopup(enabled);\r\n  }\r\n}\r\n\r\n/**\r\n * 获取 WebSocket 自动处理弹窗设置\r\n */\r\nexport function getWebSocketAutoHandlePopup(): boolean {\r\n  return websocketClient ? websocketClient.getAutoHandlePopup() : false;\r\n}\r\n\r\n/**\r\n * 识别用户并设置用户属性\r\n * @param userId 用户ID\r\n * @param properties 用户属性，可包含 email、phone 等\r\n */\r\nexport function identify(userId: string, properties?: UserProperties): void {\r\n  if (!trackerOptions) return;\r\n\r\n  // 更新用户属性\r\n  if (properties) {\r\n    userProperties = {\r\n      ...userProperties,\r\n      ...properties,\r\n      id: userId,\r\n    };\r\n\r\n    // 同步到 PostHog\r\n    identifyPostHogUser(userId, properties);\r\n\r\n    console.log(`[XD-Tracker] 用户已识别，用户ID: ${userId}，属性已更新`);\r\n  } else {\r\n    // 同步到 PostHog\r\n    identifyPostHogUser(userId);\r\n\r\n    console.log(`[XD-Tracker] 用户已识别，用户ID: ${userId}`);\r\n  }\r\n  reconnectionWS();\r\n}\r\n\r\n/**\r\n * 重置用户信息，清除所有用户属性\r\n * 退出登录时调用，会重新生成 distinct_id 并重新初始化 WebSocket\r\n */\r\nexport function reset(): void {\r\n  if (!trackerOptions) return;\r\n\r\n  // 清空所有用户属性\r\n  userProperties = {};\r\n\r\n  // 同步到 PostHog（会重新生成 distinct_id）\r\n  resetPostHogUser();\r\n  reconnectionWS();\r\n}\r\n\r\nfunction reconnectionWS() {\r\n  // 获取新的 distinct_id\r\n  const posthog = getPostHogInstance();\r\n  const newDistinctId = posthog.get_distinct_id?.();\r\n  // 更新 persistedUserId\r\n  const oldDistinctId = persistedUserId;\r\n  persistedUserId = newDistinctId;\r\n\r\n  // 如果配置了 WebSocket 且 distinct_id 发生变化\r\n  if (trackerOptions?.websocketUrl && oldDistinctId !== newDistinctId) {\r\n    // 关闭旧的 WebSocket 连接\r\n    if (websocketClient) {\r\n      websocketClient.disconnect();\r\n      websocketClient = null;\r\n    }\r\n\r\n    // 用新的 distinct_id 重新初始化 WebSocket\r\n    initializeWebSocketConnection(newDistinctId);\r\n  }\r\n}\r\n\r\nexport function track(eventName: string, properties?: Record<string, any>) {\r\n  capturePostHogEvent(eventName, properties);\r\n\r\n  let attempts = 0;\r\n  const maxAttempts = 50; // 最多尝试 50 次 (5秒)\r\n  const checkInterval = 100; // 每 100ms 检查一次\r\n\r\n  setTimeout(() => {\r\n    if (eventName === \"UserLogin\") {\r\n      const posthog = getPostHogInstance();\r\n      const newDistinctId = posthog.get_distinct_id?.();\r\n      const payload = JSON.stringify({\r\n        eventName,\r\n        distinct_id: newDistinctId,\r\n        userId: newDistinctId,\r\n        sdk: trackerOptions?.posthog.apiKey,\r\n      });\r\n      const intervalId = setInterval(() => {\r\n        attempts++;\r\n\r\n        if (websocketClient && websocketClient.isConnected()) {\r\n          // 连接成功，发送消息\r\n          const sent = websocketClient.send(payload);\r\n          if (sent) {\r\n            console.log(\r\n              `[XD-Tracker] UserLogin 事件已发送 (尝试 ${attempts} 次)`\r\n            );\r\n          }\r\n          clearInterval(intervalId);\r\n        } else if (attempts >= maxAttempts) {\r\n          // 超时\r\n          console.warn(\r\n            `[XD-Tracker] UserLogin 事件发送超时，WebSocket 未在 ${\r\n              maxAttempts * checkInterval\r\n            }ms 内连接`\r\n          );\r\n          clearInterval(intervalId);\r\n        } else {\r\n          console.log(\r\n            `[XD-Tracker] 等待 WebSocket 连接... (${attempts}/${maxAttempts})`\r\n          );\r\n        }\r\n      }, checkInterval);\r\n    }\r\n  }, 200);\r\n}\r\n\r\nexport function isIdentified(): boolean {\r\n  const posthog = getPostHogInstance();\r\n  if (!posthog) {\r\n    return false;\r\n  }\r\n\r\n  return posthog._isIdentified();\r\n}","import { showPopup, PopupPayload } from \"./popup\";\r\n\r\nexport interface SSEConfig {\r\n  url: string;\r\n  sessionId?: string;\r\n  headers?: Record<string, string>;\r\n  withCredentials?: boolean;\r\n  onOpen?: () => void;\r\n  onClose?: () => void;\r\n  onError?: (error: Event) => void;\r\n  onMessage?: (data: any) => void;\r\n  retryInterval?: number;\r\n  maxRetryAttempts?: number;\r\n  autoHandlePopup?: boolean; // 是否自动处理弹窗消息，默认 true\r\n}\r\n\r\nexport interface PopupMessage {\r\n  type: \"popup\";\r\n  payload: PopupPayload;\r\n  strategy: any;\r\n  options?: {\r\n    containerId?: string;\r\n    overlayClosable?: boolean;\r\n    zIndex?: number;\r\n  };\r\n}\r\n\r\nexport class SSEClient {\r\n  private eventSource: EventSource | null = null;\r\n  private config: SSEConfig;\r\n  private retryAttempts = 0;\r\n  private retryTimer: NodeJS.Timeout | null = null;\r\n  private isConnecting = false;\r\n\r\n  constructor(config: SSEConfig) {\r\n    this.config = {\r\n      retryInterval: 3000,\r\n      maxRetryAttempts: 5,\r\n      autoHandlePopup: true,\r\n      ...config,\r\n    };\r\n  }\r\n\r\n  connect(): void {\r\n    if (\r\n      this.isConnecting ||\r\n      this.eventSource?.readyState === EventSource.OPEN\r\n    ) {\r\n      return;\r\n    }\r\n\r\n    this.isConnecting = true;\r\n\r\n    try {\r\n      // 构建 URL，添加 sessionId 参数\r\n      let url = this.config.url;\r\n      if (this.config.sessionId) {\r\n        const separator = url.includes(\"?\") ? \"&\" : \"?\";\r\n        url = `${url}${separator}sessionId=${encodeURIComponent(\r\n          this.config.sessionId\r\n        )}`;\r\n      }\r\n\r\n      // 创建 EventSource 实例\r\n      this.eventSource = new EventSource(url, {\r\n        withCredentials: this.config.withCredentials,\r\n      });\r\n\r\n      this.setupEventHandlers();\r\n    } catch (error) {\r\n      console.error(\"SSE connection failed:\", error);\r\n      this.isConnecting = false;\r\n      this.handleRetry();\r\n    }\r\n  }\r\n\r\n  private setupEventHandlers(): void {\r\n    if (!this.eventSource) return;\r\n\r\n    this.eventSource.onopen = () => {\r\n      console.log(\"SSE connected\");\r\n      this.isConnecting = false;\r\n      this.retryAttempts = 0;\r\n      this.config.onOpen?.();\r\n    };\r\n\r\n    this.eventSource.onerror = (error) => {\r\n      console.error(\"SSE error:\", error);\r\n      this.isConnecting = false;\r\n      this.config.onError?.(error);\r\n\r\n      // SSE 会自动重连，但我们也可以添加自定义重连逻辑\r\n      if (this.eventSource?.readyState === EventSource.CLOSED) {\r\n        this.handleRetry();\r\n      }\r\n    };\r\n\r\n    // 监听自定义事件类型\r\n    this.eventSource.addEventListener(\"popup\", (event) => {\r\n      try {\r\n        const data = JSON.parse(event.data);\r\n        this.handlePopupMessage(data);\r\n        // 仍然调用外部回调\r\n        this.config.onMessage?.(data);\r\n      } catch (error) {\r\n        console.error(\"[SSE] Failed to parse popup message:\", error);\r\n      }\r\n    });\r\n\r\n    // 监听通用消息事件\r\n    this.eventSource.onmessage = (event) => {\r\n      try {\r\n        const data = JSON.parse(JSON.parse(event.data));\r\n        this.handlePopupMessage(data);\r\n        // 调用外部回调\r\n        this.config.onMessage?.(data);\r\n      } catch (error) {\r\n        console.error(\"[SSE] Failed to parse SSE message:\", error);\r\n      }\r\n    };\r\n  }\r\n\r\n  private handlePopupMessage(data: any): void {\r\n    if (this.config.autoHandlePopup) {\r\n      const popupMessage = data as PopupMessage;\r\n      showPopup(popupMessage.strategy.content, popupMessage.options);\r\n      console.log(\"[SSE] 自动显示弹窗:\", popupMessage.payload.title);\r\n    }\r\n  }\r\n\r\n  private handleMessage(data: any): void {\r\n    // 处理通用消息（弹窗消息由专门的 event handler 处理）\r\n    // 这里只处理非弹窗消息\r\n    if (data.type !== \"popup\") {\r\n      // 可以在这里添加其他类型的消息处理逻辑\r\n      console.log(\"[SSE] 收到非弹窗消息:\", data);\r\n    }\r\n  }\r\n\r\n  private handleRetry(): void {\r\n    if (this.retryAttempts >= (this.config.maxRetryAttempts || 5)) {\r\n      console.error(\"Max retry attempts reached\");\r\n      this.config.onError?.(new Event(\"Max retry attempts reached\"));\r\n      return;\r\n    }\r\n\r\n    this.retryAttempts++;\r\n    const delay = this.calculateRetryDelay();\r\n    console.log(\r\n      `Attempting to retry SSE connection in ${delay}ms... (${this.retryAttempts}/${this.config.maxRetryAttempts})`\r\n    );\r\n\r\n    this.retryTimer = setTimeout(() => {\r\n      this.connect();\r\n    }, delay);\r\n  }\r\n\r\n  private calculateRetryDelay(): number {\r\n    // 指数退避策略：基础延迟 * 2^(重试次数-1)，最大延迟为30秒\r\n    const baseDelay = this.config.retryInterval || 3000;\r\n    const maxDelay = 30000;\r\n    const delay = Math.min(\r\n      baseDelay * Math.pow(2, this.retryAttempts - 1),\r\n      maxDelay\r\n    );\r\n\r\n    // 添加随机抖动，避免多个客户端同时重试\r\n    const jitter = Math.random() * 1000;\r\n    return delay + jitter;\r\n  }\r\n\r\n  // 手动触发重连\r\n  reconnect(): void {\r\n    if (this.retryTimer) {\r\n      clearTimeout(this.retryTimer);\r\n      this.retryTimer = null;\r\n    }\r\n    this.retryAttempts = 0;\r\n    this.connect();\r\n  }\r\n\r\n  // 重置重试计数\r\n  resetRetryAttempts(): void {\r\n    this.retryAttempts = 0;\r\n    if (this.retryTimer) {\r\n      clearTimeout(this.retryTimer);\r\n      this.retryTimer = null;\r\n    }\r\n  }\r\n\r\n  // 添加自定义事件监听器\r\n  addEventListener(eventType: string, listener: EventListener): void {\r\n    if (this.eventSource) {\r\n      this.eventSource.addEventListener(eventType, listener);\r\n    }\r\n  }\r\n\r\n  // 移除自定义事件监听器\r\n  removeEventListener(eventType: string, listener: EventListener): void {\r\n    if (this.eventSource) {\r\n      this.eventSource.removeEventListener(eventType, listener);\r\n    }\r\n  }\r\n\r\n  disconnect(): void {\r\n    if (this.retryTimer) {\r\n      clearTimeout(this.retryTimer);\r\n      this.retryTimer = null;\r\n    }\r\n\r\n    if (this.eventSource) {\r\n      this.eventSource.close();\r\n      this.eventSource = null;\r\n    }\r\n\r\n    this.isConnecting = false;\r\n    this.retryAttempts = 0;\r\n  }\r\n\r\n  isConnected(): boolean {\r\n    return this.eventSource?.readyState === EventSource.OPEN;\r\n  }\r\n\r\n  getReadyState(): number {\r\n    return this.eventSource?.readyState || EventSource.CLOSED;\r\n  }\r\n\r\n  // 获取连接状态描述\r\n  getReadyStateText(): string {\r\n    const state = this.getReadyState();\r\n    switch (state) {\r\n      case EventSource.CONNECTING:\r\n        return \"CONNECTING\";\r\n      case EventSource.OPEN:\r\n        return \"OPEN\";\r\n      case EventSource.CLOSED:\r\n        return \"CLOSED\";\r\n      default:\r\n        return \"UNKNOWN\";\r\n    }\r\n  }\r\n\r\n  // 更新 sessionId 并重新连接\r\n  updateSessionId(sessionId: string): void {\r\n    this.config.sessionId = sessionId;\r\n    if (this.isConnected()) {\r\n      // 如果已连接，需要重新连接以应用新的 sessionId\r\n      this.disconnect();\r\n      this.connect();\r\n    }\r\n  }\r\n\r\n  // 获取当前 sessionId\r\n  getSessionId(): string | undefined {\r\n    return this.config.sessionId;\r\n  }\r\n\r\n  // 获取当前 URL\r\n  getUrl(): string {\r\n    return this.config.url;\r\n  }\r\n\r\n  // 设置是否自动处理弹窗\r\n  setAutoHandlePopup(enabled: boolean): void {\r\n    this.config.autoHandlePopup = enabled;\r\n  }\r\n\r\n  // 获取当前自动处理弹窗设置\r\n  getAutoHandlePopup(): boolean {\r\n    return this.config.autoHandlePopup ?? true;\r\n  }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAM,YAAY,OAAO,WAAW,eAAe,OAAO,aAAa;AAkCvE,IAAM,uBAAuB;AAC7B,IAAM,WAAW;AACjB,IAAM,qBAAqB;AAE3B,SAAS,kBAAkB,KAAa,MAAW,kBAAiC;AAClF,MAAI,CAAC;AAAW;AAChB,MAAI;AACF,UAAM,OAAO;AAAA,MACX;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB,SAAS,mBAAmB,KAAK,IAAI,IAAI,mBAAmB,MAAO;AAAA,IACrE;AACA,iBAAa,QAAQ,qBAAqB,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,EACrE,SAAS,GAAG;AACV,YAAQ,KAAK,iCAAiC,CAAC;AAAA,EACjD;AACF;AAEA,SAAS,kBAAkB,KAAkB;AAC3C,MAAI,CAAC;AAAW,WAAO;AACvB,MAAI;AACF,UAAM,OAAO,aAAa,QAAQ,qBAAqB,GAAG;AAC1D,QAAI,CAAC;AAAM,aAAO;AAElB,UAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QAAI,OAAO,WAAW,KAAK,IAAI,IAAI,OAAO,SAAS;AACjD,mBAAa,WAAW,qBAAqB,GAAG;AAChD,aAAO;AAAA,IACT;AACA,WAAO,OAAO;AAAA,EAChB,SAAS,GAAG;AACV,YAAQ,KAAK,6CAA6C,CAAC;AAC3D,WAAO;AAAA,EACT;AACF;AAWA,SAAS,qBAAqB,QAAsB;AAClD,MAAI,CAAC;AAAW;AAChB,QAAM,WAAW,SAAS,eAAe,QAAQ;AACjD,MAAI;AAAU;AAEd,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,KAAK;AACX,QAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAmBP,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAsNH,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["posthog","isBrowser","isBrowser","posthog"]}