@apteva/apteva-kit 0.1.135 → 0.1.137

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -4491,6 +4491,8 @@ function useVoiceSession(config) {
4491
4491
  const mutedRef = useRef9(false);
4492
4492
  const configRef = useRef9(config);
4493
4493
  configRef.current = config;
4494
+ const agentSpeakingRef = useRef9(false);
4495
+ const agentSpeakingTimeoutRef = useRef9(null);
4494
4496
  const cleanup = useCallback4(() => {
4495
4497
  if (durationIntervalRef.current) {
4496
4498
  clearInterval(durationIntervalRef.current);
@@ -4527,6 +4529,11 @@ function useVoiceSession(config) {
4527
4529
  }
4528
4530
  nextPlayTimeRef.current = 0;
4529
4531
  mutedRef.current = false;
4532
+ agentSpeakingRef.current = false;
4533
+ if (agentSpeakingTimeoutRef.current) {
4534
+ clearTimeout(agentSpeakingTimeoutRef.current);
4535
+ agentSpeakingTimeoutRef.current = null;
4536
+ }
4530
4537
  setMuted(false);
4531
4538
  setPartialTranscript("");
4532
4539
  setDuration(0);
@@ -4554,6 +4561,14 @@ function useVoiceSession(config) {
4554
4561
  const startTime = Math.max(currentTime, nextPlayTimeRef.current);
4555
4562
  source.start(startTime);
4556
4563
  nextPlayTimeRef.current = startTime + audioBuffer.duration;
4564
+ agentSpeakingRef.current = true;
4565
+ if (agentSpeakingTimeoutRef.current) {
4566
+ clearTimeout(agentSpeakingTimeoutRef.current);
4567
+ }
4568
+ const remainingMs = (nextPlayTimeRef.current - currentTime) * 1e3 + 150;
4569
+ agentSpeakingTimeoutRef.current = setTimeout(() => {
4570
+ agentSpeakingRef.current = false;
4571
+ }, remainingMs);
4557
4572
  }, []);
4558
4573
  const startCaptureRef = useRef9(() => {
4559
4574
  });
@@ -4617,13 +4632,23 @@ function useVoiceSession(config) {
4617
4632
  if (!ws) return;
4618
4633
  try {
4619
4634
  captureCtxRef.current = new AudioContext();
4635
+ if (captureCtxRef.current.state === "suspended") {
4636
+ await captureCtxRef.current.resume();
4637
+ }
4620
4638
  const nativeSampleRate = captureCtxRef.current.sampleRate;
4621
- mediaStreamRef.current = await navigator.mediaDevices.getUserMedia({ audio: true });
4639
+ mediaStreamRef.current = await navigator.mediaDevices.getUserMedia({
4640
+ audio: {
4641
+ echoCancellation: true,
4642
+ noiseSuppression: true,
4643
+ autoGainControl: true
4644
+ }
4645
+ });
4622
4646
  const source = captureCtxRef.current.createMediaStreamSource(mediaStreamRef.current);
4623
4647
  processorRef.current = captureCtxRef.current.createScriptProcessor(2048, 1, 1);
4624
4648
  processorRef.current.onaudioprocess = (e) => {
4625
4649
  if (!ws || ws.readyState !== WebSocket.OPEN) return;
4626
4650
  if (mutedRef.current) return;
4651
+ if (agentSpeakingRef.current) return;
4627
4652
  const inputData = e.inputBuffer.getChannelData(0);
4628
4653
  const resampledData = resampleAudio(inputData, nativeSampleRate, 16e3);
4629
4654
  const int16Data = float32ToInt16(resampledData);
@@ -4656,6 +4681,12 @@ function useVoiceSession(config) {
4656
4681
  }
4657
4682
  const ws = new WebSocket(wsUrl);
4658
4683
  wsRef.current = ws;
4684
+ if (!playbackCtxRef.current) {
4685
+ playbackCtxRef.current = new AudioContext({ sampleRate: 24e3 });
4686
+ }
4687
+ if (playbackCtxRef.current.state === "suspended") {
4688
+ playbackCtxRef.current.resume();
4689
+ }
4659
4690
  ws.onopen = () => {
4660
4691
  const provider = configRef.current.provider || "openai";
4661
4692
  const voice = configRef.current.voice || "ash";