@sorisdk/web-audio 0.6.4 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,7 +22,7 @@ configuration, or Node-based asset server is required:
22
22
  ```html
23
23
  <script type="module">
24
24
  import { AudioRecognizer } from
25
- "https://cdn.iplateia.com/web/sorisdk/v0.6.4/sori-web-audio.mjs";
25
+ "https://cdn.iplateia.com/web/sorisdk/v0.6.7/sori-web-audio.mjs";
26
26
 
27
27
  const recognizer = new AudioRecognizer({
28
28
  appId: "YOUR_APP_ID",
@@ -49,13 +49,39 @@ configuration, or Node-based asset server is required:
49
49
  ```
50
50
 
51
51
  Static URL imports are valid inside `<script type="module">`. Dynamic
52
- `await import("https://cdn.iplateia.com/web/sorisdk/v0.6.4/sori-web-audio.mjs")`
52
+ `await import("https://cdn.iplateia.com/web/sorisdk/v0.6.7/sori-web-audio.mjs")`
53
53
  is an optional alternative when the SDK should be loaded conditionally.
54
54
 
55
55
  Pin an exact version in production. Do not construct a mutable `latest` URL.
56
56
  The module loads its versioned WASM assets and the shared
57
57
  `https://cdn.iplateia.com/web/sorisdk/model.pack` automatically.
58
58
 
59
+ The fixed model response and caller-supplied AudioPacks use the matcher's same
60
+ 64 MiB browser transport limit by default. A valid oversized `Content-Length`
61
+ is rejected before the body is consumed, and an unknown-length response is
62
+ canceled on the first chunk that crosses the limit. The response is never
63
+ truncated; failures use the deterministic
64
+ `Pack source exceeds maximum size of <limit> bytes` error.
65
+
66
+ Set an intentional shared override through the matcher options when a larger
67
+ pack is required:
68
+
69
+ ```ts
70
+ const recognizer = new AudioRecognizer({
71
+ appId: "YOUR_APP_ID",
72
+ ephemeralKey,
73
+ wasm: {
74
+ matcher: {
75
+ maxPackBytes: 96 * 1024 * 1024
76
+ }
77
+ }
78
+ });
79
+ ```
80
+
81
+ The override applies to both the standalone fixed-model response and ordinary
82
+ pack sources. A caller-supplied `embeddedPackLoader` remains a zero-argument
83
+ callback and is not replaced by the standalone loader.
84
+
59
85
  The standalone module removes the frontend build/server requirement, but it
60
86
  does not remove the trusted server requirement for ephemeral credentials.
61
87
  Provide a backend or serverless endpoint for the `ephemeralKey` callback, and
@@ -93,7 +119,7 @@ An import map can give the standalone URL the npm package name:
93
119
  <script type="importmap">
94
120
  {
95
121
  "imports": {
96
- "@sorisdk/web-audio": "https://cdn.iplateia.com/web/sorisdk/v0.6.4/sori-web-audio.mjs"
122
+ "@sorisdk/web-audio": "https://cdn.iplateia.com/web/sorisdk/v0.6.7/sori-web-audio.mjs"
97
123
  }
98
124
  }
99
125
  </script>
@@ -142,7 +168,7 @@ const recognizer = new AudioRecognizer({
142
168
  });
143
169
 
144
170
  recognizer.on("campaign", (event) => {
145
- console.log(event.campaign);
171
+ console.log(event.activityId, event.campaign);
146
172
  });
147
173
 
148
174
  recognizer.on("error", ({ error }) => {
@@ -159,6 +185,121 @@ await recognizer.stop();
159
185
  await recognizer.destroy();
160
186
  ```
161
187
 
188
+ ## Activity refinement
189
+
190
+ The default `AudioRecognizer` activity reporter represents one ordered,
191
+ continuous material segment and its later audio-marker enrichment as one
192
+ server activity:
193
+
194
+ 1. When the coordinator accepts a successful material match, it captures one
195
+ UTC RFC 3339 `recognized_at` value before any asynchronous request mapping,
196
+ header, token, or fetch work.
197
+ 2. The initial `POST /api/activity/` includes that timestamp and the exact
198
+ `DetectedMatch.position` integer in milliseconds. With valid
199
+ `matcherSegments` metadata, the position is local to the matched segment.
200
+ 3. A marker-free match with an active marker-scan request also includes
201
+ top-level `refinement_expected: true`.
202
+ 4. The returned `activity_id` is retained for 30 seconds.
203
+ 5. If the same recognition gains `audioMarker.code`, the SDK sends
204
+ `PUT /api/activity/{activity_id}` with the same material and
205
+ `trait.marker`.
206
+ 6. The refined `campaign` event keeps the same non-empty `activityId`, so an
207
+ application can replace the earlier campaign row deterministically.
208
+
209
+ A consecutive match for the same material and fingerprint type renews a local
210
+ 30-second continuity lease without another POST or campaign event. That local
211
+ lease can keep one segment alive beyond the initial server refinement window,
212
+ but it never extends the original PUT deadline. A marker confirmed anywhere
213
+ inside the segment is sticky: the first confirmation can issue at most one PUT,
214
+ and later marker misses or repeated marker evidence issue no mutation or
215
+ downgrade.
216
+
217
+ A marker present on the first match is included in the POST and does not cause
218
+ a PUT or include `refinement_expected`; that marker-first segment is still
219
+ retained for continuity. Recognition without an active marker scan, plus
220
+ legacy/custom POST-only reporters, also omit the opt-in flag. Custom reporters
221
+ enable segment coalescing only when `refinement` is enabled, preserving legacy
222
+ POST-only behavior otherwise.
223
+
224
+ A different material, an emitted `nomatch`, a gap beyond the continuity lease,
225
+ or stop, clear, destroy, authentication/capture replacement, or reset seals the
226
+ segment. Returning to A after B always creates a new A activity and can never
227
+ refine the earlier A. Marker evidence arriving after a segment is sealed is
228
+ ignored for that segment; create or PUT transport that already started may
229
+ finish under the existing capture, deadline, and cancellation guards.
230
+
231
+ Ordinary fingerprint `match` and marker-state `audiomarker` events remain
232
+ independently observable; coalescing only changes activity mutation and
233
+ campaign delivery. An `audiomarker` event alone does not mean that server
234
+ activity refinement completed.
235
+
236
+ Recognition timing belongs only to the segment's first material POST. Later
237
+ same-material observations update only the internal `lastObservedAt` lease;
238
+ they never replace the first `recognized_at` or `position`. A later marker PUT
239
+ does not include either field, and marker-only events do not create timing
240
+ metadata. `recognized_at` identifies first SDK match acceptance rather than
241
+ HTTP receipt, marker confirmation, refinement, or webhook delivery time. Do not
242
+ derive playback start as `recognized_at - position`: the match is accepted
243
+ after its query window was collected, so that calculation lacks the query
244
+ window's wall-clock anchor.
245
+
246
+ Network and 5xx PUT failures are retried at most twice within the original
247
+ 30-second deadline. Server responses 404, 409, and 410 are terminal. An
248
+ expired or failed refinement is dropped and never becomes a second POST.
249
+ Stopping, clearing, destroying, or replacing the authenticated capture clears
250
+ pending refinement identity.
251
+
252
+ Custom `activityReporter` configurations remain POST-only by default. Enable
253
+ refinement explicitly and, if needed, provide operation-specific transport or
254
+ mapping hooks:
255
+
256
+ ```ts
257
+ const recognizer = new AudioRecognizer({
258
+ appId: "YOUR_APP_ID",
259
+ ephemeralKey: fetchEphemeralKeyFromYourServer,
260
+ activityReporter: {
261
+ endpoint: "https://example.com/activity/",
262
+ refinement: {
263
+ endpoint: (activityId) =>
264
+ `https://example.com/activity/${encodeURIComponent(activityId)}`,
265
+ maxAttempts: 2,
266
+ shouldRetry: ({ status }) => status === null || status >= 500
267
+ }
268
+ }
269
+ });
270
+ ```
271
+
272
+ Existing `mapMatchToRequest` and `mapResponseToCampaign` hooks continue to
273
+ handle POST. Additive refinement hooks can override the PUT payload, response
274
+ mapping, endpoint, headers, fetcher, and retry policy. The stable terminal
275
+ statuses 404, 409, and 410 are never retried even if a custom policy returns
276
+ `true`.
277
+
278
+ `recognized_at` and `position` are optional public request properties for
279
+ source compatibility, but they are SDK-owned transport values. After a custom
280
+ POST mapper returns an eligible material payload, the SDK overwrites any
281
+ conflicting values with the captured recognition timestamp and exact matcher
282
+ position. The SDK removes both properties from all refinement PUT payloads,
283
+ including custom refinement mappings. Existing one-argument POST mappers and
284
+ POST-only transports require no signature changes. Activity responses and
285
+ `campaign` events do not gain timing properties from this request contract.
286
+
287
+ ## API endpoint normalization
288
+
289
+ `apiEndpoint` continues to accept a `string` or `URL`. When the SDK derives the
290
+ default authentication and activity URLs, it removes all trailing ASCII `/`
291
+ characters and appends `/auth` or `/activity/` with the existing URL shapes.
292
+
293
+ The endpoint is limited to `MAX_API_ENDPOINT_LENGTH` (32,768 UTF-16 code units).
294
+ The first code unit over that limit throws
295
+ `AudioRecognizer apiEndpoint exceeds maximum length of 32768 UTF-16 code units`
296
+ before trailing-slash scanning or endpoint joining. The SDK rejects the input;
297
+ it never truncates it. An explicitly supplied `apiEndpoint` is length-validated
298
+ during construction even when custom `authEndpoint` and `activityEndpoint`
299
+ values mean its prefix is not used for either join. This resource bound limits
300
+ construction work only. It is not an authentication, authorization, quota, or
301
+ abuse-prevention control.
302
+
162
303
  ## Session identifiers
163
304
 
164
305
  `AudioRecognizer` creates one pseudonymous session identifier per application
@@ -244,6 +385,21 @@ const recognizer = new AudioRecognizer({
244
385
  });
245
386
  ```
246
387
 
388
+ Advanced callers that import `@sorisdk/web-audio/generated/window.js`
389
+ directly still use `appendFingerprint(bytes: Uint8Array): void`. Each generated
390
+ window exposes `maxAppendFingerprintByteLength()`, which is the byte length of
391
+ one complete query for that instance. An append exactly at that limit is
392
+ accepted. A larger append throws a `RangeError` before the JavaScript array is
393
+ copied into WASM, with this deterministic message:
394
+
395
+ ```text
396
+ Fingerprint append byteLength <actual> exceeds the per-instance limit of <limit> bytes
397
+ ```
398
+
399
+ The high-level SDK enforces the same boundary before it invokes the generated
400
+ class. Oversized input is rejected, never truncated or split; normal microphone
401
+ fingerprint chunks and the existing match-window cadence are unchanged.
402
+
247
403
  ## Integration flow
248
404
 
249
405
  1. Prepare your `appId` and ephemeral key flow.
@@ -6,6 +6,7 @@ export class WasmFingerprintMatchWindow {
6
6
  [Symbol.dispose](): void;
7
7
  appendFingerprint(bytes: Uint8Array): void;
8
8
  hasReadyQuery(): boolean;
9
+ maxAppendFingerprintByteLength(): number;
9
10
  constructor(sample_rate: number, afpgen_config: any | null | undefined, match_window_ms: number, match_stride_ms: number);
10
11
  reset(): void;
11
12
  takeReadyQuery(): any;
@@ -13,9 +13,10 @@ export class WasmFingerprintMatchWindow {
13
13
  * @param {Uint8Array} bytes
14
14
  */
15
15
  appendFingerprint(bytes) {
16
- const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
17
- const len0 = WASM_VECTOR_LEN;
18
- wasm.wasmfingerprintmatchwindow_appendFingerprint(this.__wbg_ptr, ptr0, len0);
16
+ const ret = wasm.wasmfingerprintmatchwindow_appendFingerprint(this.__wbg_ptr, bytes);
17
+ if (ret[1]) {
18
+ throw takeFromExternrefTable0(ret[0]);
19
+ }
19
20
  }
20
21
  /**
21
22
  * @returns {boolean}
@@ -24,6 +25,13 @@ export class WasmFingerprintMatchWindow {
24
25
  const ret = wasm.wasmfingerprintmatchwindow_hasReadyQuery(this.__wbg_ptr);
25
26
  return ret !== 0;
26
27
  }
28
+ /**
29
+ * @returns {number}
30
+ */
31
+ maxAppendFingerprintByteLength() {
32
+ const ret = wasm.wasmfingerprintmatchwindow_maxAppendFingerprintByteLength(this.__wbg_ptr);
33
+ return ret >>> 0;
34
+ }
27
35
  /**
28
36
  * @param {number} sample_rate
29
37
  * @param {any | null | undefined} afpgen_config
@@ -47,7 +55,10 @@ export class WasmFingerprintMatchWindow {
47
55
  */
48
56
  takeReadyQuery() {
49
57
  const ret = wasm.wasmfingerprintmatchwindow_takeReadyQuery(this.__wbg_ptr);
50
- return ret;
58
+ if (ret[2]) {
59
+ throw takeFromExternrefTable0(ret[1]);
60
+ }
61
+ return takeFromExternrefTable0(ret[0]);
51
62
  }
52
63
  }
53
64
  if (Symbol.dispose) WasmFingerprintMatchWindow.prototype[Symbol.dispose] = WasmFingerprintMatchWindow.prototype.free;
@@ -82,6 +93,10 @@ export function __wbg___wbindgen_in_a5d8b22e52b24dd1(arg0, arg1) {
82
93
  const ret = arg0 in arg1;
83
94
  return ret;
84
95
  }
96
+ export function __wbg___wbindgen_is_function_3baa9db1a987f47d(arg0) {
97
+ const ret = typeof(arg0) === 'function';
98
+ return ret;
99
+ }
85
100
  export function __wbg___wbindgen_is_null_52ff4ec04186736f(arg0) {
86
101
  const ret = arg0 === null;
87
102
  return ret;
@@ -116,6 +131,26 @@ export function __wbg___wbindgen_string_get_7ed5322991caaec5(arg0, arg1) {
116
131
  export function __wbg___wbindgen_throw_6b64449b9b9ed33c(arg0, arg1) {
117
132
  throw new Error(getStringFromWasm0(arg0, arg1));
118
133
  }
134
+ export function __wbg_call_14b169f759b26747() { return handleError(function (arg0, arg1) {
135
+ const ret = arg0.call(arg1);
136
+ return ret;
137
+ }, arguments); }
138
+ export function __wbg_call_a24592a6f349a97e() { return handleError(function (arg0, arg1, arg2) {
139
+ const ret = arg0.call(arg1, arg2);
140
+ return ret;
141
+ }, arguments); }
142
+ export function __wbg_getOwnPropertyDescriptor_131bd582a45a6f5d(arg0, arg1) {
143
+ const ret = Object.getOwnPropertyDescriptor(arg0, arg1);
144
+ return ret;
145
+ }
146
+ export function __wbg_getPrototypeOf_a56da9261bbd1e5b(arg0) {
147
+ const ret = Object.getPrototypeOf(arg0);
148
+ return ret;
149
+ }
150
+ export function __wbg_get_6011fa3a58f61074() { return handleError(function (arg0, arg1) {
151
+ const ret = Reflect.get(arg0, arg1);
152
+ return ret;
153
+ }, arguments); }
119
154
  export function __wbg_get_with_ref_key_6412cf3094599694(arg0, arg1) {
120
155
  const ret = arg0[arg1];
121
156
  return ret;
@@ -152,6 +187,10 @@ export function __wbg_new_0c7403db6e782f19(arg0) {
152
187
  const ret = new Uint8Array(arg0);
153
188
  return ret;
154
189
  }
190
+ export function __wbg_new_191521fecb171639(arg0, arg1) {
191
+ const ret = new RangeError(getStringFromWasm0(arg0, arg1));
192
+ return ret;
193
+ }
155
194
  export function __wbg_new_from_slice_b5ea43e23f6008c0(arg0, arg1) {
156
195
  const ret = new Uint8Array(getArrayU8FromWasm0(arg0, arg1));
157
196
  return ret;
@@ -159,7 +198,28 @@ export function __wbg_new_from_slice_b5ea43e23f6008c0(arg0, arg1) {
159
198
  export function __wbg_prototypesetcall_a6b02eb00b0f4ce2(arg0, arg1, arg2) {
160
199
  Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
161
200
  }
201
+ export function __wbg_static_accessor_GLOBAL_8cfadc87a297ca02() {
202
+ const ret = typeof global === 'undefined' ? null : global;
203
+ return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
204
+ }
205
+ export function __wbg_static_accessor_GLOBAL_THIS_602256ae5c8f42cf() {
206
+ const ret = typeof globalThis === 'undefined' ? null : globalThis;
207
+ return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
208
+ }
209
+ export function __wbg_static_accessor_SELF_e445c1c7484aecc3() {
210
+ const ret = typeof self === 'undefined' ? null : self;
211
+ return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
212
+ }
213
+ export function __wbg_static_accessor_WINDOW_f20e8576ef1e0f17() {
214
+ const ret = typeof window === 'undefined' ? null : window;
215
+ return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
216
+ }
162
217
  export function __wbindgen_cast_0000000000000001(arg0, arg1) {
218
+ // Cast intrinsic for `Ref(Slice(U8)) -> NamedExternref("Uint8Array")`.
219
+ const ret = getArrayU8FromWasm0(arg0, arg1);
220
+ return ret;
221
+ }
222
+ export function __wbindgen_cast_0000000000000002(arg0, arg1) {
163
223
  // Cast intrinsic for `Ref(String) -> Externref`.
164
224
  const ret = getStringFromWasm0(arg0, arg1);
165
225
  return ret;
@@ -274,15 +334,17 @@ function getUint8ArrayMemory0() {
274
334
  return cachedUint8ArrayMemory0;
275
335
  }
276
336
 
277
- function isLikeNone(x) {
278
- return x === undefined || x === null;
337
+ function handleError(f, args) {
338
+ try {
339
+ return f.apply(this, args);
340
+ } catch (e) {
341
+ const idx = addToExternrefTable0(e);
342
+ wasm.__wbindgen_exn_store(idx);
343
+ }
279
344
  }
280
345
 
281
- function passArray8ToWasm0(arg, malloc) {
282
- const ptr = malloc(arg.length * 1, 1) >>> 0;
283
- getUint8ArrayMemory0().set(arg, ptr / 1);
284
- WASM_VECTOR_LEN = arg.length;
285
- return ptr;
346
+ function isLikeNone(x) {
347
+ return x === undefined || x === null;
286
348
  }
287
349
 
288
350
  function passStringToWasm0(arg, malloc, realloc) {
Binary file
@@ -2,14 +2,16 @@
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
4
  export const __wbg_wasmfingerprintmatchwindow_free: (a: number, b: number) => void;
5
- export const wasmfingerprintmatchwindow_appendFingerprint: (a: number, b: number, c: number) => void;
5
+ export const wasmfingerprintmatchwindow_appendFingerprint: (a: number, b: any) => [number, number];
6
6
  export const wasmfingerprintmatchwindow_hasReadyQuery: (a: number) => number;
7
+ export const wasmfingerprintmatchwindow_maxAppendFingerprintByteLength: (a: number) => number;
7
8
  export const wasmfingerprintmatchwindow_new: (a: number, b: number, c: number, d: number) => [number, number, number];
8
9
  export const wasmfingerprintmatchwindow_reset: (a: number) => void;
9
- export const wasmfingerprintmatchwindow_takeReadyQuery: (a: number) => any;
10
+ export const wasmfingerprintmatchwindow_takeReadyQuery: (a: number) => [number, number, number];
10
11
  export const __wbindgen_malloc: (a: number, b: number) => number;
11
12
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
12
- export const __wbindgen_externrefs: WebAssembly.Table;
13
+ export const __wbindgen_exn_store: (a: number) => void;
13
14
  export const __externref_table_alloc: () => number;
15
+ export const __wbindgen_externrefs: WebAssembly.Table;
14
16
  export const __externref_table_dealloc: (a: number) => void;
15
17
  export const __wbindgen_start: () => void;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { MatcherEphemeralAuthOptions, InitMatcherOptions, MatcherEphemeralAuthResult, AudioMarkerDetection, PackSource, MatchResult, AudioFingerprintType } from '@sorisdk/matcher';
1
+ import { MatcherEphemeralAuthOptions, InitMatcherOptions, MatcherEphemeralAuthResult, AudioMarkerDetection, PackSource, MatchResult, MatcherSessionOptions, AudioFingerprintType } from '@sorisdk/matcher';
2
2
  export { AudioFingerprintType, AudioMarkerConfig, AudioMarkerDetection, PackSource } from '@sorisdk/matcher';
3
3
  import { InitAfpgenOptions } from '@sorisdk/afpgen';
4
4
 
@@ -62,6 +62,15 @@ interface AudioMarkerEvent {
62
62
  interface MaterialActivityRequestPayload {
63
63
  type: "material";
64
64
  material_id: string;
65
+ /** SDK-owned UTC recognition timestamp. Custom mapper values are overwritten on POST. */
66
+ recognized_at?: string;
67
+ /** SDK-owned matcher position in milliseconds. Custom mapper values are overwritten on POST. */
68
+ position?: number;
69
+ refinement_expected?: true;
70
+ trait?: {
71
+ marker?: string;
72
+ [key: string]: unknown;
73
+ };
65
74
  metadata?: unknown;
66
75
  }
67
76
  interface MicrophoneMatcherCampaignEvent {
@@ -70,6 +79,27 @@ interface MicrophoneMatcherCampaignEvent {
70
79
  activityId: string | null;
71
80
  raw: Record<string, unknown>;
72
81
  }
82
+ interface ActivityRefinementRequestContext {
83
+ operation: "refine";
84
+ activityId: string;
85
+ attempt: number;
86
+ deadline: number;
87
+ }
88
+ interface ActivityRefinementFailureContext extends ActivityRefinementRequestContext {
89
+ error: Error;
90
+ status: number | null;
91
+ detail: string | null;
92
+ }
93
+ interface MicrophoneMatcherActivityRefinementOptions {
94
+ endpoint?: string | URL | ((activityId: string) => string | URL | Promise<string | URL>);
95
+ fetch?: typeof fetch;
96
+ headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
97
+ mapMatchToRequest?: (match: DetectedMatch, context: ActivityRefinementRequestContext) => MaterialActivityRequestPayload | null | Promise<MaterialActivityRequestPayload | null>;
98
+ mapResponseToCampaign?: (response: Record<string, unknown>, match: DetectedMatch, context: ActivityRefinementRequestContext) => MicrophoneMatcherCampaignEvent | null | Promise<MicrophoneMatcherCampaignEvent | null>;
99
+ shouldRetry?: (context: ActivityRefinementFailureContext) => boolean | Promise<boolean>;
100
+ maxAttempts?: number;
101
+ now?: () => number;
102
+ }
73
103
  interface MicrophoneMatcherActivityReporterOptions {
74
104
  endpoint: string | URL;
75
105
  token: string | (() => string | Promise<string>);
@@ -77,10 +107,11 @@ interface MicrophoneMatcherActivityReporterOptions {
77
107
  headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
78
108
  mapMatchToRequest?: (match: DetectedMatch) => MaterialActivityRequestPayload | null | Promise<MaterialActivityRequestPayload | null>;
79
109
  mapResponseToCampaign?: (response: Record<string, unknown>, match: DetectedMatch) => MicrophoneMatcherCampaignEvent | null | Promise<MicrophoneMatcherCampaignEvent | null>;
110
+ refinement?: false | MicrophoneMatcherActivityRefinementOptions;
80
111
  }
81
112
  interface CreateMicrophoneMatcherWasmOptions {
82
113
  afpgen?: InitAfpgenOptions;
83
- matcher?: Omit<InitMatcherOptions, "auth">;
114
+ matcher?: Omit<MatcherSessionOptions, "auth">;
84
115
  matchWindow?: InitMatchWindowWasmOptions;
85
116
  }
86
117
  interface CreateMicrophoneMatcherOptions {
@@ -120,6 +151,7 @@ type MicrophoneMatcherListener<T extends MicrophoneMatcherEventName> = (payload:
120
151
  type Awaitable<T> = T | Promise<T>;
121
152
  type AudioRecognizerMatcherOptions = Omit<CreateMicrophoneMatcherOptions, "activityReporter" | "packSource">;
122
153
  declare const DEFAULT_SORI_API_ENDPOINT = "https://console.soriapi.com/api";
154
+ declare const MAX_API_ENDPOINT_LENGTH: number;
123
155
  interface AudioRecognizerAuthOptions {
124
156
  endpoint: string | URL;
125
157
  appId: string;
@@ -182,6 +214,8 @@ declare class AudioRecognizer {
182
214
  private setAuthResult;
183
215
  }
184
216
 
217
+ declare const ACTIVITY_REFINEMENT_WINDOW_MS = 30000;
218
+
185
219
  declare class MicrophoneMatcher {
186
220
  private readonly events;
187
221
  private readonly matcherSession;
@@ -193,6 +227,7 @@ declare class MicrophoneMatcher {
193
227
  private readonly captureSampleRate;
194
228
  private readonly audioGraphFactory;
195
229
  private readonly packSource;
230
+ private readonly activityRefinement;
196
231
  private readonly options;
197
232
  private extractor;
198
233
  private graphController;
@@ -211,6 +246,7 @@ declare class MicrophoneMatcher {
211
246
  private latestAudioMarker;
212
247
  private latestAudioMarkerDetection;
213
248
  private audioMarkerRequestId;
249
+ private activityRecognitionId;
214
250
  private hopSize;
215
251
  private diagnostics;
216
252
  constructor(options: CreateMicrophoneMatcherOptions);
@@ -260,4 +296,4 @@ declare function requestMicrophoneStream(mediaDevices: MediaDevices, mediaConstr
260
296
  preferredSampleRate?: number;
261
297
  }): Promise<MediaStream>;
262
298
 
263
- export { type AudioMarkerEvent, AudioRecognizer, type AudioRecognizerAuthOptions, type AudioRecognizerOptions, type AuthenticateAndLoadAudioPackOptions, type AuthenticateAndLoadAudioPackResult, type BrowserAudioPackLoader, type BrowserAudioPackState, type BrowserAudioPackStateStore, type BrowserSessionManager, type CreateLocalStorageAudioPackStoreOptions, type CreateLocalStorageSessionManagerOptions, type CreateMicrophoneMatcherOptions, type CreateMicrophoneMatcherWasmOptions, DEFAULT_BROWSER_AUDIOPACK_VERSION, DEFAULT_SORI_API_ENDPOINT, type DetectedMatch, type MaterialActivityRequestPayload, MicrophoneMatcher, type MicrophoneMatcherActivityReporterOptions, type MicrophoneMatcherCampaignEvent, type MicrophoneMatcherEventMap, type MicrophoneMatcherEventName, type MicrophoneMatcherListener, authenticateAndLoadAudioPack, createLocalStorageAudioPackStore, createLocalStorageSessionManager, createMicrophoneMatcher, requestMicrophoneStream };
299
+ export { ACTIVITY_REFINEMENT_WINDOW_MS, type ActivityRefinementFailureContext, type ActivityRefinementRequestContext, type AudioMarkerEvent, AudioRecognizer, type AudioRecognizerAuthOptions, type AudioRecognizerOptions, type AuthenticateAndLoadAudioPackOptions, type AuthenticateAndLoadAudioPackResult, type BrowserAudioPackLoader, type BrowserAudioPackState, type BrowserAudioPackStateStore, type BrowserSessionManager, type CreateLocalStorageAudioPackStoreOptions, type CreateLocalStorageSessionManagerOptions, type CreateMicrophoneMatcherOptions, type CreateMicrophoneMatcherWasmOptions, DEFAULT_BROWSER_AUDIOPACK_VERSION, DEFAULT_SORI_API_ENDPOINT, type DetectedMatch, MAX_API_ENDPOINT_LENGTH, type MaterialActivityRequestPayload, MicrophoneMatcher, type MicrophoneMatcherActivityRefinementOptions, type MicrophoneMatcherActivityReporterOptions, type MicrophoneMatcherCampaignEvent, type MicrophoneMatcherEventMap, type MicrophoneMatcherEventName, type MicrophoneMatcherListener, authenticateAndLoadAudioPack, createLocalStorageAudioPackStore, createLocalStorageSessionManager, createMicrophoneMatcher, requestMicrophoneStream };