Problem:
When the gateway restarts, loadActiveCalls() reloads non-terminal calls from
calls.jsonl. However, these calls may have already ended (e.g., Twilio timed
them out, or webhook couldn't reach local URL) and are now stale. This causes
the concurrent call limit to be reached with phantom calls.
Solution:
- Add getCallStatus() method to VoiceCallProvider interface
- Implement getCallStatus() for all providers (Twilio, Plivo, Telnyx, Mock)
- On load, verify each non-terminal call with the provider before adding to activeCalls
- Skip calls that the provider reports as terminal (completed, failed, etc.)
- Also skip calls older than maxDurationSeconds as a fallback
This is an improvement over PR #2810 which only uses time-based cleanup.
By querying the provider, we can accurately determine if a call is still active.
* fix(voice-call): prevent audio overlap with TTS queue
Add a TTS queue to serialize audio playback and prevent overlapping
speech during voice calls. Previously, concurrent speak() calls could
send audio chunks simultaneously, causing garbled/choppy output.
Changes:
- Add queueTts() to MediaStreamHandler for sequential TTS playback
- Wrap playTtsViaStream() audio sending in the queue
- Clear queue on barge-in (when user starts speaking)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(voice-call): use iterative queue processing to prevent heap exhaustion
The recursive processQueue() pattern accumulated stack frames, causing
JavaScript heap out of memory errors on macOS CI. Convert to while loop
for constant stack usage regardless of queue depth.
* fix: prevent voice-call TTS overlap (#1713) (thanks @dguido)
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
The `validateProviderConfig()` function now checks both config values
AND environment variables when validating provider credentials. This
aligns the validation behavior with `resolveProvider()` which already
falls back to env vars.
Previously, users who set credentials via environment variables would
get validation errors even though the credentials would be found at
runtime. The error messages correctly suggested env vars as an
alternative, but the validation didn't actually check them.
Affects all three supported providers: Twilio, Telnyx, and Plivo.
Fixes#1709
Co-Authored-By: Claude <noreply@anthropic.com>
- Switch from inline to URL-based TwiML for outbound calls
- Store TwiML content temporarily and serve on webhook request
- Add twimlStorage map and cleanup helper methods
- Fix TwiML serving to handle CallStatus='in-progress' on initial request
Closes#864