mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2026-10-26 13:24:33 +00:00
* feat(elevenlabs): forward DTMF to the agent and support llm:update
Adds opt-in llmOptions.dtmf {enable, interDigitTimeout, finishOnKey}.
Digits are buffered until finishOnKey, the inter-digit timeout or 50
digits, then sent as a user_message with source_medium "dtmf". Each
key press also sends user_activity so the agent turn timeout does not
fire while the caller is typing.
llm:update now forwards user_message, user_activity and
contextual_update client events instead of ignoring them.
Client events escape "|" so payloads containing it are no longer
split by the api argument delimiter (this also fixes tool results).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(elevenlabs): send DTMF per digit like ultravox, drop llmOptions.dtmf
Match the ultravox adapter: DTMF is always forwarded, with no llmOptions
setting. Each digit is sent as soon as it arrives, as a user_message with
source_medium "dtmf". Digit buffering, the inter-digit timeout and
finishOnKey are left to the agent's dtmf_input_settings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(elevenlabs): buffer DTMF behind llmOptions.dtmf again
Per-digit sending does not work for ElevenLabs. Over the agent
WebSocket each user_message becomes its own turn: "1234#" produced 5
turns, and the agent answered "Are you still there?". The same digits
sent as a single message produce one dtmf turn, "1234".
- restores the opt-in llmOptions.dtmf {enable, interDigitTimeout, finishOnKey}
- digits are buffered and sent as one user_message, source_medium "dtmf"
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: shared DtmfInput util with gather dtmf semantics
Any llm or agent vendor can turn caller DTMF into whole entries without
copying gather or touching it.
- lib/utils/dtmf-input.js uses gather options: finishOnKey, numDigits,
minDigits, maxDigits, interDigitTimeout, timeout (15s default, 0 = off)
- no invented defaults: no implicit "#", no 2s timeout, no 50-digit cap
- minDigits defaults to 1; in gather an unset minDigits never arms the
inter-digit timer
- stop() removes only its own dtmf listener
- elevenlabs uses it behind llmOptions.dtmf.enable
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(dtmf): review fixes for DtmfInput and elevenlabs
- inter-digit timer replaces the overall timeout while typing, as in gather
- warn when no option can ever complete an entry
- no DtmfInput when the session connects after kill (listener leak)
- llm:update rejects user_message/contextual_update without string text,
since an ElevenLabs error event ends the conversation
- unit tests use mock timers instead of wall-clock waits
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>