@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.
Files changed (55) hide show
  1. package/dist/{ResponsesClient-BYx3YLGo.d.ts → ResponsesClient-BE3-hx3m.d.ts} +2 -0
  2. package/dist/{ResponsesClient-Dft3bg3b.d.cts → ResponsesClient-DjZWjlFH.d.cts} +2 -0
  3. package/dist/chunk-2T2YYBVX.js +1 -0
  4. package/dist/chunk-3WAJD62J.js +4 -0
  5. package/dist/{chunk-K23AZPI4.js → chunk-5HKWNK3O.js} +1 -1
  6. package/dist/chunk-7M6LY6DR.js +2 -0
  7. package/dist/chunk-BSHT6RZZ.js +1 -0
  8. package/dist/{chunk-GBBY3PCZ.js → chunk-FP4RSAIE.js} +1 -1
  9. package/dist/chunk-HR5H6S7L.js +1 -0
  10. package/dist/chunk-NY23USZF.js +57 -0
  11. package/dist/chunk-VLRMJRLS.js +6 -0
  12. package/dist/gemini-live.cjs +2 -2
  13. package/dist/gemini-live.d.cts +17 -2
  14. package/dist/gemini-live.d.ts +7 -2
  15. package/dist/gemini-live.js +1 -1
  16. package/dist/hosted/bin.cjs +40 -26
  17. package/dist/hosted/bin.js +4 -4
  18. package/dist/hosted/index.cjs +39 -26
  19. package/dist/hosted/index.d.cts +643 -16
  20. package/dist/hosted/index.d.ts +153 -5
  21. package/dist/hosted/index.js +1 -1
  22. package/dist/index.cjs +1 -1
  23. package/dist/index.d.cts +4 -4
  24. package/dist/index.d.ts +4 -4
  25. package/dist/index.js +1 -1
  26. package/dist/{models-NYMZrklp.d.cts → models-DUdx_Y6X.d.cts} +1 -1
  27. package/dist/pi-extension/index.cjs +7 -7
  28. package/dist/pi-extension/index.d.cts +1 -1
  29. package/dist/pi-extension/index.d.ts +1 -1
  30. package/dist/pi-extension/index.js +1 -1
  31. package/dist/pi-extension/standalone.cjs +48 -48
  32. package/dist/proxy/cli.cjs +53 -43
  33. package/dist/proxy/cli.js +14 -14
  34. package/dist/proxy/index.cjs +32 -30
  35. package/dist/proxy/index.d.cts +84 -8
  36. package/dist/proxy/index.d.ts +16 -6
  37. package/dist/proxy/index.js +1 -6
  38. package/dist/responses-turn-Dr37N3kH.d.ts +486 -0
  39. package/dist/responses-turn-tNUHq5b0.d.cts +1807 -0
  40. package/dist/{translator-C9uPKypK.d.ts → translator-BCoRFaTs.d.ts} +1 -1
  41. package/dist/{translator-CcDBEfvm.d.cts → translator-Bh0Bp_Ie.d.cts} +3 -3
  42. package/dist/{video-out-D20UuJ8G.d.cts → video-out-CCksIcj8.d.cts} +5 -5
  43. package/package.json +12 -11
  44. package/dist/chunk-5BZCM3RS.js +0 -4
  45. package/dist/chunk-5NXM4IO3.js +0 -2
  46. package/dist/chunk-CWJRDBDC.js +0 -1
  47. package/dist/chunk-DMD5UENK.js +0 -1
  48. package/dist/chunk-I2Q3B3OG.js +0 -6
  49. package/dist/chunk-OI2OY32M.js +0 -1
  50. package/dist/chunk-QVF7NF7G.js +0 -44
  51. package/dist/responses-turn-KOAoIqZ-.d.ts +0 -200
  52. package/dist/responses-turn-OrO4euEN.d.cts +0 -513
  53. /package/dist/{chunk-YSFSRI3D.js → chunk-5CCJUNH7.js} +0 -0
  54. /package/dist/{models-NYMZrklp.d.ts → models-DUdx_Y6X.d.ts} +0 -0
  55. /package/dist/{video-out-CWesbk12.d.ts → video-out-IGQ4YQ-c.d.ts} +0 -0
@@ -1,10 +1,10 @@
1
1
  import { Server, IncomingMessage } from 'node:http';
2
- import { a as ProxyHandlerOptions, P as ProxyClients } from '../responses-turn-OrO4euEN.cjs';
3
- export { b as ProxyIdentity, c as ProxyVideoOutLane, S as SessionGoneError, U as UnknownModelError } from '../responses-turn-OrO4euEN.cjs';
4
- export { h as GEMINI_LIVE_PATH, V as VIDEO_OUT_SETUP_KEY } from '../translator-CcDBEfvm.cjs';
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-NYMZrklp.cjs';
7
- import '../video-out-D20UuJ8G.cjs';
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
- /** Bridge voice OUT frame → `response.output_audio.delta` on the open turn. */
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
- export { type GeminiLiveCall, type GeminiLiveClients, OPENAI_REALTIME_PATH, type OpenAIProxyOptions, OpenAIRealtimeConnection, type OpenAIRealtimeOptions, type OpenAIRealtimeResolver, ProxyClients, type RealtimeBinding, ResumptionRegistry, attachGeminiLive, attachOpenAIRealtime, createOpenAIProxy, serveGeminiLiveSocket };
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 };
@@ -1,10 +1,10 @@
1
1
  import { Server, IncomingMessage } from 'node:http';
2
- import { a as ProxyHandlerOptions, P as ProxyClients } from '../responses-turn-KOAoIqZ-.js';
3
- export { b as ProxyIdentity, c as ProxyVideoOutLane, S as SessionGoneError, U as UnknownModelError } from '../responses-turn-KOAoIqZ-.js';
4
- export { h as GEMINI_LIVE_PATH, V as VIDEO_OUT_SETUP_KEY } from '../translator-C9uPKypK.js';
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-NYMZrklp.js';
7
- import '../video-out-CWesbk12.js';
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
- export { type GeminiLiveCall, type GeminiLiveClients, OPENAI_REALTIME_PATH, type OpenAIProxyOptions, OpenAIRealtimeConnection, type OpenAIRealtimeOptions, type OpenAIRealtimeResolver, ProxyClients, type RealtimeBinding, ResumptionRegistry, attachGeminiLive, attachOpenAIRealtime, createOpenAIProxy, serveGeminiLiveSocket };
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 };
@@ -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};