mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 12:56:01 -06:00
test(openai): verify terminal audio cleanup
This commit is contained in:
@@ -185,6 +185,72 @@ describe("OpenAIQuicksilverVoiceBridge", () => {
|
||||
expect(harness.onReady).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("bounds queued audio by aggregate bytes before session readiness", async () => {
|
||||
const harness = createHarness({ autoStart: false });
|
||||
const connecting = harness.bridge.connect();
|
||||
await vi.waitFor(() => expect(harness.socket.readyState).toBe(1));
|
||||
|
||||
harness.bridge.sendAudio(Buffer.alloc(512 * 1024, 0x01));
|
||||
harness.bridge.sendAudio(Buffer.alloc(512 * 1024, 0x02));
|
||||
harness.bridge.sendAudio(Buffer.from("overflow"));
|
||||
harness.socket.serverEvent({
|
||||
type: "session.started",
|
||||
session: { id: "live-1", expires_at: Math.floor(Date.now() / 1000) + 60 },
|
||||
});
|
||||
await connecting;
|
||||
|
||||
const audioEvents = sentEvents(harness.socket).filter(
|
||||
(event) => event.type === "input_audio.append",
|
||||
);
|
||||
expect(audioEvents).toHaveLength(2);
|
||||
expect(
|
||||
audioEvents.map((event) => Buffer.from(String(event.audio), "base64").byteLength),
|
||||
).toEqual([512 * 1024, 512 * 1024]);
|
||||
harness.bridge.close();
|
||||
});
|
||||
|
||||
it("does not carry queued audio across terminal close and explicit reconnect", async () => {
|
||||
const sockets: FakeSocket[] = [];
|
||||
const bridge = new OpenAIQuicksilverVoiceBridge({
|
||||
providerConfig: {},
|
||||
model: "gpt-live-1-codex",
|
||||
audioFormat: { encoding: "pcm16", sampleRateHz: 24000, channels: 1 },
|
||||
resolveAuth: async () => ({ type: "api-key", token: "test-key" }),
|
||||
webSocketFactory: (_url, _options) => {
|
||||
const socket = new FakeSocket(false);
|
||||
sockets.push(socket);
|
||||
queueMicrotask(() => socket.open());
|
||||
return socket as unknown as OpenAIQuicksilverSocket;
|
||||
},
|
||||
onAudio: vi.fn(),
|
||||
onClearAudio: vi.fn(),
|
||||
});
|
||||
|
||||
const firstConnect = bridge.connect();
|
||||
await vi.waitFor(() => expect(sockets[0]?.readyState).toBe(1));
|
||||
bridge.sendAudio(Buffer.from("queued-before-close"));
|
||||
bridge.close();
|
||||
await firstConnect;
|
||||
bridge.sendAudio(Buffer.from("sent-after-close"));
|
||||
|
||||
const reconnecting = bridge.connect();
|
||||
await vi.waitFor(() => expect(sockets[1]?.readyState).toBe(1));
|
||||
sockets[1]?.serverEvent({
|
||||
type: "session.started",
|
||||
session: { id: "live-2", expires_at: Math.floor(Date.now() / 1000) + 60 },
|
||||
});
|
||||
await reconnecting;
|
||||
|
||||
const secondSocket = sockets[1];
|
||||
if (!secondSocket) {
|
||||
throw new Error("expected bridge to reconnect");
|
||||
}
|
||||
expect(
|
||||
sentEvents(secondSocket).filter((event) => event.type === "input_audio.append"),
|
||||
).toHaveLength(0);
|
||||
bridge.close();
|
||||
});
|
||||
|
||||
it("rejects startup failures without emitting terminal callbacks", async () => {
|
||||
const harness = createHarness({ autoStart: false });
|
||||
const connecting = harness.bridge.connect();
|
||||
|
||||
@@ -1517,6 +1517,75 @@ describe("buildOpenAIRealtimeVoiceProvider", () => {
|
||||
expect(bridge.isConnected()).toBe(true);
|
||||
});
|
||||
|
||||
it("bounds queued audio by aggregate bytes before session readiness", async () => {
|
||||
const provider = buildOpenAIRealtimeVoiceProvider();
|
||||
const bridge = provider.createBridge({
|
||||
providerConfig: { apiKey: "sk-test" }, // pragma: allowlist secret
|
||||
onAudio: vi.fn(),
|
||||
onClearAudio: vi.fn(),
|
||||
});
|
||||
const connecting = bridge.connect();
|
||||
const socket = FakeWebSocket.instances[0];
|
||||
if (!socket) {
|
||||
throw new Error("expected bridge to create a websocket");
|
||||
}
|
||||
socket.readyState = FakeWebSocket.OPEN;
|
||||
socket.emit("open");
|
||||
await Promise.resolve();
|
||||
|
||||
bridge.sendAudio(Buffer.alloc(512 * 1024, 0x01));
|
||||
bridge.sendAudio(Buffer.alloc(512 * 1024, 0x02));
|
||||
bridge.sendAudio(Buffer.from("overflow"));
|
||||
socket.emit("message", Buffer.from(JSON.stringify({ type: "session.updated" })));
|
||||
await connecting;
|
||||
|
||||
const audioEvents = parseSent(socket).filter(
|
||||
(event) => event.type === "input_audio_buffer.append",
|
||||
);
|
||||
expect(audioEvents).toHaveLength(2);
|
||||
expect(
|
||||
audioEvents.map((event) => Buffer.from(String(event.audio), "base64").byteLength),
|
||||
).toEqual([512 * 1024, 512 * 1024]);
|
||||
bridge.close();
|
||||
});
|
||||
|
||||
it("does not carry queued audio across terminal close and explicit reconnect", async () => {
|
||||
const provider = buildOpenAIRealtimeVoiceProvider();
|
||||
const bridge = provider.createBridge({
|
||||
providerConfig: { apiKey: "sk-test" }, // pragma: allowlist secret
|
||||
onAudio: vi.fn(),
|
||||
onClearAudio: vi.fn(),
|
||||
});
|
||||
const firstConnect = bridge.connect();
|
||||
const firstSocket = FakeWebSocket.instances[0];
|
||||
if (!firstSocket) {
|
||||
throw new Error("expected bridge to create a websocket");
|
||||
}
|
||||
firstSocket.readyState = FakeWebSocket.OPEN;
|
||||
firstSocket.emit("open");
|
||||
await Promise.resolve();
|
||||
|
||||
bridge.sendAudio(Buffer.from("queued-before-close"));
|
||||
bridge.close();
|
||||
await firstConnect;
|
||||
bridge.sendAudio(Buffer.from("sent-after-close"));
|
||||
|
||||
const reconnecting = bridge.connect();
|
||||
const secondSocket = FakeWebSocket.instances[1];
|
||||
if (!secondSocket) {
|
||||
throw new Error("expected bridge to reconnect");
|
||||
}
|
||||
secondSocket.readyState = FakeWebSocket.OPEN;
|
||||
secondSocket.emit("open");
|
||||
secondSocket.emit("message", Buffer.from(JSON.stringify({ type: "session.updated" })));
|
||||
await reconnecting;
|
||||
|
||||
expect(
|
||||
parseSent(secondSocket).filter((event) => event.type === "input_audio_buffer.append"),
|
||||
).toHaveLength(0);
|
||||
bridge.close();
|
||||
});
|
||||
|
||||
it("shares an in-flight connection until session readiness", async () => {
|
||||
const provider = buildOpenAIRealtimeVoiceProvider();
|
||||
const onReady = vi.fn();
|
||||
|
||||
Reference in New Issue
Block a user