fix(frontend): track playback completion and meaningful inactivity
This commit is contained in:
@@ -9,6 +9,7 @@ const audio = vi.hoisted(() => ({
|
||||
close: vi.fn<() => Promise<void>>(),
|
||||
play: vi.fn(),
|
||||
clear: vi.fn(),
|
||||
finishPlayback: vi.fn(),
|
||||
setMuted: vi.fn(),
|
||||
setGate: vi.fn(),
|
||||
}));
|
||||
@@ -19,6 +20,7 @@ vi.mock("../audio/engine", () => ({
|
||||
close = audio.close;
|
||||
play = audio.play;
|
||||
clear = audio.clear;
|
||||
finishPlayback = audio.finishPlayback;
|
||||
setMuted = audio.setMuted;
|
||||
setGate = audio.setGate;
|
||||
},
|
||||
@@ -89,6 +91,33 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe("realtime session", () => {
|
||||
it("waits for buffered audio to drain after response.done", async () => {
|
||||
const client = new RealtimeClient(options());
|
||||
const socket = await connect(client);
|
||||
socket.receive({ type: "response.created", response: { id: "r1" } });
|
||||
socket.receive({ type: "response.audio.delta", response_id: "r1", delta: "AAAA" });
|
||||
socket.receive({ type: "response.done", response: { id: "r1", status: "completed" } });
|
||||
await vi.waitFor(() => {
|
||||
expect(audio.finishPlayback).toHaveBeenCalledOnce();
|
||||
});
|
||||
expect(client.status).toBe("ai-speaking");
|
||||
audio.start.mock.calls[0]?.[3]();
|
||||
expect(client.status).toBe("listening");
|
||||
await client.close();
|
||||
});
|
||||
it("does not let a playback drain override a user interruption", async () => {
|
||||
const client = new RealtimeClient(options());
|
||||
const socket = await connect(client);
|
||||
socket.receive({ type: "response.created", response: { id: "r1" } });
|
||||
socket.receive({ type: "response.audio.delta", response_id: "r1", delta: "AAAA" });
|
||||
socket.receive({ type: "input_audio_buffer.speech_started" });
|
||||
await vi.waitFor(() => {
|
||||
expect(client.status).toBe("user-speaking");
|
||||
});
|
||||
audio.start.mock.calls[0]?.[3]();
|
||||
expect(client.status).toBe("user-speaking");
|
||||
await client.close();
|
||||
});
|
||||
it("starts microphone streaming without a session.updated acknowledgment", async () => {
|
||||
const client = new RealtimeClient(options());
|
||||
const pending = client.connect();
|
||||
|
||||
Reference in New Issue
Block a user