@monitordog/detector 1.0.10 → 1.0.12

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.
@@ -39,11 +39,11 @@ function u() {
39
39
  function d(e) {
40
40
  return e === "auto" || e === 320 || e === 416 || e === 640;
41
41
  }
42
- function f(e, t) {
42
+ function ee(e, t) {
43
43
  let n = e ?? "auto";
44
44
  return n === "auto" ? t ? 416 : 640 : n;
45
45
  }
46
- function p(e) {
46
+ function f(e) {
47
47
  if (e === void 0) return;
48
48
  let t = e.trim();
49
49
  if (t.length === 0) throw Error("MonitorDog runtimeAssetBaseUrl must be a non-empty string when provided.");
@@ -52,36 +52,36 @@ function p(e) {
52
52
  }
53
53
  //#endregion
54
54
  //#region src/sdk-error.ts
55
- var m = class extends Error {
55
+ var p = class extends Error {
56
56
  code;
57
57
  cause;
58
58
  constructor(e, t, n) {
59
59
  super(t), this.name = "MonitorDogSdkError", this.code = e, this.cause = n;
60
60
  }
61
61
  };
62
- function h(e) {
63
- return e instanceof m;
62
+ function m(e) {
63
+ return e instanceof p;
64
64
  }
65
65
  //#endregion
66
66
  //#region src/events.ts
67
- function ee(e) {
68
- if (e.faceCount === 0) return _("noFaceDetected", e);
69
- if (e.faceCount >= 2) return _("twoFacesDetected", e);
70
- if (e.phoneCount >= 1) return _("mobileDevice", e);
67
+ function h(e) {
68
+ if (e.faceCount === 0) return v("noFaceDetected", e);
69
+ if (e.faceCount >= 2) return v("twoFacesDetected", e);
70
+ if (e.phoneCount >= 1) return v("mobileDevice", e);
71
71
  }
72
- function te(e) {
72
+ function g(e) {
73
73
  return {
74
- ...v(e, (/* @__PURE__ */ new Date()).toISOString()),
74
+ ...y(e, (/* @__PURE__ */ new Date()).toISOString()),
75
75
  properties: {},
76
76
  webcam_imgs: [],
77
77
  monitor_imgs: []
78
78
  };
79
79
  }
80
- function g(e) {
80
+ function _(e) {
81
81
  return e.phoneCount === 0 && e.faceCount === 1;
82
82
  }
83
- function _(e, t) {
84
- let n = v(e, (/* @__PURE__ */ new Date()).toISOString());
83
+ function v(e, t) {
84
+ let n = y(e, (/* @__PURE__ */ new Date()).toISOString());
85
85
  switch (e) {
86
86
  case "noFaceDetected": return {
87
87
  type: e,
@@ -98,7 +98,7 @@ function _(e, t) {
98
98
  payload: {
99
99
  ...n,
100
100
  properties: {
101
- confidence: y(t.faceDetections),
101
+ confidence: b(t.faceDetections),
102
102
  spots: t.faceDetections
103
103
  }
104
104
  }
@@ -108,16 +108,16 @@ function _(e, t) {
108
108
  payload: {
109
109
  ...n,
110
110
  properties: {
111
- confidence: y(t.phoneDetections),
111
+ confidence: b(t.phoneDetections),
112
112
  spots: t.phoneDetections
113
113
  }
114
114
  }
115
115
  };
116
116
  }
117
117
  }
118
- function v(e, t) {
118
+ function y(e, t) {
119
119
  return {
120
- basic_event_uuid: b(e),
120
+ basic_event_uuid: x(e),
121
121
  occured_at: t,
122
122
  sended_at: (/* @__PURE__ */ new Date()).toISOString(),
123
123
  device_type: l(),
@@ -125,10 +125,10 @@ function v(e, t) {
125
125
  device_id: "browser"
126
126
  };
127
127
  }
128
- function y(e) {
128
+ function b(e) {
129
129
  return e.reduce((e, t) => Math.max(e, t.score), 0);
130
130
  }
131
- function b(e) {
131
+ function x(e) {
132
132
  switch (e) {
133
133
  case "logout": return "12ca646a-d832-4581-b03c-48f95627507f";
134
134
  case "login": return "4c6f98ea-88d8-4215-9b6a-9b3ccb753465";
@@ -140,9 +140,9 @@ function b(e) {
140
140
  }
141
141
  //#endregion
142
142
  //#region src/service/auth-service.ts
143
- var x = "MonitorDog token refresh was superseded.", S = 300 * 1e3, C = class {
143
+ var S = "MonitorDog token refresh was superseded.", C = 300 * 1e3, w = class {
144
144
  services;
145
- refreshBeforeMs = S;
145
+ refreshBeforeMs = C;
146
146
  periodicRefreshIntervalMs = r;
147
147
  token;
148
148
  tokenExpiresAt;
@@ -236,7 +236,7 @@ var x = "MonitorDog token refresh was superseded.", S = 300 * 1e3, C = class {
236
236
  if (!t) throw Error("MonitorDog login email is required to refresh SDK token.");
237
237
  let n = await this.fetchSessionToken(t), r = i(n);
238
238
  if (!r || typeof r != "string") throw Error("MonitorDog SDK token response did not include a token.");
239
- if (e !== this.authSessionId) throw Error(x);
239
+ if (e !== this.authSessionId) throw Error(S);
240
240
  return this.setSessionTokenPayload(n), r;
241
241
  }
242
242
  startPeriodicRefresh() {
@@ -259,7 +259,7 @@ var x = "MonitorDog token refresh was superseded.", S = 300 * 1e3, C = class {
259
259
  return !!(this.tokenExpiresAt && Date.now() >= this.tokenExpiresAt);
260
260
  }
261
261
  isRefreshSupersededError(e) {
262
- return e instanceof Error && e.message === x;
262
+ return e instanceof Error && e.message === S;
263
263
  }
264
264
  async fetchSessionToken(e) {
265
265
  let t = this.services.options.sessionTokenProvider;
@@ -287,24 +287,24 @@ var x = "MonitorDog token refresh was superseded.", S = 300 * 1e3, C = class {
287
287
  let t = await this.authorizedFetch("/event", {
288
288
  method: "POST",
289
289
  headers: { "content-type": "application/json" },
290
- body: JSON.stringify(te(e))
290
+ body: JSON.stringify(g(e))
291
291
  });
292
292
  if (!t.ok) throw Error(`MonitorDog ${e} event failed: ${t.status}`);
293
293
  } catch (t) {
294
- let n = this.createSdkError(w(e), `MonitorDog ${e} event failed.`, t);
294
+ let n = this.createSdkError(T(e), `MonitorDog ${e} event failed.`, t);
295
295
  if (this.services.options.onAuthError?.(n), e === "logout") throw n;
296
296
  }
297
297
  }
298
298
  createSdkError(e, t, n) {
299
- return n instanceof m ? n : new m(e, t, n);
299
+ return n instanceof p ? n : new p(e, t, n);
300
300
  }
301
301
  };
302
- function w(e) {
302
+ function T(e) {
303
303
  return e === "logout" ? "LOGOUT_FAILED" : "SESSION_TOKEN_FAILED";
304
304
  }
305
305
  //#endregion
306
306
  //#region src/service/camera-service.ts
307
- var T = /(obs|virtual|xsplit|manycam|splitcam|webcammax|fake|loopback|camtwist|e2esoft|vcam|droidcam|iriun|epoccam|camo|mmhmm|nvidia broadcast|streamlabs|bandicam|wirecast|chromacam|youcam|cyberlink|altserver|logi capture|elgato|streamfx|screen capture|desktop capture)/i, E = class {
307
+ var E = /(obs|virtual|xsplit|manycam|splitcam|webcammax|fake|loopback|camtwist|e2esoft|vcam|droidcam|iriun|epoccam|camo|mmhmm|nvidia broadcast|streamlabs|bandicam|wirecast|chromacam|youcam|cyberlink|altserver|logi capture|elgato|streamfx|screen capture|desktop capture)/i, te = class {
308
308
  async createWebcamStream(e) {
309
309
  if (!navigator.mediaDevices?.getUserMedia) throw Error("getUserMedia is not available in this browser.");
310
310
  let t = this.getBaseWebcamConstraints(e), n = await this.createFirstCameraConstraints(t);
@@ -423,7 +423,7 @@ var T = /(obs|virtual|xsplit|manycam|splitcam|webcammax|fake|loopback|camtwist|e
423
423
  }
424
424
  isVirtualCamera(e) {
425
425
  let t = e.label.toLowerCase();
426
- return t ? T.test(t) : !1;
426
+ return t ? E.test(t) : !1;
427
427
  }
428
428
  isPermissionError(e) {
429
429
  return e instanceof DOMException && (e.name === "NotAllowedError" || e.name === "SecurityError");
@@ -447,7 +447,7 @@ var T = /(obs|virtual|xsplit|manycam|splitcam|webcammax|fake|loopback|camtwist|e
447
447
  };
448
448
  //#endregion
449
449
  //#region src/capture.ts
450
- function D(e) {
450
+ function ne(e) {
451
451
  if (e.videoWidth === 0 || e.videoHeight === 0) throw Error("Video frame is not ready for capture.");
452
452
  let t = document.createElement("canvas"), n = t.getContext("2d");
453
453
  if (!n) throw Error("2D canvas context is not available.");
@@ -461,7 +461,7 @@ function D(e) {
461
461
  }, "image/jpeg", .9);
462
462
  });
463
463
  }
464
- async function O() {
464
+ async function re() {
465
465
  if (typeof document > "u" || !document.body) return null;
466
466
  let t = await e(document.body, {
467
467
  backgroundColor: "#ffffff",
@@ -473,7 +473,7 @@ async function O() {
473
473
  }
474
474
  //#endregion
475
475
  //#region src/service/detection-event-service.ts
476
- var ne = class e {
476
+ var ie = class e {
477
477
  static NO_FACE_STARTUP_GRACE_MS = 1500;
478
478
  services;
479
479
  detectionEventLocked = !1;
@@ -489,12 +489,12 @@ var ne = class e {
489
489
  this.reset();
490
490
  return;
491
491
  }
492
- if (g(e)) {
492
+ if (_(e)) {
493
493
  this.noFaceStartedAt = void 0, this.clearLock();
494
494
  return;
495
495
  }
496
496
  if (this.detectionEventLocked || this.detectionEventInFlight) return;
497
- let n = ee(e);
497
+ let n = h(e);
498
498
  if (!n) {
499
499
  this.noFaceStartedAt = void 0;
500
500
  return;
@@ -531,11 +531,11 @@ var ne = class e {
531
531
  }
532
532
  async uploadWebcamImage(e) {
533
533
  if (!(e instanceof HTMLVideoElement) || e.videoWidth === 0 || e.videoHeight === 0) return;
534
- let t = await D(e);
534
+ let t = await ne(e);
535
535
  return this.uploadImage(t, "webcam.jpg");
536
536
  }
537
537
  async uploadMonitorImage() {
538
- let e = this.services.options.captureMonitorImage ? await this.services.options.captureMonitorImage() : await O();
538
+ let e = this.services.options.captureMonitorImage ? await this.services.options.captureMonitorImage() : await re();
539
539
  if (!e) return;
540
540
  let t = typeof File < "u" && e instanceof File ? e.name : "monitor.jpg";
541
541
  return this.uploadImage(e, t);
@@ -552,8 +552,8 @@ var ne = class e {
552
552
  }
553
553
  shouldSendEvent(e, t) {
554
554
  switch (e) {
555
- case "mobileDevice": return this.services.userPreferences.mobileDetectionEnabled && k(t.phoneDetections) >= this.services.options.confidenceThreshold;
556
- case "twoFacesDetected": return this.services.userPreferences.multiPersonDetectionEnabled && k(t.faceDetections) >= this.services.userPreferences.faceDetectionThreshold;
555
+ case "mobileDevice": return this.services.userPreferences.mobileDetectionEnabled && D(t.phoneDetections) >= this.services.options.confidenceThreshold;
556
+ case "twoFacesDetected": return this.services.userPreferences.multiPersonDetectionEnabled && D(t.faceDetections) >= this.services.userPreferences.faceDetectionThreshold;
557
557
  case "noFaceDetected": return this.services.userPreferences.noPersonDetectionEnabled;
558
558
  }
559
559
  }
@@ -585,12 +585,12 @@ var ne = class e {
585
585
  }
586
586
  }
587
587
  };
588
- function k(e) {
588
+ function D(e) {
589
589
  return e.reduce((e, t) => Math.max(e, t.score), 0);
590
590
  }
591
591
  //#endregion
592
592
  //#region src/detect/inference-worker.ts?worker&url
593
- var A = "" + new URL("assets/inference-worker-BTPzhc2n.js", import.meta.url).href, j = class {
593
+ var ae = "" + new URL("assets/inference-worker-GKAp-Pp3.js", import.meta.url).href, O = class {
594
594
  worker;
595
595
  nextRequestId = 1;
596
596
  pendingRequests = /* @__PURE__ */ new Map();
@@ -633,7 +633,7 @@ var A = "" + new URL("assets/inference-worker-BTPzhc2n.js", import.meta.url).hre
633
633
  });
634
634
  }
635
635
  getWorker() {
636
- return this.worker || (this.worker = new Worker(A, {
636
+ return this.worker || (this.worker = new Worker(ae, {
637
637
  name: "MonitorDogInference",
638
638
  type: "module"
639
639
  }), this.worker.addEventListener("message", this.handleMessage), this.worker.addEventListener("error", this.handleError), this.worker.addEventListener("messageerror", this.handleError)), this.worker;
@@ -659,15 +659,15 @@ var A = "" + new URL("assets/inference-worker-BTPzhc2n.js", import.meta.url).hre
659
659
  };
660
660
  //#endregion
661
661
  //#region src/detect/preprocess.ts
662
- async function M(e) {
663
- let { sourceWidth: t, sourceHeight: n } = N(e);
662
+ async function k(e) {
663
+ let { sourceWidth: t, sourceHeight: n } = A(e);
664
664
  if (e instanceof ImageData) return {
665
665
  kind: "rgba",
666
666
  data: new Uint8ClampedArray(e.data),
667
667
  sourceWidth: t,
668
668
  sourceHeight: n
669
669
  };
670
- if (P() && F()) try {
670
+ if (j() && M()) try {
671
671
  return {
672
672
  kind: "bitmap",
673
673
  bitmap: await createImageBitmap(e),
@@ -675,9 +675,9 @@ async function M(e) {
675
675
  sourceHeight: n
676
676
  };
677
677
  } catch {}
678
- return I(e, t, n);
678
+ return N(e, t, n);
679
679
  }
680
- function N(e) {
680
+ function A(e) {
681
681
  return e instanceof ImageData ? {
682
682
  sourceWidth: e.width,
683
683
  sourceHeight: e.height
@@ -692,13 +692,13 @@ function N(e) {
692
692
  sourceHeight: e.height
693
693
  };
694
694
  }
695
- function P() {
695
+ function j() {
696
696
  return typeof createImageBitmap == "function";
697
697
  }
698
- function F() {
698
+ function M() {
699
699
  return typeof OffscreenCanvas == "function";
700
700
  }
701
- function I(e, t, n) {
701
+ function N(e, t, n) {
702
702
  let r = document.createElement("canvas"), i = r.getContext("2d");
703
703
  if (!i) throw Error("2D canvas context is not available.");
704
704
  return r.width = t, r.height = n, i.drawImage(e, 0, 0, t, n), {
@@ -710,43 +710,65 @@ function I(e, t, n) {
710
710
  }
711
711
  //#endregion
712
712
  //#region src/detect/rotation-fallback.ts
713
- function L(e, t, n) {
714
- return e.map((e) => z(e, t, n));
713
+ function P(e, t, n) {
714
+ return e.map((e) => L(e, t, n));
715
+ }
716
+ function F(e, t, n) {
717
+ return e.map((e) => L(e, t, n));
715
718
  }
716
- function R(e, t, n, r) {
717
- if (e.phoneDetected || t.phoneDetections.length === 0) return e;
718
- let i = L(t.phoneDetections, n, r);
719
+ function I(e, t, n, r) {
720
+ if (e.phoneDetected) return e;
721
+ let i = [...e.phoneCandidates, ...F(t.phoneCandidates, n, r)];
722
+ if (t.phoneDetections.length === 0) return i.length === e.phoneCandidates.length ? e : {
723
+ ...e,
724
+ phoneCandidates: i
725
+ };
726
+ let a = P(t.phoneDetections, n, r);
719
727
  return {
720
728
  ...e,
721
- phoneDetected: i.length > 0,
722
- phoneCount: i.length,
723
- phoneDetections: i
729
+ phoneDetected: a.length > 0,
730
+ phoneCount: a.length,
731
+ phoneDetections: a,
732
+ phoneCandidates: i
724
733
  };
725
734
  }
726
- function z(e, t, n) {
735
+ function L(e, t, n) {
727
736
  return {
728
737
  ...e,
729
- x: B(t - (e.x + e.width), 0, t),
730
- y: B(n - (e.y + e.height), 0, n)
738
+ x: R(t - (e.x + e.width), 0, t),
739
+ y: R(n - (e.y + e.height), 0, n)
731
740
  };
732
741
  }
733
- function B(e, t, n) {
742
+ function R(e, t, n) {
734
743
  return Math.min(Math.max(e, t), n);
735
744
  }
736
745
  //#endregion
746
+ //#region src/runtime-assets.ts
747
+ var z = {
748
+ sdk: {
749
+ "detector-320.onnx.enc": new URL("./assets/sdk/detector-320.onnx.enc", import.meta.url).href,
750
+ "detector-416.onnx.enc": new URL("./assets/sdk/detector-416.onnx.enc", import.meta.url).href,
751
+ "detector-640.onnx.enc": new URL("./assets/sdk/detector-640.onnx.enc", import.meta.url).href
752
+ },
753
+ ort: {
754
+ mjs: new URL("./assets/ort/ort-wasm-simd-threaded.mjs", import.meta.url).href,
755
+ wasm: new URL("./assets/ort/ort-wasm-simd-threaded.wasm", import.meta.url).href
756
+ }
757
+ };
758
+ //#endregion
737
759
  //#region src/video.ts
738
- function V(e) {
760
+ function B(e) {
739
761
  return e.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA && e.videoWidth > 0 && e.videoHeight > 0 && !e.paused && !e.ended;
740
762
  }
741
- function H(e, t = 1e4) {
742
- return U(e) ? Promise.resolve() : new Promise((n, r) => {
763
+ function V(e, t = 1e4) {
764
+ return H(e) ? Promise.resolve() : new Promise((n, r) => {
743
765
  let i = window.setTimeout(() => {
744
766
  o(), r(/* @__PURE__ */ Error("Timed out waiting for webcam video metadata."));
745
767
  }, t), a = window.setInterval(s, 100), o = () => {
746
768
  window.clearTimeout(i), window.clearInterval(a), e.removeEventListener("loadedmetadata", c), e.removeEventListener("loadeddata", c), e.removeEventListener("canplay", c), e.removeEventListener("playing", c), e.removeEventListener("resize", c), e.removeEventListener("error", l);
747
769
  };
748
770
  function s() {
749
- U(e) && (o(), n());
771
+ H(e) && (o(), n());
750
772
  }
751
773
  let c = () => {
752
774
  s();
@@ -756,18 +778,19 @@ function H(e, t = 1e4) {
756
778
  e.addEventListener("loadedmetadata", c, { once: !0 }), e.addEventListener("loadeddata", c, { once: !0 }), e.addEventListener("canplay", c, { once: !0 }), e.addEventListener("playing", c, { once: !0 }), e.addEventListener("resize", c, { once: !0 }), e.addEventListener("error", l, { once: !0 });
757
779
  });
758
780
  }
759
- function U(e) {
781
+ function H(e) {
760
782
  return e.readyState >= HTMLMediaElement.HAVE_METADATA && e.videoWidth > 0 && e.videoHeight > 0;
761
783
  }
762
784
  //#endregion
763
785
  //#region src/service/detect-service.ts
764
- var W = class {
786
+ var U = 700, oe = .25, W = .8, G = class {
765
787
  services;
766
788
  primaryInferenceWorker;
767
789
  rotationInferenceWorker;
768
790
  loadPromise;
769
791
  lastInferenceMemoryErrorAt = 0;
770
792
  lastParallelPhoneRotationFallbackAt = -Infinity;
793
+ phoneCandidateHistory = [];
771
794
  constructor(e) {
772
795
  this.services = e;
773
796
  }
@@ -778,24 +801,25 @@ var W = class {
778
801
  await this.load();
779
802
  let t = this.services.options, n = t.debug ? performance.now() : 0, r = t.debug ? performance.now() : 0, i = r, a;
780
803
  if (this.shouldUseParallelPhoneRotationFallback(t) && this.shouldRunParallelPhoneRotationFallback(t)) {
781
- let [n, r] = await Promise.all([M(e), M(e)]);
804
+ let [n, r] = await Promise.all([k(e), k(e)]);
782
805
  i = t.debug ? performance.now() : 0, a = await this.runParallelPhoneRotationFallback(n, r, t);
783
806
  } else {
784
- let n = await M(e);
807
+ let n = await k(e);
785
808
  i = t.debug ? performance.now() : 0, a = await this.runWorkerInference(this.getInferenceWorker(), n, t, {
786
809
  inputRotation: "none",
787
810
  phoneRotationFallback: t.phoneRotationFallback && t.phoneRotationFallbackExecution === "sequential"
788
811
  });
789
812
  }
813
+ let o = this.confirmTemporalPhoneCandidates(a);
790
814
  if (t.debug) {
791
815
  let e = performance.now();
792
816
  console.info("[MonitorDog] detect frame", {
793
- sourceMs: G(i - r),
794
- workerRoundtripMs: G(e - i),
795
- totalMs: G(e - n)
817
+ sourceMs: J(i - r),
818
+ workerRoundtripMs: J(e - i),
819
+ totalMs: J(e - n)
796
820
  });
797
821
  }
798
- return a;
822
+ return o;
799
823
  }
800
824
  toPublicResult(e) {
801
825
  return {
@@ -811,7 +835,7 @@ var W = class {
811
835
  let t = !1, n, r = this.services.options.detectionIntervalMs, i = async () => {
812
836
  if (!t) {
813
837
  try {
814
- if (!this.services.shouldPauseDetection && V(e)) {
838
+ if (!this.services.shouldPauseDetection && B(e)) {
815
839
  let n = await this.detect(e);
816
840
  if (t) return;
817
841
  try {
@@ -826,7 +850,7 @@ var W = class {
826
850
  if (t) return;
827
851
  await this.services.detectionEvents.handleDetectionResult(n, e).catch((e) => {
828
852
  this.services.options.onError?.(e);
829
- }), g(n) && this.services.detectionEvents.clearTransientState();
853
+ }), _(n) && this.services.detectionEvents.clearTransientState();
830
854
  }
831
855
  } catch (e) {
832
856
  this.handleDetectionLoopError(e);
@@ -834,15 +858,15 @@ var W = class {
834
858
  t || (n = setTimeout(i, r));
835
859
  }
836
860
  };
837
- return i(), { stop() {
838
- t = !0, n && clearTimeout(n);
861
+ return i(), { stop: () => {
862
+ t = !0, this.resetPhoneCandidateHistory(), n && clearTimeout(n);
839
863
  } };
840
864
  }
841
865
  async startWebcamDetection() {
842
866
  let e = this.services.options, t = await this.services.camera.createWebcamStream(e.constraints), n = this.services.camera, r = !e.video, i = e.video ?? document.createElement("video"), a = i.muted, o = i.playsInline, s = i.srcObject;
843
867
  i.muted = !0, i.playsInline = !0, i.srcObject = t;
844
868
  try {
845
- await Promise.all([i.play(), H(i)]);
869
+ await Promise.all([i.play(), V(i)]);
846
870
  } catch (e) {
847
871
  throw n.stopStream(t), i.pause(), r ? i.srcObject = null : (i.muted = a, i.playsInline = o, i.srcObject = s), e;
848
872
  }
@@ -859,7 +883,34 @@ var W = class {
859
883
  };
860
884
  }
861
885
  dispose() {
862
- this.primaryInferenceWorker?.terminate(), this.rotationInferenceWorker?.terminate(), this.primaryInferenceWorker = void 0, this.rotationInferenceWorker = void 0, this.loadPromise = void 0, this.lastParallelPhoneRotationFallbackAt = -Infinity, this.services.detectionEvents.reset();
886
+ this.primaryInferenceWorker?.terminate(), this.rotationInferenceWorker?.terminate(), this.primaryInferenceWorker = void 0, this.rotationInferenceWorker = void 0, this.loadPromise = void 0, this.lastParallelPhoneRotationFallbackAt = -Infinity, this.resetPhoneCandidateHistory(), this.services.detectionEvents.reset();
887
+ }
888
+ confirmTemporalPhoneCandidates(e) {
889
+ if (e.phoneCandidates.length === 0) return this.prunePhoneCandidateHistory(performance.now()), e;
890
+ let t = performance.now(), n = this.getRecentPhoneCandidateHistory(t), r = e.phoneCandidates.filter((e) => this.isTemporallyConfirmedPhoneCandidate(e, n));
891
+ if (this.phoneCandidateHistory = [...n, ...e.phoneCandidates.map((e) => ({
892
+ candidate: e,
893
+ observedAt: t
894
+ }))], r.length === 0) return e;
895
+ let i = [...e.phoneDetections, ...r.map(se)];
896
+ return {
897
+ ...e,
898
+ phoneDetected: !0,
899
+ phoneCount: i.length,
900
+ phoneDetections: i
901
+ };
902
+ }
903
+ isTemporallyConfirmedPhoneCandidate(e, t) {
904
+ return K(e) ? t.some(({ candidate: t }) => q(e, t) && ce(e, t) >= oe) : !1;
905
+ }
906
+ getRecentPhoneCandidateHistory(e) {
907
+ return this.phoneCandidateHistory.filter((t) => e - t.observedAt <= U);
908
+ }
909
+ prunePhoneCandidateHistory(e) {
910
+ this.phoneCandidateHistory = this.getRecentPhoneCandidateHistory(e);
911
+ }
912
+ resetPhoneCandidateHistory() {
913
+ this.phoneCandidateHistory = [];
863
914
  }
864
915
  async runParallelPhoneRotationFallback(e, t, n) {
865
916
  let r = e.sourceWidth, i = e.sourceHeight, [a, o] = await Promise.all([this.runWorkerInference(this.getInferenceWorker(), e, n, {
@@ -869,7 +920,7 @@ var W = class {
869
920
  inputRotation: "rotate180",
870
921
  phoneRotationFallback: !1
871
922
  })]);
872
- return R(a, o, r, i);
923
+ return I(a, o, r, i);
873
924
  }
874
925
  runWorkerInference(e, t, n, r) {
875
926
  return e.run({
@@ -905,10 +956,10 @@ var W = class {
905
956
  return /out of memory|oom|memory access out of bounds|cannot enlarge memory|array buffer allocation|bad allocation|allocation failed/i.test(t);
906
957
  }
907
958
  getInferenceWorker() {
908
- return this.primaryInferenceWorker ||= new j(), this.primaryInferenceWorker;
959
+ return this.primaryInferenceWorker ||= new O(), this.primaryInferenceWorker;
909
960
  }
910
961
  getRotationInferenceWorker() {
911
- return this.rotationInferenceWorker ||= new j(), this.rotationInferenceWorker;
962
+ return this.rotationInferenceWorker ||= new O(), this.rotationInferenceWorker;
912
963
  }
913
964
  shouldUseParallelPhoneRotationFallback(e) {
914
965
  return e.phoneRotationFallback && e.phoneRotationFallbackExecution === "parallel";
@@ -937,6 +988,7 @@ var W = class {
937
988
  apiBaseUrl: t.apiBaseUrl,
938
989
  accessToken: e,
939
990
  inputSize: t.inputSize,
991
+ runtimeAssetUrls: z,
940
992
  runtimeAssetBaseUrl: t.runtimeAssetBaseUrl
941
993
  };
942
994
  if (this.shouldUseParallelPhoneRotationFallback(t)) {
@@ -946,12 +998,34 @@ var W = class {
946
998
  await this.getInferenceWorker().load(n);
947
999
  }
948
1000
  };
949
- function G(e) {
1001
+ function K(e) {
1002
+ return e.handOverlapped || e.score >= W;
1003
+ }
1004
+ function q(e, t) {
1005
+ return e.handOverlapped === t.handOverlapped ? K(t) : !1;
1006
+ }
1007
+ function se(e) {
1008
+ return {
1009
+ classId: e.classId,
1010
+ label: e.label,
1011
+ score: e.score,
1012
+ confidence: e.confidence,
1013
+ x: e.x,
1014
+ y: e.y,
1015
+ width: e.width,
1016
+ height: e.height
1017
+ };
1018
+ }
1019
+ function ce(e, t) {
1020
+ let n = e.x + e.width, r = e.y + e.height, i = t.x + t.width, a = t.y + t.height, o = Math.max(0, Math.min(n, i) - Math.max(e.x, t.x)) * Math.max(0, Math.min(r, a) - Math.max(e.y, t.y)), s = e.width * e.height + t.width * t.height - o;
1021
+ return s <= 0 ? 0 : o / s;
1022
+ }
1023
+ function J(e) {
950
1024
  return Math.round(e * 10) / 10;
951
1025
  }
952
1026
  //#endregion
953
1027
  //#region src/service/webcam-service.ts
954
- var K = class {
1028
+ var le = class {
955
1029
  services;
956
1030
  isWebcamRunning = !1;
957
1031
  stopCurrentWebcam;
@@ -1043,7 +1117,7 @@ var K = class {
1043
1117
  removeVisibilityListener() {
1044
1118
  typeof document > "u" || document.removeEventListener("visibilitychange", this.handleVisibilityChange);
1045
1119
  }
1046
- }, q = class {
1120
+ }, ue = class {
1047
1121
  auth;
1048
1122
  camera;
1049
1123
  detectionEvents;
@@ -1052,10 +1126,10 @@ var K = class {
1052
1126
  onCameraDisconnect;
1053
1127
  onLoginRequired;
1054
1128
  #e = 0;
1055
- #t = J();
1129
+ #t = Y();
1056
1130
  #n;
1057
1131
  constructor(e) {
1058
- this.#n = e, this.camera = new E(), this.auth = new C(this), this.detectionEvents = new ne(this), this.detect = new W(this), this.webcam = new K(this);
1132
+ this.#n = e, this.camera = new te(), this.auth = new w(this), this.detectionEvents = new ie(this), this.detect = new G(this), this.webcam = new le(this);
1059
1133
  }
1060
1134
  get options() {
1061
1135
  return Object.freeze({ ...this.#n() });
@@ -1091,18 +1165,18 @@ var K = class {
1091
1165
  }
1092
1166
  applyPolicyItems(e, t) {
1093
1167
  let n = { ...this.#t };
1094
- for (let t of e) X(n, t);
1168
+ for (let t of e) fe(n, t);
1095
1169
  this.#t = n, this.syncEffectivePhoneConfidenceThreshold(), this.#n().faceConfidenceThreshold = n.faceDetectionThreshold, this.updateRequiredPasswordFromServer(!1);
1096
1170
  }
1097
1171
  resetAuthenticatedState() {
1098
- this.#e = 0, this.#t = J(), this.#n().requiredPassword = !1, this.syncEffectivePhoneConfidenceThreshold(), this.#n().faceConfidenceThreshold = this.#t.faceDetectionThreshold;
1172
+ this.#e = 0, this.#t = Y(), this.#n().requiredPassword = !1, this.syncEffectivePhoneConfidenceThreshold(), this.#n().faceConfidenceThreshold = this.#t.faceDetectionThreshold;
1099
1173
  }
1100
1174
  syncEffectivePhoneConfidenceThreshold() {
1101
1175
  let e = this.#n();
1102
1176
  e.confidenceThreshold = e.phoneConfidenceThreshold ?? this.#t.mobileDetectionThreshold;
1103
1177
  }
1104
1178
  };
1105
- function J() {
1179
+ function Y() {
1106
1180
  return {
1107
1181
  mobileDetectionThreshold: .8,
1108
1182
  faceDetectionThreshold: .8,
@@ -1118,19 +1192,19 @@ function J() {
1118
1192
  multiPersonDetectionMode: "auto_lock"
1119
1193
  };
1120
1194
  }
1121
- function Y(e) {
1195
+ function de(e) {
1122
1196
  return e === "none";
1123
1197
  }
1124
- function X(e, t) {
1125
- let n = t.policy, r = !Y(t.policy), i = t.seconds * 1e3, a = "sensitivity" in t ? 1 - t.sensitivity / 100 : void 0;
1198
+ function fe(e, t) {
1199
+ let n = t.policy, r = !de(t.policy), i = t.seconds * 1e3, a = "sensitivity" in t ? 1 - t.sensitivity / 100 : void 0;
1126
1200
  switch (t.basic_event_uuid) {
1127
- case b("mobileDevice"):
1201
+ case x("mobileDevice"):
1128
1202
  e.mobileDetectionEnabled = r, e.mobileDetectionLockDuration = i, e.mobileDetectionMode = n, a !== void 0 && (e.mobileDetectionThreshold = a);
1129
1203
  break;
1130
- case b("twoFacesDetected"):
1204
+ case x("twoFacesDetected"):
1131
1205
  e.multiPersonDetectionEnabled = r, e.multiPersonLockDuration = i, e.multiPersonDetectionMode = n, a !== void 0 && (e.faceDetectionThreshold = a);
1132
1206
  break;
1133
- case b("noFaceDetected"):
1207
+ case x("noFaceDetected"):
1134
1208
  e.noPersonDetectionEnabled = r, e.noPersonLockDuration = i, e.noPersonDetectionMode = n;
1135
1209
  break;
1136
1210
  default: break;
@@ -1138,7 +1212,7 @@ function X(e, t) {
1138
1212
  }
1139
1213
  //#endregion
1140
1214
  //#region src/index.ts
1141
- var Z = class e {
1215
+ var X = class e {
1142
1216
  #e;
1143
1217
  #t;
1144
1218
  #n = "anonymous";
@@ -1147,11 +1221,11 @@ var Z = class e {
1147
1221
  #a;
1148
1222
  #o;
1149
1223
  static async init(t) {
1150
- return Q = new e(t), Q;
1224
+ return Z = new e(t), Z;
1151
1225
  }
1152
1226
  constructor(e) {
1153
- ce(e);
1154
- let r = se(), i = p(e.runtimeAssetBaseUrl);
1227
+ Q(e);
1228
+ let r = _e(), i = f(e.runtimeAssetBaseUrl);
1155
1229
  this.#t = {
1156
1230
  ...e,
1157
1231
  apiBaseUrl: c(e.apiBaseUrl),
@@ -1160,7 +1234,7 @@ var Z = class e {
1160
1234
  faceConfidenceThreshold: t,
1161
1235
  iouThreshold: n,
1162
1236
  maxDetections: 100,
1163
- inputSize: f(e.modelInputSize, r),
1237
+ inputSize: ee(e.modelInputSize, r),
1164
1238
  inputType: "float32",
1165
1239
  detectionIntervalMs: e.detectionIntervalMs ?? 300,
1166
1240
  requiredPassword: !1,
@@ -1168,7 +1242,7 @@ var Z = class e {
1168
1242
  phoneRotationFallback: e.phoneRotationFallback ?? !1,
1169
1243
  phoneRotationFallbackMinIntervalMs: e.phoneRotationFallbackMinIntervalMs ?? 500,
1170
1244
  phoneRotationFallbackExecution: e.phoneRotationFallbackExecution ?? "sequential"
1171
- }, this.#e = new q(() => this.#t), this.#e.onLoginRequired = () => this.resetLoggedOutState(), Object.freeze(this);
1245
+ }, this.#e = new ue(() => this.#t), this.#e.onLoginRequired = () => this.resetLoggedOutState(), Object.freeze(this);
1172
1246
  }
1173
1247
  async load() {
1174
1248
  this.assertUsable(), this.assertAuthenticated("loading detection");
@@ -1305,7 +1379,7 @@ var Z = class e {
1305
1379
  });
1306
1380
  } catch (e) {
1307
1381
  let t = this.createSdkError(this.getStartErrorCode(e), this.getStartErrorMessage(e), e);
1308
- throw this.transitionToError(t, re(t.code) ? "blocked" : "idle"), this.#t.onError?.(t), t;
1382
+ throw this.transitionToError(t, pe(t.code) ? "blocked" : "idle"), this.#t.onError?.(t), t;
1309
1383
  }
1310
1384
  }
1311
1385
  clearSessionState() {
@@ -1351,7 +1425,7 @@ var Z = class e {
1351
1425
  }
1352
1426
  }
1353
1427
  createSdkError(e, t, n) {
1354
- return h(n) ? n : new m(e, t, n);
1428
+ return m(n) ? n : new p(e, t, n);
1355
1429
  }
1356
1430
  isDetectorRunning() {
1357
1431
  return this.#r === "running" || this.#r === "starting" || !!this.#o || this.#e.webcam.isRunning || this.#e.webcam.isStarting;
@@ -1377,40 +1451,40 @@ var Z = class e {
1377
1451
  return typeof DOMException < "u" && e instanceof DOMException && e.name === "NotReadableError";
1378
1452
  }
1379
1453
  };
1380
- function re(e) {
1454
+ function pe(e) {
1381
1455
  return e === "CAMERA_PERMISSION_DENIED" || e === "CAMERA_READ_FAILED";
1382
1456
  }
1383
- var Q;
1384
- function ie(e) {
1385
- return Q = new Z(e), Q;
1457
+ var Z;
1458
+ function me(e) {
1459
+ return Z = new X(e), Z;
1386
1460
  }
1387
- async function ae(e) {
1388
- return Z.init(e);
1461
+ async function he(e) {
1462
+ return X.init(e);
1389
1463
  }
1390
- function oe() {
1391
- if (!Q) throw Error("MonitorDog is not configured. Call MonitorDogDetector.init(), createMonitorDogDetector(), or configureMonitorDogDetector() before using getDetector().");
1392
- return Q;
1464
+ function ge() {
1465
+ if (!Z) throw Error("MonitorDog is not configured. Call MonitorDogDetector.init(), createMonitorDogDetector(), or configureMonitorDogDetector() before using getDetector().");
1466
+ return Z;
1393
1467
  }
1394
- function se() {
1468
+ function _e() {
1395
1469
  if (typeof navigator > "u") return !1;
1396
1470
  let e = l();
1397
1471
  return e === "mobile" || e === "tablet";
1398
1472
  }
1399
- function ce(e) {
1473
+ function Q(e) {
1400
1474
  if (!e || typeof e.apiBaseUrl != "string" || e.apiBaseUrl.length === 0) throw Error("MonitorDog apiBaseUrl is required.");
1401
1475
  if (typeof e.sessionTokenProvider != "function") throw Error("MonitorDog sessionTokenProvider is required.");
1402
1476
  if (typeof e.onDetect != "function") throw Error("MonitorDog onDetect callback is required.");
1403
- if (e.runtimeAssetBaseUrl !== void 0 && p(e.runtimeAssetBaseUrl), e.modelInputSize !== void 0 && !d(e.modelInputSize)) throw Error("MonitorDog modelInputSize must be \"auto\", 320, 416, or 640.");
1477
+ if (e.runtimeAssetBaseUrl !== void 0 && f(e.runtimeAssetBaseUrl), e.modelInputSize !== void 0 && !d(e.modelInputSize)) throw Error("MonitorDog modelInputSize must be \"auto\", 320, 416, or 640.");
1404
1478
  if (e.phoneRotationFallback !== void 0 && typeof e.phoneRotationFallback != "boolean") throw Error("MonitorDog phoneRotationFallback must be a boolean when provided.");
1405
- if (e.phoneRotationFallbackMinIntervalMs !== void 0 && !le(e.phoneRotationFallbackMinIntervalMs)) throw Error("MonitorDog phoneRotationFallbackMinIntervalMs must be a non-negative finite number when provided.");
1479
+ if (e.phoneRotationFallbackMinIntervalMs !== void 0 && !ve(e.phoneRotationFallbackMinIntervalMs)) throw Error("MonitorDog phoneRotationFallbackMinIntervalMs must be a non-negative finite number when provided.");
1406
1480
  if (e.phoneRotationFallbackExecution !== void 0 && e.phoneRotationFallbackExecution !== "sequential" && e.phoneRotationFallbackExecution !== "parallel") throw Error("MonitorDog phoneRotationFallbackExecution must be \"sequential\" or \"parallel\" when provided.");
1407
1481
  $(e.phoneConfidenceThreshold);
1408
1482
  }
1409
- function le(e) {
1483
+ function ve(e) {
1410
1484
  return typeof e == "number" && Number.isFinite(e) && e >= 0;
1411
1485
  }
1412
1486
  function $(e) {
1413
1487
  if (e !== void 0 && (typeof e != "number" || !Number.isFinite(e) || e < 0 || e > 1)) throw Error("MonitorDog phoneConfidenceThreshold must be a finite number between 0 and 1 when provided.");
1414
1488
  }
1415
1489
  //#endregion
1416
- export { Z as MonitorDogDetector, m as MonitorDogSdkError, ie as configureMonitorDogDetector, ae as createMonitorDogDetector, oe as getDetector, h as isMonitorDogSdkError };
1490
+ export { X as MonitorDogDetector, p as MonitorDogSdkError, me as configureMonitorDogDetector, he as createMonitorDogDetector, ge as getDetector, m as isMonitorDogSdkError };