Skip to content

Commit 607e6c2

Browse files
committed
fix: validate elevenlabs realtime numeric config
1 parent 4829146 commit 607e6c2

2 files changed

Lines changed: 84 additions & 5 deletions

File tree

extensions/elevenlabs/realtime-transcription-provider.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,58 @@ describe("buildElevenLabsRealtimeTranscriptionProvider", () => {
3939
});
4040
});
4141

42+
it("drops malformed numeric realtime config values", () => {
43+
const provider = buildElevenLabsRealtimeTranscriptionProvider();
44+
const resolved = provider.resolveConfig?.({
45+
cfg: {} as OpenClawConfig,
46+
rawConfig: {
47+
providers: {
48+
elevenlabs: {
49+
sample_rate: "8000.5",
50+
vad_silence_threshold_secs: "999",
51+
vad_threshold: "0",
52+
min_speech_duration_ms: "0",
53+
min_silence_duration_ms: "10.5",
54+
},
55+
},
56+
},
57+
});
58+
59+
expect(resolved).toMatchObject({
60+
sampleRate: undefined,
61+
vadSilenceThresholdSecs: undefined,
62+
vadThreshold: undefined,
63+
minSpeechDurationMs: undefined,
64+
minSilenceDurationMs: undefined,
65+
});
66+
});
67+
68+
it("keeps realtime VAD numeric config inside provider ranges", () => {
69+
const provider = buildElevenLabsRealtimeTranscriptionProvider();
70+
const resolved = provider.resolveConfig?.({
71+
cfg: {} as OpenClawConfig,
72+
rawConfig: {
73+
providers: {
74+
elevenlabs: {
75+
sample_rate: "8000",
76+
vad_silence_threshold_secs: "3",
77+
vad_threshold: "0.9",
78+
min_speech_duration_ms: "50",
79+
min_silence_duration_ms: "2000",
80+
},
81+
},
82+
},
83+
});
84+
85+
expect(resolved).toMatchObject({
86+
sampleRate: 8000,
87+
vadSilenceThresholdSecs: 3,
88+
vadThreshold: 0.9,
89+
minSpeechDurationMs: 50,
90+
minSilenceDurationMs: 2000,
91+
});
92+
});
93+
4294
it("builds an ElevenLabs realtime websocket URL", () => {
4395
const url = testing.toElevenLabsRealtimeWsUrl({
4496
apiKey: "eleven-key",

extensions/elevenlabs/realtime-transcription-provider.ts

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,23 @@ function normalizeCommitStrategy(value: unknown): "manual" | "vad" | undefined {
7878
throw new Error(`Invalid ElevenLabs realtime transcription commit strategy: ${normalized}`);
7979
}
8080

81+
function normalizePositiveSafeInteger(value: unknown): number | undefined {
82+
const parsed = readFiniteNumber(value);
83+
return parsed !== undefined && Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
84+
}
85+
86+
function normalizeFiniteRange(value: unknown, min: number, max: number): number | undefined {
87+
const parsed = readFiniteNumber(value);
88+
return parsed !== undefined && parsed >= min && parsed <= max ? parsed : undefined;
89+
}
90+
91+
function normalizeIntegerRange(value: unknown, min: number, max: number): number | undefined {
92+
const parsed = readFiniteNumber(value);
93+
return parsed !== undefined && Number.isSafeInteger(parsed) && parsed >= min && parsed <= max
94+
? parsed
95+
: undefined;
96+
}
97+
8198
function normalizeProviderConfig(
8299
config: RealtimeTranscriptionProviderConfig,
83100
): ElevenLabsRealtimeTranscriptionProviderConfig {
@@ -90,15 +107,25 @@ function normalizeProviderConfig(
90107
baseUrl: normalizeOptionalString(raw.baseUrl),
91108
modelId: normalizeOptionalString(raw.modelId ?? raw.model ?? raw.sttModel),
92109
audioFormat: normalizeOptionalString(raw.audioFormat ?? raw.audio_format ?? raw.encoding),
93-
sampleRate: readFiniteNumber(raw.sampleRate ?? raw.sample_rate),
110+
sampleRate: normalizePositiveSafeInteger(raw.sampleRate ?? raw.sample_rate),
94111
languageCode: normalizeOptionalString(raw.languageCode ?? raw.language),
95112
commitStrategy: normalizeCommitStrategy(raw.commitStrategy ?? raw.commit_strategy),
96-
vadSilenceThresholdSecs: readFiniteNumber(
113+
vadSilenceThresholdSecs: normalizeFiniteRange(
97114
raw.vadSilenceThresholdSecs ?? raw.vad_silence_threshold_secs,
115+
0.3,
116+
3,
117+
),
118+
vadThreshold: normalizeFiniteRange(raw.vadThreshold ?? raw.vad_threshold, 0.1, 0.9),
119+
minSpeechDurationMs: normalizeIntegerRange(
120+
raw.minSpeechDurationMs ?? raw.min_speech_duration_ms,
121+
50,
122+
2_000,
123+
),
124+
minSilenceDurationMs: normalizeIntegerRange(
125+
raw.minSilenceDurationMs ?? raw.min_silence_duration_ms,
126+
50,
127+
2_000,
98128
),
99-
vadThreshold: readFiniteNumber(raw.vadThreshold ?? raw.vad_threshold),
100-
minSpeechDurationMs: readFiniteNumber(raw.minSpeechDurationMs ?? raw.min_speech_duration_ms),
101-
minSilenceDurationMs: readFiniteNumber(raw.minSilenceDurationMs ?? raw.min_silence_duration_ms),
102129
};
103130
}
104131

0 commit comments

Comments
 (0)