

























@@ -328,18 +328,23 @@ describe("buildOpenAIRealtimeVoiceProvider", () => {
328328 onReady,
329329});
330330const connecting = bridge.connect();
331+let connectResolved = false;
332+void connecting.then(() => {
333+connectResolved = true;
334+});
331335const socket = FakeWebSocket.instances[0];
332336if (!socket) {
333337throw new Error("expected bridge to create a websocket");
334338}
335339336340socket.readyState = FakeWebSocket.OPEN;
337341socket.emit("open");
338-await connecting;
342+await Promise.resolve();
339343340344bridge.sendAudio(Buffer.from("before-ready"));
341345socket.emit("message", Buffer.from(JSON.stringify({ type: "session.created" })));
342346347+expect(connectResolved).toBe(false);
343348expect(onReady).not.toHaveBeenCalled();
344349expect(parseSent(socket).map((event) => event.type)).toEqual(["session.update"]);
345350expect(parseSent(socket)[0]?.session).toMatchObject({
@@ -349,7 +354,9 @@ describe("buildOpenAIRealtimeVoiceProvider", () => {
349354expect(bridge.isConnected()).toBe(false);
350355351356socket.emit("message", Buffer.from(JSON.stringify({ type: "session.updated" })));
357+await connecting;
352358359+expect(connectResolved).toBe(true);
353360expect(onReady).toHaveBeenCalledTimes(1);
354361expect(parseSent(socket).map((event) => event.type)).toEqual([
355362"session.update",
@@ -358,6 +365,35 @@ describe("buildOpenAIRealtimeVoiceProvider", () => {
358365expect(bridge.isConnected()).toBe(true);
359366});
360367368+it("rejects connection when session configuration fails before readiness", async () => {
369+const provider = buildOpenAIRealtimeVoiceProvider();
370+const bridge = provider.createBridge({
371+providerConfig: { apiKey: "sk-test" }, // pragma: allowlist secret
372+onAudio: vi.fn(),
373+onClearAudio: vi.fn(),
374+});
375+const connecting = bridge.connect();
376+const socket = FakeWebSocket.instances[0];
377+if (!socket) {
378+throw new Error("expected bridge to create a websocket");
379+}
380+381+socket.readyState = FakeWebSocket.OPEN;
382+socket.emit("open");
383+socket.emit(
384+"message",
385+Buffer.from(
386+JSON.stringify({
387+type: "error",
388+error: { message: "invalid realtime session" },
389+}),
390+),
391+);
392+393+await expect(connecting).rejects.toThrow("invalid realtime session");
394+expect(bridge.isConnected()).toBe(false);
395+});
396+361397it("can request PCM16 24 kHz realtime audio for Chrome command-pair bridges", async () => {
362398const provider = buildOpenAIRealtimeVoiceProvider();
363399const bridge = provider.createBridge({
@@ -375,6 +411,7 @@ describe("buildOpenAIRealtimeVoiceProvider", () => {
375411376412socket.readyState = FakeWebSocket.OPEN;
377413socket.emit("open");
414+socket.emit("message", Buffer.from(JSON.stringify({ type: "session.updated" })));
378415await connecting;
379416380417expect(parseSent(socket)[0]?.session).toMatchObject({
@@ -425,8 +462,8 @@ describe("buildOpenAIRealtimeVoiceProvider", () => {
425462426463socket.readyState = FakeWebSocket.OPEN;
427464socket.emit("open");
428-await connecting;
429465socket.emit("message", Buffer.from(JSON.stringify({ type: "session.updated" })));
466+await connecting;
430467431468bridge.setMediaTimestamp(1000);
432469socket.emit(
@@ -476,8 +513,8 @@ describe("buildOpenAIRealtimeVoiceProvider", () => {
476513477514socket.readyState = FakeWebSocket.OPEN;
478515socket.emit("open");
479-await connecting;
480516socket.emit("message", Buffer.from(JSON.stringify({ type: "session.updated" })));
517+await connecting;
481518482519const audio = Buffer.from("assistant audio");
483520socket.emit(
@@ -525,8 +562,8 @@ describe("buildOpenAIRealtimeVoiceProvider", () => {
525562526563socket.readyState = FakeWebSocket.OPEN;
527564socket.emit("open");
528-await connecting;
529565socket.emit("message", Buffer.from(JSON.stringify({ type: "session.updated" })));
566+await connecting;
530567531568bridge.triggerGreeting?.("Say exactly: hello from explicit speech.");
532569此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。