openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
4 lines • 57.1 kB
JavaScript
import{n as e}from"./rolldown-runtime-8BhlS34s.js";import{Pu as t,wi as n,xu as r,yu as i,zu as a}from"./control-ui-core-CBJ5efDh.js";import{Mt as o,Pt as s}from"./control-ui-boot-shared-CkXlyZBY.js";import{F as c,I as l,L as u}from"./control-ui-boot-chat-Ye5j4vAg.js";import{Gi as d,Kt as ee,No as te,Po as f,Ui as ne,Wt as re,_a as ie,ba as p,wa as m}from"./ui-CmSP4d14.js";import{n as ae,t as oe}from"./response-body-Cs9VotSw.js";import{_t as h,ft as g,gt as se,ht as ce,in as le,mt as ue,on as de,pt as fe,vt as pe}from"./control-ui-boot-shared-dOnP4mAA.js";var me,he;function ge(){return(ge=e((()=>{me=3e3,he=class{constructor(e){this.onNotice=e,this.pendingMs=0,this.lossReported=!1}reserve(e){return this.pendingMs+e<=me?(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 y(e){let t=te(e);return l(t,C)?t:void 0}function b(e,t){return t.some(t=>t.test(e))}function _e(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 x(e){let t=y(e.mode);if(t)return{mode:t,confidence:`high`,reason:`explicit_mode`,shouldAutoControl:!0};let n=e.text.trim().toLowerCase();return b(n,k)?{mode:`steer`,confidence:`medium`,reason:`steer_command`,shouldAutoControl:!0}:!_e(n)&&b(n,T)?{mode:`cancel`,confidence:`high`,reason:`cancel_safety`,shouldAutoControl:!0}:b(n,E)?{mode:`status`,confidence:`high`,reason:`status_query`,shouldAutoControl:!0}:b(n,D)?{mode:`followup`,confidence:`high`,reason:`followup_marker`,shouldAutoControl:!0}:b(n,O)?{mode:`steer`,confidence:`medium`,reason:`steer_command`,shouldAutoControl:!0}:{mode:`status`,confidence:`low`,reason:`safe_default`,shouldAutoControl:!1}}function S(e){return x({text:e}).shouldAutoControl}function ve(e){let t=e;if(typeof e==`string`){let n=e.trim();try{t=n?JSON.parse(n):{}}catch{t={text:n}}}let n=ie(t),r=u(n,[`text`,`message`,`request`,`query`]);if(!r)throw Error(`text required`);return{text:r,mode:y(n.mode)??x({text:r}).mode}}function ye(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 be(e=`Cancelled the active OpenClaw run.`){return{status:`cancelled`,message:e}}var C,w,T,E,D,O,k;function A(){return(A=e((()=>{c(),C=[`status`,`steer`,`cancel`,`followup`],w=`openclaw_agent_control`,T=[/^(?:(?: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/],E=[/^(?:(?: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|[.!?])/],D=[/^(after that|when you'?re done|when it'?s done|next|then|also|one more thing|follow up)(\b|[,.!?])/],O=[/^(?:(?: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/],k=[/^(?:(?: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 j(e,t){let n=0,r=0,i,a=Se(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`&&!xe(e.type)?e.turnId:(i=e.turnId??i??`turn-${++r}`,i)}}function xe(e){return e===`turn.ended`||e===`turn.cancelled`||e.startsWith(`input.audio.`)||e.startsWith(`transcript.`)||e.startsWith(`output.`)||e.startsWith(`tool.`)}function Se(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 Ce(e){let t=p(e);return t?typeof t.text==`string`?t.text:(Array.isArray(t.content)?t.content:[]).map(e=>{let t=p(e);return t?.type===`text`&&typeof t.text==`string`?t.text:``}).filter(Boolean).join(`
`).trim():``}function we(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();return 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?Error(t||`OpenClaw tool call timed out`):void 0}function Te(e){return new Promise((t,n)=>{if(e.signal?.aborted){n(new DOMException(`OpenClaw tool call aborted`,`AbortError`));return}let r=window.setTimeout(()=>{l(Error(`OpenClaw tool call timed out`))},e.timeoutMs),i=!1,a=!1,o,s=()=>{l(new DOMException(`OpenClaw tool call aborted`,`AbortError`))};e.signal?.addEventListener(`abort`,s,{once:!0});let c=()=>void 0,l=a=>{i||(i=!0,window.clearTimeout(r),o!==void 0&&window.clearTimeout(o),e.signal?.removeEventListener(`abort`,s),c(),typeof a==`string`?t(a):n(a))},u=()=>{a||(a=!0,e.client.request(`agent.wait`,{runId:e.runId,timeoutMs:e.timeoutMs}).then(e=>{if(i)return;let t=we(e);if(t){l(t);return}e?.status!==`timeout`&&(o=window.setTimeout(()=>{l(`OpenClaw finished with no text.`)},z))}).catch(e=>{l(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(Ee(e.emitTalkEvent,n),n.state===`final`){let e=Ce(n.message);if(e){l(e);return}u()}else n.state===`aborted`?l(new DOMException(n.errorMessage??`OpenClaw tool call aborted`,`AbortError`)):n.state===`error`&&l(Error(n.errorMessage??`OpenClaw tool call failed`))}})})}function Ee(e,t){if(!e||t.stream!==`tool`)return;let n=p(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 M(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 N(e){return{type:`tool.progress`,payload:{name:w,result:e},final:e&&typeof e==`object`&&`mode`in e?e.mode===`status`||e.mode===`cancel`:void 0}}function P(e){let t=p(e);return t?.ok===!0&&(t.mode===`cancel`||t.suppress===!0&&t.mode!==`steer`)}async function F(e){let t=e.text.trim();if(!t)return;let n=M(e.ctx,e.sessionId,t,e.mode);try{let t=await n;e.onControlResult?.(t),De(t,e.speakControlResult,e.suppressSpeechForModes),e.emitTalkEvent?.(N(t))}catch(t){e.emitTalkEvent?.({type:`tool.error`,payload:{message:i(t)},final:!0})}}async function I(e){if(e.signal?.aborted)return;let t,n;try{let r=ve(e.args);if(t=await M(e.ctx,e.sessionId,r.text,r.mode),e.signal?.aborted)return;n={...N(t),callId:e.callId}}catch(r){let a=i(r);if(n={type:`tool.error`,callId:e.callId,payload:{message:a},final:!0},t={error:a},e.signal?.aborted||R(r))return}await e.submit(e.callId,t),!e.signal?.aborted&&e.emitTalkEvent?.(n)}function De(e,t,n){let r=p(e);if(!t||!r)return;let 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(ye(a))}async function L(e){let{ctx:t,callId:n,submit:r}=e;t.callbacks.onStatus?.(`thinking`);let a,o=!1,s=!1,c=!1,l=async e=>{s||(s=!0,await r(n,e),c=!0)},u=async()=>{e.submitAbortResult!==!1&&await l(be())},d=()=>{o=!0,a&&t.client.request(`chat.abort`,{sessionKey:a.agentSessionKey,agentId:a.agentId,runId:a.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(a=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 Te({client:t.client,runId:a.runId,timeoutMs:12e4,emitTalkEvent:e.emitTalkEvent,signal:e.signal})})}catch(t){if(s)throw t;if(o||e.signal?.aborted||R(t)){await u();return}await l({error:i(t)})}finally{e.signal?.removeEventListener(`abort`,d),c&&!o&&!e.signal?.aborted&&t.callbacks.onStatus?.(`listening`)}}function R(e){return typeof e==`object`&&!!e&&`name`in e&&e.name===`AbortError`}var z;function B(){return(B=e((()=>{v(),A(),r(),z=500})))()}function Oe(e){try{return(JSON.stringify(e)?.length??0)*2}catch{return 262145}}var V,ke,Ae,je,Me,Ne,Pe,Fe;function Ie(){return(Ie=e((()=>{ee(),o(),t(),r(),ge(),h(),B(),V=.02,ke=.08,Ae=2,je=8e3,Me=8e3,Ne=32,Pe=262144,Fe=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 fe,this.unsubscribe=null,this.closed=!1,this.closeCompletion=Promise.resolve(),this.audioAppendAbortController=null,this.audioInputBudget=new he(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:re}).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 g(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:Me}).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,r=e.length/this.session.audio.inputSampleRateHz*1e3;if(!t||t.signal.aborted||this.pendingOutputCancellations||!this.audioInputBudget.reserve(r))return;let i=se(e);this.ctx.client.request(`talk.session.appendAudio`,{sessionId:this.session.relaySessionId,audioBase64:n(i),timestamp:Math.round((this.inputContext?.currentTime??0)*1e3)},{signal:t.signal,timeoutMs:je}).catch(e=>this.failAudioAppend(e)).finally(()=>this.audioInputBudget.settle(r))})}abortPendingAudioAppends(){this.audioAppendAbortController?.abort(),this.audioAppendAbortController=null,this.audioInputBudget.reset()}failAudioAppend(e){if(!this.closed)try{this.ctx.callbacks.onStatus?.(`error`,i(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?i(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=Oe(e);if(this.pendingActivationEvents.length>=Ne||t>Pe-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`,a(`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(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.completeToolCall(e.callId,!0);return;case`toolResult`:{let t=e.talkEvent;t?.type!==`tool.progress`&&(t?.type!==`tool.result`||t.final!==!1)&&this.completeToolCall(e.callId);return}case`error`:this.lastRelayError=e.message?i(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=!0){this.outputQueue.stop(this.outputContext),this.speechFramesDuringPlayback=0,e&&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 I({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.`},!0),this.completedToolCalls.has(t))return;if(r.signal.aborted){await this.submitToolResult(t,{status:`cancelled`});return}}await L({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=!1){if(!this.completedToolCalls.has(e)){if(!this.closed&&!n&&(this.pendingOutputCancellations>0||this.outputPlaybackDelayMs()>0)){let n={callId:e,result:t};this.delayedToolResults.add(n),this.rescheduleDelayedToolResult(n);return}await this.sendToolResultNow(e,t,n)}}async sendToolResultNow(e,t,n=!1){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:{willContinue:!0}}:{}})}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).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=i(e);this.lastRelayError=t,this.ctx.callbacks.onStatus?.(`error`,t)}completeToolCall(e,t=!1){let n=e?.trim();if(n&&(this.completedToolCalls.add(n),(t||!this.submittingToolCalls.has(n))&&(this.toolAbortControllers.get(n)?.abort(),this.toolAbortControllers.delete(n),t)))for(let e of this.delayedToolResults)e.callId===n&&this.discardDelayedToolResult(e)}cancelOutput(e,t=!0){if(t&&!this.outputQueue.isPlaying||this.cancelRequestedForPlayback)return;let n=this.activeOutputTurnId;if(!n){this.ctx.callbacks.onStatus?.(`error`,a(`chat.composer.realtimeTalkMissingTurnIdentity`)),this.stop();return}this.cancelRequestedForPlayback=!0,this.pendingOutputCancellations+=1,this.pauseDelayedToolResults(),this.stopOutput(!1),this.ctx.client.request(`talk.session.cancelOutput`,{sessionId:this.session.relaySessionId,reason:e,turnId:n}).then(e=>{if(!s(e)||(e.status===void 0||e.status===`applied`)&&e.turnId!==void 0&&e.turnId!==n)throw Error(a(`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=pe(e);return t.rms>=V&&t.peak>=ke?this.speechFramesDuringPlayback+=1:this.speechFramesDuringPlayback=0,this.speechFramesDuringPlayback>=Ae}}})))()}var H;function U(){return(U=e((()=>{le(),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 de(this.options.getDeviceId(),{signal: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 Le(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()!==ze)throw Error(`Untrusted Google Live WebSocket host`);if(t.username||t.password)throw Error(`Google Live WebSocket URL must not include credentials`);if(!Be.test(t.pathname))throw Error(`Untrusted Google Live WebSocket path`);return t.search=``,t.searchParams.set(`access_token`,e.clientSecret),t.toString()}function Re(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 ze,Be,W,Ve;function He(){return(He=e((()=>{ze=`generativelanguage.googleapis.com`,Be=/^\/ws\/google\.ai\.generativelanguage\.v[0-9a-z]+\.GenerativeService\.BidiGenerateContent(?:Constrained)?$/,W=3e4,Ve=class{constructor(){this.state=`idle`,this.socket=null,this.waiter=null}get isActive(){return this.state===`active`}begin(e){return this.state=`connecting`,this.socket=e,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(typeof this.state!=`string`)throw this.state;return this.state===`cancelled`?`cancelled`:e}activate(){if(this.state===`active`)return!1;if(typeof this.state!=`string`)throw this.state;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=t,this.takeWaiter()?.reject(t),!0)}cancel(){this.state!==`cancelled`&&typeof this.state==`string`&&(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 Ue,We;function Ge(){return(Ge=e((()=>{K(),r(),B(),Ue=1024,We=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>=Ue){this.options.failConnection(`Google Live tool-call session limit exceeded`);return}if(this.seenCallIds.add(n),this.pendingCalls.set(n,{name:t,cancelled:!1}),t!==`openclaw_agent_control`&&t!==`describe_view`&&t!==`openclaw_agent_consult`){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)}}async runAgentTool(e,t,n){let r=new AbortController;this.abortControllers.set(t,r);try{let{ctx:i}=this.options,a={ctx:{...i,callbacks:{onStatus:(e,t)=>{this.options.isClosed()||i.callbacks.onStatus?.(e,t)}}},callId:t,args:n??{},signal:r.signal,emitTalkEvent:this.options.emitTalkEvent,submit:(e,t)=>{this.submitResult(e,t)}};e===`openclaw_agent_control`?await I(a):await L({...a,submitAbortResult:!1})}finally{this.abortControllers.get(t)===r&&this.abortControllers.delete(t);let e=this.pendingCalls.get(t);e?.cancelled&&(this.pendingCalls.delete(t),e.name===`openclaw_agent_consult`&&!this.options.isClosed()&&!this.hasPendingConsult()&&this.options.ctx.callbacks.onStatus?.(`listening`))}}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}})}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(i(e)),!1}return this.pendingCalls.delete(e),!0}}})))()}async function Ke(e,t,n){if(!e?.srcObject)throw Error(`Camera preview is unavailable`);if(e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA&&await qe(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<Je;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`)}async function qe(e){let t=Promise.withResolvers(),n=()=>t.resolve();try{await d(()=>(e.addEventListener(`loadeddata`,n),e.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA&&t.resolve(),t.promise),5e3,()=>{throw Error(`Camera preview did not become ready`)})}finally{e.removeEventListener(`loadeddata`,n)}}var Je;function q(){return(q=e((()=>{ne(),Je=8})))()}function Ye(e){return{realtimeInput:{video:e}}}async function Xe(e){let t=e;return typeof t==`string`?t:(typeof Blob<`u`&&t instanceof Blob&&(t=await t.arrayBuffer()),Ze(t)?new TextDecoder().decode(new Uint8Array(t)):ArrayBuffer.isView(t)?new TextDecoder().decode(new Uint8Array(t.buffer,t.byteOffset,t.byteLength)):String(t))}function Ze(e){return e instanceof ArrayBuffer||Object.prototype.toString.call(e)===`[object ArrayBuffer]`}var J,Qe,$e,et,tt;function Y(){return(Y=e((()=>{r(),h(),U(),He(),Ge(),B(),q(),J=1e3,Qe=524288,$e=262144,et=new TextEncoder,tt=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 fe,this.closed=!1,this.interruptedTurn=!1,this.lifecycle=new Ve,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}};let n=e.model?.replace(/^models\//,``)??``;this.gemini31LiveModel=!e.model||n.startsWith(`gemini-3.1-`)&&n.includes(`-live`),this.completeInputTranscripts=this.gemini31LiveModel||n.startsWith(`gemini-3.8-live`),this.extendedThinkingModel=n.startsWith(`gemini-3.8-live`)&&n.includes(`extended-thinking`),this.emitTalkEvent=j(t,e),this.toolOwner=new We({ctx:t,emitTalkEvent:this.emitTalkEvent,isClosed:()=>this.closed,failConnection:e=>this.failConnection(this.ws,e),isDescribeViewActive:()=>this.videoFramesActive&&this.hasSentVideoFrame&&this.camera.hasUsableTrack(),sendResult:(e,t,n)=>this.sendToolResult(e,t,n)}),this.camera=new H({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=Le(this.session);this.closed=!1,this.cameraPublished=!1,this.input.adopt(e=>this.failConnection(this.ws,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 g(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(),Re([()=>{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,Re([()=>this.input.stop(),()=>this.toolOwner.release(),()=>this.inputPump.stop(),()=>e?.stop(),()=>this.camera.release(),()=>this.outputQueue.stop(this.outputContext),()=>{t?.close()},()=>{n?.close()},()=>r?.close()])}clearSetupTimeout(){this.setupTimeout!==null&&(globalThis.clearTimeout(this.setupTimeout),this.setupTimeout=null)}failConnection(e,t){if(!this.closed&&e&&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=se(e);this.send({realtimeInput:{audio:{data:n(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 Xe(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.outputQueue.stop(this.outputContext)),(!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&&(!this.extendedThinkingModel||r.interactionStatus===`IDLE`)&&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`&&this.completeInputTranscripts;if(t.text){if(n.byteCount+=et.encode(t.text).byteLength,n.byteCount>$e)return 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()&&S(t)&&F({ctx:this.ctx,text:t,emitTalkEvent:this.emitTalkEvent,onControlResult:e=>{P(e)&&this.outputQueue.stop(this.outputContext)},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.outputQueue.stop(this.outputContext),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())}sendToolResult(e,t,n){if(!this.send({toolResponse:{functionResponses:[{id:e,name:t,...!this.gemini31LiveModel&&!this.extendedThinkingModel?{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=i(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(J);return}try{let t=await Ke(e,Qe,Ye);if(!this.videoFramesActive||this.closed||this.camera.video!==e)return;if(!this.send(Ye(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(J)}stopVideoFrames(){this.videoFramesActive=!1,this.hasSentVideoFrame=!1,this.videoFrameTimer!==null&&(globalThis.clearTimeout(this.videoFrameTimer),this.videoFrameTimer=null)}sendControlSpeechMessage(e){this.outputQueue.stop(this.outputContext),this.send(this.gemini31LiveModel?{realtimeInput:{text:e}}:{clientContent:{turns:[{role:`user`,parts:[{text:e}]}],turnComplete:!0}})}}})))()}function nt(e){let t=m(e.response)?e.response:void 0,n=m(t?.status_details)?t.status_details:void 0,r=m(n?.error)?n.error:void 0,i=f(r?.code),a=f(r?.message),o=f(r?.type),s=i||a||o?{...i?{code:i}:{},...a?{message:a}:{},...o?{type:o}:{}}:void 0,c=f(n?.reason),l=f(t?.id)??f(e.responseId),u=l?{responseId:l}:{};switch(t?.status){case`completed`:return{...u,status:`completed`};case`cancelled`:return{...u,status:`cancelled`,...c?{reason:c}:{}};case`failed`:case`incomplete`:{let n=t.status,r=[c,a??i??o].filter(Boolean).join(`: `);return{...u,status:n,...c?{reason:c}:{},...s?{error:s}:{},message:`${e.providerLabel} response ${n}${r?`: ${r}`:``}`}}default:{let n=f(t?.status),r=n?`invalid status ${n}`:`missing terminal status`;return{...u,status:`failed`,reason:`invalid_response_status`,error:{type:`invalid_response_status`,message:r},message:`${e.providerLabel} response failed: ${r}`}}}}function rt(){return(rt=e((()=>{})))()}function*it(e){let t=e.response;if(m(t)&&t.status===`completed`&&Array.isArray(t.output))for(let e of t.output){if(!m(e)||e.type!==`function_call`||e.status!==void 0&&e.status!==`completed`)continue;let t=typeof e.id==`string`&&e.id.trim()||void 0,n=typeof e.call_id==`string`?e.call_id.trim():``,r=typeof e.name==`string`?e.name.trim():``,i=typeof e.arguments==`string`?e.arguments:``;n&&r&&i.trim()&&(yield{itemId:t,callId:n,name:r,args:i})}}function at(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 ot(e,t){let n=e??ut;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 st(e){let t=e?.sctp?.maxMessageSize;return typeof t==`number`&&Number.isFinite(t)&&t>0?t:lt}function ct(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,lt,ut,dt,ft;function pt(){return(pt=e((()=>{rt(),oe(),X=3e4,lt=65536,ut=`https://api.openai.com/v1/realtime/calls`,dt=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}:{}}:nt({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()}},ft=class{constructor(){this.pendingRequest=null}async readAnswer(e){this.abort();let t=new AbortController,n={controller:t,timeout:globalThis.setTimeout(()=>{t.abort(Error(`Realtime WebRTC offer request timed out after ${X}ms`))},X)};this.pendingRequest=n;try{let t=await fetch(ot(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:n.controller.signal});if(!e.isCurrent()){t.body?.cancel().catch(()=>void 0);return}if(!t.ok)throw t.body?.cancel().catch(()=>void 0),Error(`Realtime WebRTC setup failed (${t.status})`);let r=e.session.offerResponseMaxBytes,i=r===void 0?await t.text():await ae(t,{maxBytes:r,tooLargeMessage:`Realtime WebRTC SDP answer: text response exceeds ${r} bytes`});return e.isCurrent()?i:void 0}catch(t){if(!e.isCurrent())return;throw t}finally{globalThis.clearTimeout(n.timeout),this.pendingRequest===n&&(this.pendingRequest=null)}}abort(){let e=this.pendingRequest;e&&(this.pendingRequest=null,globalThis.clearTimeout(e.timeout),e.controller.abort())}}})))()}var mt,Z,ht,Q,gt;function _t(){return(_t=e((()=>{K(),r(),h(),U(),B(),q(),pt(),mt=256e3,Z=1024,ht=new TextEncoder,Q=Symbol(`cancelledSetup`),gt=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.responseState=`idle`,this.responseCreatePending=!1,this.responseOutcomes=new dt(Z),this.completedToolCallIds=new Set,this.offerExchange=new ft,this.consultAbortControllers=new Set,this.controlAbortController=new AbortController,this.starting=!1,this.startupError=null;let n=j(t,e);this.emitTalkEvent=e=>{(!this.closed||e.type===`session.closed`)&&n(e)},this.camera=new H({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: ${i(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 g(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===Q||!this.isCurrentPeer(e)||await this.awaitSetupStep(e,e.setLocalDescription(r))===Q||!this.isCurrentPeer(e))return this.cancelledStart();let a=await this.offerExchange.readAnswer({session:this.session,offer:r,gatewayUrl:this.ctx.client.gatewayUrl,isCurrent:()=>this.isCurrentPeer(e)});return a===void 0||!this.isCurrentPeer(e)||await this.awaitSetupStep(e,e.setRemoteDescription({type:`answer`,sdp:a}))===Q||!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 Q;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.responseState=`idle`,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=at(t);if(!(n&&(this.ctx.callbacks.onTranscriptItem?.(n),this.closed)))switch(t.type){case`session.input_transcript.delta`:this.emitTranscript(`user`,t.delta,!1,void 0,`verbatim`);return;case`session.output_transcript.delta`:this.emitTranscript(`assistant`,t.delta,!1,void 0,`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.emitTranscript(t.type===`input_transcript.added`?`user`:`assistant`,t.item?.text,!1,t.item?.id,`verbatim`);return;case`turn.done`:{let e=t.turn?.role;if(e===`user`||e===`assistant`){if(this.emitTranscript(e,t.turn?.transcript,!0,t.turn?.id,`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.emitTranscript(`user`,t.transcript,!0,t.item_id))return;this.consultAbortControllers.size>0&&S(t.transcript)&&F({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.emitTranscript(`assistant`,t.delta,!1,t.item_id);return;case`response.output_text.done`:case`response.audio_transcript.done`:case`response.output_audio_transcript.done`:this.emitTranscript(`assistant`,t.transcript??t.text,!0,t.item_id);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.responseState=`active`,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.responseState=`idle`,this.responseCreatePending&&(this.responseCreatePending=!1,this.requestResponseCreate())}return}case`error`:case`conversation.item.input_audio_transcription.failed`:t.type===`error`&&this.responseState===`requested`&&(this.responseState=`idle`),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)}})}}emitTranscript(e,t,n,r,i){let a;if(i){if(!t)return!1;a={role:e,text:t,final:n,textMode:i}}else{if(typeof t!=`string`)return!1;a={role:e,text:t,final:n,itemId:r}}let o=a.text;if(this.ctx.callbacks.onTranscript?.(a),this.closed)return!1;let s=e===`user`?n?`transcript.done`:`transcript.delta`:n?`output.text.done`:`output.text.delta`;return this.emitTalkEvent({type:s,final:n,itemId:r,payload:e===`user`||i?{role:e,text:o}:{text:o}}),!0}extractErrorDetail(e){let t=m(e)?e:{},n=typeof t.message==`string`?t.message.trim():``,r=typeof t.code==`string`?t.code.trim():``,i=typeof t.type==`string`?t.type.trim():``;return n||r||i||`Realtime provider error`}handleCompletedResponse(e){for(let t of it(e)){let{itemId:e,callId:n,name:r,args:a}=t;if((r===`openclaw_agent_control`||r===`describe_view`||r===`openclaw_agent_consult`)&&!this.completedToolCallIds.has(n)){if(this.completedToolCallIds.size>=Z){this.failConnection(`Realtime tool-call session limit exceeded`);return}if(this.completedToolCallIds.add(n),ht.encode(a).byteLength>mt){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=>{if(!this.closed){let t=i(e);this.ctx.callbacks.onStatus?.(`error`,t)}})}}}async handleToolCall(e){let{itemId:t,callId:n,name:r,args:i}=e;if(r===`openclaw_agent_control`){await I({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 L({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){this.emitTalkEvent({type:`tool.call`,callId:e,itemId:t,payload:{name:G}});let n=n=>{this.submitToolResult(e,{ok:!1,error:n}),this.emitTalkEvent({type:`tool.error`,callId:e,itemId:t,final:!0,payload:{name:G,message:n}})};if(!this.camera.hasLiveTrack()){n(`camera is off`);return}try{let n=await Ke(this.camera.video,st(this.peer),ct);this.send(ct(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(e){n(i(e))}}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())}sendControlSpeechMessage(e){this.responseState===`active`&&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.responseState===`active`&&P(e)&&this.send({type:`response.cancel`})}requestResponseCreate(){if(this.responseState!==`idle`){this.responseCreatePending=!0;return}this.responseCreatePending=!1,this.responseState=`requested`,this.send({type:`response.create`})}}})))()}function vt(e,t){if(e.transport===`webrtc`)return new gt(e,t);if(e.transport===`provider-websocket`)return new tt(e,t);if(e.transport===`gateway-relay`)return new Fe(e,t);let n=e.transport??`unknown`;throw Error(`Unsupported realtime Talk transport: ${n}`)}function $(){return($=e((()=>{Ie(),Y(),_t()})))()}$();export{vt as createRealtimeTalkTransport};