fix: speechmatics credential test ignored the configured region (#563)

The speechmatics branch of the /test route destructured only api_key out of the
decrypted credential, so testSpeechmaticsStt() passed realtimeUrl: undefined to
the sdk. ConnectionConfigFull only applies an override when the value is truthy,
so every credential was silently tested against wss://eu2.rt.speechmatics.com/v2
no matter which region was stored - a neu or wus key was judged by whatever eu2
happened to answer.

- pass speechmatics_stt_uri through from the route
- normalize it before handing it to the sdk. The field holds a bare hostname,
  which the sdk cannot use as-is: it appends the language, yielding
  "eu2.rt.speechmatics.com/en" and ERR_INVALID_URL. At call time the same value
  goes to mod_speechmatics_transcribe as SPEECHMATICS_HOST, which always
  connects over wss on port 443 with a path of /v2, so build exactly that url.
  Anything else - a full ws url, a port - now fails the test with an actionable
  message rather than passing against an endpoint only the test can reach, and a
  credential that has lost the field fails too: the feature server omits
  SPEECHMATICS_HOST when it is unset and the module refuses the session, so
  defaulting to a hosted region here would show a green check on a dead
  credential.
- record the speechmatics STT result with sttTestResult(), not ttsTestResult(),
  which is what every other STT vendor in this file does; the tts column was
  being stamped for an STT-only vendor

Adds coverage for the url building to the main test suite - it is the part of
this that can be exercised without an api key.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hoan Luu HuuandClaude Opus 5 authored and GitHub committed 2026-08-14 11:06:28 -04:00
1 parent 53279a59c0
commit baf80cb84c
4 files changed
+64 -5

No files matched your search

+24 -1
View File
@@ -83,11 +83,33 @@ const testSonioxStt = async(logger, credentials) => {
});
};
/**
* speechmatics_stt_uri is stored as a bare hostname - eu2.rt.speechmatics.com and friends for
* the hosted service, or the hostname of an on-prem container - while the sdk wants a full url
* that it appends the language to. At call time the stored value is handed to
* mod_speechmatics_transcribe as SPEECHMATICS_HOST, which always dials wss on port 443 with a
* path of /v2, so test exactly that. Accepting a shape the runtime cannot dial (a full url, a
* port) would report a credential as good that then fails on every call, and quietly falling
* back to a default host would do the same for a credential that has lost the field - the
* feature server omits SPEECHMATICS_HOST entirely when it is unset, and the module then
* refuses to start the session.
*/
const speechmaticsRealtimeUrl = (speechmatics_stt_uri) => {
const host = (speechmatics_stt_uri || '').trim();
if (!host) throw new Error('speechmatics_stt_uri is not set on this speech credential');
if (!/^[a-z0-9.-]+$/i.test(host)) {
throw new Error(
`invalid speechmatics_stt_uri '${host}': expected a bare hostname, e.g. eu2.rt.speechmatics.com`);
}
return `wss://${host}/v2`;
};
const testSpeechmaticsStt = async(logger, credentials) => {
const {api_key, speechmatics_stt_uri} = credentials;
const realtimeUrl = speechmaticsRealtimeUrl(speechmatics_stt_uri);
return new Promise(async(resolve, reject) => {
try {
const session = new RealtimeSession({ apiKey: api_key, realtimeUrl: speechmatics_stt_uri });
const session = new RealtimeSession({ apiKey: api_key, realtimeUrl });
let transcription = '';
session.addListener('Error', (error) => {
reject(error);
@@ -1845,6 +1867,7 @@ module.exports = {
testVerbioStt,
getLanguagesAndVoicesForVendor,
testSpeechmaticsStt,
speechmaticsRealtimeUrl,
testCartesia,
testVoxistStt,
testOpenAiStt,