@runtypelabs/persona 4.27.0 → 4.28.1

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 (72) hide show
  1. package/README.md +25 -0
  2. package/dist/{approval-ui-QAKWNFNM.js → approval-ui-OBBI62ES.js} +1 -1
  3. package/dist/approval-ui.cjs +2 -2
  4. package/dist/approval-ui.d.cts +20 -5
  5. package/dist/approval-ui.d.ts +20 -5
  6. package/dist/approval-ui.js +2 -2
  7. package/dist/artifacts-ui.d.cts +20 -5
  8. package/dist/artifacts-ui.d.ts +20 -5
  9. package/dist/{chunk-NQLDCJAP.js → chunk-D4TDKCT5.js} +2 -2
  10. package/dist/chunk-FNXK3VTC.js +1 -0
  11. package/dist/{client-history-HTRKHBAF.js → client-history-QGAFMCBE.js} +1 -1
  12. package/dist/client-history.js +1 -1
  13. package/dist/{client-stream-N22JHTLE.js → client-stream-WXD2FL23.js} +1 -1
  14. package/dist/client-stream.js +3 -3
  15. package/dist/codegen.cjs +4 -4
  16. package/dist/codegen.js +5 -5
  17. package/dist/context-mentions.d.cts +20 -5
  18. package/dist/context-mentions.d.ts +20 -5
  19. package/dist/event-stream-view.d.cts +20 -5
  20. package/dist/event-stream-view.d.ts +20 -5
  21. package/dist/forms-ui.d.cts +26 -5
  22. package/dist/forms-ui.d.ts +26 -5
  23. package/dist/index.cjs +41 -41
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +59 -30
  26. package/dist/index.d.ts +59 -30
  27. package/dist/index.global.js +1 -1
  28. package/dist/index.global.js.map +1 -1
  29. package/dist/index.js +41 -41
  30. package/dist/index.js.map +1 -1
  31. package/dist/session-reconnect.d.cts +20 -5
  32. package/dist/session-reconnect.d.ts +20 -5
  33. package/dist/smart-dom-reader.d.cts +20 -5
  34. package/dist/smart-dom-reader.d.ts +20 -5
  35. package/dist/theme-editor-preview.cjs +63 -63
  36. package/dist/theme-editor-preview.d.cts +20 -5
  37. package/dist/theme-editor-preview.d.ts +20 -5
  38. package/dist/theme-editor-preview.js +6 -6
  39. package/dist/theme-editor.d.cts +21 -6
  40. package/dist/theme-editor.d.ts +21 -6
  41. package/dist/voice-runtime-TWFJ4UUS.js +17 -0
  42. package/dist/voice-runtime.cjs +8 -8
  43. package/dist/voice-runtime.d.cts +31 -5
  44. package/dist/voice-runtime.d.ts +31 -5
  45. package/dist/voice-runtime.js +8 -8
  46. package/dist/webmcp-runtime-5Q3IHAHP.js +6 -0
  47. package/dist/webmcp-runtime.cjs +2 -2
  48. package/dist/webmcp-runtime.d.cts +22 -26
  49. package/dist/webmcp-runtime.d.ts +22 -26
  50. package/dist/webmcp-runtime.js +2 -2
  51. package/package.json +5 -2
  52. package/src/client.interrupt.test.ts +18 -0
  53. package/src/client.ts +7 -0
  54. package/src/generated/runtype-openapi-contract.ts +3 -0
  55. package/src/session.ts +11 -3
  56. package/src/session.voice.test.ts +140 -0
  57. package/src/theme-editor/webmcp/types.ts +1 -1
  58. package/src/types.ts +26 -5
  59. package/src/voice/runtype-voice-provider.ts +93 -11
  60. package/src/voice/voice-clause-buffer.test.ts +143 -0
  61. package/src/voice/voice-clause-buffer.ts +187 -0
  62. package/src/voice/voice-delegation.ts +85 -3
  63. package/src/voice/voice.test.ts +257 -2
  64. package/src/webmcp-bridge.test.ts +87 -21
  65. package/src/webmcp-bridge.ts +21 -26
  66. package/src/webmcp-polyfill.integration.test.ts +339 -0
  67. package/src/webmcp-polyfill.ts +7 -4
  68. package/src/webmcp-runtime-bundle.test.ts +1 -1
  69. package/src/webmcp-runtime-entry.ts +34 -19
  70. package/dist/chunk-3255TNY7.js +0 -1
  71. package/dist/voice-runtime-RHRX4F3T.js +0 -17
  72. package/dist/webmcp-runtime-V6ZWW3PI.js +0 -6
@@ -3214,9 +3214,8 @@ type WebMcpConfirmInfo = {
3214
3214
  };
3215
3215
  /**
3216
3216
  * Why the confirm was requested. Currently always `'gate'`: the default
3217
- * confirm-by-default gate that fires before every `webmcp:*` call. (The
3218
- * `@mcp-b/webmcp-polyfill` owns the spec's `requestUserInteraction` callback
3219
- * internally, so Persona no longer surfaces a nested in-tool confirm.)
3217
+ * confirm-by-default gate that fires before every `webmcp:*` call. Tool
3218
+ * callbacks on v6 receive an AbortSignal, not a nested confirmation API.
3220
3219
  */
3221
3220
  reason: 'gate';
3222
3221
  };
@@ -7130,6 +7129,13 @@ type VoiceDelegationRequest = {
7130
7129
  role: string;
7131
7130
  content: unknown;
7132
7131
  }>;
7132
+ /**
7133
+ * Set when the server streams delegated answers (`delegation_stream`): called
7134
+ * with each speakable piece of the turn's answer, in order, while it renders.
7135
+ * The pieces, concatenated, are a prefix of the result's `text`; the result
7136
+ * says how much of it with `streamedChars`.
7137
+ */
7138
+ stream?: (text: string) => void;
7133
7139
  };
7134
7140
  /**
7135
7141
  * How a delegated turn ended, or that it waits on an approval (contract
@@ -7160,6 +7166,12 @@ type VoiceDelegationResult = {
7160
7166
  * @default true
7161
7167
  */
7162
7168
  inChat?: boolean;
7169
+ /**
7170
+ * How many leading characters of `text` already went out through
7171
+ * `request.stream` (the rest, such as an approval script, is unstreamed).
7172
+ * Omitted or 0: nothing was streamed.
7173
+ */
7174
+ streamedChars?: number;
7163
7175
  /**
7164
7176
  * Set when the turn parked on approvals (`text` then asks for the decision).
7165
7177
  * Resolves with the terminal result once the visitor decides (or the
@@ -9279,8 +9291,11 @@ type AgentWidgetConfig = {
9279
9291
  /**
9280
9292
  * WebMCP: consume page-registered tools (`document.modelContext.registerTool`).
9281
9293
  * When `enabled`, the widget installs `@mcp-b/webmcp-polyfill`, snapshots the
9282
- * registry on every dispatch, ships it as `clientTools[]`, and executes
9283
- * returned `webmcp:*` tool calls with confirm-by-default gating.
9294
+ * current document's registry on every dispatch, ships it as `clientTools[]`,
9295
+ * and executes returned `webmcp:*` calls with confirm-by-default gating.
9296
+ * Supports host-installed v5 JSON-string and v6 object-input contracts.
9297
+ * The automatic fallback stays on v5 to preserve existing browser support
9298
+ * and callback-result behavior.
9284
9299
  *
9285
9300
  * Server-side policy on the chat surface is the source of truth: these
9286
9301
  * fields layer on top.
@@ -10463,7 +10478,7 @@ declare function tokenRefDisplayName(path: string): string;
10463
10478
  *
10464
10479
  * We deliberately keep our own small WebMCP types rather than depending on
10465
10480
  * `@mcp-b/webmcp-types`, so the tool definitions are transport-agnostic and the
10466
- * widget package takes on no polyfill dependency. These mirror the WebMCP draft
10481
+ * tool definitions do not depend on the polyfill's types. These mirror the WebMCP draft
10467
10482
  * (`registerTool(tool, { signal })`) and the MCP tool-result envelope that
10468
10483
  * `@mcp-b/webmcp-polyfill` expects `execute` to return.
10469
10484
  */
@@ -3214,9 +3214,8 @@ type WebMcpConfirmInfo = {
3214
3214
  };
3215
3215
  /**
3216
3216
  * Why the confirm was requested. Currently always `'gate'`: the default
3217
- * confirm-by-default gate that fires before every `webmcp:*` call. (The
3218
- * `@mcp-b/webmcp-polyfill` owns the spec's `requestUserInteraction` callback
3219
- * internally, so Persona no longer surfaces a nested in-tool confirm.)
3217
+ * confirm-by-default gate that fires before every `webmcp:*` call. Tool
3218
+ * callbacks on v6 receive an AbortSignal, not a nested confirmation API.
3220
3219
  */
3221
3220
  reason: 'gate';
3222
3221
  };
@@ -7130,6 +7129,13 @@ type VoiceDelegationRequest = {
7130
7129
  role: string;
7131
7130
  content: unknown;
7132
7131
  }>;
7132
+ /**
7133
+ * Set when the server streams delegated answers (`delegation_stream`): called
7134
+ * with each speakable piece of the turn's answer, in order, while it renders.
7135
+ * The pieces, concatenated, are a prefix of the result's `text`; the result
7136
+ * says how much of it with `streamedChars`.
7137
+ */
7138
+ stream?: (text: string) => void;
7133
7139
  };
7134
7140
  /**
7135
7141
  * How a delegated turn ended, or that it waits on an approval (contract
@@ -7160,6 +7166,12 @@ type VoiceDelegationResult = {
7160
7166
  * @default true
7161
7167
  */
7162
7168
  inChat?: boolean;
7169
+ /**
7170
+ * How many leading characters of `text` already went out through
7171
+ * `request.stream` (the rest, such as an approval script, is unstreamed).
7172
+ * Omitted or 0: nothing was streamed.
7173
+ */
7174
+ streamedChars?: number;
7163
7175
  /**
7164
7176
  * Set when the turn parked on approvals (`text` then asks for the decision).
7165
7177
  * Resolves with the terminal result once the visitor decides (or the
@@ -9279,8 +9291,11 @@ type AgentWidgetConfig = {
9279
9291
  /**
9280
9292
  * WebMCP: consume page-registered tools (`document.modelContext.registerTool`).
9281
9293
  * When `enabled`, the widget installs `@mcp-b/webmcp-polyfill`, snapshots the
9282
- * registry on every dispatch, ships it as `clientTools[]`, and executes
9283
- * returned `webmcp:*` tool calls with confirm-by-default gating.
9294
+ * current document's registry on every dispatch, ships it as `clientTools[]`,
9295
+ * and executes returned `webmcp:*` calls with confirm-by-default gating.
9296
+ * Supports host-installed v5 JSON-string and v6 object-input contracts.
9297
+ * The automatic fallback stays on v5 to preserve existing browser support
9298
+ * and callback-result behavior.
9284
9299
  *
9285
9300
  * Server-side policy on the chat surface is the source of truth: these
9286
9301
  * fields layer on top.
@@ -10463,7 +10478,7 @@ declare function tokenRefDisplayName(path: string): string;
10463
10478
  *
10464
10479
  * We deliberately keep our own small WebMCP types rather than depending on
10465
10480
  * `@mcp-b/webmcp-types`, so the tool definitions are transport-agnostic and the
10466
- * widget package takes on no polyfill dependency. These mirror the WebMCP draft
10481
+ * tool definitions do not depend on the polyfill's types. These mirror the WebMCP draft
10467
10482
  * (`registerTool(tool, { signal })`) and the MCP tool-result envelope that
10468
10483
  * `@mcp-b/webmcp-polyfill` expects `execute` to return.
10469
10484
  */
@@ -0,0 +1,17 @@
1
+ import{a as ae}from"./chunk-6V3MNEKB.js";import{a as oe}from"./chunk-FNXK3VTC.js";var K=16e3,Me=24e3,Te=4096,_e=K*2*8,Ee=4,Ie=1380533830,Ve=3e4,Pe=1e3,Re=5e3,Le=3e4,Ne=3e4,Oe=6e5,De="full-duplex-v1",Ue=300,xe=2e3,$e=2e3,Be="runtype-browser-v1",We=54e4,He="You're talking to an AI assistant. Voice is processed by OpenAI.",qe=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."]]),ce=["provider_error","server_restart"],O="Voice connection lost.",je=8e3,Fe=4e3,Xe=12,le=2e3;function ze(i,e){let t="Conversation so far:",s=e.slice(0,Fe).trim(),n=je-(s?s.length+2:0)-t.length,r=[];for(let l of i.slice(-Xe).reverse()){let a=l.content.replace(/\s+/g," ").trim();if(!a)continue;a.length>le&&(a=`${a.slice(0,le-1)}\u2026`);let o=`${l.role==="user"?"User":"Assistant"}: ${a}`;if(o.length+1>n)break;n-=o.length+1,r.unshift(o)}let d=r.length>0?[`${t}
2
+ ${r.join(`
3
+ `)}`]:[];return s&&d.push(s),d.join(`
4
+
5
+ `)}function Ge(i){return i.byteLength>=44&&new DataView(i).getUint32(0,!1)===Ie?new Uint8Array(i,44):new Uint8Array(i)}function de(i){let e=i.replace(/\/+$/,"");return/^wss?:\/\//i.test(e)?e:/^https?:\/\//i.test(e)?e.replace(/^http/i,"ws"):`${typeof window<"u"&&window.location?.protocol==="https:"?"wss:":"ws:"}//${e}`}function Ke(i){return de(i).replace(/^ws/i,"http")}function Ye(i){return typeof i!="number"||!Number.isFinite(i)?Le:Math.min(Oe,Math.max(Ne,Math.round(i)))}var R=class{constructor(e){this.config=e;this.type="runtype";this.#e=null;this.#n=null;this.#a=[];this.#i=null;this.#c=null;this.#l=null;this.#y=[];this.#b=0;this.#r=null;this.#h=!1;this.#g=!1;this.#s=0;this.#E=!1;this.#J=Number.NEGATIVE_INFINITY;this.#o=null;this.#f=!1;this.#I=!1;this.#V=0;this.#v=0;this.#w=!1;this.bridge=null;this.#R=!1;this.#d=new Set;this.#A=new Map;this.#C=new Set;this.#L=null;this.#p=null;this.#U=!1;this.#x=!1;this.#$=!1;this.#N=null;this.#B=null;this.#W=Promise.resolve();this.#S=new Set;this.#k=new Set;this.#H=null;this.#u=!1;this.#M=new Set;this.#T=new Set;this.#Q=[];this.#q=[];this.#j=[];this.#F=[];this.#X=[]}#e;#n;#a;#i;#c;#l;#y;#b;#r;#h;#g;#s;#E;#J;#o;#f;#I;#V;#v;#P;#w;#R;#d;#A;#C;#D;#L;#p;#Z;#U;#x;#$;#N;#B;#W;#S;#k;#H;#u;#M;#T;#Q;#q;#j;#F;#X;async connect(){}setSessionBridge(e){this.bridge=e}prewarm(){if(this.#h||this.#o)return;let e=this.config?.agentId,t=this.config?.clientToken,s=this.config?.host;if(!e||!t||!s)return;let n=Date.now();if(!(n-this.#J<Ve)){this.#J=n;try{this.config?.prewarmMode==="attach"?this.#de(s,e,t):this.#le(s,e,t)}catch{}}}#le(e,t,s){if(typeof fetch!="function")return;let n=`${Ke(e)}/v1/client/agents/${encodeURIComponent(t)}/voice/prewarm`;fetch(n,{method:"POST",headers:{Authorization:`Bearer ${s}`},keepalive:!0}).catch(()=>{})}#de(e,t,s){let n=new URLSearchParams,r=this.config?.attachIdleMs,d=Ye(r);r!==void 0&&n.set("attachIdleMs",String(d));let l=new WebSocket(this.#te(e,t,n),["runtype.bearer","runtype.attach",s]);l.binaryType="arraybuffer";let a=()=>{},o=new Promise(u=>{a=u}),c={ws:l,state:"connecting",ready:o,settle:a,openedAt:0,idleTimer:void 0};this.#o=c,l.onopen=()=>{this.#o===c&&(c.state=l.protocol==="runtype.attach"?"attached":"live",c.openedAt=Date.now(),this.#ee(c,d),c.state==="attached"&&l.send('{"type":"ping"}'),c.settle())},l.onmessage=u=>{if(this.#o!==c||typeof u.data!="string")return;let h;try{h=JSON.parse(u.data)}catch{return}h.type==="attached"&&typeof h.idleMs=="number"&&this.#ee(c,h.idleMs-(Date.now()-c.openedAt))},l.onerror=()=>{},l.onclose=()=>{this.#o===c&&this.#O()}}#ee(e,t){clearTimeout(e.idleTimer),e.idleTimer=setTimeout(()=>{this.#o===e&&this.#O()},Math.max(0,t))}#O(){let e=this.#o;if(!e)return;this.#o=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#ue(){let e=this.#o;if(!e)return null;if(e.state==="connecting"){let t;await Promise.race([e.ready,new Promise(s=>{t=setTimeout(s,Re)})]),clearTimeout(t)}return this.#o!==e?null:e.state==="connecting"||e.ws.readyState!==WebSocket.OPEN?(this.#O(),null):(this.#o=null,clearTimeout(e.idleTimer),{ws:e.ws,live:e.state==="live"})}#te(e,t,s){let n=["partial_transcript","context"];this.bridge&&this.config?.clientDelegation!==!1&&n.push("client_delegation","delegation_update","delegation_read_back","delegation_stream"),s&&n.unshift("attach");let r=new URLSearchParams({voiceProtocol:Be,clientVersion:`persona/${oe}`,voiceCapabilities:De,clientCapabilities:n.join(",")});return s?.forEach((d,l)=>r.set(l,d)),`${de(e)}/ws/agents/${encodeURIComponent(t)}/voice?${r}`}async startListening(){if(this.#h)return;let e=this.#x;e||(this.#U=!1,this.#p=null),this.#x=!1;let t=this.config?.agentId,s=this.config?.clientToken,n=this.config?.host;if(!t)throw new Error("Runtype voice requires an agentId");if(!s)throw new Error("Runtype voice requires a clientToken");if(!n)throw new Error("Runtype voice requires a host (or widget apiUrl)");let r=++this.#s;this.#E=!1,this.#h=!0;try{let d=await navigator.mediaDevices.getUserMedia({audio:{sampleRate:K,channelCount:1,echoCancellation:!0}});if(r!==this.#s){d.getTracks().forEach(h=>h.stop());return}this.#i=d;let l=window.AudioContext||window.webkitAudioContext,a=new l({sampleRate:K});if(this.#n=a,a.state==="suspended"){if(await Promise.race([a.resume().catch(()=>{}),new Promise(h=>setTimeout(h,e?500:Pe))]),r!==this.#s)return;if(a.state!=="running")throw e?new Error(this.#p=`${O} Tap the mic to reconnect.`):new Error("Audio blocked until a tap")}let o=this.config?.createPlaybackEngine?await this.config.createPlaybackEngine():new ae(Me);if(r!==this.#s){o.destroy(),d.getTracks().forEach(h=>h.stop()),a.close().catch(()=>{});return}this.#r=o,this.#K(),this.#ge(a,d,r);let c=await this.#ue();if(r!==this.#s){c?.ws.close(1e3,"client ended call");return}if(c){let{ws:h}=c;this.#e=h,this.#se(h,r),c.live||h.send('{"type":"start"}'),this.#z(h),this.#t("listening");return}let u=new WebSocket(this.#te(n,t),["runtype.bearer",s]);u.binaryType="arraybuffer",this.#e=u,u.onopen=()=>{r===this.#s&&(this.#z(u),this.#t("listening"))},this.#se(u,r)}catch(d){throw this.#m(),this.#_(d),this.#t("error"),d}}#se(e,t){e.onmessage=s=>this.#fe(s,t),e.onerror=()=>{t!==this.#s||this.#L||(this.#_(new Error("Voice connection failed")),this.#t("error"),this.#m())},e.onclose=s=>{if(this.#E){this.#E=!1;return}if(t!==this.#s)return;let n=this.#L??(s.code===4408?{reason:"idle_timeout"}:null);if(!n){if(s.code!==1e3){let r=s.code?` (code ${s.code})`:"";this.#_(new Error(`Voice connection closed${r}`)),this.#t("error")}else this.#t("idle");this.#m();return}this.#he(n.reason,n.message)}}#he(e,t){let s=ce.includes(e)&&!this.#U;if(this.#m(),s){this.#U=!0,this.#h=!0,this.#p=e==="provider_error"?`${O} Reconnecting\u2026`:"Reconnecting\u2026",this.#Z=setTimeout(()=>{this.#h=!1,this.#x=!0,this.startListening().catch(()=>{})},1e3+Math.random()*1e3),this.#t("idle");return}if(ce.includes(e))return this.#p=O,this.#_(new Error(O)),this.#t("error");if(e==="error")return this.#t("error");this.#p=e==="quota"&&t||qe.get(e)||null,this.#t("idle")}takeNotice(){let e=this.#p;return this.#p=null,e}getDisclosure(){let e=this.config?.disclosureText;return this.#h&&this.#f&&e!==!1?e||He:null}async stopListening(){this.#m(),this.#t("idle")}async disconnect(){this.#m(),this.#t("disconnected"),this.#Q=[],this.#q=[],this.#j=[],this.#F=[],this.#X=[]}stopPlayback(){this.#ce();let e=this.#e;e&&e.readyState===WebSocket.OPEN&&(this.#f&&(this.#V=Date.now()+xe,e.send('{"type":"cancel"}')),this.#t("listening"))}getInterruptionMode(){return"barge-in"}isBargeInActive(){return this.#h}onLevel(e){this.#a.push(e)}async deactivateBargeIn(){this.#m(),this.#t("idle")}#ge(e,t,s){let n=e.createMediaStreamSource(t);this.#c=n;let r=e.createScriptProcessor(Te,1,1);this.#l=r,r.onaudioprocess=d=>{if(s!==this.#s)return;let l=this.#e,a=l?.readyState===WebSocket.OPEN;if(l&&!a&&l.readyState!==WebSocket.CONNECTING)return;let o=d.inputBuffer.getChannelData(0),c=new Int16Array(o.length),u=0;for(let h=0;h<o.length;h++){let m=Math.max(-1,Math.min(1,o[h]));u+=m*m,c[h]=m<0?m*32768:m*32767}if(l&&a)this.#z(l),l.send(c.buffer);else for(this.#y.push(c.buffer),this.#b+=c.byteLength;this.#b>_e;)this.#b-=this.#y.shift().byteLength;if(this.#a.length>0){let h=Math.sqrt(u/o.length),m=Math.max(0,Math.min(1,h*Ee));for(let f of this.#a)f(m)}},n.connect(r),r.connect(e.destination)}#z(e){for(let t of this.#y)e.send(t);this.#y=[],this.#b=0}#fe(e,t){if(t!==this.#s)return;if(e.data instanceof ArrayBuffer){this.#ve(e.data,t);return}let s;try{s=JSON.parse(e.data)}catch{return}switch(s.type){case"session_config":s.speechMode&&(this.#f=s.speechMode==="speech_to_speech",this.#r?.setContinuousMode?.(this.#f)),Array.isArray(s.capabilities)&&(this.#d=new Set(s.capabilities)),typeof s.callId=="string"&&(this.#D=s.callId),this.#R=this.#f&&this.#d.has("client_delegation")&&!!this.bridge,this.#f&&!this.#g&&this.#t("listening"),this.#d.has("context")&&!this.#$&&(this.#$=!0,this.#N=this.#pe());break;case"transcript_update":{let n=s.role==="assistant"?"assistant":"user",r=s.utteranceId??s.turnId;if(!r||n==="assistant"&&this.#G())break;let d=String(r);if(n==="user")s.final===!0&&this.#ie(t),this.#u=!1;else{if(this.#d.has("delegation_read_back")){let l=s.delegationId;typeof l=="string"&&this.#S.has(l)&&!this.#M.has(d)?(this.#T.add(d),this.#u=!1):this.#u&&!this.#M.has(d)&&(this.#T.add(d),this.#u=!1)}else this.#u&&!this.#M.has(d)&&(this.#T.add(d),this.#u=!1);if(this.#M.add(d),this.#T.has(d))break}this.#Y(n,s.text??"",s.final===!0,{turnId:d,...typeof s.startMs=="number"&&{startMs:s.startMs},...typeof s.endMs=="number"&&{endMs:s.endMs},...this.#R&&{caption:!0}});break}case"delegation_started":case"delegation_completed":{let n=String(s.delegationId??s.turnId);if(s.type==="delegation_started"){this.#ie(t);let r=s.input;this.#R&&r&&this.#me(n,{delegationId:n,userText:String(r.text??""),userUtteranceIds:Array.isArray(r.userUtteranceIds)?r.userUtteranceIds.filter(d=>typeof d=="string"):[],messages:Array.isArray(r.messages)?r.messages:[]},t)}else s.speak!==!1&&this.#S.has(n)&&!this.#k.delete(n)&&!this.#d.has("delegation_read_back")&&this.#re(n);this.#I=s.type==="delegation_started",!this.#g&&!this.#G()&&this.#t(this.#I?"processing":"listening");break}case"delegation_progress":{let n=String(s.delegationId);this.#S.has(n)&&!this.#k.has(n)&&!this.#C.has(n)&&(this.#k.add(n),this.#re(n));break}case"delegation_cancelled":this.#oe(String(s.delegationId),s.reason!=="session_ending"&&s.reason!=="provider_cancelled");break;case"warning":console.warn(`[Persona voice] ${s.code}: ${s.message??""}`,this.#D??""),s.delegationId&&(s.code==="UNKNOWN_DELEGATION"||s.code==="LATE_RESULT_LIMIT")&&this.#oe(String(s.delegationId));break;case"audio_clear":this.#ce(),this.#V=0,this.#t("listening");break;case"transcript_interim":this.#t("listening"),this.#Y("user",s.text??"",!1);break;case"transcript_final":{let n=s.role==="assistant"?"assistant":"user";this.#t(n==="user"?"processing":"speaking"),this.#Y(n,s.text??"",!0);break}case"audio_end":this.#r?this.#r.markStreamEnd():(this.#g=!1,this.#t("listening"));break;case"metrics":this.#ye({llmMs:s.llm_ms,ttsMs:s.tts_ms,firstAudioMs:s.first_audio_ms,totalMs:s.total_ms});break;case"error":this.#_(new Error(s.error||"Voice error")),this.#t("error");break;case"session_end":this.#L={reason:String(s.reason),...typeof s.message=="string"&&{message:s.message}};break}}async#pe(){let e=this.bridge?.getHistory()??[],t="";try{let s=this.config?.callContext;t=String((typeof s=="function"?await s():s)??"")}catch{}return ze(e,t)}#ie(e){let t=this.#N;if(!t)return;this.#N=null;let s=!1,n=t.then(r=>{let d=this.#e;s||!r||e!==this.#s||d?.readyState!==WebSocket.OPEN||d.send(JSON.stringify({type:"context",text:r}))});this.#B={done:n,drop:()=>s=!0}}async#ne(){let e=this.#B;if(!e)return;let t,s=await Promise.race([e.done.then(()=>!1),new Promise(n=>{t=setTimeout(()=>n(!0),$e)})]);clearTimeout(t),s&&e.drop()}#re(e){this.#u=!0,this.#H=e}#oe(e,t=!1){this.#C.add(e),this.#H===e&&(this.#u=!1),this.#k.delete(e),this.bridge?.dropDelegation?.(e,t),this.#A.get(e)?.abort()}#me(e,t,s){let n=this.bridge,r=({type:l,...a})=>{let o=this.#e;return s!==this.#s||o?.readyState!==WebSocket.OPEN||this.#C.has(e)?!1:(o.send(JSON.stringify({type:l,delegationId:e,...a})),!0)},d=(l,a,o,c=0)=>r({type:l,status:a,text:o,...c>0&&{streamedChars:c}});this.#W=this.#W.then(async()=>{if(s!==this.#s||this.#C.has(e))return;let l=null,a=this.#d.has("delegation_stream")&&this.#d.has("delegation_read_back"),o=S=>{l=(l??this.#ne()).then(()=>{r({type:"delegation_delta",text:S})&&this.#S.add(e)})},c=await n.runDelegatedTurn(a?{...t,stream:o}:t).catch(()=>({status:"failed",text:""}));await this.#ne(),await l;let u=a?c.streamedChars??0:0,h=!!c.followUp,m=h&&this.#d.has("delegation_update");if(!d(m?"delegation_update":"delegation_result",h&&!m?"completed":c.status,c.text,u)||(c.status!=="failed"&&c.inChat!==!1&&this.#S.add(e),!c.followUp))return;let p=new AbortController;this.#A.set(e,p),c.followUp({signal:p.signal,approvalTimeoutMs:this.config?.approvalTimeoutMs&&Math.min(this.config.approvalTimeoutMs,We),readBack:m,onUpdate:S=>d("delegation_update","pending_approval",S)}).then(S=>{this.#A.delete(e),m&&S&&!p.signal.aborted&&d("delegation_result",S.status,S.text)})})}#ve(e,t){if(t!==this.#s||!this.#r||this.#G())return;let s=Ge(e);s.length!==0&&(this.#g||(this.#g=!0,this.#t("speaking")),this.#K(),this.#r.enqueue(s),this.#f&&this.#Se(s.length))}#G(){return Date.now()<this.#V}#K(){if(this.#w||!this.#r)return;this.#w=!0;let e=this.#s;this.#r.onFinished(()=>{e===this.#s&&(this.#w=!1,this.#ae())})}#Se(e){let t=Date.now();this.#v=Math.max(t,this.#v)+e/48,clearTimeout(this.#P),this.#P=setTimeout(()=>this.#ae(),this.#v-t+Ue)}#ae(){this.#g=!1,this.#v=0,this.#e&&this.#e.readyState===WebSocket.OPEN&&this.#t(this.#I?"processing":"listening")}#ce(){this.#r?.flush(),this.#w=!1,this.#K(),this.#g=!1,this.#v=0,clearTimeout(this.#P)}#m(){this.#s+=1,this.#h=!1,this.#g=!1,this.#O(),this.#f=!1,this.#I=!1,this.#R=!1,this.#d=new Set;for(let e of this.#A.values())e.abort();if(this.#A.clear(),this.#C.clear(),this.#D=void 0,this.#L=null,clearTimeout(this.#Z),this.#$=!1,this.#N=null,this.#B=null,this.#W=Promise.resolve(),this.#S.clear(),this.#k.clear(),this.#H=null,this.#u=!1,this.#M.clear(),this.#T.clear(),this.#w=!1,this.#V=0,this.#v=0,clearTimeout(this.#P),this.#y=[],this.#b=0,this.#l&&(this.#l.onaudioprocess=null,this.#l.disconnect(),this.#l=null),this.#c&&(this.#c.disconnect(),this.#c=null),this.#i&&(this.#i.getTracks().forEach(e=>e.stop()),this.#i=null),this.#n&&(this.#n.close().catch(()=>{}),this.#n=null),this.#r&&(this.#r.destroy(),this.#r=null),this.#e){this.#E=!0;try{this.#e.close(1e3,"client ended call")}catch{}this.#e=null}}onResult(e){this.#Q.push(e)}onError(e){this.#q.push(e)}onStatusChange(e){this.#j.push(e)}onTranscript(e){this.#F.push(e)}onMetrics(e){this.#X.push(e)}#t(e){this.#j.forEach(t=>t(e))}#_(e){this.#q.forEach(t=>t(e))}#Y(e,t,s,n){this.#F.forEach(r=>r(e,t,s,n))}#ye(e){this.#X.forEach(t=>t(e))}};var _=class{constructor(e={}){this.config=e;this.type="browser";this.#e=null;this.#n=[];this.#a=[];this.#i=[];this.#c=!1;this.#l=typeof window<"u"?window:void 0}#e;#n;#a;#i;#c;#l;async connect(){this.#i.forEach(e=>e("connected"))}async startListening(){try{if(this.#c)throw new Error("Already listening");if(!this.#l)throw new Error("Window object not available");let e=this.#l.SpeechRecognition||this.#l.webkitSpeechRecognition;if(!e)throw new 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=t=>{let s=Array.from(t.results).map(r=>r[0]).map(r=>r.transcript).join(""),n=t.results[t.results.length-1].isFinal;this.#n.forEach(r=>r({text:s,confidence:n?.8:.5,provider:"browser"})),n&&!this.config?.continuous&&this.stopListening()},this.#e.onerror=t=>{this.#a.forEach(s=>s(new Error(t.error))),this.#i.forEach(s=>s("error"))},this.#e.onstart=()=>{this.#c=!0,this.#i.forEach(t=>t("listening"))},this.#e.onend=()=>{this.#c=!1,this.#i.forEach(t=>t("idle"))},this.#e.start()}catch(e){throw this.#a.forEach(t=>t(e)),this.#i.forEach(t=>t("error")),e}}async stopListening(){this.#e&&(this.#e.stop(),this.#e=null),this.#c=!1,this.#i.forEach(e=>e("idle"))}onResult(e){this.#n.push(e)}onError(e){this.#a.push(e)}onStatusChange(e){this.#i.push(e)}async disconnect(){await this.stopListening(),this.#i.forEach(e=>e("disconnected"))}static isSupported(){return"SpeechRecognition"in window||"webkitSpeechRecognition"in window}};function D(i){switch(i.type){case"runtype":if(!i.runtype)throw new Error("Runtype voice provider requires configuration");return new R(i.runtype);case"browser":if(!_.isSupported())throw new Error("Browser speech recognition not supported");return new _(i.browser||{});case"custom":{let e=i.custom;if(!e)throw new Error("Custom voice provider requires a `custom` provider instance or factory");let t=typeof e=="function"?e():e;if(!t||typeof t.startListening!="function")throw new Error("Custom voice provider `custom` must be a VoiceProvider (or a factory returning one)");return t}default:throw new Error(`Unknown voice provider type: ${i.type}`)}}function ue(i){if(i?.type==="custom"&&i.custom)return D({type:"custom",custom:i.custom});if(i?.type==="runtype"&&i.runtype)return D({type:"runtype",runtype:i.runtype});if(_.isSupported())return D({type:"browser",browser:i?.browser||{language:"en-US"}});throw new Error("No supported voice providers available")}function Je(i){try{return ue(i),!0}catch{return!1}}var he=i=>i.toLowerCase().replace(/[^\p{L}\p{N}]+/gu,""),Y=class{constructor(e){this.host=e;this.turns=new Map;this.latestId=null;this.cancelled=new Set}apply(e,t,s,n,r,d){let l=this.host;t=t.trim();let a=this.turns.get(n);if(a||(a={},this.turns.set(n,a),this.latestId=n),e==="user"){a.userFinal=s;let o=a.userId?l.find(a.userId):void 0;if(o){let c=a.userStartMs===void 0&&r!==void 0;c&&(a.userStartMs=r),l.upsert({...o,content:t,voiceProcessing:!s,...c&&this.placeBefore(this.startedAfter(r))})}else{a.userStartMs=r;let c=a.assistantId?l.find(a.assistantId):void 0;a.userId=l.inject({role:"user",content:t,streaming:!1,voiceProcessing:!s,voiceCaption:d,...this.placeBefore(this.startedAfter(r)??c)}).id}}else if(!this.cancelled.has(n)){a.assistantFinal=s;let o=a.assistantId?l.find(a.assistantId):void 0;if(o){let c=a.assistantStartMs===void 0&&r!==void 0;c&&(a.assistantStartMs=r),l.upsert({...o,content:t,streaming:!s,voiceProcessing:!s,...c&&this.placeBefore(this.startedAfter(r))})}else t&&(a.assistantStartMs=r,a.assistantId=l.inject({role:"assistant",content:t,streaming:!s,voiceProcessing:!s,voiceCaption:d,...this.placeBefore(this.startedAfter(r))}).id);s&&a.assistantId&&l.markSpoken(a.assistantId)}this.sync()}claimUserTurn(e,t=[]){let s=t[t.length-1];for(let r of t)r!==s&&(this.turns.has(r)||this.turns.set(r,{}),this.turns.get(r).claimed=!0);let n;if(s){if(n=this.turns.get(s),n||(n={},this.turns.set(s,n)),n.claimed)return null;(!n.userId||!this.host.find(n.userId))&&(n.userFinal=!0,n.userId=this.host.inject({role:"user",content:e.trim()}).id)}else{let r=he(e),d=[...this.turns.values()].reverse().flatMap(l=>{let a=l.userId&&!l.claimed?this.host.find(l.userId):void 0;return a?[{turn:l,text:he(a.content)}]:[]}).filter(({text:l})=>l&&r);n=(d.find(({text:l})=>l===r)??d.find(({text:l})=>l.startsWith(r)||r.startsWith(l)))?.turn}return n?(n.claimed=!0,n.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(),s=this.inFlight();if(!t&&s.length===0)return;for(let d of s)this.turns.get(d).assistantFinal=!0;this.closeReplies(s);let n=this.host.inject({role:"assistant",content:e,streaming:!1,voiceProcessing:!1}),r=t?this.turns.get(t):void 0;r&&(r.assistantId=n.id,r.assistantFinal=!0),this.sync()}settle(){if(this.turns.size===0)return;let e=this.pending(),t=new Set;for(let s of this.turns.values())s.userId&&t.add(s.userId),s.assistantId&&(t.add(s.assistantId),this.host.markSpoken(s.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 s of this.turns.values())for(let[n,r]of[[s.userId,s.userStartMs],[s.assistantId,s.assistantStartMs]])n&&r!==void 0&&r>e&&(!t||r<t.start)&&(t={start:r,id:n});return t&&this.host.find(t.id)}placeBefore(e){if(!e)return;let t=e.sequence??0,s=t-1;for(let n of this.turns.values())for(let r of[n.userId,n.assistantId]){let d=r?this.host.find(r):void 0,l=d?.sequence;d?.createdAt===e.createdAt&&l!==void 0&&l>s&&l<t&&(s=l)}return{createdAt:e.createdAt,sequence:(s+t)/2}}closeReplies(e){let t=new Set;for(let s of e){let n=this.turns.get(s)?.assistantId;n&&(t.add(n),this.host.markSpoken(n))}t.size>0&&this.host.settle(t)}inFlight(){let e=[];for(let[t,s]of this.turns)s.assistantId&&!s.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())}};var Ze=new Set(["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"]),Qe=/([.!?]+|[,;:])(["'”’)\]*_]*)(\s+)|\n\s*/g;function et(i){let e=/(\S+)$/.exec(i)?.[1];if(!e)return!1;let t=e.replace(/^[("'“‘[*_]+/,"").toLowerCase();if(Ze.has(t)||/^[a-z](?:\.[a-z])*$/.test(t))return!0;if(/^\d+$/.test(e)){let s=i.length-e.length;return s===0||/\n\s*$/.test(i.slice(0,s))}return!1}function*ge(i,e){let t=new RegExp(Qe.source,"g");for(let s=t.exec(i);s;s=t.exec(i)){let n=s[1];if(!i.slice(0,s.index+(n?.length??0)).trim()||n!==void 0&&(/^[,;:]$/.test(n)&&!e||n==="."&&et(i.slice(0,s.index))))continue;let r=s.index+s[0].length;r<i.length&&(yield r)}}function fe(i,e){let t=i.slice(0,e),s=0;for(let n of t.matchAll(/\s+/g))t.slice(0,n.index).trim()&&(s=n.index+n[0].length);return s}function J(i){let e=0;for(let n of ge(i.slice(0,220),!0))e=n;if(e)return e;let t=fe(i,220);if(t)return t;let s=i.charCodeAt(219);return s>=55296&&s<=56319?219:220}var U=class{#e="";#n=!0;push(e){return this.#e+=e,this.#a()}flush(){let e=this.#a(),t=this.#e;if(this.#e="",t.trim()){for(let s=0;s<t.length;){let n=t.slice(s),r=n.length>220?J(n):n.length;e.push(n.slice(0,r)),s+=r}this.#n=!1}return e}idle(){let e=this.#e;if(!e.trim()||!/(?:[.!?…]["'”’)\]*_]*|\n)\s*$/.test(e))return[];this.#e="",this.#n=!1;let t=[];for(let s=0;s<e.length;){let n=e.slice(s),r=n.length>220?J(n):n.length;t.push(n.slice(0,r)),s+=r}return t}#a(){let e=[];for(let t=this.#i();t>0;t=this.#i())e.push(this.#e.slice(0,t)),this.#e=this.#e.slice(t),this.#n=!1;return e}#i(){let e=this.#e;if(!e.trim())return 0;let t=ge(e,this.#n).next().value??0;if(t&&t<=220)return t;let s=/[.!?]["'”’)\]*_]*$/.test(e);if(this.#n&&!s){let n=e.match(/\S+\s+/g)?.length??0;if(e.trim().length>=30||n>=6){let r=fe(e,220);if(r)return r}}return e.length>220?J(e):0}};var tt=200,st=(i,e)=>{let t=0;for(;t<i.length&&t<e.length&&i[t]===e[t];)t+=1;return t},it=50,nt="I need your answer in the chat before I can continue.",rt=1e3,ot=5*6e4,pe="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)",at=new RegExp(`^(?:${pe})(?: (?:${pe}))?(?: thanks| thank you)?$`),ct=i=>at.test(i.toLowerCase().replace(/[^a-z' ]+/g," ").replace(/\s+/g," ").trim()),me="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.",ve=()=>new Promise(i=>setTimeout(i,it)),Z=(i,e)=>i.length>e?`${i.slice(0,e-1).trimEnd()}\u2026`:i,E=i=>i.replace(/^webmcp:/,"").replace(/([a-z\d])([A-Z])/g,"$1 $2").replace(/[_\-.]+/g," ").trim().toLowerCase();function Q(i,e=0){if(i==null||i==="")return"";if(typeof i!="object")return String(i);if(e>2)return"";if(Array.isArray(i))return i.map(r=>Q(r,e+1)).filter(Boolean).join(", ");let t=i,s=t.quantity??t.qty??t.count,n=t.name??t.item??t.product??t.title;return s!=null&&n!=null&&typeof n!="object"?`${s} ${n}`:Object.entries(t).filter(([r])=>!r.startsWith("_")).map(([r,d])=>{let l=Q(d,e+1);return l&&(e?`${E(r)} ${l}`:`${E(r)}: ${l}`)}).filter(Boolean).join(e?", ":"; ")}function Se(i){let e=i.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:",t=rt-e.length-me.length-2,s=i.map(n=>{let r=[E(n.toolName)];n.description&&r.push(`(${Z(n.description.trim(),160)})`);let d=Q(n.parameters);return d&&r.push(`with ${d}`),n.reason&&r.push(`because: ${Z(n.reason.trim(),160)}`),Z(`- ${r.join(" ")}`,Math.floor(t/i.length)-1)});return`${e}
6
+ ${s.join(`
7
+ `)}
8
+
9
+ ${me}`}var x=i=>i.variant==="approval"&&i.approval?.status==="pending";function lt(i){let e=null,t=null,s=()=>i.track(e??t),n=[],r=new Map,d=new Map,l=(f,p)=>{r.set(f,[...r.get(f)??[],p]),r.size>32&&r.delete(r.keys().next().value)},a=f=>i.messages().find(p=>p.id===f),o=f=>f.approvals.filter(p=>a(p)?.approval?.status==="pending"),c=f=>E(a(f)?.approval?.toolName??""),u=(f,p,S)=>{f.outcome={status:p,text:S};for(let y of o(f))i.decide(y)},h=f=>f.flatMap(p=>i.messages().find(S=>S.id===p)??[]).filter(p=>!p.variant&&p.content.trim()).map(p=>p.content.trim()).join(`
10
+
11
+ `),m=async f=>{do await ve();while(i.busy()&&!(f&&(i.parked()||f.failed)))};return{getHistory:()=>{let f=i.messages().filter(y=>(y.role==="user"||y.role==="assistant")&&!y.variant&&!y.voiceProcessing&&!y.streaming&&y.content),p=!1,S=[];for(let y=f.length-1;y>=0;y-=1){let k=f[y];if(k.role==="user")p=!1;else if(!k.voiceCaption)p=!0;else if(p)continue;S.unshift({role:k.role,content:k.content})}return S},dropDelegation(f,p){d.set(f,!!p),d.size>32&&d.delete(d.keys().next().value);let S=p&&n.find(y=>y.delegationId===f);S&&!S.outcome&&u(S,"timeout","");for(let y of r.get(f)??[])y.stopStream?.(),y.dropped=!0,y.ids.length&&i.unspoken(y.ids)},async runDelegatedTurn({delegationId:f,userText:p,userUtteranceIds:S,stream:y}){let k=n.filter(g=>o(g).length),$=k.flatMap(o);if($.length===1&&ct(p)){let g=c($[0]);return u(k[0],"denied",""),{status:"denied",text:`Okay, I cancelled the ${g} request. Nothing was done.`,inChat:!1}}let ee=i.parked()&&i.messages().every(g=>!x(g)||$.includes(g.id));i.busy()&&!ee&&await m();let ye=new Set(i.messages().map(g=>g.id)),B=()=>i.messages().filter(g=>!ye.has(g.id)&&g.variant==="approval"),w={ids:[],failed:!1},I=y?new U:null,L="",te="",V=!1,W=g=>{for(let v of g)te+=v,y(v)},P;I&&(w.onUpdate=()=>{if(V)return;let g=h(w.ids);if(!g.startsWith(L)){V=!0,clearTimeout(P);return}if(g.length===L.length)return;let v=g.slice(L.length);L=g,W(I.push(v)),clearTimeout(P),P=setTimeout(()=>{V||W(I.idle())},tt)},w.stopStream=()=>{clearTimeout(P),V=!0,w.onUpdate=void 0}),l(f,w),e=w,s();try{await i.send(p,i.claim(p,S)??void 0),await m(w)}catch{w.failed=!0}finally{e=null,s()}I&&(w.onUpdate?.(),clearTimeout(P),V||W(I.flush()),w.onUpdate=void 0,w.stopStream=void 0);let H=g=>{let v=st(te,g);return v>0?{streamedChars:v}:{}},be=w.ids.flatMap(g=>i.messages().find(v=>v.id===g)??[]),C=h(w.ids),N=w.failed?[]:B().filter(x),we=new Set(N.map(g=>E(g.approval.toolName)));for(let g of k){if(g.outcome)continue;for(let A of o(g).filter(q=>we.has(c(q))))g.replaced.add(A),i.decide(A);let v=c(g.approvals[0]);g.approvals.every(A=>g.replaced.has(A))?g.outcome={status:"cancelled",text:`The earlier ${v} request was replaced by the new one; it was not done.`}:ee&&g.approvals.every(A=>a(A)?.approval?.status==="denied")&&(g.outcome={status:"cancelled",text:`The earlier ${v} request was replaced by the new one; it was not done.`})}if(N.length){let g=new Set(N.map(A=>A.id)),v={delegationId:f,approvals:[...g],at:Date.now(),replaced:new Set};return n.push(v),d.get(f)&&u(v,"timeout",""),C=`${C}
12
+
13
+ ${Se(N.map(A=>A.approval))}`.trim(),{status:"pending_approval",text:C,...H(C),followUp:async({signal:A,approvalTimeoutMs:q=ot,readBack:se=!0,onUpdate:Ae})=>{let M={ids:[],failed:!1};r.delete(f),l(f,M);let ie=()=>B().filter(b=>g.has(b.id)||M.ids.includes(b.id)),Ce=()=>B().filter(b=>x(b)&&!g.has(b.id)&&!n.some(T=>T.approvals.includes(b.id))&&(M.ids.includes(b.id)||b.approval?.toolType==="webmcp"&&t===M)),ne=()=>{t=M,s()};se&&ne();try{for(;!A.aborted&&!v.outcome&&(e||i.busy()||ie().some(x));){se&&t!==M&&!o(v).length&&ne();let b=Ce();if(b.length){for(let T of b)g.add(T.id),v.approvals.push(T.id);v.at=Date.now(),Ae?.(Se(b.map(T=>T.approval)))}if(Date.now()-v.at>=q&&o(v).length&&(!i.busy()||i.parked())){u(v,"timeout",`That ${c(v.approvals[0])} request expired, so nothing was done.`);break}await ve()}}finally{t===M&&(t=null,s()),n.splice(n.indexOf(v),1)}if(A.aborted)return null;if(v.outcome)return v.outcome;if(M.failed)return{status:"failed",text:`The ${c(v.approvals[0])} request didn't complete.`};let re=ie(),j=b=>re.filter(b).map(T=>E(T.approval.toolName)).join(", "),F=re.some(b=>b.approval?.status==="approved"),X=j(b=>b.approval?.status==="denied"&&!v.replaced.has(b.id)),z=j(b=>v.replaced.has(b.id)),G=j(b=>b.approval?.status==="timeout"),ke=[F?h(M.ids):"",X&&`The user declined the ${X} request in the chat, so ${F?"that part was not done":"nothing was done"}.`,z&&`The earlier ${z} request was replaced by the new one; it was not done.`,G&&`The ${G} request timed out, so it was not done.`].filter(Boolean).join(`
14
+
15
+ `);return{status:F?"completed":X?"denied":z?"cancelled":G?"timeout":"completed",text:ke}}}}return!w.failed&&i.parked()||be.some(g=>g.agentMetadata?.awaitingLocalTool&&!g.agentMetadata.askUserQuestionAnswered&&!g.toolCall?.name?.startsWith("webmcp:"))?(C=`${C}
16
+
17
+ ${nt}`.trim(),{status:w.failed?"failed":"completed",text:C,...H(C)}):{status:!w.failed&&C?"completed":"failed",text:C,...H(C)}}}}var dt=(i,e,t,s)=>{let n=i.session;try{i.keyed=t?new t({find:o=>n.messages.find(c=>c.id===o),inject:o=>n.injectMessage(o),upsert:o=>n.upsertMessage(o),settle:o=>{n.messages=n.messages.map(c=>o.has(c.id)?{...c,streaming:!1,voiceProcessing:!1}:c),n.callbacks.onMessagesChanged([...n.messages])},setStreaming:o=>{(o||!i.busy())&&i.setStreaming(o)},markSpoken:o=>{n.ttsSpokenMessageIds.add(o)}}):null,s&&e.setSessionBridge&&e.setSessionBridge(s({messages:()=>n.messages,busy:()=>i.busy(),parked:()=>n.webMcpApprovalResolvers.size>0,claim:(o,c)=>i.keyed?.claimUserTurn(o,c)??null,send:(o,c)=>n.sendMessage(o,{viaVoice:!0,voiceTurn:{userMessageId:c}}),track:o=>{i.setDelegation(o)},unspoken:o=>{for(let c of o)n.ttsSpokenMessageIds.delete(c);n.streaming||n.speakLatestAssistantMessage(o)},decide:o=>{if(n.webMcpApprovalResolvers.has(o))return n.resolveWebMcpApproval(o,"denied");let c=n.messages.find(u=>u.id===o)?.approval;c?.status==="pending"&&n.resolveApproval(c,"denied")}}));let r=i.generation(),d=()=>i.provider()===e&&r===i.generation(),a=(n.config.voiceRecognition??{}).processingErrorText??"Voice processing failed. Please try again.";e.onResult(o=>{d()&&o.provider!=="runtype"&&o.text&&o.text.trim()&&n.sendMessage(o.text,{viaVoice:!0})}),e.onTranscript&&e.onTranscript((o,c,u,h)=>{if(d()){if(h?.turnId){i.keyed?.apply(o,c,u,h.turnId,h.startMs,h.caption);return}if(o==="user"){if(i.pendingUser)n.upsertMessage({id:i.pendingUser,role:"user",content:c,createdAt:new Date().toISOString(),streaming:!1,voiceProcessing:!u});else{let m=n.injectMessage({role:"user",content:c,streaming:!1,voiceProcessing:!u});i.pendingUser=m.id}if(u){i.turns().start(h?.turnId),i.pendingUser=null;let m=n.injectMessage({role:"assistant",content:"",streaming:!0,voiceProcessing:!0});i.pendingAssistant=m.id,i.setStreaming(!0)}}else{if(!i.turns().accepts(h?.turnId))return;if(i.pendingAssistant)n.upsertMessage({id:i.pendingAssistant,role:"assistant",content:c,createdAt:new Date().toISOString(),streaming:!u,voiceProcessing:!u});else{let m=n.injectMessage({role:"assistant",content:c,streaming:!u,voiceProcessing:!u});i.pendingAssistant=m.id}u&&(i.pendingAssistant&&n.ttsSpokenMessageIds.add(i.pendingAssistant),i.setStreaming(!1),i.pendingAssistant=null)}}}),e.onLevel&&e.onLevel(o=>{d()&&i.setLevel(Number.isFinite(o)?Math.max(0,Math.min(1,o)):0)}),e.onMetrics&&e.onMetrics(o=>{d()&&n.config.voiceRecognition?.onMetrics?.(o)}),e.onError(o=>{d()&&(console.error("Voice error:",o),i.pendingAssistant&&(n.upsertMessage({id:i.pendingAssistant,role:"assistant",content:a,createdAt:new Date().toISOString(),streaming:!1,voiceProcessing:!1}),i.setStreaming(!1),i.pendingUser=null,i.pendingAssistant=null),i.keyed?.fail(a))}),e.onStatusChange(o=>{d()&&(i.setStatus(o),(o==="listening"||o==="idle"||o==="disconnected")&&i.settlePending(o!=="listening"),(o==="idle"||o==="disconnected")&&i.keyed?.settle(),n.callbacks.onVoiceStatusChanged?.(o))}),e.connect()}catch(r){console.error("Failed to setup voice:",r)}};var ut=i=>{let e=a=>{if(i.original)return;let o=i.config().voiceRecognition??{};i.original={backgroundColor:a.style.backgroundColor,color:a.style.color,borderColor:a.style.borderColor,iconName:o.iconName??"mic",iconSize:parseFloat(o.iconSize??"")||i.iconFallbackPx}},t=(a,o,c)=>{let u=a.querySelector("svg");u&&u.remove();let h=i.original?.iconSize??(parseFloat(i.config().voiceRecognition?.iconSize??"")||i.iconFallbackPx),m=i.renderIcon(o,h,c,1.5);m&&a.appendChild(m)},s=a=>{a.classList.remove("persona-voice-recording","persona-voice-processing","persona-voice-speaking")};return{recording:()=>{let a=i.mic();if(!a)return;e(a);let o=i.config().voiceRecognition??{},c=o.recordingBackgroundColor,u=o.recordingIconColor,h=o.recordingBorderColor;if(s(a),a.classList.add("persona-voice-recording"),i.setMicState("recording"),a.style.backgroundColor=c??"var(--persona-voice-recording-bg, #ef4444)",a.style.color=u??"var(--persona-voice-recording-indicator, #ffffff)",u){let m=a.querySelector("svg");m&&m.setAttribute("stroke",u)}h&&(a.style.borderColor=h),a.setAttribute("aria-label","Stop voice recognition")},processing:()=>{let a=i.mic();if(!a)return;e(a);let o=i.config().voiceRecognition??{},c=i.session().getVoiceInterruptionMode(),u=i.original,h=o.processingIconName??"loader",m=o.processingIconColor??u?.color??"",f=o.processingBackgroundColor??u?.backgroundColor??"",p=o.processingBorderColor??u?.borderColor??"";s(a),a.classList.add("persona-voice-processing"),i.setMicState("processing"),a.style.backgroundColor=f,a.style.borderColor=p;let S=m||"currentColor";a.style.color=S,t(a,h,S),a.setAttribute("aria-label","Processing voice input"),c==="none"&&(a.style.cursor="default")},speaking:()=>{let a=i.mic();if(!a)return;e(a);let o=i.config().voiceRecognition??{},c=i.session().getVoiceInterruptionMode(),u=i.original,h=c==="cancel"?"square":c==="barge-in"?"mic":"volume-2",m=o.speakingIconName??h,f=o.speakingIconColor??(c==="barge-in"?o.recordingIconColor??u?.color??"":u?.color??""),p=o.speakingBackgroundColor??(c==="barge-in"?o.recordingBackgroundColor??"var(--persona-voice-recording-bg, #ef4444)":u?.backgroundColor??""),S=o.speakingBorderColor??(c==="barge-in"?o.recordingBorderColor??"":u?.borderColor??"");s(a),a.classList.add("persona-voice-speaking"),i.setMicState("speaking"),a.style.backgroundColor=p,a.style.borderColor=S;let y=f||"currentColor";a.style.color=y,t(a,m,y);let k=c==="cancel"?"Stop playback and re-record":c==="barge-in"?"Speak to interrupt":"Agent is speaking";a.setAttribute("aria-label",k),c==="none"&&(a.style.cursor="default"),c==="barge-in"&&a.classList.add("persona-voice-recording")},reset:()=>{let a=i.mic();if(!a)return;s(a),i.setMicState("idle");let o=i.original;o&&(a.style.backgroundColor=o.backgroundColor??"",a.style.color=o.color??"",a.style.borderColor=o.borderColor??"",t(a,o.iconName,o.color||"currentColor"),i.original=null),a.style.cursor="",a.setAttribute("aria-label","Start voice recognition")}}};export{_ as BrowserVoiceProvider,Y as KeyedVoiceTranscript,R as RuntypeVoiceProvider,ue as createBestAvailableVoiceProvider,ut as createMicStateStyles,D as createVoiceProvider,lt as createVoiceSessionBridge,Je as isVoiceSupported,dt as wireSessionVoice};
@@ -1,17 +1,17 @@
1
- "use strict";var $=Object.defineProperty;var ve=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames;var Se=Object.prototype.hasOwnProperty;var ke=(i,e)=>{for(var t in e)$(i,t,{get:e[t],enumerable:!0})},Ae=(i,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of we(e))!Se.call(i,n)&&n!==t&&$(i,n,{get:()=>e[n],enumerable:!(s=ve(e,n))||s.enumerable});return i};var Ce=i=>Ae($({},"__esModule",{value:!0}),i);var tt={};ke(tt,{BrowserVoiceProvider:()=>T,KeyedVoiceTranscript:()=>R,RuntypeVoiceProvider:()=>x,createBestAvailableVoiceProvider:()=>H,createMicStateStyles:()=>pe,createVoiceProvider:()=>I,createVoiceSessionBridge:()=>de,isVoiceSupported:()=>ne,wireSessionVoice:()=>ue});module.exports=Ce(tt);var V=class{#e=null;#r=0;#d=[];#i=[];#a=[];#c=!1;#f=!1;#m=0;#n=!1;#p=!1;#l;#t=[];#y=0;#M=!1;#o;#u;#g;#h=null;constructor(e=24e3,t={}){this.#u=e;let s=Math.max(0,t.prebufferMs??0);this.#g=Math.round(e*s/1e3),this.#l=this.#g>0}#b(){if(!this.#e){let t=typeof window<"u"?window:void 0;if(!t)throw new Error("AudioPlaybackManager requires a browser environment");let s=t.AudioContext||t.webkitAudioContext;this.#e=new s({sampleRate:this.#u})}let e=this.#e;return e.state==="suspended"&&!this.#p&&e.resume(),e}enqueue(e){if(e.length===0)return;let t=e;if(this.#h){let n=new Uint8Array(this.#h.length+e.length);n.set(this.#h),n.set(e,this.#h.length),t=n,this.#h=null}if(t.length%2!==0&&(this.#h=new Uint8Array([t[t.length-1]]),t=t.subarray(0,t.length-1)),t.length===0)return;let s=this.#S(t);s.length!==0&&(this.#l?(this.#t.push(s),this.#y+=s.length,clearTimeout(this.#o),this.#y>=this.#g?this.#v():this.#M&&(this.#o=setTimeout(()=>this.#v(),this.#g/this.#u*1e3))):this.#w(s))}markStreamEnd(){this.#t.length>0&&this.#v(),this.#f=!0,this.#k()}flush(){for(let e of this.#d){e.onended=null;try{e.stop(),e.disconnect()}catch{}}this.#d=[],this.#m=0,this.#r=0,this.#c=!1,this.#f=!1,this.#i=[],this.#a=[],this.#h=null,this.#t=[],this.#y=0,this.#l=this.#g>0,this.#n=!1,clearTimeout(this.#o)}setContinuousMode(e){this.#M=e}isPlaying(){return this.#c}onFinished(e){this.#i.push(e)}onStarted(e){this.#a.push(e)}pause(){this.#p=!0,this.#e&&this.#e.state==="running"&&this.#e.suspend()}resume(){this.#p=!1,this.#e&&this.#e.state==="suspended"&&this.#e.resume()}async destroy(){this.flush(),this.#e&&(await this.#e.close(),this.#e=null)}#v(){this.#l=!1;let e=this.#t;this.#t=[],this.#y=0;for(let t of e)this.#w(t)}#w(e){if(e.length===0)return;let t=this.#b(),s=t.createBuffer(1,e.length,this.#u);s.getChannelData(0).set(e);let n=t.createBufferSource();n.buffer=s,n.connect(t.destination);let r=t.currentTime;if(this.#r===0?this.#r=r:this.#r<r&&(this.#r=r,this.#g>0&&(this.#l=!0)),n.start(this.#r),this.#r+=s.duration,this.#d.push(n),this.#m++,this.#c=!0,!this.#n){this.#n=!0;let c=this.#a.slice();this.#a=[];for(let d of c)d()}n.onended=()=>{let c=this.#d.indexOf(n);c!==-1&&(this.#d.splice(c,1),this.#m--,this.#k())}}#k(){if(this.#f&&this.#m<=0&&this.#t.length===0){this.#c=!1,this.#f=!1;let e=this.#i.slice();this.#i=[];for(let t of e)t()}}#S(e){let t=Math.floor(e.length/2),s=new Float32Array(t),n=new DataView(e.buffer,e.byteOffset,e.byteLength);for(let r=0;r<t;r++){let c=n.getInt16(r*2,!0);s[r]=c/32768}return s}};var Q="4.27.0";var ee=Q;var F=16e3,Te=24e3,Ee=4096,xe=F*2*8,_e=4,Ie=1380533830,Pe=3e4,Ve=1e3,je=5e3,Re=3e4,Le=3e4,Oe=6e5,Ne="full-duplex-v1",De=300,qe=2e3,Ue=2e3,Be="runtype-browser-v1",We=54e4,$e="You're talking to an AI assistant. Voice is processed by OpenAI.",Fe=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."]]),te=["provider_error","server_restart"],j="Voice connection lost.",He=8e3,ze=4e3,Xe=12,se=2e3;function Ge(i,e){let t="Conversation so far:",s=e.slice(0,ze).trim(),n=He-(s?s.length+2:0)-t.length,r=[];for(let d of i.slice(-Xe).reverse()){let a=d.content.replace(/\s+/g," ").trim();if(!a)continue;a.length>se&&(a=`${a.slice(0,se-1)}\u2026`);let o=`${d.role==="user"?"User":"Assistant"}: ${a}`;if(o.length+1>n)break;n-=o.length+1,r.unshift(o)}let c=r.length>0?[`${t}
1
+ "use strict";var J=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Ve=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var je=(n,e)=>{for(var t in e)J(n,t,{get:e[t],enumerable:!0})},Le=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ve(e))!Re.call(n,i)&&i!==t&&J(n,i,{get:()=>e[i],enumerable:!(s=Pe(e,i))||s.enumerable});return n};var Ne=n=>Le(J({},"__esModule",{value:!0}),n);var St={};je(St,{BrowserVoiceProvider:()=>_,KeyedVoiceTranscript:()=>U,RuntypeVoiceProvider:()=>E,createBestAvailableVoiceProvider:()=>Q,createMicStateStyles:()=>Ce,createVoiceProvider:()=>R,createVoiceSessionBridge:()=>Ae,isVoiceSupported:()=>ge,wireSessionVoice:()=>ke});module.exports=Ne(St);var N=class{#e=null;#i=0;#r=[];#n=[];#c=[];#l=!1;#m=!1;#y=0;#o=!1;#p=!1;#d;#t=[];#b=0;#_=!1;#a;#u;#g;#h=null;constructor(e=24e3,t={}){this.#u=e;let s=Math.max(0,t.prebufferMs??0);this.#g=Math.round(e*s/1e3),this.#d=this.#g>0}#w(){if(!this.#e){let t=typeof window<"u"?window:void 0;if(!t)throw new Error("AudioPlaybackManager requires a browser environment");let s=t.AudioContext||t.webkitAudioContext;this.#e=new s({sampleRate:this.#u})}let e=this.#e;return e.state==="suspended"&&!this.#p&&e.resume(),e}enqueue(e){if(e.length===0)return;let t=e;if(this.#h){let i=new Uint8Array(this.#h.length+e.length);i.set(this.#h),i.set(e,this.#h.length),t=i,this.#h=null}if(t.length%2!==0&&(this.#h=new Uint8Array([t[t.length-1]]),t=t.subarray(0,t.length-1)),t.length===0)return;let s=this.#f(t);s.length!==0&&(this.#d?(this.#t.push(s),this.#b+=s.length,clearTimeout(this.#a),this.#b>=this.#g?this.#S():this.#_&&(this.#a=setTimeout(()=>this.#S(),this.#g/this.#u*1e3))):this.#A(s))}markStreamEnd(){this.#t.length>0&&this.#S(),this.#m=!0,this.#k()}flush(){for(let e of this.#r){e.onended=null;try{e.stop(),e.disconnect()}catch{}}this.#r=[],this.#y=0,this.#i=0,this.#l=!1,this.#m=!1,this.#n=[],this.#c=[],this.#h=null,this.#t=[],this.#b=0,this.#d=this.#g>0,this.#o=!1,clearTimeout(this.#a)}setContinuousMode(e){this.#_=e}isPlaying(){return this.#l}onFinished(e){this.#n.push(e)}onStarted(e){this.#c.push(e)}pause(){this.#p=!0,this.#e&&this.#e.state==="running"&&this.#e.suspend()}resume(){this.#p=!1,this.#e&&this.#e.state==="suspended"&&this.#e.resume()}async destroy(){this.flush(),this.#e&&(await this.#e.close(),this.#e=null)}#S(){this.#d=!1;let e=this.#t;this.#t=[],this.#b=0;for(let t of e)this.#A(t)}#A(e){if(e.length===0)return;let t=this.#w(),s=t.createBuffer(1,e.length,this.#u);s.getChannelData(0).set(e);let i=t.createBufferSource();i.buffer=s,i.connect(t.destination);let r=t.currentTime;if(this.#i===0?this.#i=r:this.#i<r&&(this.#i=r,this.#g>0&&(this.#d=!0)),i.start(this.#i),this.#i+=s.duration,this.#r.push(i),this.#y++,this.#l=!0,!this.#o){this.#o=!0;let l=this.#c.slice();this.#c=[];for(let d of l)d()}i.onended=()=>{let l=this.#r.indexOf(i);l!==-1&&(this.#r.splice(l,1),this.#y--,this.#k())}}#k(){if(this.#m&&this.#y<=0&&this.#t.length===0){this.#l=!1,this.#m=!1;let e=this.#n.slice();this.#n=[];for(let t of e)t()}}#f(e){let t=Math.floor(e.length/2),s=new Float32Array(t),i=new DataView(e.buffer,e.byteOffset,e.byteLength);for(let r=0;r<t;r++){let l=i.getInt16(r*2,!0);s[r]=l/32768}return s}};var le="4.28.1";var de=le;var Z=16e3,Ue=24e3,De=4096,Be=Z*2*8,qe=4,$e=1380533830,We=3e4,He=1e3,Fe=5e3,ze=3e4,Xe=3e4,Ge=6e5,Ke="full-duplex-v1",Ye=300,Je=2e3,Ze=2e3,Qe="runtype-browser-v1",et=54e4,tt="You're talking to an AI assistant. Voice is processed by OpenAI.",st=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."]]),ue=["provider_error","server_restart"],O="Voice connection lost.",it=8e3,nt=4e3,rt=12,pe=2e3;function ot(n,e){let t="Conversation so far:",s=e.slice(0,nt).trim(),i=it-(s?s.length+2:0)-t.length,r=[];for(let d of n.slice(-rt).reverse()){let a=d.content.replace(/\s+/g," ").trim();if(!a)continue;a.length>pe&&(a=`${a.slice(0,pe-1)}\u2026`);let o=`${d.role==="user"?"User":"Assistant"}: ${a}`;if(o.length+1>i)break;i-=o.length+1,r.unshift(o)}let l=r.length>0?[`${t}
2
2
  ${r.join(`
3
- `)}`]:[];return s&&c.push(s),c.join(`
3
+ `)}`]:[];return s&&l.push(s),l.join(`
4
4
 
5
- `)}function Ke(i){return i.byteLength>=44&&new DataView(i).getUint32(0,!1)===Ie?new Uint8Array(i,44):new Uint8Array(i)}function ie(i){let e=i.replace(/\/+$/,"");return/^wss?:\/\//i.test(e)?e:/^https?:\/\//i.test(e)?e.replace(/^http/i,"ws"):`${typeof window<"u"&&window.location?.protocol==="https:"?"wss:":"ws:"}//${e}`}function Je(i){return ie(i).replace(/^ws/i,"http")}function Ye(i){return typeof i!="number"||!Number.isFinite(i)?Re:Math.min(Oe,Math.max(Le,Math.round(i)))}var x=class{constructor(e){this.config=e;this.type="runtype";this.#e=null;this.#r=null;this.#d=[];this.#i=null;this.#a=null;this.#c=null;this.#f=[];this.#m=0;this.#n=null;this.#p=!1;this.#l=!1;this.#t=0;this.#y=!1;this.#M=Number.NEGATIVE_INFINITY;this.#o=null;this.#u=!1;this.#g=!1;this.#h=0;this.#b=0;this.#w=!1;this.bridge=null;this.#k=!1;this.#S=new Set;this.#T=new Map;this.#_=new Set;this.#I=null;this.#A=null;this.#N=!1;this.#D=!1;this.#q=!1;this.#P=null;this.#U=null;this.#B=Promise.resolve();this.#V=new Set;this.#E=!1;this.#j=new Set;this.#R=new Set;this.#Y=[];this.#W=[];this.#$=[];this.#F=[];this.#H=[]}#e;#r;#d;#i;#a;#c;#f;#m;#n;#p;#l;#t;#y;#M;#o;#u;#g;#h;#b;#v;#w;#k;#S;#T;#_;#O;#I;#A;#J;#N;#D;#q;#P;#U;#B;#V;#E;#j;#R;#Y;#W;#$;#F;#H;async connect(){}setSessionBridge(e){this.bridge=e}prewarm(){if(this.#p||this.#o)return;let e=this.config?.agentId,t=this.config?.clientToken,s=this.config?.host;if(!e||!t||!s)return;let n=Date.now();if(!(n-this.#M<Pe)){this.#M=n;try{this.config?.prewarmMode==="attach"?this.#oe(s,e,t):this.#re(s,e,t)}catch{}}}#re(e,t,s){if(typeof fetch!="function")return;let n=`${Je(e)}/v1/client/agents/${encodeURIComponent(t)}/voice/prewarm`;fetch(n,{method:"POST",headers:{Authorization:`Bearer ${s}`},keepalive:!0}).catch(()=>{})}#oe(e,t,s){let n=new URLSearchParams,r=this.config?.attachIdleMs,c=Ye(r);r!==void 0&&n.set("attachIdleMs",String(c));let d=new WebSocket(this.#Q(e,t,n),["runtype.bearer","runtype.attach",s]);d.binaryType="arraybuffer";let a=()=>{},o=new Promise(u=>{a=u}),l={ws:d,state:"connecting",ready:o,settle:a,openedAt:0,idleTimer:void 0};this.#o=l,d.onopen=()=>{this.#o===l&&(l.state=d.protocol==="runtype.attach"?"attached":"live",l.openedAt=Date.now(),this.#Z(l,c),l.state==="attached"&&d.send('{"type":"ping"}'),l.settle())},d.onmessage=u=>{if(this.#o!==l||typeof u.data!="string")return;let p;try{p=JSON.parse(u.data)}catch{return}p.type==="attached"&&typeof p.idleMs=="number"&&this.#Z(l,p.idleMs-(Date.now()-l.openedAt))},d.onerror=()=>{},d.onclose=()=>{this.#o===l&&this.#L()}}#Z(e,t){clearTimeout(e.idleTimer),e.idleTimer=setTimeout(()=>{this.#o===e&&this.#L()},Math.max(0,t))}#L(){let e=this.#o;if(!e)return;this.#o=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#ae(){let e=this.#o;if(!e)return null;if(e.state==="connecting"){let t;await Promise.race([e.ready,new Promise(s=>{t=setTimeout(s,je)})]),clearTimeout(t)}return this.#o!==e?null:e.state==="connecting"||e.ws.readyState!==WebSocket.OPEN?(this.#L(),null):(this.#o=null,clearTimeout(e.idleTimer),{ws:e.ws,live:e.state==="live"})}#Q(e,t,s){let n=["partial_transcript","context"];this.bridge&&this.config?.clientDelegation!==!1&&n.push("client_delegation","delegation_update","delegation_read_back"),s&&n.unshift("attach");let r=new URLSearchParams({voiceProtocol:Be,clientVersion:`persona/${ee}`,voiceCapabilities:Ne,clientCapabilities:n.join(",")});return s?.forEach((c,d)=>r.set(d,c)),`${ie(e)}/ws/agents/${encodeURIComponent(t)}/voice?${r}`}async startListening(){if(this.#p)return;let e=this.#D;e||(this.#N=!1,this.#A=null),this.#D=!1;let t=this.config?.agentId,s=this.config?.clientToken,n=this.config?.host;if(!t)throw new Error("Runtype voice requires an agentId");if(!s)throw new Error("Runtype voice requires a clientToken");if(!n)throw new Error("Runtype voice requires a host (or widget apiUrl)");let r=++this.#t;this.#y=!1,this.#p=!0;try{let c=await navigator.mediaDevices.getUserMedia({audio:{sampleRate:F,channelCount:1,echoCancellation:!0}});if(r!==this.#t){c.getTracks().forEach(p=>p.stop());return}this.#i=c;let d=window.AudioContext||window.webkitAudioContext,a=new d({sampleRate:F});if(this.#r=a,a.state==="suspended"){if(await Promise.race([a.resume().catch(()=>{}),new Promise(p=>setTimeout(p,e?500:Ve))]),r!==this.#t)return;if(a.state!=="running")throw e?new Error(this.#A=`${j} Tap the mic to reconnect.`):new Error("Audio blocked until a tap")}let o=this.config?.createPlaybackEngine?await this.config.createPlaybackEngine():new V(Te);if(r!==this.#t){o.destroy(),c.getTracks().forEach(p=>p.stop()),a.close().catch(()=>{});return}this.#n=o,this.#G(),this.#le(a,c,r);let l=await this.#ae();if(r!==this.#t){l?.ws.close(1e3,"client ended call");return}if(l){let{ws:p}=l;this.#e=p,this.#ee(p,r),l.live||p.send('{"type":"start"}'),this.#z(p),this.#s("listening");return}let u=new WebSocket(this.#Q(n,t),["runtype.bearer",s]);u.binaryType="arraybuffer",this.#e=u,u.onopen=()=>{r===this.#t&&(this.#z(u),this.#s("listening"))},this.#ee(u,r)}catch(c){throw this.#C(),this.#x(c),this.#s("error"),c}}#ee(e,t){e.onmessage=s=>this.#de(s,t),e.onerror=()=>{t!==this.#t||this.#I||(this.#x(new Error("Voice connection failed")),this.#s("error"),this.#C())},e.onclose=s=>{if(this.#y){this.#y=!1;return}if(t!==this.#t)return;let n=this.#I??(s.code===4408?{reason:"idle_timeout"}:null);if(!n){if(s.code!==1e3){let r=s.code?` (code ${s.code})`:"";this.#x(new Error(`Voice connection closed${r}`)),this.#s("error")}else this.#s("idle");this.#C();return}this.#ce(n.reason,n.message)}}#ce(e,t){let s=te.includes(e)&&!this.#N;if(this.#C(),s){this.#N=!0,this.#p=!0,this.#A=e==="provider_error"?`${j} Reconnecting\u2026`:"Reconnecting\u2026",this.#J=setTimeout(()=>{this.#p=!1,this.#D=!0,this.startListening().catch(()=>{})},1e3+Math.random()*1e3),this.#s("idle");return}if(te.includes(e))return this.#A=j,this.#x(new Error(j)),this.#s("error");if(e==="error")return this.#s("error");this.#A=e==="quota"&&t||Fe.get(e)||null,this.#s("idle")}takeNotice(){let e=this.#A;return this.#A=null,e}getDisclosure(){let e=this.config?.disclosureText;return this.#p&&this.#u&&e!==!1?e||$e:null}async stopListening(){this.#C(),this.#s("idle")}async disconnect(){this.#C(),this.#s("disconnected"),this.#Y=[],this.#W=[],this.#$=[],this.#F=[],this.#H=[]}stopPlayback(){this.#ne();let e=this.#e;e&&e.readyState===WebSocket.OPEN&&(this.#u&&(this.#h=Date.now()+qe,e.send('{"type":"cancel"}')),this.#s("listening"))}getInterruptionMode(){return"barge-in"}isBargeInActive(){return this.#p}onLevel(e){this.#d.push(e)}async deactivateBargeIn(){this.#C(),this.#s("idle")}#le(e,t,s){let n=e.createMediaStreamSource(t);this.#a=n;let r=e.createScriptProcessor(Ee,1,1);this.#c=r,r.onaudioprocess=c=>{if(s!==this.#t)return;let d=this.#e,a=d?.readyState===WebSocket.OPEN;if(d&&!a&&d.readyState!==WebSocket.CONNECTING)return;let o=c.inputBuffer.getChannelData(0),l=new Int16Array(o.length),u=0;for(let p=0;p<o.length;p++){let m=Math.max(-1,Math.min(1,o[p]));u+=m*m,l[p]=m<0?m*32768:m*32767}if(d&&a)this.#z(d),d.send(l.buffer);else for(this.#f.push(l.buffer),this.#m+=l.byteLength;this.#m>xe;)this.#m-=this.#f.shift().byteLength;if(this.#d.length>0){let p=Math.sqrt(u/o.length),m=Math.max(0,Math.min(1,p*_e));for(let h of this.#d)h(m)}},n.connect(r),r.connect(e.destination)}#z(e){for(let t of this.#f)e.send(t);this.#f=[],this.#m=0}#de(e,t){if(t!==this.#t)return;if(e.data instanceof ArrayBuffer){this.#ge(e.data,t);return}let s;try{s=JSON.parse(e.data)}catch{return}switch(s.type){case"session_config":s.speechMode&&(this.#u=s.speechMode==="speech_to_speech",this.#n?.setContinuousMode?.(this.#u)),Array.isArray(s.capabilities)&&(this.#S=new Set(s.capabilities)),typeof s.callId=="string"&&(this.#O=s.callId),this.#k=this.#u&&this.#S.has("client_delegation")&&!!this.bridge,this.#u&&!this.#l&&this.#s("listening"),this.#S.has("context")&&!this.#q&&(this.#q=!0,this.#P=this.#ue());break;case"transcript_update":{let n=s.role==="assistant"?"assistant":"user",r=s.utteranceId??s.turnId;if(!r||n==="assistant"&&this.#X())break;let c=String(r);if(n==="user")s.final===!0&&this.#te(t),this.#E=!1;else{if(this.#S.has("delegation_read_back")){let d=s.delegationId;typeof d=="string"&&this.#V.has(d)&&!this.#j.has(c)&&this.#R.add(c)}else this.#E&&!this.#j.has(c)&&(this.#R.add(c),this.#E=!1);if(this.#j.add(c),this.#R.has(c))break}this.#K(n,s.text??"",s.final===!0,{turnId:c,...typeof s.startMs=="number"&&{startMs:s.startMs},...typeof s.endMs=="number"&&{endMs:s.endMs},...this.#k&&{caption:!0}});break}case"delegation_started":case"delegation_completed":{let n=String(s.delegationId??s.turnId);if(s.type==="delegation_started"){this.#te(t);let r=s.input;this.#k&&r&&this.#he(n,{delegationId:n,userText:String(r.text??""),userUtteranceIds:Array.isArray(r.userUtteranceIds)?r.userUtteranceIds.filter(c=>typeof c=="string"):[],messages:Array.isArray(r.messages)?r.messages:[]},t)}else s.speak!==!1&&this.#V.has(n)&&(this.#E=!0);this.#g=s.type==="delegation_started",!this.#l&&!this.#X()&&this.#s(this.#g?"processing":"listening");break}case"delegation_cancelled":this.#se(String(s.delegationId),s.reason!=="session_ending"&&s.reason!=="provider_cancelled");break;case"warning":console.warn(`[Persona voice] ${s.code}: ${s.message??""}`,this.#O??""),s.delegationId&&(s.code==="UNKNOWN_DELEGATION"||s.code==="LATE_RESULT_LIMIT")&&this.#se(String(s.delegationId));break;case"audio_clear":this.#ne(),this.#h=0,this.#s("listening");break;case"transcript_interim":this.#s("listening"),this.#K("user",s.text??"",!1);break;case"transcript_final":{let n=s.role==="assistant"?"assistant":"user";this.#s(n==="user"?"processing":"speaking"),this.#K(n,s.text??"",!0);break}case"audio_end":this.#n?this.#n.markStreamEnd():(this.#l=!1,this.#s("listening"));break;case"metrics":this.#me({llmMs:s.llm_ms,ttsMs:s.tts_ms,firstAudioMs:s.first_audio_ms,totalMs:s.total_ms});break;case"error":this.#x(new Error(s.error||"Voice error")),this.#s("error");break;case"session_end":this.#I={reason:String(s.reason),...typeof s.message=="string"&&{message:s.message}};break}}async#ue(){let e=this.bridge?.getHistory()??[],t="";try{let s=this.config?.callContext;t=String((typeof s=="function"?await s():s)??"")}catch{}return Ge(e,t)}#te(e){let t=this.#P;if(!t)return;this.#P=null;let s=!1,n=t.then(r=>{let c=this.#e;s||!r||e!==this.#t||c?.readyState!==WebSocket.OPEN||c.send(JSON.stringify({type:"context",text:r}))});this.#U={done:n,drop:()=>s=!0}}async#pe(){let e=this.#U;if(!e)return;let t,s=await Promise.race([e.done.then(()=>!1),new Promise(n=>{t=setTimeout(()=>n(!0),Ue)})]);clearTimeout(t),s&&e.drop()}#se(e,t=!1){this.#_.add(e),this.bridge?.dropDelegation?.(e,t),this.#T.get(e)?.abort()}#he(e,t,s){let n=this.bridge,r=(c,d,a)=>{let o=this.#e;return s!==this.#t||o?.readyState!==WebSocket.OPEN||this.#_.has(e)?!1:(o.send(JSON.stringify({type:c,delegationId:e,status:d,text:a})),!0)};this.#B=this.#B.then(async()=>{if(s!==this.#t||this.#_.has(e))return;let c=await n.runDelegatedTurn(t).catch(()=>({status:"failed",text:""}));await this.#pe();let d=!!c.followUp,a=d&&this.#S.has("delegation_update");if(!r(a?"delegation_update":"delegation_result",d&&!a?"completed":c.status,c.text)||(c.status!=="failed"&&c.inChat!==!1&&this.#V.add(e),!c.followUp))return;let l=new AbortController;this.#T.set(e,l),c.followUp({signal:l.signal,approvalTimeoutMs:this.config?.approvalTimeoutMs&&Math.min(this.config.approvalTimeoutMs,We),readBack:a,onUpdate:u=>r("delegation_update","pending_approval",u)}).then(u=>{this.#T.delete(e),a&&u&&!l.signal.aborted&&r("delegation_result",u.status,u.text)})})}#ge(e,t){if(t!==this.#t||!this.#n||this.#X())return;let s=Ke(e);s.length!==0&&(this.#l||(this.#l=!0,this.#s("speaking")),this.#G(),this.#n.enqueue(s),this.#u&&this.#fe(s.length))}#X(){return Date.now()<this.#h}#G(){if(this.#w||!this.#n)return;this.#w=!0;let e=this.#t;this.#n.onFinished(()=>{e===this.#t&&(this.#w=!1,this.#ie())})}#fe(e){let t=Date.now();this.#b=Math.max(t,this.#b)+e/48,clearTimeout(this.#v),this.#v=setTimeout(()=>this.#ie(),this.#b-t+De)}#ie(){this.#l=!1,this.#b=0,this.#e&&this.#e.readyState===WebSocket.OPEN&&this.#s(this.#g?"processing":"listening")}#ne(){this.#n?.flush(),this.#w=!1,this.#G(),this.#l=!1,this.#b=0,clearTimeout(this.#v)}#C(){this.#t+=1,this.#p=!1,this.#l=!1,this.#L(),this.#u=!1,this.#g=!1,this.#k=!1,this.#S=new Set;for(let e of this.#T.values())e.abort();if(this.#T.clear(),this.#_.clear(),this.#O=void 0,this.#I=null,clearTimeout(this.#J),this.#q=!1,this.#P=null,this.#U=null,this.#B=Promise.resolve(),this.#V.clear(),this.#E=!1,this.#j.clear(),this.#R.clear(),this.#w=!1,this.#h=0,this.#b=0,clearTimeout(this.#v),this.#f=[],this.#m=0,this.#c&&(this.#c.onaudioprocess=null,this.#c.disconnect(),this.#c=null),this.#a&&(this.#a.disconnect(),this.#a=null),this.#i&&(this.#i.getTracks().forEach(e=>e.stop()),this.#i=null),this.#r&&(this.#r.close().catch(()=>{}),this.#r=null),this.#n&&(this.#n.destroy(),this.#n=null),this.#e){this.#y=!0;try{this.#e.close(1e3,"client ended call")}catch{}this.#e=null}}onResult(e){this.#Y.push(e)}onError(e){this.#W.push(e)}onStatusChange(e){this.#$.push(e)}onTranscript(e){this.#F.push(e)}onMetrics(e){this.#H.push(e)}#s(e){this.#$.forEach(t=>t(e))}#x(e){this.#W.forEach(t=>t(e))}#K(e,t,s,n){this.#F.forEach(r=>r(e,t,s,n))}#me(e){this.#H.forEach(t=>t(e))}};var T=class{constructor(e={}){this.config=e;this.type="browser";this.#e=null;this.#r=[];this.#d=[];this.#i=[];this.#a=!1;this.#c=typeof window<"u"?window:void 0}#e;#r;#d;#i;#a;#c;async connect(){this.#i.forEach(e=>e("connected"))}async startListening(){try{if(this.#a)throw new Error("Already listening");if(!this.#c)throw new Error("Window object not available");let e=this.#c.SpeechRecognition||this.#c.webkitSpeechRecognition;if(!e)throw new 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=t=>{let s=Array.from(t.results).map(r=>r[0]).map(r=>r.transcript).join(""),n=t.results[t.results.length-1].isFinal;this.#r.forEach(r=>r({text:s,confidence:n?.8:.5,provider:"browser"})),n&&!this.config?.continuous&&this.stopListening()},this.#e.onerror=t=>{this.#d.forEach(s=>s(new Error(t.error))),this.#i.forEach(s=>s("error"))},this.#e.onstart=()=>{this.#a=!0,this.#i.forEach(t=>t("listening"))},this.#e.onend=()=>{this.#a=!1,this.#i.forEach(t=>t("idle"))},this.#e.start()}catch(e){throw this.#d.forEach(t=>t(e)),this.#i.forEach(t=>t("error")),e}}async stopListening(){this.#e&&(this.#e.stop(),this.#e=null),this.#a=!1,this.#i.forEach(e=>e("idle"))}onResult(e){this.#r.push(e)}onError(e){this.#d.push(e)}onStatusChange(e){this.#i.push(e)}async disconnect(){await this.stopListening(),this.#i.forEach(e=>e("disconnected"))}static isSupported(){return"SpeechRecognition"in window||"webkitSpeechRecognition"in window}};function I(i){switch(i.type){case"runtype":if(!i.runtype)throw new Error("Runtype voice provider requires configuration");return new x(i.runtype);case"browser":if(!T.isSupported())throw new Error("Browser speech recognition not supported");return new T(i.browser||{});case"custom":{let e=i.custom;if(!e)throw new Error("Custom voice provider requires a `custom` provider instance or factory");let t=typeof e=="function"?e():e;if(!t||typeof t.startListening!="function")throw new Error("Custom voice provider `custom` must be a VoiceProvider (or a factory returning one)");return t}default:throw new Error(`Unknown voice provider type: ${i.type}`)}}function H(i){if(i?.type==="custom"&&i.custom)return I({type:"custom",custom:i.custom});if(i?.type==="runtype"&&i.runtype)return I({type:"runtype",runtype:i.runtype});if(T.isSupported())return I({type:"browser",browser:i?.browser||{language:"en-US"}});throw new Error("No supported voice providers available")}function ne(i){try{return H(i),!0}catch{return!1}}var re=i=>i.toLowerCase().replace(/[^\p{L}\p{N}]+/gu,""),R=class{constructor(e){this.host=e;this.turns=new Map;this.latestId=null;this.cancelled=new Set}apply(e,t,s,n,r,c){let d=this.host;t=t.trim();let a=this.turns.get(n);if(a||(a={},this.turns.set(n,a),this.latestId=n),e==="user"){a.userFinal=s;let o=a.userId?d.find(a.userId):void 0;if(o){let l=a.userStartMs===void 0&&r!==void 0;l&&(a.userStartMs=r),d.upsert({...o,content:t,voiceProcessing:!s,...l&&this.placeBefore(this.startedAfter(r))})}else{a.userStartMs=r;let l=a.assistantId?d.find(a.assistantId):void 0;a.userId=d.inject({role:"user",content:t,streaming:!1,voiceProcessing:!s,voiceCaption:c,...this.placeBefore(this.startedAfter(r)??l)}).id}}else if(!this.cancelled.has(n)){a.assistantFinal=s;let o=a.assistantId?d.find(a.assistantId):void 0;if(o){let l=a.assistantStartMs===void 0&&r!==void 0;l&&(a.assistantStartMs=r),d.upsert({...o,content:t,streaming:!s,voiceProcessing:!s,...l&&this.placeBefore(this.startedAfter(r))})}else t&&(a.assistantStartMs=r,a.assistantId=d.inject({role:"assistant",content:t,streaming:!s,voiceProcessing:!s,voiceCaption:c,...this.placeBefore(this.startedAfter(r))}).id);s&&a.assistantId&&d.markSpoken(a.assistantId)}this.sync()}claimUserTurn(e,t=[]){let s=t[t.length-1];for(let r of t)r!==s&&(this.turns.has(r)||this.turns.set(r,{}),this.turns.get(r).claimed=!0);let n;if(s){if(n=this.turns.get(s),n||(n={},this.turns.set(s,n)),n.claimed)return null;(!n.userId||!this.host.find(n.userId))&&(n.userFinal=!0,n.userId=this.host.inject({role:"user",content:e.trim()}).id)}else{let r=re(e),c=[...this.turns.values()].reverse().flatMap(d=>{let a=d.userId&&!d.claimed?this.host.find(d.userId):void 0;return a?[{turn:d,text:re(a.content)}]:[]}).filter(({text:d})=>d&&r);n=(c.find(({text:d})=>d===r)??c.find(({text:d})=>d.startsWith(r)||r.startsWith(d)))?.turn}return n?(n.claimed=!0,n.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(),s=this.inFlight();if(!t&&s.length===0)return;for(let c of s)this.turns.get(c).assistantFinal=!0;this.closeReplies(s);let n=this.host.inject({role:"assistant",content:e,streaming:!1,voiceProcessing:!1}),r=t?this.turns.get(t):void 0;r&&(r.assistantId=n.id,r.assistantFinal=!0),this.sync()}settle(){if(this.turns.size===0)return;let e=this.pending(),t=new Set;for(let s of this.turns.values())s.userId&&t.add(s.userId),s.assistantId&&(t.add(s.assistantId),this.host.markSpoken(s.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 s of this.turns.values())for(let[n,r]of[[s.userId,s.userStartMs],[s.assistantId,s.assistantStartMs]])n&&r!==void 0&&r>e&&(!t||r<t.start)&&(t={start:r,id:n});return t&&this.host.find(t.id)}placeBefore(e){if(!e)return;let t=e.sequence??0,s=t-1;for(let n of this.turns.values())for(let r of[n.userId,n.assistantId]){let c=r?this.host.find(r):void 0,d=c?.sequence;c?.createdAt===e.createdAt&&d!==void 0&&d>s&&d<t&&(s=d)}return{createdAt:e.createdAt,sequence:(s+t)/2}}closeReplies(e){let t=new Set;for(let s of e){let n=this.turns.get(s)?.assistantId;n&&(t.add(n),this.host.markSpoken(n))}t.size>0&&this.host.settle(t)}inFlight(){let e=[];for(let[t,s]of this.turns)s.assistantId&&!s.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())}};var Ze="I need your answer in the chat before I can continue.";var oe="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)",Qe=new RegExp(`^(?:${oe})(?: (?:${oe}))?(?: thanks| thank you)?$`),et=i=>Qe.test(i.toLowerCase().replace(/[^a-z' ]+/g," ").replace(/\s+/g," ").trim()),ae="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.",ce=()=>new Promise(i=>setTimeout(i,50)),z=(i,e)=>i.length>e?`${i.slice(0,e-1).trimEnd()}\u2026`:i,_=i=>i.replace(/^webmcp:/,"").replace(/([a-z\d])([A-Z])/g,"$1 $2").replace(/[_\-.]+/g," ").trim().toLowerCase();function X(i,e=0){if(i==null||i==="")return"";if(typeof i!="object")return String(i);if(e>2)return"";if(Array.isArray(i))return i.map(r=>X(r,e+1)).filter(Boolean).join(", ");let t=i,s=t.quantity??t.qty??t.count,n=t.name??t.item??t.product??t.title;return s!=null&&n!=null&&typeof n!="object"?`${s} ${n}`:Object.entries(t).filter(([r])=>!r.startsWith("_")).map(([r,c])=>{let d=X(c,e+1);return d&&(e?`${_(r)} ${d}`:`${_(r)}: ${d}`)}).filter(Boolean).join(e?", ":"; ")}function le(i){let e=i.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:",t=1e3-e.length-ae.length-2,s=i.map(n=>{let r=[_(n.toolName)];n.description&&r.push(`(${z(n.description.trim(),160)})`);let c=X(n.parameters);return c&&r.push(`with ${c}`),n.reason&&r.push(`because: ${z(n.reason.trim(),160)}`),z(`- ${r.join(" ")}`,Math.floor(t/i.length)-1)});return`${e}
5
+ `)}function at(n){return n.byteLength>=44&&new DataView(n).getUint32(0,!1)===$e?new Uint8Array(n,44):new Uint8Array(n)}function he(n){let e=n.replace(/\/+$/,"");return/^wss?:\/\//i.test(e)?e:/^https?:\/\//i.test(e)?e.replace(/^http/i,"ws"):`${typeof window<"u"&&window.location?.protocol==="https:"?"wss:":"ws:"}//${e}`}function ct(n){return he(n).replace(/^ws/i,"http")}function lt(n){return typeof n!="number"||!Number.isFinite(n)?ze:Math.min(Ge,Math.max(Xe,Math.round(n)))}var E=class{constructor(e){this.config=e;this.type="runtype";this.#e=null;this.#i=null;this.#r=[];this.#n=null;this.#c=null;this.#l=null;this.#m=[];this.#y=0;this.#o=null;this.#p=!1;this.#d=!1;this.#t=0;this.#b=!1;this.#_=Number.NEGATIVE_INFINITY;this.#a=null;this.#u=!1;this.#g=!1;this.#h=0;this.#w=0;this.#A=!1;this.bridge=null;this.#k=!1;this.#f=new Set;this.#E=new Map;this.#x=new Set;this.#j=null;this.#C=null;this.#U=!1;this.#D=!1;this.#B=!1;this.#L=null;this.#q=null;this.#$=Promise.resolve();this.#T=new Set;this.#I=new Set;this.#W=null;this.#v=!1;this.#P=new Set;this.#V=new Set;this.#Q=[];this.#H=[];this.#F=[];this.#z=[];this.#X=[]}#e;#i;#r;#n;#c;#l;#m;#y;#o;#p;#d;#t;#b;#_;#a;#u;#g;#h;#w;#S;#A;#k;#f;#E;#x;#O;#j;#C;#Z;#U;#D;#B;#L;#q;#$;#T;#I;#W;#v;#P;#V;#Q;#H;#F;#z;#X;async connect(){}setSessionBridge(e){this.bridge=e}prewarm(){if(this.#p||this.#a)return;let e=this.config?.agentId,t=this.config?.clientToken,s=this.config?.host;if(!e||!t||!s)return;let i=Date.now();if(!(i-this.#_<We)){this.#_=i;try{this.config?.prewarmMode==="attach"?this.#de(s,e,t):this.#le(s,e,t)}catch{}}}#le(e,t,s){if(typeof fetch!="function")return;let i=`${ct(e)}/v1/client/agents/${encodeURIComponent(t)}/voice/prewarm`;fetch(i,{method:"POST",headers:{Authorization:`Bearer ${s}`},keepalive:!0}).catch(()=>{})}#de(e,t,s){let i=new URLSearchParams,r=this.config?.attachIdleMs,l=lt(r);r!==void 0&&i.set("attachIdleMs",String(l));let d=new WebSocket(this.#te(e,t,i),["runtype.bearer","runtype.attach",s]);d.binaryType="arraybuffer";let a=()=>{},o=new Promise(u=>{a=u}),c={ws:d,state:"connecting",ready:o,settle:a,openedAt:0,idleTimer:void 0};this.#a=c,d.onopen=()=>{this.#a===c&&(c.state=d.protocol==="runtype.attach"?"attached":"live",c.openedAt=Date.now(),this.#ee(c,l),c.state==="attached"&&d.send('{"type":"ping"}'),c.settle())},d.onmessage=u=>{if(this.#a!==c||typeof u.data!="string")return;let p;try{p=JSON.parse(u.data)}catch{return}p.type==="attached"&&typeof p.idleMs=="number"&&this.#ee(c,p.idleMs-(Date.now()-c.openedAt))},d.onerror=()=>{},d.onclose=()=>{this.#a===c&&this.#N()}}#ee(e,t){clearTimeout(e.idleTimer),e.idleTimer=setTimeout(()=>{this.#a===e&&this.#N()},Math.max(0,t))}#N(){let e=this.#a;if(!e)return;this.#a=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#ue(){let e=this.#a;if(!e)return null;if(e.state==="connecting"){let t;await Promise.race([e.ready,new Promise(s=>{t=setTimeout(s,Fe)})]),clearTimeout(t)}return this.#a!==e?null:e.state==="connecting"||e.ws.readyState!==WebSocket.OPEN?(this.#N(),null):(this.#a=null,clearTimeout(e.idleTimer),{ws:e.ws,live:e.state==="live"})}#te(e,t,s){let i=["partial_transcript","context"];this.bridge&&this.config?.clientDelegation!==!1&&i.push("client_delegation","delegation_update","delegation_read_back","delegation_stream"),s&&i.unshift("attach");let r=new URLSearchParams({voiceProtocol:Qe,clientVersion:`persona/${de}`,voiceCapabilities:Ke,clientCapabilities:i.join(",")});return s?.forEach((l,d)=>r.set(d,l)),`${he(e)}/ws/agents/${encodeURIComponent(t)}/voice?${r}`}async startListening(){if(this.#p)return;let e=this.#D;e||(this.#U=!1,this.#C=null),this.#D=!1;let t=this.config?.agentId,s=this.config?.clientToken,i=this.config?.host;if(!t)throw new Error("Runtype voice requires an agentId");if(!s)throw new Error("Runtype voice requires a clientToken");if(!i)throw new Error("Runtype voice requires a host (or widget apiUrl)");let r=++this.#t;this.#b=!1,this.#p=!0;try{let l=await navigator.mediaDevices.getUserMedia({audio:{sampleRate:Z,channelCount:1,echoCancellation:!0}});if(r!==this.#t){l.getTracks().forEach(p=>p.stop());return}this.#n=l;let d=window.AudioContext||window.webkitAudioContext,a=new d({sampleRate:Z});if(this.#i=a,a.state==="suspended"){if(await Promise.race([a.resume().catch(()=>{}),new Promise(p=>setTimeout(p,e?500:He))]),r!==this.#t)return;if(a.state!=="running")throw e?new Error(this.#C=`${O} Tap the mic to reconnect.`):new Error("Audio blocked until a tap")}let o=this.config?.createPlaybackEngine?await this.config.createPlaybackEngine():new N(Ue);if(r!==this.#t){o.destroy(),l.getTracks().forEach(p=>p.stop()),a.close().catch(()=>{});return}this.#o=o,this.#Y(),this.#he(a,l,r);let c=await this.#ue();if(r!==this.#t){c?.ws.close(1e3,"client ended call");return}if(c){let{ws:p}=c;this.#e=p,this.#se(p,r),c.live||p.send('{"type":"start"}'),this.#G(p),this.#s("listening");return}let u=new WebSocket(this.#te(i,t),["runtype.bearer",s]);u.binaryType="arraybuffer",this.#e=u,u.onopen=()=>{r===this.#t&&(this.#G(u),this.#s("listening"))},this.#se(u,r)}catch(l){throw this.#M(),this.#R(l),this.#s("error"),l}}#se(e,t){e.onmessage=s=>this.#ge(s,t),e.onerror=()=>{t!==this.#t||this.#j||(this.#R(new Error("Voice connection failed")),this.#s("error"),this.#M())},e.onclose=s=>{if(this.#b){this.#b=!1;return}if(t!==this.#t)return;let i=this.#j??(s.code===4408?{reason:"idle_timeout"}:null);if(!i){if(s.code!==1e3){let r=s.code?` (code ${s.code})`:"";this.#R(new Error(`Voice connection closed${r}`)),this.#s("error")}else this.#s("idle");this.#M();return}this.#pe(i.reason,i.message)}}#pe(e,t){let s=ue.includes(e)&&!this.#U;if(this.#M(),s){this.#U=!0,this.#p=!0,this.#C=e==="provider_error"?`${O} Reconnecting\u2026`:"Reconnecting\u2026",this.#Z=setTimeout(()=>{this.#p=!1,this.#D=!0,this.startListening().catch(()=>{})},1e3+Math.random()*1e3),this.#s("idle");return}if(ue.includes(e))return this.#C=O,this.#R(new Error(O)),this.#s("error");if(e==="error")return this.#s("error");this.#C=e==="quota"&&t||st.get(e)||null,this.#s("idle")}takeNotice(){let e=this.#C;return this.#C=null,e}getDisclosure(){let e=this.config?.disclosureText;return this.#p&&this.#u&&e!==!1?e||tt:null}async stopListening(){this.#M(),this.#s("idle")}async disconnect(){this.#M(),this.#s("disconnected"),this.#Q=[],this.#H=[],this.#F=[],this.#z=[],this.#X=[]}stopPlayback(){this.#ce();let e=this.#e;e&&e.readyState===WebSocket.OPEN&&(this.#u&&(this.#h=Date.now()+Je,e.send('{"type":"cancel"}')),this.#s("listening"))}getInterruptionMode(){return"barge-in"}isBargeInActive(){return this.#p}onLevel(e){this.#r.push(e)}async deactivateBargeIn(){this.#M(),this.#s("idle")}#he(e,t,s){let i=e.createMediaStreamSource(t);this.#c=i;let r=e.createScriptProcessor(De,1,1);this.#l=r,r.onaudioprocess=l=>{if(s!==this.#t)return;let d=this.#e,a=d?.readyState===WebSocket.OPEN;if(d&&!a&&d.readyState!==WebSocket.CONNECTING)return;let o=l.inputBuffer.getChannelData(0),c=new Int16Array(o.length),u=0;for(let p=0;p<o.length;p++){let m=Math.max(-1,Math.min(1,o[p]));u+=m*m,c[p]=m<0?m*32768:m*32767}if(d&&a)this.#G(d),d.send(c.buffer);else for(this.#m.push(c.buffer),this.#y+=c.byteLength;this.#y>Be;)this.#y-=this.#m.shift().byteLength;if(this.#r.length>0){let p=Math.sqrt(u/o.length),m=Math.max(0,Math.min(1,p*qe));for(let g of this.#r)g(m)}},i.connect(r),r.connect(e.destination)}#G(e){for(let t of this.#m)e.send(t);this.#m=[],this.#y=0}#ge(e,t){if(t!==this.#t)return;if(e.data instanceof ArrayBuffer){this.#ye(e.data,t);return}let s;try{s=JSON.parse(e.data)}catch{return}switch(s.type){case"session_config":s.speechMode&&(this.#u=s.speechMode==="speech_to_speech",this.#o?.setContinuousMode?.(this.#u)),Array.isArray(s.capabilities)&&(this.#f=new Set(s.capabilities)),typeof s.callId=="string"&&(this.#O=s.callId),this.#k=this.#u&&this.#f.has("client_delegation")&&!!this.bridge,this.#u&&!this.#d&&this.#s("listening"),this.#f.has("context")&&!this.#B&&(this.#B=!0,this.#L=this.#fe());break;case"transcript_update":{let i=s.role==="assistant"?"assistant":"user",r=s.utteranceId??s.turnId;if(!r||i==="assistant"&&this.#K())break;let l=String(r);if(i==="user")s.final===!0&&this.#ie(t),this.#v=!1;else{if(this.#f.has("delegation_read_back")){let d=s.delegationId;typeof d=="string"&&this.#T.has(d)&&!this.#P.has(l)?(this.#V.add(l),this.#v=!1):this.#v&&!this.#P.has(l)&&(this.#V.add(l),this.#v=!1)}else this.#v&&!this.#P.has(l)&&(this.#V.add(l),this.#v=!1);if(this.#P.add(l),this.#V.has(l))break}this.#J(i,s.text??"",s.final===!0,{turnId:l,...typeof s.startMs=="number"&&{startMs:s.startMs},...typeof s.endMs=="number"&&{endMs:s.endMs},...this.#k&&{caption:!0}});break}case"delegation_started":case"delegation_completed":{let i=String(s.delegationId??s.turnId);if(s.type==="delegation_started"){this.#ie(t);let r=s.input;this.#k&&r&&this.#me(i,{delegationId:i,userText:String(r.text??""),userUtteranceIds:Array.isArray(r.userUtteranceIds)?r.userUtteranceIds.filter(l=>typeof l=="string"):[],messages:Array.isArray(r.messages)?r.messages:[]},t)}else s.speak!==!1&&this.#T.has(i)&&!this.#I.delete(i)&&!this.#f.has("delegation_read_back")&&this.#re(i);this.#g=s.type==="delegation_started",!this.#d&&!this.#K()&&this.#s(this.#g?"processing":"listening");break}case"delegation_progress":{let i=String(s.delegationId);this.#T.has(i)&&!this.#I.has(i)&&!this.#x.has(i)&&(this.#I.add(i),this.#re(i));break}case"delegation_cancelled":this.#oe(String(s.delegationId),s.reason!=="session_ending"&&s.reason!=="provider_cancelled");break;case"warning":console.warn(`[Persona voice] ${s.code}: ${s.message??""}`,this.#O??""),s.delegationId&&(s.code==="UNKNOWN_DELEGATION"||s.code==="LATE_RESULT_LIMIT")&&this.#oe(String(s.delegationId));break;case"audio_clear":this.#ce(),this.#h=0,this.#s("listening");break;case"transcript_interim":this.#s("listening"),this.#J("user",s.text??"",!1);break;case"transcript_final":{let i=s.role==="assistant"?"assistant":"user";this.#s(i==="user"?"processing":"speaking"),this.#J(i,s.text??"",!0);break}case"audio_end":this.#o?this.#o.markStreamEnd():(this.#d=!1,this.#s("listening"));break;case"metrics":this.#ve({llmMs:s.llm_ms,ttsMs:s.tts_ms,firstAudioMs:s.first_audio_ms,totalMs:s.total_ms});break;case"error":this.#R(new Error(s.error||"Voice error")),this.#s("error");break;case"session_end":this.#j={reason:String(s.reason),...typeof s.message=="string"&&{message:s.message}};break}}async#fe(){let e=this.bridge?.getHistory()??[],t="";try{let s=this.config?.callContext;t=String((typeof s=="function"?await s():s)??"")}catch{}return ot(e,t)}#ie(e){let t=this.#L;if(!t)return;this.#L=null;let s=!1,i=t.then(r=>{let l=this.#e;s||!r||e!==this.#t||l?.readyState!==WebSocket.OPEN||l.send(JSON.stringify({type:"context",text:r}))});this.#q={done:i,drop:()=>s=!0}}async#ne(){let e=this.#q;if(!e)return;let t,s=await Promise.race([e.done.then(()=>!1),new Promise(i=>{t=setTimeout(()=>i(!0),Ze)})]);clearTimeout(t),s&&e.drop()}#re(e){this.#v=!0,this.#W=e}#oe(e,t=!1){this.#x.add(e),this.#W===e&&(this.#v=!1),this.#I.delete(e),this.bridge?.dropDelegation?.(e,t),this.#E.get(e)?.abort()}#me(e,t,s){let i=this.bridge,r=({type:d,...a})=>{let o=this.#e;return s!==this.#t||o?.readyState!==WebSocket.OPEN||this.#x.has(e)?!1:(o.send(JSON.stringify({type:d,delegationId:e,...a})),!0)},l=(d,a,o,c=0)=>r({type:d,status:a,text:o,...c>0&&{streamedChars:c}});this.#$=this.#$.then(async()=>{if(s!==this.#t||this.#x.has(e))return;let d=null,a=this.#f.has("delegation_stream")&&this.#f.has("delegation_read_back"),o=b=>{d=(d??this.#ne()).then(()=>{r({type:"delegation_delta",text:b})&&this.#T.add(e)})},c=await i.runDelegatedTurn(a?{...t,stream:o}:t).catch(()=>({status:"failed",text:""}));await this.#ne(),await d;let u=a?c.streamedChars??0:0,p=!!c.followUp,m=p&&this.#f.has("delegation_update");if(!l(m?"delegation_update":"delegation_result",p&&!m?"completed":c.status,c.text,u)||(c.status!=="failed"&&c.inChat!==!1&&this.#T.add(e),!c.followUp))return;let f=new AbortController;this.#E.set(e,f),c.followUp({signal:f.signal,approvalTimeoutMs:this.config?.approvalTimeoutMs&&Math.min(this.config.approvalTimeoutMs,et),readBack:m,onUpdate:b=>l("delegation_update","pending_approval",b)}).then(b=>{this.#E.delete(e),m&&b&&!f.signal.aborted&&l("delegation_result",b.status,b.text)})})}#ye(e,t){if(t!==this.#t||!this.#o||this.#K())return;let s=at(e);s.length!==0&&(this.#d||(this.#d=!0,this.#s("speaking")),this.#Y(),this.#o.enqueue(s),this.#u&&this.#be(s.length))}#K(){return Date.now()<this.#h}#Y(){if(this.#A||!this.#o)return;this.#A=!0;let e=this.#t;this.#o.onFinished(()=>{e===this.#t&&(this.#A=!1,this.#ae())})}#be(e){let t=Date.now();this.#w=Math.max(t,this.#w)+e/48,clearTimeout(this.#S),this.#S=setTimeout(()=>this.#ae(),this.#w-t+Ye)}#ae(){this.#d=!1,this.#w=0,this.#e&&this.#e.readyState===WebSocket.OPEN&&this.#s(this.#g?"processing":"listening")}#ce(){this.#o?.flush(),this.#A=!1,this.#Y(),this.#d=!1,this.#w=0,clearTimeout(this.#S)}#M(){this.#t+=1,this.#p=!1,this.#d=!1,this.#N(),this.#u=!1,this.#g=!1,this.#k=!1,this.#f=new Set;for(let e of this.#E.values())e.abort();if(this.#E.clear(),this.#x.clear(),this.#O=void 0,this.#j=null,clearTimeout(this.#Z),this.#B=!1,this.#L=null,this.#q=null,this.#$=Promise.resolve(),this.#T.clear(),this.#I.clear(),this.#W=null,this.#v=!1,this.#P.clear(),this.#V.clear(),this.#A=!1,this.#h=0,this.#w=0,clearTimeout(this.#S),this.#m=[],this.#y=0,this.#l&&(this.#l.onaudioprocess=null,this.#l.disconnect(),this.#l=null),this.#c&&(this.#c.disconnect(),this.#c=null),this.#n&&(this.#n.getTracks().forEach(e=>e.stop()),this.#n=null),this.#i&&(this.#i.close().catch(()=>{}),this.#i=null),this.#o&&(this.#o.destroy(),this.#o=null),this.#e){this.#b=!0;try{this.#e.close(1e3,"client ended call")}catch{}this.#e=null}}onResult(e){this.#Q.push(e)}onError(e){this.#H.push(e)}onStatusChange(e){this.#F.push(e)}onTranscript(e){this.#z.push(e)}onMetrics(e){this.#X.push(e)}#s(e){this.#F.forEach(t=>t(e))}#R(e){this.#H.forEach(t=>t(e))}#J(e,t,s,i){this.#z.forEach(r=>r(e,t,s,i))}#ve(e){this.#X.forEach(t=>t(e))}};var _=class{constructor(e={}){this.config=e;this.type="browser";this.#e=null;this.#i=[];this.#r=[];this.#n=[];this.#c=!1;this.#l=typeof window<"u"?window:void 0}#e;#i;#r;#n;#c;#l;async connect(){this.#n.forEach(e=>e("connected"))}async startListening(){try{if(this.#c)throw new Error("Already listening");if(!this.#l)throw new Error("Window object not available");let e=this.#l.SpeechRecognition||this.#l.webkitSpeechRecognition;if(!e)throw new 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=t=>{let s=Array.from(t.results).map(r=>r[0]).map(r=>r.transcript).join(""),i=t.results[t.results.length-1].isFinal;this.#i.forEach(r=>r({text:s,confidence:i?.8:.5,provider:"browser"})),i&&!this.config?.continuous&&this.stopListening()},this.#e.onerror=t=>{this.#r.forEach(s=>s(new Error(t.error))),this.#n.forEach(s=>s("error"))},this.#e.onstart=()=>{this.#c=!0,this.#n.forEach(t=>t("listening"))},this.#e.onend=()=>{this.#c=!1,this.#n.forEach(t=>t("idle"))},this.#e.start()}catch(e){throw this.#r.forEach(t=>t(e)),this.#n.forEach(t=>t("error")),e}}async stopListening(){this.#e&&(this.#e.stop(),this.#e=null),this.#c=!1,this.#n.forEach(e=>e("idle"))}onResult(e){this.#i.push(e)}onError(e){this.#r.push(e)}onStatusChange(e){this.#n.push(e)}async disconnect(){await this.stopListening(),this.#n.forEach(e=>e("disconnected"))}static isSupported(){return"SpeechRecognition"in window||"webkitSpeechRecognition"in window}};function R(n){switch(n.type){case"runtype":if(!n.runtype)throw new Error("Runtype voice provider requires configuration");return new E(n.runtype);case"browser":if(!_.isSupported())throw new Error("Browser speech recognition not supported");return new _(n.browser||{});case"custom":{let e=n.custom;if(!e)throw new Error("Custom voice provider requires a `custom` provider instance or factory");let t=typeof e=="function"?e():e;if(!t||typeof t.startListening!="function")throw new Error("Custom voice provider `custom` must be a VoiceProvider (or a factory returning one)");return t}default:throw new Error(`Unknown voice provider type: ${n.type}`)}}function Q(n){if(n?.type==="custom"&&n.custom)return R({type:"custom",custom:n.custom});if(n?.type==="runtype"&&n.runtype)return R({type:"runtype",runtype:n.runtype});if(_.isSupported())return R({type:"browser",browser:n?.browser||{language:"en-US"}});throw new Error("No supported voice providers available")}function ge(n){try{return Q(n),!0}catch{return!1}}var fe=n=>n.toLowerCase().replace(/[^\p{L}\p{N}]+/gu,""),U=class{constructor(e){this.host=e;this.turns=new Map;this.latestId=null;this.cancelled=new Set}apply(e,t,s,i,r,l){let d=this.host;t=t.trim();let a=this.turns.get(i);if(a||(a={},this.turns.set(i,a),this.latestId=i),e==="user"){a.userFinal=s;let o=a.userId?d.find(a.userId):void 0;if(o){let c=a.userStartMs===void 0&&r!==void 0;c&&(a.userStartMs=r),d.upsert({...o,content:t,voiceProcessing:!s,...c&&this.placeBefore(this.startedAfter(r))})}else{a.userStartMs=r;let c=a.assistantId?d.find(a.assistantId):void 0;a.userId=d.inject({role:"user",content:t,streaming:!1,voiceProcessing:!s,voiceCaption:l,...this.placeBefore(this.startedAfter(r)??c)}).id}}else if(!this.cancelled.has(i)){a.assistantFinal=s;let o=a.assistantId?d.find(a.assistantId):void 0;if(o){let c=a.assistantStartMs===void 0&&r!==void 0;c&&(a.assistantStartMs=r),d.upsert({...o,content:t,streaming:!s,voiceProcessing:!s,...c&&this.placeBefore(this.startedAfter(r))})}else t&&(a.assistantStartMs=r,a.assistantId=d.inject({role:"assistant",content:t,streaming:!s,voiceProcessing:!s,voiceCaption:l,...this.placeBefore(this.startedAfter(r))}).id);s&&a.assistantId&&d.markSpoken(a.assistantId)}this.sync()}claimUserTurn(e,t=[]){let s=t[t.length-1];for(let r of t)r!==s&&(this.turns.has(r)||this.turns.set(r,{}),this.turns.get(r).claimed=!0);let i;if(s){if(i=this.turns.get(s),i||(i={},this.turns.set(s,i)),i.claimed)return null;(!i.userId||!this.host.find(i.userId))&&(i.userFinal=!0,i.userId=this.host.inject({role:"user",content:e.trim()}).id)}else{let r=fe(e),l=[...this.turns.values()].reverse().flatMap(d=>{let a=d.userId&&!d.claimed?this.host.find(d.userId):void 0;return a?[{turn:d,text:fe(a.content)}]:[]}).filter(({text:d})=>d&&r);i=(l.find(({text:d})=>d===r)??l.find(({text:d})=>d.startsWith(r)||r.startsWith(d)))?.turn}return i?(i.claimed=!0,i.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(),s=this.inFlight();if(!t&&s.length===0)return;for(let l of s)this.turns.get(l).assistantFinal=!0;this.closeReplies(s);let i=this.host.inject({role:"assistant",content:e,streaming:!1,voiceProcessing:!1}),r=t?this.turns.get(t):void 0;r&&(r.assistantId=i.id,r.assistantFinal=!0),this.sync()}settle(){if(this.turns.size===0)return;let e=this.pending(),t=new Set;for(let s of this.turns.values())s.userId&&t.add(s.userId),s.assistantId&&(t.add(s.assistantId),this.host.markSpoken(s.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 s of this.turns.values())for(let[i,r]of[[s.userId,s.userStartMs],[s.assistantId,s.assistantStartMs]])i&&r!==void 0&&r>e&&(!t||r<t.start)&&(t={start:r,id:i});return t&&this.host.find(t.id)}placeBefore(e){if(!e)return;let t=e.sequence??0,s=t-1;for(let i of this.turns.values())for(let r of[i.userId,i.assistantId]){let l=r?this.host.find(r):void 0,d=l?.sequence;l?.createdAt===e.createdAt&&d!==void 0&&d>s&&d<t&&(s=d)}return{createdAt:e.createdAt,sequence:(s+t)/2}}closeReplies(e){let t=new Set;for(let s of e){let i=this.turns.get(s)?.assistantId;i&&(t.add(i),this.host.markSpoken(i))}t.size>0&&this.host.settle(t)}inFlight(){let e=[];for(let[t,s]of this.turns)s.assistantId&&!s.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())}};var dt=new Set(["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"]),ut=/([.!?]+|[,;:])(["'”’)\]*_]*)(\s+)|\n\s*/g;function pt(n){let e=/(\S+)$/.exec(n)?.[1];if(!e)return!1;let t=e.replace(/^[("'“‘[*_]+/,"").toLowerCase();if(dt.has(t)||/^[a-z](?:\.[a-z])*$/.test(t))return!0;if(/^\d+$/.test(e)){let s=n.length-e.length;return s===0||/\n\s*$/.test(n.slice(0,s))}return!1}function*me(n,e){let t=new RegExp(ut.source,"g");for(let s=t.exec(n);s;s=t.exec(n)){let i=s[1];if(!n.slice(0,s.index+(i?.length??0)).trim()||i!==void 0&&(/^[,;:]$/.test(i)&&!e||i==="."&&pt(n.slice(0,s.index))))continue;let r=s.index+s[0].length;r<n.length&&(yield r)}}function ye(n,e){let t=n.slice(0,e),s=0;for(let i of t.matchAll(/\s+/g))t.slice(0,i.index).trim()&&(s=i.index+i[0].length);return s}function ee(n){let e=0;for(let i of me(n.slice(0,220),!0))e=i;if(e)return e;let t=ye(n,220);if(t)return t;let s=n.charCodeAt(219);return s>=55296&&s<=56319?219:220}var D=class{#e="";#i=!0;push(e){return this.#e+=e,this.#r()}flush(){let e=this.#r(),t=this.#e;if(this.#e="",t.trim()){for(let s=0;s<t.length;){let i=t.slice(s),r=i.length>220?ee(i):i.length;e.push(i.slice(0,r)),s+=r}this.#i=!1}return e}idle(){let e=this.#e;if(!e.trim()||!/(?:[.!?…]["'”’)\]*_]*|\n)\s*$/.test(e))return[];this.#e="",this.#i=!1;let t=[];for(let s=0;s<e.length;){let i=e.slice(s),r=i.length>220?ee(i):i.length;t.push(i.slice(0,r)),s+=r}return t}#r(){let e=[];for(let t=this.#n();t>0;t=this.#n())e.push(this.#e.slice(0,t)),this.#e=this.#e.slice(t),this.#i=!1;return e}#n(){let e=this.#e;if(!e.trim())return 0;let t=me(e,this.#i).next().value??0;if(t&&t<=220)return t;let s=/[.!?]["'”’)\]*_]*$/.test(e);if(this.#i&&!s){let i=e.match(/\S+\s+/g)?.length??0;if(e.trim().length>=30||i>=6){let r=ye(e,220);if(r)return r}}return e.length>220?ee(e):0}};var ht=200,gt=(n,e)=>{let t=0;for(;t<n.length&&t<e.length&&n[t]===e[t];)t+=1;return t},ft=50,mt="I need your answer in the chat before I can continue.",yt=1e3,bt=5*6e4,be="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)",vt=new RegExp(`^(?:${be})(?: (?:${be}))?(?: thanks| thank you)?$`),wt=n=>vt.test(n.toLowerCase().replace(/[^a-z' ]+/g," ").replace(/\s+/g," ").trim()),ve="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.",we=()=>new Promise(n=>setTimeout(n,ft)),te=(n,e)=>n.length>e?`${n.slice(0,e-1).trimEnd()}\u2026`:n,x=n=>n.replace(/^webmcp:/,"").replace(/([a-z\d])([A-Z])/g,"$1 $2").replace(/[_\-.]+/g," ").trim().toLowerCase();function se(n,e=0){if(n==null||n==="")return"";if(typeof n!="object")return String(n);if(e>2)return"";if(Array.isArray(n))return n.map(r=>se(r,e+1)).filter(Boolean).join(", ");let t=n,s=t.quantity??t.qty??t.count,i=t.name??t.item??t.product??t.title;return s!=null&&i!=null&&typeof i!="object"?`${s} ${i}`:Object.entries(t).filter(([r])=>!r.startsWith("_")).map(([r,l])=>{let d=se(l,e+1);return d&&(e?`${x(r)} ${d}`:`${x(r)}: ${d}`)}).filter(Boolean).join(e?", ":"; ")}function Se(n){let e=n.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:",t=yt-e.length-ve.length-2,s=n.map(i=>{let r=[x(i.toolName)];i.description&&r.push(`(${te(i.description.trim(),160)})`);let l=se(i.parameters);return l&&r.push(`with ${l}`),i.reason&&r.push(`because: ${te(i.reason.trim(),160)}`),te(`- ${r.join(" ")}`,Math.floor(t/n.length)-1)});return`${e}
6
6
  ${s.join(`
7
7
  `)}
8
8
 
9
- ${ae}`}var L=i=>i.variant==="approval"&&i.approval?.status==="pending";function de(i){let e=null,t=null,s=()=>i.track(e??t),n=[],r=new Map,c=new Map,d=(h,f)=>{r.set(h,[...r.get(h)??[],f]),r.size>32&&r.delete(r.keys().next().value)},a=h=>i.messages().find(f=>f.id===h),o=h=>h.approvals.filter(f=>a(f)?.approval?.status==="pending"),l=h=>_(a(h)?.approval?.toolName??""),u=(h,f,w)=>{h.outcome={status:f,text:w};for(let y of o(h))i.decide(y)},p=h=>h.flatMap(f=>i.messages().find(w=>w.id===f)??[]).filter(f=>!f.variant&&f.content.trim()).map(f=>f.content.trim()).join(`
9
+ ${ve}`}var B=n=>n.variant==="approval"&&n.approval?.status==="pending";function Ae(n){let e=null,t=null,s=()=>n.track(e??t),i=[],r=new Map,l=new Map,d=(g,f)=>{r.set(g,[...r.get(g)??[],f]),r.size>32&&r.delete(r.keys().next().value)},a=g=>n.messages().find(f=>f.id===g),o=g=>g.approvals.filter(f=>a(f)?.approval?.status==="pending"),c=g=>x(a(g)?.approval?.toolName??""),u=(g,f,b)=>{g.outcome={status:f,text:b};for(let v of o(g))n.decide(v)},p=g=>g.flatMap(f=>n.messages().find(b=>b.id===f)??[]).filter(f=>!f.variant&&f.content.trim()).map(f=>f.content.trim()).join(`
10
10
 
11
- `),m=async h=>{do await ce();while(i.busy()&&!(h&&(i.parked()||h.failed)))};return{getHistory:()=>{let h=i.messages().filter(y=>(y.role==="user"||y.role==="assistant")&&!y.variant&&!y.voiceProcessing&&!y.streaming&&y.content),f=!1,w=[];for(let y=h.length-1;y>=0;y-=1){let k=h[y];if(k.role==="user")f=!1;else if(!k.voiceCaption)f=!0;else if(f)continue;w.unshift({role:k.role,content:k.content})}return w},dropDelegation(h,f){c.set(h,!!f),c.size>32&&c.delete(c.keys().next().value);let w=f&&n.find(y=>y.delegationId===h);w&&!w.outcome&&u(w,"timeout","");for(let y of r.get(h)??[])y.dropped=!0,y.ids.length&&i.unspoken(y.ids)},async runDelegatedTurn({delegationId:h,userText:f,userUtteranceIds:w}){let y=n.filter(g=>o(g).length),k=y.flatMap(o);if(k.length===1&&et(f)){let g=l(k[0]);return u(y[0],"denied",""),{status:"denied",text:`Okay, I cancelled the ${g} request. Nothing was done.`,inChat:!1}}let G=i.parked()&&i.messages().every(g=>!L(g)||k.includes(g.id));i.busy()&&!G&&await m();let he=new Set(i.messages().map(g=>g.id)),O=()=>i.messages().filter(g=>!he.has(g.id)&&g.variant==="approval"),A={ids:[],failed:!1};d(h,A),e=A,s();try{await i.send(f,i.claim(f,w)??void 0),await m(A)}catch{A.failed=!0}finally{e=null,s()}let ge=A.ids.flatMap(g=>i.messages().find(v=>v.id===g)??[]),E=p(A.ids),P=A.failed?[]:O().filter(L),fe=new Set(P.map(g=>_(g.approval.toolName)));for(let g of y){if(g.outcome)continue;for(let S of o(g).filter(N=>fe.has(l(N))))g.replaced.add(S),i.decide(S);let v=l(g.approvals[0]);g.approvals.every(S=>g.replaced.has(S))?g.outcome={status:"cancelled",text:`The earlier ${v} request was replaced by the new one; it was not done.`}:G&&g.approvals.every(S=>a(S)?.approval?.status==="denied")&&(g.outcome={status:"cancelled",text:`The earlier ${v} request was replaced by the new one; it was not done.`})}if(P.length){let g=new Set(P.map(S=>S.id)),v={delegationId:h,approvals:[...g],at:Date.now(),replaced:new Set};return n.push(v),c.get(h)&&u(v,"timeout",""),E=`${E}
11
+ `),m=async g=>{do await we();while(n.busy()&&!(g&&(n.parked()||g.failed)))};return{getHistory:()=>{let g=n.messages().filter(v=>(v.role==="user"||v.role==="assistant")&&!v.variant&&!v.voiceProcessing&&!v.streaming&&v.content),f=!1,b=[];for(let v=g.length-1;v>=0;v-=1){let C=g[v];if(C.role==="user")f=!1;else if(!C.voiceCaption)f=!0;else if(f)continue;b.unshift({role:C.role,content:C.content})}return b},dropDelegation(g,f){l.set(g,!!f),l.size>32&&l.delete(l.keys().next().value);let b=f&&i.find(v=>v.delegationId===g);b&&!b.outcome&&u(b,"timeout","");for(let v of r.get(g)??[])v.stopStream?.(),v.dropped=!0,v.ids.length&&n.unspoken(v.ids)},async runDelegatedTurn({delegationId:g,userText:f,userUtteranceIds:b,stream:v}){let C=i.filter(h=>o(h).length),q=C.flatMap(o);if(q.length===1&&wt(f)){let h=c(q[0]);return u(C[0],"denied",""),{status:"denied",text:`Okay, I cancelled the ${h} request. Nothing was done.`,inChat:!1}}let ie=n.parked()&&n.messages().every(h=>!B(h)||q.includes(h.id));n.busy()&&!ie&&await m();let Me=new Set(n.messages().map(h=>h.id)),$=()=>n.messages().filter(h=>!Me.has(h.id)&&h.variant==="approval"),S={ids:[],failed:!1},I=v?new D:null,j="",ne="",P=!1,W=h=>{for(let y of h)ne+=y,v(y)},V;I&&(S.onUpdate=()=>{if(P)return;let h=p(S.ids);if(!h.startsWith(j)){P=!0,clearTimeout(V);return}if(h.length===j.length)return;let y=h.slice(j.length);j=h,W(I.push(y)),clearTimeout(V),V=setTimeout(()=>{P||W(I.idle())},ht)},S.stopStream=()=>{clearTimeout(V),P=!0,S.onUpdate=void 0}),d(g,S),e=S,s();try{await n.send(f,n.claim(f,b)??void 0),await m(S)}catch{S.failed=!0}finally{e=null,s()}I&&(S.onUpdate?.(),clearTimeout(V),P||W(I.flush()),S.onUpdate=void 0,S.stopStream=void 0);let H=h=>{let y=gt(ne,h);return y>0?{streamedChars:y}:{}},Te=S.ids.flatMap(h=>n.messages().find(y=>y.id===h)??[]),k=p(S.ids),L=S.failed?[]:$().filter(B),_e=new Set(L.map(h=>x(h.approval.toolName)));for(let h of C){if(h.outcome)continue;for(let A of o(h).filter(F=>_e.has(c(F))))h.replaced.add(A),n.decide(A);let y=c(h.approvals[0]);h.approvals.every(A=>h.replaced.has(A))?h.outcome={status:"cancelled",text:`The earlier ${y} request was replaced by the new one; it was not done.`}:ie&&h.approvals.every(A=>a(A)?.approval?.status==="denied")&&(h.outcome={status:"cancelled",text:`The earlier ${y} request was replaced by the new one; it was not done.`})}if(L.length){let h=new Set(L.map(A=>A.id)),y={delegationId:g,approvals:[...h],at:Date.now(),replaced:new Set};return i.push(y),l.get(g)&&u(y,"timeout",""),k=`${k}
12
12
 
13
- ${le(P.map(S=>S.approval))}`.trim(),{status:"pending_approval",text:E,followUp:async({signal:S,approvalTimeoutMs:N=3e5,readBack:K=!0,onUpdate:me})=>{let C={ids:[],failed:!1};r.delete(h),d(h,C);let J=()=>O().filter(b=>g.has(b.id)||C.ids.includes(b.id)),ye=()=>O().filter(b=>L(b)&&!g.has(b.id)&&!n.some(M=>M.approvals.includes(b.id))&&(C.ids.includes(b.id)||b.approval?.toolType==="webmcp"&&t===C)),Y=()=>{t=C,s()};K&&Y();try{for(;!S.aborted&&!v.outcome&&(e||i.busy()||J().some(L));){K&&t!==C&&!o(v).length&&Y();let b=ye();if(b.length){for(let M of b)g.add(M.id),v.approvals.push(M.id);v.at=Date.now(),me?.(le(b.map(M=>M.approval)))}if(Date.now()-v.at>=N&&o(v).length&&(!i.busy()||i.parked())){u(v,"timeout",`That ${l(v.approvals[0])} request expired, so nothing was done.`);break}await ce()}}finally{t===C&&(t=null,s()),n.splice(n.indexOf(v),1)}if(S.aborted)return null;if(v.outcome)return v.outcome;if(C.failed)return{status:"failed",text:`The ${l(v.approvals[0])} request didn't complete.`};let Z=J(),D=b=>Z.filter(b).map(M=>_(M.approval.toolName)).join(", "),q=Z.some(b=>b.approval?.status==="approved"),U=D(b=>b.approval?.status==="denied"&&!v.replaced.has(b.id)),B=D(b=>v.replaced.has(b.id)),W=D(b=>b.approval?.status==="timeout"),be=[q?p(C.ids):"",U&&`The user declined the ${U} request in the chat, so ${q?"that part was not done":"nothing was done"}.`,B&&`The earlier ${B} request was replaced by the new one; it was not done.`,W&&`The ${W} request timed out, so it was not done.`].filter(Boolean).join(`
13
+ ${Se(L.map(A=>A.approval))}`.trim(),{status:"pending_approval",text:k,...H(k),followUp:async({signal:A,approvalTimeoutMs:F=bt,readBack:re=!0,onUpdate:Ee})=>{let M={ids:[],failed:!1};r.delete(g),d(g,M);let oe=()=>$().filter(w=>h.has(w.id)||M.ids.includes(w.id)),xe=()=>$().filter(w=>B(w)&&!h.has(w.id)&&!i.some(T=>T.approvals.includes(w.id))&&(M.ids.includes(w.id)||w.approval?.toolType==="webmcp"&&t===M)),ae=()=>{t=M,s()};re&&ae();try{for(;!A.aborted&&!y.outcome&&(e||n.busy()||oe().some(B));){re&&t!==M&&!o(y).length&&ae();let w=xe();if(w.length){for(let T of w)h.add(T.id),y.approvals.push(T.id);y.at=Date.now(),Ee?.(Se(w.map(T=>T.approval)))}if(Date.now()-y.at>=F&&o(y).length&&(!n.busy()||n.parked())){u(y,"timeout",`That ${c(y.approvals[0])} request expired, so nothing was done.`);break}await we()}}finally{t===M&&(t=null,s()),i.splice(i.indexOf(y),1)}if(A.aborted)return null;if(y.outcome)return y.outcome;if(M.failed)return{status:"failed",text:`The ${c(y.approvals[0])} request didn't complete.`};let ce=oe(),z=w=>ce.filter(w).map(T=>x(T.approval.toolName)).join(", "),X=ce.some(w=>w.approval?.status==="approved"),G=z(w=>w.approval?.status==="denied"&&!y.replaced.has(w.id)),K=z(w=>y.replaced.has(w.id)),Y=z(w=>w.approval?.status==="timeout"),Ie=[X?p(M.ids):"",G&&`The user declined the ${G} request in the chat, so ${X?"that part was not done":"nothing was done"}.`,K&&`The earlier ${K} request was replaced by the new one; it was not done.`,Y&&`The ${Y} request timed out, so it was not done.`].filter(Boolean).join(`
14
14
 
15
- `);return{status:q?"completed":U?"denied":B?"cancelled":W?"timeout":"completed",text:be}}}}return!A.failed&&i.parked()||ge.some(g=>g.agentMetadata?.awaitingLocalTool&&!g.agentMetadata.askUserQuestionAnswered&&!g.toolCall?.name?.startsWith("webmcp:"))?{status:A.failed?"failed":"completed",text:`${E}
15
+ `);return{status:X?"completed":G?"denied":K?"cancelled":Y?"timeout":"completed",text:Ie}}}}return!S.failed&&n.parked()||Te.some(h=>h.agentMetadata?.awaitingLocalTool&&!h.agentMetadata.askUserQuestionAnswered&&!h.toolCall?.name?.startsWith("webmcp:"))?(k=`${k}
16
16
 
17
- ${Ze}`.trim()}:{status:!A.failed&&E?"completed":"failed",text:E}}}}var ue=(i,e,t,s)=>{let n=i.session;try{i.keyed=t?new t({find:o=>n.messages.find(l=>l.id===o),inject:o=>n.injectMessage(o),upsert:o=>n.upsertMessage(o),settle:o=>{n.messages=n.messages.map(l=>o.has(l.id)?{...l,streaming:!1,voiceProcessing:!1}:l),n.callbacks.onMessagesChanged([...n.messages])},setStreaming:o=>{(o||!i.busy())&&i.setStreaming(o)},markSpoken:o=>{n.ttsSpokenMessageIds.add(o)}}):null,s&&e.setSessionBridge&&e.setSessionBridge(s({messages:()=>n.messages,busy:()=>i.busy(),parked:()=>n.webMcpApprovalResolvers.size>0,claim:(o,l)=>i.keyed?.claimUserTurn(o,l)??null,send:(o,l)=>n.sendMessage(o,{viaVoice:!0,voiceTurn:{userMessageId:l}}),track:o=>{i.setDelegation(o)},unspoken:o=>{for(let l of o)n.ttsSpokenMessageIds.delete(l);n.streaming||n.speakLatestAssistantMessage(o)},decide:o=>{if(n.webMcpApprovalResolvers.has(o))return n.resolveWebMcpApproval(o,"denied");let l=n.messages.find(u=>u.id===o)?.approval;l?.status==="pending"&&n.resolveApproval(l,"denied")}}));let r=i.generation(),c=()=>i.provider()===e&&r===i.generation(),a=(n.config.voiceRecognition??{}).processingErrorText??"Voice processing failed. Please try again.";e.onResult(o=>{c()&&o.provider!=="runtype"&&o.text&&o.text.trim()&&n.sendMessage(o.text,{viaVoice:!0})}),e.onTranscript&&e.onTranscript((o,l,u,p)=>{if(c()){if(p?.turnId){i.keyed?.apply(o,l,u,p.turnId,p.startMs,p.caption);return}if(o==="user"){if(i.pendingUser)n.upsertMessage({id:i.pendingUser,role:"user",content:l,createdAt:new Date().toISOString(),streaming:!1,voiceProcessing:!u});else{let m=n.injectMessage({role:"user",content:l,streaming:!1,voiceProcessing:!u});i.pendingUser=m.id}if(u){i.turns().start(p?.turnId),i.pendingUser=null;let m=n.injectMessage({role:"assistant",content:"",streaming:!0,voiceProcessing:!0});i.pendingAssistant=m.id,i.setStreaming(!0)}}else{if(!i.turns().accepts(p?.turnId))return;if(i.pendingAssistant)n.upsertMessage({id:i.pendingAssistant,role:"assistant",content:l,createdAt:new Date().toISOString(),streaming:!u,voiceProcessing:!u});else{let m=n.injectMessage({role:"assistant",content:l,streaming:!u,voiceProcessing:!u});i.pendingAssistant=m.id}u&&(i.pendingAssistant&&n.ttsSpokenMessageIds.add(i.pendingAssistant),i.setStreaming(!1),i.pendingAssistant=null)}}}),e.onLevel&&e.onLevel(o=>{c()&&i.setLevel(Number.isFinite(o)?Math.max(0,Math.min(1,o)):0)}),e.onMetrics&&e.onMetrics(o=>{c()&&n.config.voiceRecognition?.onMetrics?.(o)}),e.onError(o=>{c()&&(console.error("Voice error:",o),i.pendingAssistant&&(n.upsertMessage({id:i.pendingAssistant,role:"assistant",content:a,createdAt:new Date().toISOString(),streaming:!1,voiceProcessing:!1}),i.setStreaming(!1),i.pendingUser=null,i.pendingAssistant=null),i.keyed?.fail(a))}),e.onStatusChange(o=>{c()&&(i.setStatus(o),(o==="listening"||o==="idle"||o==="disconnected")&&i.settlePending(o!=="listening"),(o==="idle"||o==="disconnected")&&i.keyed?.settle(),n.callbacks.onVoiceStatusChanged?.(o))}),e.connect()}catch(r){console.error("Failed to setup voice:",r)}};var pe=i=>{let e=a=>{if(i.original)return;let o=i.config().voiceRecognition??{};i.original={backgroundColor:a.style.backgroundColor,color:a.style.color,borderColor:a.style.borderColor,iconName:o.iconName??"mic",iconSize:parseFloat(o.iconSize??"")||i.iconFallbackPx}},t=(a,o,l)=>{let u=a.querySelector("svg");u&&u.remove();let p=i.original?.iconSize??(parseFloat(i.config().voiceRecognition?.iconSize??"")||i.iconFallbackPx),m=i.renderIcon(o,p,l,1.5);m&&a.appendChild(m)},s=a=>{a.classList.remove("persona-voice-recording","persona-voice-processing","persona-voice-speaking")};return{recording:()=>{let a=i.mic();if(!a)return;e(a);let o=i.config().voiceRecognition??{},l=o.recordingBackgroundColor,u=o.recordingIconColor,p=o.recordingBorderColor;if(s(a),a.classList.add("persona-voice-recording"),i.setMicState("recording"),a.style.backgroundColor=l??"var(--persona-voice-recording-bg, #ef4444)",a.style.color=u??"var(--persona-voice-recording-indicator, #ffffff)",u){let m=a.querySelector("svg");m&&m.setAttribute("stroke",u)}p&&(a.style.borderColor=p),a.setAttribute("aria-label","Stop voice recognition")},processing:()=>{let a=i.mic();if(!a)return;e(a);let o=i.config().voiceRecognition??{},l=i.session().getVoiceInterruptionMode(),u=i.original,p=o.processingIconName??"loader",m=o.processingIconColor??u?.color??"",h=o.processingBackgroundColor??u?.backgroundColor??"",f=o.processingBorderColor??u?.borderColor??"";s(a),a.classList.add("persona-voice-processing"),i.setMicState("processing"),a.style.backgroundColor=h,a.style.borderColor=f;let w=m||"currentColor";a.style.color=w,t(a,p,w),a.setAttribute("aria-label","Processing voice input"),l==="none"&&(a.style.cursor="default")},speaking:()=>{let a=i.mic();if(!a)return;e(a);let o=i.config().voiceRecognition??{},l=i.session().getVoiceInterruptionMode(),u=i.original,p=l==="cancel"?"square":l==="barge-in"?"mic":"volume-2",m=o.speakingIconName??p,h=o.speakingIconColor??(l==="barge-in"?o.recordingIconColor??u?.color??"":u?.color??""),f=o.speakingBackgroundColor??(l==="barge-in"?o.recordingBackgroundColor??"var(--persona-voice-recording-bg, #ef4444)":u?.backgroundColor??""),w=o.speakingBorderColor??(l==="barge-in"?o.recordingBorderColor??"":u?.borderColor??"");s(a),a.classList.add("persona-voice-speaking"),i.setMicState("speaking"),a.style.backgroundColor=f,a.style.borderColor=w;let y=h||"currentColor";a.style.color=y,t(a,m,y);let k=l==="cancel"?"Stop playback and re-record":l==="barge-in"?"Speak to interrupt":"Agent is speaking";a.setAttribute("aria-label",k),l==="none"&&(a.style.cursor="default"),l==="barge-in"&&a.classList.add("persona-voice-recording")},reset:()=>{let a=i.mic();if(!a)return;s(a),i.setMicState("idle");let o=i.original;o&&(a.style.backgroundColor=o.backgroundColor??"",a.style.color=o.color??"",a.style.borderColor=o.borderColor??"",t(a,o.iconName,o.color||"currentColor"),i.original=null),a.style.cursor="",a.setAttribute("aria-label","Start voice recognition")}}};0&&(module.exports={BrowserVoiceProvider,KeyedVoiceTranscript,RuntypeVoiceProvider,createBestAvailableVoiceProvider,createMicStateStyles,createVoiceProvider,createVoiceSessionBridge,isVoiceSupported,wireSessionVoice});
17
+ ${mt}`.trim(),{status:S.failed?"failed":"completed",text:k,...H(k)}):{status:!S.failed&&k?"completed":"failed",text:k,...H(k)}}}}var ke=(n,e,t,s)=>{let i=n.session;try{n.keyed=t?new t({find:o=>i.messages.find(c=>c.id===o),inject:o=>i.injectMessage(o),upsert:o=>i.upsertMessage(o),settle:o=>{i.messages=i.messages.map(c=>o.has(c.id)?{...c,streaming:!1,voiceProcessing:!1}:c),i.callbacks.onMessagesChanged([...i.messages])},setStreaming:o=>{(o||!n.busy())&&n.setStreaming(o)},markSpoken:o=>{i.ttsSpokenMessageIds.add(o)}}):null,s&&e.setSessionBridge&&e.setSessionBridge(s({messages:()=>i.messages,busy:()=>n.busy(),parked:()=>i.webMcpApprovalResolvers.size>0,claim:(o,c)=>n.keyed?.claimUserTurn(o,c)??null,send:(o,c)=>i.sendMessage(o,{viaVoice:!0,voiceTurn:{userMessageId:c}}),track:o=>{n.setDelegation(o)},unspoken:o=>{for(let c of o)i.ttsSpokenMessageIds.delete(c);i.streaming||i.speakLatestAssistantMessage(o)},decide:o=>{if(i.webMcpApprovalResolvers.has(o))return i.resolveWebMcpApproval(o,"denied");let c=i.messages.find(u=>u.id===o)?.approval;c?.status==="pending"&&i.resolveApproval(c,"denied")}}));let r=n.generation(),l=()=>n.provider()===e&&r===n.generation(),a=(i.config.voiceRecognition??{}).processingErrorText??"Voice processing failed. Please try again.";e.onResult(o=>{l()&&o.provider!=="runtype"&&o.text&&o.text.trim()&&i.sendMessage(o.text,{viaVoice:!0})}),e.onTranscript&&e.onTranscript((o,c,u,p)=>{if(l()){if(p?.turnId){n.keyed?.apply(o,c,u,p.turnId,p.startMs,p.caption);return}if(o==="user"){if(n.pendingUser)i.upsertMessage({id:n.pendingUser,role:"user",content:c,createdAt:new Date().toISOString(),streaming:!1,voiceProcessing:!u});else{let m=i.injectMessage({role:"user",content:c,streaming:!1,voiceProcessing:!u});n.pendingUser=m.id}if(u){n.turns().start(p?.turnId),n.pendingUser=null;let m=i.injectMessage({role:"assistant",content:"",streaming:!0,voiceProcessing:!0});n.pendingAssistant=m.id,n.setStreaming(!0)}}else{if(!n.turns().accepts(p?.turnId))return;if(n.pendingAssistant)i.upsertMessage({id:n.pendingAssistant,role:"assistant",content:c,createdAt:new Date().toISOString(),streaming:!u,voiceProcessing:!u});else{let m=i.injectMessage({role:"assistant",content:c,streaming:!u,voiceProcessing:!u});n.pendingAssistant=m.id}u&&(n.pendingAssistant&&i.ttsSpokenMessageIds.add(n.pendingAssistant),n.setStreaming(!1),n.pendingAssistant=null)}}}),e.onLevel&&e.onLevel(o=>{l()&&n.setLevel(Number.isFinite(o)?Math.max(0,Math.min(1,o)):0)}),e.onMetrics&&e.onMetrics(o=>{l()&&i.config.voiceRecognition?.onMetrics?.(o)}),e.onError(o=>{l()&&(console.error("Voice error:",o),n.pendingAssistant&&(i.upsertMessage({id:n.pendingAssistant,role:"assistant",content:a,createdAt:new Date().toISOString(),streaming:!1,voiceProcessing:!1}),n.setStreaming(!1),n.pendingUser=null,n.pendingAssistant=null),n.keyed?.fail(a))}),e.onStatusChange(o=>{l()&&(n.setStatus(o),(o==="listening"||o==="idle"||o==="disconnected")&&n.settlePending(o!=="listening"),(o==="idle"||o==="disconnected")&&n.keyed?.settle(),i.callbacks.onVoiceStatusChanged?.(o))}),e.connect()}catch(r){console.error("Failed to setup voice:",r)}};var Ce=n=>{let e=a=>{if(n.original)return;let o=n.config().voiceRecognition??{};n.original={backgroundColor:a.style.backgroundColor,color:a.style.color,borderColor:a.style.borderColor,iconName:o.iconName??"mic",iconSize:parseFloat(o.iconSize??"")||n.iconFallbackPx}},t=(a,o,c)=>{let u=a.querySelector("svg");u&&u.remove();let p=n.original?.iconSize??(parseFloat(n.config().voiceRecognition?.iconSize??"")||n.iconFallbackPx),m=n.renderIcon(o,p,c,1.5);m&&a.appendChild(m)},s=a=>{a.classList.remove("persona-voice-recording","persona-voice-processing","persona-voice-speaking")};return{recording:()=>{let a=n.mic();if(!a)return;e(a);let o=n.config().voiceRecognition??{},c=o.recordingBackgroundColor,u=o.recordingIconColor,p=o.recordingBorderColor;if(s(a),a.classList.add("persona-voice-recording"),n.setMicState("recording"),a.style.backgroundColor=c??"var(--persona-voice-recording-bg, #ef4444)",a.style.color=u??"var(--persona-voice-recording-indicator, #ffffff)",u){let m=a.querySelector("svg");m&&m.setAttribute("stroke",u)}p&&(a.style.borderColor=p),a.setAttribute("aria-label","Stop voice recognition")},processing:()=>{let a=n.mic();if(!a)return;e(a);let o=n.config().voiceRecognition??{},c=n.session().getVoiceInterruptionMode(),u=n.original,p=o.processingIconName??"loader",m=o.processingIconColor??u?.color??"",g=o.processingBackgroundColor??u?.backgroundColor??"",f=o.processingBorderColor??u?.borderColor??"";s(a),a.classList.add("persona-voice-processing"),n.setMicState("processing"),a.style.backgroundColor=g,a.style.borderColor=f;let b=m||"currentColor";a.style.color=b,t(a,p,b),a.setAttribute("aria-label","Processing voice input"),c==="none"&&(a.style.cursor="default")},speaking:()=>{let a=n.mic();if(!a)return;e(a);let o=n.config().voiceRecognition??{},c=n.session().getVoiceInterruptionMode(),u=n.original,p=c==="cancel"?"square":c==="barge-in"?"mic":"volume-2",m=o.speakingIconName??p,g=o.speakingIconColor??(c==="barge-in"?o.recordingIconColor??u?.color??"":u?.color??""),f=o.speakingBackgroundColor??(c==="barge-in"?o.recordingBackgroundColor??"var(--persona-voice-recording-bg, #ef4444)":u?.backgroundColor??""),b=o.speakingBorderColor??(c==="barge-in"?o.recordingBorderColor??"":u?.borderColor??"");s(a),a.classList.add("persona-voice-speaking"),n.setMicState("speaking"),a.style.backgroundColor=f,a.style.borderColor=b;let v=g||"currentColor";a.style.color=v,t(a,m,v);let C=c==="cancel"?"Stop playback and re-record":c==="barge-in"?"Speak to interrupt":"Agent is speaking";a.setAttribute("aria-label",C),c==="none"&&(a.style.cursor="default"),c==="barge-in"&&a.classList.add("persona-voice-recording")},reset:()=>{let a=n.mic();if(!a)return;s(a),n.setMicState("idle");let o=n.original;o&&(a.style.backgroundColor=o.backgroundColor??"",a.style.color=o.color??"",a.style.borderColor=o.borderColor??"",t(a,o.iconName,o.color||"currentColor"),n.original=null),a.style.cursor="",a.setAttribute("aria-label","Start voice recognition")}}};0&&(module.exports={BrowserVoiceProvider,KeyedVoiceTranscript,RuntypeVoiceProvider,createBestAvailableVoiceProvider,createMicStateStyles,createVoiceProvider,createVoiceSessionBridge,isVoiceSupported,wireSessionVoice});
@@ -3281,9 +3281,8 @@ type WebMcpConfirmInfo = {
3281
3281
  };
3282
3282
  /**
3283
3283
  * Why the confirm was requested. Currently always `'gate'`: the default
3284
- * confirm-by-default gate that fires before every `webmcp:*` call. (The
3285
- * `@mcp-b/webmcp-polyfill` owns the spec's `requestUserInteraction` callback
3286
- * internally, so Persona no longer surfaces a nested in-tool confirm.)
3284
+ * confirm-by-default gate that fires before every `webmcp:*` call. Tool
3285
+ * callbacks on v6 receive an AbortSignal, not a nested confirmation API.
3287
3286
  */
3288
3287
  reason: 'gate';
3289
3288
  };
@@ -7294,6 +7293,13 @@ type VoiceDelegationRequest = {
7294
7293
  role: string;
7295
7294
  content: unknown;
7296
7295
  }>;
7296
+ /**
7297
+ * Set when the server streams delegated answers (`delegation_stream`): called
7298
+ * with each speakable piece of the turn's answer, in order, while it renders.
7299
+ * The pieces, concatenated, are a prefix of the result's `text`; the result
7300
+ * says how much of it with `streamedChars`.
7301
+ */
7302
+ stream?: (text: string) => void;
7297
7303
  };
7298
7304
  /**
7299
7305
  * How a delegated turn ended, or that it waits on an approval (contract
@@ -7324,6 +7330,12 @@ type VoiceDelegationResult = {
7324
7330
  * @default true
7325
7331
  */
7326
7332
  inChat?: boolean;
7333
+ /**
7334
+ * How many leading characters of `text` already went out through
7335
+ * `request.stream` (the rest, such as an approval script, is unstreamed).
7336
+ * Omitted or 0: nothing was streamed.
7337
+ */
7338
+ streamedChars?: number;
7327
7339
  /**
7328
7340
  * Set when the turn parked on approvals (`text` then asks for the decision).
7329
7341
  * Resolves with the terminal result once the visitor decides (or the
@@ -9541,8 +9553,11 @@ type AgentWidgetConfig = {
9541
9553
  /**
9542
9554
  * WebMCP: consume page-registered tools (`document.modelContext.registerTool`).
9543
9555
  * When `enabled`, the widget installs `@mcp-b/webmcp-polyfill`, snapshots the
9544
- * registry on every dispatch, ships it as `clientTools[]`, and executes
9545
- * returned `webmcp:*` tool calls with confirm-by-default gating.
9556
+ * current document's registry on every dispatch, ships it as `clientTools[]`,
9557
+ * and executes returned `webmcp:*` calls with confirm-by-default gating.
9558
+ * Supports host-installed v5 JSON-string and v6 object-input contracts.
9559
+ * The automatic fallback stays on v5 to preserve existing browser support
9560
+ * and callback-result behavior.
9546
9561
  *
9547
9562
  * Server-side policy on the chat surface is the source of truth: these
9548
9563
  * fields layer on top.
@@ -10635,11 +10650,16 @@ declare class KeyedVoiceTranscript {
10635
10650
  /**
10636
10651
  * What a delegated turn streamed: its assistant messages, whether it failed,
10637
10652
  * and whether the server dropped its result (then browser TTS may read it).
10653
+ * `onUpdate` runs after each of its assistant messages is stored (the answer
10654
+ * grew), so a streaming bridge can read the new text.
10638
10655
  */
10639
10656
  type VoiceDelegationCapture = {
10640
10657
  ids: string[];
10641
10658
  failed: boolean;
10642
10659
  dropped?: boolean;
10660
+ onUpdate?: () => void;
10661
+ /** Stops a streaming answer (its pending idle flush included); set while it streams. */
10662
+ stopStream?: () => void;
10643
10663
  };
10644
10664
  /** The session internals the delegation bridge drives. */
10645
10665
  interface VoiceDelegationHost {
@@ -10683,6 +10703,12 @@ type DispatchOptions = {
10683
10703
  * `submitMode: "interrupt"` so the server cancels the prior run.
10684
10704
  */
10685
10705
  interrupt?: boolean;
10706
+ /**
10707
+ * Client-token only: a voice model reads the reply aloud (a delegated voice
10708
+ * turn). Sends `voice: { spoken: true }` so the server asks for a speakable
10709
+ * answer.
10710
+ */
10711
+ voiceSpoken?: boolean;
10686
10712
  };
10687
10713
  type SSEHandler = (event: AgentWidgetEvent) => void;
10688
10714
  type SSEEventCallback = (eventType: string, payload: unknown) => void;