@urun-sh/openai 0.5.3 → 0.5.5

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 (43) hide show
  1. package/dist/chunk-5BZCM3RS.js +4 -0
  2. package/dist/chunk-DMD5UENK.js +1 -0
  3. package/dist/{chunk-G3NMGP4N.js → chunk-GBBY3PCZ.js} +1 -1
  4. package/dist/chunk-I2Q3B3OG.js +6 -0
  5. package/dist/chunk-K23AZPI4.js +1 -0
  6. package/dist/chunk-OI2OY32M.js +1 -0
  7. package/dist/chunk-QVF7NF7G.js +44 -0
  8. package/dist/gemini-live.cjs +2 -2
  9. package/dist/gemini-live.d.cts +6 -0
  10. package/dist/gemini-live.d.ts +6 -0
  11. package/dist/gemini-live.js +1 -1
  12. package/dist/hosted/bin.cjs +36 -22
  13. package/dist/hosted/bin.js +4 -4
  14. package/dist/hosted/index.cjs +32 -18
  15. package/dist/hosted/index.d.cts +140 -198
  16. package/dist/hosted/index.d.ts +63 -82
  17. package/dist/hosted/index.js +1 -1
  18. package/dist/index.cjs +1 -1
  19. package/dist/index.d.cts +2 -18
  20. package/dist/index.d.ts +2 -18
  21. package/dist/index.js +1 -1
  22. package/dist/models-NYMZrklp.d.cts +38 -0
  23. package/dist/models-NYMZrklp.d.ts +38 -0
  24. package/dist/pi-extension/index.cjs +6 -6
  25. package/dist/pi-extension/index.js +1 -1
  26. package/dist/pi-extension/standalone.cjs +49 -49
  27. package/dist/proxy/cli.cjs +41 -37
  28. package/dist/proxy/cli.js +1 -1
  29. package/dist/proxy/index.cjs +30 -21
  30. package/dist/proxy/index.d.cts +468 -2
  31. package/dist/proxy/index.d.ts +173 -2
  32. package/dist/proxy/index.js +6 -1
  33. package/dist/responses-turn-KOAoIqZ-.d.ts +200 -0
  34. package/dist/responses-turn-OrO4euEN.d.cts +513 -0
  35. package/package.json +3 -3
  36. package/dist/chunk-F2TEK34X.js +0 -1
  37. package/dist/chunk-FVD4NMXJ.js +0 -1
  38. package/dist/chunk-M6ICU4F5.js +0 -40
  39. package/dist/chunk-ODHCPZHI.js +0 -6
  40. package/dist/chunk-UVAY7Q7Z.js +0 -1
  41. package/dist/chunk-XHIIEA6Z.js +0 -1
  42. package/dist/server-BfME37pQ.d.cts +0 -200
  43. package/dist/server-l1himPxc.d.ts +0 -82
@@ -1 +1,6 @@
1
- import{b as t}from"../chunk-M6ICU4F5.js";import"../chunk-XHIIEA6Z.js";import{a as r,h as o}from"../chunk-5NXM4IO3.js";import"../chunk-CWJRDBDC.js";import{c as e}from"../chunk-YSFSRI3D.js";e();export{r as GEMINI_LIVE_PATH,o as VIDEO_OUT_SETUP_KEY,t as createOpenAIProxy};
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};
@@ -0,0 +1,200 @@
1
+ import { C as CatalogRow } from './models-NYMZrklp.js';
2
+ import { IncomingMessage } from 'node:http';
3
+ import { a as AudioBridge, h as VideoFrameLane, j as VideoOutLane } from './video-out-CWesbk12.js';
4
+
5
+ interface ProxyIdentity {
6
+ app: string;
7
+ org: string;
8
+ fn: string;
9
+
10
+ base_url: string;
11
+ proxy_version: string;
12
+ }
13
+
14
+ type OpenRouterProviderDoc = {
15
+ data: OpenRouterProviderModel[];
16
+ };
17
+ interface OpenRouterProviderModel {
18
+ schema_version: '2.4';
19
+
20
+ id: string;
21
+ name: string;
22
+ created: number;
23
+
24
+ quantization: string | null;
25
+ description: string;
26
+ hugging_face_id: string;
27
+ input_modalities: Array<Record<string, unknown>>;
28
+ output_modalities: Array<Record<string, unknown>>;
29
+ }
30
+
31
+ interface DeployedApp {
32
+ app_slug: string;
33
+ function_name?: string | null;
34
+ deployment_status?: string | null;
35
+ [k: string]: unknown;
36
+ }
37
+
38
+ declare class UnknownModelError extends Error {
39
+ }
40
+
41
+ declare class SessionGoneError extends Error {
42
+ }
43
+
44
+ interface RouterModelEntry {
45
+ id: string;
46
+ object: 'model';
47
+ created: number;
48
+ owned_by: string;
49
+
50
+ name?: string;
51
+
52
+ description?: string;
53
+
54
+ task?: string;
55
+
56
+ engine?: string;
57
+
58
+ gpu_spec?: string;
59
+
60
+ context_length?: number;
61
+ }
62
+ interface RouterModelList {
63
+ object: 'list';
64
+ data: RouterModelEntry[];
65
+ }
66
+ interface ModelRouterOptions<S> {
67
+
68
+ defaultApp: string | null;
69
+
70
+ fnName: string;
71
+
72
+ openSession: (appSlug: string) => S | Promise<S>;
73
+
74
+ closeSession: (entry: S) => Promise<void>;
75
+
76
+ listApps: (() => Promise<DeployedApp[]>) | null;
77
+
78
+ listCatalog: (() => Promise<CatalogRow[]>) | null;
79
+
80
+ appsTtlMs?: number;
81
+
82
+ sessionKey?: (entry: S) => string;
83
+ }
84
+
85
+ type ImageCapabilityMode = 'generation' | 'edit';
86
+
87
+ declare class ModelRouter<S> {
88
+ private readonly opts;
89
+ private readonly pool;
90
+ private appsCache;
91
+ private rowsCache;
92
+ constructor(opts: ModelRouterOptions<S>);
93
+
94
+ seed(appSlug: string, entry: S): void;
95
+ private deployedApps;
96
+
97
+ private catalogRows;
98
+
99
+ private servable;
100
+ private availableIds;
101
+
102
+ private noDefaultApp;
103
+
104
+ resolveApp(model: string | undefined): Promise<string>;
105
+
106
+ sessionFor(model: string | undefined): Promise<{
107
+ app: string;
108
+ entry: S;
109
+ }>;
110
+ private keyOf;
111
+
112
+ handleFor(model: string | undefined): Promise<{
113
+ app: string;
114
+ handle: string;
115
+ }>;
116
+
117
+ sessionForHandle(handle: string): Promise<{
118
+ app: string;
119
+ entry: S;
120
+ }>;
121
+
122
+ evict(app: string, entry: S): Promise<void>;
123
+
124
+ modelList(): Promise<RouterModelList>;
125
+
126
+ openRouterModels(): Promise<OpenRouterProviderDoc>;
127
+
128
+ supportsImages(model: string | undefined, mode: ImageCapabilityMode): Promise<boolean>;
129
+
130
+ closeAll(): Promise<void>;
131
+ }
132
+
133
+ interface ResponsesCreateParams {
134
+ model?: string;
135
+ input: unknown;
136
+ stream?: boolean;
137
+ tools?: unknown;
138
+ tool_choice?: unknown;
139
+ temperature?: number;
140
+ max_output_tokens?: number;
141
+
142
+ instructions?: string;
143
+ top_p?: number;
144
+ stop?: string[];
145
+
146
+ reasoning_effort?: string;
147
+ chat_template_kwargs?: Record<string, unknown>;
148
+ }
149
+
150
+ interface SessionEndInfo {
151
+
152
+ timeLeftMs: number | null;
153
+
154
+ reason: string;
155
+ }
156
+
157
+ interface ProxyClients {
158
+
159
+ createResponse(params: ResponsesCreateParams): Promise<AsyncIterable<unknown>> | AsyncIterable<unknown>;
160
+
161
+ listModels(): Promise<unknown>;
162
+
163
+ openRouterModels?(): Promise<unknown>;
164
+
165
+ openAudio?(model: string | undefined): Promise<ProxyAudioLane>;
166
+
167
+ openVideo?(model: string | undefined): Promise<ProxyVideoLane>;
168
+
169
+ openVideoOut?(model: string | undefined): Promise<ProxyVideoOutLane>;
170
+
171
+ sessionHandle(model: string | undefined): Promise<string>;
172
+
173
+ createResponseOn(handle: string, params: ResponsesCreateParams): Promise<AsyncIterable<unknown>> | AsyncIterable<unknown>;
174
+
175
+ onSessionEnd(handle: string, cb: (end: SessionEndInfo) => void): Promise<() => void>;
176
+ }
177
+
178
+ type ProxyAudioLane = Pick<AudioBridge, 'appendInputAudio' | 'onOutputAudio'>;
179
+
180
+ type ProxyVideoLane = Pick<VideoFrameLane, 'sendInputFrame'>;
181
+
182
+ type ProxyVideoOutLane = Pick<VideoOutLane, 'codec' | 'onOutputFrame' | 'onLaneError'>;
183
+
184
+ type ProxyClientsFor = (req: IncomingMessage) => ProxyClients | Promise<ProxyClients>;
185
+ interface ProxyHandlerOptions {
186
+
187
+ clients: ProxyClients | ProxyClientsFor;
188
+
189
+ apiKey?: string;
190
+
191
+ identity?: ProxyIdentity;
192
+
193
+ statusOf?: (err: unknown) => {
194
+ status: number;
195
+ openaiType: string;
196
+ anthropicType: string;
197
+ } | null;
198
+ }
199
+
200
+ export { ModelRouter as M, type ProxyClients as P, SessionGoneError as S, UnknownModelError as U, type ProxyHandlerOptions as a, type ProxyIdentity as b, type ProxyVideoOutLane as c };