@runtypelabs/persona 4.28.2 → 4.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/dist/animations/glyph-cycle.d.cts +1 -1
  2. package/dist/animations/glyph-cycle.d.ts +1 -1
  3. package/dist/animations/wipe.d.cts +1 -1
  4. package/dist/animations/wipe.d.ts +1 -1
  5. package/dist/approval-ui.d.cts +1 -1
  6. package/dist/approval-ui.d.ts +1 -1
  7. package/dist/artifacts-ui.d.cts +2 -2
  8. package/dist/artifacts-ui.d.ts +2 -2
  9. package/dist/chunk-BkW8s3fj.js +2 -0
  10. package/dist/chunk-CIVsNcrk.js +1 -0
  11. package/dist/chunk-CKdlNyzM.js +9 -0
  12. package/dist/{chunk-DrYAfpvk.js → chunk-DjOvgFsn.js} +1 -1
  13. package/dist/chunk-lA5CJCgK.js +1 -0
  14. package/dist/client-history.js +1 -1
  15. package/dist/codegen.cjs +1 -1
  16. package/dist/codegen.js +1 -1
  17. package/dist/{composer-input-C39npJaz.d.cts → composer-input-D3sB8_P_.d.cts} +1 -1
  18. package/dist/{composer-input-C39npJaz.d.ts → composer-input-D3sB8_P_.d.ts} +1 -1
  19. package/dist/{context-mention-manager-DLCB1l9E.d.cts → context-mention-manager-D2qxE5op.d.cts} +1 -1
  20. package/dist/{context-mention-manager-DLCB1l9E.d.ts → context-mention-manager-D2qxE5op.d.ts} +1 -1
  21. package/dist/context-mentions-inline.d.cts +2 -2
  22. package/dist/context-mentions-inline.d.ts +2 -2
  23. package/dist/context-mentions.d.cts +3 -3
  24. package/dist/context-mentions.d.ts +3 -3
  25. package/dist/{defaults-DiAgWHXy.d.cts → defaults-Dsw66XqE.d.cts} +1 -1
  26. package/dist/{defaults-DiAgWHXy.d.ts → defaults-Dsw66XqE.d.ts} +1 -1
  27. package/dist/event-stream-view.d.cts +1 -1
  28. package/dist/event-stream-view.d.ts +1 -1
  29. package/dist/{fallback-speech-engine-C5_PUZjH.d.cts → fallback-speech-engine-DJpJcWAk.d.cts} +1 -1
  30. package/dist/{fallback-speech-engine-C5_PUZjH.d.ts → fallback-speech-engine-DJpJcWAk.d.ts} +1 -1
  31. package/dist/forms-ui.d.cts +2 -2
  32. package/dist/forms-ui.d.ts +2 -2
  33. package/dist/history-view.d.cts +1 -1
  34. package/dist/history-view.d.ts +1 -1
  35. package/dist/index.cjs +45 -44
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +7 -7
  38. package/dist/index.d.ts +7 -7
  39. package/dist/index.global.js +1 -1
  40. package/dist/index.global.js.map +1 -1
  41. package/dist/index.js +34 -33
  42. package/dist/index.js.map +1 -1
  43. package/dist/{markdown-parsers-loader-BBdyIEU7.d.cts → markdown-parsers-loader-CCY7T4Up.d.cts} +1 -1
  44. package/dist/{markdown-parsers-loader-BBdyIEU7.d.ts → markdown-parsers-loader-CCY7T4Up.d.ts} +1 -1
  45. package/dist/{preview-Chjb0bmI.d.cts → preview-DKKpfTo7.d.cts} +2 -2
  46. package/dist/{preview-Chjb0bmI.d.ts → preview-DKKpfTo7.d.ts} +2 -2
  47. package/dist/{session-a_qIp4xp.d.ts → session-DleMr9dZ.d.cts} +13 -7
  48. package/dist/{session-a_qIp4xp.d.cts → session-DleMr9dZ.d.ts} +13 -7
  49. package/dist/session-reconnect.d.cts +2 -2
  50. package/dist/session-reconnect.d.ts +2 -2
  51. package/dist/smart-dom-reader.d.cts +1 -1
  52. package/dist/smart-dom-reader.d.ts +1 -1
  53. package/dist/theme-editor-preview.cjs +41 -40
  54. package/dist/theme-editor-preview.d.cts +1 -1
  55. package/dist/theme-editor-preview.d.ts +1 -1
  56. package/dist/theme-editor-preview.js +20 -20
  57. package/dist/theme-editor.d.cts +2 -2
  58. package/dist/theme-editor.d.ts +2 -2
  59. package/dist/theme-reference.d.cts +2 -2
  60. package/dist/theme-reference.d.ts +2 -2
  61. package/dist/{types-BdO1jNRm.d.cts → types-oAZ1VReS.d.cts} +166 -21
  62. package/dist/{types-BdO1jNRm.d.ts → types-oAZ1VReS.d.ts} +166 -21
  63. package/dist/voice-client-tools.cjs +1 -0
  64. package/dist/voice-client-tools.d.cts +13 -0
  65. package/dist/voice-client-tools.d.ts +13 -0
  66. package/dist/voice-client-tools.js +1 -0
  67. package/dist/voice-runtime.cjs +3 -3
  68. package/dist/voice-runtime.d.cts +7 -3
  69. package/dist/voice-runtime.d.ts +7 -3
  70. package/dist/voice-runtime.js +4 -4
  71. package/dist/voice-worklet-player.d.cts +2 -2
  72. package/dist/voice-worklet-player.d.ts +2 -2
  73. package/dist/{webmcp-runtime-entry-B6bpVWSa.d.ts → webmcp-runtime-entry-Deg0NfmB.d.cts} +26 -5
  74. package/dist/{webmcp-runtime-entry-B6bpVWSa.d.cts → webmcp-runtime-entry-Deg0NfmB.d.ts} +26 -5
  75. package/dist/webmcp-runtime.cjs +2 -1
  76. package/dist/webmcp-runtime.d.cts +1 -1
  77. package/dist/webmcp-runtime.d.ts +1 -1
  78. package/dist/webmcp-runtime.js +2 -1
  79. package/package.json +6 -1
  80. package/src/client.ts +37 -0
  81. package/src/client.voice-tools.test.ts +65 -0
  82. package/src/generated/runtype-openapi-contract.ts +38 -0
  83. package/src/index-core.ts +11 -0
  84. package/src/index-global.ts +6 -0
  85. package/src/session.test.ts +26 -0
  86. package/src/session.ts +8 -1
  87. package/src/session.voice.test.ts +43 -0
  88. package/src/types.ts +141 -20
  89. package/src/voice/runtype-voice-provider.ts +85 -3
  90. package/src/voice/session-voice-wiring.ts +26 -1
  91. package/src/voice/voice-client-tools-session.ts +116 -0
  92. package/src/voice/voice-delegation.ts +9 -0
  93. package/src/voice/voice.test.ts +360 -0
  94. package/src/voice-client-tools-bundle.test.ts +37 -0
  95. package/src/voice-client-tools-loader.ts +24 -0
  96. package/src/voice-client-tools.ts +9 -0
  97. package/src/webmcp-bridge.test.ts +152 -1
  98. package/src/webmcp-bridge.ts +5 -6
  99. package/src/webmcp-polyfill.integration.test.ts +5 -1
  100. package/src/webmcp-runtime-entry.ts +151 -26
  101. package/dist/chunk-CztSjKHK.js +0 -9
  102. package/dist/chunk-HUOUif-P.js +0 -1
  103. package/dist/chunk-UlcxdHef.js +0 -1
@@ -1,9 +1,9 @@
1
- var e=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(e){throw n=[e],e}},t,n=e((()=>{t=class{#e=null;#t=0;#n=[];#r=[];#i=[];#a=!1;#o=!1;#s=0;#c=!1;#l=!1;#u;#d=[];#f=0;#p=!1;#m;#h;#g;#_=null;constructor(e=24e3,t={}){this.#h=e;let n=Math.max(0,t.prebufferMs??0);this.#g=Math.round(e*n/1e3),this.#u=this.#g>0}#v(){if(!this.#e){let e=typeof window<`u`?window:void 0;if(!e)throw Error(`AudioPlaybackManager requires a browser environment`);let t=e.AudioContext||e.webkitAudioContext;this.#e=new t({sampleRate:this.#h})}let e=this.#e;return e.state===`suspended`&&!this.#l&&e.resume(),e}enqueue(e){if(e.length===0)return;let t=e;if(this.#_){let n=new Uint8Array(this.#_.length+e.length);n.set(this.#_),n.set(e,this.#_.length),t=n,this.#_=null}if(t.length%2!=0&&(this.#_=new Uint8Array([t[t.length-1]]),t=t.subarray(0,t.length-1)),t.length===0)return;let n=this.#S(t);n.length!==0&&(this.#u?(this.#d.push(n),this.#f+=n.length,clearTimeout(this.#m),this.#f>=this.#g?this.#y():this.#p&&(this.#m=setTimeout(()=>this.#y(),this.#g/this.#h*1e3))):this.#b(n))}markStreamEnd(){this.#d.length>0&&this.#y(),this.#o=!0,this.#x()}flush(){for(let e of this.#n){e.onended=null;try{e.stop(),e.disconnect()}catch{}}this.#n=[],this.#s=0,this.#t=0,this.#a=!1,this.#o=!1,this.#r=[],this.#i=[],this.#_=null,this.#d=[],this.#f=0,this.#u=this.#g>0,this.#c=!1,clearTimeout(this.#m)}setContinuousMode(e){this.#p=e}isPlaying(){return this.#a}onFinished(e){this.#r.push(e)}onStarted(e){this.#i.push(e)}pause(){this.#l=!0,this.#e&&this.#e.state===`running`&&this.#e.suspend()}resume(){this.#l=!1,this.#e&&this.#e.state===`suspended`&&this.#e.resume()}async destroy(){this.flush(),this.#e&&=(await this.#e.close(),null)}#y(){this.#u=!1;let e=this.#d;this.#d=[],this.#f=0;for(let t of e)this.#b(t)}#b(e){if(e.length===0)return;let t=this.#v(),n=t.createBuffer(1,e.length,this.#h);n.getChannelData(0).set(e);let r=t.createBufferSource();r.buffer=n,r.connect(t.destination);let i=t.currentTime;if(this.#t===0?this.#t=i:this.#t<i&&(this.#t=i,this.#g>0&&(this.#u=!0)),r.start(this.#t),this.#t+=n.duration,this.#n.push(r),this.#s++,this.#a=!0,!this.#c){this.#c=!0;let e=this.#i.slice();this.#i=[];for(let t of e)t()}r.onended=()=>{let e=this.#n.indexOf(r);e!==-1&&(this.#n.splice(e,1),this.#s--,this.#x())}}#x(){if(this.#o&&this.#s<=0&&this.#d.length===0){this.#a=!1,this.#o=!1;let e=this.#r.slice();this.#r=[];for(let t of e)t()}}#S(e){let t=Math.floor(e.length/2),n=new Float32Array(t),r=new DataView(e.buffer,e.byteOffset,e.byteLength);for(let e=0;e<t;e++){let t=r.getInt16(e*2,!0);n[e]=t/32768}return n}}})),r=`4.28.2`,i,a=e((()=>{i=r}));function o(e,t){let n=t.slice(0,P).trim(),r=N-(n?n.length+2:0)-20,i=[];for(let t of e.slice(-12).reverse()){let e=t.content.replace(/\s+/g,` `).trim();if(!e)continue;e.length>ee&&(e=`${e.slice(0,1999)}…`);let n=`${t.role===`user`?`User`:`Assistant`}: ${e}`;if(n.length+1>r)break;r-=n.length+1,i.unshift(n)}let a=i.length>0?[`Conversation so far:\n${i.join(`
1
+ var e=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(e){throw n=[e],e}},t,n=e((()=>{t=class{#e=null;#t=0;#n=[];#r=[];#i=[];#a=!1;#o=!1;#s=0;#c=!1;#l=!1;#u;#d=[];#f=0;#p=!1;#m;#h;#g;#_=null;constructor(e=24e3,t={}){this.#h=e;let n=Math.max(0,t.prebufferMs??0);this.#g=Math.round(e*n/1e3),this.#u=this.#g>0}#v(){if(!this.#e){let e=typeof window<`u`?window:void 0;if(!e)throw Error(`AudioPlaybackManager requires a browser environment`);let t=e.AudioContext||e.webkitAudioContext;this.#e=new t({sampleRate:this.#h})}let e=this.#e;return e.state===`suspended`&&!this.#l&&e.resume(),e}enqueue(e){if(e.length===0)return;let t=e;if(this.#_){let n=new Uint8Array(this.#_.length+e.length);n.set(this.#_),n.set(e,this.#_.length),t=n,this.#_=null}if(t.length%2!=0&&(this.#_=new Uint8Array([t[t.length-1]]),t=t.subarray(0,t.length-1)),t.length===0)return;let n=this.#S(t);n.length!==0&&(this.#u?(this.#d.push(n),this.#f+=n.length,clearTimeout(this.#m),this.#f>=this.#g?this.#y():this.#p&&(this.#m=setTimeout(()=>this.#y(),this.#g/this.#h*1e3))):this.#b(n))}markStreamEnd(){this.#d.length>0&&this.#y(),this.#o=!0,this.#x()}flush(){for(let e of this.#n){e.onended=null;try{e.stop(),e.disconnect()}catch{}}this.#n=[],this.#s=0,this.#t=0,this.#a=!1,this.#o=!1,this.#r=[],this.#i=[],this.#_=null,this.#d=[],this.#f=0,this.#u=this.#g>0,this.#c=!1,clearTimeout(this.#m)}setContinuousMode(e){this.#p=e}isPlaying(){return this.#a}onFinished(e){this.#r.push(e)}onStarted(e){this.#i.push(e)}pause(){this.#l=!0,this.#e&&this.#e.state===`running`&&this.#e.suspend()}resume(){this.#l=!1,this.#e&&this.#e.state===`suspended`&&this.#e.resume()}async destroy(){this.flush(),this.#e&&=(await this.#e.close(),null)}#y(){this.#u=!1;let e=this.#d;this.#d=[],this.#f=0;for(let t of e)this.#b(t)}#b(e){if(e.length===0)return;let t=this.#v(),n=t.createBuffer(1,e.length,this.#h);n.getChannelData(0).set(e);let r=t.createBufferSource();r.buffer=n,r.connect(t.destination);let i=t.currentTime;if(this.#t===0?this.#t=i:this.#t<i&&(this.#t=i,this.#g>0&&(this.#u=!0)),r.start(this.#t),this.#t+=n.duration,this.#n.push(r),this.#s++,this.#a=!0,!this.#c){this.#c=!0;let e=this.#i.slice();this.#i=[];for(let t of e)t()}r.onended=()=>{let e=this.#n.indexOf(r);e!==-1&&(this.#n.splice(e,1),this.#s--,this.#x())}}#x(){if(this.#o&&this.#s<=0&&this.#d.length===0){this.#a=!1,this.#o=!1;let e=this.#r.slice();this.#r=[];for(let t of e)t()}}#S(e){let t=Math.floor(e.length/2),n=new Float32Array(t),r=new DataView(e.buffer,e.byteOffset,e.byteLength);for(let e=0;e<t;e++){let t=r.getInt16(e*2,!0);n[e]=t/32768}return n}}})),r=`4.29.0`,i,a=e((()=>{i=r}));function o(e,t){let n=t.slice(0,P).trim(),r=N-(n?n.length+2:0)-20,i=[];for(let t of e.slice(-12).reverse()){let e=t.content.replace(/\s+/g,` `).trim();if(!e)continue;e.length>ee&&(e=`${e.slice(0,1999)}…`);let n=`${t.role===`user`?`User`:`Assistant`}: ${e}`;if(n.length+1>r)break;r-=n.length+1,i.unshift(n)}let a=i.length>0?[`Conversation so far:\n${i.join(`
2
2
  `)}`]:[];return n&&a.push(n),a.join(`
3
3
 
4
- `)}function s(e){return e.byteLength>=44&&new DataView(e).getUint32(0,!1)===g?new Uint8Array(e,44):new Uint8Array(e)}function c(e){let t=e.replace(/\/+$/,``);return/^wss?:\/\//i.test(t)?t:/^https?:\/\//i.test(t)?t.replace(/^http/i,`ws`):`${typeof window<`u`&&window.location?.protocol===`https:`?`wss:`:`ws:`}//${t}`}function l(e){return c(e).replace(/^ws/i,`http`)}function u(e){return typeof e!=`number`||!Number.isFinite(e)?b:Math.min(S,Math.max(x,Math.round(e)))}var d,f,p,m,h,g,_,v,y,b,x,S,C,w,T,E,D,O,k,A,j,M,N,P,ee,F,te=e((()=>{n(),a(),d=16e3,f=24e3,p=4096,m=d*2*8,h=4,g=1380533830,_=3e4,v=1e3,y=5e3,b=3e4,x=3e4,S=6e5,C=`full-duplex-v1`,w=300,T=2e3,E=2e3,D=`runtype-browser-v1`,O=54e4,k=`You're talking to an AI assistant. Voice is processed by OpenAI.`,A=/* @__PURE__ */ new Map([[`idle_timeout`,`Voice call ended after a quiet period.`],[`max_duration`,`This voice call reached its time limit.`],[`provider_ended`,`The voice session ended.`],[`quota`,`Voice is unavailable right now.`],[`auth_expired`,`Voice session expired. Tap the mic to reconnect.`]]),j=[`provider_error`,`server_restart`],M=`Voice connection lost.`,N=8e3,P=4e3,ee=2e3,F=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p;#m;#h;#g;#_;#v;#y;#b;#x;#S;#C;#w;#T;#E;#D;#O;#k;#A;#j;#M;#N;#P;#F;#I;#L;#R;#z;#B;#V;#H;#U;#W;#G;constructor(e){this.config=e,this.type=`runtype`,this.#e=null,this.#t=null,this.#n=[],this.#r=null,this.#i=null,this.#a=null,this.#o=[],this.#s=0,this.#c=null,this.#l=!1,this.#u=!1,this.#d=0,this.#f=!1,this.#p=-1/0,this.#m=null,this.#h=!1,this.#g=!1,this.#_=0,this.#v=0,this.#b=!1,this.bridge=null,this.#x=!1,this.#S=/* @__PURE__ */ new Set,this.#C=/* @__PURE__ */ new Map,this.#w=/* @__PURE__ */ new Set,this.#E=null,this.#D=null,this.#k=!1,this.#A=!1,this.#j=!1,this.#M=null,this.#N=null,this.#P=Promise.resolve(),this.#F=/* @__PURE__ */ new Set,this.#I=/* @__PURE__ */ new Set,this.#L=null,this.#R=!1,this.#z=/* @__PURE__ */ new Set,this.#B=/* @__PURE__ */ new Set,this.#V=[],this.#H=[],this.#U=[],this.#W=[],this.#G=[]}async connect(){}setSessionBridge(e){this.bridge=e}prewarm(){if(this.#l||this.#m)return;let e=this.config?.agentId,t=this.config?.clientToken,n=this.config?.host;if(!e||!t||!n)return;let r=Date.now();if(!(r-this.#p<_)){this.#p=r;try{this.config?.prewarmMode===`attach`?this.#q(n,e,t):this.#K(n,e,t)}catch{}}}#K(e,t,n){if(typeof fetch!=`function`)return;let r=`${l(e)}/v1/client/agents/${encodeURIComponent(t)}/voice/prewarm`;fetch(r,{method:`POST`,headers:{Authorization:`Bearer ${n}`},keepalive:!0}).catch(()=>{})}#q(e,t,n){let r=new URLSearchParams,i=this.config?.attachIdleMs,a=u(i);i!==void 0&&r.set(`attachIdleMs`,String(a));let o=new WebSocket(this.#Z(e,t,r),[`runtype.bearer`,`runtype.attach`,n]);o.binaryType=`arraybuffer`;let s=()=>{},c={ws:o,state:`connecting`,ready:new Promise(e=>{s=e}),settle:s,openedAt:0,idleTimer:void 0};this.#m=c,o.onopen=()=>{this.#m===c&&(c.state=o.protocol===`runtype.attach`?`attached`:`live`,c.openedAt=Date.now(),this.#J(c,a),c.state===`attached`&&o.send(`{"type":"ping"}`),c.settle())},o.onmessage=e=>{if(this.#m!==c||typeof e.data!=`string`)return;let t;try{t=JSON.parse(e.data)}catch{return}t.type===`attached`&&typeof t.idleMs==`number`&&this.#J(c,t.idleMs-(Date.now()-c.openedAt))},o.onerror=()=>{},o.onclose=()=>{this.#m===c&&this.#Y()}}#J(e,t){clearTimeout(e.idleTimer),e.idleTimer=setTimeout(()=>{this.#m===e&&this.#Y()},Math.max(0,t))}#Y(){let e=this.#m;if(!e)return;this.#m=null,clearTimeout(e.idleTimer);let{ws:t}=e;if(t.onopen=null,t.onmessage=null,t.onerror=null,t.onclose=null,e.settle(),t.readyState===WebSocket.CONNECTING||t.readyState===WebSocket.OPEN)try{t.close(1e3,`prewarm released`)}catch{}}async#X(){let e=this.#m;if(!e)return null;if(e.state===`connecting`){let t;await Promise.race([e.ready,new Promise(e=>{t=setTimeout(e,y)})]),clearTimeout(t)}return this.#m===e?e.state===`connecting`||e.ws.readyState!==WebSocket.OPEN?(this.#Y(),null):(this.#m=null,clearTimeout(e.idleTimer),{ws:e.ws,live:e.state===`live`}):null}#Z(e,t,n){let r=[`partial_transcript`,`context`];this.bridge&&this.config?.clientDelegation!==!1&&r.push(`client_delegation`,`delegation_update`,`delegation_read_back`,`delegation_stream`),n&&r.unshift(`attach`);let a=new URLSearchParams({voiceProtocol:D,clientVersion:`persona/${i}`,voiceCapabilities:C,clientCapabilities:r.join(`,`)});return n?.forEach((e,t)=>a.set(t,e)),`${c(e)}/ws/agents/${encodeURIComponent(t)}/voice?${a}`}async startListening(){if(this.#l)return;let e=this.#A;e||(this.#k=!1,this.#D=null),this.#A=!1;let n=this.config?.agentId,r=this.config?.clientToken,i=this.config?.host;if(!n)throw Error(`Runtype voice requires an agentId`);if(!r)throw Error(`Runtype voice requires a clientToken`);if(!i)throw Error(`Runtype voice requires a host (or widget apiUrl)`);let a=++this.#d;this.#f=!1,this.#l=!0;try{let o=await navigator.mediaDevices.getUserMedia({audio:{sampleRate:d,channelCount:1,echoCancellation:!0}});if(a!==this.#d){o.getTracks().forEach(e=>e.stop());return}this.#r=o;let s=new(window.AudioContext||window.webkitAudioContext)({sampleRate:d});if(this.#t=s,s.state===`suspended`){if(await Promise.race([s.resume().catch(()=>{}),new Promise(t=>setTimeout(t,e?500:v))]),a!==this.#d)return;if(s.state!==`running`)throw Error(e?this.#D=`${M} Tap the mic to reconnect.`:`Audio blocked until a tap`)}let c=this.config?.createPlaybackEngine?await this.config.createPlaybackEngine():new t(f);if(a!==this.#d){c.destroy(),o.getTracks().forEach(e=>e.stop()),s.close().catch(()=>{});return}this.#c=c,this.#de(),this.#ee(s,o,a);let l=await this.#X();if(a!==this.#d){l?.ws.close(1e3,`client ended call`);return}if(l){let{ws:e}=l;this.#e=e,this.#Q(e,a),l.live||e.send(`{"type":"start"}`),this.#te(e),this.#ge(`listening`);return}let u=new WebSocket(this.#Z(i,n),[`runtype.bearer`,r]);u.binaryType=`arraybuffer`,this.#e=u,u.onopen=()=>{a===this.#d&&(this.#te(u),this.#ge(`listening`))},this.#Q(u,a)}catch(e){throw this.#he(),this.#_e(e),this.#ge(`error`),e}}#Q(e,t){e.onmessage=e=>this.#ne(e,t),e.onerror=()=>{t!==this.#d||this.#E||(this.#_e(/* @__PURE__ */ Error(`Voice connection failed`)),this.#ge(`error`),this.#he())},e.onclose=e=>{if(this.#f){this.#f=!1;return}if(t!==this.#d)return;let n=this.#E??(e.code===4408?{reason:`idle_timeout`}:null);if(n)this.#$(n.reason,n.message);else{if(e.code!==1e3){let t=e.code?` (code ${e.code})`:``;this.#_e(/* @__PURE__ */ Error(`Voice connection closed${t}`)),this.#ge(`error`)}else this.#ge(`idle`);this.#he()}}}#$(e,t){let n=j.includes(e)&&!this.#k;if(this.#he(),n)this.#k=!0,this.#l=!0,this.#D=e===`provider_error`?`${M} Reconnecting…`:`Reconnecting…`,this.#O=setTimeout(()=>{this.#l=!1,this.#A=!0,this.startListening().catch(()=>{})},1e3+Math.random()*1e3),this.#ge(`idle`);else{if(j.includes(e))return this.#D=M,this.#_e(/* @__PURE__ */ Error(M)),this.#ge(`error`);if(e===`error`)return this.#ge(`error`);this.#D=e===`quota`&&t||A.get(e)||null,this.#ge(`idle`)}}takeNotice(){let e=this.#D;return this.#D=null,e}getDisclosure(){let e=this.config?.disclosureText;return this.#l&&this.#h&&e!==!1?e||k:null}async stopListening(){this.#he(),this.#ge(`idle`)}async disconnect(){this.#he(),this.#ge(`disconnected`),this.#V=[],this.#H=[],this.#U=[],this.#W=[],this.#G=[]}stopPlayback(){this.#me();let e=this.#e;e&&e.readyState===WebSocket.OPEN&&(this.#h&&(this.#_=Date.now()+T,e.send(`{"type":"cancel"}`)),this.#ge(`listening`))}getInterruptionMode(){return`barge-in`}isBargeInActive(){return this.#l}onLevel(e){this.#n.push(e)}async deactivateBargeIn(){this.#he(),this.#ge(`idle`)}#ee(e,t,n){let r=e.createMediaStreamSource(t);this.#i=r;let i=e.createScriptProcessor(p,1,1);this.#a=i,i.onaudioprocess=e=>{if(n!==this.#d)return;let t=this.#e,r=t?.readyState===WebSocket.OPEN;if(t&&!r&&t.readyState!==WebSocket.CONNECTING)return;let i=e.inputBuffer.getChannelData(0),a=new Int16Array(i.length),o=0;for(let e=0;e<i.length;e++){let t=Math.max(-1,Math.min(1,i[e]));o+=t*t,a[e]=t<0?t*32768:t*32767}if(t&&r)this.#te(t),t.send(a.buffer);else for(this.#o.push(a.buffer),this.#s+=a.byteLength;this.#s>m;)this.#s-=this.#o.shift().byteLength;if(this.#n.length>0){let e=Math.sqrt(o/i.length),t=Math.max(0,Math.min(1,e*h));for(let e of this.#n)e(t)}},r.connect(i),i.connect(e.destination)}#te(e){for(let t of this.#o)e.send(t);this.#o=[],this.#s=0}#ne(e,t){if(t!==this.#d)return;if(e.data instanceof ArrayBuffer){this.#le(e.data,t);return}let n;try{n=JSON.parse(e.data)}catch{return}switch(n.type){case`session_config`:n.speechMode&&(this.#h=n.speechMode===`speech_to_speech`,this.#c?.setContinuousMode?.(this.#h)),Array.isArray(n.capabilities)&&(this.#S=new Set(n.capabilities)),typeof n.callId==`string`&&(this.#T=n.callId),this.#x=this.#h&&this.#S.has(`client_delegation`)&&!!this.bridge,this.#h&&!this.#u&&this.#ge(`listening`),this.#S.has(`context`)&&!this.#j&&(this.#j=!0,this.#M=this.#re());break;case`transcript_update`:{let e=n.role===`assistant`?`assistant`:`user`,r=n.utteranceId??n.turnId;if(!r||e===`assistant`&&this.#ue())break;let i=String(r);if(e===`user`)n.final===!0&&this.#ie(t),this.#R=!1;else{if(this.#S.has(`delegation_read_back`)){let e=n.delegationId;(typeof e==`string`&&this.#F.has(e)&&!this.#z.has(i)||this.#R&&!this.#z.has(i))&&(this.#B.add(i),this.#R=!1)}else this.#R&&!this.#z.has(i)&&(this.#B.add(i),this.#R=!1);if(this.#z.add(i),this.#B.has(i))break}this.#ve(e,n.text??``,n.final===!0,{turnId:i,...typeof n.startMs==`number`&&{startMs:n.startMs},...typeof n.endMs==`number`&&{endMs:n.endMs},...this.#x&&{caption:!0}});break}case`delegation_started`:case`delegation_completed`:{let e=String(n.delegationId??n.turnId);if(n.type===`delegation_started`){this.#ie(t);let r=n.input;this.#x&&r&&this.#ce(e,{delegationId:e,userText:String(r.text??``),userUtteranceIds:Array.isArray(r.userUtteranceIds)?r.userUtteranceIds.filter(e=>typeof e==`string`):[],messages:Array.isArray(r.messages)?r.messages:[]},t)}else n.speak!==!1&&this.#F.has(e)&&!this.#I.delete(e)&&!this.#S.has(`delegation_read_back`)&&this.#oe(e);this.#g=n.type===`delegation_started`,!this.#u&&!this.#ue()&&this.#ge(this.#g?`processing`:`listening`);break}case`delegation_progress`:{let e=String(n.delegationId);this.#F.has(e)&&!this.#I.has(e)&&!this.#w.has(e)&&(this.#I.add(e),this.#oe(e));break}case`delegation_cancelled`:this.#se(String(n.delegationId),n.reason!==`session_ending`&&n.reason!==`provider_cancelled`);break;case`warning`:console.warn(`[Persona voice] ${n.code}: ${n.message??``}`,this.#T??``),n.delegationId&&(n.code===`UNKNOWN_DELEGATION`||n.code===`LATE_RESULT_LIMIT`)&&this.#se(String(n.delegationId));break;case`audio_clear`:this.#me(),this.#_=0,this.#ge(`listening`);break;case`transcript_interim`:this.#ge(`listening`),this.#ve(`user`,n.text??``,!1);break;case`transcript_final`:{let e=n.role===`assistant`?`assistant`:`user`;this.#ge(e===`user`?`processing`:`speaking`),this.#ve(e,n.text??``,!0);break}case`audio_end`:this.#c?this.#c.markStreamEnd():(this.#u=!1,this.#ge(`listening`));break;case`metrics`:this.#ye({llmMs:n.llm_ms,ttsMs:n.tts_ms,firstAudioMs:n.first_audio_ms,totalMs:n.total_ms});break;case`error`:this.#_e(Error(n.error||`Voice error`)),this.#ge(`error`);break;case`session_end`:this.#E={reason:String(n.reason),...typeof n.message==`string`&&{message:n.message}}}}async#re(){let e=this.bridge?.getHistory()??[],t=``;try{let e=this.config?.callContext;t=String((typeof e==`function`?await e():e)??``)}catch{}return o(e,t)}#ie(e){let t=this.#M;if(!t)return;this.#M=null;let n=!1,r=t.then(t=>{let r=this.#e;!n&&t&&e===this.#d&&r?.readyState===WebSocket.OPEN&&r.send(JSON.stringify({type:`context`,text:t}))});this.#N={done:r,drop:()=>n=!0}}async#ae(){let e=this.#N;if(!e)return;let t,n=await Promise.race([e.done.then(()=>!1),new Promise(e=>{t=setTimeout(()=>e(!0),E)})]);clearTimeout(t),n&&e.drop()}#oe(e){this.#R=!0,this.#L=e}#se(e,t=!1){this.#w.add(e),this.#L===e&&(this.#R=!1),this.#I.delete(e),this.bridge?.dropDelegation?.(e,t),this.#C.get(e)?.abort()}#ce(e,t,n){let r=this.bridge,i=({type:t,...r})=>{let i=this.#e;return n!==this.#d||i?.readyState!==WebSocket.OPEN||this.#w.has(e)?!1:(i.send(JSON.stringify({type:t,delegationId:e,...r})),!0)},a=(e,t,n,r=0)=>i({type:e,status:t,text:n,...r>0&&{streamedChars:r}});this.#P=this.#P.then(async()=>{if(n!==this.#d||this.#w.has(e))return;let o=null,s=this.#S.has(`delegation_stream`)&&this.#S.has(`delegation_read_back`),c=t=>{o=(o??this.#ae()).then(()=>{i({type:`delegation_delta`,text:t})&&this.#F.add(e)})},l=await r.runDelegatedTurn(s?{...t,stream:c}:t).catch(()=>({status:`failed`,text:``}));await this.#ae(),await o;let u=s?l.streamedChars??0:0,d=!!l.followUp,f=d&&this.#S.has(`delegation_update`);if(!a(f?`delegation_update`:`delegation_result`,d&&!f?`completed`:l.status,l.text,u)||(l.status!==`failed`&&l.inChat!==!1&&this.#F.add(e),!l.followUp))return;let p=new AbortController;this.#C.set(e,p),l.followUp({signal:p.signal,approvalTimeoutMs:this.config?.approvalTimeoutMs&&Math.min(this.config.approvalTimeoutMs,O),readBack:f,onUpdate:e=>a(`delegation_update`,`pending_approval`,e)}).then(t=>{this.#C.delete(e),f&&t&&!p.signal.aborted&&a(`delegation_result`,t.status,t.text)})})}#le(e,t){if(t!==this.#d||!this.#c||this.#ue())return;let n=s(e);n.length!==0&&(this.#u||(this.#u=!0,this.#ge(`speaking`)),this.#de(),this.#c.enqueue(n),this.#h&&this.#fe(n.length))}#ue(){return Date.now()<this.#_}#de(){if(this.#b||!this.#c)return;this.#b=!0;let e=this.#d;this.#c.onFinished(()=>{e===this.#d&&(this.#b=!1,this.#pe())})}#fe(e){let t=Date.now();this.#v=Math.max(t,this.#v)+e/48,clearTimeout(this.#y),this.#y=setTimeout(()=>this.#pe(),this.#v-t+w)}#pe(){this.#u=!1,this.#v=0,this.#e&&this.#e.readyState===WebSocket.OPEN&&this.#ge(this.#g?`processing`:`listening`)}#me(){this.#c?.flush(),this.#b=!1,this.#de(),this.#u=!1,this.#v=0,clearTimeout(this.#y)}#he(){this.#d+=1,this.#l=!1,this.#u=!1,this.#Y(),this.#h=!1,this.#g=!1,this.#x=!1,this.#S=/* @__PURE__ */ new Set;for(let e of this.#C.values())e.abort();if(this.#C.clear(),this.#w.clear(),this.#T=void 0,this.#E=null,clearTimeout(this.#O),this.#j=!1,this.#M=null,this.#N=null,this.#P=Promise.resolve(),this.#F.clear(),this.#I.clear(),this.#L=null,this.#R=!1,this.#z.clear(),this.#B.clear(),this.#b=!1,this.#_=0,this.#v=0,clearTimeout(this.#y),this.#o=[],this.#s=0,this.#a&&=(this.#a.onaudioprocess=null,this.#a.disconnect(),null),this.#i&&=(this.#i.disconnect(),null),this.#r&&=(this.#r.getTracks().forEach(e=>e.stop()),null),this.#t&&=(this.#t.close().catch(()=>{}),null),this.#c&&=(this.#c.destroy(),null),this.#e){this.#f=!0;try{this.#e.close(1e3,`client ended call`)}catch{}this.#e=null}}onResult(e){this.#V.push(e)}onError(e){this.#H.push(e)}onStatusChange(e){this.#U.push(e)}onTranscript(e){this.#W.push(e)}onMetrics(e){this.#G.push(e)}#ge(e){this.#U.forEach(t=>t(e))}#_e(e){this.#H.forEach(t=>t(e))}#ve(e,t,n,r){this.#W.forEach(i=>i(e,t,n,r))}#ye(e){this.#G.forEach(t=>t(e))}}})),I,ne=e((()=>{I=class{#e;#t;#n;#r;#i;#a;constructor(e={}){this.config=e,this.type=`browser`,this.#e=null,this.#t=[],this.#n=[],this.#r=[],this.#i=!1,this.#a=typeof window<`u`?window:void 0}async connect(){this.#r.forEach(e=>e(`connected`))}async startListening(){try{if(this.#i)throw Error(`Already listening`);if(!this.#a)throw Error(`Window object not available`);let e=this.#a.SpeechRecognition||this.#a.webkitSpeechRecognition;if(!e)throw Error(`Browser speech recognition not supported`);this.#e=new e,this.#e.lang=this.config?.language||`en-US`,this.#e.continuous=this.config?.continuous||!1,this.#e.interimResults=!0,this.#e.onresult=e=>{let t=Array.from(e.results).map(e=>e[0]).map(e=>e.transcript).join(``),n=e.results[e.results.length-1].isFinal;this.#t.forEach(e=>e({text:t,confidence:n?.8:.5,provider:`browser`})),n&&!this.config?.continuous&&this.stopListening()},this.#e.onerror=e=>{this.#n.forEach(t=>t(Error(e.error))),this.#r.forEach(e=>e(`error`))},this.#e.onstart=()=>{this.#i=!0,this.#r.forEach(e=>e(`listening`))},this.#e.onend=()=>{this.#i=!1,this.#r.forEach(e=>e(`idle`))},this.#e.start()}catch(e){throw this.#n.forEach(t=>t(e)),this.#r.forEach(e=>e(`error`)),e}}async stopListening(){this.#e&&=(this.#e.stop(),null),this.#i=!1,this.#r.forEach(e=>e(`idle`))}onResult(e){this.#t.push(e)}onError(e){this.#n.push(e)}onStatusChange(e){this.#r.push(e)}async disconnect(){await this.stopListening(),this.#r.forEach(e=>e(`disconnected`))}static isSupported(){return`SpeechRecognition`in window||`webkitSpeechRecognition`in window}}}));function L(e){switch(e.type){case`runtype`:if(!e.runtype)throw Error(`Runtype voice provider requires configuration`);return new F(e.runtype);case`browser`:if(!I.isSupported())throw Error(`Browser speech recognition not supported`);return new I(e.browser||{});case`custom`:{let t=e.custom;if(!t)throw Error("Custom voice provider requires a `custom` provider instance or factory");let n=typeof t==`function`?t():t;if(!n||typeof n.startListening!=`function`)throw Error("Custom voice provider `custom` must be a VoiceProvider (or a factory returning one)");return n}default:throw Error(`Unknown voice provider type: ${e.type}`)}}function R(e){if(e?.type===`custom`&&e.custom)return L({type:`custom`,custom:e.custom});if(e?.type===`runtype`&&e.runtype)return L({type:`runtype`,runtype:e.runtype});if(I.isSupported())return L({type:`browser`,browser:e?.browser||{language:`en-US`}});throw Error(`No supported voice providers available`)}function re(e){try{return R(e),!0}catch{return!1}}var ie=e((()=>{te(),ne()})),z,ae,oe=e((()=>{z=e=>e.toLowerCase().replace(/[^\p{L}\p{N}]+/gu,``),ae=class{constructor(e){this.host=e,this.turns=/* @__PURE__ */ new Map,this.latestId=null,this.cancelled=/* @__PURE__ */ new Set}apply(e,t,n,r,i,a){let o=this.host;t=t.trim();let s=this.turns.get(r);if(s||(s={},this.turns.set(r,s),this.latestId=r),e===`user`){s.userFinal=n;let e=s.userId?o.find(s.userId):void 0;if(e){let r=s.userStartMs===void 0&&i!==void 0;r&&(s.userStartMs=i),o.upsert({...e,content:t,voiceProcessing:!n,...r&&this.placeBefore(this.startedAfter(i))})}else{s.userStartMs=i;let e=s.assistantId?o.find(s.assistantId):void 0;s.userId=o.inject({role:`user`,content:t,streaming:!1,voiceProcessing:!n,voiceCaption:a,...this.placeBefore(this.startedAfter(i)??e)}).id}}else if(!this.cancelled.has(r)){s.assistantFinal=n;let e=s.assistantId?o.find(s.assistantId):void 0;if(e){let r=s.assistantStartMs===void 0&&i!==void 0;r&&(s.assistantStartMs=i),o.upsert({...e,content:t,streaming:!n,voiceProcessing:!n,...r&&this.placeBefore(this.startedAfter(i))})}else t&&(s.assistantStartMs=i,s.assistantId=o.inject({role:`assistant`,content:t,streaming:!n,voiceProcessing:!n,voiceCaption:a,...this.placeBefore(this.startedAfter(i))}).id);n&&s.assistantId&&o.markSpoken(s.assistantId)}this.sync()}claimUserTurn(e,t=[]){let n=t[t.length-1];for(let e of t)e!==n&&(this.turns.has(e)||this.turns.set(e,{}),this.turns.get(e).claimed=!0);let r;if(n){if(r=this.turns.get(n),r||(r={},this.turns.set(n,r)),r.claimed)return null;(!r.userId||!this.host.find(r.userId))&&(r.userFinal=!0,r.userId=this.host.inject({role:`user`,content:e.trim()}).id)}else{let t=z(e),n=[...this.turns.values()].reverse().flatMap(e=>{let t=e.userId&&!e.claimed?this.host.find(e.userId):void 0;return t?[{turn:e,text:z(t.content)}]:[]}).filter(({text:e})=>e&&t);r=(n.find(({text:e})=>e===t)??n.find(({text:e})=>e.startsWith(t)||t.startsWith(e)))?.turn}return r?(r.claimed=!0,r.userId):null}cancel(){let e=this.inFlight();if(e.length===0){let t=this.awaiting();if(!t)return;e=[t]}for(let t of e)this.cancelled.add(t);this.closeReplies(e),this.sync()}fail(e){let t=this.awaiting(),n=this.inFlight();if(!t&&n.length===0)return;for(let e of n)this.turns.get(e).assistantFinal=!0;this.closeReplies(n);let r=this.host.inject({role:`assistant`,content:e,streaming:!1,voiceProcessing:!1}),i=t?this.turns.get(t):void 0;i&&(i.assistantId=r.id,i.assistantFinal=!0),this.sync()}settle(){if(this.turns.size===0)return;let e=this.pending(),t=/* @__PURE__ */ new Set;for(let e of this.turns.values())e.userId&&t.add(e.userId),e.assistantId&&(t.add(e.assistantId),this.host.markSpoken(e.assistantId));this.turns.clear(),this.latestId=null,this.host.settle(t),e&&this.host.setStreaming(!1)}startedAfter(e){if(e===void 0)return;let t;for(let n of this.turns.values())for(let[r,i]of[[n.userId,n.userStartMs],[n.assistantId,n.assistantStartMs]])r&&i!==void 0&&i>e&&(!t||i<t.start)&&(t={start:i,id:r});return t&&this.host.find(t.id)}placeBefore(e){if(!e)return;let t=e.sequence??0,n=t-1;for(let r of this.turns.values())for(let i of[r.userId,r.assistantId]){let r=i?this.host.find(i):void 0,a=r?.sequence;r?.createdAt===e.createdAt&&a!==void 0&&a>n&&a<t&&(n=a)}return{createdAt:e.createdAt,sequence:(n+t)/2}}closeReplies(e){let t=/* @__PURE__ */ new Set;for(let n of e){let e=this.turns.get(n)?.assistantId;e&&(t.add(e),this.host.markSpoken(e))}t.size>0&&this.host.settle(t)}inFlight(){let e=[];for(let[t,n]of this.turns)n.assistantId&&!n.assistantFinal&&!this.cancelled.has(t)&&e.push(t);return e}awaiting(){let e=this.latestId;if(!e)return null;let t=this.turns.get(e);return t?.userFinal&&!t.assistantId&&!t.claimed&&!this.cancelled.has(e)?e:null}pending(){return this.awaiting()!==null||this.inFlight().length>0}sync(){this.host.setStreaming(this.pending())}}}));function se(e){let t=/(\S+)$/.exec(e)?.[1];if(!t)return!1;let n=t.replace(/^[("'“‘[*_]+/,``).toLowerCase();if(G.has(n)||/^[a-z](?:\.[a-z])*$/.test(n))return!0;if(/^\d+$/.test(t)){let n=e.length-t.length;return n===0||/\n\s*$/.test(e.slice(0,n))}return!1}function*B(e,t){let n=new RegExp(K.source,`g`);for(let r=n.exec(e);r;r=n.exec(e)){let n=r[1];if(!e.slice(0,r.index+(n?.length??0)).trim()||n!==void 0&&(/^[,;:]$/.test(n)&&!t||n===`.`&&se(e.slice(0,r.index))))continue;let i=r.index+r[0].length;i<e.length&&(yield i)}}function V(e,t){let n=e.slice(0,t),r=0;for(let e of n.matchAll(/\s+/g))n.slice(0,e.index).trim()&&(r=e.index+e[0].length);return r}function H(e){let t=0;for(let n of B(e.slice(0,220),!0))t=n;if(t)return t;let n=V(e,220);if(n)return n;let r=e.charCodeAt(219);return r>=55296&&r<=56319?219:220}var U,W,G,K,ce,le=e((()=>{U=30,W=6,G=/* @__PURE__ */ new Set(/* @__PURE__ */ `mr,mrs,ms,dr,prof,sr,jr,st,mt,vs,etc,approx,inc,ltd,co,corp,no,nos,fig,ft,dept,est,min,max,e.g,i.e,a.m,p.m,u.s,u.k`.split(`,`)),K=/([.!?]+|[,;:])(["'”’)\]*_]*)(\s+)|\n\s*/g,ce=class{#e=``;#t=!0;push(e){return this.#e+=e,this.#n()}flush(){let e=this.#n(),t=this.#e;if(this.#e=``,t.trim()){for(let n=0;n<t.length;){let r=t.slice(n),i=r.length>220?H(r):r.length;e.push(r.slice(0,i)),n+=i}this.#t=!1}return e}idle(){let e=this.#e;if(!e.trim()||!/(?:[.!?…]["'”’)\]*_]*|\n)\s*$/.test(e))return[];this.#e=``,this.#t=!1;let t=[];for(let n=0;n<e.length;){let r=e.slice(n),i=r.length>220?H(r):r.length;t.push(r.slice(0,i)),n+=i}return t}#n(){let e=[];for(let t=this.#r();t>0;t=this.#r())e.push(this.#e.slice(0,t)),this.#e=this.#e.slice(t),this.#t=!1;return e}#r(){let e=this.#e;if(!e.trim())return 0;let t=B(e,this.#t).next().value??0;if(t&&t<=220)return t;let n=/[.!?]["'”’)\]*_]*$/.test(e);if(this.#t&&!n){let t=e.match(/\S+\s+/g)?.length??0;if(e.trim().length>=U||t>=W){let t=V(e,220);if(t)return t}}return e.length>220?H(e):0}}}));function q(e,t=0){if(e==null||e===``)return``;if(typeof e!=`object`)return String(e);if(t>2)return``;if(Array.isArray(e))return e.map(e=>q(e,t+1)).filter(Boolean).join(`, `);let n=e,r=n.quantity??n.qty??n.count,i=n.name??n.item??n.product??n.title;return r!=null&&i!=null&&typeof i!=`object`?`${r} ${i}`:Object.entries(n).filter(([e])=>!e.startsWith(`_`)).map(([e,n])=>{let r=q(n,t+1);return r&&(t?`${Q(e)} ${r}`:`${Q(e)}: ${r}`)}).filter(Boolean).join(t?`, `:`; `)}function ue(e){let t=e.length>1?`These actions need the user's approval in the chat before they happen:`:`This action needs the user's approval in the chat before it happens:`,n=ge-t.length-119-2;return`${t}\n${e.map(t=>{let r=[Q(t.toolName)];t.description&&r.push(`(${Z(t.description.trim(),160)})`);let i=q(t.parameters);return i&&r.push(`with ${i}`),t.reason&&r.push(`because: ${Z(t.reason.trim(),160)}`),Z(`- ${r.join(` `)}`,Math.floor(n/e.length)-1)}).join(`
4
+ `)}function s(e){return e.byteLength>=44&&new DataView(e).getUint32(0,!1)===g?new Uint8Array(e,44):new Uint8Array(e)}function c(e){let t=e.replace(/\/+$/,``);return/^wss?:\/\//i.test(t)?t:/^https?:\/\//i.test(t)?t.replace(/^http/i,`ws`):`${typeof window<`u`&&window.location?.protocol===`https:`?`wss:`:`ws:`}//${t}`}function l(e){return c(e).replace(/^ws/i,`http`)}function u(e){return typeof e!=`number`||!Number.isFinite(e)?b:Math.min(S,Math.max(x,Math.round(e)))}var d,f,p,m,h,g,_,v,y,b,x,S,C,w,T,E,D,O,k,A,j,M,N,P,ee,F,te=e((()=>{n(),a(),d=16e3,f=24e3,p=4096,m=d*2*8,h=4,g=1380533830,_=3e4,v=1e3,y=5e3,b=3e4,x=3e4,S=6e5,C=`full-duplex-v1`,w=300,T=2e3,E=2e3,D=`runtype-browser-v1`,O=54e4,k=`You're talking to an AI assistant. Voice is processed by OpenAI.`,A=/* @__PURE__ */ new Map([[`idle_timeout`,`Voice call ended after a quiet period.`],[`max_duration`,`This voice call reached its time limit.`],[`provider_ended`,`The voice session ended.`],[`quota`,`Voice is unavailable right now.`],[`auth_expired`,`Voice session expired. Tap the mic to reconnect.`]]),j=[`provider_error`,`server_restart`],M=`Voice connection lost.`,N=8e3,P=4e3,ee=2e3,F=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p;#m;#h;#g;#_;#v;#y;#b;#x;#S;#C;#w;#T;#E;#D;#O;#k;#A;#j;#M;#N;#P;#F;#I;#L;#R;#z;#B;#V;#H;#U;#W;#G;#K;#q;#J;#Y;constructor(e){this.config=e,this.type=`runtype`,this.#e=null,this.#t=null,this.#n=[],this.#r=null,this.#i=null,this.#a=null,this.#o=[],this.#s=0,this.#c=null,this.#l=!1,this.#u=!1,this.#d=0,this.#f=!1,this.#p=-1/0,this.#m=null,this.#h=!1,this.#g=!1,this.#_=0,this.#v=0,this.#b=!1,this.bridge=null,this.#x=!1,this.#S=/* @__PURE__ */ new Set,this.#C=/* @__PURE__ */ new Map,this.#w=/* @__PURE__ */ new Set,this.#E=null,this.#D=null,this.#k=!1,this.#A=!1,this.#j=!1,this.#M=null,this.#N=null,this.#P=Promise.resolve(),this.#F=/* @__PURE__ */ new Set,this.#I=/* @__PURE__ */ new Set,this.#L=null,this.#R=!1,this.#z=/* @__PURE__ */ new Set,this.#B=/* @__PURE__ */ new Set,this.#V=null,this.#H=/* @__PURE__ */ new Set,this.#U=null,this.#W=/* @__PURE__ */ new Map,this.#G=[],this.#K=[],this.#q=[],this.#J=[],this.#Y=[]}async connect(){}setSessionBridge(e){this.bridge=e}prewarm(){if(this.#l||this.#m)return;let e=this.config?.agentId,t=this.config?.clientToken,n=this.config?.host;if(!e||!t||!n)return;let r=Date.now();if(!(r-this.#p<_)){this.#p=r;try{this.config?.prewarmMode===`attach`?this.#Z(n,e,t):this.#X(n,e,t)}catch{}}}#X(e,t,n){if(typeof fetch!=`function`)return;let r=`${l(e)}/v1/client/agents/${encodeURIComponent(t)}/voice/prewarm`;fetch(r,{method:`POST`,headers:{Authorization:`Bearer ${n}`},keepalive:!0}).catch(()=>{})}#Z(e,t,n){let r=new URLSearchParams,i=this.config?.attachIdleMs,a=u(i);i!==void 0&&r.set(`attachIdleMs`,String(a));let o=new WebSocket(this.#te(e,t,r),[`runtype.bearer`,`runtype.attach`,n]);o.binaryType=`arraybuffer`;let s=()=>{},c={ws:o,state:`connecting`,ready:new Promise(e=>{s=e}),settle:s,openedAt:0,idleTimer:void 0};this.#m=c,o.onopen=()=>{this.#m===c&&(c.state=o.protocol===`runtype.attach`?`attached`:`live`,c.openedAt=Date.now(),this.#Q(c,a),c.state===`attached`&&o.send(`{"type":"ping"}`),c.settle())},o.onmessage=e=>{if(this.#m!==c||typeof e.data!=`string`)return;let t;try{t=JSON.parse(e.data)}catch{return}t.type===`attached`&&typeof t.idleMs==`number`&&this.#Q(c,t.idleMs-(Date.now()-c.openedAt))},o.onerror=()=>{},o.onclose=()=>{this.#m===c&&this.#$()}}#Q(e,t){clearTimeout(e.idleTimer),e.idleTimer=setTimeout(()=>{this.#m===e&&this.#$()},Math.max(0,t))}#$(){let e=this.#m;if(!e)return;this.#m=null,clearTimeout(e.idleTimer);let{ws:t}=e;if(t.onopen=null,t.onmessage=null,t.onerror=null,t.onclose=null,e.settle(),t.readyState===WebSocket.CONNECTING||t.readyState===WebSocket.OPEN)try{t.close(1e3,`prewarm released`)}catch{}}async#ee(){let e=this.#m;if(!e)return null;if(e.state===`connecting`){let t;await Promise.race([e.ready,new Promise(e=>{t=setTimeout(e,y)})]),clearTimeout(t)}return this.#m===e?e.state===`connecting`||e.ws.readyState!==WebSocket.OPEN?(this.#$(),null):(this.#m=null,clearTimeout(e.idleTimer),{ws:e.ws,live:e.state===`live`}):null}#te(e,t,n){let r=[`partial_transcript`,`context`];this.bridge&&this.config?.clientDelegation!==!1&&(r.push(`client_delegation`,`delegation_update`,`delegation_read_back`,`delegation_stream`),this.bridge.clientTools?.()&&r.push(`client_tools`)),n&&r.unshift(`attach`);let a=new URLSearchParams({voiceProtocol:D,clientVersion:`persona/${i}`,voiceCapabilities:C,clientCapabilities:r.join(`,`)});return n?.forEach((e,t)=>a.set(t,e)),`${c(e)}/ws/agents/${encodeURIComponent(t)}/voice?${a}`}async startListening(){if(this.#l)return;let e=this.#A;e||(this.#k=!1,this.#D=null),this.#A=!1;let n=this.config?.agentId,r=this.config?.clientToken,i=this.config?.host;if(!n)throw Error(`Runtype voice requires an agentId`);if(!r)throw Error(`Runtype voice requires a clientToken`);if(!i)throw Error(`Runtype voice requires a host (or widget apiUrl)`);let a=++this.#d;this.#f=!1,this.#l=!0;try{let o=await navigator.mediaDevices.getUserMedia({audio:{sampleRate:d,channelCount:1,echoCancellation:!0}});if(a!==this.#d){o.getTracks().forEach(e=>e.stop());return}this.#r=o;let s=new(window.AudioContext||window.webkitAudioContext)({sampleRate:d});if(this.#t=s,s.state===`suspended`){if(await Promise.race([s.resume().catch(()=>{}),new Promise(t=>setTimeout(t,e?500:v))]),a!==this.#d)return;if(s.state!==`running`)throw Error(e?this.#D=`${M} Tap the mic to reconnect.`:`Audio blocked until a tap`)}let c=this.config?.createPlaybackEngine?await this.config.createPlaybackEngine():new t(f);if(a!==this.#d){c.destroy(),o.getTracks().forEach(e=>e.stop()),s.close().catch(()=>{});return}this.#c=c,this.#he(),this.#ie(s,o,a);let l=await this.#ee();if(a!==this.#d){l?.ws.close(1e3,`client ended call`);return}if(l){let{ws:e}=l;this.#e=e,this.#ne(e,a),l.live||e.send(`{"type":"start"}`),this.#ae(e),this.#be(`listening`);return}let u=new WebSocket(this.#te(i,n),[`runtype.bearer`,r]);u.binaryType=`arraybuffer`,this.#e=u,u.onopen=()=>{a===this.#d&&(this.#ae(u),this.#be(`listening`))},this.#ne(u,a)}catch(e){throw this.#ye(),this.#xe(e),this.#be(`error`),e}}#ne(e,t){e.onmessage=e=>this.#oe(e,t),e.onerror=()=>{t!==this.#d||this.#E||(this.#xe(/* @__PURE__ */ Error(`Voice connection failed`)),this.#be(`error`),this.#ye())},e.onclose=e=>{if(this.#f){this.#f=!1;return}if(t!==this.#d)return;let n=this.#E??(e.code===4408?{reason:`idle_timeout`}:null);if(n)this.#re(n.reason,n.message);else{if(e.code!==1e3){let t=e.code?` (code ${e.code})`:``;this.#xe(/* @__PURE__ */ Error(`Voice connection closed${t}`)),this.#be(`error`)}else this.#be(`idle`);this.#ye()}}}#re(e,t){let n=j.includes(e)&&!this.#k;if(this.#ye(),n)this.#k=!0,this.#l=!0,this.#D=e===`provider_error`?`${M} Reconnecting…`:`Reconnecting…`,this.#O=setTimeout(()=>{this.#l=!1,this.#A=!0,this.startListening().catch(()=>{})},1e3+Math.random()*1e3),this.#be(`idle`);else{if(j.includes(e))return this.#D=M,this.#xe(/* @__PURE__ */ Error(M)),this.#be(`error`);if(e===`error`)return this.#be(`error`);this.#D=e===`quota`&&t||A.get(e)||null,this.#be(`idle`)}}takeNotice(){let e=this.#D;return this.#D=null,e}getDisclosure(){let e=this.config?.disclosureText;return this.#l&&this.#h&&e!==!1?e||k:null}async stopListening(){this.#ye(),this.#be(`idle`)}async disconnect(){this.#ye(),this.#be(`disconnected`),this.#G=[],this.#K=[],this.#q=[],this.#J=[],this.#Y=[]}stopPlayback(){this.#ve();let e=this.#e;e&&e.readyState===WebSocket.OPEN&&(this.#h&&(this.#_=Date.now()+T,e.send(`{"type":"cancel"}`)),this.#be(`listening`))}getInterruptionMode(){return`barge-in`}isBargeInActive(){return this.#l}onLevel(e){this.#n.push(e)}async deactivateBargeIn(){this.#ye(),this.#be(`idle`)}#ie(e,t,n){let r=e.createMediaStreamSource(t);this.#i=r;let i=e.createScriptProcessor(p,1,1);this.#a=i,i.onaudioprocess=e=>{if(n!==this.#d)return;let t=this.#e,r=t?.readyState===WebSocket.OPEN;if(t&&!r&&t.readyState!==WebSocket.CONNECTING)return;let i=e.inputBuffer.getChannelData(0),a=new Int16Array(i.length),o=0;for(let e=0;e<i.length;e++){let t=Math.max(-1,Math.min(1,i[e]));o+=t*t,a[e]=t<0?t*32768:t*32767}if(t&&r)this.#ae(t),t.send(a.buffer);else for(this.#o.push(a.buffer),this.#s+=a.byteLength;this.#s>m;)this.#s-=this.#o.shift().byteLength;if(this.#n.length>0){let e=Math.sqrt(o/i.length),t=Math.max(0,Math.min(1,e*h));for(let e of this.#n)e(t)}},r.connect(i),i.connect(e.destination)}#ae(e){for(let t of this.#o)e.send(t);this.#o=[],this.#s=0}#oe(e,t){if(t!==this.#d)return;if(e.data instanceof ArrayBuffer){this.#pe(e.data,t);return}let n;try{n=JSON.parse(e.data)}catch{return}switch(n.type){case`session_config`:n.speechMode&&(this.#h=n.speechMode===`speech_to_speech`,this.#c?.setContinuousMode?.(this.#h)),Array.isArray(n.capabilities)&&(this.#S=new Set(n.capabilities)),typeof n.callId==`string`&&(this.#T=n.callId),this.#x=this.#h&&this.#S.has(`client_delegation`)&&!!this.bridge,this.#h&&!this.#u&&this.#be(`listening`),this.#S.has(`context`)&&!this.#j&&(this.#j=!0,this.#M=this.#se()),this.#x&&this.#S.has(`client_tools`)&&!this.#V&&(this.#V=this.bridge?.clientTools?.()?.open({send:e=>{let n=this.#e;return t!==this.#d||n?.readyState!==WebSocket.OPEN?!1:(n.send(JSON.stringify(e)),!0)},cancelled:e=>this.#w.has(e)}).catch(()=>null)??null);break;case`client_tool_call`:{let e=String(n.delegationId);this.#V&&!this.#W.has(e)&&(this.#W.set(e,this.#U),this.#F.add(e)),this.#V?.then(e=>e?.call(n));break}case`transcript_update`:{let e=n.role===`assistant`?`assistant`:`user`,r=n.utteranceId??n.turnId;if(!r||e===`assistant`&&this.#me())break;let i=String(r);if(e===`user`)n.final===!0&&(this.#ce(t),this.#U={id:i,text:String(n.text??``)}),this.#R=!1;else{if(this.#S.has(`delegation_read_back`)){let e=n.delegationId;(typeof e==`string`&&this.#F.has(e)&&!this.#z.has(i)||this.#R&&!this.#z.has(i))&&(this.#B.add(i),this.#R=!1)}else this.#R&&!this.#z.has(i)&&(this.#B.add(i),this.#R=!1);if(this.#z.add(i),this.#B.has(i))break}this.#Se(e,n.text??``,n.final===!0,{turnId:i,...typeof n.startMs==`number`&&{startMs:n.startMs},...typeof n.endMs==`number`&&{endMs:n.endMs},...this.#x&&{caption:!0}});break}case`delegation_started`:case`delegation_completed`:{let e=String(n.delegationId??n.turnId);if(n.type===`delegation_started`){this.#ce(t),this.#H.add(e),this.#F.delete(e),this.#W.delete(e)&&this.#V?.then(t=>t?.abort(e));let r=n.input;this.#x&&r&&this.#fe(e,{delegationId:e,userText:String(r.text??``),userUtteranceIds:Array.isArray(r.userUtteranceIds)?r.userUtteranceIds.filter(e=>typeof e==`string`):[],messages:Array.isArray(r.messages)?r.messages:[]},t)}else if(n.route===`direct`&&this.#V&&!this.#H.has(e)){let t=this.#W.get(e)??this.#U;this.#W.delete(e),this.#H.add(e),this.#F.add(e),this.bridge?.recordDirectTurn?.({delegationId:e,userText:t?.text??``,userUtteranceIds:t?[t.id]:[],assistantText:typeof n.text==`string`?n.text:``})}n.type===`delegation_completed`&&n.speak!==!1&&this.#F.has(e)&&!this.#I.delete(e)&&!this.#S.has(`delegation_read_back`)&&this.#ue(e),this.#g=n.type===`delegation_started`,!this.#u&&!this.#me()&&this.#be(this.#g?`processing`:`listening`);break}case`delegation_progress`:{let e=String(n.delegationId);this.#F.has(e)&&!this.#I.has(e)&&!this.#w.has(e)&&(this.#I.add(e),this.#ue(e));break}case`delegation_cancelled`:this.#de(String(n.delegationId),n.reason!==`session_ending`&&n.reason!==`provider_cancelled`);break;case`warning`:console.warn(`[Persona voice] ${n.code}: ${n.message??``}`,this.#T??``),n.delegationId&&(n.code===`UNKNOWN_DELEGATION`||n.code===`LATE_RESULT_LIMIT`)&&this.#de(String(n.delegationId));break;case`audio_clear`:this.#ve(),this.#_=0,this.#be(`listening`);break;case`transcript_interim`:this.#be(`listening`),this.#Se(`user`,n.text??``,!1);break;case`transcript_final`:{let e=n.role===`assistant`?`assistant`:`user`;this.#be(e===`user`?`processing`:`speaking`),this.#Se(e,n.text??``,!0);break}case`audio_end`:this.#c?this.#c.markStreamEnd():(this.#u=!1,this.#be(`listening`));break;case`metrics`:this.#Ce({llmMs:n.llm_ms,ttsMs:n.tts_ms,firstAudioMs:n.first_audio_ms,totalMs:n.total_ms});break;case`error`:this.#xe(Error(n.error||`Voice error`)),this.#be(`error`);break;case`session_end`:this.#E={reason:String(n.reason),...typeof n.message==`string`&&{message:n.message}}}}async#se(){let e=this.bridge?.getHistory()??[],t=``;try{let e=this.config?.callContext;t=String((typeof e==`function`?await e():e)??``)}catch{}return o(e,t)}#ce(e){let t=this.#M;if(!t)return;this.#M=null;let n=!1,r=t.then(t=>{let r=this.#e;!n&&t&&e===this.#d&&r?.readyState===WebSocket.OPEN&&r.send(JSON.stringify({type:`context`,text:t}))});this.#N={done:r,drop:()=>n=!0}}async#le(){let e=this.#N;if(!e)return;let t,n=await Promise.race([e.done.then(()=>!1),new Promise(e=>{t=setTimeout(()=>e(!0),E)})]);clearTimeout(t),n&&e.drop()}#ue(e){this.#R=!0,this.#L=e}#de(e,t=!1){this.#w.add(e),this.#L===e&&(this.#R=!1),this.#I.delete(e),this.#H.has(e)||this.#F.delete(e),this.#V?.then(t=>t?.abort(e)),this.bridge?.dropDelegation?.(e,t),this.#C.get(e)?.abort()}#fe(e,t,n){let r=this.bridge,i=({type:t,...r})=>{let i=this.#e;return n!==this.#d||i?.readyState!==WebSocket.OPEN||this.#w.has(e)?!1:(i.send(JSON.stringify({type:t,delegationId:e,...r})),!0)},a=(e,t,n,r=0)=>i({type:e,status:t,text:n,...r>0&&{streamedChars:r}});this.#P=this.#P.then(async()=>{if(n!==this.#d||this.#w.has(e))return;let o=null,s=this.#S.has(`delegation_stream`)&&this.#S.has(`delegation_read_back`),c=t=>{o=(o??this.#le()).then(()=>{i({type:`delegation_delta`,text:t})&&this.#F.add(e)})},l=await r.runDelegatedTurn(s?{...t,stream:c}:t).catch(()=>({status:`failed`,text:``}));await this.#le(),await o;let u=s?l.streamedChars??0:0,d=!!l.followUp,f=d&&this.#S.has(`delegation_update`);if(!a(f?`delegation_update`:`delegation_result`,d&&!f?`completed`:l.status,l.text,u)||(l.status!==`failed`&&l.inChat!==!1&&this.#F.add(e),!l.followUp))return;let p=new AbortController;this.#C.set(e,p),l.followUp({signal:p.signal,approvalTimeoutMs:this.config?.approvalTimeoutMs&&Math.min(this.config.approvalTimeoutMs,O),readBack:f,onUpdate:e=>a(`delegation_update`,`pending_approval`,e)}).then(t=>{this.#C.delete(e),f&&t&&!p.signal.aborted&&a(`delegation_result`,t.status,t.text)})})}#pe(e,t){if(t!==this.#d||!this.#c||this.#me())return;let n=s(e);n.length!==0&&(this.#u||(this.#u=!0,this.#be(`speaking`)),this.#he(),this.#c.enqueue(n),this.#h&&this.#ge(n.length))}#me(){return Date.now()<this.#_}#he(){if(this.#b||!this.#c)return;this.#b=!0;let e=this.#d;this.#c.onFinished(()=>{e===this.#d&&(this.#b=!1,this.#_e())})}#ge(e){let t=Date.now();this.#v=Math.max(t,this.#v)+e/48,clearTimeout(this.#y),this.#y=setTimeout(()=>this.#_e(),this.#v-t+w)}#_e(){this.#u=!1,this.#v=0,this.#e&&this.#e.readyState===WebSocket.OPEN&&this.#be(this.#g?`processing`:`listening`)}#ve(){this.#c?.flush(),this.#b=!1,this.#he(),this.#u=!1,this.#v=0,clearTimeout(this.#y)}#ye(){this.#d+=1,this.#l=!1,this.#u=!1,this.#$(),this.#h=!1,this.#g=!1,this.#x=!1,this.#S=/* @__PURE__ */ new Set;for(let e of this.#C.values())e.abort();if(this.#C.clear(),this.#w.clear(),this.#T=void 0,this.#E=null,clearTimeout(this.#O),this.#j=!1,this.#M=null,this.#N=null,this.#P=Promise.resolve(),this.#F.clear(),this.#I.clear(),this.#L=null,this.#R=!1,this.#z.clear(),this.#B.clear(),this.#V?.then(e=>e?.close()),this.#V=null,this.#H.clear(),this.#W.clear(),this.#U=null,this.#b=!1,this.#_=0,this.#v=0,clearTimeout(this.#y),this.#o=[],this.#s=0,this.#a&&=(this.#a.onaudioprocess=null,this.#a.disconnect(),null),this.#i&&=(this.#i.disconnect(),null),this.#r&&=(this.#r.getTracks().forEach(e=>e.stop()),null),this.#t&&=(this.#t.close().catch(()=>{}),null),this.#c&&=(this.#c.destroy(),null),this.#e){this.#f=!0;try{this.#e.close(1e3,`client ended call`)}catch{}this.#e=null}}onResult(e){this.#G.push(e)}onError(e){this.#K.push(e)}onStatusChange(e){this.#q.push(e)}onTranscript(e){this.#J.push(e)}onMetrics(e){this.#Y.push(e)}#be(e){this.#q.forEach(t=>t(e))}#xe(e){this.#K.forEach(t=>t(e))}#Se(e,t,n,r){this.#J.forEach(i=>i(e,t,n,r))}#Ce(e){this.#Y.forEach(t=>t(e))}}})),I,ne=e((()=>{I=class{#e;#t;#n;#r;#i;#a;constructor(e={}){this.config=e,this.type=`browser`,this.#e=null,this.#t=[],this.#n=[],this.#r=[],this.#i=!1,this.#a=typeof window<`u`?window:void 0}async connect(){this.#r.forEach(e=>e(`connected`))}async startListening(){try{if(this.#i)throw Error(`Already listening`);if(!this.#a)throw Error(`Window object not available`);let e=this.#a.SpeechRecognition||this.#a.webkitSpeechRecognition;if(!e)throw Error(`Browser speech recognition not supported`);this.#e=new e,this.#e.lang=this.config?.language||`en-US`,this.#e.continuous=this.config?.continuous||!1,this.#e.interimResults=!0,this.#e.onresult=e=>{let t=Array.from(e.results).map(e=>e[0]).map(e=>e.transcript).join(``),n=e.results[e.results.length-1].isFinal;this.#t.forEach(e=>e({text:t,confidence:n?.8:.5,provider:`browser`})),n&&!this.config?.continuous&&this.stopListening()},this.#e.onerror=e=>{this.#n.forEach(t=>t(Error(e.error))),this.#r.forEach(e=>e(`error`))},this.#e.onstart=()=>{this.#i=!0,this.#r.forEach(e=>e(`listening`))},this.#e.onend=()=>{this.#i=!1,this.#r.forEach(e=>e(`idle`))},this.#e.start()}catch(e){throw this.#n.forEach(t=>t(e)),this.#r.forEach(e=>e(`error`)),e}}async stopListening(){this.#e&&=(this.#e.stop(),null),this.#i=!1,this.#r.forEach(e=>e(`idle`))}onResult(e){this.#t.push(e)}onError(e){this.#n.push(e)}onStatusChange(e){this.#r.push(e)}async disconnect(){await this.stopListening(),this.#r.forEach(e=>e(`disconnected`))}static isSupported(){return`SpeechRecognition`in window||`webkitSpeechRecognition`in window}}}));function L(e){switch(e.type){case`runtype`:if(!e.runtype)throw Error(`Runtype voice provider requires configuration`);return new F(e.runtype);case`browser`:if(!I.isSupported())throw Error(`Browser speech recognition not supported`);return new I(e.browser||{});case`custom`:{let t=e.custom;if(!t)throw Error("Custom voice provider requires a `custom` provider instance or factory");let n=typeof t==`function`?t():t;if(!n||typeof n.startListening!=`function`)throw Error("Custom voice provider `custom` must be a VoiceProvider (or a factory returning one)");return n}default:throw Error(`Unknown voice provider type: ${e.type}`)}}function R(e){if(e?.type===`custom`&&e.custom)return L({type:`custom`,custom:e.custom});if(e?.type===`runtype`&&e.runtype)return L({type:`runtype`,runtype:e.runtype});if(I.isSupported())return L({type:`browser`,browser:e?.browser||{language:`en-US`}});throw Error(`No supported voice providers available`)}function re(e){try{return R(e),!0}catch{return!1}}var ie=e((()=>{te(),ne()})),z,ae,oe=e((()=>{z=e=>e.toLowerCase().replace(/[^\p{L}\p{N}]+/gu,``),ae=class{constructor(e){this.host=e,this.turns=/* @__PURE__ */ new Map,this.latestId=null,this.cancelled=/* @__PURE__ */ new Set}apply(e,t,n,r,i,a){let o=this.host;t=t.trim();let s=this.turns.get(r);if(s||(s={},this.turns.set(r,s),this.latestId=r),e===`user`){s.userFinal=n;let e=s.userId?o.find(s.userId):void 0;if(e){let r=s.userStartMs===void 0&&i!==void 0;r&&(s.userStartMs=i),o.upsert({...e,content:t,voiceProcessing:!n,...r&&this.placeBefore(this.startedAfter(i))})}else{s.userStartMs=i;let e=s.assistantId?o.find(s.assistantId):void 0;s.userId=o.inject({role:`user`,content:t,streaming:!1,voiceProcessing:!n,voiceCaption:a,...this.placeBefore(this.startedAfter(i)??e)}).id}}else if(!this.cancelled.has(r)){s.assistantFinal=n;let e=s.assistantId?o.find(s.assistantId):void 0;if(e){let r=s.assistantStartMs===void 0&&i!==void 0;r&&(s.assistantStartMs=i),o.upsert({...e,content:t,streaming:!n,voiceProcessing:!n,...r&&this.placeBefore(this.startedAfter(i))})}else t&&(s.assistantStartMs=i,s.assistantId=o.inject({role:`assistant`,content:t,streaming:!n,voiceProcessing:!n,voiceCaption:a,...this.placeBefore(this.startedAfter(i))}).id);n&&s.assistantId&&o.markSpoken(s.assistantId)}this.sync()}claimUserTurn(e,t=[]){let n=t[t.length-1];for(let e of t)e!==n&&(this.turns.has(e)||this.turns.set(e,{}),this.turns.get(e).claimed=!0);let r;if(n){if(r=this.turns.get(n),r||(r={},this.turns.set(n,r)),r.claimed)return null;(!r.userId||!this.host.find(r.userId))&&(r.userFinal=!0,r.userId=this.host.inject({role:`user`,content:e.trim()}).id)}else{let t=z(e),n=[...this.turns.values()].reverse().flatMap(e=>{let t=e.userId&&!e.claimed?this.host.find(e.userId):void 0;return t?[{turn:e,text:z(t.content)}]:[]}).filter(({text:e})=>e&&t);r=(n.find(({text:e})=>e===t)??n.find(({text:e})=>e.startsWith(t)||t.startsWith(e)))?.turn}return r?(r.claimed=!0,r.userId):null}cancel(){let e=this.inFlight();if(e.length===0){let t=this.awaiting();if(!t)return;e=[t]}for(let t of e)this.cancelled.add(t);this.closeReplies(e),this.sync()}fail(e){let t=this.awaiting(),n=this.inFlight();if(!t&&n.length===0)return;for(let e of n)this.turns.get(e).assistantFinal=!0;this.closeReplies(n);let r=this.host.inject({role:`assistant`,content:e,streaming:!1,voiceProcessing:!1}),i=t?this.turns.get(t):void 0;i&&(i.assistantId=r.id,i.assistantFinal=!0),this.sync()}settle(){if(this.turns.size===0)return;let e=this.pending(),t=/* @__PURE__ */ new Set;for(let e of this.turns.values())e.userId&&t.add(e.userId),e.assistantId&&(t.add(e.assistantId),this.host.markSpoken(e.assistantId));this.turns.clear(),this.latestId=null,this.host.settle(t),e&&this.host.setStreaming(!1)}startedAfter(e){if(e===void 0)return;let t;for(let n of this.turns.values())for(let[r,i]of[[n.userId,n.userStartMs],[n.assistantId,n.assistantStartMs]])r&&i!==void 0&&i>e&&(!t||i<t.start)&&(t={start:i,id:r});return t&&this.host.find(t.id)}placeBefore(e){if(!e)return;let t=e.sequence??0,n=t-1;for(let r of this.turns.values())for(let i of[r.userId,r.assistantId]){let r=i?this.host.find(i):void 0,a=r?.sequence;r?.createdAt===e.createdAt&&a!==void 0&&a>n&&a<t&&(n=a)}return{createdAt:e.createdAt,sequence:(n+t)/2}}closeReplies(e){let t=/* @__PURE__ */ new Set;for(let n of e){let e=this.turns.get(n)?.assistantId;e&&(t.add(e),this.host.markSpoken(e))}t.size>0&&this.host.settle(t)}inFlight(){let e=[];for(let[t,n]of this.turns)n.assistantId&&!n.assistantFinal&&!this.cancelled.has(t)&&e.push(t);return e}awaiting(){let e=this.latestId;if(!e)return null;let t=this.turns.get(e);return t?.userFinal&&!t.assistantId&&!t.claimed&&!this.cancelled.has(e)?e:null}pending(){return this.awaiting()!==null||this.inFlight().length>0}sync(){this.host.setStreaming(this.pending())}}}));function se(e){let t=/(\S+)$/.exec(e)?.[1];if(!t)return!1;let n=t.replace(/^[("'“‘[*_]+/,``).toLowerCase();if(G.has(n)||/^[a-z](?:\.[a-z])*$/.test(n))return!0;if(/^\d+$/.test(t)){let n=e.length-t.length;return n===0||/\n\s*$/.test(e.slice(0,n))}return!1}function*B(e,t){let n=new RegExp(K.source,`g`);for(let r=n.exec(e);r;r=n.exec(e)){let n=r[1];if(!e.slice(0,r.index+(n?.length??0)).trim()||n!==void 0&&(/^[,;:]$/.test(n)&&!t||n===`.`&&se(e.slice(0,r.index))))continue;let i=r.index+r[0].length;i<e.length&&(yield i)}}function V(e,t){let n=e.slice(0,t),r=0;for(let e of n.matchAll(/\s+/g))n.slice(0,e.index).trim()&&(r=e.index+e[0].length);return r}function H(e){let t=0;for(let n of B(e.slice(0,220),!0))t=n;if(t)return t;let n=V(e,220);if(n)return n;let r=e.charCodeAt(219);return r>=55296&&r<=56319?219:220}var U,W,G,K,ce,le=e((()=>{U=30,W=6,G=/* @__PURE__ */ new Set(/* @__PURE__ */ `mr,mrs,ms,dr,prof,sr,jr,st,mt,vs,etc,approx,inc,ltd,co,corp,no,nos,fig,ft,dept,est,min,max,e.g,i.e,a.m,p.m,u.s,u.k`.split(`,`)),K=/([.!?]+|[,;:])(["'”’)\]*_]*)(\s+)|\n\s*/g,ce=class{#e=``;#t=!0;push(e){return this.#e+=e,this.#n()}flush(){let e=this.#n(),t=this.#e;if(this.#e=``,t.trim()){for(let n=0;n<t.length;){let r=t.slice(n),i=r.length>220?H(r):r.length;e.push(r.slice(0,i)),n+=i}this.#t=!1}return e}idle(){let e=this.#e;if(!e.trim()||!/(?:[.!?…]["'”’)\]*_]*|\n)\s*$/.test(e))return[];this.#e=``,this.#t=!1;let t=[];for(let n=0;n<e.length;){let r=e.slice(n),i=r.length>220?H(r):r.length;t.push(r.slice(0,i)),n+=i}return t}#n(){let e=[];for(let t=this.#r();t>0;t=this.#r())e.push(this.#e.slice(0,t)),this.#e=this.#e.slice(t),this.#t=!1;return e}#r(){let e=this.#e;if(!e.trim())return 0;let t=B(e,this.#t).next().value??0;if(t&&t<=220)return t;let n=/[.!?]["'”’)\]*_]*$/.test(e);if(this.#t&&!n){let t=e.match(/\S+\s+/g)?.length??0;if(e.trim().length>=U||t>=W){let t=V(e,220);if(t)return t}}return e.length>220?H(e):0}}}));function q(e,t=0){if(e==null||e===``)return``;if(typeof e!=`object`)return String(e);if(t>2)return``;if(Array.isArray(e))return e.map(e=>q(e,t+1)).filter(Boolean).join(`, `);let n=e,r=n.quantity??n.qty??n.count,i=n.name??n.item??n.product??n.title;return r!=null&&i!=null&&typeof i!=`object`?`${r} ${i}`:Object.entries(n).filter(([e])=>!e.startsWith(`_`)).map(([e,n])=>{let r=q(n,t+1);return r&&(t?`${Q(e)} ${r}`:`${Q(e)}: ${r}`)}).filter(Boolean).join(t?`, `:`; `)}function ue(e){let t=e.length>1?`These actions need the user's approval in the chat before they happen:`:`This action needs the user's approval in the chat before it happens:`,n=ge-t.length-119-2;return`${t}\n${e.map(t=>{let r=[Q(t.toolName)];t.description&&r.push(`(${Z(t.description.trim(),160)})`);let i=q(t.parameters);return i&&r.push(`with ${i}`),t.reason&&r.push(`because: ${Z(t.reason.trim(),160)}`),Z(`- ${r.join(` `)}`,Math.floor(n/e.length)-1)}).join(`
5
5
  `)}\n\n${ye}`}function de(e){let t=null,n=null,r=()=>e.track(t??n),i=[],a=/* @__PURE__ */ new Map,o=/* @__PURE__ */ new Map,s=(e,t)=>{a.set(e,[...a.get(e)??[],t]),a.size>32&&a.delete(a.keys().next().value)},c=t=>e.messages().find(e=>e.id===t),l=e=>e.approvals.filter(e=>c(e)?.approval?.status===`pending`),u=e=>Q(c(e)?.approval?.toolName??``),d=(t,n,r)=>{t.outcome={status:n,text:r};for(let n of l(t))e.decide(n)},f=t=>t.flatMap(t=>e.messages().find(e=>e.id===t)??[]).filter(e=>!e.variant&&e.content.trim()).map(e=>e.content.trim()).join(`
6
6
 
7
- `),p=async t=>{do await X();while(e.busy()&&!(t&&(e.parked()||t.failed)))};return{getHistory:()=>{let t=e.messages().filter(e=>(e.role===`user`||e.role===`assistant`)&&!e.variant&&!e.voiceProcessing&&!e.streaming&&e.content),n=!1,r=[];for(let e=t.length-1;e>=0;--e){let i=t[e];if(i.role===`user`)n=!1;else if(!i.voiceCaption)n=!0;else if(n)continue;r.unshift({role:i.role,content:i.content})}return r},dropDelegation(t,n){o.set(t,!!n),o.size>32&&o.delete(o.keys().next().value);let r=n&&i.find(e=>e.delegationId===t);r&&!r.outcome&&d(r,`timeout`,``);for(let n of a.get(t)??[])n.stopStream?.(),n.dropped=!0,n.ids.length&&e.unspoken(n.ids)},async runDelegatedTurn({delegationId:m,userText:h,userUtteranceIds:g,stream:_}){let v=i.filter(e=>l(e).length),y=v.flatMap(l);if(y.length===1&&Y(h)){let e=u(y[0]);return d(v[0],`denied`,``),{status:`denied`,text:`Okay, I cancelled the ${e} request. Nothing was done.`,inChat:!1}}let b=e.parked()&&e.messages().every(e=>!$(e)||y.includes(e.id));e.busy()&&!b&&await p();let x=new Set(e.messages().map(e=>e.id)),S=()=>e.messages().filter(e=>!x.has(e.id)&&e.variant===`approval`),C={ids:[],failed:!1},w=_?new ce:null,T=``,E=``,D=!1,O=e=>{for(let t of e)E+=t,_(t)},k;w&&(C.onUpdate=()=>{if(D)return;let e=f(C.ids);if(!e.startsWith(T)){D=!0,clearTimeout(k);return}if(e.length===T.length)return;let t=e.slice(T.length);T=e,O(w.push(t)),clearTimeout(k),k=setTimeout(()=>{D||O(w.idle())},fe)},C.stopStream=()=>{clearTimeout(k),D=!0,C.onUpdate=void 0}),s(m,C),t=C,r();try{await e.send(h,e.claim(h,g)??void 0),await p(C)}catch{C.failed=!0}finally{t=null,r()}w&&(C.onUpdate?.(),clearTimeout(k),D||O(w.flush()),C.onUpdate=void 0,C.stopStream=void 0);let A=e=>{let t=pe(E,e);return t>0?{streamedChars:t}:{}},j=C.ids.flatMap(t=>e.messages().find(e=>e.id===t)??[]),M=f(C.ids),N=C.failed?[]:S().filter($),P=new Set(N.map(e=>Q(e.approval.toolName)));for(let t of v){if(t.outcome)continue;for(let n of l(t).filter(e=>P.has(u(e))))t.replaced.add(n),e.decide(n);let n=u(t.approvals[0]);(t.approvals.every(e=>t.replaced.has(e))||b&&t.approvals.every(e=>c(e)?.approval?.status===`denied`))&&(t.outcome={status:`cancelled`,text:`The earlier ${n} request was replaced by the new one; it was not done.`})}if(N.length){let c=new Set(N.map(e=>e.id)),p={delegationId:m,approvals:[...c],at:Date.now(),replaced:/* @__PURE__ */ new Set};return i.push(p),o.get(m)&&d(p,`timeout`,``),M=`${M}\n\n${ue(N.map(e=>e.approval))}`.trim(),{status:`pending_approval`,text:M,...A(M),followUp:async({signal:o,approvalTimeoutMs:h=_e,readBack:g=!0,onUpdate:_})=>{let v={ids:[],failed:!1};a.delete(m),s(m,v);let y=()=>S().filter(e=>c.has(e.id)||v.ids.includes(e.id)),b=()=>S().filter(e=>$(e)&&!c.has(e.id)&&!i.some(t=>t.approvals.includes(e.id))&&(v.ids.includes(e.id)||e.approval?.toolType===`webmcp`&&n===v)),x=()=>{n=v,r()};g&&x();try{for(;!o.aborted&&!p.outcome&&(t||e.busy()||y().some($));){g&&n!==v&&!l(p).length&&x();let t=b();if(t.length){for(let e of t)c.add(e.id),p.approvals.push(e.id);p.at=Date.now(),_?.(ue(t.map(e=>e.approval)))}if(Date.now()-p.at>=h&&l(p).length&&(!e.busy()||e.parked())){d(p,`timeout`,`That ${u(p.approvals[0])} request expired, so nothing was done.`);break}await X()}}finally{n===v&&(n=null,r()),i.splice(i.indexOf(p),1)}if(o.aborted)return null;if(p.outcome)return p.outcome;if(v.failed)return{status:`failed`,text:`The ${u(p.approvals[0])} request didn't complete.`};let C=y(),w=e=>C.filter(e).map(e=>Q(e.approval.toolName)).join(`, `),T=C.some(e=>e.approval?.status===`approved`),E=w(e=>e.approval?.status===`denied`&&!p.replaced.has(e.id)),D=w(e=>p.replaced.has(e.id)),O=w(e=>e.approval?.status===`timeout`),k=[T?f(v.ids):``,E&&`The user declined the ${E} request in the chat, so ${T?`that part was not done`:`nothing was done`}.`,D&&`The earlier ${D} request was replaced by the new one; it was not done.`,O&&`The ${O} request timed out, so it was not done.`].filter(Boolean).join(`
7
+ `),p=async t=>{do await X();while(e.busy()&&!(t&&(e.parked()||t.failed)))};return{clientTools:e.clientTools,recordDirectTurn:e.recordDirect,getHistory:()=>{let t=e.messages().filter(e=>(e.role===`user`||e.role===`assistant`)&&!e.variant&&!e.voiceProcessing&&!e.streaming&&e.content),n=!1,r=[];for(let e=t.length-1;e>=0;--e){let i=t[e];if(i.role===`user`)n=!1;else if(!i.voiceCaption)n=!0;else if(n)continue;r.unshift({role:i.role,content:i.content})}return r},dropDelegation(t,n){o.set(t,!!n),o.size>32&&o.delete(o.keys().next().value);let r=n&&i.find(e=>e.delegationId===t);r&&!r.outcome&&d(r,`timeout`,``);for(let n of a.get(t)??[])n.stopStream?.(),n.dropped=!0,n.ids.length&&e.unspoken(n.ids)},async runDelegatedTurn({delegationId:m,userText:h,userUtteranceIds:g,stream:_}){let v=i.filter(e=>l(e).length),y=v.flatMap(l);if(y.length===1&&Y(h)){let e=u(y[0]);return d(v[0],`denied`,``),{status:`denied`,text:`Okay, I cancelled the ${e} request. Nothing was done.`,inChat:!1}}let b=e.parked()&&e.messages().every(e=>!$(e)||y.includes(e.id));e.busy()&&!b&&await p();let x=new Set(e.messages().map(e=>e.id)),S=()=>e.messages().filter(e=>!x.has(e.id)&&e.variant===`approval`),C={ids:[],failed:!1},w=_?new ce:null,T=``,E=``,D=!1,O=e=>{for(let t of e)E+=t,_(t)},k;w&&(C.onUpdate=()=>{if(D)return;let e=f(C.ids);if(!e.startsWith(T)){D=!0,clearTimeout(k);return}if(e.length===T.length)return;let t=e.slice(T.length);T=e,O(w.push(t)),clearTimeout(k),k=setTimeout(()=>{D||O(w.idle())},fe)},C.stopStream=()=>{clearTimeout(k),D=!0,C.onUpdate=void 0}),s(m,C),t=C,r();try{await e.send(h,e.claim(h,g)??void 0),await p(C)}catch{C.failed=!0}finally{t=null,r()}w&&(C.onUpdate?.(),clearTimeout(k),D||O(w.flush()),C.onUpdate=void 0,C.stopStream=void 0);let A=e=>{let t=pe(E,e);return t>0?{streamedChars:t}:{}},j=C.ids.flatMap(t=>e.messages().find(e=>e.id===t)??[]),M=f(C.ids),N=C.failed?[]:S().filter($),P=new Set(N.map(e=>Q(e.approval.toolName)));for(let t of v){if(t.outcome)continue;for(let n of l(t).filter(e=>P.has(u(e))))t.replaced.add(n),e.decide(n);let n=u(t.approvals[0]);(t.approvals.every(e=>t.replaced.has(e))||b&&t.approvals.every(e=>c(e)?.approval?.status===`denied`))&&(t.outcome={status:`cancelled`,text:`The earlier ${n} request was replaced by the new one; it was not done.`})}if(N.length){let c=new Set(N.map(e=>e.id)),p={delegationId:m,approvals:[...c],at:Date.now(),replaced:/* @__PURE__ */ new Set};return i.push(p),o.get(m)&&d(p,`timeout`,``),M=`${M}\n\n${ue(N.map(e=>e.approval))}`.trim(),{status:`pending_approval`,text:M,...A(M),followUp:async({signal:o,approvalTimeoutMs:h=_e,readBack:g=!0,onUpdate:_})=>{let v={ids:[],failed:!1};a.delete(m),s(m,v);let y=()=>S().filter(e=>c.has(e.id)||v.ids.includes(e.id)),b=()=>S().filter(e=>$(e)&&!c.has(e.id)&&!i.some(t=>t.approvals.includes(e.id))&&(v.ids.includes(e.id)||e.approval?.toolType===`webmcp`&&n===v)),x=()=>{n=v,r()};g&&x();try{for(;!o.aborted&&!p.outcome&&(t||e.busy()||y().some($));){g&&n!==v&&!l(p).length&&x();let t=b();if(t.length){for(let e of t)c.add(e.id),p.approvals.push(e.id);p.at=Date.now(),_?.(ue(t.map(e=>e.approval)))}if(Date.now()-p.at>=h&&l(p).length&&(!e.busy()||e.parked())){d(p,`timeout`,`That ${u(p.approvals[0])} request expired, so nothing was done.`);break}await X()}}finally{n===v&&(n=null,r()),i.splice(i.indexOf(p),1)}if(o.aborted)return null;if(p.outcome)return p.outcome;if(v.failed)return{status:`failed`,text:`The ${u(p.approvals[0])} request didn't complete.`};let C=y(),w=e=>C.filter(e).map(e=>Q(e.approval.toolName)).join(`, `),T=C.some(e=>e.approval?.status===`approved`),E=w(e=>e.approval?.status===`denied`&&!p.replaced.has(e.id)),D=w(e=>p.replaced.has(e.id)),O=w(e=>e.approval?.status===`timeout`),k=[T?f(v.ids):``,E&&`The user declined the ${E} request in the chat, so ${T?`that part was not done`:`nothing was done`}.`,D&&`The earlier ${D} request was replaced by the new one; it was not done.`,O&&`The ${O} request timed out, so it was not done.`].filter(Boolean).join(`
8
8
 
9
- `);return{status:T?`completed`:E?`denied`:D?`cancelled`:O?`timeout`:`completed`,text:k}}}}return!C.failed&&e.parked()||j.some(e=>e.agentMetadata?.awaitingLocalTool&&!e.agentMetadata.askUserQuestionAnswered&&!e.toolCall?.name?.startsWith(`webmcp:`))?(M=`${M}\n\n${he}`.trim(),{status:C.failed?`failed`:`completed`,text:M,...A(M)}):{status:!C.failed&&M?`completed`:`failed`,text:M,...A(M)}}}}var fe,pe,me,he,ge,_e,J,ve,Y,ye,X,Z,Q,$,be=e((()=>{le(),fe=200,pe=(e,t)=>{let n=0;for(;n<e.length&&n<t.length&&e[n]===t[n];)n+=1;return n},me=50,he=`I need your answer in the chat before I can continue.`,ge=1e3,_e=3e5,J=`no|nope|never ?mind|decline(?: it| that)?|cancel(?: it| that| this)?(?: (?:the|my|that|this) (?:[a-z]+ )?(?:order|request))?|don'?t (?:do|place) (?:it|that|the (?:[a-z]+ )?order)`,ve=RegExp(`^(?:${J})(?: (?:${J}))?(?: thanks| thank you)?$`),Y=e=>ve.test(e.toLowerCase().replace(/[^a-z' ]+/g,` `).replace(/\s+/g,` `).trim()),ye=`Briefly tell the user what you're about to do and ask them to approve or decline it in the chat. Don't claim it's done.`,X=()=>new Promise(e=>setTimeout(e,me)),Z=(e,t)=>e.length>t?`${e.slice(0,t-1).trimEnd()}…`:e,Q=e=>e.replace(/^webmcp:/,``).replace(/([a-z\d])([A-Z])/g,`$1 $2`).replace(/[_\-.]+/g,` `).trim().toLowerCase(),$=e=>e.variant===`approval`&&e.approval?.status===`pending`})),xe,Se=e((()=>{xe=(e,t,n,r)=>{let i=e.session;try{e.keyed=n?new n({find:e=>i.messages.find(t=>t.id===e),inject:e=>i.injectMessage(e),upsert:e=>i.upsertMessage(e),settle:e=>{i.messages=i.messages.map(t=>e.has(t.id)?{...t,streaming:!1,voiceProcessing:!1}:t),i.callbacks.onMessagesChanged([...i.messages])},setStreaming:t=>{(t||!e.busy())&&e.setStreaming(t)},markSpoken:e=>{i.ttsSpokenMessageIds.add(e)}}):null,r&&t.setSessionBridge&&t.setSessionBridge(r({messages:()=>i.messages,busy:()=>e.busy(),parked:()=>i.webMcpApprovalResolvers.size>0,claim:(t,n)=>e.keyed?.claimUserTurn(t,n)??null,send:(e,t)=>i.sendMessage(e,{viaVoice:!0,voiceTurn:{userMessageId:t}}),track:t=>{e.setDelegation(t)},unspoken:e=>{for(let t of e)i.ttsSpokenMessageIds.delete(t);i.streaming||i.speakLatestAssistantMessage(e)},decide:e=>{if(i.webMcpApprovalResolvers.has(e))return i.resolveWebMcpApproval(e,`denied`);let t=i.messages.find(t=>t.id===e)?.approval;t?.status===`pending`&&i.resolveApproval(t,`denied`)}}));let a=e.generation(),o=()=>e.provider()===t&&a===e.generation(),s=(i.config.voiceRecognition??{}).processingErrorText??`Voice processing failed. Please try again.`;t.onResult(e=>{o()&&e.provider!==`runtype`&&e.text&&e.text.trim()&&i.sendMessage(e.text,{viaVoice:!0})}),t.onTranscript&&t.onTranscript((t,n,r,a)=>{if(o()){if(a?.turnId)e.keyed?.apply(t,n,r,a.turnId,a.startMs,a.caption);else if(t===`user`)e.pendingUser?i.upsertMessage({id:e.pendingUser,role:`user`,content:n,createdAt:(/* @__PURE__ */ new Date()).toISOString(),streaming:!1,voiceProcessing:!r}):e.pendingUser=i.injectMessage({role:`user`,content:n,streaming:!1,voiceProcessing:!r}).id,r&&(e.turns().start(a?.turnId),e.pendingUser=null,e.pendingAssistant=i.injectMessage({role:`assistant`,content:``,streaming:!0,voiceProcessing:!0}).id,e.setStreaming(!0));else{if(!e.turns().accepts(a?.turnId))return;e.pendingAssistant?i.upsertMessage({id:e.pendingAssistant,role:`assistant`,content:n,createdAt:(/* @__PURE__ */ new Date()).toISOString(),streaming:!r,voiceProcessing:!r}):e.pendingAssistant=i.injectMessage({role:`assistant`,content:n,streaming:!r,voiceProcessing:!r}).id,r&&(e.pendingAssistant&&i.ttsSpokenMessageIds.add(e.pendingAssistant),e.setStreaming(!1),e.pendingAssistant=null)}}}),t.onLevel&&t.onLevel(t=>{o()&&e.setLevel(Number.isFinite(t)?Math.max(0,Math.min(1,t)):0)}),t.onMetrics&&t.onMetrics(e=>{o()&&i.config.voiceRecognition?.onMetrics?.(e)}),t.onError(t=>{o()&&(console.error(`Voice error:`,t),e.pendingAssistant&&=(i.upsertMessage({id:e.pendingAssistant,role:`assistant`,content:s,createdAt:(/* @__PURE__ */ new Date()).toISOString(),streaming:!1,voiceProcessing:!1}),e.setStreaming(!1),e.pendingUser=null,null),e.keyed?.fail(s))}),t.onStatusChange(t=>{o()&&(e.setStatus(t),(t===`listening`||t===`idle`||t===`disconnected`)&&e.settlePending(t!==`listening`),(t===`idle`||t===`disconnected`)&&e.keyed?.settle(),i.callbacks.onVoiceStatusChanged?.(t))}),t.connect()}catch(e){console.error(`Failed to setup voice:`,e)}}})),Ce,we=e((()=>{Ce=e=>{let t=t=>{if(e.original)return;let n=e.config().voiceRecognition??{};e.original={backgroundColor:t.style.backgroundColor,color:t.style.color,borderColor:t.style.borderColor,iconName:n.iconName??`mic`,iconSize:parseFloat(n.iconSize??``)||e.iconFallbackPx}},n=(t,n,r)=>{let i=t.querySelector(`svg`);i&&i.remove();let a=e.original?.iconSize??(parseFloat(e.config().voiceRecognition?.iconSize??``)||e.iconFallbackPx),o=e.renderIcon(n,a,r,1.5);o&&t.appendChild(o)},r=e=>{e.classList.remove(`persona-voice-recording`,`persona-voice-processing`,`persona-voice-speaking`)};return{recording:()=>{let n=e.mic();if(!n)return;t(n);let i=e.config().voiceRecognition??{},a=i.recordingBackgroundColor,o=i.recordingIconColor,s=i.recordingBorderColor;if(r(n),n.classList.add(`persona-voice-recording`),e.setMicState(`recording`),n.style.backgroundColor=a??`var(--persona-voice-recording-bg, #ef4444)`,n.style.color=o??`var(--persona-voice-recording-indicator, #ffffff)`,o){let e=n.querySelector(`svg`);e&&e.setAttribute(`stroke`,o)}s&&(n.style.borderColor=s),n.setAttribute(`aria-label`,`Stop voice recognition`)},processing:()=>{let i=e.mic();if(!i)return;t(i);let a=e.config().voiceRecognition??{},o=e.session().getVoiceInterruptionMode(),s=e.original,c=a.processingIconName??`loader`,l=a.processingIconColor??s?.color??``,u=a.processingBackgroundColor??s?.backgroundColor??``,d=a.processingBorderColor??s?.borderColor??``;r(i),i.classList.add(`persona-voice-processing`),e.setMicState(`processing`),i.style.backgroundColor=u,i.style.borderColor=d;let f=l||`currentColor`;i.style.color=f,n(i,c,f),i.setAttribute(`aria-label`,`Processing voice input`),o===`none`&&(i.style.cursor=`default`)},speaking:()=>{let i=e.mic();if(!i)return;t(i);let a=e.config().voiceRecognition??{},o=e.session().getVoiceInterruptionMode(),s=e.original,c=o===`cancel`?`square`:o===`barge-in`?`mic`:`volume-2`,l=a.speakingIconName??c,u=a.speakingIconColor??(o===`barge-in`?a.recordingIconColor??s?.color??``:s?.color??``),d=a.speakingBackgroundColor??(o===`barge-in`?a.recordingBackgroundColor??`var(--persona-voice-recording-bg, #ef4444)`:s?.backgroundColor??``),f=a.speakingBorderColor??(o===`barge-in`?a.recordingBorderColor??``:s?.borderColor??``);r(i),i.classList.add(`persona-voice-speaking`),e.setMicState(`speaking`),i.style.backgroundColor=d,i.style.borderColor=f;let p=u||`currentColor`;i.style.color=p,n(i,l,p);let m=o===`cancel`?`Stop playback and re-record`:o===`barge-in`?`Speak to interrupt`:`Agent is speaking`;i.setAttribute(`aria-label`,m),o===`none`&&(i.style.cursor=`default`),o===`barge-in`&&i.classList.add(`persona-voice-recording`)},reset:()=>{let t=e.mic();if(!t)return;r(t),e.setMicState(`idle`);let i=e.original;i&&(t.style.backgroundColor=i.backgroundColor??``,t.style.color=i.color??``,t.style.borderColor=i.borderColor??``,n(t,i.iconName,i.color||`currentColor`),e.original=null),t.style.cursor=``,t.setAttribute(`aria-label`,`Start voice recognition`)}}}}));e((()=>{ie(),te(),ne(),oe(),be(),Se(),we()}))();export{I as BrowserVoiceProvider,ae as KeyedVoiceTranscript,F as RuntypeVoiceProvider,R as createBestAvailableVoiceProvider,Ce as createMicStateStyles,L as createVoiceProvider,de as createVoiceSessionBridge,re as isVoiceSupported,xe as wireSessionVoice};
9
+ `);return{status:T?`completed`:E?`denied`:D?`cancelled`:O?`timeout`:`completed`,text:k}}}}return!C.failed&&e.parked()||j.some(e=>e.agentMetadata?.awaitingLocalTool&&!e.agentMetadata.askUserQuestionAnswered&&!e.toolCall?.name?.startsWith(`webmcp:`))?(M=`${M}\n\n${he}`.trim(),{status:C.failed?`failed`:`completed`,text:M,...A(M)}):{status:!C.failed&&M?`completed`:`failed`,text:M,...A(M)}}}}var fe,pe,me,he,ge,_e,J,ve,Y,ye,X,Z,Q,$,be=e((()=>{le(),fe=200,pe=(e,t)=>{let n=0;for(;n<e.length&&n<t.length&&e[n]===t[n];)n+=1;return n},me=50,he=`I need your answer in the chat before I can continue.`,ge=1e3,_e=3e5,J=`no|nope|never ?mind|decline(?: it| that)?|cancel(?: it| that| this)?(?: (?:the|my|that|this) (?:[a-z]+ )?(?:order|request))?|don'?t (?:do|place) (?:it|that|the (?:[a-z]+ )?order)`,ve=RegExp(`^(?:${J})(?: (?:${J}))?(?: thanks| thank you)?$`),Y=e=>ve.test(e.toLowerCase().replace(/[^a-z' ]+/g,` `).replace(/\s+/g,` `).trim()),ye=`Briefly tell the user what you're about to do and ask them to approve or decline it in the chat. Don't claim it's done.`,X=()=>new Promise(e=>setTimeout(e,me)),Z=(e,t)=>e.length>t?`${e.slice(0,t-1).trimEnd()}…`:e,Q=e=>e.replace(/^webmcp:/,``).replace(/([a-z\d])([A-Z])/g,`$1 $2`).replace(/[_\-.]+/g,` `).trim().toLowerCase(),$=e=>e.variant===`approval`&&e.approval?.status===`pending`})),xe,Se=e((()=>{xe=(e,t,n,r)=>{let i=e.session;try{e.keyed=n?new n({find:e=>i.messages.find(t=>t.id===e),inject:e=>i.injectMessage(e),upsert:e=>i.upsertMessage(e),settle:e=>{i.messages=i.messages.map(t=>e.has(t.id)?{...t,streaming:!1,voiceProcessing:!1}:t),i.callbacks.onMessagesChanged([...i.messages])},setStreaming:t=>{(t||!e.busy())&&e.setStreaming(t)},markSpoken:e=>{i.ttsSpokenMessageIds.add(e)}}):null,r&&t.setSessionBridge&&t.setSessionBridge(r({messages:()=>i.messages,busy:()=>e.busy(),parked:()=>i.webMcpApprovalResolvers.size>0,claim:(t,n)=>e.keyed?.claimUserTurn(t,n)??null,send:(e,t)=>i.sendMessage(e,{viaVoice:!0,voiceTurn:{userMessageId:t}}),track:t=>{e.setDelegation(t)},unspoken:e=>{for(let t of e)i.ttsSpokenMessageIds.delete(t);i.streaming||i.speakLatestAssistantMessage(e)},clientTools:()=>i.getClient().getVoiceClientTools(),recordDirect:({delegationId:t,userText:n,userUtteranceIds:r,assistantText:a})=>{let o=e.keyed?.claimUserTurn(n,r),s=!1;i.messages=i.messages.map(e=>{if(e.id!==o||e.role!==`user`)return e;s=!0;let{voiceCaption:t,...n}=e;return{...n,viaVoice:!0}}),s?i.callbacks.onMessagesChanged([...i.messages]):n.trim()&&i.injectMessage({role:`user`,content:n.trim()});let c=a.trim();if(!c)return;let l=`voice-direct-${t}`;i.ttsSpokenMessageIds.add(l),i.injectMessage({id:l,role:`assistant`,content:c})},decide:e=>{if(i.webMcpApprovalResolvers.has(e))return i.resolveWebMcpApproval(e,`denied`);let t=i.messages.find(t=>t.id===e)?.approval;t?.status===`pending`&&i.resolveApproval(t,`denied`)}}));let a=e.generation(),o=()=>e.provider()===t&&a===e.generation(),s=(i.config.voiceRecognition??{}).processingErrorText??`Voice processing failed. Please try again.`;t.onResult(e=>{o()&&e.provider!==`runtype`&&e.text&&e.text.trim()&&i.sendMessage(e.text,{viaVoice:!0})}),t.onTranscript&&t.onTranscript((t,n,r,a)=>{if(o()){if(a?.turnId)e.keyed?.apply(t,n,r,a.turnId,a.startMs,a.caption);else if(t===`user`)e.pendingUser?i.upsertMessage({id:e.pendingUser,role:`user`,content:n,createdAt:(/* @__PURE__ */ new Date()).toISOString(),streaming:!1,voiceProcessing:!r}):e.pendingUser=i.injectMessage({role:`user`,content:n,streaming:!1,voiceProcessing:!r}).id,r&&(e.turns().start(a?.turnId),e.pendingUser=null,e.pendingAssistant=i.injectMessage({role:`assistant`,content:``,streaming:!0,voiceProcessing:!0}).id,e.setStreaming(!0));else{if(!e.turns().accepts(a?.turnId))return;e.pendingAssistant?i.upsertMessage({id:e.pendingAssistant,role:`assistant`,content:n,createdAt:(/* @__PURE__ */ new Date()).toISOString(),streaming:!r,voiceProcessing:!r}):e.pendingAssistant=i.injectMessage({role:`assistant`,content:n,streaming:!r,voiceProcessing:!r}).id,r&&(e.pendingAssistant&&i.ttsSpokenMessageIds.add(e.pendingAssistant),e.setStreaming(!1),e.pendingAssistant=null)}}}),t.onLevel&&t.onLevel(t=>{o()&&e.setLevel(Number.isFinite(t)?Math.max(0,Math.min(1,t)):0)}),t.onMetrics&&t.onMetrics(e=>{o()&&i.config.voiceRecognition?.onMetrics?.(e)}),t.onError(t=>{o()&&(console.error(`Voice error:`,t),e.pendingAssistant&&=(i.upsertMessage({id:e.pendingAssistant,role:`assistant`,content:s,createdAt:(/* @__PURE__ */ new Date()).toISOString(),streaming:!1,voiceProcessing:!1}),e.setStreaming(!1),e.pendingUser=null,null),e.keyed?.fail(s))}),t.onStatusChange(t=>{o()&&(e.setStatus(t),(t===`listening`||t===`idle`||t===`disconnected`)&&e.settlePending(t!==`listening`),(t===`idle`||t===`disconnected`)&&e.keyed?.settle(),i.callbacks.onVoiceStatusChanged?.(t))}),t.connect()}catch(e){console.error(`Failed to setup voice:`,e)}}})),Ce,we=e((()=>{Ce=e=>{let t=t=>{if(e.original)return;let n=e.config().voiceRecognition??{};e.original={backgroundColor:t.style.backgroundColor,color:t.style.color,borderColor:t.style.borderColor,iconName:n.iconName??`mic`,iconSize:parseFloat(n.iconSize??``)||e.iconFallbackPx}},n=(t,n,r)=>{let i=t.querySelector(`svg`);i&&i.remove();let a=e.original?.iconSize??(parseFloat(e.config().voiceRecognition?.iconSize??``)||e.iconFallbackPx),o=e.renderIcon(n,a,r,1.5);o&&t.appendChild(o)},r=e=>{e.classList.remove(`persona-voice-recording`,`persona-voice-processing`,`persona-voice-speaking`)};return{recording:()=>{let n=e.mic();if(!n)return;t(n);let i=e.config().voiceRecognition??{},a=i.recordingBackgroundColor,o=i.recordingIconColor,s=i.recordingBorderColor;if(r(n),n.classList.add(`persona-voice-recording`),e.setMicState(`recording`),n.style.backgroundColor=a??`var(--persona-voice-recording-bg, #ef4444)`,n.style.color=o??`var(--persona-voice-recording-indicator, #ffffff)`,o){let e=n.querySelector(`svg`);e&&e.setAttribute(`stroke`,o)}s&&(n.style.borderColor=s),n.setAttribute(`aria-label`,`Stop voice recognition`)},processing:()=>{let i=e.mic();if(!i)return;t(i);let a=e.config().voiceRecognition??{},o=e.session().getVoiceInterruptionMode(),s=e.original,c=a.processingIconName??`loader`,l=a.processingIconColor??s?.color??``,u=a.processingBackgroundColor??s?.backgroundColor??``,d=a.processingBorderColor??s?.borderColor??``;r(i),i.classList.add(`persona-voice-processing`),e.setMicState(`processing`),i.style.backgroundColor=u,i.style.borderColor=d;let f=l||`currentColor`;i.style.color=f,n(i,c,f),i.setAttribute(`aria-label`,`Processing voice input`),o===`none`&&(i.style.cursor=`default`)},speaking:()=>{let i=e.mic();if(!i)return;t(i);let a=e.config().voiceRecognition??{},o=e.session().getVoiceInterruptionMode(),s=e.original,c=o===`cancel`?`square`:o===`barge-in`?`mic`:`volume-2`,l=a.speakingIconName??c,u=a.speakingIconColor??(o===`barge-in`?a.recordingIconColor??s?.color??``:s?.color??``),d=a.speakingBackgroundColor??(o===`barge-in`?a.recordingBackgroundColor??`var(--persona-voice-recording-bg, #ef4444)`:s?.backgroundColor??``),f=a.speakingBorderColor??(o===`barge-in`?a.recordingBorderColor??``:s?.borderColor??``);r(i),i.classList.add(`persona-voice-speaking`),e.setMicState(`speaking`),i.style.backgroundColor=d,i.style.borderColor=f;let p=u||`currentColor`;i.style.color=p,n(i,l,p);let m=o===`cancel`?`Stop playback and re-record`:o===`barge-in`?`Speak to interrupt`:`Agent is speaking`;i.setAttribute(`aria-label`,m),o===`none`&&(i.style.cursor=`default`),o===`barge-in`&&i.classList.add(`persona-voice-recording`)},reset:()=>{let t=e.mic();if(!t)return;r(t),e.setMicState(`idle`);let i=e.original;i&&(t.style.backgroundColor=i.backgroundColor??``,t.style.color=i.color??``,t.style.borderColor=i.borderColor??``,n(t,i.iconName,i.color||`currentColor`),e.original=null),t.style.cursor=``,t.setAttribute(`aria-label`,`Start voice recognition`)}}}}));e((()=>{ie(),te(),ne(),oe(),be(),Se(),we()}))();export{I as BrowserVoiceProvider,ae as KeyedVoiceTranscript,F as RuntypeVoiceProvider,R as createBestAvailableVoiceProvider,Ce as createMicStateStyles,L as createVoiceProvider,de as createVoiceSessionBridge,re as isVoiceSupported,xe as wireSessionVoice};
@@ -1,5 +1,5 @@
1
- import { Nr as PcmStreamPlayer, ei as SpeechCallbacks, fi as VoicePlaybackEngine, ni as SpeechRequest, ti as SpeechEngine } from "./types-BdO1jNRm.cjs";
2
- import { n as FallbackSpeechEngineOptions, t as FallbackSpeechEngine } from "./fallback-speech-engine-C5_PUZjH.cjs";
1
+ import { Ci as VoicePlaybackEngine, Ir as PcmStreamPlayer, ai as SpeechRequest, ii as SpeechEngine, ri as SpeechCallbacks } from "./types-oAZ1VReS.cjs";
2
+ import { n as FallbackSpeechEngineOptions, t as FallbackSpeechEngine } from "./fallback-speech-engine-DJpJcWAk.cjs";
3
3
  //#region src/voice/worklet-playback-engine.d.ts
4
4
  interface PcmStreamPlayerOptions {
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { Nr as PcmStreamPlayer, ei as SpeechCallbacks, fi as VoicePlaybackEngine, ni as SpeechRequest, ti as SpeechEngine } from "./types-BdO1jNRm.js";
2
- import { n as FallbackSpeechEngineOptions, t as FallbackSpeechEngine } from "./fallback-speech-engine-C5_PUZjH.js";
1
+ import { Ci as VoicePlaybackEngine, Ir as PcmStreamPlayer, ai as SpeechRequest, ii as SpeechEngine, ri as SpeechCallbacks } from "./types-oAZ1VReS.js";
2
+ import { n as FallbackSpeechEngineOptions, t as FallbackSpeechEngine } from "./fallback-speech-engine-DJpJcWAk.js";
3
3
  //#region src/voice/worklet-playback-engine.d.ts
4
4
  interface PcmStreamPlayerOptions {
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { Tn as ClientToolDefinition, bi as WebMcpToolResult, sn as AgentWidgetWebMcpConfig, vi as WebMcpConfirmHandler } from "./types-BdO1jNRm.js";
1
+ import { En as ClientToolDefinition, ji as WebMcpToolResult, ki as WebMcpConfirmHandler, sn as AgentWidgetWebMcpConfig, ui as VoiceClientToolOutcome } from "./types-oAZ1VReS.cjs";
2
2
  //#region src/webmcp-bridge.d.ts
3
3
  /** Server-applied wire prefix; strip when looking up registry entries. */
4
4
  declare const WEBMCP_TOOL_PREFIX = "webmcp:";
@@ -42,10 +42,7 @@ interface ModelContextToolInfo {
42
42
  * absent on v4 and whenever the tool declared none -- the spec omits the
43
43
  * member rather than emitting an empty object.
44
44
  */
45
- annotations?: {
46
- readOnlyHint?: boolean;
47
- untrustedContentHint?: boolean;
48
- };
45
+ annotations?: ClientToolDefinition["annotations"];
49
46
  }
50
47
  /** The slice of `@mcp-b/webmcp-polyfill` the bridge consumes on install. */
51
48
  type WebMcpPolyfillModule = {
@@ -124,6 +121,30 @@ declare class WebMcpBridge {
124
121
  * from firing a host-page side effect with no matching `/resume`.
125
122
  */
126
123
  executeToolCall(wireToolName: string, args: unknown, signal?: AbortSignal): Promise<WebMcpToolResult>;
124
+ /**
125
+ * Execute a page tool the voice server picked for a delegation
126
+ * (`client_tool_call`) and return its `client_tool_result` outcome.
127
+ *
128
+ * Same registry lookup, allowlist, abort points and timeout as
129
+ * `executeToolCall`, with one difference: when `autoConfirmReadOnly` is set,
130
+ * a tool whose LIVE registry entry declares `annotations.readOnlyHint ===
131
+ * true` skips the confirm gate. Every other tool still shows it, and a
132
+ * decline answers `denied`. A tool missing from the registry or excluded by
133
+ * the allowlist answers `stale` (the server's snapshot is out of date).
134
+ * `signal` aborting (the caller's deadline, a hang-up) answers `failed`;
135
+ * the caller decides whether that was its timeout.
136
+ */
137
+ executeVoiceToolCall(wireToolName: string, args: unknown, options?: {
138
+ signal?: AbortSignal;
139
+ autoConfirmReadOnly?: boolean;
140
+ }): Promise<VoiceClientToolOutcome>;
141
+ /**
142
+ * Call `listener` whenever the page's tool registry changes (the WebMCP
143
+ * `toolchange` event on `document.modelContext`). Returns an unsubscribe.
144
+ * A registry without the event never calls it: callers then keep the
145
+ * snapshot they took first.
146
+ */
147
+ watchToolChanges(listener: () => void): () => void;
127
148
  }
128
149
  //#endregion
129
150
  export { stripWebMcpPrefix as a, isWebMcpToolName as i, WebMcpBridgeDeps as n, WEBMCP_TOOL_PREFIX as r, WebMcpBridge as t };
@@ -1,4 +1,4 @@
1
- import { Tn as ClientToolDefinition, bi as WebMcpToolResult, sn as AgentWidgetWebMcpConfig, vi as WebMcpConfirmHandler } from "./types-BdO1jNRm.cjs";
1
+ import { En as ClientToolDefinition, ji as WebMcpToolResult, ki as WebMcpConfirmHandler, sn as AgentWidgetWebMcpConfig, ui as VoiceClientToolOutcome } from "./types-oAZ1VReS.js";
2
2
  //#region src/webmcp-bridge.d.ts
3
3
  /** Server-applied wire prefix; strip when looking up registry entries. */
4
4
  declare const WEBMCP_TOOL_PREFIX = "webmcp:";
@@ -42,10 +42,7 @@ interface ModelContextToolInfo {
42
42
  * absent on v4 and whenever the tool declared none -- the spec omits the
43
43
  * member rather than emitting an empty object.
44
44
  */
45
- annotations?: {
46
- readOnlyHint?: boolean;
47
- untrustedContentHint?: boolean;
48
- };
45
+ annotations?: ClientToolDefinition["annotations"];
49
46
  }
50
47
  /** The slice of `@mcp-b/webmcp-polyfill` the bridge consumes on install. */
51
48
  type WebMcpPolyfillModule = {
@@ -124,6 +121,30 @@ declare class WebMcpBridge {
124
121
  * from firing a host-page side effect with no matching `/resume`.
125
122
  */
126
123
  executeToolCall(wireToolName: string, args: unknown, signal?: AbortSignal): Promise<WebMcpToolResult>;
124
+ /**
125
+ * Execute a page tool the voice server picked for a delegation
126
+ * (`client_tool_call`) and return its `client_tool_result` outcome.
127
+ *
128
+ * Same registry lookup, allowlist, abort points and timeout as
129
+ * `executeToolCall`, with one difference: when `autoConfirmReadOnly` is set,
130
+ * a tool whose LIVE registry entry declares `annotations.readOnlyHint ===
131
+ * true` skips the confirm gate. Every other tool still shows it, and a
132
+ * decline answers `denied`. A tool missing from the registry or excluded by
133
+ * the allowlist answers `stale` (the server's snapshot is out of date).
134
+ * `signal` aborting (the caller's deadline, a hang-up) answers `failed`;
135
+ * the caller decides whether that was its timeout.
136
+ */
137
+ executeVoiceToolCall(wireToolName: string, args: unknown, options?: {
138
+ signal?: AbortSignal;
139
+ autoConfirmReadOnly?: boolean;
140
+ }): Promise<VoiceClientToolOutcome>;
141
+ /**
142
+ * Call `listener` whenever the page's tool registry changes (the WebMCP
143
+ * `toolchange` event on `document.modelContext`). Returns an unsubscribe.
144
+ * A registry without the event never calls it: callers then keep the
145
+ * snapshot they took first.
146
+ */
147
+ watchToolChanges(listener: () => void): () => void;
127
148
  }
128
149
  //#endregion
129
150
  export { stripWebMcpPrefix as a, isWebMcpToolName as i, WebMcpBridgeDeps as n, WEBMCP_TOOL_PREFIX as r, WebMcpBridge as t };
@@ -1 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=e=>e.startsWith(`webmcp:`)?e.slice(7):e,t={warn(e,...t){typeof console<`u`&&typeof console.warn==`function`&&console.warn(`[Persona/WebMCP] ${e}`,...t)}};var n=class{#e;#t;#n=!1;#r=null;#i=!1;#a;constructor(e,t){this.config=e,this.#a=t,this.#e=e.onConfirm??null,this.#t=3e4}setConfirmHandler(e){this.#e=e}isOperational(){return this.config.enabled!==!0||!this.#n?!1:this.#c()!==null}async snapshotForDispatch(){if(await this.#o(),this.config.enabled!==!0)return[];let e=this.#c();if(!e)return[];let n;try{n=(await e.getTools()).filter(f)}catch(e){return t.warn(`getTools() threw: shipping an empty WebMCP snapshot.`,e),[]}this.#a.recordToolDisplayTitles(n);let r=typeof location<`u`?location.origin:``;return n.filter(e=>this.#u(e.name)).map(e=>{let t=a(e.annotations);return{name:e.name,description:e.description,parametersSchema:o(e.inputSchema),origin:`webmcp`,...r?{pageOrigin:r}:{},...t?{annotations:t}:{},...t?.untrustedContentHint===!0?{untrustedContentHint:!0}:{}}})}async executeToolCall(t,n,r){if(await this.#o(),this.config.enabled!==!0)return l(`WebMCP is not enabled on this widget.`);let i=this.#c();if(!i){let e=typeof document<`u`&&!!document.modelContext;return l(e?`WebMCP is not operational: document.modelContext is present but does not expose the strict getTools()/executeTool() surface (likely a different or older WebMCP polyfill).`:`WebMCP bridge is not operational on this page (document.modelContext not available).`)}let a=e(t),o;try{o=(await i.getTools()).filter(f)}catch(e){let t=e instanceof Error?e.message:String(e);return l(`Failed to read WebMCP registry: ${t}`)}this.#a.recordToolDisplayTitles(o);let u=o.find(e=>e.name===a);if(!u)return l(`WebMCP tool not registered on this page: ${a}`);if(!this.#u(a))return l(`WebMCP tool not allowed by client allowlist: ${a}`);if(r?.aborted)return l(`Aborted by cancel()`);let d=this.#a.getToolDisplayTitle(a),p={toolName:a,args:n,description:u.description,...d?{title:d}:{},reason:`gate`};if(!await this.#l(p))return l(`User declined the tool call.`);if(r?.aborted)return l(`Aborted by cancel()`);let m=new AbortController,h=!1,g=setTimeout(()=>{h=!0,m.abort()},this.#t),_=()=>m.abort();r&&(r.aborted?m.abort():r.addEventListener(`abort`,_,{once:!0}));try{let e=await i.executeTool(u,c(n),{signal:m.signal});return s(e)}catch(e){if(h)return l(`WebMCP tool '${a}' timed out after ${this.#t}ms`);if(r?.aborted)return l(`Aborted by cancel()`);let t=e instanceof Error?e.message:String(e);return l(t)}finally{clearTimeout(g),r&&r.removeEventListener(`abort`,_)}}#o(){return this.config.enabled===!0?(this.#r||=this.#s(),this.#r):Promise.resolve()}async#s(){try{if(this.#c()){this.#n=!0;return}let e=await this.#a.loadPolyfill();`initializeWebMCPPolyfill`in e?e.initializeWebMCPPolyfill():e.installWebMCP(),this.#n=!0}catch(e){t.warn(`Failed to load @mcp-b/webmcp-polyfill: WebMCP consumption disabled.`,e),this.#n=!1}}#c(){if(typeof document>`u`)return null;let e=document.modelContext;if(!e||typeof e!=`object`)return null;let n=e;return typeof n.getTools!=`function`||typeof n.executeTool!=`function`?(this.#i||(this.#i=!0,t.warn(`document.modelContext is present but does not expose getTools()/executeTool(): WebMCP consumption is disabled. Another (incompatible or older) WebMCP polyfill likely installed document.modelContext before Persona. Remove it, or use a polyfill implementing the strict standard surface (e.g. @mcp-b/webmcp-polyfill).`)),null):e}async#l(e){let n=this.#e??u;try{return await n(e)}catch(n){return t.warn(`Confirm handler threw for WebMCP tool '${e.toolName}'; declining.`,n),!1}}#u(e){let t=this.config.allowlist;return!t||t.length===0||t.some(t=>r(e,t))}};const r=(e,t)=>{if(t===`*`)return!0;let n=t.replace(/[.+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`^`+n.replace(/\*/g,`.*`)+`$`).test(e)},i={type:`object`,properties:{}},a=e=>{if(!e||typeof e!=`object`)return;let t={...typeof e.readOnlyHint==`boolean`?{readOnlyHint:e.readOnlyHint}:{},...typeof e.untrustedContentHint==`boolean`?{untrustedContentHint:e.untrustedContentHint}:{}};return Object.keys(t).length>0?t:void 0},o=e=>{if(e===void 0||e===``)return{...i};if(typeof e==`object`)return e!==null&&!Array.isArray(e)?e:{...i};try{let t=JSON.parse(e);return typeof t==`object`&&t&&!Array.isArray(t)?t:{...i}}catch{return{...i}}},s=e=>{if(e==null)return{content:[{type:`text`,text:``}]};let t;try{t=JSON.parse(e)}catch{return{content:[{type:`text`,text:e}]}}return typeof t==`object`&&t&&Array.isArray(t.content)?t:{content:[{type:`text`,text:typeof t==`string`?t:p(t)}]}},c=e=>{let t;try{t=JSON.stringify(e)??`{}`}catch{t=`{}`}let n=JSON.parse(t);if(typeof n!=`object`||!n)throw TypeError(`WebMCP tool arguments must be an object or array.`);return Object.defineProperty(n,Symbol.toPrimitive,{value:()=>t}),n},l=e=>({isError:!0,content:[{type:`text`,text:e}]}),u=async e=>{if(typeof window>`u`||typeof window.confirm!=`function`)return!1;let t=d(e.args),n=`Allow the AI to call ${e.toolName}`+(t?`\n\nArguments:\n${t}`:``)+(e.description?`\n\n${e.description}`:``);return window.confirm(n)},d=e=>{if(e==null)return``;try{let t=JSON.stringify(e,null,2);return t.length>500?t.slice(0,500)+`…`:t}catch{return String(e)}},f=e=>(e.window===void 0||typeof window<`u`&&e.window===window)&&(e.origin===void 0||typeof location<`u`&&e.origin===location.origin),p=e=>{if(e===void 0)return``;try{return JSON.stringify(e)}catch{return String(e)}};exports.WebMcpBridge=n;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=(e,t)=>({ok:!1,reason:e,message:t}),t=e=>e.startsWith(`webmcp:`)?e.slice(7):e,n={warn(e,...t){typeof console<`u`&&typeof console.warn==`function`&&console.warn(`[Persona/WebMCP] ${e}`,...t)}};var r=class{#e;#t;#n=!1;#r=null;#i=!1;#a;constructor(e,t){this.config=e,this.#a=t,this.#e=e.onConfirm??null,this.#t=3e4}setConfirmHandler(e){this.#e=e}isOperational(){return this.config.enabled!==!0||!this.#n?!1:this.#l()!==null}async snapshotForDispatch(){if(await this.#s(),this.config.enabled!==!0)return[];let e=this.#l();if(!e)return[];let t;try{t=(await e.getTools()).filter(h)}catch(e){return n.warn(`getTools() threw: shipping an empty WebMCP snapshot.`,e),[]}this.#a.recordToolDisplayTitles(t);let r=typeof location<`u`?location.origin:``;return t.filter(e=>this.#d(e.name)).map(e=>{let t=o(e.annotations);return{name:e.name,description:e.description,parametersSchema:s(e.inputSchema),origin:`webmcp`,...r?{pageOrigin:r}:{},...t?{annotations:t}:{},...t?.untrustedContentHint===!0?{untrustedContentHint:!0}:{}}})}async executeToolCall(e,t,n){let r=await this.#o(e,t,n,!1);return r.ok?c(r.raw):u(r.message)}async executeVoiceToolCall(e,t,n={}){let r=await this.#o(e,t,n.signal,n.autoConfirmReadOnly===!0);return r.ok?f(r.raw):{status:r.reason===`aborted`?`failed`:r.reason,error:{message:r.message}}}watchToolChanges(e){let t=!1,n=null;return this.#s().then(()=>{if(t||this.config.enabled!==!0)return;let r=this.#l();r&&typeof r.addEventListener==`function`&&(n=r,n.addEventListener(`toolchange`,e))}),()=>{t=!0,n?.removeEventListener(`toolchange`,e),n=null}}async#o(n,r,i,a){if(await this.#s(),this.config.enabled!==!0)return e(`failed`,`WebMCP is not enabled on this widget.`);let s=this.#l();if(!s){let t=typeof document<`u`&&!!document.modelContext;return e(`failed`,t?`WebMCP is not operational: document.modelContext is present but does not expose the strict getTools()/executeTool() surface (likely a different or older WebMCP polyfill).`:`WebMCP bridge is not operational on this page (document.modelContext not available).`)}let c=t(n),u;try{u=(await s.getTools()).filter(h)}catch(t){let n=t instanceof Error?t.message:String(t);return e(`failed`,`Failed to read WebMCP registry: ${n}`)}this.#a.recordToolDisplayTitles(u);let d=u.find(e=>e.name===c);if(!d)return e(`stale`,`WebMCP tool not registered on this page: ${c}`);if(!this.#d(c))return e(`stale`,`WebMCP tool not allowed by client allowlist: ${c}`);if(i?.aborted)return e(`aborted`,`Aborted by cancel()`);let f=this.#a.getToolDisplayTitle(c),p=o(d.annotations),m={toolName:c,args:r,description:d.description,...p?{annotations:p}:{},...f?{title:f}:{},...i?{signal:i}:{},reason:`gate`};if(!(a&&p?.readOnlyHint===!0)&&!await this.#u(m))return e(`denied`,`User declined the tool call.`);if(i?.aborted)return e(`aborted`,`Aborted by cancel()`);let g=new AbortController,_=!1,v=setTimeout(()=>{_=!0,g.abort()},this.#t),y=()=>g.abort();i&&(i.aborted?g.abort():i.addEventListener(`abort`,y,{once:!0}));try{return{ok:!0,raw:await s.executeTool(d,l(r),{signal:g.signal})}}catch(t){if(_)return e(`timeout`,`WebMCP tool '${c}' timed out after ${this.#t}ms`);if(i?.aborted)return e(`aborted`,`Aborted by cancel()`);let n=t instanceof Error?t.message:String(t);return e(`failed`,n)}finally{clearTimeout(v),i&&i.removeEventListener(`abort`,y)}}#s(){return this.config.enabled===!0?(this.#r||=this.#c(),this.#r):Promise.resolve()}async#c(){try{if(this.#l()){this.#n=!0;return}let e=await this.#a.loadPolyfill();`initializeWebMCPPolyfill`in e?e.initializeWebMCPPolyfill():e.installWebMCP(),this.#n=!0}catch(e){n.warn(`Failed to load @mcp-b/webmcp-polyfill: WebMCP consumption disabled.`,e),this.#n=!1}}#l(){if(typeof document>`u`)return null;let e=document.modelContext;if(!e||typeof e!=`object`)return null;let t=e;return typeof t.getTools!=`function`||typeof t.executeTool!=`function`?(this.#i||(this.#i=!0,n.warn(`document.modelContext is present but does not expose getTools()/executeTool(): WebMCP consumption is disabled. Another (incompatible or older) WebMCP polyfill likely installed document.modelContext before Persona. Remove it, or use a polyfill implementing the strict standard surface (e.g. @mcp-b/webmcp-polyfill).`)),null):e}async#u(e){let t=this.#e??p;try{return await t(e)}catch(t){return n.warn(`Confirm handler threw for WebMCP tool '${e.toolName}'; declining.`,t),!1}}#d(e){let t=this.config.allowlist;return!t||t.length===0||t.some(t=>i(e,t))}};const i=(e,t)=>{if(t===`*`)return!0;let n=t.replace(/[.+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`^`+n.replace(/\*/g,`.*`)+`$`).test(e)},a={type:`object`,properties:{}},o=e=>{if(!e||typeof e!=`object`)return;let t={};for(let n of[`readOnlyHint`,`destructiveHint`,`consequentialHint`,`untrustedContentHint`,`idempotentHint`,`openWorldHint`,`debugging`]){let r=e[n];typeof r==`boolean`&&(t[n]=r)}return Object.keys(t).length>0?t:void 0},s=e=>{if(e===void 0||e===``)return{...a};if(typeof e==`object`)return e!==null&&!Array.isArray(e)?e:{...a};try{let t=JSON.parse(e);return typeof t==`object`&&t&&!Array.isArray(t)?t:{...a}}catch{return{...a}}},c=e=>{if(e==null)return{content:[{type:`text`,text:``}]};let t;try{t=JSON.parse(e)}catch{return{content:[{type:`text`,text:e}]}}return typeof t==`object`&&t&&Array.isArray(t.content)?t:{content:[{type:`text`,text:typeof t==`string`?t:g(t)}]}},l=e=>{let t;try{t=JSON.stringify(e)??`{}`}catch{t=`{}`}let n=JSON.parse(t);if(typeof n!=`object`||!n)throw TypeError(`WebMCP tool arguments must be an object or array.`);return Object.defineProperty(n,Symbol.toPrimitive,{value:()=>t}),n},u=e=>({isError:!0,content:[{type:`text`,text:e}]}),d=e=>Array.isArray(e)?e.map(e=>e&&typeof e==`object`&&typeof e.text==`string`?e.text:``).filter(Boolean).join(`
2
+ `):``,f=e=>{if(e==null)return{status:`completed`};let t;try{t=JSON.parse(e)}catch{return{status:`completed`,result:e}}return typeof t==`object`&&t&&t.isError===!0?{status:`failed`,error:{message:d(t.content)||`The page tool reported an error.`}}:t===void 0?{status:`completed`}:{status:`completed`,result:t}},p=async e=>{if(typeof window>`u`||typeof window.confirm!=`function`)return!1;let t=m(e.args),n=`Allow the AI to call ${e.toolName}`+(t?`\n\nArguments:\n${t}`:``)+(e.description?`\n\n${e.description}`:``);return window.confirm(n)},m=e=>{if(e==null)return``;try{let t=JSON.stringify(e,null,2);return t.length>500?t.slice(0,500)+`…`:t}catch{return String(e)}},h=e=>(e.window===void 0||typeof window<`u`&&e.window===window)&&(e.origin===void 0||typeof location<`u`&&e.origin===location.origin),g=e=>{if(e===void 0)return``;try{return JSON.stringify(e)}catch{return String(e)}};exports.WebMcpBridge=r;
@@ -1,3 +1,3 @@
1
- import { n as WebMcpBridgeDeps, t as WebMcpBridge } from "./webmcp-runtime-entry-B6bpVWSa.cjs";
1
+ import { n as WebMcpBridgeDeps, t as WebMcpBridge } from "./webmcp-runtime-entry-Deg0NfmB.cjs";
2
2
  export { WebMcpBridge, type WebMcpBridgeDeps };
3
3
  export {}
@@ -1,3 +1,3 @@
1
- import { n as WebMcpBridgeDeps, t as WebMcpBridge } from "./webmcp-runtime-entry-B6bpVWSa.js";
1
+ import { n as WebMcpBridgeDeps, t as WebMcpBridge } from "./webmcp-runtime-entry-Deg0NfmB.js";
2
2
  export { WebMcpBridge, type WebMcpBridgeDeps };
3
3
  export {}
@@ -1 +1,2 @@
1
- const e=e=>e.startsWith(`webmcp:`)?e.slice(7):e,t={warn(e,...t){typeof console<`u`&&typeof console.warn==`function`&&console.warn(`[Persona/WebMCP] ${e}`,...t)}};var n=class{#e;#t;#n=!1;#r=null;#i=!1;#a;constructor(e,t){this.config=e,this.#a=t,this.#e=e.onConfirm??null,this.#t=3e4}setConfirmHandler(e){this.#e=e}isOperational(){return this.config.enabled!==!0||!this.#n?!1:this.#c()!==null}async snapshotForDispatch(){if(await this.#o(),this.config.enabled!==!0)return[];let e=this.#c();if(!e)return[];let n;try{n=(await e.getTools()).filter(f)}catch(e){return t.warn(`getTools() threw: shipping an empty WebMCP snapshot.`,e),[]}this.#a.recordToolDisplayTitles(n);let r=typeof location<`u`?location.origin:``;return n.filter(e=>this.#u(e.name)).map(e=>{let t=a(e.annotations);return{name:e.name,description:e.description,parametersSchema:o(e.inputSchema),origin:`webmcp`,...r?{pageOrigin:r}:{},...t?{annotations:t}:{},...t?.untrustedContentHint===!0?{untrustedContentHint:!0}:{}}})}async executeToolCall(t,n,r){if(await this.#o(),this.config.enabled!==!0)return l(`WebMCP is not enabled on this widget.`);let i=this.#c();if(!i){let e=typeof document<`u`&&!!document.modelContext;return l(e?`WebMCP is not operational: document.modelContext is present but does not expose the strict getTools()/executeTool() surface (likely a different or older WebMCP polyfill).`:`WebMCP bridge is not operational on this page (document.modelContext not available).`)}let a=e(t),o;try{o=(await i.getTools()).filter(f)}catch(e){let t=e instanceof Error?e.message:String(e);return l(`Failed to read WebMCP registry: ${t}`)}this.#a.recordToolDisplayTitles(o);let u=o.find(e=>e.name===a);if(!u)return l(`WebMCP tool not registered on this page: ${a}`);if(!this.#u(a))return l(`WebMCP tool not allowed by client allowlist: ${a}`);if(r?.aborted)return l(`Aborted by cancel()`);let d=this.#a.getToolDisplayTitle(a),p={toolName:a,args:n,description:u.description,...d?{title:d}:{},reason:`gate`};if(!await this.#l(p))return l(`User declined the tool call.`);if(r?.aborted)return l(`Aborted by cancel()`);let m=new AbortController,h=!1,g=setTimeout(()=>{h=!0,m.abort()},this.#t),_=()=>m.abort();r&&(r.aborted?m.abort():r.addEventListener(`abort`,_,{once:!0}));try{let e=await i.executeTool(u,c(n),{signal:m.signal});return s(e)}catch(e){if(h)return l(`WebMCP tool '${a}' timed out after ${this.#t}ms`);if(r?.aborted)return l(`Aborted by cancel()`);let t=e instanceof Error?e.message:String(e);return l(t)}finally{clearTimeout(g),r&&r.removeEventListener(`abort`,_)}}#o(){return this.config.enabled===!0?(this.#r||=this.#s(),this.#r):Promise.resolve()}async#s(){try{if(this.#c()){this.#n=!0;return}let e=await this.#a.loadPolyfill();`initializeWebMCPPolyfill`in e?e.initializeWebMCPPolyfill():e.installWebMCP(),this.#n=!0}catch(e){t.warn(`Failed to load @mcp-b/webmcp-polyfill: WebMCP consumption disabled.`,e),this.#n=!1}}#c(){if(typeof document>`u`)return null;let e=document.modelContext;if(!e||typeof e!=`object`)return null;let n=e;return typeof n.getTools!=`function`||typeof n.executeTool!=`function`?(this.#i||(this.#i=!0,t.warn(`document.modelContext is present but does not expose getTools()/executeTool(): WebMCP consumption is disabled. Another (incompatible or older) WebMCP polyfill likely installed document.modelContext before Persona. Remove it, or use a polyfill implementing the strict standard surface (e.g. @mcp-b/webmcp-polyfill).`)),null):e}async#l(e){let n=this.#e??u;try{return await n(e)}catch(n){return t.warn(`Confirm handler threw for WebMCP tool '${e.toolName}'; declining.`,n),!1}}#u(e){let t=this.config.allowlist;return!t||t.length===0||t.some(t=>r(e,t))}};const r=(e,t)=>{if(t===`*`)return!0;let n=t.replace(/[.+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`^`+n.replace(/\*/g,`.*`)+`$`).test(e)},i={type:`object`,properties:{}},a=e=>{if(!e||typeof e!=`object`)return;let t={...typeof e.readOnlyHint==`boolean`?{readOnlyHint:e.readOnlyHint}:{},...typeof e.untrustedContentHint==`boolean`?{untrustedContentHint:e.untrustedContentHint}:{}};return Object.keys(t).length>0?t:void 0},o=e=>{if(e===void 0||e===``)return{...i};if(typeof e==`object`)return e!==null&&!Array.isArray(e)?e:{...i};try{let t=JSON.parse(e);return typeof t==`object`&&t&&!Array.isArray(t)?t:{...i}}catch{return{...i}}},s=e=>{if(e==null)return{content:[{type:`text`,text:``}]};let t;try{t=JSON.parse(e)}catch{return{content:[{type:`text`,text:e}]}}return typeof t==`object`&&t&&Array.isArray(t.content)?t:{content:[{type:`text`,text:typeof t==`string`?t:p(t)}]}},c=e=>{let t;try{t=JSON.stringify(e)??`{}`}catch{t=`{}`}let n=JSON.parse(t);if(typeof n!=`object`||!n)throw TypeError(`WebMCP tool arguments must be an object or array.`);return Object.defineProperty(n,Symbol.toPrimitive,{value:()=>t}),n},l=e=>({isError:!0,content:[{type:`text`,text:e}]}),u=async e=>{if(typeof window>`u`||typeof window.confirm!=`function`)return!1;let t=d(e.args),n=`Allow the AI to call ${e.toolName}`+(t?`\n\nArguments:\n${t}`:``)+(e.description?`\n\n${e.description}`:``);return window.confirm(n)},d=e=>{if(e==null)return``;try{let t=JSON.stringify(e,null,2);return t.length>500?t.slice(0,500)+`…`:t}catch{return String(e)}},f=e=>(e.window===void 0||typeof window<`u`&&e.window===window)&&(e.origin===void 0||typeof location<`u`&&e.origin===location.origin),p=e=>{if(e===void 0)return``;try{return JSON.stringify(e)}catch{return String(e)}};export{n as WebMcpBridge};
1
+ const e=(e,t)=>({ok:!1,reason:e,message:t}),t=e=>e.startsWith(`webmcp:`)?e.slice(7):e,n={warn(e,...t){typeof console<`u`&&typeof console.warn==`function`&&console.warn(`[Persona/WebMCP] ${e}`,...t)}};var r=class{#e;#t;#n=!1;#r=null;#i=!1;#a;constructor(e,t){this.config=e,this.#a=t,this.#e=e.onConfirm??null,this.#t=3e4}setConfirmHandler(e){this.#e=e}isOperational(){return this.config.enabled!==!0||!this.#n?!1:this.#l()!==null}async snapshotForDispatch(){if(await this.#s(),this.config.enabled!==!0)return[];let e=this.#l();if(!e)return[];let t;try{t=(await e.getTools()).filter(h)}catch(e){return n.warn(`getTools() threw: shipping an empty WebMCP snapshot.`,e),[]}this.#a.recordToolDisplayTitles(t);let r=typeof location<`u`?location.origin:``;return t.filter(e=>this.#d(e.name)).map(e=>{let t=o(e.annotations);return{name:e.name,description:e.description,parametersSchema:s(e.inputSchema),origin:`webmcp`,...r?{pageOrigin:r}:{},...t?{annotations:t}:{},...t?.untrustedContentHint===!0?{untrustedContentHint:!0}:{}}})}async executeToolCall(e,t,n){let r=await this.#o(e,t,n,!1);return r.ok?c(r.raw):u(r.message)}async executeVoiceToolCall(e,t,n={}){let r=await this.#o(e,t,n.signal,n.autoConfirmReadOnly===!0);return r.ok?f(r.raw):{status:r.reason===`aborted`?`failed`:r.reason,error:{message:r.message}}}watchToolChanges(e){let t=!1,n=null;return this.#s().then(()=>{if(t||this.config.enabled!==!0)return;let r=this.#l();r&&typeof r.addEventListener==`function`&&(n=r,n.addEventListener(`toolchange`,e))}),()=>{t=!0,n?.removeEventListener(`toolchange`,e),n=null}}async#o(n,r,i,a){if(await this.#s(),this.config.enabled!==!0)return e(`failed`,`WebMCP is not enabled on this widget.`);let s=this.#l();if(!s){let t=typeof document<`u`&&!!document.modelContext;return e(`failed`,t?`WebMCP is not operational: document.modelContext is present but does not expose the strict getTools()/executeTool() surface (likely a different or older WebMCP polyfill).`:`WebMCP bridge is not operational on this page (document.modelContext not available).`)}let c=t(n),u;try{u=(await s.getTools()).filter(h)}catch(t){let n=t instanceof Error?t.message:String(t);return e(`failed`,`Failed to read WebMCP registry: ${n}`)}this.#a.recordToolDisplayTitles(u);let d=u.find(e=>e.name===c);if(!d)return e(`stale`,`WebMCP tool not registered on this page: ${c}`);if(!this.#d(c))return e(`stale`,`WebMCP tool not allowed by client allowlist: ${c}`);if(i?.aborted)return e(`aborted`,`Aborted by cancel()`);let f=this.#a.getToolDisplayTitle(c),p=o(d.annotations),m={toolName:c,args:r,description:d.description,...p?{annotations:p}:{},...f?{title:f}:{},...i?{signal:i}:{},reason:`gate`};if(!(a&&p?.readOnlyHint===!0)&&!await this.#u(m))return e(`denied`,`User declined the tool call.`);if(i?.aborted)return e(`aborted`,`Aborted by cancel()`);let g=new AbortController,_=!1,v=setTimeout(()=>{_=!0,g.abort()},this.#t),y=()=>g.abort();i&&(i.aborted?g.abort():i.addEventListener(`abort`,y,{once:!0}));try{return{ok:!0,raw:await s.executeTool(d,l(r),{signal:g.signal})}}catch(t){if(_)return e(`timeout`,`WebMCP tool '${c}' timed out after ${this.#t}ms`);if(i?.aborted)return e(`aborted`,`Aborted by cancel()`);let n=t instanceof Error?t.message:String(t);return e(`failed`,n)}finally{clearTimeout(v),i&&i.removeEventListener(`abort`,y)}}#s(){return this.config.enabled===!0?(this.#r||=this.#c(),this.#r):Promise.resolve()}async#c(){try{if(this.#l()){this.#n=!0;return}let e=await this.#a.loadPolyfill();`initializeWebMCPPolyfill`in e?e.initializeWebMCPPolyfill():e.installWebMCP(),this.#n=!0}catch(e){n.warn(`Failed to load @mcp-b/webmcp-polyfill: WebMCP consumption disabled.`,e),this.#n=!1}}#l(){if(typeof document>`u`)return null;let e=document.modelContext;if(!e||typeof e!=`object`)return null;let t=e;return typeof t.getTools!=`function`||typeof t.executeTool!=`function`?(this.#i||(this.#i=!0,n.warn(`document.modelContext is present but does not expose getTools()/executeTool(): WebMCP consumption is disabled. Another (incompatible or older) WebMCP polyfill likely installed document.modelContext before Persona. Remove it, or use a polyfill implementing the strict standard surface (e.g. @mcp-b/webmcp-polyfill).`)),null):e}async#u(e){let t=this.#e??p;try{return await t(e)}catch(t){return n.warn(`Confirm handler threw for WebMCP tool '${e.toolName}'; declining.`,t),!1}}#d(e){let t=this.config.allowlist;return!t||t.length===0||t.some(t=>i(e,t))}};const i=(e,t)=>{if(t===`*`)return!0;let n=t.replace(/[.+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`^`+n.replace(/\*/g,`.*`)+`$`).test(e)},a={type:`object`,properties:{}},o=e=>{if(!e||typeof e!=`object`)return;let t={};for(let n of[`readOnlyHint`,`destructiveHint`,`consequentialHint`,`untrustedContentHint`,`idempotentHint`,`openWorldHint`,`debugging`]){let r=e[n];typeof r==`boolean`&&(t[n]=r)}return Object.keys(t).length>0?t:void 0},s=e=>{if(e===void 0||e===``)return{...a};if(typeof e==`object`)return e!==null&&!Array.isArray(e)?e:{...a};try{let t=JSON.parse(e);return typeof t==`object`&&t&&!Array.isArray(t)?t:{...a}}catch{return{...a}}},c=e=>{if(e==null)return{content:[{type:`text`,text:``}]};let t;try{t=JSON.parse(e)}catch{return{content:[{type:`text`,text:e}]}}return typeof t==`object`&&t&&Array.isArray(t.content)?t:{content:[{type:`text`,text:typeof t==`string`?t:g(t)}]}},l=e=>{let t;try{t=JSON.stringify(e)??`{}`}catch{t=`{}`}let n=JSON.parse(t);if(typeof n!=`object`||!n)throw TypeError(`WebMCP tool arguments must be an object or array.`);return Object.defineProperty(n,Symbol.toPrimitive,{value:()=>t}),n},u=e=>({isError:!0,content:[{type:`text`,text:e}]}),d=e=>Array.isArray(e)?e.map(e=>e&&typeof e==`object`&&typeof e.text==`string`?e.text:``).filter(Boolean).join(`
2
+ `):``,f=e=>{if(e==null)return{status:`completed`};let t;try{t=JSON.parse(e)}catch{return{status:`completed`,result:e}}return typeof t==`object`&&t&&t.isError===!0?{status:`failed`,error:{message:d(t.content)||`The page tool reported an error.`}}:t===void 0?{status:`completed`}:{status:`completed`,result:t}},p=async e=>{if(typeof window>`u`||typeof window.confirm!=`function`)return!1;let t=m(e.args),n=`Allow the AI to call ${e.toolName}`+(t?`\n\nArguments:\n${t}`:``)+(e.description?`\n\n${e.description}`:``);return window.confirm(n)},m=e=>{if(e==null)return``;try{let t=JSON.stringify(e,null,2);return t.length>500?t.slice(0,500)+`…`:t}catch{return String(e)}},h=e=>(e.window===void 0||typeof window<`u`&&e.window===window)&&(e.origin===void 0||typeof location<`u`&&e.origin===location.origin),g=e=>{if(e===void 0)return``;try{return JSON.stringify(e)}catch{return String(e)}};export{r as WebMcpBridge};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/persona",
3
- "version": "4.28.2",
3
+ "version": "4.29.0",
4
4
  "description": "Themeable, pluggable streaming agent widget for websites, in plain JS with support for voice input and reasoning / tool output.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -117,6 +117,11 @@
117
117
  "import": "./dist/voice-runtime.js",
118
118
  "require": "./dist/voice-runtime.cjs"
119
119
  },
120
+ "./voice-client-tools": {
121
+ "types": "./dist/voice-client-tools.d.ts",
122
+ "import": "./dist/voice-client-tools.js",
123
+ "require": "./dist/voice-client-tools.cjs"
124
+ },
120
125
  "./forms-ui": {
121
126
  "types": "./dist/forms-ui.d.ts",
122
127
  "import": "./dist/forms-ui.js",
package/src/client.ts CHANGED
@@ -34,6 +34,7 @@ import {
34
34
  recordWebMcpToolDisplayTitles,
35
35
  } from "./webmcp-bridge";
36
36
  import { loadWebMcpRuntime } from "./webmcp-runtime-loader";
37
+ import { loadVoiceClientTools } from "./voice-client-tools-loader";
37
38
  import type { WebMcpBridge } from "./webmcp-runtime-entry";
38
39
  import { resolveTarget } from "./utils/target";
39
40
  import { generateTurnId } from "./utils/message-id";
@@ -406,6 +407,42 @@ export class AgentWidgetClient {
406
407
  * session that it should fall back to the legacy local-tool resume path,
407
408
  * if any).
408
409
  */
410
+ /**
411
+ * WebMCP access for a Runtype voice call's fast tier: the same per-turn
412
+ * snapshot `clientTools[]` carries, registry change notifications, and the
413
+ * voice execute path. `null` when WebMCP is not enabled.
414
+ */
415
+ public getVoiceClientTools():import("./types").VoiceClientTools | null {
416
+ if (this.config.webmcp?.enabled !== true) return null;
417
+ const bridge = () => this.#getWebMcpBridge();
418
+ const surface: import("./types").VoiceClientTools = {
419
+ open: async (channel) => (await loadVoiceClientTools()).createVoiceClientToolsSession(surface, channel),
420
+ snapshot: async () => {
421
+ const tools = (await (await bridge())?.snapshotForDispatch()) ?? [];
422
+ return { tools, fingerprint: computeClientToolsFingerprint(tools) };
423
+ },
424
+ onChange: (listener) => {
425
+ let stop: (() => void) | null = null;
426
+ let stopped = false;
427
+ void bridge().then((b) => {
428
+ if (b && !stopped) stop = b.watchToolChanges(listener);
429
+ });
430
+ return () => {
431
+ stopped = true;
432
+ stop?.();
433
+ };
434
+ },
435
+ execute: async (name, args, options) => {
436
+ const b = await bridge();
437
+ if (!b) {
438
+ return { status: "failed", error: { message: "WebMCP runtime failed to load." } };
439
+ }
440
+ return b.executeVoiceToolCall(name, args, options);
441
+ },
442
+ };
443
+ return surface;
444
+ }
445
+
409
446
  public executeWebMcpToolCall(
410
447
  wireToolName: string,
411
448
  args: unknown,
@@ -0,0 +1,65 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+
3
+ import { AgentWidgetClient } from "./client";
4
+ import type { ClientToolDefinition } from "./types";
5
+ import { computeClientToolsFingerprint } from "./webmcp-bridge";
6
+
7
+ const tool: ClientToolDefinition = {
8
+ name: "next_slide",
9
+ description: "Advance the presentation to the next slide.",
10
+ parametersSchema: { type: "object", properties: {} },
11
+ origin: "webmcp",
12
+ annotations: { readOnlyHint: true },
13
+ };
14
+
15
+ const withBridge = (bridge: Record<string, unknown>) => {
16
+ const client = new AgentWidgetClient({ apiUrl: "http://test", webmcp: { enabled: true } });
17
+ (client as unknown as { webMcpBridge: unknown }).webMcpBridge = bridge;
18
+ return client;
19
+ };
20
+
21
+ describe("AgentWidgetClient.getVoiceClientTools", () => {
22
+ it("is null when WebMCP is off", () => {
23
+ expect(new AgentWidgetClient({ apiUrl: "http://test" }).getVoiceClientTools()).toBeNull();
24
+ });
25
+
26
+ it("snapshots exactly the dispatch clientTools[] entries, with their fingerprint", async () => {
27
+ const client = withBridge({ snapshotForDispatch: async () => [tool] });
28
+ const snapshot = await client.getVoiceClientTools()!.snapshot();
29
+ expect(snapshot).toEqual({ tools: [tool], fingerprint: computeClientToolsFingerprint([tool]) });
30
+ });
31
+
32
+ it("routes execute and change subscriptions to the bridge's voice methods", async () => {
33
+ const stop = vi.fn();
34
+ const watchToolChanges = vi.fn(() => stop);
35
+ const executeVoiceToolCall = vi.fn(async () => ({ status: "completed", result: { slidePosition: 2 } }));
36
+ const surface = withBridge({ watchToolChanges, executeVoiceToolCall }).getVoiceClientTools()!;
37
+
38
+ const signal = new AbortController().signal;
39
+ const outcome = await surface.execute("webmcp:next_slide", {}, { signal, autoConfirmReadOnly: true });
40
+ expect(executeVoiceToolCall).toHaveBeenCalledWith("webmcp:next_slide", {}, { signal, autoConfirmReadOnly: true });
41
+ expect(outcome).toEqual({ status: "completed", result: { slidePosition: 2 } });
42
+
43
+ const listener = vi.fn();
44
+ const unsubscribe = surface.onChange(listener);
45
+ await Promise.resolve();
46
+ await Promise.resolve();
47
+ expect(watchToolChanges).toHaveBeenCalledWith(listener);
48
+ unsubscribe();
49
+ expect(stop).toHaveBeenCalledTimes(1);
50
+ });
51
+
52
+ it("opens a fast-tier session from the lazy chunk that sends the snapshot through the channel", async () => {
53
+ const client = new AgentWidgetClient({ apiUrl: "http://test", webmcp: { enabled: true } });
54
+ const slot = client as unknown as { webMcpBridge: unknown };
55
+ // Let the real lazy bridge adopt first, so it cannot replace the fake mid-test.
56
+ await vi.waitFor(() => expect(slot.webMcpBridge).not.toBeNull());
57
+ slot.webMcpBridge = { snapshotForDispatch: async () => [tool], watchToolChanges: () => () => undefined };
58
+ const surface = client.getVoiceClientTools()!;
59
+ const sent: Array<Record<string, unknown>> = [];
60
+ const session = await surface.open({ send: (frame) => (sent.push(frame), true), cancelled: () => false });
61
+ await vi.waitFor(() => expect(sent).toHaveLength(1));
62
+ expect(sent[0]).toMatchObject({ type: "client_tools", tools: [{ ...tool, name: "webmcp:next_slide" }] });
63
+ session.close();
64
+ });
65
+ });