@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 @@
1
+ import"./prompt-CCrXTRRx.js";import{a as e,n as t}from"./deviceBridge-wRAbqdap.js";import{f as n,o as r,s as i}from"./enrollment-DIRoCkx5.js";import{IndexedDBManager as a,fetchWithWalletHomeDiscovery as o,readAuthMethodEnabled as s}from"../voiceid-host.js";async function c(e){let{authMethod:t,challenge:n}=e;if(n.walletId!==t.walletId||n.walletAuthMethodId!==t.walletAuthMethodId||n.walletAuthorityId!==t.walletAuthorityId||n.deviceKeyId!==t.deviceKeyId)throw Error(`VoiceID challenge does not match the selected device method.`);let r=await e.capture({challenge:n,signal:e.signal,onCapture:e.onCapture,phrase:e.phrase});try{if(e.signal.aborted)throw Error(`VoiceID unlock was cancelled.`);let n=await e.http.verify({assertion:r.assertion,signal:e.signal});if(e.signal.aborted)throw Error(`VoiceID unlock was cancelled.`);if(n.walletSession.walletId!==t.walletId||n.walletSession.authMethodId!==t.walletAuthMethodId||n.walletSession.authorityId!==t.walletAuthorityId||n.custodyEnvelope.factor.deviceKeyId!==t.deviceKeyId)throw Error(`VoiceID server verified a different device method.`);return await e.install(n,r.factorSecret32)}finally{r.factorSecret32.fill(0)}}async function l(t,c,l){if(!await s(t.walletId,t.walletAuthMethodId))throw Error(`VoiceID is turned off in this browser. Enable it in Authentication methods.`);let u=await t.prepareSession(c),f=await a.getWalletAuthMethodV2(t.walletAuthMethodId);if(!f||f.kind!==`voiceid`||f.status!==`active`||f.walletId!==t.walletId||f.walletAuthMethodId!==t.walletAuthMethodId)throw Error(`Activate VoiceID on this device before unlocking this wallet.`);let p=new e(t.relayerUrl,location.origin,o);if(!await r(await i(t.walletId,t.walletAuthMethodId)))throw Error(`Unlock with a passkey, then open Manage voice to import or record your enrollment.`);await n(l),c.throwIfAborted(),t.assertActive();let m=await p.challenge({walletId:t.walletId,walletAuthMethodId:t.walletAuthMethodId,signal:AbortSignal.any([c,AbortSignal.timeout(15e3)])});t.assertActive();let h={authMethod:f,challenge:m,http:p,install:u};return c.throwIfAborted(),{kind:`recording`,expiresAtMs:m.expiresAtMs,action:d.bind(null,h)}}function u(e,t,n,r){return e({walletSession:n.walletSession,operationCredential:n.operationCredential,custodyEnvelope:n.custodyEnvelope,factorSecret32:r,signal:t,near:n.near})}async function d(e,n,r,i){return await c({authMethod:e.authMethod,challenge:e.challenge,http:e.http,capture:t,install:u.bind(null,e.install,n),signal:n,onCapture:r,phrase:i})}export{l as prepareUnlockSurface};
@@ -0,0 +1,21 @@
1
+ class VoiceActivityFrames extends AudioWorkletProcessor {
2
+ constructor() {
3
+ super();
4
+ this.frame = new Float32Array(512);
5
+ this.offset = 0;
6
+ }
7
+ process(inputs) {
8
+ const channel = inputs[0]?.[0];
9
+ if (!channel) return true;
10
+ for (const sample of channel) {
11
+ this.frame[this.offset++] = sample;
12
+ if (this.offset === 512) {
13
+ this.port.postMessage(this.frame, [this.frame.buffer]);
14
+ this.frame = new Float32Array(512);
15
+ this.offset = 0;
16
+ }
17
+ }
18
+ return true;
19
+ }
20
+ }
21
+ registerProcessor('voice-activity-frames', VoiceActivityFrames);
@@ -0,0 +1,11 @@
1
+ import type { PreparedVoiceCapture } from '../capture/surface';
2
+ import type { RegistrationCapability, RegistrationWebContext } from '@seams/wallet/voiceid-host';
3
+ import { type WalletId } from '@seams/wallet/voiceid-host';
4
+ import type { Variant } from '@seams/wallet/voiceid-host';
5
+ type AddVoiceIdResult = Variant<Awaited<ReturnType<RegistrationCapability['activateAuthMethod']>>, 'kind', 'activated'>;
6
+ export declare function prepareActivationSurface(input: {
7
+ readonly context: RegistrationWebContext;
8
+ readonly walletId: WalletId;
9
+ }, signal: AbortSignal): Promise<PreparedVoiceCapture<AddVoiceIdResult>>;
10
+ export {};
11
+ //# sourceMappingURL=addVoiceId.d.ts.map
@@ -0,0 +1,4 @@
1
+ import type { RegistrationWebContext } from '@seams/wallet/voiceid-host';
2
+ import { type VoiceEnrollmentScope } from '../browser/enrollmentStore';
3
+ export declare function manageVoiceEnrollment(context: RegistrationWebContext, scope: VoiceEnrollmentScope, signal: AbortSignal): Promise<void>;
4
+ //# sourceMappingURL=manageEnrollment.d.ts.map
@@ -0,0 +1,17 @@
1
+ import type { RegistrationWebContext } from '@seams/wallet/voiceid-host';
2
+ import { type VoiceEnrollmentScope, type VoiceEnrollmentSnapshot, type VoiceChangeGuard, type VoiceActivationGuard } from '../browser/enrollmentStore';
3
+ type VoiceChangeAction = 'replace' | 'improve' | 'reset' | 'import';
4
+ export declare function prepareVoiceOwner(scope: VoiceEnrollmentScope, target: 'enrolled'): Promise<VoiceChangeGuard>;
5
+ export declare function prepareVoiceOwner(scope: VoiceEnrollmentScope, target: 'activating'): Promise<VoiceActivationGuard>;
6
+ /** A verified, single-use permission for one enrollment change, never for signing or unlock. */
7
+ export declare class ConfirmedVoiceChange {
8
+ private readonly binding;
9
+ private readonly expiresAtMs;
10
+ private readonly assertCurrentOwner;
11
+ private consumed;
12
+ private constructor();
13
+ static request(context: RegistrationWebContext, scope: VoiceEnrollmentScope, guard: VoiceChangeGuard, snapshot: VoiceEnrollmentSnapshot, action: VoiceChangeAction, signal: AbortSignal): Promise<ConfirmedVoiceChange>;
14
+ consume(scope: VoiceEnrollmentScope, guard: VoiceChangeGuard, snapshot: VoiceEnrollmentSnapshot, action: VoiceChangeAction, signal: AbortSignal): Promise<void>;
15
+ }
16
+ export {};
17
+ //# sourceMappingURL=ownerConfirmation.d.ts.map
@@ -0,0 +1,19 @@
1
+ import { parseVoiceIdDevicePublicKeyB64u } from '@seams/wallet/voiceid-host';
2
+ import { type DigestB64u } from '@seams/wallet/voiceid-host';
3
+ import type { WalletId, WalletAuthMethodId } from '@seams/wallet/voiceid-host';
4
+ export type BrowserVoiceDevice = Readonly<{
5
+ kind: 'browser_voiceid_device_v1';
6
+ walletId: WalletId;
7
+ walletAuthMethodId: WalletAuthMethodId;
8
+ privateKey: CryptoKey;
9
+ publicKeyB64u: ReturnType<typeof parseVoiceIdDevicePublicKeyB64u>;
10
+ deviceKeyId: DigestB64u;
11
+ wrappingKey: CryptoKey;
12
+ nonce: Uint8Array<ArrayBuffer>;
13
+ ciphertext: ArrayBuffer;
14
+ }>;
15
+ export declare function deviceKey(walletId: WalletId, methodId: WalletAuthMethodId): string;
16
+ export declare function readBrowserVoiceDevice(walletId: WalletId, methodId: WalletAuthMethodId): Promise<BrowserVoiceDevice | null>;
17
+ export declare function createBrowserVoiceDevice(walletId: WalletId, methodId: WalletAuthMethodId): Promise<BrowserVoiceDevice>;
18
+ export declare function openBrowserVoiceFactor(device: BrowserVoiceDevice): Promise<Uint8Array<ArrayBuffer>>;
19
+ //# sourceMappingURL=deviceStore.d.ts.map
@@ -0,0 +1,37 @@
1
+ import { type SpokenPhrase } from './phrase';
2
+ import { type VoiceCaptureQuality, type VoiceCaptureObserver } from './microphone';
3
+ import { type VoiceEnrollmentScope, type VoiceEnrollmentSnapshot, type VoiceOwnerGuard, type VoiceTemplateAccess } from './enrollmentStore';
4
+ import type { ConfirmedVoiceChange } from '../activation/ownerConfirmation';
5
+ import type { Variant } from '@seams/wallet/voiceid-host';
6
+ type EnrollmentCapturePlan = {
7
+ readonly scope: VoiceEnrollmentScope;
8
+ readonly guard: VoiceOwnerGuard;
9
+ } & ({
10
+ readonly kind: 'activate';
11
+ readonly snapshot: {
12
+ readonly kind: 'missing';
13
+ };
14
+ readonly confirmation?: never;
15
+ } | {
16
+ readonly kind: 'replace';
17
+ readonly snapshot: VoiceEnrollmentSnapshot;
18
+ readonly confirmation: ConfirmedVoiceChange;
19
+ } | {
20
+ readonly kind: 'improve';
21
+ readonly snapshot: Variant<VoiceEnrollmentSnapshot, 'kind', 'present'>;
22
+ readonly confirmation: ConfirmedVoiceChange;
23
+ });
24
+ export declare function enrollBrowserVoice(plan: EnrollmentCapturePlan, signal: AbortSignal): Promise<void>;
25
+ export declare function verifyBrowserVoice(access: VoiceTemplateAccess, signal: AbortSignal, onCapture: VoiceCaptureObserver, phrase: SpokenPhrase): Promise<{
26
+ kind: 'matched';
27
+ } | {
28
+ kind: 'mismatch';
29
+ quality: VoiceCaptureQuality;
30
+ } | {
31
+ kind: 'phrase_mismatch';
32
+ } | {
33
+ kind: 'insufficient_audio';
34
+ quality: VoiceCaptureQuality;
35
+ }>;
36
+ export {};
37
+ //# sourceMappingURL=enrollment.d.ts.map
@@ -0,0 +1,91 @@
1
+ import type { Variant } from '@seams/wallet/voiceid-host';
2
+ import type { WalletId, WalletAuthMethodId, WalletAuthorityId } from '@seams/wallet/voiceid-host';
3
+ import type { DigestB64u } from '@seams/wallet/voiceid-host';
4
+ import type { WalletSessionId } from '@seams/wallet/voiceid-host';
5
+ import { type BrowserVoiceDevice } from './deviceStore';
6
+ import type { ConfirmedVoiceChange } from '../activation/ownerConfirmation';
7
+ export type VoiceEnrollmentScope = Readonly<{
8
+ walletId: WalletId;
9
+ authorityId: WalletAuthorityId;
10
+ walletAuthMethodId: WalletAuthMethodId;
11
+ deviceKeyId: DigestB64u;
12
+ }>;
13
+ export type VoiceEnrollment = Readonly<{
14
+ kind: 'browser_voiceid_enrollment_v2';
15
+ scope: VoiceEnrollmentScope;
16
+ model: string;
17
+ generation: string;
18
+ revision: number;
19
+ baseline: readonly number[];
20
+ adaptation: {
21
+ readonly kind: 'baseline';
22
+ readonly samples?: never;
23
+ } | {
24
+ readonly kind: 'adapted';
25
+ readonly samples: readonly (readonly number[])[];
26
+ };
27
+ }>;
28
+ export type VoiceEnrollmentSnapshot = {
29
+ readonly kind: 'missing';
30
+ readonly enrollment?: never;
31
+ } | {
32
+ readonly kind: 'present';
33
+ readonly enrollment: VoiceEnrollment;
34
+ };
35
+ export type VoiceOwnerGuard = Readonly<{
36
+ sessionMethodId: WalletAuthMethodId;
37
+ walletSessionId: WalletSessionId;
38
+ lockGeneration: number;
39
+ expiresAtMs: number;
40
+ availabilityRevision: string;
41
+ } & ({
42
+ target: 'activating';
43
+ confirmationMethodId?: never;
44
+ } | {
45
+ target: 'enrolled';
46
+ confirmationMethodId: WalletAuthMethodId;
47
+ })>;
48
+ export type VoiceChangeGuard = Variant<VoiceOwnerGuard, 'target', 'enrolled'>;
49
+ export type VoiceActivationGuard = Variant<VoiceOwnerGuard, 'target', 'activating'>;
50
+ export declare function voiceEnrollmentScope(device: BrowserVoiceDevice, authorityId: WalletAuthorityId): VoiceEnrollmentScope;
51
+ export declare function resolveVoiceEnrollmentScope(walletId: WalletId, methodId: WalletAuthMethodId): Promise<VoiceEnrollmentScope>;
52
+ export declare function readVoiceEnrollment(scope: VoiceEnrollmentScope): Promise<VoiceEnrollment | null>;
53
+ export declare function readImportableVoiceBaseline(): Promise<readonly number[] | null>;
54
+ export declare function assertVoiceOwner(scope: VoiceEnrollmentScope, guard: VoiceOwnerGuard): Promise<void>;
55
+ export type VoiceTemplateAccess = {
56
+ readonly kind: 'active';
57
+ readonly scope: VoiceEnrollmentScope;
58
+ readonly owner?: never;
59
+ } | {
60
+ readonly kind: 'activation';
61
+ readonly scope: VoiceEnrollmentScope;
62
+ readonly owner: VoiceOwnerGuard;
63
+ };
64
+ export declare function readVoiceTemplate(access: VoiceTemplateAccess, signal: AbortSignal): Promise<{
65
+ template: number[];
66
+ baseline: number[];
67
+ kind: 'baseline' | 'adapted';
68
+ }>;
69
+ export type VoiceEnrollmentChange = {
70
+ readonly kind: 'activate';
71
+ readonly baseline: readonly number[];
72
+ readonly samples?: never;
73
+ readonly confirmation?: never;
74
+ } | {
75
+ readonly kind: 'replace' | 'import';
76
+ readonly baseline: readonly number[];
77
+ readonly samples?: never;
78
+ readonly confirmation: ConfirmedVoiceChange;
79
+ } | {
80
+ readonly kind: 'improve';
81
+ readonly samples: readonly (readonly number[])[];
82
+ readonly baseline?: never;
83
+ readonly confirmation: ConfirmedVoiceChange;
84
+ } | {
85
+ readonly kind: 'reset';
86
+ readonly samples?: never;
87
+ readonly baseline?: never;
88
+ readonly confirmation: ConfirmedVoiceChange;
89
+ };
90
+ export declare function commitVoiceEnrollment(scope: VoiceEnrollmentScope, guard: VoiceOwnerGuard, snapshot: VoiceEnrollmentSnapshot, change: VoiceEnrollmentChange, signal: AbortSignal): Promise<void>;
91
+ //# sourceMappingURL=enrollmentStore.d.ts.map
@@ -0,0 +1,39 @@
1
+ import type { InferenceSession } from 'onnxruntime-web';
2
+ type ModelAsset = Readonly<{
3
+ path: string;
4
+ sha256: string;
5
+ bytes: number;
6
+ label: string;
7
+ }>;
8
+ export type VoiceAssetProgress = {
9
+ kind: 'checking_cache';
10
+ } | {
11
+ kind: 'downloading';
12
+ received: number;
13
+ } | {
14
+ kind: 'ready';
15
+ };
16
+ declare class BrowserInferenceAsset {
17
+ private readonly asset;
18
+ private pending;
19
+ private progress;
20
+ private readonly listeners;
21
+ constructor(asset: ModelAsset);
22
+ get size(): number;
23
+ download(onProgress?: (progress: VoiceAssetProgress) => void): Promise<ArrayBuffer>;
24
+ private readonly failed;
25
+ private publish;
26
+ private valid;
27
+ private bytes;
28
+ }
29
+ export declare const voiceInferenceEngine: BrowserInferenceAsset;
30
+ export declare class BrowserInferenceModel {
31
+ readonly asset: BrowserInferenceAsset;
32
+ private session;
33
+ constructor(asset: ModelAsset);
34
+ prepare(): Promise<InferenceSession>;
35
+ private readonly failed;
36
+ private load;
37
+ }
38
+ export {};
39
+ //# sourceMappingURL=inference.d.ts.map
@@ -0,0 +1,61 @@
1
+ /** One 32 ms frame as the recorder judged it. No capture event carries the stream. */
2
+ export type VoiceActivityEvent = Readonly<{
3
+ kind: 'activity';
4
+ rms: number;
5
+ /** The voice activity model and the level check both found speech. */
6
+ speech: boolean;
7
+ stream?: never;
8
+ }>;
9
+ export type VoiceCaptureEvent = {
10
+ readonly kind: 'listening';
11
+ readonly stream?: never;
12
+ } | VoiceActivityEvent | {
13
+ readonly kind: 'processing';
14
+ readonly stream?: never;
15
+ } | {
16
+ readonly kind: 'measured';
17
+ readonly quality: VoiceCaptureQuality;
18
+ readonly stream?: never;
19
+ };
20
+ export type VoiceCaptureObserver = (event: VoiceCaptureEvent) => void;
21
+ export type VoiceCaptureQuality = Readonly<{
22
+ attemptId: string;
23
+ capturedAtMs: number;
24
+ durationMs: number;
25
+ recordingMs: number;
26
+ endedBy: 'pause' | 'limit' | 'stream_ended';
27
+ voicedMs: number;
28
+ peakFrameRms: number;
29
+ levelThreshold: number;
30
+ requiredVoicedMs: number;
31
+ microphone: string;
32
+ processing: Readonly<{
33
+ noiseSuppression: boolean | null;
34
+ echoCancellation: boolean | string | null;
35
+ autoGainControl: boolean | null;
36
+ sampleRate: number | null;
37
+ }>;
38
+ backgroundRms: number;
39
+ speechToBackgroundDb: number | null;
40
+ noise: 'high' | 'normal' | 'unknown';
41
+ }>;
42
+ type VoiceRecordingResult = {
43
+ kind: 'captured';
44
+ samples: Float32Array;
45
+ quality: VoiceCaptureQuality;
46
+ } | {
47
+ kind: 'insufficient_audio';
48
+ quality: VoiceCaptureQuality;
49
+ samples?: never;
50
+ };
51
+ export declare function voiceQualityMessage(quality: VoiceCaptureQuality): string;
52
+ /** Carries a typed capture rejection across the SDK's exception-based UI action boundary. */
53
+ export declare class InsufficientVoiceAudioError extends Error {
54
+ readonly quality: VoiceCaptureQuality;
55
+ constructor(quality: VoiceCaptureQuality);
56
+ }
57
+ export declare function requireVoiceUserAction(): void;
58
+ export declare function requireVoiceForeground(): void;
59
+ export declare function recordVoice(signal: AbortSignal, onCapture: VoiceCaptureObserver): Promise<VoiceRecordingResult>;
60
+ export {};
61
+ //# sourceMappingURL=microphone.d.ts.map
@@ -0,0 +1,8 @@
1
+ import { BrowserInferenceModel } from './inference';
2
+ export declare const VOICE_MODEL_ID = "redimnet-b1:e04dd7a6a1e23fc7b89e47682ea9d0a3946cf7bc59d07922c3db3efc52ae4269";
3
+ export declare const VOICE_MATCH_THRESHOLD = 0.5;
4
+ export declare const voiceModel: BrowserInferenceModel;
5
+ export declare function voiceEmbedding(samples: Float32Array): Promise<number[]>;
6
+ export declare function normalizeVoiceVector(values: readonly number[]): number[];
7
+ export declare function voiceSimilarity(left: readonly number[], right: readonly number[]): number;
8
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1,35 @@
1
+ import { BrowserInferenceModel } from './inference';
2
+ import { SPOKEN_PHRASES } from './phraseVocabulary';
3
+ export type SpokenPhrase = (typeof SPOKEN_PHRASES)[number];
4
+ export declare const phraseModel: BrowserInferenceModel;
5
+ export declare function newSpokenPhrase(previous: SpokenPhrase | null): SpokenPhrase;
6
+ type PhraseRecognition = {
7
+ kind: 'recognized';
8
+ phrase: SpokenPhrase;
9
+ difference: number;
10
+ margin: number;
11
+ decodedText: string;
12
+ } | {
13
+ kind: 'uncertain';
14
+ candidate: SpokenPhrase;
15
+ difference: number;
16
+ margin: number;
17
+ decodedText: string;
18
+ reason: 'different' | 'ambiguous' | 'negated';
19
+ } | {
20
+ kind: 'empty';
21
+ };
22
+ /** A local phrase rejection can retry while the original server challenge is valid. */
23
+ export declare class VoicePhraseMismatchError extends Error {
24
+ constructor();
25
+ }
26
+ export type PhraseCheck = {
27
+ kind: 'matched';
28
+ recognition: PhraseRecognition;
29
+ } | {
30
+ kind: 'mismatch';
31
+ recognition: PhraseRecognition;
32
+ };
33
+ export declare function checkSpokenPhrase(samples: Float32Array, expected: SpokenPhrase): Promise<PhraseCheck>;
34
+ export {};
35
+ //# sourceMappingURL=phrase.d.ts.map
@@ -0,0 +1,3 @@
1
+ export declare const SPOKEN_PHRASES: readonly ["please sign this trade now", "confirm my order for today", "i review every order carefully", "dump on them slowly", "send this order to market", "i'm here for the tech", "keep this trade on track", "the order book looks busy", "if you panic panic early", "i check the latest quote", "exit liquidity for all passengers", "no crying in the casino", "this trade fits my plan", "approve this transfer at once", "check the price before trading", "let this trade go through"];
2
+ export declare const PHRASE_TOKEN_PIECES: readonly string[];
3
+ //# sourceMappingURL=phraseVocabulary.d.ts.map
@@ -0,0 +1,2 @@
1
+ export declare function prepareVoiceModelWithProgress(parent: HTMLElement): Promise<void>;
2
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1,63 @@
1
+ import type { VoiceActivityEvent } from './microphone';
2
+ type RibbonPhase = 'idle' | 'listening' | 'processing';
3
+ /** How the line shows that the voice is being checked. */
4
+ export type VoiceCheckingStyle = 'ring' | 'segments';
5
+ /** Visual feedback from recorder activity. Never opens or retains an audio stream. */
6
+ export declare class VoiceRibbon {
7
+ private readonly checking;
8
+ readonly element: SVGSVGElement;
9
+ private readonly lines;
10
+ private readonly ripple;
11
+ private readonly track;
12
+ private readonly middle;
13
+ private readonly top;
14
+ private readonly bottom;
15
+ private readonly seal;
16
+ private readonly check;
17
+ private readonly motion;
18
+ private phase;
19
+ private stage;
20
+ private settleSuccess;
21
+ private successBegun;
22
+ private frame;
23
+ private previousTime;
24
+ private position;
25
+ private target;
26
+ private level;
27
+ private stopped;
28
+ constructor(document: Document, checking?: VoiceCheckingStyle);
29
+ readonly readLevel: () => number;
30
+ setPhase(phase: RibbonPhase): void;
31
+ /**
32
+ * Closes the ring into the success seal; resolves when the check is drawn.
33
+ * `begin` runs once the formed ring starts to close, after any capture in flight.
34
+ */
35
+ succeed(begin: () => void): Promise<void>;
36
+ add(event: VoiceActivityEvent): void;
37
+ dispose(): void;
38
+ private readonly awaitSuccess;
39
+ private settle;
40
+ private append;
41
+ private wake;
42
+ private readonly draw;
43
+ private idleAmplitude;
44
+ private paint;
45
+ private paintLine;
46
+ private paintSegments;
47
+ /** Each segment brightens one beat after the one before it, from the resting line's opacity. */
48
+ private segmentOpacity;
49
+ private paintCapture;
50
+ private paintJoin;
51
+ /** The auth menu ring's arc: it grows and shrinks on its own clock while the ring turns. */
52
+ private spinnerArc;
53
+ private beginSuccess;
54
+ private paintSuccess;
55
+ private paintSeal;
56
+ private paintArc;
57
+ private displacement;
58
+ private linePath;
59
+ /** The stroke between two distances on a half's capture track. */
60
+ private halfPath;
61
+ }
62
+ export {};
63
+ //# sourceMappingURL=ribbon.d.ts.map
@@ -0,0 +1,6 @@
1
+ import type { VoiceCaptureQuality } from './microphone';
2
+ /** Keeps a local speaker rejection retryable without changing server authorization. */
3
+ export declare class VoiceSpeakerMismatchError extends Error {
4
+ constructor(quality: VoiceCaptureQuality);
5
+ }
6
+ //# sourceMappingURL=verificationError.d.ts.map
@@ -0,0 +1,15 @@
1
+ import { BrowserInferenceModel } from './inference';
2
+ import type { InferenceSession } from 'onnxruntime-web';
3
+ export declare const voiceActivityModel: BrowserInferenceModel;
4
+ export declare function createVoiceActivity(): Promise<VoiceActivity>;
5
+ declare class VoiceActivity {
6
+ private readonly session;
7
+ private readonly ort;
8
+ private readonly state;
9
+ private readonly context;
10
+ constructor(session: InferenceSession, ort: typeof import('onnxruntime-web/wasm'));
11
+ probability(frame: Float32Array): Promise<number>;
12
+ clear(): void;
13
+ }
14
+ export {};
15
+ //# sourceMappingURL=voiceActivity.d.ts.map
@@ -0,0 +1,36 @@
1
+ import type { AuthMethodApprovalResult } from '@seams/wallet/voiceid-host';
2
+ import type { ParentToChildEnvelope } from '@seams/wallet/voiceid-host';
3
+ import { type ConfiguredWalletHost } from '@seams/wallet/voiceid-host';
4
+ import { type TransactionReviewWire } from '@seams/wallet/voiceid-host';
5
+ import type { WalletId } from '@seams/wallet/voiceid-host';
6
+ export type VoiceIdPolicy = {
7
+ readonly kind: 'disabled';
8
+ readonly approval?: never;
9
+ } | {
10
+ readonly kind: 'required';
11
+ readonly approval: VoiceIdApproval;
12
+ };
13
+ export declare function voiceIdPolicyForRequest(request: ParentToChildEnvelope, configuration: ConfiguredWalletHost): Promise<VoiceIdPolicy>;
14
+ export declare class VoiceIdApproval {
15
+ private readonly reviewExpiresAtMs;
16
+ private readonly operationHash;
17
+ private readonly walletId;
18
+ private phrase;
19
+ private readonly prompt;
20
+ readonly surface: HTMLElement;
21
+ get messages(): {
22
+ confirm: string;
23
+ approved: string;
24
+ };
25
+ private state;
26
+ private constructor();
27
+ static forReview(review: TransactionReviewWire, operationHash: string, walletId: WalletId): VoiceIdApproval;
28
+ approve(signal: AbortSignal): Promise<AuthMethodApprovalResult>;
29
+ /** Binds one listening attempt to the operation and to what remains of the review. */
30
+ private beginAttempt;
31
+ /** Resolves when the person selects Try again; rejects when the review closes or expires. */
32
+ private waitForRetry;
33
+ consume(): void;
34
+ private assertListening;
35
+ }
36
+ //# sourceMappingURL=approval.d.ts.map
@@ -0,0 +1,12 @@
1
+ import { type VoiceCaptureObserver } from '../browser/microphone';
2
+ import { type SpokenPhrase } from '../browser/phrase';
3
+ import type { AuthMethodApprovalResult } from '@seams/wallet/voiceid-host';
4
+ import type { VoiceEnrollmentScope } from '../browser/enrollmentStore';
5
+ export type VoiceBinding = Readonly<{
6
+ attemptId: string;
7
+ operationHash: string;
8
+ expiresAtMs: number;
9
+ }>;
10
+ export declare function sameVoiceBinding(left: VoiceBinding, right: VoiceBinding): boolean;
11
+ export declare function listenForVoiceApproval(scope: VoiceEnrollmentScope, binding: VoiceBinding, timeoutMs: number, signal: AbortSignal, onCapture: VoiceCaptureObserver, phrase: SpokenPhrase): Promise<AuthMethodApprovalResult>;
12
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1,29 @@
1
+ import type { VoiceCaptureObserver } from '../browser/microphone';
2
+ import { type SpokenPhrase } from '../browser/phrase';
3
+ import { type VoiceIdWalletSessionChallenge } from '@seams/wallet/voiceid-host';
4
+ import type { WalletId, WalletAuthMethodId } from '@seams/wallet/voiceid-host';
5
+ import type { VoiceIdDeviceAssertion, VoiceIdDevicePublicKeyB64u } from '@seams/wallet/voiceid-host';
6
+ import type { DigestB64u } from '@seams/wallet/voiceid-host';
7
+ export declare function captureVoiceIdActivation(input: {
8
+ readonly walletId: WalletId;
9
+ readonly walletAuthMethodId: WalletAuthMethodId;
10
+ readonly signal: AbortSignal;
11
+ readonly onCapture: VoiceCaptureObserver;
12
+ readonly phrase: SpokenPhrase;
13
+ }): Promise<{
14
+ kind: 'activated';
15
+ publicKeyB64u: VoiceIdDevicePublicKeyB64u;
16
+ deviceKeyId: DigestB64u;
17
+ factorSecret32: Uint8Array;
18
+ }>;
19
+ export declare function captureVoiceIdUnlock(input: {
20
+ readonly challenge: VoiceIdWalletSessionChallenge;
21
+ readonly signal: AbortSignal;
22
+ readonly onCapture: VoiceCaptureObserver;
23
+ readonly phrase: SpokenPhrase;
24
+ }): Promise<{
25
+ kind: 'unlocked';
26
+ assertion: VoiceIdDeviceAssertion;
27
+ factorSecret32: Uint8Array;
28
+ }>;
29
+ //# sourceMappingURL=deviceBridge.d.ts.map
@@ -0,0 +1,41 @@
1
+ import type { SpokenPhrase } from '../browser/phrase';
2
+ import type { VoiceCaptureEvent } from '../browser/microphone';
3
+ import type { VoiceCheckingStyle } from '../browser/ribbon';
4
+ export declare class VoicePrompt {
5
+ readonly element: HTMLElement;
6
+ readonly title: HTMLHeadingElement;
7
+ readonly phrase: HTMLParagraphElement;
8
+ readonly status: HTMLParagraphElement;
9
+ readonly record: HTMLButtonElement;
10
+ readonly cancel: HTMLButtonElement;
11
+ readonly progress: HTMLElement;
12
+ private readonly visual;
13
+ private disposed;
14
+ constructor(document: Document, label: string, phrase: SpokenPhrase, checking?: VoiceCheckingStyle);
15
+ setPhrase(phrase: SpokenPhrase): void;
16
+ readonly capture: (event: VoiceCaptureEvent) => void;
17
+ /** Settle the visual when an enrollment sample is accepted. */
18
+ accepted(): void;
19
+ /**
20
+ * Plays the unlock success in place and resolves when the check is drawn. Once
21
+ * the ring has formed it glides to the middle of `area` (the card by default).
22
+ */
23
+ succeed(headline: string, message: string, area?: SuccessArea): Promise<void>;
24
+ ready(message: string): void;
25
+ dispose(): void;
26
+ /** The ribbon turns into the ring and the copy may change, so the card's rows hold their size. */
27
+ private lockLayout;
28
+ /**
29
+ * The ring has formed: the reading copy fades where it is, only the ring glides
30
+ * to the middle of the free space, and the success copy arrives in place around
31
+ * it, headline first. The rows keep their locked size throughout.
32
+ */
33
+ private beginSuccess;
34
+ private unlockLayout;
35
+ }
36
+ type SuccessArea = Readonly<{
37
+ top: number;
38
+ bottom: number;
39
+ }>;
40
+ export {};
41
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1,27 @@
1
+ import type { AuthMethodCaptureMount } from '@seams/wallet/voiceid-host';
2
+ import type { UiConfirmSurfaceMeasurementBinding } from '@seams/wallet/voiceid-host';
3
+ import { type SpokenPhrase } from '../browser/phrase';
4
+ import { type VoiceCaptureObserver } from '../browser/microphone';
5
+ type CaptureAction<T> = (signal: AbortSignal, onCapture: VoiceCaptureObserver, phrase: SpokenPhrase) => Promise<T>;
6
+ type PreparedRecording<T> = Readonly<{
7
+ kind: 'recording';
8
+ action: CaptureAction<T>;
9
+ expiresAtMs: number | null;
10
+ }>;
11
+ export type PreparedVoiceCapture<T> = PreparedRecording<T> | Readonly<{
12
+ kind: 'management';
13
+ action: (signal: AbortSignal) => Promise<T>;
14
+ expiresAtMs?: never;
15
+ }>;
16
+ type CapturePreparation<T> = (signal: AbortSignal, parent: HTMLElement) => Promise<PreparedVoiceCapture<T>>;
17
+ export declare class VoiceIdCaptureCancelledError extends Error {
18
+ constructor();
19
+ }
20
+ export declare function showVoiceIdCaptureSurface<T>(input: {
21
+ readonly prepare: CapturePreparation<T>;
22
+ readonly purpose: 'activation' | 'unlock';
23
+ readonly measurement: UiConfirmSurfaceMeasurementBinding;
24
+ readonly mountCapture?: AuthMethodCaptureMount;
25
+ }): Promise<T>;
26
+ export {};
27
+ //# sourceMappingURL=surface.d.ts.map
@@ -0,0 +1,13 @@
1
+ import type { VoicePrompt } from './prompt';
2
+ export declare class VoiceUnlockFrame {
3
+ private readonly prompt;
4
+ private readonly footer;
5
+ constructor(element: HTMLElement, prompt: VoicePrompt);
6
+ /** After an unlock the back control cannot act, so it fades and the success centers under the origin. */
7
+ succeed(): Readonly<{
8
+ top: number;
9
+ bottom: number;
10
+ }>;
11
+ dispose(): void;
12
+ }
13
+ //# sourceMappingURL=unlockFrame.d.ts.map
@@ -0,0 +1,24 @@
1
+ import type { VoiceActivityEvent } from '../browser/microphone';
2
+ import { type VoiceCheckingStyle } from '../browser/ribbon';
3
+ /** Shared by enrollment, unlock and signing. The recorder remains the only audio owner. */
4
+ export declare class VoiceVisual {
5
+ readonly element: SVGSVGElement;
6
+ readonly glow: HTMLDivElement;
7
+ private readonly ribbon;
8
+ private readonly prompt;
9
+ private readonly themeObserver;
10
+ private phase;
11
+ private disposed;
12
+ constructor(document: Document, prompt: HTMLElement, checking: VoiceCheckingStyle);
13
+ listen(): void;
14
+ add(event: VoiceActivityEvent): void;
15
+ checking(): void;
16
+ accept(): void;
17
+ ready(): void;
18
+ /** The glow settles while the ribbon closes into the success seal; resolves when the check is drawn. */
19
+ succeed(begin: () => void): Promise<void>;
20
+ stop(): void;
21
+ private setPhase;
22
+ private readonly render;
23
+ }
24
+ //# sourceMappingURL=visual.d.ts.map