@seams/voiceid 0.42.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@ and the trusted host API. Existing voice enrollments keep their storage identity
10
10
  Install matching Wallet and VoiceID versions, then import the descriptor:
11
11
 
12
12
  ```sh
13
- pnpm add @seams/wallet@0.42.0 @seams/voiceid@0.42.0
13
+ pnpm add @seams/wallet@0.44.0 @seams/voiceid@0.44.0
14
14
  ```
15
15
 
16
16
  ```ts
@@ -26,8 +26,8 @@ const config = defineSeamsConfig({
26
26
  ```
27
27
 
28
28
  Choose `transcriptionModel: 'aurora'` for the smaller speech model. Citrinet is
29
- the default when this option is omitted. The choice applies to enrollment,
30
- unlock, and transaction approval. Each action keeps its chosen model throughout
29
+ the default when this option is omitted. The choice applies to enrollment
30
+ and unlock. Each action keeps its chosen model throughout
31
31
  preparation and recording.
32
32
 
33
33
  | Speech model | Uncompressed | Gzip |
@@ -47,35 +47,13 @@ loading in the trusted Wallet iframe. Passkey and Email OTP flows remain indepen
47
47
  The optional `VoiceBeam` and `VoiceAssistantCard` visuals are exported from
48
48
  `@seams/voiceid/react`. Import `@seams/voiceid/styles` when using the card.
49
49
 
50
- ## Configure a signing challenge
50
+ ## Signing after a VoiceID unlock
51
51
 
52
- Pass `voiceId.confirmationCommand` in the `options` of an existing reviewed NEAR
53
- or EVM signing request:
54
-
55
- ```ts
56
- const options = {
57
- voiceId: {
58
- confirmationCommand: 'Sell 100 NEAR for USDC at $5.5',
59
- },
60
- };
61
- ```
62
-
63
- The Wallet selects a short action-only challenge, such as “Approve this sale at
64
- once” or “Let the sale go through.” It omits amounts, assets, and prices from the
65
- spoken phrase. The full transaction review remains authoritative.
66
-
67
- The leading English verb selects the phrase family: `sell`, `buy`, `swap`, or
68
- `send`/`transfer`. Other wording uses the default random challenges. Commands
69
- must be nonempty strings of at most 256 characters without control characters.
70
- The application cannot supply the final phrase or change verification thresholds.
71
- Retries choose a different phrase within the selected family.
72
-
73
- This option changes wording only. It does not enable VoiceID for unsupported
74
- transactions or interpret a trading command. VoiceID currently supports reviewed
75
- native transfers on NEAR testnet and Arc testnet. Approval remains bound to the
76
- complete signing request and review deadline, including the supplied command.
77
- Enrollment and unlock retain the default phrase bank. This adds no model or API
78
- request and keeps audio in the Wallet iframe.
52
+ VoiceID works like a passkey. A VoiceID unlock opens a normal signing session.
53
+ Each operation on any chain shows the ordinary **Confirm**, with no further voice
54
+ check, within the session's uses and expiry. When the session needs fresh
55
+ authentication, the owner unlocks with VoiceID again. Key export needs a passkey
56
+ or Email OTP.
79
57
 
80
58
  ## Install on the Wallet host
81
59
 
@@ -122,12 +100,8 @@ same card. Retry keeps verified assets and voice enrollment. Close the card to
122
100
  choose a passkey instead. A missing or incompatible host package requires an
123
101
  operator fix; other module failures include connection and reload instructions.
124
102
 
125
- Transaction reviews prepare VoiceID before enabling **Confirm with VoiceID**.
126
- The voice attempt timer starts after that click. The transaction's expiry remains
127
- in force while loading or retrying, so an expired transaction needs a fresh review.
128
-
129
- VoiceID remembers the microphone used for usable audio in this browser. Enrollment,
130
- unlock, and signing request that input even when the system default changes.
103
+ VoiceID remembers the microphone used for usable audio in this browser. Enrollment
104
+ and unlock request that input even when the system default changes.
131
105
  If it is unavailable, VoiceID can use the current default. Reconnecting the saved
132
106
  microphone restores it. Interrupted recordings require a new attempt. Voice
133
107
  enrollment and verification thresholds stay unchanged.
@@ -139,6 +113,6 @@ The cold payload before transfer compression is roughly 27 MB with Aurora or
139
113
  Splitting it removes that payload from Wallet-only installations. It does not
140
114
  reduce the bytes needed for the first VoiceID operation.
141
115
 
142
- Use the [public VoiceID guide](https://wallet.seams.sh/docs/concepts/auth-methods/voiceid)
143
- for enrollment, unlock, transfer approval, and storage behavior.
116
+ Use the [public VoiceID guide](https://docs.wallet.seams.sh/concepts/auth-methods/voiceid)
117
+ for enrollment, unlock, signing, and storage behavior.
144
118
  See [implementation notes](src/README.md) for code boundaries and enrollment storage.
@@ -0,0 +1 @@
1
+ import"./prompt-DsRKGfyb.js";import{a as e,i as t,o as n,r,t as i}from"./deviceBridge-vf25pKzp.js";import{WorkerDeferred as a,prepareVoiceOwner as o,toError as s}from"../voiceid-host.js";const c=`http://www.w3.org/2000/svg`;async function l(e,t,n,r,i){let a=new u(e,t,n,r,i);try{await a.result}finally{a.dispose()}}var u=class{completion=new a;result=this.completion.promise;document;element;enrollment;enrollmentValue;enrollmentSummary;startOver;status;actions;busy=!1;closed=!1;constructor(e,t,n,r,i){this.parent=e,this.confirmChange=t,this.scope=n,this.signal=r,this.model=i,this.document=e.ownerDocument,this.element=this.document.createElement(`div`),this.enrollment=this.document.createElement(`div`),this.enrollmentValue=this.document.createElement(`span`),this.enrollmentSummary=this.document.createElement(`span`),this.startOver=this.document.createElement(`p`),this.status=this.document.createElement(`p`),this.element.className=`seams-voiceid-prompt seams-voiceid-management`;let a=this.document.createElement(`div`);a.className=`seams-voiceid-management-header`;let o=this.document.createElement(`button`);o.type=`button`,o.className=`seams-voiceid-management-back`,o.setAttribute(`aria-label`,`Back`),o.append(d(this.document,`M15 6l-6 6 6 6`,20)),o.addEventListener(`click`,this.cancel);let s=this.document.createElement(`h2`);s.textContent=`Manage voice`,a.append(o,s);let c=this.document.createElement(`p`);c.className=`seams-voiceid-management-intro`,c.textContent=`Voice unlock on this device. Each change asks for your passkey.`,this.element.append(a,c,this.enrollmentRow()),this.actions={reset:this.resetAction(),improve:this.action(`improve`,`Improve recognition`,!0),import:this.action(`import`,`Use saved enrollment`,!1),replace:this.startOverAction()},this.status.setAttribute(`role`,`status`),this.element.append(this.status),this.enrollmentValue.textContent=`Checking…`,this.actions.import.button.hidden=!0,this.render(null,!1,!1),this.parent.replaceChildren(this.element),this.signal.addEventListener(`abort`,this.cancel,{once:!0}),this.refresh(),o.focus()}enrollmentRow(){this.enrollment.className=`seams-voiceid-management-enrollment`;let e=this.document.createElement(`span`);return e.textContent=`Enrollment`,this.enrollmentValue.className=`seams-voiceid-management-value`,this.enrollmentSummary.className=`seams-voiceid-management-summary`,this.enrollmentSummary.append(this.enrollmentValue),this.enrollment.append(e,this.enrollmentSummary),this.enrollment}resetAction(){let e=this.document.createElement(`button`);e.type=`button`,e.className=`seams-voiceid-management-reset`,e.textContent=`Reset`,e.setAttribute(`aria-label`,`Reset improvements`),e.addEventListener(`click`,this.begin.bind(this,`reset`));let t=this.document.createElement(`span`);return t.className=`seams-voiceid-management-enrollment-detail`,this.enrollmentSummary.append(t),this.enrollment.append(e),{button:e,title:e,detail:t,frame:this.enrollment}}startOverAction(){return this.startOver.className=`seams-voiceid-management-section`,this.startOver.textContent=`Start over`,this.element.append(this.startOver),this.action(`replace`,`Record voice again`,!1)}action(e,t,n){let r=this.document.createElement(`button`);r.type=`button`,r.className=`seams-voiceid-management-action`;let i=this.document.createElement(`span`),a=this.document.createElement(`span`);a.className=`seams-voiceid-management-action-heading`;let o=this.document.createElement(`span`);o.id=`seams-voiceid-management-${e}-title`,o.textContent=t,a.append(o);let s=[];if(n){let t=this.document.createElement(`span`);t.id=`seams-voiceid-management-${e}-chip`,t.className=`seams-voiceid-management-chip`,t.textContent=`Experimental`,a.append(t),s.push(t.id)}let c=this.document.createElement(`span`);return c.id=`seams-voiceid-management-${e}-detail`,c.className=`seams-voiceid-management-action-detail`,s.push(c.id),i.append(a,c),r.append(i,d(this.document,`M9 6l6 6-6 6`,16)),r.setAttribute(`aria-labelledby`,o.id),r.setAttribute(`aria-describedby`,s.join(` `)),r.disabled=!0,r.addEventListener(`click`,this.begin.bind(this,e)),this.element.append(r),{button:r,title:o,detail:c,frame:r}}async refresh(){try{let t=await n(this.scope),r=t?null:await e();if(this.closed)return;this.render(t,r!==null,!0)}catch(e){this.completion.reject(s(e))}}render(e,t,n){let r=e?.adaptation??null,{improve:i,reset:a,import:o,replace:s}=this.actions;n&&(this.enrollment.dataset.enrollment=r?.kind??`missing`,this.enrollmentValue.textContent=r===null?`Not on this device`:r.kind===`adapted`?`Improved`:`Original`,i.button.hidden=e===null,o.button.hidden=!t),a.button.hidden=r?.kind!==`adapted`,a.detail.textContent=r?.kind===`adapted`?`Saved on this device`:``,i.title.textContent=r?.kind===`adapted`?`Improve again`:`Improve recognition`,i.detail.textContent=r?.kind===`adapted`?`Replace the added samples. Your original enrollment stays.`:`Add three samples. They stay until you replace or reset them.`,o.detail.textContent=`Import the voice enrollment saved in this browser.`,s.detail.textContent=r?.kind===`adapted`?`Replace your enrollment and remove improvements.`:`Replace your enrollment with three new samples.`,this.startOver.hidden=i.button.hidden&&o.button.hidden;for(let e of Object.values(this.actions))delete e.frame.dataset.state,e.button.disabled=!n;this.status.textContent=``,delete this.status.dataset.placement}show(e,t,n){let r=this.actions[e];if(this.status.textContent=n,r.button.hidden){this.status.dataset.placement=`dialog`;return}r.frame.dataset.state=t,r.detail.textContent=n}begin(e){if(!(this.busy||this.closed)){this.busy=!0;for(let e of Object.values(this.actions))e.button.disabled=!0;this.show(e,`pending`,`Confirm with your passkey to continue.`),this.perform(e)}}async perform(e){try{let i=await o(this.scope,`enrolled`),a=await n(this.scope),s=await f(e,i,a?{kind:`present`,enrollment:a}:{kind:`missing`},this.signal),c=await this.confirmChange(s);switch(this.signal.throwIfAborted(),s.kind){case`improve`:await r(this.parent,{kind:`improve`,scope:this.scope,guard:s.guard,snapshot:s.snapshot,confirmation:c},this.signal,this.model);break;case`replace`:await r(this.parent,{kind:`replace`,scope:this.scope,guard:s.guard,snapshot:s.snapshot,confirmation:c},this.signal,this.model);break;case`reset`:await t({kind:`reset`,scope:this.scope,guard:s.guard,snapshot:s.snapshot,confirmation:c,signal:this.signal});break;case`import`:await t({kind:`import`,scope:this.scope,guard:s.guard,snapshot:s.snapshot,baseline:s.baseline,confirmation:c,signal:this.signal});break;default:return p(s)}this.closed||this.completion.resolve()}catch(t){if(this.closed)return;this.parent.replaceChildren(this.element),await this.refresh(),this.closed||this.show(e,`error`,t instanceof Error?t.message:`VoiceID could not be updated.`)}finally{this.busy=!1}}cancel=()=>{this.closed||(this.closed=!0,this.parent.dispatchEvent(new Event(`cancel`,{bubbles:!0})),this.completion.reject(Error(`VoiceID management was cancelled.`)))};dispose(){this.closed=!0,this.signal.removeEventListener(`abort`,this.cancel),this.element.remove()}};function d(e,t,n){let r=e.createElementNS(c,`svg`);r.setAttribute(`viewBox`,`0 0 24 24`),r.setAttribute(`width`,String(n)),r.setAttribute(`height`,String(n)),r.setAttribute(`aria-hidden`,`true`);let i=e.createElementNS(c,`path`);return i.setAttribute(`d`,t),i.setAttribute(`fill`,`none`),i.setAttribute(`stroke`,`currentColor`),i.setAttribute(`stroke-width`,`1.75`),i.setAttribute(`stroke-linecap`,`round`),i.setAttribute(`stroke-linejoin`,`round`),r.append(i),r}async function f(t,n,r,i){switch(t){case`replace`:return{kind:t,guard:n,snapshot:r,signal:i};case`import`:{if(r.kind!==`missing`)throw Error(`The previous enrollment is unavailable.`);let a=await e();if(!a)throw Error(`The previous enrollment is unavailable.`);return{kind:t,guard:n,snapshot:r,signal:i,baseline:a}}case`improve`:case`reset`:if(r.kind!==`present`)throw Error(`Record or import your original voice first.`);return{kind:t,guard:n,snapshot:r,signal:i};default:return p(t)}}function p(e){throw Error(`Unsupported VoiceID enrollment management action.`)}async function m(e,t,n,r){t.throwIfAborted();let i=await e.prepareActivation();return t.throwIfAborted(),i.kind===`enroll_existing`?{kind:`management`,action:h.bind(null,r,i,n)}:{kind:`recording`,action:g.bind(null,r,i,n),expiresAtMs:null}}async function h(e,t,n,r){return await l(n,t.confirmChange,t.scope,r,e),r.throwIfAborted(),{kind:`activated`,walletId:t.scope.walletId,walletAuthMethodId:t.scope.walletAuthMethodId}}function g(e,t,n,r,a,o){return t.activate(i.bind(null,e,{parent:n,onCapture:a,phrase:o}),r)}export{m as prepareActivationSurface};
@@ -0,0 +1 @@
1
+ import{_ as e,a as t,c as n,d as r,f as i,g as a,h as o,i as s,m as c,o as l,p as u,s as d,t as f,u as p,v as m}from"./prompt-DsRKGfyb.js";import{WorkerDeferred as h,assertVoiceOwner as g,base64UrlEncode as _,createBrowserVoiceDevice as v,isFiniteNumber as ee,openBrowserVoiceFactor as y,parseVoiceIdDeviceAssertion as b,prepareVoiceOwner as x,readBrowserVoiceDevice as S,requireRecord as C,resolveActivatingVoiceEnrollmentScope as w,resolveVoiceEnrollmentScope as T,toError as E,voiceEnrollmentStorage as D,voiceIdWalletSessionChallengeBytes as O}from"../voiceid-host.js";const k=`e04dd7a6a1e23fc7b89e47682ea9d0a3946cf7bc59d07922c3db3efc52ae4269`,A=`redimnet-b1:${k}`,j=new o({path:`/sdk/voiceid/redimnet-b1.onnx`,sha256:k,bytes:8859593,label:`Speaker verification`});async function M(e){let t=await j.prepare(),n=new(await(import(`./ort.wasm.bundle.min-7y-hlRN8.js`))).Tensor(`float32`,e,[1,e.length]);try{let e=await t.run({samples:n});try{let t=e.embedding;if(!t||!(t.data instanceof Float32Array))throw Error(`VoiceID model returned an invalid embedding.`);return N(Array.from(t.data))}finally{for(let t of Object.values(e))t.dispose()}}finally{n.dispose()}}function N(e){if(e.length!==192)throw Error(`VoiceID template dimensions are invalid.`);let t=0;for(let n of e){if(!Number.isFinite(n))throw Error(`VoiceID template is invalid.`);t+=n*n}if(t<1e-12)throw Error(`VoiceID template contains no signal.`);let n=Math.sqrt(t),r=[];for(let t of e)r.push(t/n);return r}function P(e,t){if(e.length!==192||t.length!==192)throw Error(`VoiceID templates are incompatible.`);let n=0;for(let r=0;r<e.length;r+=1)n+=e[r]*t[r];return n}function F(e){return e.asset}function I(e,t){return e+t.size}var L=class{element=document.createElement(`section`);status=document.createElement(`p`);meter=document.createElement(`progress`);retryButton=document.createElement(`button`);retry=null;cancelled=new h;reveal;received=new Map;models;assets;total;constructor(t,n,r){this.parent=t,this.signal=n,this.models=[j,u(r),p],this.assets=[e,...this.models.map(F)],this.total=this.assets.reduce(I,0),this.element.className=`seams-voiceid-model-download`,this.status.setAttribute(`role`,`status`),this.status.setAttribute(`aria-live`,`polite`),this.meter.setAttribute(`aria-label`,`VoiceID download`),this.meter.style.width=`100%`,this.retryButton.type=`button`,this.retryButton.className=`seams-voiceid-primary`,this.retryButton.textContent=`Retry loading`,this.retryButton.hidden=!0,this.retryButton.addEventListener(`click`,this.retryLoading),this.element.append(this.status,this.meter,this.retryButton),this.status.textContent=`Loading saved VoiceID…`,this.reveal=setTimeout(t.append.bind(t,this.element),300),n.addEventListener(`abort`,this.abort,{once:!0})}settle=()=>{clearTimeout(this.reveal),this.signal.removeEventListener(`abort`,this.abort),this.retryButton.removeEventListener(`click`,this.retryLoading)};abort=()=>{let e=new DOMException(`VoiceID preparation was cancelled.`,`AbortError`);this.cancelled.reject(e),this.retry?.reject(e)};retryLoading=()=>{this.retry?.resolve(),this.retry=null};async prepare(){this.signal.throwIfAborted(),await Promise.race([this.prepareUntilReady(),this.cancelled.promise])}async prepareUntilReady(){for(;;){this.signal.throwIfAborted(),this.retryButton.hidden=!0,this.meter.hidden=!1;try{for(let e of this.assets)await e.download(this.update.bind(this,e)),this.signal.throwIfAborted();this.preparing();for(let e of this.models)await e.prepare(),this.signal.throwIfAborted();this.ready();return}catch(e){if(this.signal.throwIfAborted(),!(e instanceof a))throw e;clearTimeout(this.reveal),this.parent.append(this.element),this.element.dataset.state=`failed`,this.meter.hidden=!0,this.status.textContent=e.message,this.retry=new h,this.retryButton.hidden=!1,this.retryButton.focus(),await this.retry.promise}}}update=(e,t)=>{switch(t.kind){case`checking_cache`:return;case`downloading`:this.received.set(e,t.received),this.element.dataset.state=`downloading`;break;case`ready`:this.received.set(e,e.size);break;default:}if(this.element.dataset.state!==`downloading`)return;let n=0;for(let e of this.received.values())n+=e;this.meter.max=this.total,this.meter.value=n,this.status.textContent=`Downloading VoiceID: ${(n/1e6).toFixed(1)} of ${(this.total/1e6).toFixed(1)} MB · ${Math.floor(n/this.total*100)}%`};preparing(){this.element.dataset.state=`preparing`,this.meter.removeAttribute(`value`),this.status.textContent=`Preparing VoiceID…`}ready(){this.element.dataset.state=`ready`,this.meter.hidden=!0,this.status.textContent=`VoiceID is ready.`}};async function R(e,t,n){let r=new L(e,t,n);try{await r.prepare()}finally{r.settle()}}const z=.2,B=D({model:A,parseEnrollment:H});function V(e){if(!Array.isArray(e)||!e.every(ee))throw Error(`VoiceID template is invalid.`);let t=N(e);for(let n=0;n<e.length;n+=1)if(Math.abs(e[n]-t[n])>1e-6)throw Error(`VoiceID template is not normalized.`);return e.slice()}function H(e,t){if(e===void 0)return null;let n=C(e,`VoiceID enrollment`),r=C(n.scope,`VoiceID enrollment scope`);if(n.kind!==`browser_voiceid_enrollment_v2`||r.walletId!==t.walletId||r.authorityId!==t.authorityId||r.walletAuthMethodId!==t.walletAuthMethodId||r.deviceKeyId!==t.deviceKeyId||typeof n.generation!=`string`||!n.generation||typeof n.revision!=`number`||!Number.isSafeInteger(n.revision)||n.revision<0)throw Error(`VoiceID enrollment identity is invalid.`);if(n.model!==A)return null;let i=V(n.baseline),a={kind:`baseline`};try{let e=C(n.adaptation,`VoiceID improvements`);if(e.kind===`adapted`&&Array.isArray(e.samples)&&e.samples.length===3){let t=e.samples.map(V);W(i,t),a={kind:`adapted`,samples:t}}}catch{a={kind:`baseline`}}return{kind:`browser_voiceid_enrollment_v2`,scope:t,model:A,generation:n.generation,revision:n.revision,baseline:i,adaptation:a}}function U(e,t){let n=Array(192).fill(0);for(let e of t)for(let r=0;r<n.length;r+=1)n[r]+=e[r]/t.length;let r=N(n);for(let t=0;t<n.length;t+=1)n[t]=(1-z)*e[t]+z*r[t];return N(n)}function W(e,t){if(t.length!==3)throw Error(`Record three samples before saving voice improvements.`);for(let n of t)if(P(e,n)<.45)throw Error(`This sample differs from your original voice. Try again or re-record your enrollment.`);if(P(e,U(e,t))<.98)throw Error(`These samples differ too much from your original voice. Re-record your enrollment instead.`)}function G(e){return B.read(e)}async function K(e,t){let n=await B.readTemplate(e,t),r=n.adaptation;return{template:r.kind===`adapted`?U(n.baseline,r.samples):[...n.baseline],baseline:[...n.baseline],kind:r.kind}}async function q(){let e=await B.readImportable();if(e===void 0)return null;let t=C(e,`Previous VoiceID enrollment`);return t.kind!==`browser_voiceid_enrollment_v1`||t.model!==A?null:V(t.template)}async function J(e){let{scope:t,signal:n}=e;switch(e.kind){case`activate`:return B.commit({kind:`activate`,scope:t,signal:n,guard:e.guard,snapshot:e.snapshot,baseline:V(e.baseline)});case`import`:return B.commit({kind:`import`,scope:t,signal:n,guard:e.guard,snapshot:e.snapshot,confirmation:e.confirmation,baseline:V(e.baseline)});case`replace`:return B.commit({kind:`replace`,scope:t,signal:n,guard:e.guard,snapshot:e.snapshot,confirmation:e.confirmation,baseline:V(e.baseline)});case`improve`:return W(e.snapshot.enrollment.baseline,e.samples),B.commit({kind:`improve`,scope:t,signal:n,guard:e.guard,snapshot:e.snapshot,confirmation:e.confirmation,samples:e.samples});case`reset`:return B.commit({kind:`reset`,scope:t,signal:n,guard:e.guard,snapshot:e.snapshot,confirmation:e.confirmation});default:return Y(e)}}function Y(e){throw Error(`Unsupported VoiceID enrollment change.`)}async function X(e,t,n,r){await R(e,n,r),n.throwIfAborted();let i=new Z(e,t,n,r);try{await i.result}finally{i.dispose()}}var Z=class{completion=new h;result=this.completion.promise;status;prompt;phrase=c(null);record;cancel;samples=[];phase=`ready`;get closed(){return this.phase===`closed`}controller=new AbortController;guardTimer;checkingGuard=!1;constructor(e,t,n,r){this.plan=t,this.signal=n,this.model=r,this.prompt=new f(e.ownerDocument,`Enroll your voice in this browser`,this.phrase),this.prompt.title.textContent=`Read aloud · 0 of 3 accepted`,this.status=this.prompt.status,this.record=this.prompt.record,this.cancel=this.prompt.cancel,this.record.textContent=`Record sample 1`,this.record.addEventListener(`click`,this.capture),this.cancel.setAttribute(`aria-label`,`Cancel enrollment`),this.cancel.addEventListener(`click`,this.cancelled),this.prompt.ready(t.kind===`improve`?`Read naturally. Your original enrollment stays unchanged.`:`Read the full phrase at your normal pace.`),e.replaceChildren(this.prompt.element),n.addEventListener(`abort`,this.cancelled,{once:!0}),this.guardTimer=setInterval(this.checkGuard,250),n.aborted?this.cancelled():this.record.focus()}capture=()=>{this.collect()};async collect(){if(this.phase!==`ready`)return;let e=this.samples.length+1;try{d(),this.phase=`recording`,this.record.disabled=!0,this.status.textContent=`Opening microphone…`;let e=await t(this.controller.signal,this.prompt.capture);if(this.signal.aborted||this.closed){e.kind===`captured`&&e.samples.fill(0);return}if(e.kind===`insufficient_audio`){this.status.textContent=n(e.quality);return}if(this.plan.kind===`improve`&&e.quality.noise!==`normal`){e.samples.fill(0),this.status.textContent=`Use a quiet place to improve your voice enrollment.`;return}let a;try{if(await g(this.plan.scope,this.plan.guard),this.status.textContent=`Checking your voice…`,(await i(e.samples,this.phrase,this.model)).kind===`mismatch`)throw new r;a=await M(e.samples)}finally{e.samples.fill(0)}if(this.signal.aborted||this.closed){a.fill(0);return}if(this.plan.kind===`improve`&&P(this.plan.snapshot.enrollment.baseline,a)<.45)throw a.fill(0),Error(`Your voice did not match the original enrollment. To replace it, return to Manage voice and choose Record voice again.`);for(let e of this.samples)if(P(e,a)<.45)throw a.fill(0),Error(`This sample differs from the earlier samples. Use the same microphone and try again.`);if(this.samples.push(a),this.samples.length<3){this.prompt.accepted(),this.status.textContent=`Sample ${this.samples.length} accepted. Record the next sample.`,this.record.textContent=`Record sample ${this.samples.length+1}`;return}let o=Array(192).fill(0);for(let e of this.samples)for(let t=0;t<o.length;t+=1)o[t]+=e[t]/3;this.phase=`committing`,this.prompt.title.textContent=`3 of 3 accepted`,this.status.textContent=`Saving voice enrollment…`;let s=this.plan;switch(s.kind){case`activate`:await J({kind:`activate`,scope:s.scope,guard:s.guard,snapshot:s.snapshot,baseline:N(o),signal:this.controller.signal});break;case`replace`:await J({kind:`replace`,scope:s.scope,guard:s.guard,snapshot:s.snapshot,baseline:N(o),confirmation:s.confirmation,signal:this.controller.signal});break;case`improve`:await J({kind:`improve`,scope:s.scope,guard:s.guard,snapshot:s.snapshot,samples:this.samples,confirmation:s.confirmation,signal:this.controller.signal});break;default:return Q(s)}if(this.signal.aborted||this.closed)return;this.phase=`closed`,this.prompt.accepted(),this.status.textContent=`Voice enrollment saved.`,this.completion.resolve()}catch(e){if(!this.closed&&this.phase===`committing`){this.phase=`closed`,this.controller.abort(),this.completion.reject(E(e));return}!this.closed&&this.samples.length===3&&this.samples.pop()?.fill(0),this.closed||(this.status.textContent=e instanceof Error?e.message:`VoiceID enrollment failed.`)}finally{this.closed||(this.samples.length<e&&(this.record.textContent=`Retry sample ${e}`,this.status.textContent=`Sample ${e} was not accepted. ${this.status.textContent??``}`),this.phrase=c(this.phrase),this.prompt.setPhrase(this.phrase),this.prompt.title.textContent=`Read aloud · ${this.samples.length} of 3 accepted`,this.prompt.ready(this.status.textContent??``),this.phase=`ready`,this.record.disabled=!1)}}cancelled=()=>{this.closed||(this.phase=`closed`,this.controller.abort(),this.completion.reject(Error(`VoiceID enrollment was cancelled.`)))};checkGuard=()=>{this.closed||this.checkingGuard||(this.checkingGuard=!0,this.validateGuard())};async validateGuard(){try{await g(this.plan.scope,this.plan.guard)}catch(e){this.closed||(this.phase=`closed`,this.controller.abort(),this.completion.reject(E(e)))}finally{this.checkingGuard=!1}}dispose(){this.phase=`closed`,this.controller.abort(),clearInterval(this.guardTimer),this.signal.removeEventListener(`abort`,this.cancelled),this.prompt.dispose(),this.record.removeEventListener(`click`,this.capture),this.cancel.removeEventListener(`click`,this.cancelled);for(let e of this.samples)e.fill(0)}};function Q(e){throw Error(`Unsupported VoiceID enrollment capture.`)}async function te(e,n,r,a,o){let s=await t(n,r);if(s.kind===`insufficient_audio`)return n.throwIfAborted(),s;try{n.throwIfAborted();let t=await i(s.samples,a,o),r=await M(s.samples),c;try{n.throwIfAborted();let t=await K(e,n);try{c=P(r,t.template)}finally{t.template.fill(0),t.baseline.fill(0)}}finally{r.fill(0)}return c<.45?{kind:`mismatch`,quality:s.quality}:t.kind===`matched`?{kind:`matched`}:{kind:`phrase_mismatch`}}finally{s.samples.fill(0)}}async function ne(e,t,n){d();let r=await v(n.walletId,n.walletAuthMethodId),i=await w(r);if(await G(i))await $({kind:`activation`,scope:i,owner:await x(i,`activating`)},n.signal,t.onCapture,t.phrase,e);else{let r=await x(i,`activating`);await X(t.parent,{kind:`activate`,scope:i,guard:r,snapshot:{kind:`missing`}},n.signal,e)}n.signal.throwIfAborted();let a=await y(r);if(n.signal.aborted)throw a.fill(0),Error(`VoiceID activation was cancelled.`);return{kind:`activated`,publicKeyB64u:r.publicKeyB64u,deviceKeyId:r.deviceKeyId,factorSecret32:a}}async function re(e,t,n){l();let{challenge:r}=n;if(r.requestOrigin!==location.origin||r.expiresAtMs<=Date.now())throw Error(`VoiceID challenge is expired or belongs to another Wallet origin.`);let i=await S(r.walletId,r.walletAuthMethodId);if(!i||i.deviceKeyId!==r.deviceKeyId)throw Error(`VoiceID device key is unavailable in this browser.`);if(await $({kind:`active`,scope:await T(r.walletId,r.walletAuthMethodId)},n.signal,t.onCapture,t.phrase,e),n.signal.throwIfAborted(),r.expiresAtMs<=Date.now())throw Error(`VoiceID challenge expired. Start unlock again.`);let a=await crypto.subtle.sign(`Ed25519`,i.privateKey,O(r)),o=await y(i);if(n.signal.aborted||r.expiresAtMs<=Date.now())throw o.fill(0),Error(`VoiceID unlock expired or was cancelled.`);return{kind:`unlocked`,assertion:b({kind:`voiceid_device_assertion_v1`,challenge:r,signatureB64u:_(new Uint8Array(a))}),factorSecret32:o}}async function $(e,t,n,i,a){let o=await te(e,t,n,i,a);switch(o.kind){case`matched`:return;case`insufficient_audio`:throw new s(o.quality);case`mismatch`:throw new m(o.quality);case`phrase_mismatch`:throw new r;default:return ie(o)}}function ie(e){throw Error(`Unexpected voice result: ${String(e)}`)}export{q as a,J as i,re as n,G as o,X as r,R as s,ne as t};
@@ -1,4 +1,4 @@
1
- import{d as e,h as t,i as n,l as r,n as i,r as a,t as o,y as s}from"./prompt-yshUSnwN.js";import{SeamsWordmark as c,VOICE_ID_HOST_API_VERSION as l,WorkerDeferred as u,authMenuSuccessCopy as d,backIcon as f,createCspStylesheetManager as p,createWalletIframeSurfaceMeasurementReporter as m,getDefaultCspNonce as h,toError as g}from"../voiceid-host.js";const _=new WeakMap;var v=class{footer;constructor(e,t){this.prompt=t;let n=e.ownerDocument,r=_.get(n);r||(r=p({doc:n,baseCss:`
1
+ import{d as e,i as t,l as n,m as r,n as i,r as a,t as o,v as s}from"./prompt-DsRKGfyb.js";import{SeamsWordmark as c,VOICE_ID_HOST_API_VERSION as l,WorkerDeferred as u,authMenuSuccessCopy as d,backIcon as f,createCspStylesheetManager as p,createWalletIframeSurfaceMeasurementReporter as m,getDefaultCspNonce as h,toError as g}from"../voiceid-host.js";const _=new WeakMap;var v=class{footer;constructor(e,t){this.prompt=t;let n=e.ownerDocument,r=_.get(n);r||(r=p({doc:n,baseCss:`
2
2
  .seams-voiceid-activation-surface.seams-voiceid-unlock {
3
3
  box-sizing: border-box;
4
4
  overflow: hidden;
@@ -52,7 +52,8 @@ import{d as e,h as t,i as n,l as r,n as i,r as a,t as o,y as s}from"./prompt-ysh
52
52
  padding: 0.75rem 1.5rem 1.5rem;
53
53
  grid-template-rows: auto minmax(6rem, auto) 5rem minmax(3.375rem, auto) auto auto;
54
54
  }
55
- .seams-voiceid-unlock .seams-voiceid-record-slot:has(button[hidden]) {
55
+ /* Only a hidden record button empties the slot; the microphone choice is hidden by default. */
56
+ .seams-voiceid-unlock .seams-voiceid-record-slot:has(> .seams-voiceid-primary[hidden]) {
56
57
  display: none;
57
58
  }
58
59
  .seams-voiceid-unlock-footer {
@@ -77,4 +78,4 @@ import{d as e,h as t,i as n,l as r,n as i,r as a,t as o,y as s}from"./prompt-ysh
77
78
  color: var(--seams-colors-textPrimary, #eff2f3);
78
79
  }
79
80
  }
80
- `,nonce:h}),_.set(n,r)),r.ensureBase(),e.classList.add(`seams-voiceid-unlock`);let o=n.createElement(`div`);o.className=`seams-voiceid-unlock-header`,t.cancel.className=`seams-voiceid-unlock-back`,t.cancel.setAttribute(`aria-label`,`Back`),t.cancel.replaceChildren(),i(f(),t.cancel),o.append(t.cancel),e.prepend(o),this.footer=n.createElement(`div`),this.footer.className=`seams-voiceid-unlock-footer`,i([a(`span`,null,`Secured by`),` `,a(c,{})],this.footer),e.append(this.footer)}succeed(){let e=this.prompt.cancel;return e.animate([{opacity:1},{opacity:0}],{duration:150,easing:`ease-in`,fill:`forwards`}),{top:e.getBoundingClientRect().top,bottom:this.footer.getBoundingClientRect().top}}dispose(){i(null,this.prompt.cancel),i(null,this.footer)}},y=class{result;completion=new u;controller=new AbortController;element;activateButton;cancelButton;status;prompt;unlockFrame;autoStartUnlock;unmountCapture;measurement;phrase=t(null);state={kind:`preparing`};settlement=`closed`;expiryTimer=null;constructor(e,t,n,r){let i=t===`activation`?`Activate VoiceID`:`Unlock with VoiceID`,a=document.getElementById(`root`)??document.body;if(!a)throw Error(`Wallet activation surface has no mount root.`);this.element=document.createElement(`section`),this.element.className=`seams-wallet-ui seams-auth-method-activation-surface seams-voiceid-activation-surface`,this.element.setAttribute(`role`,`dialog`),this.element.setAttribute(`aria-modal`,`true`),this.element.setAttribute(`aria-label`,i),this.prompt=new o(document,i,this.phrase),this.element.append(this.prompt.element),this.unlockFrame=t===`unlock`?new v(this.element,this.prompt):null,this.autoStartUnlock=this.unlockFrame!==null&&r!==void 0,this.status=this.prompt.status,this.status.textContent=`Loading VoiceID…`,this.prompt.title.textContent=`VoiceID`,this.element.dataset.preparation=`loading`,this.activateButton=this.prompt.record,this.activateButton.textContent=i,this.activateButton.disabled=!0,this.activateButton.hidden=this.autoStartUnlock,this.activateButton.addEventListener(`click`,this.begin),this.cancelButton=this.prompt.cancel,this.cancelButton.addEventListener(`click`,this.cancel),this.element.addEventListener(`cancel`,this.cancel),this.unmountCapture=r?r(this.element):null,r||a.appendChild(this.element),this.measurement=!r&&n.kind===`wallet_iframe`?m({kind:`request_surface`,element:this.element,requestId:n.requestId,postMeasurement:n.postMeasurement}):null,this.cancelButton.focus(),this.result=this.completion.promise,this.initialize(e)}dispose(){this.measurement?.disconnect(),this.expiryTimer!==null&&clearTimeout(this.expiryTimer),this.element.removeEventListener(`cancel`,this.cancel),this.activateButton.removeEventListener(`click`,this.begin),this.cancelButton.removeEventListener(`click`,this.cancel),this.unlockFrame?.dispose(),this.prompt.dispose(),this.unmountCapture?this.unmountCapture(this.settlement):this.element.remove()}async initialize(e){try{await new Promise(S),this.controller.signal.throwIfAborted();let t=await e(this.controller.signal,{parent:this.element,progress:this.prompt.progress});if(this.state.kind===`closed`)return;if(t.kind===`management`){this.element.setAttribute(`aria-label`,`Manage voice`),this.element.dataset.preparation=`ready`,this.state={kind:`capturing`};let e=await t.action(this.controller.signal);this.controller.signal.throwIfAborted(),this.state={kind:`closed`},this.completion.resolve(e);return}let n=t.expiresAtMs===null?null:t.expiresAtMs-Date.now();if(n!==null&&n<=0)throw Error(`VoiceID challenge expired. Start unlock again.`);this.state={kind:`ready`,capture:t},this.expiryTimer=n===null?null:setTimeout(this.expire,n);for(let e of this.element.querySelectorAll(`.seams-voiceid-model-download`))e.remove();this.element.dataset.preparation=`ready`,this.prompt.title.textContent=`Read aloud`,this.status.textContent=`Read naturally, then pause.`,this.activateButton.disabled=!1,this.autoStartUnlock?this.begin():this.activateButton.focus()}catch(e){if(this.state.kind===`closed`)return;this.state={kind:`closed`},this.completion.reject(g(e))}}begin=()=>{if(this.state.kind!==`ready`)return;let e=this.state.capture;this.state={kind:`capturing`},this.perform(e)};async perform(i){this.activateButton.disabled=!0,this.status.textContent=`Opening microphone…`;try{let e=await i.action(this.controller.signal,this.prompt.capture,this.phrase);if(this.state.kind===`closed`)return;this.unlockFrame&&await this.showUnlocked(this.unlockFrame),this.state={kind:`closed`},this.completion.resolve(e)}catch(a){if(this.state.kind===`closed`)return;if(a instanceof n||a instanceof e||a instanceof r||a instanceof s){if(i.expiresAtMs!==null&&Date.now()>=i.expiresAtMs){this.expire();return}let e=this.phrase;this.phrase=t(e),this.prompt.setPhrase(this.phrase),this.state={kind:`ready`,capture:i},this.activateButton.hidden=!1,this.activateButton.textContent=`Try again`,this.prompt.ready(a.message),this.activateButton.focus();return}this.state={kind:`closed`},this.completion.reject(g(a))}}async showUnlocked(e){this.state={kind:`succeeding`},this.settlement=`succeeded`,this.expiryTimer!==null&&clearTimeout(this.expiryTimer),this.expiryTimer=null,this.cancelButton.disabled=!0;let t=performance.now(),n=d(`authenticated`);await this.prompt.succeed(n.headline,n.message,e.succeed());let r=Math.max(0,1300-(performance.now()-t));await this.element.animate([{opacity:1},{opacity:1,offset:r/(r+240),easing:`ease-in`},{opacity:0}],{duration:r+240,fill:`forwards`}).finished}cancel=()=>{this.state.kind===`closed`||this.state.kind===`succeeding`||(this.state={kind:`closed`},this.controller.abort(),this.completion.reject(new b))};expire=()=>{this.state.kind===`closed`||this.state.kind===`succeeding`||(this.state={kind:`closed`},this.controller.abort(),this.completion.reject(Error(`VoiceID challenge expired. Start unlock again.`)))}},b=class extends Error{constructor(){super(`VoiceID capture was cancelled.`),this.name=`VoiceIdCaptureCancelledError`}};async function x(e){let t=new y(e.prepare,e.purpose,e.measurement,e.mountCapture);try{return await t.result}finally{t.dispose()}}function S(e){requestAnimationFrame(C.bind(null,e))}function C(e){setTimeout(e,0)}const w=6;if(l!==6)throw Error(`VoiceID requires a matching Wallet host API.`);function T(e){return{unlock:E.bind(null,e),activate:O.bind(null,e),review:A.bind(null,e)}}function E(e,t){return x({purpose:`unlock`,measurement:t.surfaceMeasurementBinding,mountCapture:t.mountCapture,prepare:D.bind(null,e,t)})}async function D(e,t,n,r){let i=await import(`./unlock-CjaOTqR2.js`);return n.throwIfAborted(),i.prepareUnlockSurface(t,n,r.progress,e)}async function O(e,t){try{return await x({purpose:`activation`,measurement:t.surfaceMeasurementBinding,prepare:k.bind(null,e,t)})}catch(e){if(e instanceof b)return{kind:`cancelled`};throw e}}async function k(e,t,n,r){let i=await import(`./addVoiceId-DAtqPP1y.js`);return n.throwIfAborted(),i.prepareActivationSurface(t,n,r.parent,e)}async function A(e,t){return(await import(`./approval-DHvEDAip.js`)).VoiceIdApproval.forReview(t,e)}export{T as createVoiceIdHostPlugin,w as hostApiVersion};
81
+ `,nonce:h}),_.set(n,r)),r.ensureBase(),e.classList.add(`seams-voiceid-unlock`);let o=n.createElement(`div`);o.className=`seams-voiceid-unlock-header`,t.cancel.className=`seams-voiceid-unlock-back`,t.cancel.setAttribute(`aria-label`,`Back`),t.cancel.replaceChildren(),i(f(),t.cancel),o.append(t.cancel),e.prepend(o),this.footer=n.createElement(`div`),this.footer.className=`seams-voiceid-unlock-footer`,i([a(`span`,null,`Secured by`),` `,a(c,{})],this.footer),e.append(this.footer)}succeed(){let e=this.prompt.cancel;return e.animate([{opacity:1},{opacity:0}],{duration:150,easing:`ease-in`,fill:`forwards`}),{top:e.getBoundingClientRect().top,bottom:this.footer.getBoundingClientRect().top}}dispose(){i(null,this.prompt.cancel),i(null,this.footer)}},y=class{result;completion=new u;controller=new AbortController;element;activateButton;cancelButton;status;prompt;unlockFrame;autoStartUnlock;unmountCapture;measurement;phrase=r(null);state={kind:`preparing`};settlement=`closed`;expiryTimer=null;constructor(e,t,n,r){let i=t===`activation`?`Activate VoiceID`:`Unlock with VoiceID`,a=document.getElementById(`root`)??document.body;if(!a)throw Error(`Wallet activation surface has no mount root.`);this.element=document.createElement(`section`),this.element.className=`seams-wallet-ui seams-auth-method-activation-surface seams-voiceid-activation-surface`,this.element.setAttribute(`role`,`dialog`),this.element.setAttribute(`aria-modal`,`true`),this.element.setAttribute(`aria-label`,i),this.prompt=new o(document,i,this.phrase),this.element.append(this.prompt.element),this.unlockFrame=t===`unlock`?new v(this.element,this.prompt):null,this.autoStartUnlock=this.unlockFrame!==null&&r!==void 0,this.status=this.prompt.status,this.status.textContent=`Loading VoiceID…`,this.prompt.title.textContent=`VoiceID`,this.element.dataset.preparation=`loading`,this.activateButton=this.prompt.record,this.activateButton.textContent=i,this.activateButton.disabled=!0,this.activateButton.hidden=this.autoStartUnlock,this.activateButton.addEventListener(`click`,this.begin),this.cancelButton=this.prompt.cancel,this.cancelButton.addEventListener(`click`,this.cancel),this.element.addEventListener(`cancel`,this.cancel),this.unmountCapture=r?r(this.element):null,r||a.appendChild(this.element),this.measurement=!r&&n.kind===`wallet_iframe`?m({kind:`request_surface`,element:this.element,requestId:n.requestId,postMeasurement:n.postMeasurement}):null,this.cancelButton.focus(),this.result=this.completion.promise,this.initialize(e)}dispose(){this.measurement?.disconnect(),this.expiryTimer!==null&&clearTimeout(this.expiryTimer),this.element.removeEventListener(`cancel`,this.cancel),this.activateButton.removeEventListener(`click`,this.begin),this.cancelButton.removeEventListener(`click`,this.cancel),this.unlockFrame?.dispose(),this.prompt.dispose(),this.unmountCapture?this.unmountCapture(this.settlement):this.element.remove()}async initialize(e){try{await new Promise(S),this.controller.signal.throwIfAborted();let t=await e(this.controller.signal,{parent:this.element,progress:this.prompt.progress});if(this.state.kind===`closed`)return;if(t.kind===`management`){this.element.setAttribute(`aria-label`,`Manage voice`),this.element.dataset.preparation=`ready`,this.state={kind:`capturing`};let e=await t.action(this.controller.signal);this.controller.signal.throwIfAborted(),this.state={kind:`closed`},this.completion.resolve(e);return}let n=t.expiresAtMs===null?null:t.expiresAtMs-Date.now();if(n!==null&&n<=0)throw Error(`VoiceID challenge expired. Start unlock again.`);this.state={kind:`ready`,capture:t},this.expiryTimer=n===null?null:setTimeout(this.expire,n);for(let e of this.element.querySelectorAll(`.seams-voiceid-model-download`))e.remove();this.element.dataset.preparation=`ready`,this.prompt.title.textContent=`Read aloud`,this.status.textContent=`Read naturally, then pause.`,this.activateButton.disabled=!1,this.autoStartUnlock?this.begin():this.activateButton.focus()}catch(e){if(this.state.kind===`closed`)return;this.state={kind:`closed`},this.completion.reject(g(e))}}begin=()=>{if(this.state.kind!==`ready`)return;let e=this.state.capture;this.state={kind:`capturing`},this.perform(e)};async perform(i){this.activateButton.disabled=!0,this.status.textContent=`Opening microphone…`;try{let e=await i.action(this.controller.signal,this.prompt.capture,this.phrase);if(this.state.kind===`closed`)return;this.unlockFrame&&await this.showUnlocked(this.unlockFrame),this.state={kind:`closed`},this.completion.resolve(e)}catch(a){if(this.state.kind===`closed`)return;if(a instanceof t||a instanceof e||a instanceof n||a instanceof s){if(i.expiresAtMs!==null&&Date.now()>=i.expiresAtMs){this.expire();return}let e=this.phrase;this.phrase=r(e),this.prompt.setPhrase(this.phrase),this.state={kind:`ready`,capture:i},this.activateButton.hidden=!1,this.activateButton.textContent=`Try again`,this.prompt.ready(a.message),this.activateButton.focus();return}this.state={kind:`closed`},this.completion.reject(g(a))}}async showUnlocked(e){this.state={kind:`succeeding`},this.settlement=`succeeded`,this.expiryTimer!==null&&clearTimeout(this.expiryTimer),this.expiryTimer=null,this.cancelButton.disabled=!0;let t=performance.now(),n=d(`authenticated`);await this.prompt.succeed(n.headline,n.message,e.succeed());let r=Math.max(0,1300-(performance.now()-t));await this.element.animate([{opacity:1},{opacity:1,offset:r/(r+240),easing:`ease-in`},{opacity:0}],{duration:r+240,fill:`forwards`}).finished}cancel=()=>{this.state.kind===`closed`||this.state.kind===`succeeding`||(this.state={kind:`closed`},this.controller.abort(),this.completion.reject(new b))};expire=()=>{this.state.kind===`closed`||this.state.kind===`succeeding`||(this.state={kind:`closed`},this.controller.abort(),this.completion.reject(Error(`VoiceID challenge expired. Start unlock again.`)))}},b=class extends Error{constructor(){super(`VoiceID capture was cancelled.`),this.name=`VoiceIdCaptureCancelledError`}};async function x(e){let t=new y(e.prepare,e.purpose,e.measurement,e.mountCapture);try{return await t.result}finally{t.dispose()}}function S(e){requestAnimationFrame(C.bind(null,e))}function C(e){setTimeout(e,0)}const w=7;if(l!==7)throw Error(`VoiceID requires a matching Wallet host API.`);function T(e){return{unlock:E.bind(null,e),activate:O.bind(null,e)}}function E(e,t){return x({purpose:`unlock`,measurement:t.surfaceMeasurementBinding,mountCapture:t.mountCapture,prepare:D.bind(null,e,t)})}async function D(e,t,n,r){let i=await import(`./unlock-DdzR0kE9.js`);return n.throwIfAborted(),i.prepareUnlockSurface(t,n,r.progress,e)}async function O(e,t){try{return await x({purpose:`activation`,measurement:t.surfaceMeasurementBinding,prepare:k.bind(null,e,t)})}catch(e){if(e instanceof b)return{kind:`cancelled`};throw e}}async function k(e,t,n,r){let i=await import(`./addVoiceId-B2XmPljL.js`);return n.throwIfAborted(),i.prepareActivationSurface(t,n,r.parent,e)}export{T as createVoiceIdHostPlugin,w as hostApiVersion};