From 1d1d16e221c7db519d31819c0efe564257414f4e Mon Sep 17 00:00:00 2001 From: Ben Younes Date: Wed, 9 Sep 2026 16:54:07 +0200 Subject: [PATCH] fix: return tts:tokens-result when tts:tokens command is missing id (#1548) (#1577) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _lccTtsTokens silently returned on a missing `id`, leaving the WS client with no feedback — no tts:tokens-result, no audio, only a server-side info log. Mirror the existing missing-`tokens` handling and reply with status 'failed' / reason 'missing id' so callers that omit `id` (e.g. the Python SDK) get an actionable result. --- lib/session/call-session.js | 5 ++++- test/index.js | 1 + test/tts-tokens-missing-id-test.js | 34 ++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 test/tts-tokens-missing-id-test.js diff --git a/lib/session/call-session.js b/lib/session/call-session.js index ca743a75..b369e0ba 100644 --- a/lib/session/call-session.js +++ b/lib/session/call-session.js @@ -1986,7 +1986,10 @@ Duration=${duration} ` if (id === undefined) { this.logger.info({opts}, 'CallSession:_lccTtsTokens - invalid command since id is missing'); - return; + return this.requestor.request('tts:tokens-result', '/tokens-result', { + status: 'failed', + reason: 'missing id' + }).catch((err) => this.logger.debug({err}, 'CallSession:_notifyTaskStatus - Error sending')); } else if (tokens === undefined) { this.logger.info({opts}, 'CallSession:_lccTtsTokens - invalid command since tokens is missing'); diff --git a/test/index.js b/test/index.js index 46f525a4..1ec44bea 100644 --- a/test/index.js +++ b/test/index.js @@ -4,6 +4,7 @@ require('./ws-requestor-unit-test'); require('./http-requestor-retry-test'); require('./http-requestor-unit-test'); require('./unit-tests'); +require('./tts-tokens-missing-id-test'); require('./hold-unhold-test'); require('./docker_start'); require('./create-test-db'); diff --git a/test/tts-tokens-missing-id-test.js b/test/tts-tokens-missing-id-test.js new file mode 100644 index 00000000..89e0f0d8 --- /dev/null +++ b/test/tts-tokens-missing-id-test.js @@ -0,0 +1,34 @@ +const test = require('tape'); +const sinon = require('sinon'); +const CallSession = require('../lib/session/call-session'); + +// Regression test for #1548: _lccTtsTokens must not silently drop a tts:tokens +// command that is missing `id`. It should reply with a tts:tokens-result of +// status 'failed'/reason 'missing id', mirroring how a missing `tokens` field +// is already handled — otherwise the WS client (e.g. the Python SDK, which does +// not send `id`) gets no feedback at all. + +const buildFakeSession = () => { + const requestor = { request: sinon.stub().resolves({}) }; + const logger = { info: sinon.stub(), debug: sinon.stub() }; + return { requestor, logger, ttsStreamingBuffer: { bufferTokens: sinon.stub().resolves({}) } }; +}; + +test('_lccTtsTokens: missing id returns a failed tts:tokens-result instead of silently dropping', async (t) => { + const session = buildFakeSession(); + + // WHEN a tts:tokens command arrives without `id` + await CallSession.prototype._lccTtsTokens.call(session, {tokens: 'hello world'}); + + // THEN a tts:tokens-result with status 'failed'/reason 'missing id' is sent back + t.ok(session.requestor.request.calledOnce, 'requestor.request should be called once'); + const [type, path, payload] = session.requestor.request.firstCall.args; + t.equal(type, 'tts:tokens-result', 'response type is tts:tokens-result'); + t.equal(path, '/tokens-result', 'response path is /tokens-result'); + t.equal(payload.status, 'failed', 'status is failed'); + t.equal(payload.reason, 'missing id', 'reason is missing id'); + + // AND tokens are never buffered for an invalid command + t.ok(session.ttsStreamingBuffer.bufferTokens.notCalled, 'tokens are not buffered when id is missing'); + t.end(); +});