{"version":3,"sources":["../src/components/liquid-orb/context/liquidOrbContext.ts","../src/events/emitter.ts","../src/events/AISphereEventsProvider.tsx","../src/components/liquid-orb/utils/audioBands.ts","../src/components/liquid-orb/hooks/audioGraph.ts","../src/components/liquid-orb/hooks/useAudioAnalyser.ts","../src/components/liquid-orb/hooks/useAudioEvents.ts","../src/components/liquid-orb/context/LiquidOrbProvider.tsx","../src/components/liquid-orb/context/types.ts","../src/components/liquid-orb/utils/math.ts","../src/components/liquid-orb/hooks/useAudioEnvelope.ts","../src/components/liquid-orb/presets.ts","../src/components/liquid-orb/hooks/useOrbController.ts","../src/components/liquid-orb/hooks/useOrbUniforms.ts","../src/components/liquid-orb/hooks/usePulseValue.ts","../src/components/liquid-orb/shaders/simplex3d.ts","../src/components/liquid-orb/shaders/orbVertex.ts","../src/components/liquid-orb/shaders/orbFragment.ts","../src/components/liquid-orb/LiquidOrbScene.tsx","../src/components/liquid-orb/LiquidOrbCanvas.tsx","../src/components/liquid-orb/LiquidOrb.tsx","../src/components/speech-recorder/useStreamingSTT.ts","../src/components/speech-recorder/useVAD.ts","../src/components/speech-recorder/useSpeechRecorder.ts","../src/components/speech-recorder/useWebSpeech.ts","../src/utils/useTextChunker.ts","../src/components/conversation/useConversation.ts","../src/logger/store.ts","../src/logger/useLoggerBridge.ts"],"names":["createContext","useContext","useRef","useEffect","useState","useCallback","useMemo","jsx","useFrame","THREE2","THREE3","jsxs","computeMicBands","preferBrowser","DEFAULT_CONFIG","el"],"mappings":"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","file":"chunk-WFSO4MNC.mjs","sourcesContent":["import { createContext, useContext } from 'react';\nimport type { LiquidOrbContextValue, LiquidOrbInternalContextValue } from './types.js';\n\nexport const LiquidOrbContext = createContext<LiquidOrbContextValue | null>(null);\n\nexport const LiquidOrbInternalContext = createContext<LiquidOrbInternalContextValue | null>(null);\n\nexport function useLiquidOrb(): LiquidOrbContextValue {\n  const ctx = useContext(LiquidOrbContext);\n  if (!ctx) {\n    throw new Error('useLiquidOrb must be used within a <LiquidOrbProvider>');\n  }\n  return ctx;\n}\n\nexport function useLiquidOrbInternal(): LiquidOrbInternalContextValue {\n  const ctx = useContext(LiquidOrbInternalContext);\n  if (!ctx) {\n    throw new Error('useLiquidOrbInternal must be used within a <LiquidOrbProvider>');\n  }\n  return ctx;\n}\n","export type EventHandler<T = void> = (data: T) => void;\n\nexport class TypedEmitter<TMap extends Record<string, any>> {\n  private listeners = new Map<keyof TMap, Set<EventHandler<any>>>();\n\n  on<K extends keyof TMap>(event: K, handler: EventHandler<TMap[K]>): () => void {\n    let set = this.listeners.get(event);\n    if (!set) {\n      set = new Set();\n      this.listeners.set(event, set);\n    }\n    set.add(handler);\n    return () => { set!.delete(handler); };\n  }\n\n  emit<K extends keyof TMap>(event: K, data: TMap[K]): void {\n    const set = this.listeners.get(event);\n    if (set) {\n      for (const handler of set) handler(data);\n    }\n  }\n\n  off<K extends keyof TMap>(event: K, handler: EventHandler<TMap[K]>): void {\n    this.listeners.get(event)?.delete(handler);\n  }\n\n  removeAllListeners(): void {\n    this.listeners.clear();\n  }\n}\n","import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react';\nimport { TypedEmitter } from './emitter.js';\nimport type { AISphereEventMap } from './types.js';\n\nexport const AISphereEventsContext = createContext<TypedEmitter<AISphereEventMap> | null>(null);\n\nexport function AISphereEventsProvider({ children }: { children: React.ReactNode }) {\n  const emitter = useMemo(() => new TypedEmitter<AISphereEventMap>(), []);\n  return (\n    <AISphereEventsContext.Provider value={emitter}>\n      {children}\n    </AISphereEventsContext.Provider>\n  );\n}\n\nexport function useAISphereEmitter(): TypedEmitter<AISphereEventMap> {\n  const ctx = useContext(AISphereEventsContext);\n  if (!ctx) throw new Error('useAISphereEmitter must be used within <AISphereEventsProvider>');\n  return ctx;\n}\n\nexport function useAISphereEvent<K extends keyof AISphereEventMap>(\n  event: K,\n  handler: (data: AISphereEventMap[K]) => void,\n): void {\n  const handlerRef = useRef(handler);\n  handlerRef.current = handler;\n\n  const emitter = useContext(AISphereEventsContext);\n\n  useEffect(() => {\n    if (!emitter) return;\n    return emitter.on(event, (data) => handlerRef.current(data));\n  }, [emitter, event]);\n}\n","import type { AudioFrame } from '../context/types.js';\n\n/**\n * Maps raw FFT frequency data into low/mid/high energy bands + overall volume.\n *\n * Assumes 1024 FFT size (512 bins) at 44100 Hz sample rate.\n * - Low:  bins  0–10   (~0–430 Hz)\n * - Mid:  bins 11–80   (~430–3500 Hz)\n * - High: bins 81–255  (~3500–11000 Hz)\n */\nexport function computeAudioBands(\n  frequencyData: Uint8Array,\n  out: AudioFrame,\n): void {\n  const len = frequencyData.length;\n  if (len === 0) {\n    out.low = 0;\n    out.mid = 0;\n    out.high = 0;\n    out.volume = 0;\n    return;\n  }\n\n  const lowEnd = Math.min(11, len);\n  const midEnd = Math.min(81, len);\n  const highEnd = Math.min(256, len);\n\n  let lowSum = 0;\n  let midSum = 0;\n  let highSum = 0;\n  let totalSum = 0;\n\n  for (let i = 0; i < lowEnd; i++) {\n    lowSum += frequencyData[i]!;\n  }\n  for (let i = lowEnd; i < midEnd; i++) {\n    midSum += frequencyData[i]!;\n  }\n  for (let i = midEnd; i < highEnd; i++) {\n    highSum += frequencyData[i]!;\n  }\n  for (let i = 0; i < len; i++) {\n    totalSum += frequencyData[i]!;\n  }\n\n  // Normalize to 0–1 (max byte value = 255)\n  out.low = lowSum / (lowEnd * 255);\n  out.mid = midEnd > lowEnd ? midSum / ((midEnd - lowEnd) * 255) : 0;\n  out.high = highEnd > midEnd ? highSum / ((highEnd - midEnd) * 255) : 0;\n  out.volume = totalSum / (len * 255);\n}\n","// ── HMR-safe WebAudio graph cache ────────────────────────────────────────────\n//\n// `createMediaElementSource` can only be called once per HTMLAudioElement —\n// subsequent calls throw. Module-level WeakMap resets on HMR, losing the\n// reference while the browser still holds the binding. Storing on globalThis\n// via Symbol.for ensures the cache survives hot reloads.\n//\n// A single shared AudioContext is reused across all elements to avoid hitting\n// Chrome's ~6-8 concurrent AudioContext limit.\n\nexport interface AudioGraph {\n  ctx: AudioContext;\n  source: MediaElementAudioSourceNode;\n  analyser: AnalyserNode;\n}\n\nconst CACHE_KEY = Symbol.for('__aisphere_audio_cache__');\nconst CTX_KEY = Symbol.for('__aisphere_audio_ctx__');\n\nfunction getCache(): WeakMap<HTMLAudioElement, AudioGraph> {\n  const g = globalThis as unknown as Record<symbol, WeakMap<HTMLAudioElement, AudioGraph>>;\n  if (!g[CACHE_KEY]) {\n    g[CACHE_KEY] = new WeakMap();\n  }\n  return g[CACHE_KEY];\n}\n\nfunction getSharedContext(): AudioContext {\n  const g = globalThis as unknown as Record<symbol, AudioContext>;\n  if (!g[CTX_KEY]) {\n    g[CTX_KEY] = new AudioContext();\n  }\n  const ctx = g[CTX_KEY];\n  if (ctx.state === 'suspended') {\n    const resume = () => { void ctx.resume(); };\n    document.addEventListener('click', resume, { once: true });\n    document.addEventListener('keydown', resume, { once: true });\n  }\n  return ctx;\n}\n\n/**\n * Get or create a WebAudio graph (AudioContext → MediaElementSource → AnalyserNode)\n * for the given audio element. Cached per element, survives HMR.\n * Uses a single shared AudioContext to avoid Chrome's context limit.\n */\nexport function getAudioGraph(audioElement: HTMLAudioElement): AudioGraph {\n  const cache = getCache();\n  let entry = cache.get(audioElement);\n\n  if (!entry) {\n    const ctx = getSharedContext();\n\n    // Ensure AudioContext is running\n    if (ctx.state === 'suspended') {\n      void ctx.resume();\n    }\n\n    const analyser = ctx.createAnalyser();\n    analyser.fftSize = 1024;\n    analyser.smoothingTimeConstant = 0.4;\n\n    const source = ctx.createMediaElementSource(audioElement);\n    source.connect(analyser);\n    analyser.connect(ctx.destination);\n\n    entry = { ctx, source, analyser };\n    cache.set(audioElement, entry);\n  } else {\n    // Entry exists - ensure AudioContext is running and analyser is connected\n    if (entry.ctx.state === 'suspended') {\n      void entry.ctx.resume();\n    }\n    // Reconnect analyser to destination in case it was disconnected\n    try {\n      entry.analyser.connect(entry.ctx.destination);\n    } catch {\n      // Already connected, ignore\n    }\n  }\n\n  return entry;\n}\n\n/**\n * Disconnect the analyser output for a given audio element.\n * Does NOT remove from cache or close the AudioContext — because\n * `createMediaElementSource` is a one-time browser binding that\n * cannot be re-created for the same element. The cache entry is\n * kept so that `getAudioGraph` can reconnect if needed.\n *\n * The AudioContext itself is cleaned up by GC once the\n * HTMLAudioElement is no longer referenced (WeakMap key).\n */\nexport function releaseAudioGraph(audioElement: HTMLAudioElement): void {\n  const cache = getCache();\n  const entry = cache.get(audioElement);\n  if (entry) {\n    // Disconnect analyser output to stop feeding audio data,\n    // but keep source→analyser connected so the graph can be reused.\n    entry.analyser.disconnect();\n  }\n}\n","import { useEffect, useRef } from 'react';\nimport type { AudioFrame } from '../context/types.js';\nimport { computeAudioBands } from '../utils/audioBands.js';\nimport { getAudioGraph } from './audioGraph.js';\n\n/** How long an event-driven write holds priority over FFT (ms). */\nconst EVENT_PRIORITY_TTL = 200;\n\n/**\n * Reads FFT data from a WebAudio AnalyserNode into an AudioFrame ref\n * via a rAF loop. Only writes when:\n *  1. The audio element is actively playing\n *  2. No event-driven write happened within the last EVENT_PRIORITY_TTL ms\n *\n * This lets event-driven sources (mic/tts) take priority while active,\n * and FFT automatically fills gaps when events stop arriving.\n */\nexport function useAudioAnalyser(\n  audioElement: HTMLAudioElement | null | undefined,\n  frameRef: React.RefObject<AudioFrame>,\n  lastEventWriteRef?: React.RefObject<{ time: number }>,\n): void {\n  const rafRef = useRef<number>(0);\n\n  useEffect(() => {\n    if (!audioElement) {\n      // Don't zero frame here — SSE-based audio:tts-frame events may still be\n      // writing data. Let the frame hold its last value; the orb controller\n      // handles smooth decay on its own.\n      return;\n    }\n\n    const { analyser } = getAudioGraph(audioElement);\n    const frequencyData = new Uint8Array(analyser.frequencyBinCount);\n\n    let cancelled = false;\n\n    const tick = () => {\n      if (cancelled) return;\n      // Only write FFT data when audio is actually playing AND\n      // no recent event-driven write occurred (within EVENT_PRIORITY_TTL)\n      const eventActive = lastEventWriteRef?.current\n        ? (performance.now() - lastEventWriteRef.current.time < EVENT_PRIORITY_TTL)\n        : false;\n      if (!audioElement.paused && !audioElement.ended && !eventActive) {\n        analyser.getByteFrequencyData(frequencyData);\n        const frame = frameRef.current;\n        if (frame) {\n          computeAudioBands(frequencyData, frame);\n        }\n      }\n      rafRef.current = requestAnimationFrame(tick);\n    };\n    rafRef.current = requestAnimationFrame(tick);\n\n    return () => {\n      cancelled = true;\n      cancelAnimationFrame(rafRef.current);\n    };\n  }, [audioElement, frameRef, lastEventWriteRef]);\n}\n","import { useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport type { AudioFrame } from '../context/types.js';\nimport { AISphereEventsContext } from '../../../events/AISphereEventsProvider.js';\nimport { useAudioAnalyser } from './useAudioAnalyser.js';\n\nconst DEFAULT_AUDIO_FRAME: AudioFrame = { low: 0, mid: 0, high: 0, volume: 0 };\n\n/**\n * Single source of truth for all audio data flowing into the orb.\n *\n * Merges three input channels into one `audioFrameRef`:\n *  1. **Events** — `audio:mic-frame` and `audio:tts-frame` written directly by producers\n *  2. **WebAudio FFT** — `useAudioAnalyser` on the active HTMLAudioElement (fallback for buffered TTS)\n *  3. **Imperative** — `writeAudioFrame()` for direct writes from outside the event system\n *\n * Also manages the TTS audio element lifecycle via `audio:tts-start` / `audio:tts-end` events.\n *\n * `lastEventWriteRef` tracks the timestamp of the last event-driven write so the FFT\n * analyser yields to recent event sources and fills gaps automatically after 200ms.\n */\nexport function useAudioEvents(\n  /** Fallback audio source (file playback). Event-driven TTS takes priority when active. */\n  audioSource: HTMLAudioElement | null | undefined,\n) {\n  const emitter = useContext(AISphereEventsContext);\n\n  // TTS audio element set via events (takes priority over explicit audioSource\n  // when active, because conversation TTS needs to drive the orb)\n  const [ttsAudioEl, setTtsAudioEl] = useState<HTMLAudioElement | null>(null);\n  const effectiveAudioSource = ttsAudioEl ?? audioSource;\n\n  const audioFrameRef = useRef<AudioFrame>({ ...DEFAULT_AUDIO_FRAME });\n\n  // Timestamp of the last event-driven write — FFT yields when recent (< 200ms)\n  const lastEventWriteRef = useRef<{ time: number }>({ time: 0 });\n\n  // WebAudio FFT fallback — analyses the active HTMLAudioElement.\n  // Yields to event-driven sources when a recent event write occurred.\n  useAudioAnalyser(effectiveAudioSource, audioFrameRef, lastEventWriteRef);\n\n  // Subscribe to all audio events\n  useEffect(() => {\n    if (!emitter) return;\n\n    const unsubs: Array<() => void> = [];\n\n    // Mic audio frames\n    unsubs.push(emitter.on('audio:mic-frame', (frame) => {\n      lastEventWriteRef.current.time = performance.now();\n      const ref = audioFrameRef.current;\n      if (ref) {\n        ref.low = frame.low;\n        ref.mid = frame.mid;\n        ref.high = frame.high;\n        ref.volume = frame.volume;\n      }\n    }));\n\n    // TTS SSE audio frames (server-side analysis)\n    unsubs.push(emitter.on('audio:tts-frame', (frame) => {\n      lastEventWriteRef.current.time = performance.now();\n      const ref = audioFrameRef.current;\n      if (ref) {\n        ref.low = frame.low;\n        ref.mid = frame.mid;\n        ref.high = frame.high;\n        ref.volume = frame.volume;\n      }\n    }));\n\n    // TTS lifecycle\n    unsubs.push(emitter.on('audio:tts-start', (audioEl) => {\n      setTtsAudioEl(audioEl);\n    }));\n\n    unsubs.push(emitter.on('audio:tts-end', () => {\n      setTtsAudioEl(null);\n    }));\n\n    // Reset audio frame to zero when conversation goes idle\n    // This prevents smoothed values from accumulating across cycles\n    unsubs.push(emitter.on('conversation:phase-change', (phase) => {\n      if (phase === 'idle') {\n        const ref = audioFrameRef.current;\n        if (ref) {\n          ref.low = 0;\n          ref.mid = 0;\n          ref.high = 0;\n          ref.volume = 0;\n        }\n        // Reset event timestamp so FFT doesn't think recent events occurred\n        lastEventWriteRef.current.time = 0;\n      }\n    }));\n\n    return () => {\n      for (const unsub of unsubs) unsub();\n    };\n  }, [emitter]);\n\n  // Imperative write — for consumers outside the event system (e.g. cmdop writeFrameRef)\n  const writeAudioFrame = useCallback((frame: AudioFrame) => {\n    lastEventWriteRef.current.time = performance.now();\n    const ref = audioFrameRef.current;\n    if (ref) {\n      ref.low = frame.low;\n      ref.mid = frame.mid;\n      ref.high = frame.high;\n      ref.volume = frame.volume;\n    }\n  }, []);\n\n  return { audioFrameRef, writeAudioFrame };\n}\n","import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { Color } from 'three';\nimport type {\n  LiquidOrbConfig,\n  LiquidOrbContextValue,\n  LiquidOrbInternalContextValue,\n  LiquidOrbMode,\n  OrbParams,\n  PulseType,\n} from './types.js';\nimport { LiquidOrbContext, LiquidOrbInternalContext } from './liquidOrbContext.js';\nimport { useAudioEvents } from '../hooks/useAudioEvents.js';\nimport { AISphereEventsContext } from '../../../events/AISphereEventsProvider.js';\n\nconst DEFAULT_PARAMS: OrbParams = {\n  noiseFrequency: 0.8,\n  noiseAmplitude: 0.03,\n  noiseSpeed: 0.2,\n  breathSpeed: 0.6,\n  breathAmplitude: 0.015,\n  distortion: 0,\n  color1: '#4a9eff',\n  color2: '#8b5cf6',\n  _color1: new Color('#4a9eff'),\n  _color2: new Color('#8b5cf6'),\n  emissiveIntensity: 0.3,\n  glowOpacity: 0.4,\n  glowScale: 1.5,\n  iridescence: 0.2,\n};\n\nconst EMPTY_CONFIG: LiquidOrbConfig = {};\n\ninterface LiquidOrbProviderProps {\n  mode?: LiquidOrbMode;\n  audioSource?: HTMLAudioElement | null;\n  config?: LiquidOrbConfig;\n  children: React.ReactNode;\n}\n\nexport function LiquidOrbProvider({\n  mode: modeProp,\n  audioSource,\n  config = EMPTY_CONFIG,\n  children,\n}: LiquidOrbProviderProps) {\n  // Optional event emitter — does NOT throw if outside provider\n  const emitter = useContext(AISphereEventsContext);\n\n  const [modeState, setModeState] = useState<LiquidOrbMode>('idle');\n  const mode = modeProp ?? modeState;\n\n  const modeRef = useRef<LiquidOrbMode>(mode);\n  modeRef.current = mode;\n\n  // Single source of truth for all audio data\n  const { audioFrameRef, writeAudioFrame } = useAudioEvents(audioSource);\n\n  const paramsRef = useRef<OrbParams>({\n    ...DEFAULT_PARAMS,\n    _color1: new Color('#4a9eff'),\n    _color2: new Color('#8b5cf6'),\n  });\n  const pulseRef = useRef<{ active: boolean; type: PulseType; startTime: number }>({\n    active: false,\n    type: 'info',\n    startTime: 0,\n  });\n\n  // Subscribe to conversation phase events (non-audio)\n  const modePropRef = useRef(modeProp);\n  modePropRef.current = modeProp;\n\n  useEffect(() => {\n    if (!emitter) return;\n\n    // Phase change → set mode (only in uncontrolled mode)\n    return emitter.on('conversation:phase-change', (phase) => {\n      if (modePropRef.current === undefined) {\n        setModeState(phase as LiquidOrbMode);\n      }\n    });\n  }, [emitter]);\n\n  const triggerPulse = useCallback((type: PulseType) => {\n    pulseRef.current = { active: true, type, startTime: performance.now() };\n  }, []);\n\n  const publicValue = useMemo<LiquidOrbContextValue>(\n    () => ({ mode, setMode: setModeState, triggerPulse, writeAudioFrame }),\n    [mode, triggerPulse, writeAudioFrame],\n  );\n\n  const internalValue = useMemo<LiquidOrbInternalContextValue>(\n    () => ({\n      audioFrameRef,\n      paramsRef,\n      pulseRef,\n      modeRef,\n      quality: 'high',\n      qualityConfig: { dpr: 2, segments: 128, antialias: true },\n      config,\n    }),\n    [config, audioFrameRef],\n  );\n\n  return (\n    <LiquidOrbContext.Provider value={publicValue}>\n      <LiquidOrbInternalContext.Provider value={internalValue}>\n        {children}\n      </LiquidOrbInternalContext.Provider>\n    </LiquidOrbContext.Provider>\n  );\n}\n","import type { ReactNode } from 'react';\nimport type { Color } from 'three';\n\n// ── Modes ──────────────────────────────────────────────────────────────────────\n\nexport type LiquidOrbMode = 'idle' | 'listening' | 'thinking' | 'speaking';\n\nexport type PulseType = 'success' | 'error' | 'info';\n\n// ── Audio ──────────────────────────────────────────────────────────────────────\n\nexport interface AudioFrame {\n  low: number;   // 0-1 bass energy\n  mid: number;   // 0-1 mid energy\n  high: number;  // 0-1 treble energy\n  volume: number; // 0-1 overall volume\n}\n\n// ── Quality ────────────────────────────────────────────────────────────────────\n\nexport type QualityTier = 'high' | 'medium' | 'low';\n\nexport interface QualityConfig {\n  dpr: number;\n  segments: number;\n  antialias: boolean;\n}\n\n// ── Orb params (interpolated per-frame) ────────────────────────────────────────\n\nexport interface OrbParams {\n  noiseFrequency: number;\n  noiseAmplitude: number;\n  noiseSpeed: number;\n  breathSpeed: number;\n  breathAmplitude: number;\n  distortion: number;\n  color1: string;\n  color2: string;\n  /** Pre-parsed Color objects — written by useOrbController, read by useOrbUniforms (avoids hex parse per frame) */\n  _color1?: Color;\n  _color2?: Color;\n  emissiveIntensity: number;\n  glowOpacity: number;\n  glowScale: number;\n  iridescence: number;\n}\n\n// ── Audio reactivity config ────────────────────────────────────────────────────\n\nexport interface AudioReactivityConfig {\n  lowGain: number;       // how much bass affects noise amplitude\n  midGain: number;       // how much mids affect noise amplitude\n  highGain: number;      // how much treble affects distortion\n  volumeGain: number;    // how much overall volume affects speed\n  smoothAttack: number;  // EMA attack factor 0-1\n  smoothRelease: number; // EMA release factor 0-1\n  emissiveGain: number;  // how much volume boosts emissive intensity\n}\n\nexport const DEFAULT_AUDIO_REACTIVITY: AudioReactivityConfig = {\n  lowGain: 0.12,        // bass → noise amplitude\n  midGain: 0.06,        // mids → noise amplitude\n  highGain: 0.04,       // treble → distortion\n  volumeGain: 0.20,     // volume → speed\n  smoothAttack: 0.06,   // smooth attack (was 0.12 - too fast)\n  smoothRelease: 0.025, // slow release for smooth decay\n  emissiveGain: 0.4,    // volume → glow\n};\n\n// ── Full config ────────────────────────────────────────────────────────────────\n\nexport interface LiquidOrbConfig {\n  presets?: Partial<Record<LiquidOrbMode, Partial<OrbParams>>>;\n  audioReactivity?: Partial<AudioReactivityConfig>;\n  lerpSpeed?: number; // mode transition speed (default 0.04)\n}\n\n// ── Props ──────────────────────────────────────────────────────────────────────\n\nexport interface LiquidOrbProps {\n  mode?: LiquidOrbMode;\n  audioSource?: HTMLAudioElement | null;\n  size?: number;\n  config?: LiquidOrbConfig;\n  className?: string;\n  children?: ReactNode;\n}\n\n// ── Context values ─────────────────────────────────────────────────────────────\n\nexport interface LiquidOrbContextValue {\n  mode: LiquidOrbMode;\n  setMode: (mode: LiquidOrbMode) => void;\n  triggerPulse: (type: PulseType) => void;\n  /** Write mic audio frame data directly into the orb's audio pipeline */\n  writeAudioFrame: (frame: AudioFrame) => void;\n}\n\nexport interface LiquidOrbInternalContextValue {\n  audioFrameRef: React.RefObject<AudioFrame>;\n  paramsRef: React.RefObject<OrbParams>;\n  pulseRef: React.RefObject<{ active: boolean; type: PulseType; startTime: number }>;\n  modeRef: React.RefObject<LiquidOrbMode>;\n  quality: QualityTier;\n  qualityConfig: QualityConfig;\n  config: LiquidOrbConfig;\n}\n","export function clamp(value: number, min: number, max: number): number {\n  return Math.min(Math.max(value, min), max);\n}\n\nexport function lerp(a: number, b: number, t: number): number {\n  return a + (b - a) * t;\n}\n\n/**\n * Exponential moving average — used for attack/release envelope smoothing.\n * `factor` is in 0..1 range: higher = faster response.\n */\nexport function ema(current: number, target: number, factor: number): number {\n  return current + (target - current) * factor;\n}\n","import { useRef } from 'react';\nimport { useFrame } from '@react-three/fiber';\nimport type { AudioFrame } from '../context/types.js';\nimport { ema } from '../utils/math.js';\n\ninterface SmoothedAudio {\n  low: number;\n  mid: number;\n  high: number;\n  volume: number;\n}\n\n/**\n * Smooths raw audio frame data with attack/release EMA in the useFrame loop.\n * Returns a ref to the smoothed values — read in the render loop only.\n *\n * When raw frame is silent, smoothed values decay via release EMA toward zero\n * (no snap-to-zero — avoids visible jerk when audio stops).\n * Values below EPSILON are floored to zero to prevent infinite tail.\n */\nexport function useAudioEnvelope(\n  rawFrameRef: React.RefObject<AudioFrame>,\n  attack = 0.05,\n  release = 0.03,\n): React.RefObject<SmoothedAudio> {\n  const smoothedRef = useRef<SmoothedAudio>({ low: 0, mid: 0, high: 0, volume: 0 });\n\n  useFrame(() => {\n    const raw = rawFrameRef.current;\n    const s = smoothedRef.current;\n    if (!raw || !s) return;\n\n    const keys = ['low', 'mid', 'high', 'volume'] as const;\n    for (const key of keys) {\n      const target = raw[key];\n      const current = s[key];\n      const factor = target > current ? attack : release;\n      const next = ema(current, target, factor);\n      s[key] = next < 0.001 ? 0 : next;\n    }\n  });\n\n  return smoothedRef;\n}\n","import type { LiquidOrbConfig, LiquidOrbMode, OrbParams } from './context/types.js';\n\n// ── Default mode presets ──────────────────────────────────────────────────────\n\nexport const DEFAULT_PRESETS: Record<LiquidOrbMode, OrbParams> = {\n  idle: {\n    noiseFrequency: 0.8,\n    noiseAmplitude: 0.03,\n    noiseSpeed: 0.2,\n    breathSpeed: 0.6,\n    breathAmplitude: 0.015,\n    distortion: 0,\n    color1: '#4a9eff',\n    color2: '#8b5cf6',\n    emissiveIntensity: 0.3,\n    glowOpacity: 0.4,\n    glowScale: 1.5,\n    iridescence: 0.2,\n  },\n  listening: {\n    noiseFrequency: 0.95,     // frequency 0.95\n    noiseAmplitude: 0.05,     // more movement (was 0.03)\n    noiseSpeed: 0.3,          // faster (was 0.22)\n    breathSpeed: 0.8,         // faster breath (was 0.65)\n    breathAmplitude: 0.025,   // bigger breath (was 0.016)\n    distortion: 0.005,        // slight distortion (was 0)\n    color1: '#22d3ee',\n    color2: '#6366f1',\n    emissiveIntensity: 0.45,  // brighter (was 0.35)\n    glowOpacity: 0.55,        // more glow (was 0.45)\n    glowScale: 1.6,           // bigger glow (was 1.52)\n    iridescence: 0.35,        // more iridescence (was 0.25)\n  },\n  thinking: {\n    noiseFrequency: 0.9,\n    noiseAmplitude: 0.032,\n    noiseSpeed: 0.28,\n    breathSpeed: 0.7,\n    breathAmplitude: 0.013,\n    distortion: 0.003,\n    color1: '#a78bfa',\n    color2: '#f472b6',\n    emissiveIntensity: 0.4,\n    glowOpacity: 0.5,\n    glowScale: 1.55,\n    iridescence: 0.3,\n  },\n  speaking: {\n    noiseFrequency: 0.85,\n    noiseAmplitude: 0.03,\n    noiseSpeed: 0.22,\n    breathSpeed: 0.65,\n    breathAmplitude: 0.016,\n    distortion: 0.001,\n    color1: '#34d399',\n    color2: '#3b82f6',\n    emissiveIntensity: 0.35,\n    glowOpacity: 0.45,\n    glowScale: 1.52,\n    iridescence: 0.25,\n  },\n};\n\nexport function mergePresets(config: LiquidOrbConfig): Record<LiquidOrbMode, OrbParams> {\n  if (!config.presets) return DEFAULT_PRESETS;\n  const result = { ...DEFAULT_PRESETS };\n  for (const mode of Object.keys(config.presets) as LiquidOrbMode[]) {\n    const override = config.presets[mode];\n    if (override) {\n      result[mode] = { ...DEFAULT_PRESETS[mode], ...override };\n    }\n  }\n  return result;\n}\n","import { useMemo } from 'react';\nimport { useFrame } from '@react-three/fiber';\nimport * as THREE from 'three';\nimport type { LiquidOrbConfig, LiquidOrbMode, OrbParams } from '../context/types.js';\nimport { lerp } from '../utils/math.js';\nimport { mergePresets } from '../presets.js';\n\nexport function useOrbController(\n  modeRef: React.RefObject<LiquidOrbMode>,\n  paramsRef: React.RefObject<OrbParams>,\n  config: LiquidOrbConfig = {},\n): void {\n  // Persistent Color objects — avoids hex→Color→hex round-trip jitter\n  const colors = useMemo(() => ({\n    c1: new THREE.Color('#4a9eff'),\n    c2: new THREE.Color('#8b5cf6'),\n    target1: new THREE.Color(),\n    target2: new THREE.Color(),\n  }), []);\n\n  const presets = useMemo(() => mergePresets(config), [config]);\n  const lerpSpeed = config.lerpSpeed ?? 3.0; // per-second rate (frame-rate independent)\n\n  useFrame((_state, delta) => {\n    const params = paramsRef.current;\n    if (!params) return;\n\n    const target = presets[modeRef.current];\n\n    // Frame-rate independent lerp: 1 - e^(-speed * dt)\n    const t = 1 - Math.exp(-lerpSpeed * delta);\n\n    params.noiseFrequency = lerp(params.noiseFrequency, target.noiseFrequency, t);\n    params.noiseAmplitude = lerp(params.noiseAmplitude, target.noiseAmplitude, t);\n    params.noiseSpeed = lerp(params.noiseSpeed, target.noiseSpeed, t);\n    params.breathSpeed = lerp(params.breathSpeed, target.breathSpeed, t);\n    params.breathAmplitude = lerp(params.breathAmplitude, target.breathAmplitude, t);\n    params.distortion = lerp(params.distortion, target.distortion, t);\n    params.emissiveIntensity = lerp(params.emissiveIntensity, target.emissiveIntensity, t);\n    params.glowOpacity = lerp(params.glowOpacity, target.glowOpacity, t);\n    params.glowScale = lerp(params.glowScale, target.glowScale, t);\n    params.iridescence = lerp(params.iridescence, target.iridescence, t);\n\n    // Lerp colors as Color objects — write to _color1/_color2 for GPU, skip hex encode\n    colors.target1.set(target.color1);\n    colors.target2.set(target.color2);\n    colors.c1.lerp(colors.target1, t);\n    colors.c2.lerp(colors.target2, t);\n\n    if (params._color1) params._color1.copy(colors.c1);\n    if (params._color2) params._color2.copy(colors.c2);\n  });\n}\n","import { useEffect, useMemo } from 'react';\nimport { useFrame } from '@react-three/fiber';\nimport * as THREE from 'three';\nimport type { AudioReactivityConfig, LiquidOrbConfig, OrbParams, PulseType } from '../context/types.js';\nimport { DEFAULT_AUDIO_REACTIVITY } from '../context/types.js';\nimport { clamp } from '../utils/math.js';\n\nconst PULSE_COLORS: Record<string, string> = {\n  success: '#34d399',\n  error: '#ef4444',\n  info: '#60a5fa',\n};\n\ninterface OrbUniformValues {\n  [key: string]: { value: unknown };\n  uTime: { value: number };\n  uNoiseFrequency: { value: number };\n  uNoiseAmplitude: { value: number };\n  uNoiseSpeed: { value: number };\n  uBreathSpeed: { value: number };\n  uBreathAmplitude: { value: number };\n  uDistortion: { value: number };\n  uPulse: { value: number };\n  uMatcap: { value: THREE.Texture };\n  uColor1: { value: THREE.Color };\n  uColor2: { value: THREE.Color };\n  uEmissiveIntensity: { value: number };\n  uIridescence: { value: number };\n}\n\ninterface SmoothedAudio {\n  low: number;\n  mid: number;\n  high: number;\n  volume: number;\n}\n\ninterface PulseState {\n  active: boolean;\n  type: PulseType;\n  startTime: number;\n}\n\n/**\n * Creates orb shader uniforms and drives them each frame from\n * params (mode lerp), smoothed audio data and pulse state.\n */\nexport function useOrbUniforms(\n  matcapTexture: THREE.Texture,\n  paramsRef: React.RefObject<OrbParams>,\n  smoothedAudioRef: React.RefObject<SmoothedAudio>,\n  pulseRef: React.RefObject<PulseState>,\n  pulseValueRef: React.RefObject<number>,\n  config: LiquidOrbConfig,\n): OrbUniformValues {\n  const d = DEFAULT_AUDIO_REACTIVITY;\n  const ar = config.audioReactivity;\n  const lowGain = ar?.lowGain ?? d.lowGain;\n  const midGain = ar?.midGain ?? d.midGain;\n  const highGain = ar?.highGain ?? d.highGain;\n  const volumeGain = ar?.volumeGain ?? d.volumeGain;\n  const emissiveGain = ar?.emissiveGain ?? d.emissiveGain;\n\n  const scratch = useMemo(() => ({\n    c1: new THREE.Color(),\n    c2: new THREE.Color(),\n  }), []);\n\n  // Create uniforms once — never recreate the object.\n  // matcapTexture is updated via useEffect below so the shader\n  // always uses the latest loaded texture without remounting.\n  const uniforms = useMemo<OrbUniformValues>(\n    () => ({\n      uTime: { value: 0 },\n      uNoiseFrequency: { value: 0.8 },\n      uNoiseAmplitude: { value: 0.03 },\n      uNoiseSpeed: { value: 0.2 },\n      uBreathSpeed: { value: 0.6 },\n      uBreathAmplitude: { value: 0.015 },\n      uDistortion: { value: 0 },\n      uPulse: { value: 0 },\n      uMatcap: { value: matcapTexture },\n      uColor1: { value: new THREE.Color('#4a9eff') },\n      uColor2: { value: new THREE.Color('#8b5cf6') },\n      uEmissiveIntensity: { value: 0.3 },\n      uIridescence: { value: 0.2 },\n    }),\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    [],\n  );\n\n  // Sync matcap texture into the existing uniform when it loads/changes\n  useEffect(() => {\n    if (matcapTexture) {\n      uniforms.uMatcap.value = matcapTexture;\n    }\n  }, [matcapTexture, uniforms]);\n\n  useFrame((state) => {\n    const params = paramsRef.current;\n    const audio = smoothedAudioRef.current;\n    const pulse = pulseRef.current;\n    if (!params || !audio) return;\n\n    const time = state.clock.elapsedTime;\n\n    // Audio-reactive additive values (clamped to safe ranges)\n    const audioNoiseAmp = clamp(params.noiseAmplitude + audio.low * lowGain + audio.mid * midGain, 0, 0.06);\n    const audioSpeed = clamp(params.noiseSpeed + audio.volume * volumeGain, 0, 0.45);\n    const audioDistortion = clamp(params.distortion + audio.high * highGain, 0, 0.025);\n\n    // Pulse value computed by usePulseValue hook\n    const pulseValue = pulseValueRef.current ?? 0;\n\n    // Write uniforms\n    uniforms.uTime.value = time;\n    uniforms.uNoiseFrequency.value = params.noiseFrequency;\n    uniforms.uNoiseAmplitude.value = audioNoiseAmp;\n    uniforms.uNoiseSpeed.value = audioSpeed;\n    uniforms.uBreathSpeed.value = params.breathSpeed;\n    uniforms.uBreathAmplitude.value = params.breathAmplitude;\n    uniforms.uDistortion.value = audioDistortion;\n    uniforms.uPulse.value = pulseValue;\n    uniforms.uEmissiveIntensity.value = clamp(params.emissiveIntensity + audio.volume * emissiveGain, 0, 1.2);\n    uniforms.uIridescence.value = params.iridescence;\n\n    // Colors — read pre-interpolated Color objects when available (no hex parse per frame)\n    if (pulse && pulse.active && PULSE_COLORS[pulse.type]) {\n      scratch.c1.set(PULSE_COLORS[pulse.type]!);\n      uniforms.uColor1.value.lerp(scratch.c1, 0.3);\n    } else if (params._color1) {\n      uniforms.uColor1.value.copy(params._color1);\n    } else {\n      scratch.c1.set(params.color1);\n      uniforms.uColor1.value.copy(scratch.c1);\n    }\n    if (params._color2) {\n      uniforms.uColor2.value.copy(params._color2);\n    } else {\n      scratch.c2.set(params.color2);\n      uniforms.uColor2.value.copy(scratch.c2);\n    }\n  });\n\n  return uniforms;\n}\n","import { useRef } from 'react';\nimport { useFrame } from '@react-three/fiber';\nimport type { PulseType } from '../context/types.js';\n\nconst PULSE_DURATION = 400;\n\ninterface PulseState {\n  active: boolean;\n  type: PulseType;\n  startTime: number;\n}\n\nexport function usePulseValue(\n  pulseRef: React.RefObject<PulseState>,\n): React.RefObject<number> {\n  const valueRef = useRef(0);\n\n  useFrame(() => {\n    const pulse = pulseRef.current;\n    if (!pulse || !pulse.active) {\n      valueRef.current = 0;\n      return;\n    }\n    const elapsed = performance.now() - pulse.startTime;\n    if (elapsed < PULSE_DURATION) {\n      const t = elapsed / PULSE_DURATION;\n      valueRef.current = Math.sin(t * Math.PI) * 0.15;\n    } else {\n      pulse.active = false;\n      valueRef.current = 0;\n    }\n  });\n\n  return valueRef;\n}\n","/**\n * Ashima Arts 3D Simplex Noise — GLSL string.\n * https://github.com/ashima/webgl-noise\n * MIT License.\n */\nexport const simplex3d = /* glsl */ `\nvec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }\nvec4 mod289(vec4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }\nvec4 permute(vec4 x) { return mod289(((x * 34.0) + 10.0) * x); }\nvec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }\n\nfloat snoise(vec3 v) {\n  const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);\n  const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n  // First corner\n  vec3 i  = floor(v + dot(v, C.yyy));\n  vec3 x0 = v - i + dot(i, C.xxx);\n\n  // Other corners\n  vec3 g = step(x0.yzx, x0.xyz);\n  vec3 l = 1.0 - g;\n  vec3 i1 = min(g.xyz, l.zxy);\n  vec3 i2 = max(g.xyz, l.zxy);\n\n  vec3 x1 = x0 - i1 + C.xxx;\n  vec3 x2 = x0 - i2 + C.yyy;\n  vec3 x3 = x0 - D.yyy;\n\n  // Permutations\n  i = mod289(i);\n  vec4 p = permute(permute(permute(\n    i.z + vec4(0.0, i1.z, i2.z, 1.0))\n  + i.y + vec4(0.0, i1.y, i2.y, 1.0))\n  + i.x + vec4(0.0, i1.x, i2.x, 1.0));\n\n  // Gradients: 7x7 points over a square, mapped onto an octahedron\n  float n_ = 0.142857142857; // 1.0/7.0\n  vec3 ns = n_ * D.wyz - D.xzx;\n\n  vec4 j = p - 49.0 * floor(p * ns.z * ns.z);\n\n  vec4 x_ = floor(j * ns.z);\n  vec4 y_ = floor(j - 7.0 * x_);\n\n  vec4 x = x_ * ns.x + ns.yyyy;\n  vec4 y = y_ * ns.x + ns.yyyy;\n  vec4 h = 1.0 - abs(x) - abs(y);\n\n  vec4 b0 = vec4(x.xy, y.xy);\n  vec4 b1 = vec4(x.zw, y.zw);\n\n  vec4 s0 = floor(b0) * 2.0 + 1.0;\n  vec4 s1 = floor(b1) * 2.0 + 1.0;\n  vec4 sh = -step(h, vec4(0.0));\n\n  vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;\n  vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;\n\n  vec3 p0 = vec3(a0.xy, h.x);\n  vec3 p1 = vec3(a0.zw, h.y);\n  vec3 p2 = vec3(a1.xy, h.z);\n  vec3 p3 = vec3(a1.zw, h.w);\n\n  // Normalise gradients\n  vec4 norm = taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));\n  p0 *= norm.x;\n  p1 *= norm.y;\n  p2 *= norm.z;\n  p3 *= norm.w;\n\n  // Mix final noise value\n  vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);\n  m = m * m;\n  return 42.0 * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));\n}\n`;\n","import { simplex3d } from './simplex3d.js';\n\nexport const orbVertex = /* glsl */ `\n${simplex3d}\n\nuniform float uTime;\nuniform float uNoiseFrequency;\nuniform float uNoiseAmplitude;\nuniform float uNoiseSpeed;\nuniform float uBreathSpeed;\nuniform float uBreathAmplitude;\nuniform float uDistortion;\nuniform float uPulse;\n\nvarying vec3 vNormal;\nvarying vec3 vViewPosition;\nvarying vec2 vUv;\nvarying float vDisplacement;\n\nfloat getDisplacement(vec3 p) {\n  float n1 = snoise(p * uNoiseFrequency + uTime * uNoiseSpeed);\n  float n2 = snoise(p * uNoiseFrequency * 2.0 + uTime * uNoiseSpeed * 0.7) * 0.5;\n  float breath = sin(uTime * uBreathSpeed) * uBreathAmplitude;\n  return (n1 + n2) * uNoiseAmplitude + breath + uDistortion + uPulse;\n}\n\nvoid main() {\n  vUv = uv;\n\n  float displacement = getDisplacement(position);\n  vDisplacement = displacement;\n\n  vec3 newPosition = position + normal * displacement;\n\n  // Compute displaced normal via finite differences\n  float eps = 0.001;\n  vec3 tangent = normalize(cross(normal, vec3(0.0, 1.0, 0.0)));\n  // Handle poles where normal is parallel to up\n  if (length(cross(normal, vec3(0.0, 1.0, 0.0))) < 0.001) {\n    tangent = normalize(cross(normal, vec3(1.0, 0.0, 0.0)));\n  }\n  vec3 bitangent = normalize(cross(normal, tangent));\n\n  vec3 posT = position + tangent * eps;\n  vec3 posB = position + bitangent * eps;\n\n  vec3 displacedT = posT + normal * getDisplacement(posT);\n  vec3 displacedB = posB + normal * getDisplacement(posB);\n\n  vec3 displacedNormal = normalize(cross(displacedT - newPosition, displacedB - newPosition));\n\n  vNormal = normalize(normalMatrix * displacedNormal);\n  vec4 mvPosition = modelViewMatrix * vec4(newPosition, 1.0);\n  vViewPosition = -mvPosition.xyz;\n\n  gl_Position = projectionMatrix * mvPosition;\n}\n`;\n","export const orbFragment = /* glsl */ `\nuniform sampler2D uMatcap;\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform float uEmissiveIntensity;\nuniform float uIridescence;\nuniform float uTime;\n\nvarying vec3 vNormal;\nvarying vec3 vViewPosition;\nvarying vec2 vUv;\nvarying float vDisplacement;\n\nvoid main() {\n  // Matcap UV from view-space normal\n  vec3 viewNormal = normalize(vNormal);\n  vec2 matcapUv = viewNormal.xy * 0.5 + 0.5;\n  vec4 matcapColor = texture2D(uMatcap, matcapUv);\n\n  // Fresnel term\n  vec3 viewDir = normalize(vViewPosition);\n  float fresnel = 1.0 - abs(dot(viewDir, viewNormal));\n  fresnel = pow(fresnel, 3.0);\n\n  // Base color blend driven by displacement\n  float colorMix = smoothstep(-0.1, 0.2, vDisplacement);\n  vec3 baseColor = mix(uColor1, uColor2, colorMix);\n\n  // Chameleon iridescence shift on Fresnel edges\n  vec3 iridescentShift = vec3(\n    sin(fresnel * 6.2831 + uTime * 0.5) * 0.5 + 0.5,\n    sin(fresnel * 6.2831 + uTime * 0.5 + 2.094) * 0.5 + 0.5,\n    sin(fresnel * 6.2831 + uTime * 0.5 + 4.189) * 0.5 + 0.5\n  );\n  baseColor = mix(baseColor, iridescentShift, fresnel * uIridescence);\n\n  // Combine with matcap\n  vec3 finalColor = baseColor * matcapColor.rgb;\n\n  // Rim emissive glow\n  finalColor += baseColor * fresnel * uEmissiveIntensity;\n\n  gl_FragColor = vec4(finalColor, 1.0);\n}\n`;\n","import React, { useRef, useEffect, useMemo } from 'react';\nimport { useTexture } from '@react-three/drei';\nimport * as THREE from 'three';\nimport { useLiquidOrbInternal } from './context/liquidOrbContext.js';\nimport { DEFAULT_AUDIO_REACTIVITY } from './context/types.js';\nimport { useAudioEnvelope } from './hooks/useAudioEnvelope.js';\nimport { useOrbController } from './hooks/useOrbController.js';\nimport { useOrbUniforms } from './hooks/useOrbUniforms.js';\nimport { usePulseValue } from './hooks/usePulseValue.js';\nimport { orbVertex } from './shaders/orbVertex.js';\nimport { orbFragment } from './shaders/orbFragment.js';\nimport matcapUrl from './assets/matcap.png';\n\nexport function LiquidOrbScene() {\n  // Read mode from ref (via internal context) to avoid re-renders\n  // when mode changes. useOrbController reads modeRef per-frame.\n  const { audioFrameRef, paramsRef, pulseRef, modeRef, qualityConfig, config } = useLiquidOrbInternal();\n\n  const d = DEFAULT_AUDIO_REACTIVITY;\n  const ar = config.audioReactivity;\n  const smoothAttack = ar?.smoothAttack ?? d.smoothAttack;\n  const smoothRelease = ar?.smoothRelease ?? d.smoothRelease;\n\n  const smoothedAudio = useAudioEnvelope(audioFrameRef, smoothAttack, smoothRelease);\n\n  useOrbController(modeRef, paramsRef, config);\n\n  const pulseValueRef = usePulseValue(pulseRef);\n\n  const matcapTexture = useTexture(matcapUrl);\n  const orbUniforms = useOrbUniforms(matcapTexture, paramsRef, smoothedAudio, pulseRef, pulseValueRef, config);\n\n  // Create material once imperatively to prevent R3F reconciler\n  // from overwriting uniforms on re-render (which causes the black orb bug).\n  const matRef = useRef<THREE.ShaderMaterial | null>(null);\n  const material = useMemo(\n    () => new THREE.ShaderMaterial({\n      vertexShader: orbVertex,\n      fragmentShader: orbFragment,\n      uniforms: orbUniforms,\n    }),\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    [],\n  );\n  matRef.current = material;\n\n  // Keep uniforms reference in sync (object identity is stable from useOrbUniforms)\n  useEffect(() => {\n    material.uniforms = orbUniforms;\n  }, [material, orbUniforms]);\n\n  return (\n    <mesh material={material}>\n      <sphereGeometry args={[1, qualityConfig.segments, qualityConfig.segments]} />\n    </mesh>\n  );\n}\n","import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Canvas, useFrame } from '@react-three/fiber';\nimport type { LiquidOrbMode, QualityConfig } from './context/types.js';\nimport { LiquidOrbScene } from './LiquidOrbScene.js';\n\ninterface LiquidOrbCanvasProps {\n  qualityConfig: QualityConfig;\n  mode: LiquidOrbMode;\n  size?: number;\n  className?: string;\n}\n\nconst GLOW_COLORS: Record<LiquidOrbMode, string> = {\n  idle: '#4a9eff',\n  listening: '#22d3ee',\n  thinking: '#a78bfa',\n  speaking: '#34d399',\n};\n\nconst GLOW_KEYFRAMES = `\n@keyframes orbGlow {\n  0%, 100% { opacity: 0.7; transform: translate(-50%, -50%) scale(0.97); }\n  50% { opacity: 1; transform: translate(-50%, -50%) scale(1.03); }\n}`;\n\n// Inject keyframes once globally, not per component mount\nlet styleInjected = false;\nfunction ensureGlowStyle() {\n  if (styleInjected) return;\n  styleInjected = true;\n  const style = document.createElement('style');\n  style.textContent = GLOW_KEYFRAMES;\n  document.head.appendChild(style);\n}\n\nconst CAMERA = { position: [0, 0, 3.5] as const, fov: 45 };\nconst CANVAS_STYLE = { background: 'transparent' } as const;\n\n/** Fires onReady after the first rendered frame */\nfunction ReadySignal({ onReady }: { onReady: () => void }) {\n  const fired = useRef(false);\n  useFrame(() => {\n    if (!fired.current) {\n      fired.current = true;\n      onReady();\n    }\n  });\n  return null;\n}\n\nexport function LiquidOrbCanvas({ qualityConfig, mode, size = 300, className }: LiquidOrbCanvasProps) {\n  ensureGlowStyle();\n\n  const [ready, setReady] = useState(false);\n  const [glowVisible, setGlowVisible] = useState(false);\n\n  const handleReady = useCallback(() => {\n    requestAnimationFrame(() => setReady(true));\n  }, []);\n\n  useEffect(() => {\n    if (!ready) return;\n    const t = setTimeout(() => setGlowVisible(true), 1700);\n    return () => clearTimeout(t);\n  }, [ready]);\n\n  // Pre-compute styles\n  const glowColor = GLOW_COLORS[mode];\n  const g = Math.round(size * 0.2);\n  const orbVisualSize = size * 0.55;\n\n  const containerStyle = useMemo(() => ({\n    width: size,\n    height: size,\n    position: 'relative' as const,\n  }), [size]);\n\n  const glowStyle = useMemo(() => ({\n    position: 'absolute' as const,\n    width: orbVisualSize,\n    height: orbVisualSize,\n    top: '50%',\n    left: '50%',\n    transform: 'translate(-50%, -50%)',\n    borderRadius: '50%',\n    background: 'transparent',\n    boxShadow: [\n      `0 0 ${g}px ${g / 2}px ${glowColor}50`,\n      `0 0 ${g * 2}px ${g}px ${glowColor}30`,\n      `0 0 ${g * 3}px ${g * 1.5}px ${glowColor}15`,\n    ].join(', '),\n    transition: 'box-shadow 0.8s ease, opacity 1.5s ease-in',\n    animation: glowVisible ? 'orbGlow 3s ease-in-out infinite' : 'none',\n    pointerEvents: 'none' as const,\n    zIndex: 0,\n    opacity: glowVisible ? 1 : 0,\n  }), [orbVisualSize, g, glowColor, glowVisible]);\n\n  const canvasWrapperStyle = useMemo(() => ({\n    position: 'absolute' as const,\n    inset: 0,\n    zIndex: 1,\n    opacity: ready ? 1 : 0,\n    transition: 'opacity 1.5s ease-in',\n  }), [ready]);\n\n  const canvasKey = `${qualityConfig.dpr}-${qualityConfig.antialias}`;\n\n  const glConfig = useMemo(() => ({\n    antialias: qualityConfig.antialias,\n    alpha: true,\n    powerPreference: 'high-performance' as const,\n  }), [qualityConfig.antialias]);\n\n  return (\n    <div style={containerStyle} className={className}>\n      <div style={glowStyle} />\n      <div style={canvasWrapperStyle}>\n        <Canvas\n          key={canvasKey}\n          dpr={qualityConfig.dpr}\n          camera={CAMERA}\n          gl={glConfig}\n          style={CANVAS_STYLE}\n        >\n          <LiquidOrbScene />\n          <ReadySignal onReady={handleReady} />\n        </Canvas>\n      </div>\n    </div>\n  );\n}\n","import React, { Suspense, useContext, useMemo } from 'react';\nimport type { LiquidOrbProps, QualityConfig } from './context/types.js';\nimport { LiquidOrbContext } from './context/liquidOrbContext.js';\nimport { useLiquidOrb } from './context/liquidOrbContext.js';\nimport { LiquidOrbProvider } from './context/LiquidOrbProvider.js';\nimport { LiquidOrbCanvas } from './LiquidOrbCanvas.js';\n\nconst DEFAULT_QUALITY: QualityConfig = { dpr: 2, segments: 128, antialias: true };\n\nfunction LiquidOrbInner({ size = 300, className, children }: Pick<LiquidOrbProps, 'size' | 'className' | 'children'>) {\n  const { mode } = useLiquidOrb();\n  return (\n    <>\n      <LiquidOrbCanvas\n        qualityConfig={DEFAULT_QUALITY}\n        mode={mode}\n        size={size}\n        className={className}\n      />\n      {children}\n    </>\n  );\n}\n\nexport function LiquidOrb({\n  mode = 'idle',\n  audioSource,\n  size = 300,\n  config,\n  className,\n  children,\n}: LiquidOrbProps) {\n  const existingCtx = useContext(LiquidOrbContext);\n  const fallbackStyle = useMemo(() => ({ width: size, height: size }), [size]);\n\n  const inner = (\n    <Suspense fallback={<div style={fallbackStyle} />}>\n      <LiquidOrbInner size={size} className={className}>{children}</LiquidOrbInner>\n    </Suspense>\n  );\n\n  if (existingCtx) return inner;\n\n  return (\n    <LiquidOrbProvider mode={mode} audioSource={audioSource} config={config}>\n      {inner}\n    </LiquidOrbProvider>\n  );\n}\n","/**\n * useStreamingSTT — React hook for server-side streaming speech-to-text.\n *\n * Captures raw PCM audio from the microphone via AudioContext + ScriptProcessor,\n * streams it over a WebSocket to the audio_service, and receives interim/final\n * transcription results in real-time.\n */\n\nimport { useCallback, useRef, useState } from 'react';\nimport type { SDKRouterClient } from '@sdkrouter/client';\nimport type { TranscriptionStream } from '@sdkrouter/client';\nimport type { RecorderStatus, MicAudioFrame } from './useSpeechRecorder.js';\n\nexport interface UseStreamingSTTOptions {\n  client: SDKRouterClient;\n  model?: string;\n  language?: string;\n  silenceTimeout?: number;\n  silenceThreshold?: number;\n  onInterim?: (text: string) => void;\n  onResult?: (text: string) => void;\n  onError?: (error: Error) => void;\n  onAudioFrame?: (frame: MicAudioFrame) => void;\n}\n\nexport interface UseStreamingSTTReturn {\n  startRecording: () => Promise<void>;\n  stopRecording: () => void;\n  isRecording: boolean;\n  status: RecorderStatus;\n}\n\n// ── Audio bands computation (inlined to avoid cross-package import) ──────────\n\nfunction computeMicBands(frequencyData: Uint8Array, out: MicAudioFrame): void {\n  const len = frequencyData.length;\n  if (len === 0) {\n    out.low = 0; out.mid = 0; out.high = 0; out.volume = 0;\n    return;\n  }\n\n  const lowEnd = Math.min(11, len);\n  const midEnd = Math.min(81, len);\n  const highEnd = Math.min(256, len);\n\n  let lowSum = 0, midSum = 0, highSum = 0, totalSum = 0;\n\n  for (let i = 0; i < lowEnd; i++) lowSum += frequencyData[i]!;\n  for (let i = lowEnd; i < midEnd; i++) midSum += frequencyData[i]!;\n  for (let i = midEnd; i < highEnd; i++) highSum += frequencyData[i]!;\n  for (let i = 0; i < len; i++) totalSum += frequencyData[i]!;\n\n  out.low = lowSum / (lowEnd * 255);\n  out.mid = midEnd > lowEnd ? midSum / ((midEnd - lowEnd) * 255) : 0;\n  out.high = highEnd > midEnd ? highSum / ((highEnd - midEnd) * 255) : 0;\n  out.volume = totalSum / (len * 255);\n}\n\n// ── Float32 → Int16 PCM conversion ──────────────────────────────────────────\n\nfunction float32ToInt16(float32: Float32Array): Int16Array {\n  const int16 = new Int16Array(float32.length);\n  for (let i = 0; i < float32.length; i++) {\n    const s = Math.max(-1, Math.min(1, float32[i]!));\n    int16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;\n  }\n  return int16;\n}\n\n// ── Hook ─────────────────────────────────────────────────────────────────────\n\nexport function useStreamingSTT(options: UseStreamingSTTOptions): UseStreamingSTTReturn {\n  const {\n    client,\n    model = 'whisper-1',\n    language,\n    silenceTimeout = 0,\n    silenceThreshold = 0.01,\n    onInterim,\n    onResult,\n    onError,\n    onAudioFrame,\n  } = options;\n\n  const [status, setStatus] = useState<RecorderStatus>('idle');\n\n  // Refs for cleanup\n  const audioCtxRef = useRef<AudioContext | null>(null);\n  const streamRef = useRef<MediaStream | null>(null);\n  const wsStreamRef = useRef<TranscriptionStream | null>(null);\n  const processorRef = useRef<ScriptProcessorNode | null>(null);\n  const rafRef = useRef<number>(0);\n\n  // Stable refs for callbacks\n  const onInterimRef = useRef(onInterim);\n  onInterimRef.current = onInterim;\n  const onResultRef = useRef(onResult);\n  onResultRef.current = onResult;\n  const onErrorRef = useRef(onError);\n  onErrorRef.current = onError;\n  const onAudioFrameRef = useRef(onAudioFrame);\n  onAudioFrameRef.current = onAudioFrame;\n\n  const cleanup = useCallback(() => {\n    cancelAnimationFrame(rafRef.current);\n    rafRef.current = 0;\n\n    if (processorRef.current) {\n      processorRef.current.disconnect();\n      processorRef.current = null;\n    }\n\n    if (audioCtxRef.current) {\n      audioCtxRef.current.close();\n      audioCtxRef.current = null;\n    }\n\n    if (streamRef.current) {\n      streamRef.current.getTracks().forEach((t) => t.stop());\n      streamRef.current = null;\n    }\n\n    if (wsStreamRef.current) {\n      wsStreamRef.current.close();\n      wsStreamRef.current = null;\n    }\n  }, []);\n\n  const startRecording = useCallback(async () => {\n    setStatus('idle');\n\n    try {\n      // 1. Get microphone stream\n      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n      streamRef.current = stream;\n\n      // 2. Set up AudioContext at 16kHz for efficient streaming\n      const audioCtx = new AudioContext({ sampleRate: 16000 });\n      audioCtxRef.current = audioCtx;\n      const source = audioCtx.createMediaStreamSource(stream);\n\n      // 3. Open WebSocket stream\n      const wsStream = client.audio.transcribeStream(\n        { model, language, sampleRate: 16000 },\n        {\n          onReady: () => {\n            setStatus('recording');\n          },\n          onInterim: (text) => {\n            onInterimRef.current?.(text);\n          },\n          onFinal: (text) => {\n            setStatus('idle');\n            cleanup();\n            onResultRef.current?.(text);\n          },\n          onError: (err) => {\n            setStatus('error');\n            cleanup();\n            onErrorRef.current?.(err);\n          },\n          onClose: () => {\n            // Only set idle if we haven't already transitioned\n            setStatus((prev) => (prev === 'recording' ? 'idle' : prev));\n          },\n        },\n      );\n      wsStreamRef.current = wsStream;\n\n      // 4. ScriptProcessor to capture raw PCM and send over WebSocket\n      // bufferSize 4096 at 16kHz = 256ms chunks\n      const processor = audioCtx.createScriptProcessor(4096, 1, 1);\n      processorRef.current = processor;\n\n      processor.onaudioprocess = (e) => {\n        const float32 = e.inputBuffer.getChannelData(0);\n        const int16 = float32ToInt16(float32);\n        wsStream.sendAudio(int16.buffer.slice(0) as ArrayBuffer);\n      };\n\n      source.connect(processor);\n      processor.connect(audioCtx.destination); // required for processing to fire\n\n      // 5. Audio analysis for silence detection + frame emission\n      const needsAnalyser = silenceTimeout > 0 || onAudioFrameRef.current;\n      if (needsAnalyser) {\n        const analyser = audioCtx.createAnalyser();\n        analyser.fftSize = 2048;\n        source.connect(analyser);\n\n        const timeDomainData = new Uint8Array(analyser.fftSize);\n        const frequencyData = new Uint8Array(analyser.frequencyBinCount);\n        const frameOut: MicAudioFrame = { low: 0, mid: 0, high: 0, volume: 0 };\n        let silenceStart = 0;\n\n        const tick = () => {\n          if (!wsStreamRef.current || wsStreamRef.current.state === 'closed') return;\n\n          // Silence detection\n          if (silenceTimeout > 0) {\n            analyser.getByteTimeDomainData(timeDomainData);\n            let sumSquares = 0;\n            for (let i = 0; i < timeDomainData.length; i++) {\n              const normalized = (timeDomainData[i]! - 128) / 128;\n              sumSquares += normalized * normalized;\n            }\n            const rms = Math.sqrt(sumSquares / timeDomainData.length);\n\n            const now = Date.now();\n            if (rms < silenceThreshold) {\n              if (silenceStart === 0) silenceStart = now;\n              if (now - silenceStart >= silenceTimeout) {\n                wsStreamRef.current?.stop();\n                return;\n              }\n            } else {\n              silenceStart = 0;\n            }\n          }\n\n          // Audio frame emission\n          if (onAudioFrameRef.current) {\n            analyser.getByteFrequencyData(frequencyData);\n            computeMicBands(frequencyData, frameOut);\n            onAudioFrameRef.current(frameOut);\n          }\n\n          rafRef.current = requestAnimationFrame(tick);\n        };\n\n        rafRef.current = requestAnimationFrame(tick);\n      }\n    } catch (err) {\n      cleanup();\n      const e = err instanceof Error ? err : new Error(String(err));\n      setStatus('error');\n      onErrorRef.current?.(e);\n    }\n  }, [client, model, language, silenceTimeout, silenceThreshold, cleanup]);\n\n  const stopRecording = useCallback(() => {\n    const wsStream = wsStreamRef.current;\n    if (wsStream && wsStream.state !== 'closed' && wsStream.state !== 'finalizing') {\n      setStatus('transcribing');\n      wsStream.stop(); // triggers final transcription on server\n    }\n    // Cleanup mic + audio context, but keep WS open for final result\n    cancelAnimationFrame(rafRef.current);\n    rafRef.current = 0;\n    if (processorRef.current) {\n      processorRef.current.disconnect();\n      processorRef.current = null;\n    }\n    if (audioCtxRef.current) {\n      audioCtxRef.current.close();\n      audioCtxRef.current = null;\n    }\n    if (streamRef.current) {\n      streamRef.current.getTracks().forEach((t) => t.stop());\n      streamRef.current = null;\n    }\n  }, []);\n\n  return {\n    startRecording,\n    stopRecording,\n    isRecording: status === 'recording',\n    status,\n  };\n}\n","/**\n * useVAD — Professional Voice Activity Detection hook\n *\n * Features:\n * - Adaptive noise floor detection (auto-calibrates to background noise)\n * - Speech onset detection with debounce (doesn't trigger on transient sounds)\n * - Speech end detection with grace period (allows pauses between words)\n * - Minimum speech duration (ignores very short sounds)\n * - Energy smoothing (rolling average to avoid jitter)\n * - Configurable thresholds and timings\n */\n\nimport { useCallback, useRef } from 'react';\n\nexport interface VADConfig {\n  /** Silence duration (ms) before triggering speech end. Default 1500 */\n  silenceTimeout: number;\n  /** Grace period (ms) — if speech resumes within this time, continue. Default 300 */\n  gracePeriod: number;\n  /** Minimum speech duration (ms) before allowing end detection. Default 500 */\n  minSpeechDuration: number;\n  /** Maximum recording duration (ms). 0 = unlimited. Default 30000 */\n  maxDuration: number;\n  /** Base RMS threshold for silence detection. Default 0.015 */\n  silenceThreshold: number;\n  /** Multiplier above noise floor to detect speech. Default 2.5 */\n  speechThresholdMultiplier: number;\n  /** Noise floor calibration duration (ms). Default 500 */\n  calibrationDuration: number;\n  /** Energy smoothing factor (0-1). Higher = more smoothing. Default 0.3 */\n  smoothingFactor: number;\n}\n\nexport interface VADState {\n  /** Current VAD state */\n  state: 'calibrating' | 'waiting' | 'speaking' | 'grace' | 'ended';\n  /** Calibrated noise floor RMS */\n  noiseFloor: number;\n  /** Current smoothed RMS */\n  currentRMS: number;\n  /** Time speech started (0 if not speaking) */\n  speechStartTime: number;\n  /** Time silence started (0 if speaking) */\n  silenceStartTime: number;\n  /** Total speech duration so far */\n  speechDuration: number;\n}\n\nexport interface VADCallbacks {\n  /** Called when speech is first detected */\n  onSpeechStart?: () => void;\n  /** Called when speech ends (after silence timeout) */\n  onSpeechEnd?: () => void;\n  /** Called when max duration reached */\n  onMaxDuration?: () => void;\n  /** Called each frame with VAD state (for visualization) */\n  onStateChange?: (state: VADState) => void;\n}\n\nconst DEFAULT_CONFIG: VADConfig = {\n  silenceTimeout: 400,            // 0.4s silence to end\n  gracePeriod: 150,               // 0.15s pause allowed between words\n  minSpeechDuration: 200,         // 0.2s min speech before allowing end\n  maxDuration: 30000,             // 30s max recording\n  silenceThreshold: 0.01,         // sensitive threshold\n  speechThresholdMultiplier: 1.8, // speech = 1.8x noise floor\n  calibrationDuration: 200,       // 0.2s calibration\n  smoothingFactor: 0.2,           // fast response\n};\n\nexport interface UseVADReturn {\n  /** Process a frame of audio data. Call this from rAF loop. */\n  processFrame: (timeDomainData: Uint8Array) => void;\n  /** Reset VAD state (call when starting new recording) */\n  reset: () => void;\n  /** Get current VAD state */\n  getState: () => VADState;\n  /** Check if VAD determined speech has ended */\n  hasEnded: () => boolean;\n  /** Check if currently detecting speech */\n  isSpeaking: () => boolean;\n}\n\n/**\n * Professional Voice Activity Detection hook\n */\nexport function useVAD(\n  config: Partial<VADConfig> = {},\n  callbacks: VADCallbacks = {},\n): UseVADReturn {\n  const cfg = { ...DEFAULT_CONFIG, ...config };\n\n  const stateRef = useRef<VADState>({\n    state: 'calibrating',\n    noiseFloor: cfg.silenceThreshold,\n    currentRMS: 0,\n    speechStartTime: 0,\n    silenceStartTime: 0,\n    speechDuration: 0,\n  });\n\n  // Calibration samples\n  const calibrationSamplesRef = useRef<number[]>([]);\n  const calibrationStartRef = useRef<number>(0);\n\n  // Stable callback refs\n  const callbacksRef = useRef(callbacks);\n  callbacksRef.current = callbacks;\n\n  const computeRMS = useCallback((timeDomainData: Uint8Array): number => {\n    let sumSquares = 0;\n    for (let i = 0; i < timeDomainData.length; i++) {\n      const normalized = (timeDomainData[i]! - 128) / 128;\n      sumSquares += normalized * normalized;\n    }\n    return Math.sqrt(sumSquares / timeDomainData.length);\n  }, []);\n\n  const reset = useCallback(() => {\n    stateRef.current = {\n      state: 'calibrating',\n      noiseFloor: cfg.silenceThreshold,\n      currentRMS: 0,\n      speechStartTime: 0,\n      silenceStartTime: 0,\n      speechDuration: 0,\n    };\n    calibrationSamplesRef.current = [];\n    calibrationStartRef.current = 0;\n  }, [cfg.silenceThreshold]);\n\n  const processFrame = useCallback((timeDomainData: Uint8Array) => {\n    const now = Date.now();\n    const state = stateRef.current;\n    const rawRMS = computeRMS(timeDomainData);\n\n    // Smooth RMS with exponential moving average\n    state.currentRMS = state.currentRMS === 0\n      ? rawRMS\n      : state.currentRMS * cfg.smoothingFactor + rawRMS * (1 - cfg.smoothingFactor);\n\n    const rms = state.currentRMS;\n\n    // === CALIBRATION PHASE ===\n    if (state.state === 'calibrating') {\n      if (calibrationStartRef.current === 0) {\n        calibrationStartRef.current = now;\n      }\n\n      calibrationSamplesRef.current.push(rms);\n\n      if (now - calibrationStartRef.current >= cfg.calibrationDuration) {\n        // Calculate noise floor as median of samples (robust to outliers)\n        const sorted = [...calibrationSamplesRef.current].sort((a, b) => a - b);\n        const median = sorted[Math.floor(sorted.length / 2)] ?? cfg.silenceThreshold;\n        // Add small margin above median\n        state.noiseFloor = Math.max(median * 1.2, cfg.silenceThreshold);\n        state.state = 'waiting';\n        calibrationSamplesRef.current = [];\n      }\n\n      callbacksRef.current.onStateChange?.(state);\n      return;\n    }\n\n    // Dynamic speech threshold based on noise floor\n    const speechThreshold = state.noiseFloor * cfg.speechThresholdMultiplier;\n    const isSpeech = rms > speechThreshold;\n\n    // === WAITING FOR SPEECH ===\n    if (state.state === 'waiting') {\n      if (isSpeech) {\n        state.state = 'speaking';\n        state.speechStartTime = now;\n        state.silenceStartTime = 0;\n        callbacksRef.current.onSpeechStart?.();\n      }\n    }\n\n    // === SPEAKING ===\n    else if (state.state === 'speaking') {\n      state.speechDuration = now - state.speechStartTime;\n\n      // Check max duration\n      if (cfg.maxDuration > 0 && state.speechDuration >= cfg.maxDuration) {\n        state.state = 'ended';\n        callbacksRef.current.onMaxDuration?.();\n        callbacksRef.current.onStateChange?.(state);\n        return;\n      }\n\n      if (!isSpeech) {\n        // Start silence timer, but only if we've spoken long enough\n        if (state.speechDuration >= cfg.minSpeechDuration) {\n          state.state = 'grace';\n          state.silenceStartTime = now;\n        }\n        // If speech too short, stay in speaking state (might be noise)\n      }\n    }\n\n    // === GRACE PERIOD ===\n    else if (state.state === 'grace') {\n      state.speechDuration = now - state.speechStartTime;\n\n      // Check max duration\n      if (cfg.maxDuration > 0 && state.speechDuration >= cfg.maxDuration) {\n        state.state = 'ended';\n        callbacksRef.current.onMaxDuration?.();\n        callbacksRef.current.onStateChange?.(state);\n        return;\n      }\n\n      if (isSpeech) {\n        // Speech resumed — back to speaking\n        state.state = 'speaking';\n        state.silenceStartTime = 0;\n      } else {\n        const silenceDuration = now - state.silenceStartTime;\n\n        if (silenceDuration >= cfg.silenceTimeout) {\n          // Silence timeout reached — speech ended\n          state.state = 'ended';\n          callbacksRef.current.onSpeechEnd?.();\n        }\n      }\n    }\n\n    callbacksRef.current.onStateChange?.(state);\n  }, [cfg, computeRMS]);\n\n  const getState = useCallback(() => stateRef.current, []);\n  const hasEnded = useCallback(() => stateRef.current.state === 'ended', []);\n  const isSpeaking = useCallback(() =>\n    stateRef.current.state === 'speaking' || stateRef.current.state === 'grace',\n  []);\n\n  return {\n    processFrame,\n    reset,\n    getState,\n    hasEnded,\n    isSpeaking,\n  };\n}\n","import { useCallback, useRef, useState } from 'react';\nimport type { SDKRouterClient, TranscriptionResponse } from '@sdkrouter/client';\nimport { useStreamingSTT } from './useStreamingSTT.js';\nimport { useVAD } from './useVAD.js';\nimport type { VADConfig } from './useVAD.js';\n\nexport type RecorderStatus = 'idle' | 'recording' | 'transcribing' | 'error';\n\n/** Audio energy bands emitted per frame via onAudioFrame */\nexport interface MicAudioFrame {\n  low: number;   // 0-1 bass energy\n  mid: number;   // 0-1 mid energy\n  high: number;  // 0-1 treble energy\n  volume: number; // 0-1 overall volume\n}\n\nexport interface UseSpeechRecorderOptions {\n  /** SDKRouterClient instance with audioUrl configured */\n  client: SDKRouterClient;\n  /** Language hint for STT (ISO 639-1), e.g. 'en', 'ru' */\n  language?: string;\n  /** STT model, default 'whisper-1' */\n  model?: string;\n  /**\n   * Use browser Web Speech API instead of server.\n   * Falls back to server STT if browser doesn't support it.\n   * - true:  prefer browser\n   * - false: always use server (default)\n   * - 'auto': browser if supported, server otherwise\n   */\n  useWebSpeechAPI?: boolean | 'auto';\n  /** BCP-47 lang for Web Speech API, e.g. 'en-US'. Derived from `language` if not set */\n  webSpeechLang?: string;\n  /** Silence duration (ms) before auto-stop. 0 = disabled. Default 0. */\n  silenceTimeout?: number;\n  /** RMS threshold below which audio is considered silence. Default 0.01 */\n  silenceThreshold?: number;\n  /** Advanced VAD configuration (overrides silenceTimeout/silenceThreshold when provided) */\n  vadConfig?: Partial<VADConfig>;\n  /** Called when transcription completes */\n  onResult?: (text: string) => void;\n  /** Called with interim text while still speaking (Web Speech API only) */\n  onInterim?: (text: string) => void;\n  /** Called on error */\n  onError?: (error: Error) => void;\n  /** Called every animation frame with mic FFT data (for visualizations) */\n  onAudioFrame?: (frame: MicAudioFrame) => void;\n  /**\n   * Use server-side streaming STT via WebSocket.\n   * - true:    always use streaming\n   * - 'auto':  streaming if client supports it, fallback to batch\n   * - 'prefer': streaming first, then browser Web Speech, then batch\n   * - false:   never (default)\n   */\n  useStreamingSTT?: boolean | 'auto' | 'prefer';\n}\n\nexport interface UseSpeechRecorderReturn {\n  status: RecorderStatus;\n  /** Start recording from microphone */\n  startRecording: () => Promise<void>;\n  /** Stop recording and send to STT */\n  stopRecording: () => void;\n  /** True while actively recording */\n  isRecording: boolean;\n  /** Which STT backend is being used */\n  backend: 'server' | 'browser';\n  /** Whether browser Web Speech API is available */\n  webSpeechSupported: boolean;\n  /** Last error message */\n  error: string | null;\n}\n\n// ── Web Speech API detection ─────────────────────────────────────────────────\n\nfunction getSpeechRecognitionCtor(): (new () => SpeechRecognition) | null {\n  if (typeof window === 'undefined') return null;\n  return (\n    (window as unknown as Record<string, unknown>).SpeechRecognition ??\n    (window as unknown as Record<string, unknown>).webkitSpeechRecognition ??\n    null\n  ) as (new () => SpeechRecognition) | null;\n}\n\nconst webSpeechAvailable = getSpeechRecognitionCtor() !== null;\n\n/** Map ISO 639-1 → BCP-47 for common languages */\nfunction toBcp47(lang?: string): string | undefined {\n  if (!lang) return undefined;\n  if (lang.includes('-')) return lang; // already BCP-47\n  const map: Record<string, string> = {\n    en: 'en-US', ru: 'ru-RU', ko: 'ko-KR', ja: 'ja-JP',\n    zh: 'zh-CN', de: 'de-DE', fr: 'fr-FR', es: 'es-ES',\n  };\n  return map[lang] ?? lang;\n}\n\n// ── MediaRecorder helpers ────────────────────────────────────────────────────\n\nfunction getSupportedMimeType(): string {\n  const types = [\n    'audio/webm;codecs=opus',\n    'audio/webm',\n    'audio/ogg;codecs=opus',\n    'audio/mp4',\n  ];\n  for (const type of types) {\n    if (MediaRecorder.isTypeSupported(type)) return type;\n  }\n  return '';\n}\n\n// ── Audio bands computation (inlined to avoid cross-package import) ──────────\n\nfunction computeMicBands(frequencyData: Uint8Array, out: MicAudioFrame): void {\n  const len = frequencyData.length;\n  if (len === 0) {\n    out.low = 0; out.mid = 0; out.high = 0; out.volume = 0;\n    return;\n  }\n\n  const lowEnd = Math.min(11, len);\n  const midEnd = Math.min(81, len);\n  const highEnd = Math.min(256, len);\n\n  let lowSum = 0, midSum = 0, highSum = 0, totalSum = 0;\n\n  for (let i = 0; i < lowEnd; i++) lowSum += frequencyData[i]!;\n  for (let i = lowEnd; i < midEnd; i++) midSum += frequencyData[i]!;\n  for (let i = midEnd; i < highEnd; i++) highSum += frequencyData[i]!;\n  for (let i = 0; i < len; i++) totalSum += frequencyData[i]!;\n\n  out.low = lowSum / (lowEnd * 255);\n  out.mid = midEnd > lowEnd ? midSum / ((midEnd - lowEnd) * 255) : 0;\n  out.high = highEnd > midEnd ? highSum / ((highEnd - midEnd) * 255) : 0;\n  out.volume = totalSum / (len * 255);\n}\n\n// ── Hook ─────────────────────────────────────────────────────────────────────\n\nexport function useSpeechRecorder(options: UseSpeechRecorderOptions): UseSpeechRecorderReturn {\n  const {\n    client,\n    language,\n    model = 'whisper-1',\n    useWebSpeechAPI = false,\n    webSpeechLang,\n    silenceTimeout = 0,\n    silenceThreshold = 0.01,\n    vadConfig,\n    onResult,\n    onInterim,\n    onError,\n    onAudioFrame,\n    useStreamingSTT: streamingSTTOption = false,\n  } = options;\n\n  // Check if streaming STT is available (client has transcribeStream method)\n  const hasStreamingSTT = typeof client.audio.transcribeStream === 'function';\n\n  // Decide backend: 'streaming' | 'browser' | 'server'\n  // Priority when 'prefer': streaming > browser > server\n  const resolvedBackend = (() => {\n    if (streamingSTTOption === true || (streamingSTTOption === 'auto' && hasStreamingSTT)) {\n      return 'streaming' as const;\n    }\n    if (streamingSTTOption === 'prefer') {\n      if (hasStreamingSTT) return 'streaming' as const;\n      const preferBrowser =\n        useWebSpeechAPI === true ||\n        (useWebSpeechAPI === 'auto' && webSpeechAvailable);\n      if (preferBrowser && webSpeechAvailable) return 'browser' as const;\n      return 'server' as const;\n    }\n    const preferBrowser =\n      useWebSpeechAPI === true ||\n      (useWebSpeechAPI === 'auto' && webSpeechAvailable);\n    if (preferBrowser && webSpeechAvailable) return 'browser' as const;\n    return 'server' as const;\n  })();\n\n  // Streaming STT hook (always called to respect hook rules)\n  const streaming = useStreamingSTT({\n    client,\n    model,\n    language,\n    silenceTimeout,\n    silenceThreshold,\n    onInterim,\n    onResult,\n    onError,\n    onAudioFrame,\n  });\n\n  const [status, setStatus] = useState<RecorderStatus>('idle');\n  const [error, setError] = useState<string | null>(null);\n\n  // Server STT refs\n  const recorderRef = useRef<MediaRecorder | null>(null);\n  const chunksRef = useRef<Blob[]>([]);\n  const streamRef = useRef<MediaStream | null>(null);\n  const startTimeRef = useRef<number>(0);\n\n  // Audio analysis refs (shared by VAD + audio frame emission)\n  const audioCtxRef = useRef<AudioContext | null>(null);\n  const rafRef = useRef<number>(0);\n\n  // Stable ref for onAudioFrame to avoid stale closures in rAF loop\n  const onAudioFrameRef = useRef(onAudioFrame);\n  onAudioFrameRef.current = onAudioFrame;\n\n  // Determine if we should use advanced VAD (vadConfig provided or silenceTimeout > 0)\n  const useAdvancedVAD = silenceTimeout > 0 || vadConfig !== undefined;\n\n  // Merge simple options into VAD config\n  const mergedVADConfig: Partial<VADConfig> = useAdvancedVAD\n    ? {\n        silenceTimeout: vadConfig?.silenceTimeout ?? silenceTimeout,\n        silenceThreshold: vadConfig?.silenceThreshold ?? silenceThreshold,\n        ...vadConfig,\n      }\n    : {};\n\n  // VAD hook — handles speech detection with grace period, calibration, etc.\n  const vad = useVAD(mergedVADConfig, {\n    onSpeechEnd: useCallback(() => {\n      // Stop recording when VAD detects speech end\n      if (recorderRef.current && recorderRef.current.state !== 'inactive') {\n        recorderRef.current.stop();\n      }\n    }, []),\n    onMaxDuration: useCallback(() => {\n      // Stop recording when max duration reached\n      if (recorderRef.current && recorderRef.current.state !== 'inactive') {\n        recorderRef.current.stop();\n      }\n    }, []),\n  });\n\n  // Browser STT ref\n  const recognitionRef = useRef<SpeechRecognition | null>(null);\n\n  const stopAudioAnalysis = useCallback(() => {\n    cancelAnimationFrame(rafRef.current);\n    rafRef.current = 0;\n    if (audioCtxRef.current) {\n      audioCtxRef.current.close();\n      audioCtxRef.current = null;\n    }\n  }, []);\n\n  const stopMediaStream = useCallback(() => {\n    stopAudioAnalysis();\n    if (streamRef.current) {\n      streamRef.current.getTracks().forEach((t) => t.stop());\n      streamRef.current = null;\n    }\n  }, [stopAudioAnalysis]);\n\n  // ── Server STT path ─────────────────────────────────────────────────────\n\n  const startServerRecording = useCallback(async () => {\n    setError(null);\n\n    // Reset VAD state for new recording session\n    if (useAdvancedVAD) {\n      vad.reset();\n    }\n\n    try {\n      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n      streamRef.current = stream;\n\n      const mimeType = getSupportedMimeType();\n      const recorder = new MediaRecorder(stream, mimeType ? { mimeType } : undefined);\n      recorderRef.current = recorder;\n      chunksRef.current = [];\n\n      recorder.ondataavailable = (e) => {\n        if (e.data.size > 0) chunksRef.current.push(e.data);\n      };\n\n      recorder.onstop = async () => {\n        stopAudioAnalysis();\n        stopMediaStream();\n\n        const blob = new Blob(chunksRef.current, {\n          type: recorder.mimeType || 'audio/webm',\n        });\n\n        const durationMs = Date.now() - startTimeRef.current;\n        // Skip if too short or too small (< 1KB is likely noise/empty)\n        if (blob.size < 1000 || durationMs < 300) {\n          console.log('[speech-recorder] Skipping small/short recording:', blob.size, 'bytes,', durationMs, 'ms');\n          setStatus('idle');\n          onResult?.('');\n          return;\n        }\n\n        setStatus('transcribing');\n\n        try {\n          const result = await client.audio.transcribe({\n            file: blob,\n            model,\n            language,\n          });\n\n          const text = typeof result === 'string' ? result : (result as TranscriptionResponse).text;\n          setStatus('idle');\n          onResult?.(text);\n        } catch (err) {\n          const e = err instanceof Error ? err : new Error(String(err));\n          setError(e.message);\n          setStatus('error');\n          onError?.(e);\n        }\n      };\n\n      startTimeRef.current = Date.now();\n      recorder.start(250);\n      setStatus('recording');\n\n      // ── Audio analysis (VAD + audio frame emission) ──────\n      const needsAnalyser = useAdvancedVAD || onAudioFrameRef.current;\n      if (needsAnalyser) {\n        const audioCtx = new AudioContext();\n        audioCtxRef.current = audioCtx;\n        const source = audioCtx.createMediaStreamSource(stream);\n        const analyser = audioCtx.createAnalyser();\n        analyser.fftSize = 2048;\n        source.connect(analyser);\n\n        const timeDomainData = new Uint8Array(analyser.fftSize);\n        const frequencyData = new Uint8Array(analyser.frequencyBinCount);\n        const frameOut: MicAudioFrame = { low: 0, mid: 0, high: 0, volume: 0 };\n\n        const tick = () => {\n          if (!recorderRef.current || recorderRef.current.state === 'inactive') return;\n\n          // Get time-domain data for VAD\n          analyser.getByteTimeDomainData(timeDomainData);\n\n          // Process through VAD (handles calibration, speech detection, grace period)\n          // VAD will call onSpeechEnd callback when silence timeout is reached\n          if (useAdvancedVAD) {\n            vad.processFrame(timeDomainData);\n          }\n\n          // Audio frame emission (frequency-domain FFT bands)\n          if (onAudioFrameRef.current) {\n            analyser.getByteFrequencyData(frequencyData);\n            computeMicBands(frequencyData, frameOut);\n            onAudioFrameRef.current(frameOut);\n          }\n\n          rafRef.current = requestAnimationFrame(tick);\n        };\n\n        rafRef.current = requestAnimationFrame(tick);\n      }\n    } catch (err) {\n      stopMediaStream();\n      const e = err instanceof Error ? err : new Error(String(err));\n      setError(e.message);\n      setStatus('error');\n      onError?.(e);\n    }\n  }, [client, model, language, useAdvancedVAD, vad, onResult, onError, stopMediaStream, stopAudioAnalysis]);\n\n  const stopServerRecording = useCallback(() => {\n    if (recorderRef.current && recorderRef.current.state !== 'inactive') {\n      recorderRef.current.stop();\n    }\n  }, []);\n\n  // ── Browser STT path ────────────────────────────────────────────────────\n\n  const startBrowserRecording = useCallback(async () => {\n    setError(null);\n\n    const Ctor = getSpeechRecognitionCtor();\n    if (!Ctor) {\n      // Fallback to server\n      return startServerRecording();\n    }\n\n    const recognition = new Ctor();\n    recognition.continuous = false;\n    recognition.interimResults = true;\n\n    const lang = webSpeechLang ?? toBcp47(language);\n    if (lang) recognition.lang = lang;\n\n    recognition.onresult = (event: SpeechRecognitionEvent) => {\n      let finalText = '';\n      let interimText = '';\n\n      for (let i = event.resultIndex; i < event.results.length; i++) {\n        const result = event.results[i]!;\n        const transcript = result[0]!.transcript;\n        if (result.isFinal) {\n          finalText += transcript;\n        } else {\n          interimText += transcript;\n        }\n      }\n\n      if (interimText) onInterim?.(interimText);\n      if (finalText) {\n        setStatus('idle');\n        onResult?.(finalText);\n      }\n    };\n\n    recognition.onerror = (event: SpeechRecognitionErrorEvent) => {\n      if (event.error === 'no-speech' || event.error === 'aborted') {\n        setStatus('idle');\n        return;\n      }\n\n      // Fallback to server on browser STT error\n      if (useWebSpeechAPI === 'auto') {\n        recognitionRef.current = null;\n        startServerRecording();\n        return;\n      }\n\n      const err = new Error(`Speech recognition error: ${event.error}`);\n      setError(err.message);\n      setStatus('error');\n      onError?.(err);\n    };\n\n    recognition.onend = () => {\n      setStatus((prev) => (prev === 'recording' ? 'idle' : prev));\n      recognitionRef.current = null;\n    };\n\n    recognitionRef.current = recognition;\n    recognition.start();\n    setStatus('recording');\n  }, [language, webSpeechLang, useWebSpeechAPI, onResult, onInterim, onError, startServerRecording]);\n\n  const stopBrowserRecording = useCallback(() => {\n    if (recognitionRef.current) {\n      recognitionRef.current.stop();\n    }\n  }, []);\n\n  // ── Public API ──────────────────────────────────────────────────────────\n\n  const startRecording = useCallback(async () => {\n    if (resolvedBackend === 'streaming') {\n      return streaming.startRecording();\n    }\n    if (resolvedBackend === 'browser') {\n      return startBrowserRecording();\n    }\n    return startServerRecording();\n  }, [resolvedBackend, streaming, startBrowserRecording, startServerRecording]);\n\n  const stopRecording = useCallback(() => {\n    if (resolvedBackend === 'streaming') {\n      streaming.stopRecording();\n    } else if (resolvedBackend === 'browser') {\n      stopBrowserRecording();\n    } else {\n      stopServerRecording();\n    }\n  }, [resolvedBackend, streaming, stopBrowserRecording, stopServerRecording]);\n\n  // When using streaming backend, delegate status from the streaming hook\n  const effectiveStatus = resolvedBackend === 'streaming' ? streaming.status : status;\n  const effectiveIsRecording = resolvedBackend === 'streaming' ? streaming.isRecording : status === 'recording';\n\n  return {\n    status: effectiveStatus,\n    startRecording,\n    stopRecording,\n    isRecording: effectiveIsRecording,\n    backend: resolvedBackend === 'streaming' ? 'server' : resolvedBackend,\n    webSpeechSupported: webSpeechAvailable,\n    error,\n  };\n}\n","import { useCallback, useRef, useState } from 'react';\n\nexport type WebSpeechStatus = 'idle' | 'listening' | 'error';\n\nexport interface UseWebSpeechOptions {\n  /** Language (BCP-47), e.g. 'en-US', 'ru-RU'. Default: browser default */\n  lang?: string;\n  /** Continuous recognition (keeps listening until stopped). Default: false */\n  continuous?: boolean;\n  /** Interim results while speaking. Default: true */\n  interimResults?: boolean;\n  /** Called with final transcript */\n  onResult?: (text: string) => void;\n  /** Called with interim transcript (partial, still speaking) */\n  onInterim?: (text: string) => void;\n  /** Called on error */\n  onError?: (error: Error) => void;\n}\n\nexport interface UseWebSpeechReturn {\n  status: WebSpeechStatus;\n  /** Start browser speech recognition */\n  startListening: () => void;\n  /** Stop browser speech recognition */\n  stopListening: () => void;\n  isListening: boolean;\n  /** Whether Web Speech API is available in this browser */\n  isSupported: boolean;\n  error: string | null;\n}\n\n/** Check if Web Speech API is available */\nfunction getSpeechRecognition(): (new () => SpeechRecognition) | null {\n  if (typeof window === 'undefined') return null;\n  return (\n    (window as unknown as Record<string, unknown>).SpeechRecognition ??\n    (window as unknown as Record<string, unknown>).webkitSpeechRecognition ??\n    null\n  ) as (new () => SpeechRecognition) | null;\n}\n\nexport function useWebSpeech(options: UseWebSpeechOptions = {}): UseWebSpeechReturn {\n  const {\n    lang,\n    continuous = false,\n    interimResults = true,\n    onResult,\n    onInterim,\n    onError,\n  } = options;\n\n  const SpeechRecognitionCtor = getSpeechRecognition();\n  const isSupported = SpeechRecognitionCtor !== null;\n\n  const [status, setStatus] = useState<WebSpeechStatus>('idle');\n  const [error, setError] = useState<string | null>(null);\n  const recognitionRef = useRef<SpeechRecognition | null>(null);\n\n  const startListening = useCallback(() => {\n    if (!SpeechRecognitionCtor) {\n      const err = new Error('Web Speech API not supported in this browser');\n      setError(err.message);\n      setStatus('error');\n      onError?.(err);\n      return;\n    }\n\n    setError(null);\n\n    const recognition = new SpeechRecognitionCtor();\n    recognition.continuous = continuous;\n    recognition.interimResults = interimResults;\n    if (lang) recognition.lang = lang;\n\n    recognition.onresult = (event: SpeechRecognitionEvent) => {\n      let finalText = '';\n      let interimText = '';\n\n      for (let i = event.resultIndex; i < event.results.length; i++) {\n        const result = event.results[i]!;\n        const transcript = result[0]!.transcript;\n        if (result.isFinal) {\n          finalText += transcript;\n        } else {\n          interimText += transcript;\n        }\n      }\n\n      if (interimText) onInterim?.(interimText);\n      if (finalText) onResult?.(finalText);\n    };\n\n    recognition.onerror = (event: SpeechRecognitionErrorEvent) => {\n      // \"no-speech\" and \"aborted\" are not real errors\n      if (event.error === 'no-speech' || event.error === 'aborted') {\n        setStatus('idle');\n        return;\n      }\n      const err = new Error(`Speech recognition error: ${event.error}`);\n      setError(err.message);\n      setStatus('error');\n      onError?.(err);\n    };\n\n    recognition.onend = () => {\n      setStatus('idle');\n      recognitionRef.current = null;\n    };\n\n    recognitionRef.current = recognition;\n    recognition.start();\n    setStatus('listening');\n  }, [SpeechRecognitionCtor, lang, continuous, interimResults, onResult, onInterim, onError]);\n\n  const stopListening = useCallback(() => {\n    if (recognitionRef.current) {\n      recognitionRef.current.stop();\n    }\n  }, []);\n\n  return {\n    status,\n    startListening,\n    stopListening,\n    isListening: status === 'listening',\n    isSupported,\n    error,\n  };\n}\n","/**\n * useTextChunker — Smart text chunking for TTS\n *\n * Splits text into natural speech chunks optimized for TTS:\n * - Prioritizes sentence boundaries\n * - Falls back to clause boundaries (commas, semicolons)\n * - Respects minimum/maximum chunk sizes\n * - Handles streaming input (accumulates until boundary found)\n * - Preserves abbreviations, numbers, URLs\n */\n\nimport { useCallback, useRef } from 'react';\n\nexport interface TextChunkerConfig {\n  /** Minimum chunk length before emitting. Default 20 */\n  minLength: number;\n  /** Maximum chunk length — force split if exceeded. Default 200 */\n  maxLength: number;\n  /** Ideal chunk length — prefer splits near this. Default 80 */\n  idealLength: number;\n  /** Minimum length for FIRST chunk (for fast time-to-first-audio). Default: same as minLength */\n  firstChunkMinLength: number;\n  /** Language hint for smarter splitting. Default 'en' */\n  language: string;\n}\n\nexport interface TextChunkerReturn {\n  /** Feed text (can be called multiple times for streaming) */\n  push: (text: string) => string[];\n  /** Flush remaining buffer (call when stream ends) */\n  flush: () => string | null;\n  /** Reset state */\n  reset: () => void;\n  /** Get current buffer content */\n  getBuffer: () => string;\n}\n\nconst DEFAULT_CONFIG: TextChunkerConfig = {\n  minLength: 150,\n  maxLength: 500,\n  idealLength: 300,\n  firstChunkMinLength: 40,  // First chunk: ~40 chars (1 short sentence)\n  language: 'en',\n};\n\n// Sentence-ending punctuation (high priority split points)\nconst SENTENCE_END = /[.!?。！？]+[\\s\\n]|[.!?。！？]+$/;\n\n// Clause boundaries (medium priority)\nconst CLAUSE_END = /[,;:—–\\-、，；：]+\\s|[,;:—–\\-、，；：]+$/;\n\n// Phrase boundaries — conjunctions, prepositions (low priority)\n// Split BEFORE these words\nconst PHRASE_BOUNDARY_EN = /\\s+(and|or|but|so|because|when|while|if|then|that|which|where|who|how|what|however|therefore|moreover|furthermore|although|though|unless|until|after|before|since|as|for)\\s+/i;\nconst PHRASE_BOUNDARY_RU = /\\s+(и|или|но|а|что|как|где|когда|если|потому|поэтому|однако|также|кроме|после|перед|пока|чтобы|хотя)\\s+/i;\n\n// Patterns to NOT split inside\nconst NO_SPLIT_PATTERNS = [\n  // Numbers with decimals: 1.5, 3.14159\n  /\\d+\\.\\d+/g,\n  // Abbreviations: Dr., Mr., Mrs., т.е., т.д., и т.п.\n  /(?:Dr|Mr|Mrs|Ms|Prof|Inc|Ltd|т\\.?е|т\\.?д|т\\.?п|и т\\.?п|и т\\.?д|др)\\./gi,\n  // URLs\n  /https?:\\/\\/[^\\s]+/gi,\n  // Emails\n  /[\\w.-]+@[\\w.-]+\\.\\w+/gi,\n  // File paths\n  /[\\w\\/\\\\]+\\.\\w{2,4}/g,\n  // Version numbers: v1.2.3\n  /v?\\d+(\\.\\d+)+/gi,\n];\n\n// Ellipsis — DO split after\nconst ELLIPSIS = /\\.{3}|…/;\n\n/**\n * Check if position is inside a \"no-split\" zone\n */\nfunction isInsideNoSplit(text: string, pos: number): boolean {\n  for (const pattern of NO_SPLIT_PATTERNS) {\n    pattern.lastIndex = 0;\n    let match;\n    while ((match = pattern.exec(text)) !== null) {\n      if (pos > match.index && pos < match.index + match[0].length) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n/**\n * Find best split point in text\n * Returns index after which to split, or -1 if no good point found\n */\nfunction findSplitPoint(\n  text: string,\n  minLen: number,\n  maxLen: number,\n  idealLen: number,\n  language: string,\n): number {\n  if (text.length <= minLen) return -1;\n\n  // Search window: prefer splits between minLen and maxLen, ideally near idealLen\n  const searchStart = Math.max(0, minLen - 10);\n  const searchEnd = Math.min(text.length, maxLen + 10);\n  const searchText = text.slice(0, searchEnd);\n\n  // Collect all potential split points with scores\n  const candidates: Array<{ pos: number; score: number }> = [];\n\n  // 1. Sentence boundaries (highest priority)\n  let match;\n  const sentenceRegex = new RegExp(SENTENCE_END.source, 'g');\n  while ((match = sentenceRegex.exec(searchText)) !== null) {\n    const pos = match.index + match[0].trimEnd().length;\n    if (pos >= searchStart && pos <= searchEnd && !isInsideNoSplit(text, pos)) {\n      // Check for ellipsis — high score\n      const isEllipsis = ELLIPSIS.test(match[0]);\n      const distanceFromIdeal = Math.abs(pos - idealLen);\n      // Score: base 100, bonus for ellipsis, penalty for distance from ideal\n      const score = 100 + (isEllipsis ? 20 : 0) - distanceFromIdeal * 0.5;\n      candidates.push({ pos, score });\n    }\n  }\n\n  // 2. Clause boundaries (medium priority)\n  const clauseRegex = new RegExp(CLAUSE_END.source, 'g');\n  while ((match = clauseRegex.exec(searchText)) !== null) {\n    const pos = match.index + match[0].trimEnd().length;\n    if (pos >= searchStart && pos <= searchEnd && !isInsideNoSplit(text, pos)) {\n      const distanceFromIdeal = Math.abs(pos - idealLen);\n      const score = 50 - distanceFromIdeal * 0.3;\n      candidates.push({ pos, score });\n    }\n  }\n\n  // 3. Phrase boundaries (low priority)\n  const phraseRegex = language.startsWith('ru') ? PHRASE_BOUNDARY_RU : PHRASE_BOUNDARY_EN;\n  const phraseGlobal = new RegExp(phraseRegex.source, 'gi');\n  while ((match = phraseGlobal.exec(searchText)) !== null) {\n    // Split BEFORE the conjunction (after the space before it)\n    const pos = match.index + 1; // After the leading space\n    if (pos >= searchStart && pos <= searchEnd) {\n      const distanceFromIdeal = Math.abs(pos - idealLen);\n      const score = 25 - distanceFromIdeal * 0.2;\n      candidates.push({ pos, score });\n    }\n  }\n\n  // 4. If we're over maxLen, find any word boundary\n  if (text.length > maxLen && candidates.length === 0) {\n    const wordBoundary = /\\s+/g;\n    while ((match = wordBoundary.exec(searchText)) !== null) {\n      const pos = match.index;\n      if (pos >= minLen && pos <= maxLen) {\n        const distanceFromIdeal = Math.abs(pos - idealLen);\n        const score = 10 - distanceFromIdeal * 0.1;\n        candidates.push({ pos, score });\n      }\n    }\n  }\n\n  // Pick best candidate\n  if (candidates.length === 0) {\n    // Force split at maxLen if nothing found and text is too long\n    if (text.length > maxLen) {\n      // Find last space before maxLen\n      const lastSpace = text.lastIndexOf(' ', maxLen);\n      return lastSpace > minLen ? lastSpace : maxLen;\n    }\n    return -1;\n  }\n\n  // Sort by score descending\n  candidates.sort((a, b) => b.score - a.score);\n  return candidates[0]!.pos;\n}\n\n/**\n * Smart text chunker hook for TTS\n */\nexport function useTextChunker(config: Partial<TextChunkerConfig> = {}): TextChunkerReturn {\n  const cfg = { ...DEFAULT_CONFIG, ...config };\n  const bufferRef = useRef('');\n\n  const push = useCallback((text: string): string[] => {\n    bufferRef.current += text;\n    const chunks: string[] = [];\n\n    // Keep extracting chunks while buffer has enough content\n    while (bufferRef.current.length >= cfg.minLength) {\n      const splitPos = findSplitPoint(\n        bufferRef.current,\n        cfg.minLength,\n        cfg.maxLength,\n        cfg.idealLength,\n        cfg.language,\n      );\n\n      if (splitPos === -1) {\n        // No good split point yet — wait for more text\n        // Unless buffer is getting too big\n        if (bufferRef.current.length > cfg.maxLength * 1.5) {\n          // Force split at maxLength\n          const forced = bufferRef.current.slice(0, cfg.maxLength).trimEnd();\n          bufferRef.current = bufferRef.current.slice(cfg.maxLength).trimStart();\n          if (forced) chunks.push(forced);\n        } else {\n          break;\n        }\n      } else {\n        const chunk = bufferRef.current.slice(0, splitPos).trimEnd();\n        bufferRef.current = bufferRef.current.slice(splitPos).trimStart();\n        if (chunk) chunks.push(chunk);\n      }\n    }\n\n    return chunks;\n  }, [cfg]);\n\n  const flush = useCallback((): string | null => {\n    const remaining = bufferRef.current.trim();\n    bufferRef.current = '';\n    return remaining || null;\n  }, []);\n\n  const reset = useCallback(() => {\n    bufferRef.current = '';\n  }, []);\n\n  const getBuffer = useCallback(() => bufferRef.current, []);\n\n  return { push, flush, reset, getBuffer };\n}\n\n/**\n * Adaptive chunking strategy based on content analysis and chunk index\n */\ninterface AdaptiveConfig {\n  minLength: number;\n  maxLength: number;\n  idealLength: number;\n}\n\nfunction getAdaptiveConfig(\n  totalLength: number,\n  contentType: 'short' | 'medium' | 'long' | 'list',\n  chunkIndex: number,\n): AdaptiveConfig {\n  // First chunk: SMALL for fast time-to-first-audio (just need a sentence)\n  // Subsequent chunks: LARGE because they load while first plays\n  const isFirst = chunkIndex === 0;\n\n  switch (contentType) {\n    case 'short':\n      // Short responses — don't chunk at all, send whole\n      return { minLength: totalLength + 1, maxLength: 1000, idealLength: 500 };\n    case 'list':\n      // Lists — chunk by items\n      return isFirst\n        ? { minLength: 30, maxLength: 120, idealLength: 60 }\n        : { minLength: 80, maxLength: 300, idealLength: 150 };\n    case 'medium':\n      // Medium responses\n      return isFirst\n        ? { minLength: 40, maxLength: 150, idealLength: 80 }\n        : { minLength: 180, maxLength: 450, idealLength: 300 };\n    case 'long':\n    default:\n      // Long responses — first chunk ASAP, rest large for natural flow\n      return isFirst\n        ? { minLength: 40, maxLength: 180, idealLength: 100 }\n        : { minLength: 250, maxLength: 700, idealLength: 450 };\n  }\n}\n\n/**\n * Detect content type from accumulated text\n */\nfunction detectContentType(text: string): 'short' | 'medium' | 'long' | 'list' {\n  const len = text.length;\n\n  // Check for list patterns (numbered or bulleted)\n  const listPatterns = /^[\\s]*(?:\\d+[.):]\\s|[-•*]\\s)/m;\n  if (listPatterns.test(text)) {\n    return 'list';\n  }\n\n  // Length-based detection\n  if (len < 150) return 'short';\n  if (len < 400) return 'medium';\n  return 'long';\n}\n\n/**\n * Non-hook version for use outside React components\n *\n * Adaptive chunking: analyzes content to determine optimal chunk sizes\n * - Short replies (< 150 chars): send as single chunk\n * - Lists: chunk by items\n * - Medium (150-400): moderate chunks ~180 chars\n * - Long (> 400): larger chunks ~300 chars for natural flow\n */\nexport function createTextChunker(config: Partial<TextChunkerConfig> = {}) {\n  const baseCfg = { ...DEFAULT_CONFIG, ...config };\n  let buffer = '';\n  let chunkIndex = 0;\n  let totalReceived = 0;\n  let detectedType: 'short' | 'medium' | 'long' | 'list' | null = null;\n\n  // Threshold to start analyzing content type\n  const ANALYSIS_THRESHOLD = 80;\n\n  return {\n    push(text: string): string[] {\n      buffer += text;\n      totalReceived += text.length;\n      const chunks: string[] = [];\n\n      // Analyze content type once we have enough text\n      if (!detectedType && totalReceived >= ANALYSIS_THRESHOLD) {\n        detectedType = detectContentType(buffer);\n      }\n\n      // Get adaptive config based on content type and current chunk index\n      // First chunk = small, subsequent = larger (they load while first plays)\n      const adaptiveCfg = detectedType\n        ? getAdaptiveConfig(totalReceived, detectedType, chunkIndex)\n        : null;\n\n      const cfg = adaptiveCfg ?? {\n        minLength: chunkIndex === 0 ? baseCfg.firstChunkMinLength : baseCfg.minLength,\n        maxLength: baseCfg.maxLength,\n        idealLength: baseCfg.idealLength,\n      };\n\n      while (buffer.length >= cfg.minLength) {\n        const splitPos = findSplitPoint(\n          buffer,\n          cfg.minLength,\n          cfg.maxLength,\n          cfg.idealLength,\n          baseCfg.language,\n        );\n\n        if (splitPos === -1) {\n          if (buffer.length > cfg.maxLength * 1.5) {\n            const forced = buffer.slice(0, cfg.maxLength).trimEnd();\n            buffer = buffer.slice(cfg.maxLength).trimStart();\n            if (forced) {\n              chunks.push(forced);\n              chunkIndex++;\n            }\n          } else {\n            break;\n          }\n        } else {\n          const chunk = buffer.slice(0, splitPos).trimEnd();\n          buffer = buffer.slice(splitPos).trimStart();\n          if (chunk) {\n            chunks.push(chunk);\n            chunkIndex++;\n\n            // Re-detect type after first chunk for better accuracy\n            if (chunkIndex === 1 && buffer.length > 50) {\n              detectedType = detectContentType(buffer);\n            }\n          }\n        }\n\n        // Update config for next iteration (chunk index changed)\n        if (detectedType) {\n          const newCfg = getAdaptiveConfig(totalReceived, detectedType, chunkIndex);\n          cfg.minLength = newCfg.minLength;\n          cfg.maxLength = newCfg.maxLength;\n          cfg.idealLength = newCfg.idealLength;\n        }\n      }\n\n      return chunks;\n    },\n\n    flush(): string | null {\n      const remaining = buffer.trim();\n      buffer = '';\n      chunkIndex = 0;\n      totalReceived = 0;\n      detectedType = null;\n      return remaining || null;\n    },\n\n    reset() {\n      buffer = '';\n      chunkIndex = 0;\n      totalReceived = 0;\n      detectedType = null;\n    },\n\n    getBuffer() {\n      return buffer;\n    },\n\n    /** Get detected content type (for debugging) */\n    getContentType() {\n      return detectedType;\n    },\n\n    /** Get current chunk index */\n    getChunkIndex() {\n      return chunkIndex;\n    },\n  };\n}\n","import { useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport type { SDKRouterClient, ChatMessage, SpeechStreamChunk } from '@sdkrouter/client';\nimport { useSpeechRecorder } from '../speech-recorder/index.js';\nimport type { VADConfig } from '../speech-recorder/useVAD.js';\nimport { AISphereEventsContext } from '../../events/AISphereEventsProvider.js';\nimport type { TypedEmitter } from '../../events/emitter.js';\nimport type { AISphereEventMap } from '../../events/types.js';\n\nexport type ConversationPhase = 'idle' | 'listening' | 'thinking' | 'speaking';\n\nexport interface UseConversationOptions {\n  /** SDKRouterClient instance with audioUrl + llmUrl configured */\n  client: SDKRouterClient;\n  /** TTS voice, default 'nova' */\n  voice?: string;\n  /** LLM model or alias, default '@standard'. E.g. Model.smart() */\n  llmModel?: string;\n  /** TTS model or alias, default '@cheap'. E.g. AudioModel.quality() */\n  ttsModel?: string;\n  /** STT model or alias, default '@cheap'. E.g. AudioModel.cheap() */\n  sttModel?: string;\n  /** System prompt prepended to conversation */\n  systemPrompt?: string;\n  /** STT language hint (ISO 639-1) */\n  language?: string;\n  /** Silence duration (ms) before auto-stop recording. Default 600ms for conversation. */\n  silenceTimeout?: number;\n  /** Advanced VAD config for fine-tuning speech detection */\n  vadConfig?: Partial<VADConfig>;\n  /** TTS mode: 'buffered' (default), 'realtime' (SSE buffered), or 'streaming' (MediaSource real-time playback) */\n  ttsMode?: 'buffered' | 'realtime' | 'streaming';\n  /** Called whenever the conversation phase changes */\n  onPhaseChange?: (phase: ConversationPhase) => void;\n  /** Called when user transcript is ready */\n  onTranscript?: (text: string) => void;\n  /** Called when assistant response is ready */\n  onResponse?: (text: string) => void;\n  /** Called on any error */\n  onError?: (error: Error) => void;\n  /** Called every animation frame with mic FFT data during recording */\n  onAudioFrame?: (frame: { low: number; mid: number; high: number; volume: number }) => void;\n  /** Called on each SSE chunk with server-side audio analysis during TTS streaming */\n  onTTSAudioFrame?: (frame: { low: number; mid: number; high: number; volume: number }) => void;\n  /** Instructions for gpt-4o-mini-tts to control tone, pacing, and style across chunks */\n  ttsInstructions?: string;\n  /** Speed of generated audio (0.25 to 4.0, default 1.0) */\n  ttsSpeed?: number;\n}\n\nexport interface UseConversationReturn {\n  /** Current conversation phase */\n  phase: ConversationPhase;\n  /** Main toggle: idle→listen, listening→stop+process, speaking→interrupt */\n  toggle: () => void;\n  /** Force back to idle */\n  stop: () => void;\n  /** Full conversation history */\n  messages: ChatMessage[];\n  /** Last user transcript */\n  transcript: string;\n  /** Last assistant response */\n  response: string;\n  /** Last error message */\n  error: string | null;\n  /** Current TTS audio element (null when not speaking) */\n  ttsAudioEl: HTMLAudioElement | null;\n}\n\n// ── Blob URL cleanup helper ──\nfunction revokeAudioSrc(el: HTMLAudioElement) {\n  if (el.src?.startsWith('blob:')) {\n    URL.revokeObjectURL(el.src);\n  }\n}\n\n// ── TTS chunking via smart text chunker ──\nimport { createTextChunker } from '../../utils/useTextChunker.js';\n\n// Default VAD settings optimized for conversational interaction\nconst CONVERSATION_VAD_DEFAULTS: Partial<VADConfig> = {\n  silenceTimeout: 500,      // 0.5s pause ends turn (fast for conversation)\n  gracePeriod: 150,         // 150ms grace for word gaps\n  minSpeechDuration: 200,   // At least 200ms of speech\n  calibrationDuration: 200, // Quick 200ms calibration\n};\n\nexport function useConversation(options: UseConversationOptions): UseConversationReturn {\n  const {\n    client,\n    voice = 'nova',\n    llmModel = '@standard',\n    ttsModel = '@fast',\n    sttModel = '@fast',\n    systemPrompt,\n    language,\n    silenceTimeout = 500,  // Default 500ms for conversation mode\n    vadConfig,\n    ttsMode = 'buffered',\n    onPhaseChange,\n    onTranscript,\n    onResponse,\n    onError,\n    onAudioFrame,\n    onTTSAudioFrame,\n    ttsInstructions,\n    ttsSpeed,\n  } = options;\n\n  // Merge conversation defaults with user vadConfig\n  const mergedVadConfig: Partial<VADConfig> = {\n    ...CONVERSATION_VAD_DEFAULTS,\n    silenceTimeout, // User's silenceTimeout takes priority\n    ...vadConfig,   // User's vadConfig overrides everything\n  };\n\n  // Optional event emitter — does NOT throw if outside provider\n  const emitter = useContext(AISphereEventsContext) as TypedEmitter<AISphereEventMap> | null;\n\n  const [phase, setPhaseState] = useState<ConversationPhase>('idle');\n  const [messages, setMessages] = useState<ChatMessage[]>([]);\n  const [transcript, setTranscript] = useState('');\n  const [response, setResponse] = useState('');\n  const [error, setError] = useState<string | null>(null);\n  const [ttsAudioEl, setTtsAudioEl] = useState<HTMLAudioElement | null>(null);\n  const ttsAudioElRef = useRef<HTMLAudioElement | null>(null);\n\n  const phaseRef = useRef<ConversationPhase>('idle');\n  const messagesRef = useRef<ChatMessage[]>([]);\n  const abortRef = useRef<AbortController | null>(null);\n\n  // ── TTS sentence queue refs ──\n  const ttsQueueRef = useRef<HTMLAudioElement[]>([]);\n  const ttsPlayingRef = useRef(false);\n  const streamDoneRef = useRef(false);\n  const ttsPendingRef = useRef(0); // in-flight TTS requests not yet resolved\n\n  // Ordered TTS: sequence counters + pending map\n  const nextSeqRef = useRef(0);\n  const playSeqRef = useRef(0);\n  const pendingTTSRef = useRef<Map<number, HTMLAudioElement>>(new Map());\n\n  // Snapshot of messages length at pipeline start for cancel rollback\n  const pipelineStartLenRef = useRef(0);\n\n  // ── Stable callback refs (Fix #8) ──\n  // Avoid cascade re-creation when consumers pass inline arrows for callbacks\n  const onPhaseChangeRef = useRef(onPhaseChange);\n  onPhaseChangeRef.current = onPhaseChange;\n  const onErrorRef = useRef(onError);\n  onErrorRef.current = onError;\n  const onResponseRef = useRef(onResponse);\n  onResponseRef.current = onResponse;\n  const onTranscriptRef = useRef(onTranscript);\n  onTranscriptRef.current = onTranscript;\n  const emitterRef = useRef(emitter);\n  emitterRef.current = emitter;\n\n  const setPhase = useCallback((next: ConversationPhase) => {\n    phaseRef.current = next;\n    setPhaseState(next);\n    onPhaseChangeRef.current?.(next);\n    emitterRef.current?.emit('conversation:phase-change', next);\n  }, []); // no deps — all via refs\n\n  const handleError = useCallback((err: unknown) => {\n    const e = err instanceof Error ? err : new Error(String(err));\n    setError(e.message);\n    setPhase('idle');\n    onErrorRef.current?.(e);\n    emitterRef.current?.emit('conversation:error', e);\n  }, [setPhase]); // only setPhase, which is now stable\n\n  // ── Audio frame callbacks (defined before pipeline so no hoisting issue) ──\n\n  const onAudioFrameRef = useRef(onAudioFrame);\n  onAudioFrameRef.current = onAudioFrame;\n\n  const handleAudioFrame = useCallback((frame: { low: number; mid: number; high: number; volume: number }) => {\n    onAudioFrameRef.current?.(frame);\n    emitterRef.current?.emit('audio:mic-frame', frame);\n  }, []);\n\n  const onTTSAudioFrameRef = useRef(onTTSAudioFrame);\n  onTTSAudioFrameRef.current = onTTSAudioFrame;\n\n  const handleTTSChunk = useCallback((chunk: SpeechStreamChunk) => {\n    if (!chunk.analysis?.length) return;\n    const last = chunk.analysis[chunk.analysis.length - 1]!;\n    const frame = {\n      low: last.bands.low,\n      mid: last.bands.mid,\n      high: last.bands.high,\n      volume: last.rms,\n    };\n    onTTSAudioFrameRef.current?.(frame);\n    emitterRef.current?.emit('audio:tts-frame', frame);\n  }, []);\n\n  // ── TTS playback queue (gap-free sentence transitions) ──\n\n  const setTtsAudioState = useCallback((el: HTMLAudioElement | null) => {\n    ttsAudioElRef.current = el;\n    setTtsAudioEl(el);\n    if (el) {\n      emitterRef.current?.emit('audio:tts-start', el);\n    } else {\n      emitterRef.current?.emit('audio:tts-end', undefined as void);\n    }\n  }, []);\n\n  // Prefetch next audio in queue to reduce gap between chunks\n  const prefetchNext = useCallback(() => {\n    const next = ttsQueueRef.current[0];\n    if (next && next.preload !== 'auto') {\n      next.preload = 'auto';\n      next.load();\n    }\n  }, []);\n\n  // Track current audio for cleanup\n  const currentAudioRef = useRef<HTMLAudioElement | null>(null);\n\n  const playNext = useCallback(() => {\n    if (abortRef.current?.signal.aborted) return;\n\n    // Stop previous audio completely before starting new one\n    const prev = currentAudioRef.current;\n    if (prev) {\n      prev.pause();\n      prev.onended = null;\n      prev.onerror = null;\n      prev.currentTime = 0;\n      revokeAudioSrc(prev);\n    }\n\n    const next = ttsQueueRef.current.shift();\n    if (next) {\n      ttsPlayingRef.current = true;\n      currentAudioRef.current = next;\n      setTtsAudioState(next);\n      prefetchNext();\n\n      next.onended = () => {\n        revokeAudioSrc(next);\n        if (currentAudioRef.current !== next) return;\n        if (ttsQueueRef.current.length > 0) {\n          playNext();\n        } else {\n          ttsPlayingRef.current = false;\n          currentAudioRef.current = null;\n          setTtsAudioState(null);\n          if (streamDoneRef.current && ttsPendingRef.current === 0) {\n            setPhase('idle');\n          }\n        }\n      };\n      next.onerror = () => {\n        console.error('[conversation] TTS audio playback error');\n        revokeAudioSrc(next);\n        playNext();\n      };\n\n      // Wait for audio to be ready before playing\n      const tryPlay = () => {\n        next.play().catch((e) => {\n          console.error('[conversation] TTS play failed:', e);\n          revokeAudioSrc(next);\n          playNext();\n        });\n      };\n\n      if (next.readyState >= 2) {\n        tryPlay();\n      } else {\n        next.addEventListener('canplay', tryPlay, { once: true });\n        next.addEventListener('error', () => {\n          console.error('[conversation] Audio load error');\n          revokeAudioSrc(next);\n          playNext();\n        }, { once: true });\n        next.load();\n      }\n    } else {\n      ttsPlayingRef.current = false;\n      currentAudioRef.current = null;\n      setTtsAudioState(null);\n      if (streamDoneRef.current && ttsPendingRef.current === 0) {\n        setPhase('idle');\n      }\n    }\n  }, [setTtsAudioState, setPhase, prefetchNext]);\n\n  // Drain pending map in sequence order into the play queue\n  const drainPending = useCallback(() => {\n    const pending = pendingTTSRef.current;\n    while (pending.has(playSeqRef.current)) {\n      const el = pending.get(playSeqRef.current)!;\n      pending.delete(playSeqRef.current);\n      playSeqRef.current++;\n      // Prefetch as soon as added to queue\n      el.preload = 'auto';\n      el.load();\n      ttsQueueRef.current.push(el);\n    }\n    if (!ttsPlayingRef.current && ttsQueueRef.current.length > 0) {\n      playNext();\n    }\n  }, [playNext]);\n\n  const enqueueTTS = useCallback((text: string, signal: AbortSignal) => {\n    if (!text.trim() || signal.aborted) return;\n\n    const seq = nextSeqRef.current++;\n    ttsPendingRef.current++;\n\n    const instructions = ttsInstructions || undefined;\n    const speed = ttsSpeed ?? undefined;\n    let audioPromise: Promise<HTMLAudioElement>;\n    if (ttsMode === 'buffered') {\n      audioPromise = client.audio.speech(\n        { model: ttsModel, input: text, voice, instructions, speed },\n        { signal },\n      ).then((r) => r.audioEl);\n    } else if (ttsMode === 'streaming') {\n      audioPromise = client.audio.speechStreamRealtime(\n        { model: ttsModel, input: text, voice, instructions, speed, onChunk: handleTTSChunk },\n        { signal },\n      );\n    } else {\n      audioPromise = client.audio.speechStream(\n        { model: ttsModel, input: text, voice, instructions, speed, onChunk: handleTTSChunk },\n        { signal },\n      );\n    }\n\n    audioPromise.then((audioEl) => {\n      ttsPendingRef.current--;\n      if (signal.aborted) return;\n      pendingTTSRef.current.set(seq, audioEl);\n      drainPending();\n    }).catch((e) => {\n      ttsPendingRef.current--;\n      if (signal.aborted) return;\n      if (e instanceof DOMException && e.name === 'AbortError') return;\n      console.error('[conversation] TTS error:', e);\n      // If all pending resolved and stream is done, check idle\n      if (streamDoneRef.current && ttsPendingRef.current === 0\n          && !ttsPlayingRef.current && ttsQueueRef.current.length === 0) {\n        setPhase('idle');\n      }\n    });\n  }, [client, ttsModel, voice, ttsMode, ttsInstructions, ttsSpeed, drainPending, handleTTSChunk, setPhase]);\n\n  // ── Streaming LLM → sentence-level TTS pipeline ──\n\n  const runPipeline = useCallback(async (currentMessages: ChatMessage[]) => {\n    setError(null);\n\n    // Create a new AbortController for this pipeline run\n    abortRef.current?.abort();\n    const controller = new AbortController();\n    abortRef.current = controller;\n    const { signal } = controller;\n\n    // Reset TTS queue state\n    ttsQueueRef.current = [];\n    ttsPlayingRef.current = false;\n    streamDoneRef.current = false;\n    ttsPendingRef.current = 0;\n    nextSeqRef.current = 0;\n    playSeqRef.current = 0;\n    pendingTTSRef.current.clear();\n\n    const apiMessages: ChatMessage[] = [];\n    if (systemPrompt) {\n      apiMessages.push({ role: 'system', content: systemPrompt });\n    }\n    apiMessages.push(...currentMessages);\n\n    try {\n      console.log('[conversation] LLM streaming request:', llmModel, apiMessages.length, 'messages');\n\n      let responseAcc = '';\n\n      // Smart text chunker — prioritizes sentences, handles abbreviations, numbers, etc.\n      // Large chunks = fewer audio files = fewer stitch points = smoother playback\n      const chunker = createTextChunker({\n        firstChunkMinLength: 200,  // Wait for a good first sentence\n        minLength: 300,            // Minimum chunk size\n        maxLength: 800,            // Maximum before forced split\n        idealLength: 500,          // Target ~500 chars per chunk\n        language: language?.slice(0, 2) ?? 'en',\n      });\n\n      const stream = client.chat.stream({\n        model: llmModel,\n        messages: apiMessages,\n      }, { signal });\n\n      for await (const chunk of stream) {\n        if (signal.aborted) return;\n\n        const delta = chunk.choices[0]?.delta?.content;\n        if (!delta) continue;\n\n        responseAcc += delta;\n        setResponse(responseAcc);\n\n        // Push delta through chunker — returns complete chunks ready for TTS\n        const chunks = chunker.push(delta);\n\n        if (chunks.length > 0) {\n          console.log('[chunker] Emitted chunks:', chunks.map(c => `\"${c.slice(0, 50)}...\" (${c.length} chars)`));\n          if (phaseRef.current === 'thinking') {\n            setPhase('speaking');\n          }\n        }\n        for (const text of chunks) {\n          enqueueTTS(text, signal);\n        }\n      }\n\n      if (signal.aborted) return;\n\n      console.log('[conversation] LLM stream done:', responseAcc.slice(0, 100));\n      onResponseRef.current?.(responseAcc);\n      emitterRef.current?.emit('conversation:response', responseAcc);\n\n      // Append assistant message\n      const assistantMsg: ChatMessage = { role: 'assistant', content: responseAcc };\n      const withAssistant = [...messagesRef.current, assistantMsg];\n      messagesRef.current = withAssistant;\n      setMessages(withAssistant);\n\n      if (!responseAcc.trim()) {\n        console.log('[conversation] Empty response, back to idle');\n        setPhase('idle');\n        return;\n      }\n\n      // Flush remaining text in chunker buffer\n      const remaining = chunker.flush();\n      if (remaining) {\n        console.log('[chunker] Flush remaining:', `\"${remaining.slice(0, 50)}...\" (${remaining.length} chars)`);\n        if (phaseRef.current === 'thinking') {\n          setPhase('speaking');\n        }\n        enqueueTTS(remaining, signal);\n      } else {\n        console.log('[chunker] Flush: nothing remaining');\n      }\n\n      streamDoneRef.current = true;\n      // If nothing is playing, queue is empty, and no pending TTS requests, go idle\n      if (!ttsPlayingRef.current && ttsQueueRef.current.length === 0 && ttsPendingRef.current === 0) {\n        setPhase('idle');\n      }\n    } catch (err) {\n      // Ignore AbortError — it's expected when user cancels\n      if (err instanceof DOMException && err.name === 'AbortError') {\n        console.log('[conversation] Pipeline aborted');\n        return;\n      }\n      console.error('[conversation] Pipeline error:', err);\n      handleError(err);\n    }\n  }, [client, llmModel, systemPrompt, setPhase, handleError, enqueueTTS]);\n\n  // Stable ref so processTranscript always calls the latest runPipeline\n  const runPipelineRef = useRef(runPipeline);\n  runPipelineRef.current = runPipeline;\n\n  // ── Process after STT produces text ──────────────────────────────────────\n\n  const processTranscript = useCallback((text: string) => {\n    if (!text.trim()) {\n      setPhase('idle');\n      return;\n    }\n\n    setPhase('thinking');\n    setTranscript(text);\n    onTranscriptRef.current?.(text);\n    emitterRef.current?.emit('conversation:transcript', text);\n\n    // Snapshot message count before appending, for cancel rollback\n    pipelineStartLenRef.current = messagesRef.current.length;\n\n    // Append user message\n    const userMsg: ChatMessage = { role: 'user', content: text };\n    const withUser = [...messagesRef.current, userMsg];\n    messagesRef.current = withUser;\n    setMessages(withUser);\n\n    // Fire the LLM + TTS pipeline via ref (avoids stale closure)\n    console.log('[conversation] Transcript received, starting pipeline:', text.slice(0, 50));\n    runPipelineRef.current(withUser).catch((err) => {\n      console.error('[conversation] Pipeline catch:', err);\n      handleError(err);\n    });\n  }, [handleError, setPhase]);\n\n  // ── STT via useSpeechRecorder ────────────────────────────────────────────\n\n  const recorder = useSpeechRecorder({\n    client,\n    language,\n    model: sttModel,\n    silenceTimeout,\n    vadConfig: mergedVadConfig,\n    onResult: processTranscript,\n    onError: handleError,\n    onAudioFrame: handleAudioFrame,\n  });\n\n  // ── Public API ───────────────────────────────────────────────────────────\n\n  const stopTTS = useCallback(() => {\n    abortRef.current?.abort();\n    abortRef.current = null;\n\n    // Revoke blob URLs for queued elements\n    for (const el of ttsQueueRef.current) revokeAudioSrc(el);\n    // Revoke blob URLs for pending (out-of-order) elements\n    for (const el of pendingTTSRef.current.values()) revokeAudioSrc(el);\n\n    ttsQueueRef.current = [];\n    ttsPlayingRef.current = false;\n    streamDoneRef.current = false;\n    ttsPendingRef.current = 0;\n    nextSeqRef.current = 0;\n    playSeqRef.current = 0;\n    pendingTTSRef.current.clear();\n    currentAudioRef.current = null;\n\n    const el = ttsAudioElRef.current;\n    if (el) {\n      el.pause();\n      el.onended = null;\n      el.onerror = null;\n      revokeAudioSrc(el);\n    }\n    setTtsAudioState(null);\n  }, [setTtsAudioState]);\n\n  const toggle = useCallback(() => {\n    const current = phaseRef.current;\n\n    if (current === 'idle') {\n      setError(null);\n      setPhase('listening');\n      recorder.startRecording();\n      return;\n    }\n\n    if (current === 'listening') {\n      recorder.stopRecording();\n      setPhase('thinking');\n      return;\n    }\n\n    if (current === 'speaking') {\n      // Interrupt playback and switch to listening\n      stopTTS();\n      setError(null);\n      setPhase('listening');\n      recorder.startRecording();\n      return;\n    }\n\n    if (current === 'thinking') {\n      // Abort in-flight LLM/TTS requests and return to listening\n      stopTTS();\n      // Rollback messages to the snapshot before pipeline started\n      // This removes both the user message and any assistant message appended mid-stream\n      const snapshot = pipelineStartLenRef.current;\n      const restored = messagesRef.current.slice(0, snapshot);\n      messagesRef.current = restored;\n      setMessages(restored);\n      setError(null);\n      setPhase('listening');\n      recorder.startRecording();\n      return;\n    }\n  }, [recorder, setPhase, stopTTS]);\n\n  const stop = useCallback(() => {\n    // Stop recording\n    if (recorder.isRecording) {\n      recorder.stopRecording();\n    }\n    // Stop TTS + abort pipeline\n    stopTTS();\n    setPhase('idle');\n  }, [recorder, setPhase, stopTTS]);\n\n  // Ref so unmount effect can call the latest stop\n  const stopRef = useRef(stop);\n  stopRef.current = stop;\n\n  // ── Cleanup on unmount — stop recorder, TTS, and abort controller ──\n\n  useEffect(() => {\n    return () => {\n      stopRef.current();\n    };\n  }, []);\n\n  return {\n    phase,\n    toggle,\n    stop,\n    messages,\n    transcript,\n    response,\n    error,\n    ttsAudioEl,\n  };\n}\n","import { create } from 'zustand';\n\nexport interface LogEntry {\n  id: number;\n  timestamp: number;\n  event: string;\n  data: unknown;\n}\n\ninterface LoggerState {\n  logs: LogEntry[];\n  maxEntries: number;\n  nextId: number;\n  addLog: (event: string, data: unknown) => void;\n  clear: () => void;\n}\n\nexport const useLoggerStore = create<LoggerState>((set) => ({\n  logs: [],\n  maxEntries: 500,\n  nextId: 1,\n  addLog: (event, data) =>\n    set((state) => {\n      const entry: LogEntry = {\n        id: state.nextId,\n        timestamp: performance.now(),\n        event,\n        data,\n      };\n      const logs = [...state.logs, entry];\n      const trimmed = logs.length > state.maxEntries\n        ? logs.slice(logs.length - state.maxEntries)\n        : logs;\n      return { logs: trimmed, nextId: state.nextId + 1 };\n    }),\n  clear: () => set({ logs: [], nextId: 1 }),\n}));\n","import { useContext, useEffect } from 'react';\nimport { AISphereEventsContext } from '../events/AISphereEventsProvider.js';\nimport type { AISphereEventMap } from '../events/types.js';\nimport { useLoggerStore } from './store.js';\n\nconst THROTTLE_MS = 200;\n\nexport function useLoggerBridge(): void {\n  const emitter = useContext(AISphereEventsContext);\n  const addLog = useLoggerStore((s) => s.addLog);\n\n  useEffect(() => {\n    if (!emitter) return;\n\n    const events: (keyof AISphereEventMap)[] = [\n      'conversation:phase-change',\n      'conversation:transcript',\n      'conversation:response',\n      'conversation:error',\n      'audio:mic-frame',\n      'audio:tts-frame',\n      'audio:tts-start',\n      'audio:tts-end',\n    ];\n\n    const lastLogTime: Record<string, number> = {};\n    const unsubs = events.map((event) =>\n      emitter.on(event, (data: any) => {\n        // Throttle high-frequency audio frame events\n        if (event === 'audio:mic-frame' || event === 'audio:tts-frame') {\n          const now = performance.now();\n          if (now - (lastLogTime[event] ?? 0) < THROTTLE_MS) return;\n          lastLogTime[event] = now;\n        }\n        // Serialize special types for readability\n        const serialized = event === 'audio:tts-start'\n          ? '<HTMLAudioElement>'\n          : event === 'conversation:error'\n            ? (data as Error).message\n            : data;\n        addLog(event, serialized);\n      }),\n    );\n    return () => { for (const unsub of unsubs) unsub(); };\n  }, [emitter, addLog]);\n}\n"]}