openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
4 lines • 59 kB
JavaScript
import{n as e}from"./rolldown-runtime-8BhlS34s.js";import{Ji as t,Vi as n,Vt as r,Wi as i,no as a,ro as o,zt as s}from"./control-ui-foundation-ZY_Flbbd.js";import{Gl as c,hu as l,la as u,ql as d,uu as f}from"./control-ui-core-3P365fbR.js";import{h as ee,m as te}from"./control-ui-boot-shared-Rs4iS2kF.js";import{n as ne,t as re}from"./response-body-krIvH2yK.js";import{D as ie,E as ae,T as oe}from"./control-ui-boot-shared-BykNRHBP.js";import{A as se,C as p,E as ce,O as le,T as ue,X as de,Z as fe,at as pe,k as m,st as me,w as he}from"./control-ui-boot-shared-CApmg5ot.js";var ge,h;function g(){return(g=e((()=>{ge=3e3,h=class{constructor(e){this.onNotice=e,this.pendingMs=0,this.lossReported=!1}reserve(e){return this.pendingMs+e<=ge?(this.pendingMs+=e,!0):(this.lossReported||(this.lossReported=!0,this.onNotice(`Realtime Talk audio input fell behind; repeat the last part`)),!1)}settle(e){this.pendingMs=Math.max(0,this.pendingMs-e),this.lossReported&&(this.lossReported=!1,this.onNotice(`Microphone input recovered; repeat the last part`))}reset(){this.pendingMs=0,this.lossReported=!1}}})))()}var _;function v(){return(v=e((()=>{_=`openclaw_agent_consult`})))()}function _e(e){let t=a(e);return ae(t,S)?t:void 0}function y(e,t){return t.some(t=>t.test(e))}function ve(e){return/\b(?:don'?t|do\s+not|not|never)\s+(?:please\s+)?(?:cancel|cancle|stop|abort|kill|end)\b/.test(e)||/\bstop\s+(?:it|that|this)\s+from\b/.test(e)}function b(e){let t=_e(e.mode);if(t)return{mode:t,confidence:`high`,reason:`explicit_mode`,shouldAutoControl:!0};let n=e.text.trim().toLowerCase();return y(n,O)?{mode:`steer`,confidence:`medium`,reason:`steer_command`,shouldAutoControl:!0}:!ve(n)&&y(n,w)?{mode:`cancel`,confidence:`high`,reason:`cancel_safety`,shouldAutoControl:!0}:y(n,T)?{mode:`status`,confidence:`high`,reason:`status_query`,shouldAutoControl:!0}:y(n,E)?{mode:`followup`,confidence:`high`,reason:`followup_marker`,shouldAutoControl:!0}:y(n,D)?{mode:`steer`,confidence:`medium`,reason:`steer_command`,shouldAutoControl:!0}:{mode:`status`,confidence:`low`,reason:`safe_default`,shouldAutoControl:!1}}function x(e){return b({text:e}).shouldAutoControl}function ye(e){let t=be(e),r=n(t),i=ie(r,[`text`,`message`,`request`,`query`]);if(!i)throw Error(`text required`);return{text:i,mode:_e(r.mode)??b({text:i}).mode}}function be(e){if(typeof e!=`string`)return e;let t=e.trim();if(!t)return{};try{return JSON.parse(t)}catch{return{text:t}}}function xe(e){return[`Internal OpenClaw voice control result.`,`Do not delegate this message or call any tools.`,`Speak this exact OpenClaw status to the voice call, without adding, removing, or rephrasing words.`,`Status: ${JSON.stringify(e)}`].join(`
`)}function Se(e=`Cancelled the active OpenClaw run.`){return{status:`cancelled`,message:e}}var S,C,w,T,E,D,O;function k(){return(k=e((()=>{oe(),S=[`status`,`steer`,`cancel`,`followup`],C=`openclaw_agent_control`,w=[/^(?:(?:ok|okay|alright|all right)[,\s]+)?(?:please\s+)?(?:cancel|cancle|abort)(?:\s+(?:that|this|it|the\s+(?:check|run|task|work)))?(?:\s*[.!?])?$/,/^(?:(?:ok|okay|alright|all right)[,\s]+)?(?:please\s+)?(?:never mind|nevermind|forget it|kill it|end that)(?:\s*[.!?])?$/,/^(?:(?:ok|okay|alright|all right)[,\s]+)?(?:please\s+)?stop(?:\s+(?:that|this|it|the\s+(?:check|run|task|work)))?(?:\s*[.!?])?$/,/^(?:(?:ok|okay|alright|all right)[,\s]+)?(?:can|could|would)\s+you\s+(?:please\s+)?(?:cancel|cancle|stop|abort)(?:\s+(?:that|this|it|the\s+(?:check|run|task|work)))?(?:\s*[.!?])?$/,/^(?:(?:ok|okay|alright|all right|actually)[,\s]+)?(?:can|could|would)\s+(?:we|you)\s+(?:just\s+)?(?:cancel|cancle|stop|abort)(?:\s+(?:that|this|it|the\s+(?:check|run|task|work)))?(?:\s*[.!?])?$/,/\b(?:cancel|cancle|stop|abort)\s+(?:that|this|it|the\s+(?:check|run|task|work))\b/],T=[/^(?:(?:ok|okay|alright|all right)[,\s]+)?(?:status|progress|update)(?:\s*[.!?])?$/,/^(?:(?:ok|okay|alright|all right)[,\s]+)?(?:give me|what'?s|any)\s+(?:an?\s+)?update(?:\s*[.!?])?$/,/^(?:(?:ok|okay|alright|all right)[,\s]+)?(where are we|what'?s happening|what (?:are you|is it) doing|what'?s it doing|how (?:is|are) (?:it|you|that|this) going|how'?s it going|are you still working|is it done|did it finish)(\b|[.!?])/],E=[/^(after that|when you'?re done|when it'?s done|next|then|also|one more thing|follow up)(\b|[,.!?])/],D=[/^(?:(?:ok|okay|alright|all right)[,\s]+)?(?:please\s+)?update\s+\S/,/^(?:actually|instead|change|switch|focus|use|try|prefer|make|do|check|look at|go with|redirect|steer|tell it to)\b/,/^(?:can|could|would)\s+you\s+(?:actually\s+)?(?:change|switch|focus|use|try|prefer|make|do|check|look at|go with|redirect|steer)\b/,/\b(?:instead|not that|rather than|change that|switch to|focus on|use the|try the|go with|tell it to)\b/],O=[/^(?:(?:ok|okay|alright|all right)[,\s]+)?(?:please\s+)?stop\s+(?:using|doing|checking|looking at|focusing on|trying)\b/,/^(?:(?:ok|okay|alright|all right)[,\s]+)?(?:can|could|would)\s+(?:you|we)\s+(?:please\s+)?stop\s+(?:using|doing|checking|looking at|focusing on|trying)\b/,/^(?:(?:ok|okay|alright|all right)[,\s]+)?(?:please\s+)?stop\s+(?:that|this|it|the\s+(?:check|run|task|work))\s+from\b/]})))()}function A(e,t){let n=0,r=0,i,a=we(e,t);return r=>{if(!e.callbacks.onTalkEvent)return;let s=o(r);n+=1,e.callbacks.onTalkEvent({id:`${a}:${n}`,type:r.type,sessionId:a,turnId:s,captureId:r.captureId,seq:n,timestamp:new Date().toISOString(),mode:`realtime`,transport:t.transport,brain:`agent-consult`,provider:t.provider,final:r.final,callId:r.callId,itemId:r.itemId,parentId:r.parentId,payload:r.payload??null}),(r.type===`turn.ended`||r.type===`turn.cancelled`||r.type===`session.replaced`||r.type===`session.closed`)&&(i=void 0)};function o(e){return e.type!==`turn.started`&&!Ce(e.type)?e.turnId:(i=e.turnId??i??`turn-${++r}`,i)}}function Ce(e){return e===`turn.ended`||e===`turn.cancelled`||e.startsWith(`input.audio.`)||e.startsWith(`transcript.`)||e.startsWith(`output.`)||e.startsWith(`tool.`)}function we(e,t){let n=t.sessionId;return typeof n==`string`&&n.trim()?n.trim():`relaySessionId`in t&&t.relaySessionId.trim()?t.relaySessionId:`${e.sessionKey}:${t.provider}:${t.transport}`}function Te(e){if(!e||typeof e!=`object`)return``;let t=e;return typeof t.text==`string`?t.text:(Array.isArray(t.content)?t.content:[]).map(e=>{if(!e||typeof e!=`object`)return``;let t=e;return t.type===`text`&&typeof t.text==`string`?t.text:``}).filter(Boolean).join(`
`).trim()}function Ee(e){if(!e)return;let t=e.error?.trim();if(e.status===`error`)return Error(t||`OpenClaw tool call failed`);if(e.status!==`timeout`||e.pendingError)return;let n=e.stopReason?.trim(),r=e.timeoutPhase?.trim(),i=e.livenessState?.trim();if(e.endedAt!==void 0||t!==void 0||e.aborted===!0||i!==void 0&&i.length>0||e.yielded===!0||n!==void 0&&n.length>0||r===`preflight`||r===`provider`||r===`post_turn`||e.providerStarted===!0)return Error(t||`OpenClaw tool call timed out`)}function De(e){return new Promise((t,n)=>{if(e.signal?.aborted){n(new DOMException(`OpenClaw tool call aborted`,`AbortError`));return}let r=window.setTimeout(()=>{u(Error(`OpenClaw tool call timed out`))},e.timeoutMs),i=!1,a=!1,o,s=()=>{u(new DOMException(`OpenClaw tool call aborted`,`AbortError`))};e.signal?.addEventListener(`abort`,s,{once:!0});let c=()=>void 0,l=e=>{i||(i=!0,f(),t(e))},u=e=>{i||(i=!0,f(),n(e))},d=()=>{a||(a=!0,e.client.request(`agent.wait`,{runId:e.runId,timeoutMs:e.timeoutMs}).then(e=>{if(i)return;let t=Ee(e);if(t){u(t);return}e?.status!==`timeout`&&(o=window.setTimeout(()=>{l(`OpenClaw finished with no text.`)},R))}).catch(e=>{u(e instanceof Error?e:Error(String(e)))}))};c=e.client.addEventListener(t=>{if(t.event!==`chat`)return;let n=t.payload;if(n&&n.runId===e.runId){if(Oe(e.emitTalkEvent,n),n.state===`final`){let e=Te(n.message);if(e){l(e);return}d()}else n.state===`aborted`?u(new DOMException(n.errorMessage??`OpenClaw tool call aborted`,`AbortError`)):n.state===`error`&&u(Error(n.errorMessage??`OpenClaw tool call failed`))}});function f(){window.clearTimeout(r),o!==void 0&&window.clearTimeout(o),e.signal?.removeEventListener(`abort`,s),c()}})}function Oe(e,t){if(!e||t.stream!==`tool`)return;let n=t.data&&typeof t.data==`object`?t.data:{},r=typeof n.phase==`string`?n.phase:void 0,i=typeof n.name==`string`?n.name:void 0;e({type:`tool.progress`,callId:typeof n.toolCallId==`string`?n.toolCallId:void 0,payload:{runId:t.runId,...i?{name:i}:{},...r?{phase:r}:{}}})}function j(e,t,n,r){let i={sessionKey:e.sessionKey,text:n,...r?{mode:r}:{}};return t&&t.trim()?e.client.request(`talk.session.steer`,{sessionId:t,...i}):e.client.request(`talk.client.steer`,i)}function M(e){return{type:`tool.progress`,payload:{name:C,result:e},final:e&&typeof e==`object`&&`mode`in e?e.mode===`status`||e.mode===`cancel`:void 0}}function N(e){let t=i(e);return t?.ok===!0&&(t.mode===`cancel`||t.suppress===!0&&t.mode!==`steer`)}async function P(e){let t=e.text.trim();if(!t)return;let n=j(e.ctx,e.sessionId,t,e.mode);try{let t=await n;e.onControlResult?.(t),ke(t,e.speakControlResult,e.suppressSpeechForModes),e.emitTalkEvent?.(M(t))}catch(t){e.emitTalkEvent?.({type:`tool.error`,payload:{message:c(t)},final:!0})}}async function F(e){if(e.signal?.aborted)return;let t,n;try{let r=ye(e.args);if(t=await j(e.ctx,e.sessionId,r.text,r.mode),e.signal?.aborted)return;n={...M(t),callId:e.callId}}catch(r){let i=c(r);if(n={type:`tool.error`,callId:e.callId,payload:{message:i},final:!0},t={error:i},e.signal?.aborted||L(r))return}await e.submit(e.callId,t),!e.signal?.aborted&&e.emitTalkEvent?.(n)}function ke(e,t,n){if(!t||!e||typeof e!=`object`)return;let r=e,i=typeof r.mode==`string`?r.mode:void 0;if(i&&n?.includes(i))return;let a=typeof r.message==`string`?r.message.trim():``;(r.speak===!0&&r.suppress!==!0||r.ok===!0&&i===`steer`&&r.suppress===!0)&&a&&t(xe(a))}async function I(e){let{ctx:t,callId:n,submit:r}=e;t.callbacks.onStatus?.(`thinking`);let i,a=!1,o=!1,s=!1,l=async e=>{o||(o=!0,await r(n,e),s=!0)},u=async()=>{e.submitAbortResult!==!1&&await l(Se())},d=()=>{a=!0,i&&t.client.request(`chat.abort`,{sessionKey:i.agentSessionKey,agentId:i.agentId,runId:i.runId})};if(e.signal?.aborted){await u();return}e.signal?.addEventListener(`abort`,d,{once:!0});try{let r=typeof e.args==`string`?JSON.parse(e.args||`{}`):e.args??{};if(await t.flushTranscriptWrites?.(),e.signal?.aborted){await u();return}if(i=await t.client.request(`talk.client.toolCall`,{sessionKey:t.sessionKey,...t.voiceSessionId?{voiceSessionId:t.voiceSessionId}:{},callId:n,name:_,args:r,...e.relaySessionId?{relaySessionId:e.relaySessionId}:{}}),e.signal?.aborted){d(),await u();return}await l({result:await De({client:t.client,runId:i.runId,timeoutMs:12e4,emitTalkEvent:e.emitTalkEvent,signal:e.signal})})}catch(t){if(o)throw t;if(a||e.signal?.aborted||L(t)){await u();return}await l({error:c(t)})}finally{e.signal?.removeEventListener(`abort`,d),s&&!a&&!e.signal?.aborted&&t.callbacks.onStatus?.(`listening`)}}function L(e){return typeof e==`object`&&!!e&&`name`in e&&e.name===`AbortError`}var R;function z(){return(z=e((()=>{v(),k(),d(),R=500})))()}function Ae(e){try{return(JSON.stringify(e)?.length??0)*2}catch{return 262145}}var B,V,je,Me,Ne,Pe,Fe,Ie;function Le(){return(Le=e((()=>{r(),te(),f(),d(),g(),m(),z(),B=.02,V=.08,je=2,Me=8e3,Ne=8e3,Pe=32,Fe=262144,Ie=class{constructor(e,t){this.session=e,this.ctx=t,this.input=this.ctx.input,this.inputContext=null,this.outputContext=null,this.inputMeter=null,this.inputPump=new he,this.unsubscribe=null,this.closed=!1,this.closeCompletion=Promise.resolve(),this.audioAppendAbortController=null,this.audioInputBudget=new h(e=>this.ctx.callbacks.onInputNotice?.(e)),this.outputQueue=new ue,this.toolAbortControllers=new Map,this.completedToolCalls=new Set,this.submittingToolCalls=new Set,this.delayedToolResults=new Set,this.markAckTimers=new Set,this.cancelRequestedForPlayback=!1,this.activeOutputTurnId=null,this.playbackOverflowed=!1,this.pendingOutputCancellations=0,this.speechFramesDuringPlayback=0,this.supportsBargeIn=!0,this.activated=!1,this.pendingActivationEvents=[],this.pendingActivationEventBytes=0,this.startupError=null}async start(){if(this.session.audio.inputEncoding!==`pcm16`||this.session.audio.outputEncoding!==`pcm16`)throw Error(`Gateway-relay realtime Talk currently requires PCM16 audio`);this.closed=!1,this.activated=!1,this.pendingActivationEvents=[],this.pendingActivationEventBytes=0,this.startupError=null,this.unsubscribe=this.ctx.client.addEventListener(e=>{e.event===`talk.event`&&this.handleIncomingRelayEvent(e.payload)});let e=await this.ctx.client.request(`talk.catalog`,{provider:this.session.provider,...this.session.model?{model:this.session.model}:{}},{timeoutMs:s}).catch(()=>void 0);if(this.closed){let e=this.currentStartupError();if(e)throw e;return`cancelled`}this.supportsBargeIn=e?e.realtime.providers.find(e=>e.id===this.session.provider||e.aliases?.includes(this.session.provider))?.supportsBargeIn!==!1:!1;let t=this.input.adopt(e=>this.failAudioAppend(e)),n=this.currentStartupError();if(n)throw this.input.stop(),n;return this.closed?`cancelled`:(this.inputContext=new AudioContext({sampleRate:this.session.audio.inputSampleRateHz}),this.outputContext=new AudioContext({sampleRate:this.session.audio.outputSampleRateHz}),this.abortPendingAudioAppends(),this.audioAppendAbortController=new AbortController,this.ctx.callbacks.onInputLevel&&(this.inputMeter=new p(this.ctx.callbacks.onInputLevel),this.inputMeter.start(t,this.inputContext)),this.startMicrophonePump(),`ready`)}activate(){if(this.startupError)throw this.startupError;if(this.closed||this.activated)return;this.activated=!0;let e=this.pendingActivationEvents;this.pendingActivationEvents=[],this.pendingActivationEventBytes=0;for(let t of e){try{this.handleRelayEvent(t)}catch(e){throw this.stop(),e}if(this.closed)return}}stop(){let e=this.closed;return this.stopLocal(),e||(this.closeCompletion=this.ctx.client.request(`talk.session.close`,{sessionId:this.session.relaySessionId},{timeoutMs:Ne}).then(()=>void 0),this.closeCompletion.catch(()=>void 0)),this.closeCompletion}stopLocal(){this.closed=!0,this.input.stop(),this.activated=!1,this.pendingActivationEvents=[],this.pendingActivationEventBytes=0,this.unsubscribe?.(),this.unsubscribe=null,this.inputPump.stop(),this.abortPendingAudioAppends(),this.inputMeter?.stop(),this.inputMeter=null,this.markAckTimers.forEach(e=>window.clearTimeout(e)),this.markAckTimers.clear(),this.discardDelayedToolResults(),this.abortConsults(),this.playbackOverflowed=!1,this.activeOutputTurnId=null,this.stopOutput(),this.inputContext?.close(),this.inputContext=null,this.outputContext?.close(),this.outputContext=null}startMicrophonePump(){this.input.stream&&this.inputContext&&this.inputPump.start(this.input.stream,this.inputContext,e=>{if(this.closed)return;this.supportsBargeIn&&this.detectBargeInSpeech(e)&&this.cancelOutput(`barge-in`);let t=this.audioAppendAbortController,n=e.length/this.session.audio.inputSampleRateHz*1e3;if(!t||t.signal.aborted||this.pendingOutputCancellations||!this.audioInputBudget.reserve(n))return;let r=le(e);this.ctx.client.request(`talk.session.appendAudio`,{sessionId:this.session.relaySessionId,audioBase64:u(r),timestamp:Math.round((this.inputContext?.currentTime??0)*1e3)},{signal:t.signal,timeoutMs:Me}).catch(e=>this.failAudioAppend(e)).finally(()=>this.audioInputBudget.settle(n))})}abortPendingAudioAppends(){this.audioAppendAbortController?.abort(),this.audioAppendAbortController=null,this.audioInputBudget.reset()}failAudioAppend(e){if(!this.closed)try{this.ctx.callbacks.onStatus?.(`error`,c(e))}finally{this.stop()}}currentStartupError(){return this.startupError}handleIncomingRelayEvent(e){if(e.relaySessionId!==this.session.relaySessionId||this.closed)return;if(this.activated){this.handleRelayEvent(e);return}if(e.type===`error`&&(this.lastRelayError=e.message?c(e.message):`Realtime relay failed`),e.type===`close`){this.startupError=Error(e.reason===`error`?this.lastRelayError??`Realtime relay closed before browser setup completed`:`Realtime relay closed before browser setup completed`),this.stopLocal();return}let t=Ae(e);if(this.pendingActivationEvents.length>=Pe||t>Fe-this.pendingActivationEventBytes){this.startupError=Error(`Realtime relay emitted too much data before browser setup completed`),this.stop();return}this.pendingActivationEvents.push(e),this.pendingActivationEventBytes+=t}handleRelayEvent(e){if(e.relaySessionId!==this.session.relaySessionId||this.closed)return;let t=e.type===`close`;try{switch(e.talkEvent&&this.ctx.callbacks.onTalkEvent?.(e.talkEvent),e.type){case`ready`:this.ctx.callbacks.onStatus?.(`listening`);return;case`audio`:if(e.audioBase64&&!this.playbackOverflowed){let t=e.talkEvent?.turnId?.trim();if(!t){this.ctx.callbacks.onStatus?.(`error`,l(`chat.composer.realtimeTalkMissingTurnIdentity`)),this.stop();return}(this.activeOutputTurnId!==t||!this.outputQueue.isPlaying)&&(this.speechFramesDuringPlayback=0),this.activeOutputTurnId=t,this.cancelRequestedForPlayback=!1,this.playPcm16(e.audioBase64)}return;case`clear`:if(e.talkEvent?.turnId&&e.talkEvent.turnId!==this.activeOutputTurnId)return;this.playbackOverflowed=!1,this.stopOutput({releaseDelayedToolResults:this.pendingOutputCancellations===0}),this.activeOutputTurnId=null,e.talkEvent?.type===`turn.cancelled`&&this.abortConsults();return;case`mark`:e.markName&&this.scheduleMarkAck(e.markName);return;case`transcript`:e.role&&e.text&&this.ctx.callbacks.onTranscript?.({role:e.role,text:e.text,final:e.final??!1,...e.textMode?{textMode:e.textMode}:{},...e.transcriptId?{transcriptId:e.transcriptId}:{}});return;case`toolCall`:this.handleToolCall(e).catch(e=>{this.reportToolResultSubmissionError(e)});return;case`toolCallCancelled`:this.cancelToolCall(e.callId);return;case`toolResult`:this.isFinalToolResult(e)&&this.completeToolCall(e.callId);return;case`error`:this.lastRelayError=e.message?c(e.message):`Realtime relay failed`,this.ctx.callbacks.onStatus?.(`error`,this.lastRelayError);return;case`close`:this.abortConsults(),this.ctx.callbacks.onStatus?.(e.reason===`error`?`error`:`idle`,e.reason===`error`?this.lastRelayError??`Realtime relay closed`:void 0)}}finally{t&&!this.closed&&this.stopLocal()}}playPcm16(e){this.outputQueue.play(e,this.outputContext,this.session.audio.outputSampleRateHz)===`overflow`&&(this.playbackOverflowed=!0,this.cancelOutput(`playback-overflow`,!1))}stopOutput(e={}){this.outputQueue.stop(this.outputContext),this.speechFramesDuringPlayback=0,(e.releaseDelayedToolResults??!0)&&this.rescheduleDelayedToolResults()}scheduleMarkAck(e){let t=this.outputPlaybackDelayMs();if(t>0){let n=window.setTimeout(()=>{this.markAckTimers.delete(n),this.scheduleMarkAck(e)},t);this.markAckTimers.add(n);return}this.closed||this.ctx.client.request(`talk.session.acknowledgeMark`,{sessionId:this.session.relaySessionId,markName:e}).catch(e=>this.reportToolResultSubmissionError(e))}async handleToolCall(e){let t=e.callId?.trim(),n=e.name?.trim();if(!t||!n)return;if(n!==`openclaw_agent_control`&&n!==`openclaw_agent_consult`){await this.submitToolResult(t,{error:`Tool "${n}" not available in browser Talk`});return}let r=new AbortController;this.toolAbortControllers.set(t,r);try{if(n===`openclaw_agent_control`){await F({ctx:this.ctx,callId:t,args:e.args??{},sessionId:this.session.relaySessionId,signal:r.signal,submit:(e,t)=>this.submitToolResult(e,t)});return}if(e.forced){if(await this.submitToolResult(t,{status:`working`,tool:_,message:`Tell the person briefly that you are checking, then wait for the final OpenClaw result before answering with the actual result.`},{willContinue:!0}),this.completedToolCalls.has(t))return;if(r.signal.aborted){await this.submitToolResult(t,{status:`cancelled`});return}}await I({ctx:this.ctx,callId:t,args:e.args??{},relaySessionId:this.session.relaySessionId,signal:r.signal,submit:(e,t)=>this.submitToolResult(e,t)})}finally{this.toolAbortControllers.get(t)===r&&this.toolAbortControllers.delete(t)}}async submitToolResult(e,t,n){if(this.completedToolCalls.has(e))return;let r=n?.suppressResponse!==!0&&n?.willContinue!==!0;if(!this.closed&&r&&(this.pendingOutputCancellations>0||this.outputPlaybackDelayMs()>0)){let r={callId:e,result:t,...n?{options:n}:{}};this.delayedToolResults.add(r),this.rescheduleDelayedToolResult(r);return}await this.sendToolResultNow(e,t,n)}async sendToolResultNow(e,t,n){if(!this.completedToolCalls.has(e)){this.submittingToolCalls.add(e);try{await this.ctx.client.request(`talk.session.submitToolResult`,{sessionId:this.session.relaySessionId,callId:e,result:t,...n?{options:n}:{}})}finally{this.submittingToolCalls.delete(e)}}}outputPlaybackDelayMs(){return this.outputContext?Math.max(0,Math.ceil((this.outputQueue.queuedUntil-this.outputContext.currentTime)*1e3)):0}rescheduleDelayedToolResult(e){if(this.closed){this.discardDelayedToolResult(e);return}if(this.pendingOutputCancellations>0)return;let t=this.outputPlaybackDelayMs();if(t>0){e.timer=window.setTimeout(()=>{e.timer=void 0,this.rescheduleDelayedToolResult(e)},t);return}this.discardDelayedToolResult(e),this.sendToolResultNow(e.callId,e.result,e.options).catch(e=>{this.reportToolResultSubmissionError(e)})}rescheduleDelayedToolResults(){for(let e of this.delayedToolResults)this.rescheduleDelayedToolResult(e)}pauseDelayedToolResults(){for(let e of this.delayedToolResults)e.timer!==void 0&&(window.clearTimeout(e.timer),e.timer=void 0)}discardDelayedToolResults(){for(let e of this.delayedToolResults)this.discardDelayedToolResult(e)}discardDelayedToolResult(e){e.timer!==void 0&&(window.clearTimeout(e.timer),e.timer=void 0),this.delayedToolResults.delete(e)}reportToolResultSubmissionError(e){if(this.closed)return;let t=c(e);this.lastRelayError=t,this.ctx.callbacks.onStatus?.(`error`,t)}completeToolCall(e){let t=e?.trim();t&&(this.completedToolCalls.add(t),!this.submittingToolCalls.has(t)&&(this.toolAbortControllers.get(t)?.abort(),this.toolAbortControllers.delete(t)))}cancelToolCall(e){let t=e?.trim();if(t){this.completedToolCalls.add(t),this.toolAbortControllers.get(t)?.abort(),this.toolAbortControllers.delete(t);for(let e of this.delayedToolResults)e.callId===t&&this.discardDelayedToolResult(e)}}isFinalToolResult(e){let t=e.talkEvent;return!(t?.type===`tool.progress`||t?.type===`tool.result`&&t.final===!1)}cancelOutput(e,t=!0){if(t&&!this.outputQueue.isPlaying||this.cancelRequestedForPlayback)return;let n=this.activeOutputTurnId;if(!n){this.ctx.callbacks.onStatus?.(`error`,l(`chat.composer.realtimeTalkMissingTurnIdentity`)),this.stop();return}this.cancelRequestedForPlayback=!0,this.pendingOutputCancellations+=1,this.pauseDelayedToolResults(),this.stopOutput({releaseDelayedToolResults:!1}),this.ctx.client.request(`talk.session.cancelOutput`,{sessionId:this.session.relaySessionId,reason:e,turnId:n}).then(e=>{if(!ee(e)||(e.status===void 0||e.status===`applied`)&&e.turnId!==void 0&&e.turnId!==n)throw Error(l(`chat.composer.realtimeTalkCancellationRejected`));--this.pendingOutputCancellations,this.pendingOutputCancellations===0&&this.rescheduleDelayedToolResults()}).catch(e=>{--this.pendingOutputCancellations,this.reportToolResultSubmissionError(e),this.stop()})}abortConsults(){for(let e of this.toolAbortControllers.values())e.abort();this.toolAbortControllers.clear()}detectBargeInSpeech(e){if(!this.outputQueue.isPlaying||this.cancelRequestedForPlayback)return this.speechFramesDuringPlayback=0,!1;let t=se(e);return t.rms>=B&&t.peak>=V?this.speechFramesDuringPlayback+=1:this.speechFramesDuringPlayback=0,this.speechFramesDuringPlayback>=je}}})))()}var H;function U(){return(U=e((()=>{H=class{constructor(e){this.options=e,this.stream=null,this.video=null,this.setupController=null,this.handleTrackEnded=()=>this.release()}async setEnabled(e){if(!e){this.release();return}if(this.options.isClosed())throw Error(`Realtime Talk session is closed`);if(this.hasLiveTrack())return;this.setupController?.abort();let t=new AbortController;this.setupController=t;let n;try{n=await this.options.acquire(this.options.getDeviceId(),t.signal)}catch(e){if(this.options.isClosed()||t.signal.aborted)return;throw e}finally{this.setupController===t&&(this.setupController=null)}if(this.options.isClosed()||t.signal.aborted){n.getTracks().forEach(e=>e.stop());return}this.stream=n,n.getVideoTracks().forEach(e=>e.addEventListener(`ended`,this.handleTrackEnded,{once:!0}));let r=document.createElement(`video`);r.autoplay=!0,r.muted=!0,r.playsInline=!0,r.srcObject=n,this.video=r,this.options.onStream(n),r.play().catch(()=>void 0),this.options.onAcquired?.()}async switchDevice(e){let t=e?.trim()||void 0,n=this.stream?.getVideoTracks()[0]?.getSettings?.().deviceId?.trim()||this.options.getDeviceId(),r=this.stream!==null||this.setupController!==null;if(this.options.setDeviceId(t),r){this.release();try{await this.setEnabled(!0)}catch(e){if(!this.options.isClosed()&&n!==t){this.options.setDeviceId(n);try{await this.setEnabled(!0)}catch{}}throw e}}}hasLiveTrack(){return this.stream?.getVideoTracks().some(e=>e.readyState===`live`)===!0}hasUsableTrack(){return this.stream?.getVideoTracks().some(e=>e.readyState===`live`&&e.enabled&&!e.muted)===!0}release(){this.setupController?.abort(),this.setupController=null,this.options.onReleased?.(),this.stream?.getVideoTracks().forEach(e=>{e.removeEventListener(`ended`,this.handleTrackEnded),e.stop()}),this.stream=null,this.video&&=(this.video.srcObject=null,null),this.options.onStream(null)}}})))()}function Re(e){let t;try{t=new URL(e.websocketUrl)}catch{throw Error(`Invalid Google Live WebSocket URL`)}if(t.protocol!==`wss:`)throw Error(`Google Live WebSocket URL must use wss://`);if(t.hostname.toLowerCase()!==Be)throw Error(`Untrusted Google Live WebSocket host`);if(t.username||t.password)throw Error(`Google Live WebSocket URL must not include credentials`);if(!Ve.test(t.pathname))throw Error(`Untrusted Google Live WebSocket path`);return t.search=``,t.searchParams.set(`access_token`,e.clientSecret),t.toString()}function ze(e){let t;for(let n of e)try{n()}catch(e){t??=e instanceof Error?e:Error(`Realtime Talk cleanup failed`,{cause:e})}if(t)throw t}var Be,Ve,W,He;function Ue(){return(Ue=e((()=>{Be=`generativelanguage.googleapis.com`,Ve=/^\/ws\/google\.ai\.generativelanguage\.v[0-9a-z]+\.GenerativeService\.BidiGenerateContent(?:Constrained)?$/,W=3e4,He=class{constructor(){this.state=`idle`,this.socket=null,this.waiter=null,this.error=null}get isActive(){return this.state===`active`}begin(e){return this.state=`connecting`,this.socket=e,this.error=null,new Promise((e,t)=>{this.waiter={resolve:e,reject:t}})}markReady(e){return this.state!==`connecting`||this.socket!==e?!1:(this.state=`ready`,this.takeWaiter()?.resolve(`ready`),!0)}finishStart(e){if(this.error)throw this.error;return this.state===`cancelled`?`cancelled`:e}activate(){if(this.state===`active`)return!1;if(this.error)throw this.error;if(this.state===`cancelled`||this.state===`idle`)return!1;if(this.state!==`ready`)throw Error(`Google Live transport activated before setup completed`);return this.state=`active`,!0}failStartup(e,t){return this.socket!==e||this.state!==`connecting`&&this.state!==`ready`?!1:(this.state=`failed`,this.error=t,this.takeWaiter()?.reject(t),!0)}cancel(){this.state!==`cancelled`&&this.state!==`failed`&&(this.state=`cancelled`,this.takeWaiter()?.resolve(`cancelled`))}takeWaiter(){let e=this.waiter;return this.waiter=null,e}}})))()}var G;function K(){return(K=e((()=>{G=`describe_view`})))()}var We,Ge,Ke;function qe(){return(qe=e((()=>{K(),d(),z(),We=1024,Ge=1024,Ke=class{constructor(e){this.options=e,this.pendingCalls=new Map,this.seenCallIds=new Set,this.abortControllers=new Map}release(){let e=[...this.abortControllers.values()];this.abortControllers.clear(),this.pendingCalls.clear(),this.seenCallIds.clear();for(let t of e)t.abort()}hasPendingConsult(){for(let e of this.pendingCalls.values())if(!e.cancelled&&e.name===`openclaw_agent_consult`)return!0;return!1}async handleCall(e){if(this.options.isClosed())return;let t=e.name?.trim(),n=e.id?.trim();if(t&&n&&!this.seenCallIds.has(n)){if(this.seenCallIds.size>=Ge){this.options.failConnection(`Google Live tool-call session limit exceeded`);return}if(this.pendingCalls.size>=We){this.options.failConnection(`Google Live pending tool-call limit exceeded`);return}if(this.seenCallIds.add(n),this.pendingCalls.set(n,{name:t,cancelled:!1}),!this.isSupportedTool(t)){let e=`Tool "${t}" is not available in browser Talk`;if(!this.submitResult(n,{error:e}))return;this.options.emitTalkEvent({type:`tool.error`,callId:n,final:!0,payload:{name:t,message:e}});return}if(this.options.emitTalkEvent({type:`tool.call`,callId:n,payload:{name:t,args:e.args??{}}}),t===`describe_view`){this.submitDescribeView(n);return}await this.runAgentTool(t,n,e.args)}}cancel(e){for(let t of e??[]){let e=t.trim(),n=this.pendingCalls.get(e);if(!e||!n||n.cancelled)continue;n.cancelled=!0;let r=this.abortControllers.get(e);r?r.abort():this.pendingCalls.delete(e)}}isSupportedTool(e){return e===`openclaw_agent_control`||e===`describe_view`||e===`openclaw_agent_consult`}async runAgentTool(e,t,n){let r=new AbortController;this.abortControllers.set(t,r);try{let i={ctx:this.createActiveContext(),callId:t,args:n??{},signal:r.signal,emitTalkEvent:this.options.emitTalkEvent,submit:(e,t)=>{this.submitResult(e,t)}};e===`openclaw_agent_control`?await F(i):await I({...i,submitAbortResult:!1})}finally{this.finishExecution(t,r)}}submitDescribeView(e){let t=this.options.isDescribeViewActive();this.submitResult(e,t?{ok:!0,cameraStreamActive:!0}:{ok:!1,error:`camera is off`})&&this.options.emitTalkEvent({type:t?`tool.result`:`tool.error`,callId:e,final:!0,payload:{name:G,cameraStreamActive:t}})}createActiveContext(){let{ctx:e}=this.options;return{...e,callbacks:{onStatus:(t,n)=>{this.options.isClosed()||e.callbacks.onStatus?.(t,n)}}}}submitResult(e,t){let n=this.pendingCalls.get(e);if(!n||n.cancelled)return!1;try{this.options.sendResult(e,n.name,t)}catch(e){return this.options.failConnection(c(e)),!1}return this.pendingCalls.delete(e),!0}finishExecution(e,t){this.abortControllers.get(e)===t&&this.abortControllers.delete(e);let n=this.pendingCalls.get(e);n?.cancelled&&(this.pendingCalls.delete(e),n.name===`openclaw_agent_consult`&&!this.options.isClosed()&&!this.hasPendingConsult()&&this.options.ctx.callbacks.onStatus?.(`listening`))}}})))()}async function Je(e,t,n){if(!e?.srcObject)throw Error(`Camera preview is unavailable`);if(e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA&&await Ye(e),e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA||!e.videoWidth||!e.videoHeight)throw Error(`Camera frame has no image data`);let r=Math.min(1,1280/e.videoWidth,720/e.videoHeight),i=document.createElement(`canvas`),a=i.getContext(`2d`);if(!a)throw Error(`Camera frame capture is unavailable`);let o=.8;for(let s=0;s<Xe;s+=1){i.width=Math.max(1,Math.round(e.videoWidth*r)),i.height=Math.max(1,Math.round(e.videoHeight*r)),a.drawImage(e,0,0,i.width,i.height);let s=i.toDataURL(`image/jpeg`,o),c={data:s.slice(s.indexOf(`,`)+1),mimeType:`image/jpeg`},l=new TextEncoder().encode(JSON.stringify(n(c))).length;if(l<=t)return c;let u=Math.min(.75,Math.sqrt(t/l)*.9);r*=u,o=Math.max(.4,o-.1)}throw Error(`Camera frame is too large for the Realtime connection`)}function Ye(e){return new Promise((t,n)=>{let r,i=i=>{r!==void 0&&(globalThis.clearTimeout(r),r=void 0,e.removeEventListener(`loadeddata`,a),i?n(i):t())},a=()=>i();r=globalThis.setTimeout(()=>i(Error(`Camera preview did not become ready`)),5e3),e.addEventListener(`loadeddata`,a),e.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA&&i()})}var Xe;function q(){return(q=e((()=>{Xe=8})))()}function Ze(e){return{realtimeInput:{video:e}}}function Qe(e){return e.startsWith(`models/`)?e.slice(7):e}function J(e){if(!e)return!0;let t=Qe(e);return t.startsWith(`gemini-3.1-`)&&t.includes(`-live`)}function $e(e){if(!e)return!1;let t=Qe(e);return t.startsWith(`gemini-3.8-live`)&&t.includes(`extended-thinking`)}function et(e){return!J(e)&&!$e(e)}function tt(e,t){return!$e(e)||t===`IDLE`}async function nt(e){let t=e;return typeof t==`string`?t:(typeof Blob<`u`&&t instanceof Blob&&(t=await t.arrayBuffer()),rt(t)?new TextDecoder().decode(new Uint8Array(t)):ArrayBuffer.isView(t)?new TextDecoder().decode(new Uint8Array(t.buffer,t.byteOffset,t.byteLength)):String(t))}function rt(e){return e instanceof ArrayBuffer||Object.prototype.toString.call(e)===`[object ArrayBuffer]`}var Y,it,at,ot,st;function ct(){return(ct=e((()=>{d(),m(),U(),Ue(),qe(),pe(),z(),q(),Y=1e3,it=524288,at=262144,ot=new TextEncoder,st=class{constructor(e,t){this.session=e,this.ctx=t,this.ws=null,this.setupTimeout=null,this.input=this.ctx.input,this.inputContext=null,this.outputContext=null,this.inputMeter=null,this.inputPump=new he,this.closed=!1,this.interruptedTurn=!1,this.lifecycle=new He,this.cameraPublished=!1,this.videoFramesActive=!1,this.hasSentVideoFrame=!1,this.videoFrameTimer=null,this.outputQueue=new ue,this.pendingTranscripts={user:{text:``,byteCount:0},assistant:{text:``,byteCount:0}},this.emitTalkEvent=A(t,e),this.toolOwner=new Ke({ctx:t,emitTalkEvent:this.emitTalkEvent,isClosed:()=>this.closed,failConnection:e=>{let t=this.ws;t&&this.failConnection(t,e)},isDescribeViewActive:()=>this.videoFramesActive&&this.hasSentVideoFrame&&this.camera.hasUsableTrack(),sendResult:(e,t,n)=>this.sendToolResult(e,t,n)}),this.camera=new H({acquire:(e,t)=>me(e,{signal:t}),getDeviceId:()=>this.ctx.videoDeviceId,setDeviceId:e=>this.ctx.videoDeviceId=e,isClosed:()=>this.closed,onStream:e=>{if(e){if(!this.lifecycle.isActive)return;this.cameraPublished=!0,this.ctx.callbacks.onVideoStream?.(e)}else this.cameraPublished&&(this.cameraPublished=!1,this.ctx.callbacks.onVideoStream?.(null))},onAcquired:()=>{this.lifecycle.isActive&&this.startVideoFrames()},onReleased:()=>this.stopVideoFrames()})}async start(){if(typeof WebSocket>`u`)throw Error(`Realtime Talk requires browser WebSocket and microphone access`);if(this.session.protocol!==`google-live-bidi`)throw Error(`Unsupported realtime WebSocket protocol: ${this.session.protocol}`);let e=Re(this.session);this.closed=!1,this.cameraPublished=!1,this.input.adopt(e=>{let t=this.ws;t&&this.failConnection(t,e)}),this.inputContext=new AudioContext({sampleRate:this.session.audio.inputSampleRateHz}),this.outputContext=new AudioContext({sampleRate:this.session.audio.outputSampleRateHz});let t=new WebSocket(e);this.ws=t,t.binaryType=`arraybuffer`;let n=this.lifecycle.begin(t);return this.setupTimeout=globalThis.setTimeout(()=>{this.closed||this.ws!==t||(this.setupTimeout=null,this.failConnection(t,`Realtime connection timed out after ${W}ms`))},W),t.addEventListener(`open`,()=>{this.closed||this.ws!==t||this.send(this.session.initialMessage??{setup:{}})}),t.addEventListener(`message`,e=>{this.handleMessage(t,e.data)}),t.addEventListener(`close`,()=>{this.failConnection(t,`Realtime connection closed`)}),t.addEventListener(`error`,()=>{this.failConnection(t,`Realtime connection failed`)}),this.lifecycle.finishStart(await n)}activate(){if(!this.closed&&this.lifecycle.activate())try{if(this.ctx.callbacks.onStatus?.(`listening`),this.assertActivationCurrent(),this.emitTalkEvent({type:`session.ready`}),this.assertActivationCurrent(),this.ctx.callbacks.onInputLevel&&this.input.stream&&this.inputContext){let e=new p(this.ctx.callbacks.onInputLevel);this.inputMeter=e,e.start(this.input.stream,this.inputContext),this.assertActivationCurrent()}this.startMicrophonePump(),this.camera.stream&&!this.cameraPublished&&(this.cameraPublished=!0,this.ctx.callbacks.onVideoStream?.(this.camera.stream)),this.assertActivationCurrent(),this.startVideoFrames()}catch(e){try{this.stop({emitClosed:!1})}catch{}throw e}}assertActivationCurrent(){if(this.closed||!this.lifecycle.isActive)throw Error(`Google Live transport activation cancelled`)}async setVideoEnabled(e){await this.camera.setEnabled(e)}async switchCamera(e){await this.camera.switchDevice(e)}stop(e){let t=!this.closed&&this.lifecycle.isActive&&e?.emitClosed!==!1;this.closed=!0,this.lifecycle.cancel(),ze([()=>{t&&this.emitTalkEvent({type:`session.closed`,final:!0})},()=>this.releaseResources()])}releaseResources(){this.clearSetupTimeout(),this.interruptedTurn=!1,this.pendingTranscripts.user={text:``,byteCount:0},this.pendingTranscripts.assistant={text:``,byteCount:0};let e=this.inputMeter;this.inputMeter=null;let t=this.inputContext;this.inputContext=null;let n=this.outputContext;this.outputContext=null;let r=this.ws;this.ws=null,ze([()=>this.input.stop(),()=>this.toolOwner.release(),()=>this.inputPump.stop(),()=>e?.stop(),()=>this.camera.release(),()=>this.stopOutput(),()=>{t?.close()},()=>{n?.close()},()=>r?.close()])}clearSetupTimeout(){this.setupTimeout!==null&&(globalThis.clearTimeout(this.setupTimeout),this.setupTimeout=null)}failConnection(e,t){if(!(this.closed||this.ws!==e)){if(this.lifecycle.failStartup(e,Error(t))){try{this.stop({emitClosed:!1})}catch{}return}try{this.ctx.callbacks.onStatus?.(`error`,t)}finally{this.stop()}}}startMicrophonePump(){!this.closed&&this.input.stream&&this.inputContext&&this.inputPump.start(this.input.stream,this.inputContext,e=>{if(this.ws?.readyState!==WebSocket.OPEN)return;let t=le(e);this.send({realtimeInput:{audio:{data:u(t),mimeType:`audio/pcm;rate=${this.inputContext?.sampleRate??16e3}`}}})})}send(e){return!this.closed&&this.ws?.readyState===WebSocket.OPEN&&(this.ws.send(JSON.stringify(e)),!0)}async handleMessage(e,t){if(this.closed||this.ws!==e)return;let n;try{n=JSON.parse(await nt(t))}catch{return}if(this.closed||this.ws!==e||(n.setupComplete&&this.lifecycle.markReady(e)&&this.clearSetupTimeout(),!this.lifecycle.isActive))return;let r=n.serverContent;if(r?.interrupted&&(this.interruptedTurn=!0,this.stopOutput()),(!r?.inputTranscription||this.appendTranscript(`user`,r.inputTranscription))&&(!r?.outputTranscription||this.appendTranscript(`assistant`,r.outputTranscription))){for(let e of r?.modelTurn?.parts??[])if(e.inlineData?.data&&(this.emitTalkEvent({type:`output.audio.delta`,payload:{byteLength:ce(e.inlineData.data),mimeType:e.inlineData.mimeType}}),this.closed||(this.playPcm16(e.inlineData.data),this.closed)))return;if((!r?.generationComplete&&!r?.interrupted&&!r?.turnComplete||this.flushTranscript(`assistant`))&&(r?.interrupted?this.emitTalkEvent({type:`turn.cancelled`,final:!0,payload:{reason:`provider-interrupted`}}):r?.turnComplete&&!this.interruptedTurn&&tt(this.session.model,r.interactionStatus)&&this.emitTalkEvent({type:`turn.ended`,final:!0}),r?.turnComplete&&(this.interruptedTurn=!1),!this.closed)){for(let e of n.toolCall?.functionCalls??[])this.toolOwner.handleCall(e).catch(e=>{this.reportToolResultSubmissionError(e)});this.toolOwner.cancel(n.toolCallCancellation?.ids)}}}appendTranscript(e,t){let n=this.pendingTranscripts[e],r=e===`user`&&J(this.session.model);if(t.text){if(n.byteCount+=ot.encode(t.text).byteLength,n.byteCount>at)return this.ws&&this.failConnection(this.ws,`Google Live transcript exceeded the 256 KiB UTF-8 pending buffer limit`),!1;if(n.text+=t.text,!r&&!this.emitTranscript(e,t.text,!1))return!1}return t.finished||r?this.flushTranscript(e):!this.closed}flushTranscript(e){let t=this.pendingTranscripts[e].text.trim();return this.pendingTranscripts[e]={text:``,byteCount:0},t?this.emitTranscript(e,t,!0):!this.closed}emitTranscript(e,t,n){return this.ctx.callbacks.onTranscript?.({role:e,text:t,final:n}),!this.closed&&(this.emitTalkEvent({type:e===`user`?n?`transcript.done`:`transcript.delta`:n?`output.text.done`:`output.text.delta`,final:n,payload:e===`user`?{role:e,text:t}:{text:t}}),!this.closed&&e===`user`&&n&&this.toolOwner.hasPendingConsult()&&x(t)&&P({ctx:this.ctx,text:t,emitTalkEvent:this.emitTalkEvent,onControlResult:e=>this.stopOutputForSuppressedControl(e),speakControlResult:e=>this.sendControlSpeechMessage(e),suppressSpeechForModes:[`cancel`]}),!this.closed)}playPcm16(e){this.closed||this.outputQueue.play(e,this.outputContext,this.session.audio.outputSampleRateHz)===`overflow`&&(this.stopOutput(),this.emitTalkEvent({type:`turn.cancelled`,final:!0,payload:{reason:`playback-overflow`}}),this.ctx.callbacks.onStatus?.(`error`,`Realtime Talk playback exceeded the browser audio buffer limit`),this.stop())}stopOutput(){this.outputQueue.stop(this.outputContext)}sendToolResult(e,t,n){if(!this.send({toolResponse:{functionResponses:[{id:e,name:t,...et(this.session.model)?{scheduling:`WHEN_IDLE`}:{},response:n&&typeof n==`object`&&!Array.isArray(n)?n:{output:n}}]}}))throw Error(`Google Live socket is not open`)}reportToolResultSubmissionError(e){if(this.closed)return;let t=c(e);this.ctx.callbacks.onStatus?.(`error`,t)}startVideoFrames(){!this.camera.video||this.videoFramesActive||this.closed||(this.videoFramesActive=!0,this.scheduleVideoFrame(0))}scheduleVideoFrame(e){this.videoFramesActive&&!this.closed&&(this.videoFrameTimer=globalThis.setTimeout(()=>{this.videoFrameTimer=null,this.sendVideoFrame()},e))}async sendVideoFrame(){let e=this.camera.video;if(!this.camera.hasLiveTrack()){this.stopVideoFrames();return}if(!this.camera.hasUsableTrack()){this.scheduleVideoFrame(Y);return}try{let t=await Je(e,it,Ze);if(!this.videoFramesActive||this.closed||this.camera.video!==e)return;if(!this.send(Ze(t)))throw Error(`Google Live socket is not open`);this.hasSentVideoFrame=!0}catch(t){!this.closed&&this.camera.video===e&&(this.videoFramesActive=!1,this.reportToolResultSubmissionError(t));return}this.camera.video===e&&this.scheduleVideoFrame(Y)}stopVideoFrames(){this.videoFramesActive=!1,this.hasSentVideoFrame=!1,this.videoFrameTimer!==null&&(globalThis.clearTimeout(this.videoFrameTimer),this.videoFrameTimer=null)}sendControlSpeechMessage(e){if(this.stopOutput(),!J(this.session.model)){this.send({clientContent:{turns:[{role:`user`,parts:[{text:e}]}],turnComplete:!0}});return}this.send({realtimeInput:{text:e}})}stopOutputForSuppressedControl(e){N(e)&&this.stopOutput()}}})))()}function lt(e){let n=t(e.response)?e.response:void 0,r=t(n?.status_details)?n.status_details:void 0,i=t(r?.error)?r.error:void 0,a=o(i?.code),s=o(i?.message),c=o(i?.type),l=a||s||c?{...a?{code:a}:{},...s?{message:s}:{},...c?{type:c}:{}}:void 0,u=o(r?.reason),d=o(n?.id)??o(e.responseId),f=d?{responseId:d}:{};switch(n?.status){case`completed`:return{...f,status:`completed`};case`cancelled`:return{...f,status:`cancelled`,...u?{reason:u}:{}};case`failed`:case`incomplete`:{let t=n.status,r=[u,s??a??c].filter(Boolean).join(`: `);return{...f,status:t,...u?{reason:u}:{},...l?{error:l}:{},message:`${e.providerLabel} response ${t}${r?`: ${r}`:``}`}}default:{let t=o(n?.status),r=t?`invalid status ${t}`:`missing terminal status`;return{...f,status:`failed`,reason:`invalid_response_status`,error:{type:`invalid_response_status`,message:r},message:`${e.providerLabel} response failed: ${r}`}}}}function ut(){return(ut=e((()=>{})))()}function*dt(e){let n=e.response;if(t(n)&&n.status===`completed`&&Array.isArray(n.output))for(let e of n.output){if(!t(e)||e.type!==`function_call`||e.status!==void 0&&e.status!==`completed`)continue;let n=typeof e.id==`string`&&e.id.trim()||void 0,r=typeof e.call_id==`string`?e.call_id.trim():``,i=typeof e.name==`string`?e.name.trim():``,a=typeof e.arguments==`string`?e.arguments:``;r&&i&&a.trim()&&(yield{itemId:n,callId:r,name:i,args:a})}}function ft(e){switch(e.type){case`input_audio_buffer.committed`:return e.item_id?{type:`created`,itemId:e.item_id,previousItemId:e.previous_item_id,role:`user`}:void 0;case`conversation.item.added`:case`conversation.item.created`:{let t=e.item;if(!t?.id)return;let n=t.type===`message`?t.role===`assistant`?`assistant`:t.role===`user`&&t.content?.some(e=>e.type===`input_audio`)?`user`:null:null;return{type:`created`,itemId:t.id,previousItemId:e.previous_item_id,role:n}}case`conversation.item.done`:case`response.output_item.done`:return e.item?.id&&e.item.type===`message`&&e.item.role===`assistant`?{type:`settled`,itemId:e.item.id}:void 0;case`conversation.item.input_audio_transcription.failed`:return e.item_id?{type:`settled`,itemId:e.item_id}:void 0;default:return}}function pt(e,t){let n=e??_t;try{return new URL(n).toString()}catch{}let r=new URL(t,window.location.href);return r.protocol===`ws:`?r.protocol=`http:`:r.protocol===`wss:`&&(r.protocol=`https:`),r.pathname=`/`,r.search=``,r.hash=``,new URL(n,r).toString()}function mt(e){let t=e?.sctp?.maxMessageSize;return typeof t==`number`&&Number.isFinite(t)&&t>0?t:gt}function ht(e){return{type:`conversation.item.create`,item:{type:`message`,role:`user`,content:[{type:`input_image`,image_url:`data:${e.mimeType};base64,${e.data}`}]}}}var X,gt,_t,vt,yt;function bt(){return(bt=e((()=>{ut(),re(),X=3e4,gt=65536,_t=`https://api.openai.com/v1/realtime/calls`,vt=class{constructor(e){this.maxSettledResponses=e,this.unkeyedSettled=!1,this.settledResponseIds=new Set}start(e){this.activeResponseId=e,this.unkeyedSettled=!1}finish(e){let t=e.type===`response.cancelled`?{status:`cancelled`,...e.response?.id?{responseId:e.response.id}:{}}:lt({providerLabel:`OpenAI realtime voice`,response:e.response});if(t.responseId&&this.settledResponseIds.has(t.responseId)||!t.responseId&&this.unkeyedSettled||t.responseId&&this.activeResponseId!==void 0&&t.responseId!==this.activeResponseId)return;let n=t.responseId!==void 0&&this.settledResponseIds.size>=this.maxSettledResponses;return t.responseId&&!n?this.settledResponseIds.add(t.responseId):t.responseId||(this.unkeyedSettled=!0),this.activeResponseId=void 0,{outcome:t,overflow:n}}reset(){this.activeResponseId=void 0,this.unkeyedSettled=!1,this.settledResponseIds.clear()}},yt=class{constructor(){this.pendingRequest=null}async readAnswer(e){let t=this.beginRequest();try{let n;try{n=await fetch(pt(e.session.offerUrl,e.gatewayUrl),{method:`POST`,body:e.offer.sdp,headers:{...e.session.offerHeaders,Authorization:`Bearer ${e.session.clientSecret}`,"Content-Type":`application/sdp`},signal:t.controller.signal})}catch(t){if(!e.isCurrent())return;throw t}if(!e.isCurrent()){n.body?.cancel().catch(()=>void 0);return}if(!n.ok)throw n.body?.cancel().catch(()=>void 0),Error(`Realtime WebRTC setup failed (${n.status})`);let r;try{let t=e.session.offerResponseMaxBytes;r=t===void 0?await n.text():await ne(n,{maxBytes:t,tooLargeMessage:`Realtime WebRTC SDP answer: text response exceeds ${t} bytes`})}catch(t){if(!e.isCurrent())return;throw t}return e.isCurrent()?r:void 0}finally{this.finishRequest(t)}}abort(){let e=this.pendingRequest;e&&(this.pendingRequest=null,globalThis.clearTimeout(e.timeout),e.controller.abort())}beginRequest(){this.abort();let e=new AbortController,t={controller:e,timeout:globalThis.setTimeout(()=>{e.abort(Error(`Realtime WebRTC offer request timed out after ${X}ms`))},X)};return this.pendingRequest=t,t}finishRequest(e){globalThis.clearTimeout(e.timeout),this.pendingRequest===e&&(this.pendingRequest=null)}}})))()}var Z,Q,xt,$,St;function Ct(){return(Ct=e((()=>{K(),d(),m(),U(),pe(),z(),q(),bt(),Z=256e3,Q=1024,xt=new TextEncoder,$=Symbol(`cancelledSetup`),St=class{constructor(e,t){this.session=e,this.ctx=t,this.peer=null,this.channel=null,this.input=this.ctx.input,this.audio=null,this.inputMeter=null,this.closed=!1,this.responseActive=!1,this.responseCreateInFlight=!1,this.responseCreatePending=!1,this.responseOutcomes=new vt(Q),this.completedToolCallIds=new Set,this.offerExchange=new yt,this.consultAbortControllers=new Set,this.controlAbortController=new AbortController,this.starting=!1,this.startupError=null;let n=A(t,e);this.emitTalkEvent=e=>{(!this.closed||e.type===`session.closed`)&&n(e)},this.camera=new H({acquire:(e,t)=>me(e,{signal:t}),getDeviceId:()=>this.ctx.videoDeviceId,setDeviceId:e=>this.ctx.videoDeviceId=e,isClosed:()=>this.closed,onStream:e=>this.ctx.callbacks.onVideoStream?.(e)})}async start(){if(typeof RTCPeerConnection>`u`)throw Error(`Realtime Talk requires browser WebRTC and microphone access`);this.closed=!1,this.starting=!0,this.startupError=null;let e=new RTCPeerConnection;this.peer=e,this.audio=document.createElement(`audio`),this.audio.autoplay=!0,this.audio.muted=!1,this.audio.setAttribute(`playsinline`,``),this.audio.style.display=`none`,document.body.append(this.audio),e.addEventListener(`track`,e=>{let t=e.streams[0];if(this.audio&&t){this.audio.srcObject=t;let n=this.audio,r=e=>{this.audio!==n||this.closed||n.play().catch(t=>{e&&this.audio===n&&!this.closed&&this.ctx.callbacks.onStatus?.(`error`,`Realtime audio playback failed: ${c(t)}`)})};r(!e.track.muted),e.track.addEventListener(`unmute`,()=>r(!0),{once:!0})}});let t=this.input.adopt(e=>this.failConnection(e));if(this.ctx.callbacks.onInputLevel&&(this.inputMeter=new p(this.ctx.callbacks.onInputLevel),this.inputMeter.start(t)),!this.isCurrentPeer(e))return this.cancelledStart();for(let n of t.getAudioTracks())e.addTrack(n,t);let n=e.createDataChannel(`oai-events`);if(!this.isCurrentPeer(e))return n.close(),this.cancelledStart();this.channel=n,n.addEventListener(`open`,()=>{this.ctx.callbacks.onStatus?.(`listening`),this.emitTalkEvent({type:`session.ready`})}),n.addEventListener(`message`,e=>this.handleRealtimeEvent(e.data)),e.addEventListener(`connectionstatechange`,()=>{this.closed||(this.peer?.connectionState===`failed`||this.peer?.connectionState===`closed`)&&this.failConnection(`Realtime connection closed`)});let r=await this.awaitSetupStep(e,e.createOffer());if(r===$||!this.isCurrentPeer(e)||await this.awaitSetupStep(e,e.setLocalDescription(r))===$||!this.isCurrentPeer(e))return this.cancelledStart();let i=await this.offerExchange.readAnswer({session:this.session,offer:r,gatewayUrl:this.ctx.client.gatewayUrl,isCurrent:()=>this.isCurrentPeer(e)});return i===void 0||!this.isCurrentPeer(e)||await this.awaitSetupStep(e,e.setRemoteDescription({type:`answer`,sdp:i}))===$||!this.isCurrentPeer(e)?this.cancelledStart():(this.starting=!1,`ready`)}async setVideoEnabled(e){await this.camera.setEnabled(e)}async switchCamera(e){await this.camera.switchDevice(e)}isCurrentPeer(e){return!this.closed&&this.peer===e}cancelledStart(){if(this.startupError)throw this.startupError;return`cancelled`}async awaitSetupStep(e,t){try{return await t}catch(t){if(!this.isCurrentPeer(e))return $;throw t}}stop(e){let t=!this.closed&&e?.emitClosed!==!1;this.closed=!0;try{t&&this.emitTalkEvent({type:`session.closed`,final:!0})}finally{this.releaseResources()}}releaseResources(){this.starting=!1,this.controlAbortController.abort(),this.input.stop(),this.offerExchange.abort(),this.channel?.close(),this.channel=null,this.peer?.close(),this.peer=null,this.camera.release(),this.inputMeter?.stop(),this.inputMeter=null,this.audio?.remove(),this.audio=null;for(let e of this.consultAbortControllers)e.abort();this.consultAbortControllers.clear(),this.completedToolCallIds.clear(),this.responseOutcomes.reset(),this.responseActive=!1,this.responseCreateInFlight=!1,this.responseCreatePending=!1}failConnection(e){if(this.closed)return;let t=this.starting;try{t?this.startupError=Error(e):this.ctx.callbacks.onStatus?.(`error`,e)}finally{this.stop({emitClosed:!t})}}send(e){this.channel?.readyState===`open`&&this.channel.send(JSON.stringify(e))}handleRealtimeEvent(e){if(this.closed)return;let t;try{t=JSON.parse(String(e))}catch{return}let n=ft(t);if(!(n&&(this.ctx.callbacks.onTranscriptItem?.(n),this.closed)))switch(t.type){case`session.input_transcript.delta`:this.emitFramelessTranscript(`user`,t.delta,!1,{textMode:`verbatim`});return;case`session.output_transcript.delta`:this.emitFramelessTranscript(`assistant`,t.delta,!1,{textMode:`verbatim`});return;case`session.closed`:if(t.reason===`content`||t.reason===`connection_lost`){this.failConnection(`Realtime connection closed`);return}try{this.ctx.callbacks.onStatus?.(`idle`)}finally{this.stop()}return;case`input_transcript.added`:case`output_transcript.added`:this.emitFramelessTranscript(t.type===`input_transcript.added`?`user`:`assistant`,t.item?.text,!1,{itemId:t.item?.id,textMode:`verbatim`});return;case`turn.done`:{let e=t.turn?.role;if(e===`user`||e===`assistant`){if(this.emitFramelessTranscript(e,t.turn?.transcript,!0,{itemId:t.turn?.id,textMode:`snapshot`}),this.closed)return;e===`assistant`&&(this.ctx.callbacks.onStatus?.(`listening`),this.emitTalkEvent({type:`turn.ended`,final:!0,payload:{status:`completed`}}))}return}case`conversation.item.input_audio_transcription.completed`:if(typeof t.transcript==`string`){if(this.ctx.callbacks.onTranscript?.({role:`user`,text:t.transcript,final:!0,itemId:t.item_id}),this.closed)return;this.emitTalkEvent({type:`transcript.done`,final:!0,itemId:t.item_id,payload:{role:`user`,text:t.transcript}}),this.consultAbortControllers.size>0&&x(t.transcript)&&P({ctx:this.ctx,text:t.transcript,emitTalkEvent:this.emitTalkEvent,onControlResult:e=>this.interruptSuppressedControlResponse(e),speakControlResult:e=>this.sendControlSpeechMessage(e),suppressSpeechForModes:[`cancel`]})}return;case`conversation.output_transcript.delta`:case`response.output_text.delta`:case`response.audio_transcript.delta`:case`response.output_audio_transcript.delta`:this.emitAssistantTranscript(t,!1);return;case`response.output_text.done`:case`response.audio_transcript.done`:case`response.output_audio_transcript.done`:this.emitAssistantTranscript(t,!0);break;case`response.function_call_arguments.delta`:case`response.function_call_arguments.done`:break;case`input_audio_buffer.speech_started`:this.ctx.callbacks.onStatus?.(`listening`,`Speech detected`),this.emitTalkEvent({type:`turn.started`,payload:{source:t.type}});return;case`input_audio_buffer.speech_stopped`:this.ctx.callbacks.onStatus?.(`thinking`,`Processing speech`),this.emitTalkEvent({type:`input.audio.committed`,final:!0});return;case`response.created`:this.responseActive=!0,this.responseCreateInFlight=!1,this.responseOutcomes.start(t.response?.id),this.ctx.callbacks.onStatus?.(`thinking`,`Generating response`);return;case`response.cancelled`:case`response.done`:{let e=this.responseOutcomes.finish(t);if(!e)return;let{outcome:n}=e;try{if(n.status===`completed`&&(this.handleCompletedResponse(t),this.closed))return;n.status===`failed`||n.status===`incomplete`?(this.ctx.callbacks.onStatus?.(`error`,n.message),this.emitTalkEvent({type:`session.error`,final:!0,payload:n})):this.ctx.callbacks.onStatus?.(`listening`,n.status===`cancelled`?`Response cancelled`:void 0),this.emitTalkEvent({type:n.status===`cancelled`?`turn.cancelled`:`turn.ended`,final:!0,payload:n})}finally{e.overflow&&this.failConnection(`Realtime response session limit exceeded`),this.responseActive=!1,this.responseCreateInFlight=!1,this.flushPendingResponseCreate()}return}case`error`:case`conversation.item.input_audio_transcription.failed`:t.type===`error`&&(this.responseCreateInFlight=!1),this.ctx.callbacks.onStatus?.(`error`,this.extractErrorDetail(t.error)),this.emitTalkEvent({type:`session.error`,final:!0,itemId:t.item_id,payload:{message:this.extractErrorDetail(t.error)}})}}emitAssistantTranscript(e,t){let n=t?e.transcript??e.text:e.delta;typeof n==`string`&&(this.ctx.callbacks.onTranscript?.({role:`assistant`,text:n,final:t,itemId:e.item_id}),!this.closed&&this.emitTalkEvent({type:t?`output.text.done`:`output.text.delta`,final:t,itemId:e.item_id,payload:{text:n}}))}emitFramelessTranscript(e,t,n,{itemId:r,textMode:i}={}){if(!t||(this.ctx.callbacks.onTranscript?.({role:e,text:t,final:n,...i?{textMode:i}:{}}),this.closed))return;let a=e===`user`?n?`transcript.done`:`transcript.delta`:n?`output.text.done`:`output.text.delta`;this.emitTalkEvent({type:a,final:n,itemId:r,payload:{role:e,text:t}})}extractErrorDetail(e){let n=t(e)?e:{},r=typeof n.message==`string`?n.message.trim():``,i=typeof n.code==`string`?n.code.trim():``,a=typeof n.type==`string`?n.type.trim():``;return r||i||a||`Realtime provider error`}handleCompletedResponse(e){for(let t of dt(e)){let{itemId:e,callId:n,name:r,args:i}=t;if((r===`openclaw_agent_control`||r===`describe_view`||r===`openclaw_agent_consult`)&&!this.completedToolCallIds.has(n)){if(this.completedToolCallIds.size>=Q){this.failConnection(`Realtime tool-call session limit exceeded`);return}if(this.completedToolCallIds.add(n),xt.encode(i).byteLength>Z){let t=`Realtime tool arguments exceed the 256000-byte UTF-8 limit`;this.submitToolResult(n,{error:t}),this.emitTalkEvent({type:`tool.error`,callId:n,itemId:e,final:!0,payload:{name:r,message:t}});continue}this.handleToolCall(t).catch(e=>{this.reportToolResultSubmissionError(e)})}}}async handleToolCall(e){let{itemId:t,callId:n,name:r,args:i}=e;if(r===`openclaw_agent_control`){await F({ctx:this.ctx,callId:n,args:i,signal:this.controlAbortController.signal,emitTalkEvent:this.emitTalkEvent,submit:(e,t)=>this.submitToolResult(e,t)});return}if(r===`describe_view`){await this.handleDescribeViewToolCall(n,t);return}if(r!==`openclaw_agent_consult`)return;this.emitTalkEvent({type:`tool.call`,callId:n,itemId:t,payload:{name:r,args:i}});let a=new AbortController;this.consultAbortControllers.add(a);try{await I({ctx:this.ctx,callId:n,args:i,signal:a.signal,emitTalkEvent:this.emitTalkEvent,submit:(e,t)=>this.submitToolResult(e,t)})}finally{this.consultAbortControllers.delete(a)}}async handleDescribeViewToolCall(e,t){if(this.emitTalkEvent({type:`tool.call`,callId:e,itemId:t,payload:{name:G}}),!this.camera.hasLiveTrack()){this.submitToolResult(e,{ok:!1,error:`camera is off`}),this.emitTalkEvent({type:`tool.error`,callId:e,itemId:t,final:!0,payload:{name:G,message:`camera is off`}});return}try{let n=await Je(this.camera.video,mt(this.peer),ht);this.send(ht(n)),this.submitToolResult(e,{ok:!0,frameAttached:!0}),this.emitTalkEvent({type:`tool.result`,callId:e,itemId:t,final:!0,payload:{name:G,frameAttached:!0}})}catch(n){let r=c(n);this.submitToolResult(e,{ok:!1,error:r}),this.emitTalkEvent({type:`tool.error`,callId:e,itemId:t,final:!0,payload:{name:G,message:r}})}}submitToolResult(e,t){this.closed||(this.send({type:`conversation.item.create`,item:{type:`function_call_output`,call_id:e,output:JSON.stringify(t)}}),this.requestResponseCreate())}reportToolResultSubmissionError(e){if(this.closed)return;let t=c(e);this.ctx.callbacks.onStatus?.(`error`,t)}sendControlSpeechMessage(e){this.responseActive&&this.send({type:`response.cancel`}),this.send({type:`conversation.item.create`,item:{type:`message`,role:`user`,content:[{type:`input_text`,text:e}]}}),this.requestResponseCreate()}interruptSuppressedControlResponse(e){this.responseActive&&N(e)&&this.send({type:`response.cancel`})}requestResponseCreate(){if(this.responseActive||this.responseCreateInFlight){this.responseCreatePending=!0;return}this.responseCreatePending=!1,this.responseCreateInFlight=!0,this.send({type:`response.create`})}flushPendingResponseCreate(){this.responseCreatePending&&(this.responseCreatePending=!1,this.requestResponseCreate())}}})))()}function wt(e,t){let n=fe(e);if(n===`webrtc`)return new St(e,t);if(n===`provider-websocket`)return new st(e,t);if(n===`gateway-relay`)return new Ie(e,t);let r=e.transport??`unknown`;throw Error(`Unsupported realtime Talk transport: ${r}`)}function Tt(){return(Tt=e((()=>{Le(),ct(),de(),Ct()})))()}Tt();export{wt as createRealtimeTalkTransport};