@urun-sh/openai 0.5.5 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ResponsesClient-BYx3YLGo.d.ts → ResponsesClient-BE3-hx3m.d.ts} +2 -0
- package/dist/{ResponsesClient-Dft3bg3b.d.cts → ResponsesClient-DjZWjlFH.d.cts} +2 -0
- package/dist/chunk-2T2YYBVX.js +1 -0
- package/dist/chunk-3WAJD62J.js +4 -0
- package/dist/{chunk-K23AZPI4.js → chunk-5HKWNK3O.js} +1 -1
- package/dist/chunk-7M6LY6DR.js +2 -0
- package/dist/chunk-BSHT6RZZ.js +1 -0
- package/dist/{chunk-GBBY3PCZ.js → chunk-FP4RSAIE.js} +1 -1
- package/dist/chunk-HR5H6S7L.js +1 -0
- package/dist/chunk-NY23USZF.js +57 -0
- package/dist/chunk-VLRMJRLS.js +6 -0
- package/dist/gemini-live.cjs +2 -2
- package/dist/gemini-live.d.cts +17 -2
- package/dist/gemini-live.d.ts +7 -2
- package/dist/gemini-live.js +1 -1
- package/dist/hosted/bin.cjs +40 -26
- package/dist/hosted/bin.js +4 -4
- package/dist/hosted/index.cjs +39 -26
- package/dist/hosted/index.d.cts +643 -16
- package/dist/hosted/index.d.ts +153 -5
- package/dist/hosted/index.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/{models-NYMZrklp.d.cts → models-DUdx_Y6X.d.cts} +1 -1
- package/dist/pi-extension/index.cjs +7 -7
- package/dist/pi-extension/index.d.cts +1 -1
- package/dist/pi-extension/index.d.ts +1 -1
- package/dist/pi-extension/index.js +1 -1
- package/dist/pi-extension/standalone.cjs +48 -48
- package/dist/proxy/cli.cjs +53 -43
- package/dist/proxy/cli.js +14 -14
- package/dist/proxy/index.cjs +32 -30
- package/dist/proxy/index.d.cts +84 -8
- package/dist/proxy/index.d.ts +16 -6
- package/dist/proxy/index.js +1 -6
- package/dist/responses-turn-Dr37N3kH.d.ts +486 -0
- package/dist/responses-turn-tNUHq5b0.d.cts +1807 -0
- package/dist/{translator-C9uPKypK.d.ts → translator-BCoRFaTs.d.ts} +1 -1
- package/dist/{translator-CcDBEfvm.d.cts → translator-Bh0Bp_Ie.d.cts} +3 -3
- package/dist/{video-out-D20UuJ8G.d.cts → video-out-CCksIcj8.d.cts} +5 -5
- package/package.json +12 -11
- package/dist/chunk-5BZCM3RS.js +0 -4
- package/dist/chunk-5NXM4IO3.js +0 -2
- package/dist/chunk-CWJRDBDC.js +0 -1
- package/dist/chunk-DMD5UENK.js +0 -1
- package/dist/chunk-I2Q3B3OG.js +0 -6
- package/dist/chunk-OI2OY32M.js +0 -1
- package/dist/chunk-QVF7NF7G.js +0 -44
- package/dist/responses-turn-KOAoIqZ-.d.ts +0 -200
- package/dist/responses-turn-OrO4euEN.d.cts +0 -513
- /package/dist/{chunk-YSFSRI3D.js → chunk-5CCJUNH7.js} +0 -0
- /package/dist/{models-NYMZrklp.d.ts → models-DUdx_Y6X.d.ts} +0 -0
- /package/dist/{video-out-CWesbk12.d.ts → video-out-IGQ4YQ-c.d.ts} +0 -0
package/dist/proxy/index.d.cts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Server, IncomingMessage } from 'node:http';
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
4
|
-
export { h as GEMINI_LIVE_PATH, V as VIDEO_OUT_SETUP_KEY } from '../translator-
|
|
2
|
+
import { f as ProxyHandlerOptions, P as ProxyClients } from '../responses-turn-tNUHq5b0.cjs';
|
|
3
|
+
export { D as DialObserver, a as DialReport, g as ProxyIdentity, h as ProxyVideoOutLane, S as SessionGoneError, U as UnknownModelError } from '../responses-turn-tNUHq5b0.cjs';
|
|
4
|
+
export { h as GEMINI_LIVE_PATH, V as VIDEO_OUT_SETUP_KEY } from '../translator-Bh0Bp_Ie.cjs';
|
|
5
5
|
import { WebSocket } from 'ws';
|
|
6
|
-
import '../models-
|
|
7
|
-
import '../video-out-
|
|
6
|
+
import '../models-DUdx_Y6X.cjs';
|
|
7
|
+
import '../video-out-CCksIcj8.cjs';
|
|
8
8
|
import '../types-lsVTbNcH.cjs';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -329,6 +329,14 @@ interface RealtimeBinding<S = unknown> {
|
|
|
329
329
|
confidence?: number;
|
|
330
330
|
startMs?: number;
|
|
331
331
|
}>;
|
|
332
|
+
/**
|
|
333
|
+
* Release THIS attachment when the socket closes (the hosted
|
|
334
|
+
* conversation-factory seam — the twin of the Gemini Live binding's
|
|
335
|
+
* `release`): per-attachment release, native detach underneath, the named
|
|
336
|
+
* session itself stays live. Absent (the local fixed-clients lane) = the
|
|
337
|
+
* pooled sessions are the process's own and outlive the socket.
|
|
338
|
+
*/
|
|
339
|
+
release?: () => Promise<void> | void;
|
|
332
340
|
}
|
|
333
341
|
interface OpenAIRealtimeOptions<S = unknown> {
|
|
334
342
|
resolver: OpenAIRealtimeResolver<S>;
|
|
@@ -422,11 +430,29 @@ declare class OpenAIRealtimeConnection<S = unknown> {
|
|
|
422
430
|
* SdkTransport-style) OR `clients.createResponse(params)` (the canonical
|
|
423
431
|
* ProxyClients seam the shared conversation factory hands out). A binding
|
|
424
432
|
* with neither was already rejected at upgrade time; this is the loud
|
|
425
|
-
* backstop.
|
|
433
|
+
* backstop. The ProxyClients seam is PROMISE-VALUED
|
|
434
|
+
* (`rehomingCreateResponse` dials inside an async function — its
|
|
435
|
+
* private-backhaul cold wake can park the promise for seconds), so it is
|
|
436
|
+
* awaited here; awaiting the SdkTransport generator is a no-op. The cast
|
|
437
|
+
* states the seam's REAL union: typing it sync-iterable is what let the
|
|
438
|
+
* unawaited promise reach `for await` as "R is not async iterable" (the
|
|
439
|
+
* prod-usw2 speak-turn kill, 2026-09-14).
|
|
426
440
|
*/
|
|
427
441
|
private upstreamStream;
|
|
428
442
|
private startResponse;
|
|
429
|
-
/**
|
|
443
|
+
/**
|
|
444
|
+
* Bridge voice OUT frame → `response.output_audio.delta` on the open turn.
|
|
445
|
+
*
|
|
446
|
+
* OUT-OF-TURN frames split by CONTENT, per the platform's own liveness
|
|
447
|
+
* model (urun-python #1812/#1827): the runtime's egress holds a DECLARED
|
|
448
|
+
* quiet track — `CtxMediaTransport`'s silence keepalive emits Opus silence
|
|
449
|
+
* whenever the app is silent, including before the first response.create —
|
|
450
|
+
* so an all-quiet frame with no open turn is that muted egress, not voice.
|
|
451
|
+
* It is dropped quietly (the same reading as a negotiated muted WebRTC
|
|
452
|
+
* track). A NON-quiet frame with no open turn is real voice the adapter
|
|
453
|
+
* cannot attribute — still the loud, once-per-connection
|
|
454
|
+
* `out_of_turn_audio` error that caught the speak-lane bug class.
|
|
455
|
+
*/
|
|
430
456
|
private onOutputAudioFrame;
|
|
431
457
|
/** One assistant message item per turn (text and audio parts share it). */
|
|
432
458
|
private messageItemAdded;
|
|
@@ -468,4 +494,54 @@ declare class OpenAIRealtimeConnection<S = unknown> {
|
|
|
468
494
|
private teardown;
|
|
469
495
|
}
|
|
470
496
|
|
|
471
|
-
|
|
497
|
+
/**
|
|
498
|
+
* THE REALTIME BINDING COMPOSITION — the ONE seam every composition rides to
|
|
499
|
+
* turn an upgraded `/v1/realtime` request into a {@link RealtimeBinding}.
|
|
500
|
+
*
|
|
501
|
+
* The modality is read from the CATALOG (`task` stt | tts, invariant across
|
|
502
|
+
* placements) through the SAME router-backed gate seam the Images lane uses
|
|
503
|
+
* (`ProxyClients.supportsAudio` — `ModelRouter.supportsAudio`). A non-audio
|
|
504
|
+
* model is refused LOUDLY with a 404 before anything is opened; a voice
|
|
505
|
+
* binding acquires its PRIVATE audio bridge from `ProxyClients.openAudio`
|
|
506
|
+
* (the pooled session's native `audio` lane at 24 kHz — the ONE canonical
|
|
507
|
+
* session-audio wiring, `transport/media.ts` AUDIO_STREAM). There is no env-var
|
|
508
|
+
* switch and no chat-default fall-through: an absent model resolves through
|
|
509
|
+
* the router exactly like every other lane, and a chat default is refused
|
|
510
|
+
* exactly like an explicitly named chat model.
|
|
511
|
+
*
|
|
512
|
+
* Used by BOTH compositions — the local `urun compat proxy` (fixed clients,
|
|
513
|
+
* optional fixed apiKey) and the hosted multi-tenant endpoint (per-request
|
|
514
|
+
* org resolution + per-conversation private backhauls) — so there is exactly
|
|
515
|
+
* ONE binding implementation and no copy-pasted second handler.
|
|
516
|
+
*/
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* The realtime lane's model name — the GA `?model=` query parameter
|
|
520
|
+
* (`wss://…/v1/realtime?model=…`). Absent = the router's configured default
|
|
521
|
+
* resolves it (locally the startup app; hosted, a loud 404 — there IS no
|
|
522
|
+
* default app on the hosted lane).
|
|
523
|
+
*/
|
|
524
|
+
declare function realtimeModelOf(req: IncomingMessage): string | undefined;
|
|
525
|
+
/**
|
|
526
|
+
* Build the binding for `model` against `clients`:
|
|
527
|
+
* - NO `supportsAudio` seam ⇒ 501 (loud, never a silent allow-all).
|
|
528
|
+
* - {@link UnknownModelError} ⇒ 404 with the router's own loud message.
|
|
529
|
+
* - A non-audio verdict ⇒ 404 — the realtime lane never falls through to
|
|
530
|
+
* the chat lane, in either direction.
|
|
531
|
+
* - A voice verdict with no `openAudio` seam ⇒ 501 (a voice binding cannot
|
|
532
|
+
* be served without its bridge; a voiceless downgrade is never silent).
|
|
533
|
+
*/
|
|
534
|
+
declare function realtimeBindingFor(clients: Pick<ProxyClients, 'createResponse'> & Partial<Pick<ProxyClients, 'supportsAudio' | 'openAudio'>>, model: string | undefined): Promise<RealtimeBinding<ProxyClients>>;
|
|
535
|
+
/**
|
|
536
|
+
* The LOCAL lane resolver: fixed pooled clients, optional fixed apiKey (the
|
|
537
|
+
* same shared-secret rule the local Gemini Live lane applies — a mismatched
|
|
538
|
+
* or missing Bearer is a 401; with no configured key the header is not
|
|
539
|
+
* consulted). The HOSTED lane builds its own resolver per request (org
|
|
540
|
+
* resolution + per-conversation private backhaul) and reuses
|
|
541
|
+
* {@link realtimeBindingFor} for the binding itself.
|
|
542
|
+
*/
|
|
543
|
+
declare function fixedClientsResolver(clients: ProxyClients, apiKey?: string): {
|
|
544
|
+
resolve(req: IncomingMessage): Promise<RealtimeBinding<ProxyClients>>;
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
export { type GeminiLiveCall, type GeminiLiveClients, OPENAI_REALTIME_PATH, type OpenAIProxyOptions, OpenAIRealtimeConnection, type OpenAIRealtimeOptions, type OpenAIRealtimeResolver, ProxyClients, type RealtimeBinding, ResumptionRegistry, attachGeminiLive, attachOpenAIRealtime, createOpenAIProxy, fixedClientsResolver, realtimeBindingFor, realtimeModelOf, serveGeminiLiveSocket };
|
package/dist/proxy/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Server, IncomingMessage } from 'node:http';
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
4
|
-
export { h as GEMINI_LIVE_PATH, V as VIDEO_OUT_SETUP_KEY } from '../translator-
|
|
2
|
+
import { f as ProxyHandlerOptions, P as ProxyClients } from '../responses-turn-Dr37N3kH.js';
|
|
3
|
+
export { D as DialObserver, a as DialReport, g as ProxyIdentity, h as ProxyVideoOutLane, S as SessionGoneError, U as UnknownModelError } from '../responses-turn-Dr37N3kH.js';
|
|
4
|
+
export { h as GEMINI_LIVE_PATH, V as VIDEO_OUT_SETUP_KEY } from '../translator-BCoRFaTs.js';
|
|
5
5
|
import { WebSocket } from 'ws';
|
|
6
|
-
import '../models-
|
|
7
|
-
import '../video-out-
|
|
6
|
+
import '../models-DUdx_Y6X.js';
|
|
7
|
+
import '../video-out-IGQ4YQ-c.js';
|
|
8
8
|
import '../types-lsVTbNcH.js';
|
|
9
9
|
|
|
10
10
|
interface OpenAIProxyOptions extends ProxyHandlerOptions {
|
|
@@ -87,6 +87,8 @@ interface RealtimeBinding<S = unknown> {
|
|
|
87
87
|
confidence?: number;
|
|
88
88
|
startMs?: number;
|
|
89
89
|
}>;
|
|
90
|
+
|
|
91
|
+
release?: () => Promise<void> | void;
|
|
90
92
|
}
|
|
91
93
|
interface OpenAIRealtimeOptions<S = unknown> {
|
|
92
94
|
resolver: OpenAIRealtimeResolver<S>;
|
|
@@ -173,4 +175,12 @@ declare class OpenAIRealtimeConnection<S = unknown> {
|
|
|
173
175
|
private teardown;
|
|
174
176
|
}
|
|
175
177
|
|
|
176
|
-
|
|
178
|
+
declare function realtimeModelOf(req: IncomingMessage): string | undefined;
|
|
179
|
+
|
|
180
|
+
declare function realtimeBindingFor(clients: Pick<ProxyClients, 'createResponse'> & Partial<Pick<ProxyClients, 'supportsAudio' | 'openAudio'>>, model: string | undefined): Promise<RealtimeBinding<ProxyClients>>;
|
|
181
|
+
|
|
182
|
+
declare function fixedClientsResolver(clients: ProxyClients, apiKey?: string): {
|
|
183
|
+
resolve(req: IncomingMessage): Promise<RealtimeBinding<ProxyClients>>;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export { type GeminiLiveCall, type GeminiLiveClients, OPENAI_REALTIME_PATH, type OpenAIProxyOptions, OpenAIRealtimeConnection, type OpenAIRealtimeOptions, type OpenAIRealtimeResolver, ProxyClients, type RealtimeBinding, ResumptionRegistry, attachGeminiLive, attachOpenAIRealtime, createOpenAIProxy, fixedClientsResolver, realtimeBindingFor, realtimeModelOf, serveGeminiLiveSocket };
|
package/dist/proxy/index.js
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
import{a as ee,b as te,c as ne,g as ie}from"../chunk-QVF7NF7G.js";import{b as H,c as K}from"../chunk-DMD5UENK.js";import{a as Z,h as Q}from"../chunk-5NXM4IO3.js";import"../chunk-CWJRDBDC.js";import{c as g}from"../chunk-YSFSRI3D.js";g();g();g();import{WebSocketServer as ce}from"ws";g();g();import{randomUUID as se}from"crypto";function r(a){return`${a}_${se().replace(/-/g,"").slice(0,24)}`}var F=4*1024*1024,$=8*1024*1024,U=512,P=20*1024*1024;function f(a,e,t){return{type:"invalid_request_error",code:a,message:e,param:t??null}}function E(a,e){return{type:"server_error",code:a,message:e}}function m(a){return{type:"error",event_id:r("event"),error:a}}function D(){return{outputModalities:["text"],turnDetection:null,inputAudioTranscription:!1}}var u=class extends Error{constructor(t,i,n="invalid_value"){super(t);this.param=i;this.code=n;this.name="SessionUpdateError"}param;code},oe={model:!0,instructions:!0,modalities:!0,voice:!0,input_audio_format:!0,output_audio_format:!0,temperature:!0,max_output_tokens:!0,max_response_output_tokens:!0,tool_choice:!0,tools:!0,metadata:!0,turn_detection:!0,input_audio_transcription:!0,input_audio_noise_reduction:!0,audio:!0},re={format:!0,transcription:!0,turn_detection:!0,noise_reduction:!0},ae={format:!0,voice:!0,speed:!0};function W(a,e){let t=a;if(!t||typeof t!="object"||t.type!=="audio/pcm"||t.rate!==void 0&&t.rate!==24e3)throw new u(`${e} must be {"type":"audio/pcm","rate":24000} \u2014 the session audio lane is 24 kHz mono PCM16 only`,e)}function S(a,e,t){if(!a||typeof a!="object"||Array.isArray(a))throw new u("session must be an object","session","invalid_request");let i=a,n=Object.keys(i).filter(p=>!(p in oe));if(n.length>0)throw new u(`session field(s) not supported by this backend: ${n.join(", ")}`,n[0],"unsupported_field");let s={...e,outputModalities:[...e.outputModalities]};for(let[p,o]of Object.entries(i))switch(p){case"model":if(o!==null&&typeof o!="string")throw new u("model must be a string or null","model");s.model=o??void 0;break;case"instructions":if(o!==null&&typeof o!="string")throw new u("instructions must be a string or null","instructions");s.instructions=o??void 0;break;case"modalities":{if(!Array.isArray(o)||o.length===0)throw new u("modalities must be a non-empty array","modalities");let l=[];for(let d of o){if(d!=="text"&&d!=="audio")throw new u(`modality ${JSON.stringify(d)} is not "text" or "audio"`,"modalities");if(d==="audio"&&!t.voice)throw new u('modality "audio" refused: the resolver did not provide an authoritative voice binding for the resolved backend \u2014 this model cannot speak on this session',"modalities","audio_not_supported");l.includes(d)||l.push(d)}s.outputModalities=l;break}case"voice":if(o===null){delete s.voice;break}if(typeof o!="string")throw new u("voice must be a string or null","voice");if(!t.voice)throw new u("voice refused: no authoritative voice binding for the resolved backend","voice","audio_not_supported");s.voice=o;break;case"input_audio_format":case"output_audio_format":if(o!=="pcm16")throw new u(`${p} must be "pcm16" \u2014 the session audio lane is 24 kHz mono PCM16 only`,p);break;case"temperature":if(o!==null&&(typeof o!="number"||!Number.isFinite(o)))throw new u("temperature must be a finite number or null","temperature");s.temperature=o??void 0;break;case"max_output_tokens":case"max_response_output_tokens":if(o!==null&&o!=="inf"&&(typeof o!="number"||!Number.isInteger(o)||o<1))throw new u(`${p} must be a positive integer, "inf" or null`,p);s.maxOutputTokens=o===null?void 0:o;break;case"tools":if(!Array.isArray(o))throw new u("tools must be an array","tools");s.tools=o;break;case"tool_choice":s.toolChoice=o;break;case"metadata":if(o!==null&&(!o||typeof o!="object"||Array.isArray(o)))throw new u("metadata must be an object or null","metadata");s.metadata=o??null;break;case"turn_detection":{if(o===null){s.turnDetection=null;break}if(!t.turns)throw new u("turn_detection is refused: the resolved backend does not wire its own turn boundary lane (stt stream with turn_start/turn_end) \u2014 there is no native VAD source to drive responses from. Drive turns manually: input_audio_buffer.commit + response.create.","turn_detection","unsupported_field");let l=o;if(!l||typeof l!="object"||Array.isArray(l))throw new u("turn_detection must be an object or null","turn_detection");let d=String(l.type??"");if(d!=="server_vad"&&d!=="semantic_vad")throw new u(`turn_detection.type ${JSON.stringify(l.type)} is not "server_vad"/"semantic_vad"`,"turn_detection.type");s.turnDetection={createResponse:l.create_response!==!1,interruptResponse:l.interrupt_response!==!1};break}case"input_audio_transcription":{if(o===null){s.inputAudioTranscription=!1;break}if(!t.turns)throw new u("input_audio_transcription is refused: the resolved backend does not wire a transcript lane \u2014 no native transcription source exists behind this session","input_audio_transcription","unsupported_field");if(!o||typeof o!="object"||Array.isArray(o))throw new u("input_audio_transcription must be an object or null","input_audio_transcription");for(let l of Object.keys(o))if(!["model","language","languages","prompt"].includes(l))throw new u(`input_audio_transcription field not honored by this backend: ${l} (transcription comes from the voice engine itself)`,`input_audio_transcription.${l}`,"unsupported_field");s.inputAudioTranscription=!0;break}case"input_audio_noise_reduction":if(o!==null)throw new u("input_audio_noise_reduction must be null on this backend: no noise-reduction primitive exists behind the session audio bridge","input_audio_noise_reduction","unsupported_field");break;case"audio":{if(o===null)break;let l=o;if(!l||typeof l!="object"||Array.isArray(l))throw new u("audio must be an object or null","audio");if(l.input!==void 0&&l.input!==null){let d=l.input;if(!d||typeof d!="object"||Array.isArray(d))throw new u("audio.input must be an object","audio.input");for(let c of Object.keys(d))if(!(c in re))throw new u(`audio.input field not supported by this backend: ${c}`,`audio.input.${c}`,"unsupported_field");if(d.format!==void 0&&W(d.format,"audio.input.format"),d.transcription!==null&&d.transcription!==void 0){let c=S({input_audio_transcription:d.transcription},s,t);s.inputAudioTranscription=c.inputAudioTranscription}if(d.turn_detection!==null&&d.turn_detection!==void 0){let c=S({turn_detection:d.turn_detection},s,t);s.turnDetection=c.turnDetection}if(d.noise_reduction!==null&&d.noise_reduction!==void 0)throw new u("audio.input.noise_reduction must be null on this backend: no noise-reduction primitive","audio.input.noise_reduction","unsupported_field")}if(l.output!==void 0&&l.output!==null){let d=l.output;if(!d||typeof d!="object"||Array.isArray(d))throw new u("audio.output must be an object","audio.output");for(let c of Object.keys(d))if(!(c in ae))throw new u(`audio.output field not supported by this backend: ${c}`,`audio.output.${c}`,"unsupported_field");if(d.format!==void 0&&W(d.format,"audio.output.format"),d.speed!==void 0)throw new u("audio.output.speed is not supported on this backend: playback rate is fixed","audio.output.speed","unsupported_field");if(d.voice!==void 0)if(d.voice===null)delete s.voice;else{if(typeof d.voice!="string")throw new u("audio.output.voice must be a string or null","audio.output.voice");if(!t.voice)throw new u("audio.output.voice refused: no authoritative voice binding for the resolved backend","audio.output.voice","audio_not_supported");s.voice=d.voice}d.format!==void 0&&!s.outputModalities.includes("audio")&&(s.outputModalities=["text","audio"])}break}default:break}return s}function j(a,e){return{id:e,object:"realtime.session",model:a.model??null,instructions:a.instructions??"",modalities:[...a.outputModalities],voice:a.voice??null,input_audio_format:"pcm16",output_audio_format:"pcm16",input_audio_transcription:a.inputAudioTranscription?{}:null,input_audio_noise_reduction:null,turn_detection:a.turnDetection?{type:"server_vad",create_response:a.turnDetection.createResponse,interrupt_response:a.turnDetection.interruptResponse}:null,temperature:a.temperature??null,max_response_output_tokens:a.maxOutputTokens??"inf",tool_choice:a.toolChoice??"auto",tools:a.tools??[],metadata:a.metadata??null}}function q(a,e){let t=a;if(!t||typeof t!="object")throw new u("item must be an object","item","invalid_request");if(t.type==="function_call_output"){if(typeof t.call_id!="string"||typeof t.output!="string")throw new u("function_call_output item requires string call_id and output","item.call_id","invalid_request");return{id:typeof t.id=="string"?t.id:r("item"),type:"function_call_output",callId:t.call_id,output:t.output}}if(t.type==="message"){let i=t.role;if(i!=="user"&&i!=="assistant"&&i!=="system")throw new u('message item role must be "user", "assistant" or "system"',"item.role","invalid_request");if(!Array.isArray(t.content))throw new u("message item content must be an array","item.content","invalid_request");let n=[];for(let s of t.content){let p=s;if(!p||typeof p!="object")throw new u("content part must be an object","item.content","invalid_request");if(p.type==="input_text"||i==="assistant"&&p.type==="output_text"){if(typeof p.text!="string")throw new u(`${String(p.type)} part requires string text`,"item.content.text","invalid_request");n.push({type:p.type,text:p.text});continue}if(p.type==="input_audio"){if(!e)throw new u("input_audio content refused: no authoritative voice binding for the resolved backend","item.content.type","audio_not_supported");if(typeof p.audio!="string")throw new u("input_audio part requires base64 audio","item.content.audio","invalid_request");n.push({type:"input_audio",...typeof p.transcript=="string"?{transcript:p.transcript}:{}});continue}throw new u(`content part type ${String(p.type)} is not supported on message items here (input_text / output_text / input_audio)`,"item.content.type","invalid_request")}return{id:typeof t.id=="string"?t.id:r("item"),type:"message",role:i,content:n}}throw new u(`item type ${String(t.type)} is not supported \u2014 message and function_call_output items only`,"item.type","invalid_request")}function L(a){let e=[],t=!1;for(let i of a){if(i.type==="function_call"){e.push({type:"function_call",call_id:i.callId,name:i.name,arguments:i.arguments??"{}"});continue}if(i.type==="function_call_output"){e.push({type:"function_call_output",call_id:i.callId,output:i.output});continue}let n=[];for(let s of i.content??[]){if(s.type==="input_text"||s.type==="output_text"){n.push({type:s.type,text:s.text});continue}if(s.type==="input_audio"){let p=s.transcript;if(typeof p=="string"&&p.trim().length>0){n.push({type:"input_text",text:p});continue}t=!0;continue}}e.push({role:i.role,content:n})}return{input:e,sawAudioOnlyItem:t}}var ue=1001,de=1011,X=a=>a.slice(0,120),pe=/^[A-Za-z0-9+/=]*$/,R=class{id=r("conn");ws;binding;onClosed;config=D();sessionId=r("sess");conversationId=r("conv");items=[];pendingAudioBytes=[];pendingAudioTotalBytes=0;frozenAudio=[];inFlight=null;activeResponseId=null;responseFlushed=!1;cancelled=!1;voiceClaimed=!1;audioLaneOwner=!1;audioUnsubscribe=null;outOfTurnAudioWarned=!1;audioOnlyTranscriptGapWarned=!1;closed=!1;turnLaneAbort=null;turnTranscript={open:!1,text:""};lastCommittedTranscript=null;constructor(e){this.ws=e.ws,this.binding=e.binding,this.onClosed=e.onClosed,this.binding.model&&(this.config.model=this.binding.model),this.ws.on("message",t=>{this.onMessage(t)}),this.ws.on("close",()=>this.teardown("client disconnected")),this.ws.on("error",()=>this.teardown("client socket error")),this.send({type:"session.created",event_id:r("event"),session:j(this.config,this.sessionId)}),this.send({type:"conversation.created",event_id:r("event"),conversation:{id:this.conversationId,object:"realtime.conversation"}}),this.binding.turns&&this.startTurnLane()}startTurnLane(){let e=new AbortController;this.turnLaneAbort=e;let t=this.binding.turns;(async()=>{try{for await(let i of t()){if(this.closed||e.signal.aborted)return;this.onTurnEvent(i)}}catch(i){!this.closed&&!e.signal.aborted&&this.send(m(E("turn_lane_fault",`the backend turn/transcript lane failed: ${i instanceof Error?i.message:String(i)}`)))}})()}onTurnEvent(e){switch(e.kind){case"delta":case"final":{let t=typeof e.text=="string"?e.text:"";if(t.length===0)return;this.turnTranscript.open=!0,this.turnTranscript.text+=t,this.config.inputAudioTranscription&&this.send({type:"conversation.item.input_audio_transcription.delta",event_id:r("event"),item_id:"input_audio_turn",content_index:0,delta:t});return}case"turn_start":{this.turnTranscript={open:!0,text:this.turnTranscript.text},this.send({type:"input_audio_buffer.speech_started",event_id:r("event"),item_id:"input_audio_turn",audio_start_ms:typeof e.startMs=="number"?e.startMs:0}),this.config.turnDetection?.interruptResponse&&this.inFlight&&this.cancelResponse();return}case"turn_end":{let t=this.turnTranscript.text.trim(),i=t.length>0?t:null;this.turnTranscript={open:!1,text:""},this.lastCommittedTranscript=i,this.frozenAudio=this.pendingAudioBytes.splice(0),this.pendingAudioTotalBytes=0;let n=r("item"),s=this.items.length>0?this.items[this.items.length-1].id:null;this.pushItem({id:n,type:"message",role:"user",content:[{type:"input_audio",...i!==null?{transcript:i}:{}}]}),this.send({type:"input_audio_buffer.committed",event_id:r("event"),previous_item_id:s,item_id:n}),this.send({type:"conversation.item.created",event_id:r("event"),previous_item_id:s,item:this.itemToProtocol(this.items[this.items.length-1])}),this.send({type:"input_audio_buffer.speech_stopped",event_id:r("event"),item_id:n,audio_end_ms:typeof e.startMs=="number"?e.startMs:0}),this.config.inputAudioTranscription&&i!==null&&this.send({type:"conversation.item.input_audio_transcription.completed",event_id:r("event"),item_id:n,content_index:0,transcript:i}),this.config.turnDetection?.createResponse&&!this.inFlight&&this.startResponse({});return}case"turn_eager_end":case"turn_resumed":return;default:return}}takeTurnTranscript(){let e=this.lastCommittedTranscript;return this.lastCommittedTranscript=null,e}async onMessage(e){if(this.closed)return;let t;try{t=e.toString()}catch{this.fail(f("decode_error","frame is not decodable text"),"invalid_frame");return}if(Buffer.byteLength(t,"utf8")>F){this.fail(f("frame_too_large",`frame exceeds the ${F}-byte limit`),"invalid_frame");return}let i;try{i=JSON.parse(t)}catch{this.fail(f("invalid_json","frame is not valid JSON"),"invalid_frame");return}if(typeof i.type!="string"||i.type.length===0){this.fail(f("missing_type",'event is missing a string "type"'),"invalid_frame");return}try{await this.handle(i)}catch(n){let s=n;if(s&&typeof s=="object"&&s.name==="SessionUpdateError"){this.send(m({type:"invalid_request_error",code:s.code??"invalid_value",message:s.message,param:s.param??null}));return}this.fail(E(null,n instanceof Error?n.message:String(n)),"handler_fault")}}async handle(e){switch(e.type){case"session.update":this.config=S(e.session,this.config,{voice:this.binding.voice,turns:this.binding.turns!==void 0}),this.send({type:"session.updated",event_id:r("event"),session:j(this.config,this.sessionId)});return;case"conversation.item.create":{let t=q(e.item,this.binding.voice),i=this.items.length>0?this.items[this.items.length-1].id:null;this.pushItem(t),this.send({type:"conversation.item.created",event_id:r("event"),previous_item_id:i,item:this.itemToProtocol(t)});return}case"conversation.item.delete":{let t=this.items.findIndex(i=>i.id===e.item_id);if(t<0){this.send(m(f("item_not_found",`no item with id ${JSON.stringify(e.item_id)}`,"item_id")));return}this.items.splice(t,1),this.send({type:"conversation.item.deleted",event_id:r("event"),item_id:e.item_id});return}case"conversation.item.retrieve":{let t=this.items.find(i=>i.id===e.item_id);if(!t){this.send(m(f("item_not_found",`no item with id ${JSON.stringify(e.item_id)}`,"item_id")));return}this.send({type:"conversation.item.retrieved",event_id:r("event"),item:this.itemToProtocol(t)});return}case"conversation.item.truncate":{let t=this.items.find(i=>i.id===e.item_id);if(!t||t.type!=="message"||t.role!=="assistant"){this.send(m(f("item_not_found",`no assistant message item with id ${JSON.stringify(e.item_id)}`,"item_id")));return}t.truncated=!0,this.send({type:"conversation.item.truncated",event_id:r("event"),item_id:t.id,content_index:typeof e.content_index=="number"?e.content_index:0,audio_end_ms:typeof e.audio_end_ms=="number"?e.audio_end_ms:0});return}case"input_audio_buffer.append":{if(typeof e.audio!="string"||e.audio.length===0){this.send(m(f("invalid_audio",'input_audio_buffer.append requires base64 "audio"',"audio")));return}if(!this.ensureVoice())return;if(!pe.test(e.audio)){this.send(m(f("invalid_audio","input_audio_buffer.append audio must be base64","audio")));return}let t=Buffer.byteLength(e.audio,"base64");if(this.pendingAudioBytes.length+t>P){this.send(m(f("buffer_full",`uncommitted input audio exceeds the ${P}-byte bound \u2014 commit or clear first`,"audio")));return}if(this.inFlight){this.binding.audioSession.audio.appendInputAudio(e.audio);return}this.pendingAudioBytes.push(e.audio),this.pendingAudioTotalBytes+=t;return}case"input_audio_buffer.clear":{if(!this.ensureVoice())return;this.pendingAudioBytes.length=0,this.pendingAudioTotalBytes=0,this.send({type:"input_audio_buffer.cleared",event_id:r("event")});return}case"input_audio_buffer.commit":{if(!this.ensureVoice())return;if(this.pendingAudioTotalBytes===0&&this.takeTurnTranscript()===null){this.send(m(f("empty_buffer","input_audio_buffer.commit with no buffered audio","audio")));return}this.frozenAudio=this.pendingAudioBytes.splice(0),this.pendingAudioTotalBytes=0;let t=this.takeTurnTranscript();t===null&&this.binding.turns===void 0&&this.warnAudioOnlyTranscriptGap();let i=r("item"),n=this.items.length>0?this.items[this.items.length-1].id:null;this.pushItem({id:i,type:"message",role:"user",content:[{type:"input_audio",...t!==null?{transcript:t}:{}}]}),this.send({type:"input_audio_buffer.committed",event_id:r("event"),previous_item_id:n,item_id:i}),this.send({type:"conversation.item.created",event_id:r("event"),previous_item_id:n,item:this.itemToProtocol(this.items[this.items.length-1])});return}case"output_audio_buffer.clear":{this.send(m(f("output_clear_unavailable","output_audio_buffer.clear has no server-side playback queue to flush on this adapter: output audio is delivered as response.output_audio.delta events and interrupted turns are stopped with response.cancel")));return}case"response.create":this.startResponse(e.response??{});return;case"response.cancel":this.cancelResponse();return;default:this.send(m(f("unknown_event",`event type ${e.type} is not supported by this adapter`)))}}ensureVoice(){return!this.binding.voice||!this.binding.audioSession?(this.send(m(f("audio_not_supported","audio events require a voice binding from the resolver \u2014 this session was resolved text-only","audio"))),!1):(this.voiceClaimed||(this.claimVoiceBinding(),this.audioUnsubscribe=this.binding.audioSession.audio.onOutputAudio(e=>{this.onOutputAudioFrame(this.activeResponseId??"",e)}),this.voiceClaimed=!0),!0)}claimVoiceBinding(){let e=this.binding.audioSession,t=e.openaiRealtimeClaims??(e.openaiRealtimeClaims=new Set);if(t.has(e))throw new Error("voice binding already owned by another connection \u2014 the resolver handed one audio bridge to two realtime conversations, which must never happen (independent callers require private bindings)");t.add(e),this.audioLaneOwner=!0}releaseVoiceBinding(){let e=this.binding.audioSession;!e||!this.audioLaneOwner||(e.openaiRealtimeClaims?.delete(e),this.audioLaneOwner=!1)}warnAudioOnlyTranscriptGap(){this.audioOnlyTranscriptGapWarned||(this.audioOnlyTranscriptGapWarned=!0,this.send(m({type:"invalid_request_error",code:"audio_input_transcript_unavailable",message:"committed input audio is forwarded to the runtime audio lane but is NOT model-visible in the text turn lane: the resolved backend wires no turn/transcript lane (the voice engine's own stt stream with turn_start/turn_end + transcripts). Wire the transcribe/turn-detection leg upstream (the resolver supplies binding.turns) and committed audio gains its REAL transcript as the model-visible turn.",param:"input_audio_buffer.commit"})))}upstreamStream(e,t){let i=this.binding.session;if(i&&typeof i.sendResponseCreate=="function")return i.sendResponseCreate(e,e.input??[],t);let n=this.binding.clients;if(n&&typeof n.createResponse=="function")return n.createResponse(e);throw new Error("realtime binding provides neither session.sendResponseCreate nor clients.createResponse \u2014 no upstream turn seam")}startResponse(e){if(this.inFlight){this.send(m(f("response_in_progress","a response is already in progress \u2014 cancel it with response.cancel first","response.create")));return}let t=e??{};if(t.modalities!==void 0){if(!Array.isArray(t.modalities)||t.modalities.some(h=>h!=="text"&&h!=="audio")){this.send(m(f("invalid_modalities",'response.modalities must be "text"/"audio"',"response.modalities")));return}if(t.modalities.includes("audio")&&!this.ensureVoice())return}if(t.input!==void 0){this.send(m(f("response_input_unsupported","response.input is not supported by this adapter: build the context with conversation.item.create, then response.create","response.input")));return}this.cancelled=!1,this.responseFlushed=!1,this.messageItemAdded=!1;let i=r("req"),n=`resp_${i}`;this.activeResponseId=n;let s=this.items.length,{input:p,sawAudioOnlyItem:o}=L(this.items),l=typeof t.instructions=="string"?t.instructions:this.config.instructions,d=typeof t.temperature=="number"?t.temperature:this.config.temperature,c=t.max_output_tokens??this.config.maxOutputTokens,y=c==="inf"||c===void 0?void 0:c,x=t.tools!==void 0?t.tools:this.config.tools,C=t.tool_choice!==void 0?t.tool_choice:this.config.toolChoice,N={input:p,stream:!0,...this.config.model?{model:this.config.model}:{},...l!==void 0?{instructions:l}:{},...d!==void 0?{temperature:d}:{},...y!==void 0?{max_output_tokens:y}:{},...x!==void 0?{tools:x}:{},...C!==void 0?{tool_choice:C}:{}};for(let h of this.frozenAudio.splice(0))this.binding.audioSession?.audio.appendInputAudio(h);this.inFlight=(async()=>{let h=[],A=w=>{this.responseFlushed?this.send(w):h.push(w)},I=()=>{if(!this.responseFlushed){this.send({type:"response.created",event_id:r("event"),response:this.responseObject(n,"in_progress")}),this.send({type:"response.in_progress",event_id:r("event"),response:this.responseObject(n,"in_progress")});for(let w of h)this.send(w);h.length=0,this.responseFlushed=!0}},v={messageOpen:!1,messageText:"",tools:new Map,nextOutputIndex:0},Y=null;try{o&&this.binding.turns===void 0&&this.warnAudioOnlyTranscriptGap();let w;try{w=this.upstreamStream(N,i)}catch(O){this.emitUpstreamFault(O,n);return}try{for await(let O of w){if(this.cancelled)break;let _=O;if(_.type==="error"){let T=this.upstreamErrorBody(_);this.responseFlushed?this.send(m(T)):this.send({type:"response.failed",event_id:r("event"),response:this.failedResponse(n,T)});return}if(_.type==="response.output_text.delta"&&typeof _.delta=="string"){I(),v.messageOpen||(this.beginMessageItem(n,v.nextOutputIndex++),v.messageOpen=!0),A({type:"response.output_text.delta",event_id:r("event"),item_id:`${n}_msg_0`,response_id:n,output_index:0,content_index:0,delta:_.delta}),v.messageText+=_.delta;continue}if(_.type==="response.function_call_arguments.delta"){I();let T=typeof _.delta=="string"?_.delta:"",k=typeof _.call_id=="string"&&_.call_id.length>0?_.call_id:`${n}_fc_${v.nextOutputIndex}`,b=v.tools.get(k);if(!b){let z=typeof _.name=="string"&&_.name.length>0?_.name:void 0;b={outputIndex:v.nextOutputIndex++,name:z,args:""},v.tools.set(k,b),A({type:"response.output_item.added",event_id:r("event"),response_id:n,output_index:b.outputIndex,item:{id:k,object:"realtime.item",type:"function_call",call_id:k,name:z??"",arguments:"",status:"in_progress"}})}typeof _.name=="string"&&_.name.length>0&&(b.name=_.name),b.args+=T,A({type:"response.function_call_arguments.delta",event_id:r("event"),item_id:k,response_id:n,output_index:b.outputIndex,call_id:k,name:b.name??"",delta:T});continue}if(_.type==="response.completed"){Y=_.response??null;continue}}}catch(O){this.emitUpstreamFault(O,n);return}if(this.cancelled)return;this.closeOpenItems(n,v,s),I(),this.send({type:"response.done",event_id:r("event"),response:this.doneResponse(n,s,Y)})}finally{this.inFlight=null,this.activeResponseId=null}})()}onOutputAudioFrame(e,t){if(this.cancelled)return;if(this.activeResponseId!==e){!this.outOfTurnAudioWarned&&!this.closed&&(this.outOfTurnAudioWarned=!0,this.send(m({type:"invalid_request_error",code:"out_of_turn_audio",message:"the runtime produced voice OUT outside a response turn; this adapter delivers output audio only within response.output_audio.delta of an open turn \u2014 wire server-driven turns (VAD) upstream or keep speech inside response turns"})));return}this.responseFlushed||(this.send({type:"response.created",event_id:r("event"),response:this.responseObject(e,"in_progress")}),this.send({type:"response.in_progress",event_id:r("event"),response:this.responseObject(e,"in_progress")}),this.responseFlushed=!0);let i=`${e}_msg_0`;this.messageItemOpenForAudio||(this.beginAudioMessageItem(e),this.messageItemOpenForAudio=!0),this.send({type:"response.output_audio.delta",event_id:r("event"),item_id:i,response_id:e,output_index:0,content_index:0,delta:t})}messageItemAdded=!1;messageItemOpenForAudio=!1;beginMessageItem(e,t){let i=`${e}_msg_0`;this.messageItemAdded||(this.messageItemAdded=!0,this.send({type:"response.output_item.added",event_id:r("event"),response_id:e,output_index:t,item:{id:i,object:"realtime.item",type:"message",role:"assistant",status:"in_progress",content:[]}})),this.send({type:"response.content_part.added",event_id:r("event"),item_id:i,response_id:e,output_index:t,content_index:0,part:{type:"output_text",text:""}})}beginAudioMessageItem(e){let t=`${e}_msg_0`;this.messageItemAdded||(this.messageItemAdded=!0,this.send({type:"response.output_item.added",event_id:r("event"),response_id:e,output_index:0,item:{id:t,object:"realtime.item",type:"message",role:"assistant",status:"in_progress",content:[]}})),this.send({type:"response.content_part.added",event_id:r("event"),item_id:t,response_id:e,output_index:0,content_index:0,part:{type:"output_audio",transcript:""}})}closeOpenItems(e,t,i){if(t.messageOpen||this.messageItemOpenForAudio){let n=`${e}_msg_0`,s=this.messageItemOpenForAudio;s&&this.send({type:"response.output_audio.done",event_id:r("event"),item_id:n,response_id:e,output_index:0,content_index:0}),t.messageText.length>0&&this.send({type:"response.output_text.done",event_id:r("event"),item_id:n,response_id:e,output_index:0,content_index:0,text:t.messageText}),this.send({type:"response.content_part.done",event_id:r("event"),item_id:n,response_id:e,output_index:0,content_index:0,part:s?{type:"output_audio",transcript:""}:{type:"output_text",text:t.messageText}});let p=[];s&&p.push({type:"output_audio"}),t.messageText.length>0&&p.push({type:"output_text",text:t.messageText});let o={id:n,type:"message",role:"assistant",content:p};this.pushItem(o),this.send({type:"response.output_item.done",event_id:r("event"),response_id:e,output_index:0,item:this.itemToProtocol(o)})}for(let[n,s]of t.tools){let p=s.args.length>0?s.args:"{}";this.send({type:"response.function_call_arguments.done",event_id:r("event"),item_id:n,response_id:e,output_index:s.outputIndex,call_id:n,name:s.name??"",arguments:p});let o={id:n,type:"function_call",callId:n,name:s.name,arguments:p};this.pushItem(o),this.send({type:"response.output_item.done",event_id:r("event"),response_id:e,output_index:s.outputIndex,item:this.itemToProtocol(o)})}this.messageItemOpenForAudio=!1,this.messageItemAdded=!1}responseObject(e,t,i){return{id:e,object:"realtime.response",status:t,conversation_id:this.conversationId,usage:null,...i??{}}}failedResponse(e,t){return this.responseObject(e,"failed",{status_details:{error:{code:t.code,message:t.message}}})}doneResponse(e,t,i){let n=i&&typeof i.usage=="object"&&i.usage!==null?i.usage:null,s=[];for(let p=t;p<this.items.length;p++)s.push(this.itemToProtocol(this.items[p]));return this.responseObject(e,"completed",{output:s,usage:n?{input_tokens:typeof n.input_tokens=="number"&&Number.isFinite(n.input_tokens)?n.input_tokens:0,output_tokens:typeof n.output_tokens=="number"&&Number.isFinite(n.output_tokens)?n.output_tokens:0,total_tokens:typeof n.total_tokens=="number"&&Number.isFinite(n.total_tokens)?n.total_tokens:(typeof n.input_tokens=="number"&&Number.isFinite(n.input_tokens)?n.input_tokens:0)+(typeof n.output_tokens=="number"&&Number.isFinite(n.output_tokens)?n.output_tokens:0),input_token_details:{cached_tokens:0,audio_tokens:0,text_tokens:0},output_token_details:{audio_tokens:0,text_tokens:0}}:null})}upstreamErrorBody(e){let t=e.error,i=t&&typeof t.message=="string"?t.message:JSON.stringify(e);return{type:"server_error",code:t&&typeof t.code=="string"?t.code:null,message:i}}emitUpstreamFault(e,t){if(this.cancelled)return;let i=E(null,e instanceof Error?e.message:String(e));this.responseFlushed?this.send(m(i)):this.send({type:"response.failed",event_id:r("event"),response:this.failedResponse(t,i)})}cancelResponse(){let e=this.inFlight;if(!e){this.send(m(f("no_response_to_cancel","no response is in progress","response.cancel")));return}this.cancelled=!0;let t=this.activeResponseId??"resp_";e.finally(()=>{this.send({type:"response.cancelled",event_id:r("event"),response:this.responseObject(t,"cancelled")})})}pushItem(e){this.items.push(e),this.items.length>U&&(this.items.shift(),this.send(m({type:"invalid_request_error",code:"transcript_evicted",message:`the conversation transcript exceeded ${U} items \u2014 the oldest item was evicted to keep the per-connection bound`})))}itemToProtocol(e){let t={id:e.id,object:"realtime.item"};if(e.type==="function_call")return{...t,type:"function_call",call_id:e.callId,name:e.name,arguments:e.arguments??"{}",status:"completed"};if(e.type==="function_call_output")return{...t,type:"function_call_output",call_id:e.callId,output:e.output};let i=(e.content??[]).map(n=>n.type==="input_text"||n.type==="output_text"?{type:n.type,text:n.text}:n.type==="input_audio"?{type:"input_audio",...n.transcript?{transcript:n.transcript}:{}}:{type:"output_audio",transcript:n.transcript??""});return{...t,type:"message",role:e.role,status:e.truncated?"incomplete":"completed",content:i}}send(e){if(!(this.closed||this.ws.readyState!==this.ws.OPEN)){if(this.ws.bufferedAmount>$){this.ws.close(ue,X("outbound buffer exceeded")),this.teardown("outbound buffer exceeded");return}this.ws.send(JSON.stringify(e))}}fail(e,t){this.send(m(e)),this.ws.close(de,X(t)),this.teardown(t)}teardown(e){if(!this.closed){this.closed=!0,this.turnLaneAbort?.abort(),this.turnLaneAbort=null,this.releaseVoiceBinding(),this.audioUnsubscribe?.(),this.audioUnsubscribe=null;try{this.ws.removeAllListeners("message")}catch{}this.onClosed?.(this),le(this.id,e)}}},V=[];function le(a,e){V.push({id:a,reason:e}),V.length>256&&V.shift()}var G="/v1/realtime",me=a=>a.slice(0,120);function _e(a,e,t){let i=e===401||e===403?"Unauthorized":e===502?"Upstream Fault":"Upgrade Refused";a.write(`HTTP/1.1 ${e} ${i}\r
|
|
2
|
-
Connection: close\r
|
|
3
|
-
Content-Type: text/plain\r
|
|
4
|
-
\r
|
|
5
|
-
${me(t)}\r
|
|
6
|
-
`),a.destroy()}function J(a,e){let t=new ce({noServer:!0}),i=new Set;return a.on("upgrade",(n,s,p)=>{if(new URL(n.url??"/","http://localhost").pathname!==G)return;i.add(s),s.on("close",()=>{i.delete(s)});let l=c=>{let y=c,x=y.session!=null&&typeof y.session.sendResponseCreate=="function",C=y.clients!=null&&typeof y.clients.createResponse=="function";if(!x&&!C)throw new Error("resolver returned a binding without an upstream turn seam (session.sendResponseCreate or clients.createResponse required) \u2014 refusing the upgrade LOUD");return new Promise((N,h)=>{t.handleUpgrade(n,s,p,A=>{try{new R({ws:A,binding:c}),N()}catch(I){h(I)}})})};(typeof e.resolver=="function"?e.resolver:e.resolver.resolve.bind(e.resolver))(n).then(l).catch(c=>{let y=c&&typeof c=="object"&&typeof c.status=="number"?c.status:502,x=c instanceof Error?c.message:String(c);s.destroyed||_e(s,y,x)}).finally(()=>{i.delete(s)})}),async()=>{let n=Date.now()+5e3;for(;i.size>0&&Date.now()<n;)await new Promise(s=>setTimeout(s,25));await new Promise(s=>t.close(()=>s()))}}export{Z as GEMINI_LIVE_PATH,G as OPENAI_REALTIME_PATH,R as OpenAIRealtimeConnection,ee as ResumptionRegistry,K as SessionGoneError,H as UnknownModelError,Q as VIDEO_OUT_SETUP_KEY,te as attachGeminiLive,J as attachOpenAIRealtime,ie as createOpenAIProxy,ne as serveGeminiLiveSocket};
|
|
1
|
+
import{Q as I,a as n,b as p,c as m,f as l,g as a,h as x,i as s,j as O,k as f}from"../chunk-NY23USZF.js";import{d as r,e as i}from"../chunk-3WAJD62J.js";import{a as o,h as t}from"../chunk-7M6LY6DR.js";import"../chunk-BSHT6RZZ.js";import{c as e}from"../chunk-5CCJUNH7.js";e();export{o as GEMINI_LIVE_PATH,a as OPENAI_REALTIME_PATH,l as OpenAIRealtimeConnection,n as ResumptionRegistry,i as SessionGoneError,r as UnknownModelError,t as VIDEO_OUT_SETUP_KEY,p as attachGeminiLive,x as attachOpenAIRealtime,I as createOpenAIProxy,f as fixedClientsResolver,O as realtimeBindingFor,s as realtimeModelOf,m as serveGeminiLiveSocket};
|