@monitordog/detector 1.0.10 → 1.0.11

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-KC9Jl3J4.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,52 @@ 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
737
746
  //#region src/video.ts
738
- function V(e) {
747
+ function z(e) {
739
748
  return e.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA && e.videoWidth > 0 && e.videoHeight > 0 && !e.paused && !e.ended;
740
749
  }
741
- function H(e, t = 1e4) {
742
- return U(e) ? Promise.resolve() : new Promise((n, r) => {
750
+ function B(e, t = 1e4) {
751
+ return V(e) ? Promise.resolve() : new Promise((n, r) => {
743
752
  let i = window.setTimeout(() => {
744
753
  o(), r(/* @__PURE__ */ Error("Timed out waiting for webcam video metadata."));
745
754
  }, t), a = window.setInterval(s, 100), o = () => {
746
755
  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
756
  };
748
757
  function s() {
749
- U(e) && (o(), n());
758
+ V(e) && (o(), n());
750
759
  }
751
760
  let c = () => {
752
761
  s();
@@ -756,18 +765,19 @@ function H(e, t = 1e4) {
756
765
  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
766
  });
758
767
  }
759
- function U(e) {
768
+ function V(e) {
760
769
  return e.readyState >= HTMLMediaElement.HAVE_METADATA && e.videoWidth > 0 && e.videoHeight > 0;
761
770
  }
762
771
  //#endregion
763
772
  //#region src/service/detect-service.ts
764
- var W = class {
773
+ var H = 700, U = .25, oe = .8, W = class {
765
774
  services;
766
775
  primaryInferenceWorker;
767
776
  rotationInferenceWorker;
768
777
  loadPromise;
769
778
  lastInferenceMemoryErrorAt = 0;
770
779
  lastParallelPhoneRotationFallbackAt = -Infinity;
780
+ phoneCandidateHistory = [];
771
781
  constructor(e) {
772
782
  this.services = e;
773
783
  }
@@ -778,24 +788,25 @@ var W = class {
778
788
  await this.load();
779
789
  let t = this.services.options, n = t.debug ? performance.now() : 0, r = t.debug ? performance.now() : 0, i = r, a;
780
790
  if (this.shouldUseParallelPhoneRotationFallback(t) && this.shouldRunParallelPhoneRotationFallback(t)) {
781
- let [n, r] = await Promise.all([M(e), M(e)]);
791
+ let [n, r] = await Promise.all([k(e), k(e)]);
782
792
  i = t.debug ? performance.now() : 0, a = await this.runParallelPhoneRotationFallback(n, r, t);
783
793
  } else {
784
- let n = await M(e);
794
+ let n = await k(e);
785
795
  i = t.debug ? performance.now() : 0, a = await this.runWorkerInference(this.getInferenceWorker(), n, t, {
786
796
  inputRotation: "none",
787
797
  phoneRotationFallback: t.phoneRotationFallback && t.phoneRotationFallbackExecution === "sequential"
788
798
  });
789
799
  }
800
+ let o = this.confirmTemporalPhoneCandidates(a);
790
801
  if (t.debug) {
791
802
  let e = performance.now();
792
803
  console.info("[MonitorDog] detect frame", {
793
- sourceMs: G(i - r),
794
- workerRoundtripMs: G(e - i),
795
- totalMs: G(e - n)
804
+ sourceMs: J(i - r),
805
+ workerRoundtripMs: J(e - i),
806
+ totalMs: J(e - n)
796
807
  });
797
808
  }
798
- return a;
809
+ return o;
799
810
  }
800
811
  toPublicResult(e) {
801
812
  return {
@@ -811,7 +822,7 @@ var W = class {
811
822
  let t = !1, n, r = this.services.options.detectionIntervalMs, i = async () => {
812
823
  if (!t) {
813
824
  try {
814
- if (!this.services.shouldPauseDetection && V(e)) {
825
+ if (!this.services.shouldPauseDetection && z(e)) {
815
826
  let n = await this.detect(e);
816
827
  if (t) return;
817
828
  try {
@@ -826,7 +837,7 @@ var W = class {
826
837
  if (t) return;
827
838
  await this.services.detectionEvents.handleDetectionResult(n, e).catch((e) => {
828
839
  this.services.options.onError?.(e);
829
- }), g(n) && this.services.detectionEvents.clearTransientState();
840
+ }), _(n) && this.services.detectionEvents.clearTransientState();
830
841
  }
831
842
  } catch (e) {
832
843
  this.handleDetectionLoopError(e);
@@ -834,15 +845,15 @@ var W = class {
834
845
  t || (n = setTimeout(i, r));
835
846
  }
836
847
  };
837
- return i(), { stop() {
838
- t = !0, n && clearTimeout(n);
848
+ return i(), { stop: () => {
849
+ t = !0, this.resetPhoneCandidateHistory(), n && clearTimeout(n);
839
850
  } };
840
851
  }
841
852
  async startWebcamDetection() {
842
853
  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
854
  i.muted = !0, i.playsInline = !0, i.srcObject = t;
844
855
  try {
845
- await Promise.all([i.play(), H(i)]);
856
+ await Promise.all([i.play(), B(i)]);
846
857
  } catch (e) {
847
858
  throw n.stopStream(t), i.pause(), r ? i.srcObject = null : (i.muted = a, i.playsInline = o, i.srcObject = s), e;
848
859
  }
@@ -859,7 +870,34 @@ var W = class {
859
870
  };
860
871
  }
861
872
  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();
873
+ 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();
874
+ }
875
+ confirmTemporalPhoneCandidates(e) {
876
+ if (e.phoneCandidates.length === 0) return this.prunePhoneCandidateHistory(performance.now()), e;
877
+ let t = performance.now(), n = this.getRecentPhoneCandidateHistory(t), r = e.phoneCandidates.filter((e) => this.isTemporallyConfirmedPhoneCandidate(e, n));
878
+ if (this.phoneCandidateHistory = [...n, ...e.phoneCandidates.map((e) => ({
879
+ candidate: e,
880
+ observedAt: t
881
+ }))], r.length === 0) return e;
882
+ let i = [...e.phoneDetections, ...r.map(q)];
883
+ return {
884
+ ...e,
885
+ phoneDetected: !0,
886
+ phoneCount: i.length,
887
+ phoneDetections: i
888
+ };
889
+ }
890
+ isTemporallyConfirmedPhoneCandidate(e, t) {
891
+ return G(e) ? t.some(({ candidate: t }) => K(e, t) && se(e, t) >= U) : !1;
892
+ }
893
+ getRecentPhoneCandidateHistory(e) {
894
+ return this.phoneCandidateHistory.filter((t) => e - t.observedAt <= H);
895
+ }
896
+ prunePhoneCandidateHistory(e) {
897
+ this.phoneCandidateHistory = this.getRecentPhoneCandidateHistory(e);
898
+ }
899
+ resetPhoneCandidateHistory() {
900
+ this.phoneCandidateHistory = [];
863
901
  }
864
902
  async runParallelPhoneRotationFallback(e, t, n) {
865
903
  let r = e.sourceWidth, i = e.sourceHeight, [a, o] = await Promise.all([this.runWorkerInference(this.getInferenceWorker(), e, n, {
@@ -869,7 +907,7 @@ var W = class {
869
907
  inputRotation: "rotate180",
870
908
  phoneRotationFallback: !1
871
909
  })]);
872
- return R(a, o, r, i);
910
+ return I(a, o, r, i);
873
911
  }
874
912
  runWorkerInference(e, t, n, r) {
875
913
  return e.run({
@@ -905,10 +943,10 @@ var W = class {
905
943
  return /out of memory|oom|memory access out of bounds|cannot enlarge memory|array buffer allocation|bad allocation|allocation failed/i.test(t);
906
944
  }
907
945
  getInferenceWorker() {
908
- return this.primaryInferenceWorker ||= new j(), this.primaryInferenceWorker;
946
+ return this.primaryInferenceWorker ||= new O(), this.primaryInferenceWorker;
909
947
  }
910
948
  getRotationInferenceWorker() {
911
- return this.rotationInferenceWorker ||= new j(), this.rotationInferenceWorker;
949
+ return this.rotationInferenceWorker ||= new O(), this.rotationInferenceWorker;
912
950
  }
913
951
  shouldUseParallelPhoneRotationFallback(e) {
914
952
  return e.phoneRotationFallback && e.phoneRotationFallbackExecution === "parallel";
@@ -947,11 +985,33 @@ var W = class {
947
985
  }
948
986
  };
949
987
  function G(e) {
988
+ return e.handOverlapped || e.score >= oe;
989
+ }
990
+ function K(e, t) {
991
+ return e.handOverlapped === t.handOverlapped ? G(t) : !1;
992
+ }
993
+ function q(e) {
994
+ return {
995
+ classId: e.classId,
996
+ label: e.label,
997
+ score: e.score,
998
+ confidence: e.confidence,
999
+ x: e.x,
1000
+ y: e.y,
1001
+ width: e.width,
1002
+ height: e.height
1003
+ };
1004
+ }
1005
+ function se(e, t) {
1006
+ 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;
1007
+ return s <= 0 ? 0 : o / s;
1008
+ }
1009
+ function J(e) {
950
1010
  return Math.round(e * 10) / 10;
951
1011
  }
952
1012
  //#endregion
953
1013
  //#region src/service/webcam-service.ts
954
- var K = class {
1014
+ var ce = class {
955
1015
  services;
956
1016
  isWebcamRunning = !1;
957
1017
  stopCurrentWebcam;
@@ -1043,7 +1103,7 @@ var K = class {
1043
1103
  removeVisibilityListener() {
1044
1104
  typeof document > "u" || document.removeEventListener("visibilitychange", this.handleVisibilityChange);
1045
1105
  }
1046
- }, q = class {
1106
+ }, le = class {
1047
1107
  auth;
1048
1108
  camera;
1049
1109
  detectionEvents;
@@ -1052,10 +1112,10 @@ var K = class {
1052
1112
  onCameraDisconnect;
1053
1113
  onLoginRequired;
1054
1114
  #e = 0;
1055
- #t = J();
1115
+ #t = Y();
1056
1116
  #n;
1057
1117
  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);
1118
+ this.#n = e, this.camera = new te(), this.auth = new w(this), this.detectionEvents = new ie(this), this.detect = new W(this), this.webcam = new ce(this);
1059
1119
  }
1060
1120
  get options() {
1061
1121
  return Object.freeze({ ...this.#n() });
@@ -1091,18 +1151,18 @@ var K = class {
1091
1151
  }
1092
1152
  applyPolicyItems(e, t) {
1093
1153
  let n = { ...this.#t };
1094
- for (let t of e) X(n, t);
1154
+ for (let t of e) de(n, t);
1095
1155
  this.#t = n, this.syncEffectivePhoneConfidenceThreshold(), this.#n().faceConfidenceThreshold = n.faceDetectionThreshold, this.updateRequiredPasswordFromServer(!1);
1096
1156
  }
1097
1157
  resetAuthenticatedState() {
1098
- this.#e = 0, this.#t = J(), this.#n().requiredPassword = !1, this.syncEffectivePhoneConfidenceThreshold(), this.#n().faceConfidenceThreshold = this.#t.faceDetectionThreshold;
1158
+ this.#e = 0, this.#t = Y(), this.#n().requiredPassword = !1, this.syncEffectivePhoneConfidenceThreshold(), this.#n().faceConfidenceThreshold = this.#t.faceDetectionThreshold;
1099
1159
  }
1100
1160
  syncEffectivePhoneConfidenceThreshold() {
1101
1161
  let e = this.#n();
1102
1162
  e.confidenceThreshold = e.phoneConfidenceThreshold ?? this.#t.mobileDetectionThreshold;
1103
1163
  }
1104
1164
  };
1105
- function J() {
1165
+ function Y() {
1106
1166
  return {
1107
1167
  mobileDetectionThreshold: .8,
1108
1168
  faceDetectionThreshold: .8,
@@ -1118,19 +1178,19 @@ function J() {
1118
1178
  multiPersonDetectionMode: "auto_lock"
1119
1179
  };
1120
1180
  }
1121
- function Y(e) {
1181
+ function ue(e) {
1122
1182
  return e === "none";
1123
1183
  }
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;
1184
+ function de(e, t) {
1185
+ let n = t.policy, r = !ue(t.policy), i = t.seconds * 1e3, a = "sensitivity" in t ? 1 - t.sensitivity / 100 : void 0;
1126
1186
  switch (t.basic_event_uuid) {
1127
- case b("mobileDevice"):
1187
+ case x("mobileDevice"):
1128
1188
  e.mobileDetectionEnabled = r, e.mobileDetectionLockDuration = i, e.mobileDetectionMode = n, a !== void 0 && (e.mobileDetectionThreshold = a);
1129
1189
  break;
1130
- case b("twoFacesDetected"):
1190
+ case x("twoFacesDetected"):
1131
1191
  e.multiPersonDetectionEnabled = r, e.multiPersonLockDuration = i, e.multiPersonDetectionMode = n, a !== void 0 && (e.faceDetectionThreshold = a);
1132
1192
  break;
1133
- case b("noFaceDetected"):
1193
+ case x("noFaceDetected"):
1134
1194
  e.noPersonDetectionEnabled = r, e.noPersonLockDuration = i, e.noPersonDetectionMode = n;
1135
1195
  break;
1136
1196
  default: break;
@@ -1138,7 +1198,7 @@ function X(e, t) {
1138
1198
  }
1139
1199
  //#endregion
1140
1200
  //#region src/index.ts
1141
- var Z = class e {
1201
+ var X = class e {
1142
1202
  #e;
1143
1203
  #t;
1144
1204
  #n = "anonymous";
@@ -1147,11 +1207,11 @@ var Z = class e {
1147
1207
  #a;
1148
1208
  #o;
1149
1209
  static async init(t) {
1150
- return Q = new e(t), Q;
1210
+ return Z = new e(t), Z;
1151
1211
  }
1152
1212
  constructor(e) {
1153
- ce(e);
1154
- let r = se(), i = p(e.runtimeAssetBaseUrl);
1213
+ ge(e);
1214
+ let r = he(), i = f(e.runtimeAssetBaseUrl);
1155
1215
  this.#t = {
1156
1216
  ...e,
1157
1217
  apiBaseUrl: c(e.apiBaseUrl),
@@ -1160,7 +1220,7 @@ var Z = class e {
1160
1220
  faceConfidenceThreshold: t,
1161
1221
  iouThreshold: n,
1162
1222
  maxDetections: 100,
1163
- inputSize: f(e.modelInputSize, r),
1223
+ inputSize: ee(e.modelInputSize, r),
1164
1224
  inputType: "float32",
1165
1225
  detectionIntervalMs: e.detectionIntervalMs ?? 300,
1166
1226
  requiredPassword: !1,
@@ -1168,7 +1228,7 @@ var Z = class e {
1168
1228
  phoneRotationFallback: e.phoneRotationFallback ?? !1,
1169
1229
  phoneRotationFallbackMinIntervalMs: e.phoneRotationFallbackMinIntervalMs ?? 500,
1170
1230
  phoneRotationFallbackExecution: e.phoneRotationFallbackExecution ?? "sequential"
1171
- }, this.#e = new q(() => this.#t), this.#e.onLoginRequired = () => this.resetLoggedOutState(), Object.freeze(this);
1231
+ }, this.#e = new le(() => this.#t), this.#e.onLoginRequired = () => this.resetLoggedOutState(), Object.freeze(this);
1172
1232
  }
1173
1233
  async load() {
1174
1234
  this.assertUsable(), this.assertAuthenticated("loading detection");
@@ -1305,7 +1365,7 @@ var Z = class e {
1305
1365
  });
1306
1366
  } catch (e) {
1307
1367
  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;
1368
+ throw this.transitionToError(t, fe(t.code) ? "blocked" : "idle"), this.#t.onError?.(t), t;
1309
1369
  }
1310
1370
  }
1311
1371
  clearSessionState() {
@@ -1351,7 +1411,7 @@ var Z = class e {
1351
1411
  }
1352
1412
  }
1353
1413
  createSdkError(e, t, n) {
1354
- return h(n) ? n : new m(e, t, n);
1414
+ return m(n) ? n : new p(e, t, n);
1355
1415
  }
1356
1416
  isDetectorRunning() {
1357
1417
  return this.#r === "running" || this.#r === "starting" || !!this.#o || this.#e.webcam.isRunning || this.#e.webcam.isStarting;
@@ -1377,40 +1437,40 @@ var Z = class e {
1377
1437
  return typeof DOMException < "u" && e instanceof DOMException && e.name === "NotReadableError";
1378
1438
  }
1379
1439
  };
1380
- function re(e) {
1440
+ function fe(e) {
1381
1441
  return e === "CAMERA_PERMISSION_DENIED" || e === "CAMERA_READ_FAILED";
1382
1442
  }
1383
- var Q;
1384
- function ie(e) {
1385
- return Q = new Z(e), Q;
1443
+ var Z;
1444
+ function pe(e) {
1445
+ return Z = new X(e), Z;
1386
1446
  }
1387
- async function ae(e) {
1388
- return Z.init(e);
1447
+ async function me(e) {
1448
+ return X.init(e);
1389
1449
  }
1390
- function oe() {
1391
- if (!Q) throw Error("MonitorDog is not configured. Call MonitorDogDetector.init(), createMonitorDogDetector(), or configureMonitorDogDetector() before using getDetector().");
1392
- return Q;
1450
+ function Q() {
1451
+ if (!Z) throw Error("MonitorDog is not configured. Call MonitorDogDetector.init(), createMonitorDogDetector(), or configureMonitorDogDetector() before using getDetector().");
1452
+ return Z;
1393
1453
  }
1394
- function se() {
1454
+ function he() {
1395
1455
  if (typeof navigator > "u") return !1;
1396
1456
  let e = l();
1397
1457
  return e === "mobile" || e === "tablet";
1398
1458
  }
1399
- function ce(e) {
1459
+ function ge(e) {
1400
1460
  if (!e || typeof e.apiBaseUrl != "string" || e.apiBaseUrl.length === 0) throw Error("MonitorDog apiBaseUrl is required.");
1401
1461
  if (typeof e.sessionTokenProvider != "function") throw Error("MonitorDog sessionTokenProvider is required.");
1402
1462
  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.");
1463
+ 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
1464
  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.");
1465
+ if (e.phoneRotationFallbackMinIntervalMs !== void 0 && !_e(e.phoneRotationFallbackMinIntervalMs)) throw Error("MonitorDog phoneRotationFallbackMinIntervalMs must be a non-negative finite number when provided.");
1406
1466
  if (e.phoneRotationFallbackExecution !== void 0 && e.phoneRotationFallbackExecution !== "sequential" && e.phoneRotationFallbackExecution !== "parallel") throw Error("MonitorDog phoneRotationFallbackExecution must be \"sequential\" or \"parallel\" when provided.");
1407
1467
  $(e.phoneConfidenceThreshold);
1408
1468
  }
1409
- function le(e) {
1469
+ function _e(e) {
1410
1470
  return typeof e == "number" && Number.isFinite(e) && e >= 0;
1411
1471
  }
1412
1472
  function $(e) {
1413
1473
  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
1474
  }
1415
1475
  //#endregion
1416
- export { Z as MonitorDogDetector, m as MonitorDogSdkError, ie as configureMonitorDogDetector, ae as createMonitorDogDetector, oe as getDetector, h as isMonitorDogSdkError };
1476
+ export { X as MonitorDogDetector, p as MonitorDogSdkError, pe as configureMonitorDogDetector, me as createMonitorDogDetector, Q as getDetector, m as isMonitorDogSdkError };