@seams/voiceid 0.0.0-stage → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/LICENSE.md +201 -0
  2. package/README.md +74 -2
  3. package/THIRD_PARTY_NOTICES.md +504 -0
  4. package/dist/compose-host.mjs +11 -0
  5. package/dist/esm/browser/ribbon.js +489 -0
  6. package/dist/esm/capture/prompt.js +515 -0
  7. package/dist/esm/capture/visual.js +87 -0
  8. package/dist/esm/descriptor.js +7 -0
  9. package/dist/esm/index.js +2 -0
  10. package/dist/esm/react/VoiceAssistantCard.css +313 -0
  11. package/dist/esm/react/VoiceAssistantCard.js +147 -0
  12. package/dist/esm/react.js +3 -0
  13. package/dist/hosting.d.mts +4 -0
  14. package/dist/hosting.mjs +91 -0
  15. package/dist/public/sdk/voiceid/AURORA_LICENSE.txt +202 -0
  16. package/dist/public/sdk/voiceid/NOTICE.txt +54 -0
  17. package/dist/public/sdk/voiceid/SILERO_LICENSE.txt +21 -0
  18. package/dist/public/sdk/voiceid/addVoiceId-CeBXVHqs.js +1 -0
  19. package/dist/public/sdk/voiceid/approval-CCbdLhTv.js +1 -0
  20. package/dist/public/sdk/voiceid/aurora-int8.onnx +0 -0
  21. package/dist/public/sdk/voiceid/deviceBridge-wRAbqdap.js +1 -0
  22. package/dist/public/sdk/voiceid/enrollment-DIRoCkx5.js +1 -0
  23. package/dist/public/sdk/voiceid/host.js +80 -0
  24. package/dist/public/sdk/voiceid/ort-wasm-simd-threaded.mjs +59 -0
  25. package/dist/public/sdk/voiceid/ort-wasm-simd-threaded.wasm +0 -0
  26. package/dist/public/sdk/voiceid/ort.wasm.bundle.min-7y-hlRN8.js +3 -0
  27. package/dist/public/sdk/voiceid/prompt-CCrXTRRx.js +606 -0
  28. package/dist/public/sdk/voiceid/redimnet-b1.onnx +0 -0
  29. package/dist/public/sdk/voiceid/silero-vad.onnx +0 -0
  30. package/dist/public/sdk/voiceid/unlock-E7YHqBGT.js +1 -0
  31. package/dist/public/sdk/voiceid/voice-activity-worklet.js +21 -0
  32. package/dist/types/activation/addVoiceId.d.ts +11 -0
  33. package/dist/types/activation/manageEnrollment.d.ts +4 -0
  34. package/dist/types/activation/ownerConfirmation.d.ts +17 -0
  35. package/dist/types/browser/deviceStore.d.ts +19 -0
  36. package/dist/types/browser/enrollment.d.ts +37 -0
  37. package/dist/types/browser/enrollmentStore.d.ts +91 -0
  38. package/dist/types/browser/inference.d.ts +39 -0
  39. package/dist/types/browser/microphone.d.ts +61 -0
  40. package/dist/types/browser/model.d.ts +8 -0
  41. package/dist/types/browser/phrase.d.ts +35 -0
  42. package/dist/types/browser/phraseVocabulary.d.ts +3 -0
  43. package/dist/types/browser/progress.d.ts +2 -0
  44. package/dist/types/browser/ribbon.d.ts +63 -0
  45. package/dist/types/browser/verificationError.d.ts +6 -0
  46. package/dist/types/browser/voiceActivity.d.ts +15 -0
  47. package/dist/types/capture/approval.d.ts +36 -0
  48. package/dist/types/capture/bridge.d.ts +12 -0
  49. package/dist/types/capture/deviceBridge.d.ts +29 -0
  50. package/dist/types/capture/prompt.d.ts +41 -0
  51. package/dist/types/capture/surface.d.ts +27 -0
  52. package/dist/types/capture/unlockFrame.d.ts +13 -0
  53. package/dist/types/capture/visual.d.ts +24 -0
  54. package/dist/types/descriptor.d.ts +4 -0
  55. package/dist/types/host.d.ts +4 -0
  56. package/dist/types/index.d.ts +2 -0
  57. package/dist/types/react/VoiceAssistantCard.d.ts +37 -0
  58. package/dist/types/react.d.ts +5 -0
  59. package/dist/types/session/activation.d.ts +61 -0
  60. package/dist/types/session/activationStore.d.ts +21 -0
  61. package/dist/types/session/httpClient.d.ts +39 -0
  62. package/dist/types/session/unlock.d.ts +4 -0
  63. package/dist/types/session/unlockFromDevice.d.ts +18 -0
  64. package/package.json +66 -4
  65. package/src/README.md +270 -0
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -0,0 +1,54 @@
1
+ VoiceID speaker model: ReDimNet B1 (VoxCeleb2, large-margin fine-tuned)
2
+
3
+ Source: https://github.com/IDRnD/redimnet
4
+ Source revision: ce039a624cb99fe127702ceb94c6080090e5032f
5
+ Weights: https://huggingface.co/voice-is-cool/ReDimNet
6
+ Weights revision: 5180983b6895dafa0cd88aa88e8a07296df27834
7
+ Checkpoint: b1-vox2-ft_lm.pt
8
+ Checkpoint SHA-256: 6e634bbbeb0f6afd9bbbb0606da834f93e23e4869b3954177a5717acc20ea36c
9
+ ONNX SHA-256: e04dd7a6a1e23fc7b89e47682ea9d0a3946cf7bc59d07922c3db3efc52ae4269
10
+
11
+ Changes: exported to ONNX with complete 16 kHz mono waveform preprocessing.
12
+ The complex STFT is represented with ONNX STFT and equivalent power reduction.
13
+ The model emits 192-dimensional speaker embeddings. No retraining was performed.
14
+
15
+ MIT License
16
+
17
+ Copyright (c) 2024 ID R&D, Inc.
18
+
19
+ Permission is hereby granted, free of charge, to any person obtaining a copy
20
+ of this software and associated documentation files (the "Software"), to deal
21
+ in the Software without restriction, including without limitation the rights
22
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23
+ copies of the Software, and to permit persons to whom the Software is
24
+ furnished to do so, subject to the following conditions:
25
+
26
+ The above copyright notice and this permission notice shall be included in all
27
+ copies or substantial portions of the Software.
28
+
29
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35
+ SOFTWARE.
36
+
37
+ AuroraASR-1M spoken phrase model
38
+
39
+ Source: https://huggingface.co/AuroraAI-Research/AuroraASR-1M
40
+ Revision: cd307b54b4d666d6ad7dc982a7a58a96d6e7f942
41
+ Publisher: AuroraAI Research
42
+ License: Apache-2.0; see AURORA_LICENSE.txt.
43
+ ONNX SHA-256: 83ed6f3856458cd96d49a70d8c5175aeec18ba8c184e5367e089cd424eebefd6
44
+
45
+ Changes: exported the publisher's INT8-weight checkpoint to ONNX, with
46
+ full-waveform log-mel preprocessing. The complex STFT is represented by ONNX
47
+ STFT and power reduction. Constant folding is disabled to retain INT8 weights
48
+ in the downloaded file. Execution dequantizes weights to floating point.
49
+ A 16-phrase token vocabulary is generated from the publisher's SentencePiece
50
+ tokenizer. No retraining or user recordings are included.
51
+
52
+ Silero VAD v5.1.2 (MIT), snakers4/silero-vad, revision 6478567951ae5c9979ad7b234185b5515f4be7a1.
53
+ Model SHA-256: 2623a2953f6ff3d2c1e61740c6cdb7168133479b267dfef114a4a3cc5bdd788f
54
+ See SILERO_LICENSE.txt.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020-present Silero Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ import"./prompt-CCrXTRRx.js";import{a as e,i as t,r as n,t as r}from"./deviceBridge-wRAbqdap.js";import{a as i,d as a,i as o,o as s,s as c,t as l}from"./enrollment-DIRoCkx5.js";import{IndexedDBManager as u,WorkerDeferred as d,allocateWalletAuthMethodId as f,alphabetizeStringify as p,base64UrlDecode as m,buildMethodBoundEnvelopeOwnership as h,buildPasskeyCustodyEnvelopeRecord as g,buildVoiceIdEnvelopeFactor as _,buildWalletCustodySeedBinding as v,custodyEnvelopeBindingJsonV1 as y,fetchWithWalletHomeDiscovery as b,isVoiceIdSeedEnvelope as x,parseDigestB64u as S,parseEnvelopeRevision as C,parsePasskeyCustodyEnvelopeRecord as w,parsePasskeyEnvelopeId as T,parseResealedEnvelopeResult as E,parseVoiceIdDevicePublicKeyB64u as D,parseWalletAuthMethodId as O,parseWalletAuthMethodRecordV2 as k,parseWalletId as A,readUnlockedWalletEd25519ExportRootCapabilityV1 as j,rejectUnknownFields as M,requireRecord as N,secureRandomId as P,sha256DigestB64u as F,toError as I,walletCustodyCeremonyTransportFromWorkerContextV1 as L,walletSessionAuthorizations as R}from"../voiceid-host.js";async function z(e){let t=N(e,`pending VoiceID activation`);if(M(t,[`kind`,`walletId`,`walletAuthMethodId`,`devicePublicKeyB64u`,`deviceKeyId`,`custodyEnvelope`],`pending VoiceID activation`),t.kind!==`pending_voiceid_activation_v1`)throw Error(`Pending VoiceID activation kind is invalid.`);let n=A(t.walletId),r=O(t.walletAuthMethodId);if(!n.ok||!r.ok)throw Error(`Pending VoiceID activation identity is invalid.`);let i=D(t.devicePublicKeyB64u),a=S(t.deviceKeyId),o=w(t.custodyEnvelope);if(!x(o)||o.walletId!==n.value||o.ownership.walletAuthMethodId!==r.value||o.factor.deviceKeyId!==a||Number(o.envelopeRevision)!==1||await F(m(i))!==a)throw Error(`Pending VoiceID activation binding is invalid.`);return{kind:`pending_voiceid_activation_v1`,walletId:n.value,walletAuthMethodId:r.value,devicePublicKeyB64u:i,deviceKeyId:a,custodyEnvelope:o}}function B(e){throw Error(`Unhandled VoiceID activation plan: ${String(e)}`)}function V(e,t){let{capability:n}=e;if(n.walletId!==e.walletId||n.walletSessionId!==t.walletSessionId||n.expiresAtMs<=Date.now())throw Error(`VoiceID activation requires the unlocked owner seed and Wallet Session.`)}async function H(e,t){let n=_({deviceKeyId:t.deviceKeyId}),r=v(),i=h(e.walletAuthMethodId),a=C(1),o=y({walletId:e.walletId,envelopeId:e.envelopeId,factor:n,envelopeRevision:a,binding:r,ownership:i}),s=t.factorSecret32.slice(),c;try{c=E(await e.reseal({capability:e.capability,bindingJson:o,factorSecret:s.buffer}))}finally{s.byteLength>0&&s.fill(0)}if(await F(m(c.sealedCustodySecretB64u))!==c.ciphertextDigestB64u)throw Error(`VoiceID worker returned a mismatched ciphertext digest.`);let l=Date.now(),u=w(g({envelopeId:e.envelopeId,walletId:e.walletId,ownership:i,binding:r,factor:n,envelopeRevision:a,nonceB64u:c.nonceB64u,sealedCustodySecretB64u:c.sealedCustodySecretB64u,ciphertextDigestB64u:c.ciphertextDigestB64u,aadHashB64u:c.aadHashB64u,lifecycle:{state:`active`,activatedAtMs:l},createdAtMs:l,updatedAtMs:l}));if(!x(u))throw Error(`VoiceID worker produced an invalid seed envelope.`);return{kind:`pending_voiceid_activation_v1`,walletId:e.walletId,walletAuthMethodId:e.walletAuthMethodId,devicePublicKeyB64u:t.publicKeyB64u,deviceKeyId:t.deviceKeyId,custodyEnvelope:u}}async function U(e){let t=e.plan;switch(t.kind){case`new`:V(t,e.ownerCredential);break;case`resume`:break;default:return B(t)}let n=t.kind===`new`?t.walletId:t.pending.walletId,r=t.kind===`new`?t.walletAuthMethodId:t.pending.walletAuthMethodId,i=await e.capture({walletId:n,walletAuthMethodId:r,signal:e.signal,onCapture:e.onCapture,phrase:e.phrase}),a;try{switch(t.kind){case`new`:a=await H(t,i),await e.persistPending(a);break;case`resume`:if(t.pending.devicePublicKeyB64u!==i.publicKeyB64u||t.pending.deviceKeyId!==i.deviceKeyId)throw Error(`VoiceID activation retry found a different device key.`);a=t.pending;break;default:return B(t)}}finally{i.factorSecret32.fill(0)}if(e.signal.aborted)throw Error(`VoiceID activation was cancelled.`);let o=await e.http.activate({ownerCredential:e.ownerCredential,walletId:a.walletId,walletAuthMethodId:a.walletAuthMethodId,devicePublicKeyB64u:a.devicePublicKeyB64u,deviceKeyId:a.deviceKeyId,custodyEnvelope:a.custodyEnvelope,signal:e.signal});return await e.persistActive(o,a),{authMethod:o,pending:a}}const W=`voiceid-activation-v1:`;function G(e,t){return`${W}${encodeURIComponent(e)}:${encodeURIComponent(t)}`}function K(e){return`${W}${encodeURIComponent(e)}:`}function q(e,t){return p(e)===p(t)}async function J(e){if(e==null)return null;let t=N(e,`stored VoiceID activation`);switch(t.kind){case`pending`:return M(t,[`kind`,`pending`],`stored VoiceID activation`),{kind:`pending`,pending:await z(t.pending)};case`active`:{M(t,[`kind`,`pending`,`authMethod`],`stored VoiceID activation`);let e=await z(t.pending),n=k(t.authMethod);if(!n||n.kind!==`voiceid`||n.status!==`active`||n.walletId!==e.walletId||n.walletAuthMethodId!==e.walletAuthMethodId||n.deviceKeyId!==e.deviceKeyId||n.devicePublicKeyB64u!==e.devicePublicKeyB64u)throw Error(`Stored VoiceID activation method is invalid.`);return{kind:`active`,pending:e,authMethod:n}}default:throw Error(`Stored VoiceID activation lifecycle is invalid.`)}}var Y=class{constructor(e){this.storage=e}async persistPending(e){let t=G(e.walletId,e.walletAuthMethodId),n=await J(await this.storage.getAppState(t));if(n){if(n.kind===`pending`&&q(n.pending,e))return;throw Error(`A different VoiceID activation already owns this method ID.`)}await this.storage.setAppState(t,{kind:`pending`,pending:e})}async persistActive(e,t){let n=G(t.walletId,t.walletAuthMethodId),r=await J(await this.storage.getAppState(n));if(!r||!q(r.pending,t))throw Error(`VoiceID activation has no matching pending record.`);if(e.walletId!==t.walletId||e.walletAuthMethodId!==t.walletAuthMethodId||e.deviceKeyId!==t.deviceKeyId||e.devicePublicKeyB64u!==t.devicePublicKeyB64u)throw Error(`VoiceID server method does not match pending activation.`);await this.storage.upsertWalletAuthMethodV2(e),await this.storage.setAppState(n,{kind:`active`,pending:t,authMethod:e})}async readPending(e,t){let n=await J(await this.storage.getAppState(G(e,t)));if(!n||n.kind===`active`)return null;if(n.pending.walletId!==e||n.pending.walletAuthMethodId!==t)throw Error(`Stored VoiceID activation key does not match its record.`);return n.pending}async listPending(e){let t=await this.storage.listAppStateEntriesByPrefix(K(e)),n=[];for(let r of t){let t=await J(r.value);if(t){if(t.pending.walletId!==e||G(e,t.pending.walletAuthMethodId)!==r.key)throw Error(`Stored VoiceID activation key does not match its record.`);t.kind===`pending`&&n.push(t.pending)}}return n}};const X=`http://www.w3.org/2000/svg`;async function Z(e,t,n){let r=document.querySelector(`.seams-voiceid-activation-surface`);if(!(r instanceof HTMLElement))throw Error(`Open VoiceID management in the Wallet.`);let i=new Q(r,e,t,n);try{await i.result}finally{i.dispose()}}var Q=class{completion=new d;result=this.completion.promise;element=document.createElement(`div`);enrollment=document.createElement(`div`);enrollmentValue=document.createElement(`span`);startOver=document.createElement(`p`);status=document.createElement(`p`);actions;busy=!1;closed=!1;constructor(e,t,n,r){this.parent=e,this.context=t,this.scope=n,this.signal=r,this.element.className=`seams-voiceid-prompt seams-voiceid-management`;let i=document.createElement(`div`);i.className=`seams-voiceid-management-header`;let a=document.createElement(`button`);a.type=`button`,a.className=`seams-voiceid-management-back`,a.setAttribute(`aria-label`,`Back`),a.append($(`M15 6l-6 6 6 6`,20)),a.addEventListener(`click`,this.cancel);let o=document.createElement(`h2`);o.textContent=`Manage voice`,i.append(a,o);let s=document.createElement(`p`);s.className=`seams-voiceid-management-intro`,s.textContent=`Voice unlock on this device. Each change asks for your passkey.`,this.element.append(i,s,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(),a.focus()}enrollmentRow(){this.enrollment.className=`seams-voiceid-management-enrollment`;let e=document.createElement(`span`);e.textContent=`Enrollment`,this.enrollmentValue.className=`seams-voiceid-management-value`;let t=document.createElement(`span`);return t.className=`seams-voiceid-management-summary`,t.append(this.enrollmentValue),this.enrollment.append(e,t),this.enrollment}resetAction(){let e=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=document.createElement(`span`);return t.className=`seams-voiceid-management-enrollment-detail`,this.enrollment.querySelector(`.seams-voiceid-management-summary`)?.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=document.createElement(`button`);r.type=`button`,r.className=`seams-voiceid-management-action`;let i=document.createElement(`span`),a=document.createElement(`span`);a.className=`seams-voiceid-management-action-heading`;let o=document.createElement(`span`);o.id=`seams-voiceid-management-${e}-title`,o.textContent=t,a.append(o);let s=[];if(n){let t=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=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,$(`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 e=await s(this.scope),t=e?null:await i();if(this.closed)return;this.render(e,t!==null,!0)}catch(e){this.completion.reject(I(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 r=await t(this.scope,`enrolled`),a=await s(this.scope),c=a?{kind:`present`,enrollment:a}:{kind:`missing`};if(e===`improve`&&c.kind===`missing`)throw Error(`Record or import your original voice first.`);let u=e===`import`?await i():null;if(e===`import`&&(!u||c.kind!==`missing`))throw Error(`The previous enrollment is unavailable.`);let d=await n.request(this.context,this.scope,r,c,e,this.signal);switch(this.signal.throwIfAborted(),e){case`improve`:if(c.kind!==`present`)throw Error(`Original voice enrollment is unavailable.`);await l({kind:`improve`,scope:this.scope,guard:r,snapshot:c,confirmation:d},this.signal);break;case`replace`:await l({kind:`replace`,scope:this.scope,guard:r,snapshot:c,confirmation:d},this.signal);break;case`reset`:await o(this.scope,r,c,{kind:`reset`,confirmation:d},this.signal);break;case`import`:if(!u)throw Error(`Previous voice enrollment is unavailable.`);await o(this.scope,r,c,{kind:`import`,baseline:u,confirmation:d},this.signal);break}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 $(e,t){let n=document.createElementNS(X,`svg`);n.setAttribute(`viewBox`,`0 0 24 24`),n.setAttribute(`width`,String(t)),n.setAttribute(`height`,String(t)),n.setAttribute(`aria-hidden`,`true`);let r=document.createElementNS(X,`path`);return r.setAttribute(`d`,e),r.setAttribute(`fill`,`none`),r.setAttribute(`stroke`,`currentColor`),r.setAttribute(`stroke-width`,`1.75`),r.setAttribute(`stroke-linecap`,`round`),r.setAttribute(`stroke-linejoin`,`round`),n.append(r),n}async function ee(e,t){return await e.requestOperation({kind:`walletCustodyCeremony`,request:{type:`resealWalletCustodyFromUnlockedCapability`,payload:{capability:t.capability,replacementEnvelopeBindingJson:t.bindingJson,replacementFactorSecret:t.factorSecret},transfer:[t.factorSecret]}})}async function te(t,n){let r=await u.resolveSelectedWalletAuthority(n);if(r.kind!==`resolved`||r.selection.lockState!==`unlocked`||r.selection.walletId!==n||r.authMethod.status!==`active`||r.authMethod.walletId!==n||r.authMethod.walletAuthorityId!==r.authority.authorityId||r.authority.state!==`active`||r.authority.walletId!==n)throw Error(`Unlock this wallet with a passkey or Email OTP before activating VoiceID.`);let i=await R.readExactWithOperationCredential({walletId:n,authorityId:r.authority.authorityId,authMethodId:r.authMethod.walletAuthMethodId});if(i.kind!==`found`||i.record.walletId!==n||i.record.authMethodId!==r.authMethod.walletAuthMethodId||i.record.authorityId!==r.authority.authorityId||i.record.expiresAtMs<=Date.now())throw Error(`VoiceID activation requires an active owner Wallet Session.`);let o=await u.listWalletAuthMethodsV2ForWallet(n);for(let e of o){if(e.kind!==`voiceid`||e.status!==`active`||e.walletAuthorityId!==r.authority.authorityId)continue;let i=await a(n,e.walletAuthMethodId);if(i&&i.deviceKeyId===e.deviceKeyId)return{kind:`enroll_existing`,walletId:n,walletAuthMethodId:e.walletAuthMethodId,context:t}}if(r.authMethod.kind===`voiceid`)throw Error(`An existing local VoiceID enrollment is required for management.`);let s=new Y(u),c=await s.listPending(n);if(c.length>1)throw Error(`More than one VoiceID activation is pending for this wallet.`);let l;if(c.length===1)l={kind:`resume`,pending:c[0]};else{let e=j(n);if(!e||e.walletSessionId!==i.operationCredential.walletSessionId)throw Error(`Unlock the wallet again to make its custody seed available for VoiceID.`);let r=T(P(`wallet-custody-envelope`,24));if(!r.ok)throw Error(`VoiceID envelope ID generation failed.`);let a=L(t.signingEngine.getSignerWorkerContext());l={kind:`new`,walletId:n,walletAuthMethodId:f(crypto.randomUUID()),envelopeId:r.value,capability:e,reseal:ee.bind(null,a)}}return{kind:`activate`,ownerCredential:i.operationCredential,plan:l,http:new e(t.configs.network.relayer.url,location.origin,b),store:s}}async function ne(e,t){t.throwIfAborted();let{context:n,walletId:r}=e,i=await te(n,r);return t.throwIfAborted(),i.kind===`enroll_existing`?{kind:`management`,action:re.bind(null,i)}:{kind:`recording`,action:ie.bind(null,i),expiresAtMs:null}}async function re(e,t){let n=await c(e.walletId,e.walletAuthMethodId);return await Z(e.context,n,t),t.throwIfAborted(),{kind:`activated`,walletId:e.walletId,walletAuthMethodId:e.walletAuthMethodId}}async function ie(e,t,n,i){let a=await U({plan:e.plan,ownerCredential:e.ownerCredential,http:e.http,signal:t,onCapture:n,phrase:i,capture:r,persistPending:e.store.persistPending.bind(e.store),persistActive:e.store.persistActive.bind(e.store)});return{kind:`activated`,walletId:a.authMethod.walletId,walletAuthMethodId:a.authMethod.walletAuthMethodId}}export{ne as prepareActivationSurface};
@@ -0,0 +1 @@
1
+ import{c as e,f as t,g as n,t as r,u as i}from"./prompt-CCrXTRRx.js";import{f as a,n as o,s}from"./enrollment-DIRoCkx5.js";import{ActionType as c,IndexedDBManager as l,TransactionReviewError as u,isPlainObject as d,parseTransactionReviewWire as f,resolveNearNetwork as p,walletForHostRequest as m,walletHostExecutionFingerprint as h}from"../voiceid-host.js";function g(e,t){return e.attemptId===t.attemptId&&e.operationHash===t.operationHash&&e.expiresAtMs===t.expiresAtMs}async function _(t,r,a,s,c,l){let u=Math.min(r.expiresAtMs,Date.now()+a);if(s.aborted||u<=Date.now())throw Error(`VoiceID review expired or was cancelled.`);let d=await o({kind:`active`,scope:t},s,c,l);if(s.aborted||u<=Date.now())throw Error(`VoiceID review expired or was cancelled.`);switch(d.kind){case`matched`:return{kind:`approved`};case`insufficient_audio`:return{kind:`retry`,message:e(d.quality)};case`mismatch`:return{kind:`retry`,message:new n(d.quality).message};case`phrase_mismatch`:return{kind:`retry`,message:new i().message};default:return v(d)}}function v(e){throw Error(`Unexpected voice result: ${String(e)}`)}function y(e){throw Error(`Unexpected voice outcome: ${String(e)}`)}function b(e){if(!(!d(e)&&!Array.isArray(e))){for(let t of Object.values(e))b(t);Object.freeze(e)}}async function x(e,t){switch(e.type){case`PM_SIGN_TX_WITH_ACTIONS`:case`PM_SIGN_DELEGATE_ACTION`:case`PM_SIGN_NEP413`:throw T();case`PM_SIGN_TEMPO`:{let n=e.payload;if(!n||n.operationKind!==`evm_transaction`)throw T();let{tx:r}=n.request,i=n.chainTarget;if(!t.config.network.chains.some(S)||i.kind!==`evm`||i.namespace!==`eip155`||i.networkSlug!==`arc-testnet`||i.chainId!==5042002||n.request.chain!==`evm`||n.request.kind!==`eip1559`||n.request.senderSignatureAlgorithm!==`secp256k1`||r.chainId!==i.chainId||typeof r.to!=`string`||!/^0x[0-9a-fA-F]{40}$/.test(r.to)||r.data!==void 0&&r.data!==`0x`||r.accessList!==void 0&&r.accessList.length!==0||r.abi!==void 0)throw T();return await w(e,t)}case`PM_SIGN_AND_SEND_TX`:{if(p(t.config.network.chains)!==`testnet`)throw new u(`review_unsupported_mode`,`This VoiceID prototype requires NEAR testnet.`);let n=e.payload;if(!n||n.transaction.actions.length!==1||n.transaction.actions[0].type!==c.Transfer||!(`transactionReview`in e))throw T();return await w(e,t)}default:return{kind:`disabled`}}}function S(e){return e.network===`arc-testnet`&&e.chainId===5042002}function C(e,t){return typeof t==`bigint`?{bigint:t.toString()}:t}async function w(e,t){let n=f(e.transactionReview);if(n.validity.kind!==`expires_at`)throw new u(`review_invalid_input`,`VoiceID requires a review deadline.`);b(e);let r=new TextEncoder().encode(JSON.stringify({domain:`seams-voiceid-operation-v1`,origin:location.origin,executionFingerprint:h(t.config),request:e},C)),i=await crypto.subtle.digest(`SHA-256`,r),a=``;for(let e of new Uint8Array(i))a+=e.toString(16).padStart(2,`0`);let o=m(e,null);if(!o)throw Error(`VoiceID review requires a wallet identity.`);return{kind:`required`,approval:E.forReview(n,a,o)}}function T(){return new u(`review_unsupported_mode`,`VoiceID requires a reviewed NEAR or Arc testnet transfer.`)}var E=class e{phrase=t(null);prompt;surface;get messages(){return{confirm:`Confirm with VoiceID`,approved:`Voice approved this operation.`}}state={kind:`pending`};constructor(e,t,n){this.reviewExpiresAtMs=e,this.operationHash=t,this.walletId=n,this.prompt=new r(document,`Approve transfer with VoiceID`,this.phrase,`segments`),this.prompt.record.hidden=!0,this.prompt.cancel.hidden=!0,this.surface=this.prompt.element}static forReview(t,n,r){if(t.validity.kind!==`expires_at`||!/^[0-9a-f]{64}$/.test(n))throw new u(`review_invalid_input`,`VoiceID requires a bounded operation.`);return new e(t.validity.atMs,n,r)}async approve(e){if(this.state.kind===`approved`){if(e.aborted||performance.now()>=this.state.deadline||Date.now()>=this.state.binding.expiresAtMs)throw Error(`Voice approval expired or closed.`);return{kind:`approved`}}if(this.state.kind!==`pending`)throw Error(`Voice approval already started.`);if(!navigator.userActivation.isActive||document.visibilityState!==`visible`||!document.hasFocus())throw Error(`Open the Wallet review and select Confirm to start voice capture.`);this.state={kind:`preparing`},this.prompt.status.textContent=`Loading VoiceID…`;try{let n=await l.resolveSelectedWalletAuthority(this.walletId);if(n.kind!==`resolved`||n.authMethod.kind!==`voiceid`||n.selection.lockState!==`unlocked`)throw Error(`Unlock this wallet with VoiceID before voice approval.`);let r=await s(this.walletId,n.authMethod.walletAuthMethodId);await a(this.prompt.progress),this.prompt.progress.replaceChildren();let i=this.beginAttempt(e);for(;;){let{binding:n,deadline:a,remaining:o}=i,s=await _(r,n,o,e,this.prompt.capture,this.phrase);if(this.assertListening(n),e.aborted||performance.now()>=a||Date.now()>=n.expiresAtMs)throw Error(`Voice approval expired or closed.`);switch(s.kind){case`approved`:return this.state={kind:`approved`,binding:n,deadline:a,signal:e},s;case`retry`:this.phrase=t(this.phrase),this.prompt.setPhrase(this.phrase),this.prompt.record.textContent=`Try again`,this.prompt.ready(s.message),await this.waitForRetry(e),i=this.beginAttempt(e);break;default:return y(s)}}}catch(e){throw this.state={kind:`closed`},e}}beginAttempt(e){let t=Math.min(25e3,this.reviewExpiresAtMs-Date.now());if(t<250||e.aborted)throw Error(`This voice review has expired or closed.`);let n=Object.freeze({attemptId:crypto.randomUUID(),operationHash:this.operationHash,expiresAtMs:Date.now()+t}),r=performance.now()+t;return this.prompt.record.hidden=!0,this.prompt.status.textContent=`Opening microphone…`,this.state={kind:`listening`,binding:n,deadline:r,signal:e},{binding:n,deadline:r,remaining:t}}waitForRetry(e){return new Promise((t,n)=>{let r=this.prompt.record,i=i=>{clearTimeout(s),r.removeEventListener(`click`,a),e.removeEventListener(`abort`,o),i?t():n(Error(`This voice review has expired or closed.`))},a=i.bind(null,!0),o=i.bind(null,!1),s=setTimeout(o,Math.max(0,this.reviewExpiresAtMs-Date.now()));r.addEventListener(`click`,a),e.addEventListener(`abort`,o),e.aborted&&o(),r.focus()})}consume(){let e=this.state;if(this.state={kind:`consumed`},e.kind!==`approved`||e.signal.aborted||performance.now()>=e.deadline||Date.now()>=e.binding.expiresAtMs)throw Error(`A current voice approval is required before signing.`)}assertListening(e){if(this.state.kind!==`listening`||!g(e,this.state.binding))throw Error(`This voice attempt has closed.`)}};export{x as voiceIdPolicyForRequest};
@@ -0,0 +1 @@
1
+ import{g as e,i as t,o as n,s as r,u as i}from"./prompt-CCrXTRRx.js";import{c as a,d as o,l as s,n as c,o as l,r as u,s as d,t as f,u as p}from"./enrollment-DIRoCkx5.js";import{IndexedDBManager as m,availabilityKey as h,base64UrlDecode as g,base64UrlEncode as _,buildRelayerJsonPostRequestInit as v,buildWalletSessionAuthorizationHeaders as y,buildWebauthnP256SignatureWasm as b,createRelayerExactWalletSessionStatusPort as x,decodeCoseP256PublicKeyWasm as S,fetchWithWalletHomeDiscovery as C,isVoiceIdSeedEnvelope as w,joinNormalizedUrl as T,mpcMaterialActivationRefsEqual as E,normalizeRelayerBaseUrl as D,parseActiveWalletSessionV1 as O,parseEd25519YaoRecoveryCapabilityV1 as k,parseLinkedDeviceListResultV1 as ee,parsePasskeyCustodyEnvelopeRecord as te,parseStoredAuthMethodAvailability as ne,parseVoiceIdDeviceAssertion as re,parseVoiceIdWalletSessionChallenge as ie,parseWalletAuthMethodRecordV2 as ae,parseWalletSessionOperationCredentialV1 as oe,rejectUnknownFields as A,requireRecord as j,sha256DigestB64u as M,voiceIdWalletSessionChallengeBytes as N,walletSessionAuthorizations as P}from"../voiceid-host.js";async function F(e){let t;try{t=await e.json()}catch{throw Error(`VoiceID server returned an invalid response.`)}let n=j(t,`VoiceID server response`);if(!e.ok||n.ok!==!0)throw Error(`VoiceID server request failed (HTTP ${e.status}).`);return n}var I=class{walletOrigin;constructor(e,t,n){this.relayerUrl=e,this.send=n;let r=new URL(t);if(r.origin!==t||r.protocol!==`https:`&&r.protocol!==`http:`)throw Error(`VoiceID Wallet origin is invalid.`);this.walletOrigin=t}async activate(e){if(e.custodyEnvelope.walletId!==e.walletId||e.custodyEnvelope.ownership.walletAuthMethodId!==e.walletAuthMethodId||e.custodyEnvelope.factor.deviceKeyId!==e.deviceKeyId)throw Error(`VoiceID activation envelope does not match the device method.`);let t=new Request(T(this.relayerUrl,`/wallet/voiceid/activate`),{...v({body:{targetWalletAuthMethodId:e.walletAuthMethodId,devicePublicKeyB64u:e.devicePublicKeyB64u,custodyEnvelope:e.custodyEnvelope},headers:y(e.ownerCredential)}),signal:e.signal}),n=await F(await this.send(t));A(n,[`ok`,`authMethod`],`VoiceID activation response`);let r=ae(n.authMethod);if(!r||r.kind!==`voiceid`||r.status!==`active`||r.walletId!==e.walletId||r.walletAuthMethodId!==e.walletAuthMethodId||r.devicePublicKeyB64u!==e.devicePublicKeyB64u||r.deviceKeyId!==e.deviceKeyId)throw Error(`VoiceID server activated a different device method.`);return r}async challenge(e){let t=new Request(T(this.relayerUrl,`/wallet/voiceid/challenge`),{...v({body:{walletId:e.walletId,walletAuthMethodId:e.walletAuthMethodId}}),signal:e.signal}),n=await F(await this.send(t));A(n,[`ok`,`challenge`],`VoiceID challenge response`);let r=ie(n.challenge);if(r.walletId!==e.walletId||r.walletAuthMethodId!==e.walletAuthMethodId||r.requestOrigin!==this.walletOrigin||r.audience!==this.walletOrigin)throw Error(`VoiceID server challenge belongs to a different Wallet method or origin.`);return r}async verify(e){if(e.assertion.challenge.requestOrigin!==this.walletOrigin||e.assertion.challenge.audience!==this.walletOrigin)throw Error(`VoiceID assertion belongs to a different Wallet origin.`);let t=new Request(T(this.relayerUrl,`/wallet/voiceid/verify`),{...v({body:{assertion:e.assertion}}),signal:e.signal}),n=await F(await this.send(t));A(n,[`ok`,`walletSession`,`operationCredential`,`custodyEnvelope`,`near`],`VoiceID verification response`);let r=O(n.walletSession),i=oe(n.operationCredential),a=te(n.custodyEnvelope),o=e.assertion.challenge;if(!w(a)||r.walletId!==o.walletId||r.authMethodId!==o.walletAuthMethodId||r.authorityId!==o.walletAuthorityId||a.walletId!==o.walletId||a.ownership.walletAuthMethodId!==o.walletAuthMethodId||a.factor.deviceKeyId!==o.deviceKeyId)throw Error(`VoiceID server returned a different Wallet Session or custody envelope.`);let s=L(n.near);if(s.kind===`ready`&&(s.capability.applicationBinding.wallet_id!==r.walletId||!r.capabilitySubjects.some(R.bind(null,s.capability.materialActivation))))throw Error(`VoiceID NEAR capability belongs to another Wallet Session.`);return{walletSession:r,operationCredential:i,custodyEnvelope:a,near:s}}};function L(e){let t=j(e,`NEAR installation`);switch(t.kind){case`unavailable`:return A(t,[`kind`],`NEAR installation`),{kind:`unavailable`};case`ready`:if(A(t,[`kind`,`capability`,`remainingUses`],`NEAR installation`),typeof t.remainingUses!=`number`||!Number.isSafeInteger(t.remainingUses)||t.remainingUses<1)throw Error(`NEAR session budget is invalid.`);return{kind:`ready`,capability:k(t.capability),remainingUses:t.remainingUses};default:throw Error(`NEAR installation state is invalid.`)}}function R(e,t){return t.kind===`sign`&&t.keyFamily===`ed25519`&&E(e,t.materialActivation)}function z(e,t,n){if(t<24)return[t,1];let r=e.byteLength-n-1,i=new DataView(e.buffer,n+1),a,o=0;switch(t){case 24:r>0&&(a=i.getUint8(0),o=2);break;case 25:r>1&&(a=i.getUint16(0,!1),o=3);break;case 26:r>3&&(a=i.getUint32(0,!1),o=5);break;case 27:if(r>7){let e=i.getBigUint64(0,!1);if(e>=24n&&e<=2**53-1)return[Number(e),9]}break}if(a&&a>=24)return[a,o];throw Error(`Length not supported or not well formed`)}var B=class{constructor(e,t){Object.defineProperty(this,`tagId`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`tagValue`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.tagId=e,this.tagValue=t}get tag(){return this.tagId}get value(){return this.tagValue}};function V(e,t,n){return z(e,t,n)}function H(e,t,n){let[r,i]=V(e,t,n);return[-r-1,i]}function U(e,t,n){let[r,i]=z(e,t,n),a=n+i;return[new Uint8Array(e.buffer.slice(a,a+r)),i+r]}const W=new TextDecoder;function G(e,t,n){let[r,i]=U(e,t,n);return[W.decode(r),i]}function se(e,t,n){if(t===0)return[[],1];let[r,i]=z(e,t,n),a=i,o=[];for(let t=0;t<r;t++){if(e.byteLength-n-a<=0)throw Error(`array is not supported or well formed`);let[t,r]=q(e,n+a);o.push(t),a+=r}return[o,a]}const K=`Map is not supported or well formed`;function ce(e,t,n){if(t===0)return[new Map,1];let[r,i]=z(e,t,n),a=i,o=new Map;for(let t=0;t<r;t++){let t=e.byteLength-n-a;if(t<=0)throw Error(K);let[r,i]=q(e,n+a);if(a+=i,t-=i,t<=0||typeof r!=`string`&&typeof r!=`number`||o.has(r))throw Error(K);let[s,c]=q(e,n+a);a+=c,o.set(r,s)}return[o,a]}function le(e,t){if(t+3>e.byteLength)throw Error(`CBOR stream ended before end of Float 16`);let n=e.getUint16(t+1,!1);if(n==31744)return[1/0,3];if(n==32256)return[NaN,3];if(n==64512)return[-1/0,3];throw Error(`Float16 data is unsupported`)}function ue(e,t){if(t+5>e.byteLength)throw Error(`CBOR stream ended before end of Float 32`);return[e.getFloat32(t+1,!1),5]}function de(e,t){if(t+9>e.byteLength)throw Error(`CBOR stream ended before end of Float 64`);return[e.getFloat64(t+1,!1),9]}function fe(e,t,n){let[r,i]=z(e,t,n),[a,o]=q(e,n+i);return[new B(r,a),i+o]}function q(e,t){if(t>=e.byteLength)throw Error(`CBOR stream ended before tag value`);let n=e.getUint8(t),r=n>>5,i=n&31;switch(r){case 0:return V(e,i,t);case 1:return H(e,i,t);case 2:return U(e,i,t);case 3:return G(e,i,t);case 4:return se(e,i,t);case 5:return ce(e,i,t);case 6:return fe(e,i,t);case 7:switch(i){case 20:return[!1,1];case 21:return[!0,1];case 22:return[null,1];case 23:return[void 0,1];case 25:return le(e,t);case 26:return ue(e,t);case 27:return de(e,t)}}throw Error(`Unsupported or not well formed at ${t}`)}new TextEncoder;function pe(e,t){if(e.byteLength===0||e.byteLength<=t||t<0)throw Error(`No data`);return e instanceof Uint8Array?q(new DataView(e.buffer),t):e instanceof ArrayBuffer?q(new DataView(e),t):q(e,t)}function me(e){let[t,n]=pe(e,0);if(n!==e.byteLength)throw Error(`Data was decoded, but the whole stream was not processed ${n} != ${e.byteLength}`);return t}async function J(e,t){let n=await m.resolveSelectedWalletAuthority(e.walletId);if(n.kind!==`resolved`||n.selection.lockState!==`unlocked`||t===`activating`&&n.authMethod.kind===`voiceid`||n.authMethod.status!==`active`||n.authority.authorityId!==e.authorityId)throw Error(`Unlock this wallet with an owner method before managing VoiceID.`);let r=await P.readExactWithOperationCredential({walletId:e.walletId,authorityId:e.authorityId,authMethodId:n.authMethod.walletAuthMethodId});if(r.kind!==`found`||r.record.expiresAtMs<=Date.now())throw Error(`Unlock this wallet again before managing VoiceID.`);let i=ne(await m.getAppState(h(e.walletId,e.walletAuthMethodId))),a;if(t===`activating`)a={target:t,sessionMethodId:n.authMethod.walletAuthMethodId,walletSessionId:r.operationCredential.walletSessionId,lockGeneration:n.selection.lockGeneration,expiresAtMs:Math.min(r.record.expiresAtMs,Date.now()+5*6e4),availabilityRevision:i.revision};else{let o=(await m.listWalletAuthMethodsV2ForWallet(e.walletId)).find(Y.bind(null,e));if(!o)throw Error(`Add a passkey to this authority before changing your voice enrollment.`);a={target:t,sessionMethodId:n.authMethod.walletAuthMethodId,confirmationMethodId:o.walletAuthMethodId,walletSessionId:r.operationCredential.walletSessionId,lockGeneration:n.selection.lockGeneration,expiresAtMs:Math.min(r.record.expiresAtMs,Date.now()+5*6e4),availabilityRevision:i.revision}}return await u(e,a),a}function Y(e,t){return t.kind===`passkey`&&t.status===`active`&&t.walletId===e.walletId&&t.walletAuthorityId===e.authorityId}function he(e,t,n,r){return r.walletId===e.walletId&&r.walletAuthorityId===e.authorityId&&r.credential.kind===`passkey`&&r.credential.walletAuthMethodId===t.confirmationMethodId&&r.credential.credentialIdB64u===n}function X(e,t,n,r){return JSON.stringify([`seams-voiceid-enrollment-change-v1`,location.origin,e.walletId,e.authorityId,e.walletAuthMethodId,e.deviceKeyId,t.sessionMethodId,t.confirmationMethodId,t.walletSessionId,t.lockGeneration,t.availabilityRevision,t.expiresAtMs,r,n.kind===`present`?n.enrollment.generation:null,n.kind===`present`?n.enrollment.revision:null])}var ge=class e{consumed=!1;constructor(e,t,n){this.binding=e,this.expiresAtMs=t,this.assertCurrentOwner=n}static async request(t,n,r,i,a,o){await u(n,r);let s=_e.bind(null,t.configs.network.relayer.url,n,r);await s(o);let c=await m.getWalletAuthMethodV2(r.confirmationMethodId);if(!c||c.kind!==`passkey`||c.status!==`active`||c.walletId!==n.walletId||c.walletAuthorityId!==n.authorityId||c.rpId!==t.signingEngine.getRpId())throw Error(`The confirming passkey is unavailable for this wallet.`);let l=X(n,r,i,a),d=await M(new TextEncoder().encode(JSON.stringify({binding:l,nonce:crypto.randomUUID(),expiresAtMs:r.expiresAtMs})));o.throwIfAborted();let f=await navigator.credentials.get({publicKey:{challenge:g(d),rpId:c.rpId,allowCredentials:[{type:`public-key`,id:g(c.credentialIdB64u)}],userVerification:`required`,timeout:Math.min(6e4,r.expiresAtMs-Date.now())},signal:o});if(!(f instanceof PublicKeyCredential)||!(f.response instanceof AuthenticatorAssertionResponse)||_(new Uint8Array(f.rawId))!==c.credentialIdB64u)throw Error(`The passkey did not confirm this wallet.`);let p=f.response,h=new Uint8Array(p.clientDataJSON),v=j(JSON.parse(new TextDecoder().decode(h)),`Passkey client data`);if(v.type!==`webauthn.get`||v.challenge!==d||v.origin!==location.origin)throw Error(`The passkey confirmation belongs to another operation.`);let y=new Uint8Array(p.authenticatorData),b=new Uint8Array(await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(c.rpId)));if(y.length<37||(y[32]&5)!=5||_(y.slice(0,32))!==_(b))throw Error(`Passkey user verification is required for this Wallet origin.`);if(!await Q({cosePublicKey:g(c.credentialPublicKeyB64u),challenge:g(d),authenticatorData:y,clientBytes:h,signature:new Uint8Array(p.signature),workerCtx:t.signingEngine.getSignerWorkerContext()}))throw Error(`Passkey confirmation signature is invalid.`);return o.throwIfAborted(),await u(n,r),new e(l,r.expiresAtMs,s)}async consume(e,t,n,r,i){if(this.consumed||this.expiresAtMs<=Date.now()||this.binding!==X(e,t,n,r))throw Error(`Passkey confirmation expired or was already used. Start again.`);if(this.consumed=!0,await this.assertCurrentOwner(i),i.throwIfAborted(),this.expiresAtMs<=Date.now())throw Error(`Passkey confirmation expired. Start again.`)}};async function _e(e,t,n,r){let i=await P.readExactWithOperationCredential({walletId:t.walletId,authorityId:t.authorityId,authMethodId:n.sessionMethodId});if(i.kind!==`found`||i.operationCredential.walletSessionId!==n.walletSessionId)throw Error(`The owner session changed. Unlock this wallet and try again.`);r.throwIfAborted();let a=await x({relayerUrl:e,operationCredential:i.operationCredential,fetchImpl:Z.bind(null,r)}).read({walletSessionId:n.walletSessionId,quotaId:i.record.quotaId});if(a.status!==`active`&&a.status!==`exhausted`||a.authorization.walletId!==t.walletId||a.authorization.authorityId!==t.authorityId||a.authorization.authMethodId!==n.sessionMethodId)throw Error(`The owner session is unavailable. Unlock this wallet and try again.`);let o=await m.getWalletAuthMethodV2(n.confirmationMethodId);if(!o||o.kind!==`passkey`||!Y(t,o))throw Error(`The confirming passkey is unavailable.`);let s=new URLSearchParams({walletId:t.walletId,limit:`50`,cursor:``}),c=await Z(r,`${D(e)}/wallet/device-linking/v1/devices?${s}`,{headers:y(i.operationCredential)});if(!c.ok)throw Error(`Could not verify the confirming passkey with the wallet service.`);let{ok:l,...u}=j(await c.json(),`Wallet method inventory`);if(l!==!0)throw Error(`Could not verify the confirming passkey with the wallet service.`);if(!ee(u).ownerDevices.some(he.bind(null,t,n,o.credentialIdB64u)))throw Error(`The confirming passkey was removed or belongs to another authority.`);r.throwIfAborted()}function Z(e,t,n){return C(new Request(t,{...n,signal:AbortSignal.any([e,AbortSignal.timeout(15e3)])}))}async function Q(e){let t=me(e.cosePublicKey);if(!(t instanceof Map))throw Error(`Passkey public key is invalid.`);let n=new Uint8Array(await crypto.subtle.digest(`SHA-256`,new Uint8Array(e.clientBytes))),r=new Uint8Array(e.authenticatorData.length+n.length);if(r.set(e.authenticatorData),r.set(n,e.authenticatorData.length),t.get(1)===3&&t.get(3)===-257){let n=t.get(-1),i=t.get(-2);if(!(n instanceof Uint8Array)||!(i instanceof Uint8Array))throw Error(`RSA passkey public key is invalid.`);let a=await crypto.subtle.importKey(`jwk`,{kty:`RSA`,n:_(n),e:_(i)},{name:`RSASSA-PKCS1-v1_5`,hash:`SHA-256`},!1,[`verify`]);return crypto.subtle.verify(`RSASSA-PKCS1-v1_5`,a,new Uint8Array(e.signature),r)}if(t.get(1)!==2||t.get(3)!==-7)throw Error(`This passkey type cannot confirm VoiceID changes.`);let i=await S({cosePublicKey:e.cosePublicKey,workerCtx:e.workerCtx}),a=(await b({challenge32:e.challenge,authenticatorData:e.authenticatorData,clientDataJSON:e.clientBytes,signatureDer:e.signature,pubKeyX32:i.pubKeyX32,pubKeyY32:i.pubKeyY32,workerCtx:e.workerCtx})).slice(-128,-64),o=await crypto.subtle.importKey(`jwk`,{kty:`EC`,crv:`P-256`,x:_(i.pubKeyX32),y:_(i.pubKeyY32)},{name:`ECDSA`,namedCurve:`P-256`},!1,[`verify`]);return crypto.subtle.verify({name:`ECDSA`,hash:`SHA-256`},o,a,r)}async function ve(e){r();let t=await s(e.walletId,e.walletAuthMethodId),n=await m.resolveSelectedWalletAuthority(e.walletId);if(n.kind!==`resolved`)throw Error(`Select the owner wallet before enrolling VoiceID.`);let i=a(t,n.authority.authorityId);await l(i)?await $({kind:`activation`,scope:i,owner:await J(i,`activating`)},e.signal,e.onCapture,e.phrase):await f({kind:`activate`,scope:i,guard:await J(i,`activating`),snapshot:{kind:`missing`}},e.signal),e.signal.throwIfAborted();let o=await p(t);if(e.signal.aborted)throw o.fill(0),Error(`VoiceID activation was cancelled.`);return{kind:`activated`,publicKeyB64u:t.publicKeyB64u,deviceKeyId:t.deviceKeyId,factorSecret32:o}}async function ye(e){n();let{challenge:t}=e;if(t.requestOrigin!==location.origin||t.expiresAtMs<=Date.now())throw Error(`VoiceID challenge is expired or belongs to another Wallet origin.`);let r=await o(t.walletId,t.walletAuthMethodId);if(!r||r.deviceKeyId!==t.deviceKeyId)throw Error(`VoiceID device key is unavailable in this browser.`);if(await $({kind:`active`,scope:await d(t.walletId,t.walletAuthMethodId)},e.signal,e.onCapture,e.phrase),e.signal.throwIfAborted(),t.expiresAtMs<=Date.now())throw Error(`VoiceID challenge expired. Start unlock again.`);let i=await crypto.subtle.sign(`Ed25519`,r.privateKey,N(t)),a=await p(r);if(e.signal.aborted||t.expiresAtMs<=Date.now())throw a.fill(0),Error(`VoiceID unlock expired or was cancelled.`);return{kind:`unlocked`,assertion:re({kind:`voiceid_device_assertion_v1`,challenge:t,signatureB64u:_(new Uint8Array(i))}),factorSecret32:a}}async function $(n,r,a,o){let s=await c(n,r,a,o);switch(s.kind){case`matched`:return;case`insufficient_audio`:throw new t(s.quality);case`mismatch`:throw new e(s.quality);case`phrase_mismatch`:throw new i;default:return be(s)}}function be(e){throw Error(`Unexpected voice result: ${String(e)}`)}export{I as a,J as i,ye as n,ge as r,ve as t};
@@ -0,0 +1 @@
1
+ import{a as e,c as t,d as n,f as r,h as i,l as a,m as o,p as s,s as c,t as l,u}from"./prompt-CCrXTRRx.js";import{IndexedDBManager as d,SEAMS_WALLET_STORES as f,WorkerDeferred as ee,availabilityKey as te,base64UrlDecode as p,base64UrlEncode as m,buildDelegatedWalletAuthorityV1 as h,buildFullOwnerPermissionsV1 as ne,isFiniteNumber as re,isPlainObject as g,parseStoredAuthMethodAvailability as _,parseVoiceIdDevicePublicKeyB64u as v,parseWalletAuthMethodV2StorageRow as y,parseWalletAuthorityStorageRow as ie,parseWalletSelectionStorageRow as ae,requireRecord as b,sameDelegatedWalletAuthorityV1 as oe,sha256DigestB64u as x,toError as S}from"../voiceid-host.js";const C=`e04dd7a6a1e23fc7b89e47682ea9d0a3946cf7bc59d07922c3db3efc52ae4269`,w=`redimnet-b1:${C}`,T=new o({path:`/sdk/voiceid/redimnet-b1.onnx`,sha256:C,bytes:8859593,label:`Speaker verification`});async function E(e){let t=await T.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 D(Array.from(t.data))}finally{for(let t of Object.values(e))t.dispose()}}finally{n.dispose()}}function D(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 O(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}const k=[T,s,a],A=[i,...k.map(se)];function se(e){return e.asset}function j(e,t){return e+t.size}var M=class{element=document.createElement(`section`);status=document.createElement(`p`);meter=document.createElement(`progress`);reveal;received=new Map;total=A.reduce(j,0);constructor(e){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.element.append(this.status,this.meter),this.status.textContent=`Loading saved VoiceID…`,this.reveal=setTimeout(e.append.bind(e,this.element),300)}settle=()=>{clearTimeout(this.reveal)};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 N(e){let t=new M(e);try{for(let e of A)await e.download(t.update.bind(t,e));t.preparing();for(let e of k)await e.prepare();t.ready()}finally{t.settle()}}function P(e,t){return`voiceid-browser-device-v1:${encodeURIComponent(e)}:${encodeURIComponent(t)}`}function F(e,t,n){return new TextEncoder().encode(JSON.stringify([`seams-voiceid-browser-factor-v1`,location.origin,e,t,n]))}async function I(e,t){let n=await d.getAppState(P(e,t));if(n===void 0)return null;let r=b(n,`VoiceID device record`);if(r.kind!==`browser_voiceid_device_v1`||r.walletId!==e||r.walletAuthMethodId!==t)throw Error(`VoiceID device belongs to another wallet method.`);let{privateKey:i,wrappingKey:a,nonce:o,ciphertext:s}=r;if(!(i instanceof CryptoKey)||i.type!==`private`||i.extractable||i.algorithm.name!==`Ed25519`||!i.usages.includes(`sign`)||!(a instanceof CryptoKey)||a.type!==`secret`||a.extractable||a.algorithm.name!==`AES-GCM`||!a.usages.includes(`decrypt`)||!(o instanceof Uint8Array)||o.length!==12||!(s instanceof ArrayBuffer)||s.byteLength!==48)throw Error(`VoiceID device storage is invalid.`);let c=v(r.publicKeyB64u),l=await x(p(c));if(r.deviceKeyId!==l)throw Error(`VoiceID device key binding is invalid.`);return{kind:`browser_voiceid_device_v1`,walletId:e,walletAuthMethodId:t,privateKey:i,wrappingKey:a,nonce:new Uint8Array(o),ciphertext:s,publicKeyB64u:c,deviceKeyId:l}}async function ce(e,t){return await navigator.locks.request(P(e,t),le.bind(null,e,t))}async function le(e,t){let n=await I(e,t);if(n)return n;let r=await crypto.subtle.generateKey({name:`Ed25519`},!1,[`sign`,`verify`]),i=v(m(new Uint8Array(await crypto.subtle.exportKey(`raw`,r.publicKey)))),a=await x(p(i)),o=await crypto.subtle.generateKey({name:`AES-GCM`,length:256},!1,[`encrypt`,`decrypt`]),s=crypto.getRandomValues(new Uint8Array(32)),c=crypto.getRandomValues(new Uint8Array(12));try{let n=await crypto.subtle.encrypt({name:`AES-GCM`,iv:c,additionalData:F(e,t,a)},o,s),l={kind:`browser_voiceid_device_v1`,walletId:e,walletAuthMethodId:t,privateKey:r.privateKey,publicKeyB64u:i,deviceKeyId:a,wrappingKey:o,nonce:c,ciphertext:n};return await d.setAppState(P(e,t),l),l}finally{s.fill(0)}}async function L(e){let t=await crypto.subtle.decrypt({name:`AES-GCM`,iv:e.nonce,additionalData:F(e.walletId,e.walletAuthMethodId,e.deviceKeyId)},e.wrappingKey,e.ciphertext);return new Uint8Array(t)}const R=`voiceid-browser-enrollment-v1`,z=.2,B=[f.appState,f.walletSelections,f.walletAuthMethods,f.walletAuthorities];function V(e,t){return{walletId:e.walletId,walletAuthMethodId:e.walletAuthMethodId,deviceKeyId:e.deviceKeyId,authorityId:t}}async function H(e,t){let n=await d.getWalletAuthMethodV2(t),r=await I(e,t);if(!n||n.kind!==`voiceid`||n.status!==`active`||n.walletId!==e||!r||n.deviceKeyId!==r.deviceKeyId)throw Error(`VoiceID is unavailable for this wallet method.`);return V(r,n.walletAuthorityId)}function U(e){return`voiceid-browser-enrollment-v2:${[e.walletId,e.authorityId,e.walletAuthMethodId,e.deviceKeyId].map(encodeURIComponent).join(`:`)}`}function W(e){if(!Array.isArray(e)||!e.every(re))throw Error(`VoiceID template is invalid.`);let t=D(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 G(e,t){if(e===void 0)return null;let n=b(e,`VoiceID enrollment`),r=b(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!==w)return null;let i=W(n.baseline),a={kind:`baseline`};try{let e=b(n.adaptation,`VoiceID improvements`);if(e.kind===`adapted`&&Array.isArray(e.samples)&&e.samples.length===3){let t=e.samples.map(W);q(i,t),a={kind:`adapted`,samples:t}}}catch{a={kind:`baseline`}}return{kind:`browser_voiceid_enrollment_v2`,scope:t,model:w,generation:n.generation,revision:n.revision,baseline:i,adaptation:a}}function K(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=D(n);for(let t=0;t<n.length;t+=1)n[t]=(1-z)*e[t]+z*r[t];return D(n)}function q(e,t){if(t.length!==3)throw Error(`Record three samples before saving voice improvements.`);for(let n of t)if(O(e,n)<.5)throw Error(`This sample differs from your original voice. Try again or re-record your enrollment.`);if(O(e,K(e,t))<.98)throw Error(`These samples differ too much from your original voice. Re-record your enrollment instead.`)}async function ue(e){let t=(await d.seamsWalletDB.getDB()).transaction(f.appState,`readwrite`);try{let n=await t.store.get(U(e)),r=G(n?.value,e);return r&&JSON.stringify(n?.value?.adaptation)!==JSON.stringify(r.adaptation)&&(r=Z(r,r.adaptation),await t.store.put({key:U(e),value:r})),await t.done,r}catch(e){try{t.abort()}catch{}throw await t.done.catch(X),e}}async function de(){let e=await d.getAppState(R);if(e===void 0)return null;let t=b(e,`Previous VoiceID enrollment`);return t.kind!==`browser_voiceid_enrollment_v1`||t.model!==w?null:W(t.template)}async function J(e,t,n){let r=ae(await e.objectStore(f.walletSelections).get(t.walletId)),i=ie(await e.objectStore(f.walletAuthorities).get(t.authorityId)),a=await e.objectStore(f.walletAuthMethods).get(t.walletAuthMethodId),o=y(a);if(a!==void 0&&!o)throw Error(`VoiceID method storage is invalid.`);if(!i||i.record.state!==`active`||i.record.walletId!==t.walletId)throw Error(`VoiceID authority changed. Start again.`);if(o&&(o.record.kind!==`voiceid`||o.record.status!==`active`||o.record.walletId!==t.walletId||o.record.walletAuthorityId!==t.authorityId||o.record.deviceKeyId!==t.deviceKeyId)||(n===null||n.target===`enrolled`)&&!o)throw Error(`VoiceID method is unavailable.`);if((await e.objectStore(f.appState).get(P(t.walletId,t.walletAuthMethodId)))?.value?.deviceKeyId!==t.deviceKeyId)throw Error(`VoiceID device changed. Start again.`);let s=_((await e.objectStore(f.appState).get(te(t.walletId,t.walletAuthMethodId)))?.value);if(!s.enabled)throw Error(`VoiceID is turned off.`);if(n){if(!oe(h({permissions:i.record.permissions}),h({permissions:ne()})))throw Error(`Full owner authority is required to change VoiceID enrollment.`);let a=y(await e.objectStore(f.walletAuthMethods).get(n.sessionMethodId));if(n.expiresAtMs<=Date.now()||s.revision!==n.availabilityRevision||!r||r.record.lockState!==`unlocked`||r.record.lockGeneration!==n.lockGeneration||r.record.walletAuthMethodId!==n.sessionMethodId||!a||a.record.status!==`active`||n.target===`activating`&&a.record.kind===`voiceid`||a.record.walletId!==t.walletId||a.record.walletAuthorityId!==t.authorityId)throw Error(`The owner session changed or expired. Start again.`);if(n.target===`enrolled`){let r=y(await e.objectStore(f.walletAuthMethods).get(n.confirmationMethodId));if(!r||r.record.kind!==`passkey`||r.record.status!==`active`||r.record.walletId!==t.walletId||r.record.walletAuthorityId!==t.authorityId)throw Error(`The confirming passkey changed or was removed. Start again.`)}}}async function Y(e,t){let n=(await d.seamsWalletDB.getDB()).transaction(B,`readwrite`);try{await J(n,e,t),await n.done}catch(e){throw $(n),await n.done.catch(X),e}}function X(){}async function fe(e,t){let n=e.scope,r=e.kind===`activation`?e.owner:null;if(r&&r.target!==`activating`)throw Error(`VoiceID activation requires its owner scope.`);let i=(await d.seamsWalletDB.getDB()).transaction(B,`readwrite`);try{await J(i,n,r);let e=i.objectStore(f.appState),a=await e.get(U(n)),o=G(a?.value,n);if(!o)throw Error(`Unlock with a passkey, then open Manage voice to import or record your enrollment.`);t.throwIfAborted();let s=o.adaptation,c=s.kind===`adapted`?K(o.baseline,s.samples):[...o.baseline];return JSON.stringify(a?.value?.adaptation)!==JSON.stringify(s)&&await e.put({key:U(n),value:Z(o,s)}),await i.done,t.throwIfAborted(),{template:c,baseline:[...o.baseline],kind:s.kind}}catch(e){try{i.abort()}catch{}throw await i.done.catch(X),e}}function Z(e,t){return{kind:`browser_voiceid_enrollment_v2`,scope:e.scope,model:e.model,generation:e.generation,revision:e.revision+1,baseline:e.baseline,adaptation:t}}async function Q(e,t,n,r,i){let a;if(r.kind===`activate`){if(t.target!==`activating`||n.kind!==`missing`)throw Error(`VoiceID activation cannot replace an enrollment.`)}else{if(t.target!==`enrolled`)throw Error(`VoiceID changes require a confirmation guard.`);await r.confirmation.consume(e,t,n,r.kind,i)}if(r.kind===`import`&&(t.target!==`enrolled`||n.kind!==`missing`))throw Error(`Import requires an existing method without a scoped enrollment.`);if(r.kind===`replace`||r.kind===`activate`||r.kind===`import`)a={kind:`browser_voiceid_enrollment_v2`,scope:e,model:w,generation:crypto.randomUUID(),revision:0,baseline:W(r.baseline),adaptation:{kind:`baseline`}};else{if(n.kind!==`present`)throw Error(`Record or import your original voice first.`);r.kind===`improve`?(q(n.enrollment.baseline,r.samples),a=Z(n.enrollment,{kind:`adapted`,samples:r.samples})):a=Z(n.enrollment,{kind:`baseline`})}if(new TextEncoder().encode(JSON.stringify(a)).length>32768)throw Error(`VoiceID enrollment exceeds its storage limit.`);let o=await d.seamsWalletDB.getDB();i.throwIfAborted();let s=o.transaction(B,`readwrite`),c=$.bind(null,s);i.addEventListener(`abort`,c,{once:!0});try{await J(s,e,t);let o=s.objectStore(f.appState),c=G((await o.get(U(e)))?.value,e);if(n.kind===`missing`?c!==null:!c||c.generation!==n.enrollment.generation||c.revision!==n.enrollment.revision)throw Error(`VoiceID enrollment changed in another operation. Start again.`);i.throwIfAborted(),await o.put({key:U(e),value:a}),r.kind===`import`&&await pe(s),await s.done}catch(e){throw c(),await s.done.catch(X),e}finally{i.removeEventListener(`abort`,c)}}function $(e){try{e.abort()}catch{}}async function pe(e){let t=e.objectStore(f.appState),n=await e.objectStore(f.walletAuthMethods).getAll();for(let e of n){if(!g(e)||e.kind!==`voiceid`)continue;let n=y(e);if(!n)return;let r=n.record;if(r.kind!==`voiceid`||r.status!==`active`)continue;let i={walletId:r.walletId,authorityId:r.walletAuthorityId,walletAuthMethodId:r.walletAuthMethodId,deviceKeyId:r.deviceKeyId};try{if(!G((await t.get(U(i)))?.value,i))return}catch{return}}await t.delete(R)}async function me(e,t){let n=document.querySelector(`.seams-voiceid-activation-surface`);if(!(n instanceof HTMLElement))throw Error(`Open VoiceID activation in the Wallet.`);await N(n),t.throwIfAborted();let r=new he(n,e,t);try{await r.result}finally{r.dispose()}}var he=class{completion=new ee;result=this.completion.promise;status;prompt;phrase=r(null);record;cancel;samples=[];phase=`ready`;get closed(){return this.phase===`closed`}controller=new AbortController;guardTimer;checkingGuard=!1;constructor(e,t,n){this.plan=t,this.signal=n,this.prompt=new l(document,`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 i=this.samples.length+1;try{c(),this.phase=`recording`,this.record.disabled=!0,this.status.textContent=`Opening microphone…`;let r=await e(this.controller.signal,this.prompt.capture);if(this.signal.aborted||this.closed){r.kind===`captured`&&r.samples.fill(0);return}if(r.kind===`insufficient_audio`){this.status.textContent=t(r.quality);return}if(this.plan.kind===`improve`&&r.quality.noise!==`normal`){r.samples.fill(0),this.status.textContent=`Use a quiet place to improve your voice enrollment.`;return}let i;try{if(await Y(this.plan.scope,this.plan.guard),this.status.textContent=`Checking your voice…`,(await n(r.samples,this.phrase)).kind===`mismatch`)throw new u;i=await E(r.samples)}finally{r.samples.fill(0)}if(this.signal.aborted||this.closed){i.fill(0);return}if(this.plan.kind===`improve`&&O(this.plan.snapshot.enrollment.baseline,i)<.5)throw i.fill(0),Error(`Your voice did not match the original enrollment. To replace it, return to Manage voice and choose Record voice again.`);let a=1;for(let e of this.samples)a=Math.min(a,O(e,i));this.status.dataset.voiceCapture=JSON.stringify({attemptId:r.quality.attemptId,capturedAtMs:r.quality.capturedAtMs,sample:this.samples.length+1,durationMs:r.quality.durationMs,recordingMs:r.quality.recordingMs,endedBy:r.quality.endedBy,voicedMs:r.quality.voicedMs,microphone:r.quality.microphone,processing:r.quality.processing,backgroundRms:r.quality.backgroundRms,speechToBackgroundDb:r.quality.speechToBackgroundDb,noise:r.quality.noise,minimumSimilarity:a});for(let e of this.samples)if(O(e,i)<.5)throw i.fill(0),Error(`This sample differs from the earlier samples. Use the same microphone and try again.`);if(this.samples.push(i),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 Q(s.scope,s.guard,s.snapshot,{kind:`activate`,baseline:D(o)},this.controller.signal);break;case`replace`:await Q(s.scope,s.guard,s.snapshot,{kind:`replace`,baseline:D(o),confirmation:s.confirmation},this.controller.signal);break;case`improve`:await Q(s.scope,s.guard,s.snapshot,{kind:`improve`,samples:this.samples,confirmation:s.confirmation},this.controller.signal);break}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(S(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<i&&(this.record.textContent=`Retry sample ${i}`,this.status.textContent=`Sample ${i} was not accepted. ${this.status.textContent??``}`),this.phrase=r(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 Y(this.plan.scope,this.plan.guard)}catch(e){this.closed||(this.phase=`closed`,this.controller.abort(),this.completion.reject(S(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)}};async function ge(t,r,i,a){delete document.body.dataset.voiceVerification;let o=await e(r,i);if(o.kind===`insufficient_audio`)return r.throwIfAborted(),o;try{r.throwIfAborted();let e=await n(o.samples,a),i=e.kind===`matched`,s=o.samples.length/16,c=await E(o.samples),l,u,d;try{r.throwIfAborted();let e=await fe(t,r);try{l=O(c,e.template),u=O(c,e.baseline),d=e.kind}finally{e.template.fill(0),e.baseline.fill(0)}}finally{c.fill(0)}return document.body.dataset.voiceVerification=JSON.stringify({attemptId:o.quality.attemptId,capturedAtMs:o.quality.capturedAtMs,durationMs:o.quality.durationMs,recordingMs:o.quality.recordingMs,endedBy:o.quality.endedBy,voicedMs:o.quality.voicedMs,microphone:o.quality.microphone,processing:o.quality.processing,backgroundRms:o.quality.backgroundRms,speechToBackgroundDb:o.quality.speechToBackgroundDb,noise:o.quality.noise,similarity:l,baselineSimilarity:u,referenceKind:d,modelInputMs:s,threshold:.5,phraseMatched:i,phraseRecognition:e.recognition,expectedPhrase:a}),l<.5?{kind:`mismatch`,quality:o.quality}:e.kind===`matched`?{kind:`matched`}:{kind:`phrase_mismatch`}}finally{o.samples.fill(0)}}export{de as a,V as c,I as d,N as f,Q as i,ce as l,ge as n,ue as o,Y as r,H as s,me as t,L as u};
@@ -0,0 +1,80 @@
1
+ import{f as e,g as t,i as n,n as r,r as i,t as a,u as o}from"./prompt-CCrXTRRx.js";import{SeamsWordmark as s,VOICE_ID_HOST_API_VERSION as c,WorkerDeferred as l,authMenuSuccessCopy as u,backIcon as d,createCspStylesheetManager as f,createWalletIframeSurfaceMeasurementReporter as p,getDefaultCspNonce as m,toError as h}from"../voiceid-host.js";const g=new WeakMap;var _=class{footer;constructor(e,t){this.prompt=t;let n=e.ownerDocument,a=g.get(n);a||(a=f({doc:n,baseCss:`
2
+ .seams-voiceid-activation-surface.seams-voiceid-unlock {
3
+ box-sizing: border-box;
4
+ overflow: hidden;
5
+ border: 1px solid var(--seams-colors-borderPrimary, #303b41);
6
+ border-radius: var(--seams-shape-card, 24px);
7
+ background: var(--seams-colors-colorBackground, #192024);
8
+ color: var(--seams-colors-textPrimary, #eff2f3);
9
+ font-family: var(--seams-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
10
+ }
11
+ .seams-voiceid-unlock-header {
12
+ padding: 1rem 1.25rem 0;
13
+ }
14
+ .seams-voiceid-unlock-header .seams-menu-origin {
15
+ display: flex;
16
+ align-items: center;
17
+ gap: 0.5rem;
18
+ margin: 0 0 0.5rem;
19
+ font-size: 0.8125rem;
20
+ color: var(--seams-colors-textSecondary, #9cabb3);
21
+ }
22
+ .seams-voiceid-unlock-header .seams-menu-origin svg {
23
+ width: 14px;
24
+ height: 14px;
25
+ }
26
+ .seams-voiceid-unlock-back {
27
+ display: grid;
28
+ place-items: center;
29
+ width: 44px;
30
+ height: 44px;
31
+ margin-inline-start: -0.5rem;
32
+ padding: 0;
33
+ border: 0;
34
+ border-radius: var(--seams-shape-control, 10px);
35
+ background: transparent;
36
+ color: var(--seams-colors-textSecondary, #9cabb3);
37
+ cursor: pointer;
38
+ }
39
+ .seams-voiceid-unlock-back svg {
40
+ width: 20px;
41
+ height: 20px;
42
+ }
43
+ .seams-voiceid-unlock-back:focus-visible {
44
+ outline: none;
45
+ color: var(--seams-colors-textPrimary, #eff2f3);
46
+ }
47
+ .seams-voiceid-unlock .seams-voiceid-prompt {
48
+ width: 100%;
49
+ border: 0;
50
+ border-radius: 0;
51
+ background: transparent;
52
+ padding: 0.75rem 1.5rem 1.5rem;
53
+ grid-template-rows: auto minmax(6rem, auto) 5rem minmax(3.375rem, auto) auto auto;
54
+ }
55
+ .seams-voiceid-unlock .seams-voiceid-record-slot:has(button[hidden]) {
56
+ display: none;
57
+ }
58
+ .seams-voiceid-unlock-footer {
59
+ display: flex;
60
+ align-items: baseline;
61
+ justify-content: center;
62
+ gap: 0.375rem;
63
+ padding: 0.625rem 1rem;
64
+ border-top: 1px solid color-mix(in srgb, var(--seams-colors-borderPrimary, #303b41) 60%, transparent);
65
+ color: var(--seams-colors-textSecondary, #9cabb3);
66
+ font-size: 0.6875rem;
67
+ line-height: 1rem;
68
+ letter-spacing: 0.01em;
69
+ }
70
+ .seams-voiceid-unlock-footer .seams-receipt-wordmark {
71
+ flex: none;
72
+ width: 3.125rem;
73
+ height: 0.625rem;
74
+ }
75
+ @media (hover: hover) {
76
+ .seams-voiceid-unlock-back:hover {
77
+ color: var(--seams-colors-textPrimary, #eff2f3);
78
+ }
79
+ }
80
+ `,nonce:m}),g.set(n,a)),a.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(),r(d(),t.cancel),o.append(t.cancel),e.prepend(o),this.footer=n.createElement(`div`),this.footer.className=`seams-voiceid-unlock-footer`,r([i(`span`,null,`Secured by`),` `,i(s,{})],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(){r(null,this.prompt.cancel),r(null,this.footer)}},v=class{result;completion=new l;controller=new AbortController;element;activateButton;cancelButton;status;prompt;unlockFrame;unmountCapture;measurement;phrase=e(null);state={kind:`preparing`};settlement=`closed`;expiryTimer=null;constructor(e,t,n,r){let i=t===`activation`?`Activate VoiceID`:`Unlock with VoiceID`,o=document.getElementById(`root`)??document.body;if(!o)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 a(document,i,this.phrase),this.element.append(this.prompt.element),this.unlockFrame=t===`unlock`?new _(this.element,this.prompt):null,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.unlockFrame!==null,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||o.appendChild(this.element),this.measurement=!r&&n.kind===`wallet_iframe`?p({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(x),this.controller.signal.throwIfAborted();let t=await e(this.controller.signal,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.unlockFrame?this.begin():this.activateButton.focus()}catch(e){if(this.state.kind===`closed`)return;this.state={kind:`closed`},this.completion.reject(h(e))}}begin=()=>{if(this.state.kind!==`ready`)return;let e=this.state.capture;this.state={kind:`capturing`},this.perform(e)};async perform(r){this.activateButton.disabled=!0,this.status.textContent=`Opening microphone…`;try{let e=await r.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(i){if(this.state.kind===`closed`)return;if(i instanceof n||i instanceof o||i instanceof t){if(r.expiresAtMs!==null&&Date.now()>=r.expiresAtMs){this.expire();return}let t=this.phrase;this.phrase=e(t),this.prompt.setPhrase(this.phrase),this.state={kind:`ready`,capture:r},this.activateButton.hidden=!1,this.activateButton.textContent=`Try again`,this.prompt.ready(i.message),this.activateButton.focus();return}this.state={kind:`closed`},this.completion.reject(h(i))}}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=u(`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 y))};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.`)))}},y=class extends Error{constructor(){super(`VoiceID capture was cancelled.`),this.name=`VoiceIdCaptureCancelledError`}};async function b(e){let t=new v(e.prepare,e.purpose,e.measurement,e.mountCapture);try{return await t.result}finally{t.dispose()}}function x(e){requestAnimationFrame(S.bind(null,e))}function S(e){setTimeout(e,0)}const C=1;if(c!==1)throw Error(`VoiceID requires a matching Wallet host API.`);const w={unlock:T,activate:D,review:k};function T(e){return b({purpose:`unlock`,measurement:e.surfaceMeasurementBinding,mountCapture:e.mountCapture,prepare:E.bind(null,e)})}async function E(e,t,n){let r=await import(`./unlock-E7YHqBGT.js`);return t.throwIfAborted(),r.prepareUnlockSurface(e,t,n)}async function D(e){try{return await b({purpose:`activation`,measurement:e.context.signingEngine.getWalletIframeSurfaceMeasurementBinding(),prepare:O.bind(null,e)})}catch(e){if(e instanceof y)return{kind:`cancelled`};throw e}}async function O(e,t){let n=await import(`./addVoiceId-CeBXVHqs.js`);return t.throwIfAborted(),n.prepareActivationSurface(e,t)}async function k(e,t){return(await import(`./approval-CCbdLhTv.js`)).voiceIdPolicyForRequest(e,t)}export{C as hostApiVersion,w as voiceIdHostPlugin};