test(voice): harden live STT transcript checks

This commit is contained in:
Peter Steinberger
2026-04-25 19:35:30 +01:00
parent f204f0c999
commit e473577eaa
4 changed files with 27 additions and 4 deletions

View File

@@ -44,6 +44,9 @@ Docs: https://docs.openclaw.ai
- Plugins/startup: remove ownerless bundled runtime-dependency install locks
after a short grace window and include lock owner details when startup times
out waiting for a plugin runtime-deps lock. Thanks @steipete.
- Live tests/voice: accept common STT variants for OpenClaw and ElevenLabs
brand names so provider smoke tests fail on real regressions rather than
equivalent transcripts.
- Agents/replies: forward sanitized underlying agent failure details on external
channels instead of replacing unknown failures with a generic retry message.
Thanks @steipete.

View File

@@ -61,7 +61,7 @@ describeLive("elevenlabs plugin live", () => {
const normalized = normalizeTranscriptForMatch(transcript?.text ?? "");
expect(normalized).toContain("openclaw");
expect(normalized).toContain("elevenlabs");
expect(normalized).toMatch(/(?:elevenlabs|11labs)/);
}, 90_000);
it("streams realtime STT through the registered transcription provider", async () => {

View File

@@ -0,0 +1,11 @@
import { describe, expect, it } from "vitest";
import { normalizeTranscriptForMatch } from "./stt-live-audio.js";
describe("normalizeTranscriptForMatch", () => {
it("normalizes punctuation and common OpenClaw live transcription variants", () => {
expect(normalizeTranscriptForMatch("Open-Claw integration OK")).toBe("openclawintegrationok");
expect(normalizeTranscriptForMatch("Testing OpenFlaw realtime transcription")).toMatch(
/open(?:claw|flaw)/,
);
});
});

View File

@@ -12,6 +12,10 @@ export function normalizeTranscriptForMatch(value: string): string {
return value.toLowerCase().replace(/[^a-z0-9]+/g, "");
}
type ExpectedTranscriptMatch = RegExp | string;
const DEFAULT_OPENCLAW_TRANSCRIPT_MATCH = /open(?:claw|flaw)/;
export async function waitForLiveExpectation(expectation: () => void, timeoutMs = 30_000) {
const started = Date.now();
let lastError: unknown;
@@ -86,7 +90,7 @@ export async function runRealtimeSttLiveTest(params: {
provider: RealtimeTranscriptionProviderPlugin;
providerConfig: RealtimeTranscriptionProviderConfig;
audio: Buffer;
expectedNormalizedText?: string;
expectedNormalizedText?: ExpectedTranscriptMatch;
timeoutMs?: number;
closeBeforeWait?: boolean;
chunkSize?: number;
@@ -95,7 +99,7 @@ export async function runRealtimeSttLiveTest(params: {
const transcripts: string[] = [];
const partials: string[] = [];
const errors: Error[] = [];
const expected = params.expectedNormalizedText ?? "openclaw";
const expected = params.expectedNormalizedText ?? DEFAULT_OPENCLAW_TRANSCRIPT_MATCH;
const session = params.provider.createSession({
providerConfig: params.providerConfig,
onPartial: (partial) => partials.push(partial),
@@ -119,7 +123,12 @@ export async function runRealtimeSttLiveTest(params: {
if (errors[0]) {
throw errors[0];
}
expect(normalizeTranscriptForMatch(transcripts.join(" "))).toContain(expected);
const normalized = normalizeTranscriptForMatch(transcripts.join(" "));
if (typeof expected === "string") {
expect(normalized).toContain(expected);
} else {
expect(normalized).toMatch(expected);
}
}, params.timeoutMs ?? 60_000);
} finally {
session.close();