@monitordog/detector 1.0.11 → 1.0.13
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 +113 -7
- package/bin/monitordog-copy-assets.mjs +140 -0
- package/dist/assets/{inference-worker-KC9Jl3J4.js → inference-worker-Dj9tu4Yg.js} +2 -2
- package/dist/assets/sdk/detector-320.onnx.enc +0 -0
- package/dist/assets/sdk/detector-416.onnx.enc +0 -0
- package/dist/assets/sdk/detector-640.onnx.enc +0 -0
- package/dist/detect/model-loader.d.ts +9 -1
- package/dist/index.d.ts +3 -2
- package/dist/monitordog-detector.js +103 -43
- package/dist/monitordog-detector.umd.cjs +1 -1
- package/dist/runtime-assets.d.ts +2 -0
- package/dist/runtime-options.d.ts +5 -1
- package/dist/service/auth-service.d.ts +4 -1
- package/dist/types.d.ts +5 -0
- package/package.json +6 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { MonitorDogDetectorOptions, MonitorDogDetectorState, MonitorDogLoginRequest, MonitorDogSessionToken, UserPreferences } from "./types";
|
|
1
|
+
import type { MonitorDogDetectorOptions, MonitorDogDetectorState, MonitorDogLoginRequest, MonitorDogRestoreSessionRequest, MonitorDogSessionToken, UserPreferences } from "./types";
|
|
2
2
|
export declare class MonitorDogDetector {
|
|
3
3
|
#private;
|
|
4
4
|
static init(options: MonitorDogDetectorOptions): Promise<MonitorDogDetector>;
|
|
5
5
|
constructor(options: MonitorDogDetectorOptions);
|
|
6
6
|
load(): Promise<void>;
|
|
7
7
|
login(request: MonitorDogLoginRequest): Promise<MonitorDogSessionToken>;
|
|
8
|
+
restoreSession(request?: MonitorDogRestoreSessionRequest): Promise<MonitorDogSessionToken>;
|
|
8
9
|
logout(): Promise<void>;
|
|
9
10
|
start(): Promise<void>;
|
|
10
11
|
stop(): void;
|
|
@@ -38,4 +39,4 @@ export declare function configureMonitorDogDetector(options: MonitorDogDetectorO
|
|
|
38
39
|
export declare function createMonitorDogDetector(options: MonitorDogDetectorOptions): Promise<MonitorDogDetector>;
|
|
39
40
|
export declare function getDetector(): MonitorDogDetector;
|
|
40
41
|
export { MonitorDogSdkError, isMonitorDogSdkError } from "./sdk-error";
|
|
41
|
-
export type { AccountResponse, LockPolicyResponse, MonitorDogDetection, MonitorDogDetectionResult, MonitorDogDetectorCameraStatus, MonitorDogDetectorOptions, MonitorDogDetectorSessionStatus, MonitorDogDetectorState, MonitorDogDetectorStatus, MonitorDogLoginRequest, MonitorDogModelInputSize, MonitorDogPhoneRotationFallbackExecution, MonitorDogSdkErrorCode, MonitorDogSdkTokenResponse, MonitorDogSessionToken, MonitorDogSessionTokenProvider, MonitorDogVideoDetectionResult, UserPreferences, } from "./types";
|
|
42
|
+
export type { AccountResponse, LockPolicyResponse, MonitorDogDetection, MonitorDogDetectionResult, MonitorDogDetectorCameraStatus, MonitorDogDetectorOptions, MonitorDogDetectorSessionStatus, MonitorDogDetectorState, MonitorDogDetectorStatus, MonitorDogLoginRequest, MonitorDogModelInputSize, MonitorDogPhoneRotationFallbackExecution, MonitorDogRestoreSessionRequest, MonitorDogRestoreSessionTokenProvider, MonitorDogSdkErrorCode, MonitorDogSdkTokenResponse, MonitorDogSessionToken, MonitorDogSessionTokenProvider, MonitorDogVideoDetectionResult, UserPreferences, } from "./types";
|
|
@@ -150,12 +150,32 @@ var S = "MonitorDog token refresh was superseded.", C = 300 * 1e3, w = class {
|
|
|
150
150
|
refreshIntervalId;
|
|
151
151
|
authSessionId = 0;
|
|
152
152
|
sessionEmail;
|
|
153
|
+
sessionTokenRefresher;
|
|
153
154
|
constructor(e) {
|
|
154
155
|
this.services = e;
|
|
155
156
|
}
|
|
156
157
|
async login(e) {
|
|
157
158
|
let t = await this.fetchSessionToken(e.email);
|
|
158
|
-
return this.
|
|
159
|
+
return this.establishSession(t, {
|
|
160
|
+
email: e.email,
|
|
161
|
+
refresh: () => this.fetchSessionToken(e.email)
|
|
162
|
+
}), await this.sendUserActivityEvent("login"), t;
|
|
163
|
+
}
|
|
164
|
+
async restoreSession(e) {
|
|
165
|
+
let t = this.services.options.restoreSessionTokenProvider;
|
|
166
|
+
if (t) {
|
|
167
|
+
let n = await t();
|
|
168
|
+
return this.establishSession(n, {
|
|
169
|
+
email: e?.email,
|
|
170
|
+
refresh: t
|
|
171
|
+
}), n;
|
|
172
|
+
}
|
|
173
|
+
if (!e?.email) throw Error("MonitorDog restoreSession requires restoreSessionTokenProvider or an email.");
|
|
174
|
+
let n = await this.fetchSessionToken(e.email);
|
|
175
|
+
return this.establishSession(n, {
|
|
176
|
+
email: e.email,
|
|
177
|
+
refresh: () => this.fetchSessionToken(e.email)
|
|
178
|
+
}), n;
|
|
159
179
|
}
|
|
160
180
|
async logout() {
|
|
161
181
|
if (this.token) try {
|
|
@@ -209,11 +229,14 @@ var S = "MonitorDog token refresh was superseded.", C = 300 * 1e3, w = class {
|
|
|
209
229
|
expiresAt: o(e)
|
|
210
230
|
});
|
|
211
231
|
}
|
|
232
|
+
establishSession(e, t) {
|
|
233
|
+
this.authSessionId += 1, this.sessionEmail = t.email, this.sessionTokenRefresher = t.refresh, this.setSessionTokenPayload(e);
|
|
234
|
+
}
|
|
212
235
|
setTokens(e) {
|
|
213
236
|
this.token = e.accessToken, this.tokenExpiresAt = s(e), this.tokenExpiresAt ? this.startPeriodicRefresh() : this.stopPeriodicRefresh();
|
|
214
237
|
}
|
|
215
238
|
clearTokens() {
|
|
216
|
-
this.authSessionId += 1, this.token = void 0, this.tokenExpiresAt = void 0, this.refreshPromise = void 0, this.sessionEmail = void 0, this.stopPeriodicRefresh();
|
|
239
|
+
this.authSessionId += 1, this.token = void 0, this.tokenExpiresAt = void 0, this.refreshPromise = void 0, this.sessionEmail = void 0, this.sessionTokenRefresher = void 0, this.stopPeriodicRefresh();
|
|
217
240
|
}
|
|
218
241
|
async refreshToken() {
|
|
219
242
|
return this.refreshPromise ||= this.refreshAccessToken().finally(() => {
|
|
@@ -232,9 +255,9 @@ var S = "MonitorDog token refresh was superseded.", C = 300 * 1e3, w = class {
|
|
|
232
255
|
}
|
|
233
256
|
}
|
|
234
257
|
async refreshAccessToken() {
|
|
235
|
-
let e = this.authSessionId, t = this.
|
|
236
|
-
if (!t) throw Error("MonitorDog
|
|
237
|
-
let n = await
|
|
258
|
+
let e = this.authSessionId, t = this.sessionTokenRefresher;
|
|
259
|
+
if (!t) throw Error("MonitorDog SDK session refresh source is not available.");
|
|
260
|
+
let n = await t(), r = i(n);
|
|
238
261
|
if (!r || typeof r != "string") throw Error("MonitorDog SDK token response did not include a token.");
|
|
239
262
|
if (e !== this.authSessionId) throw Error(S);
|
|
240
263
|
return this.setSessionTokenPayload(n), r;
|
|
@@ -590,7 +613,7 @@ function D(e) {
|
|
|
590
613
|
}
|
|
591
614
|
//#endregion
|
|
592
615
|
//#region src/detect/inference-worker.ts?worker&url
|
|
593
|
-
var ae = "" + new URL("assets/inference-worker-
|
|
616
|
+
var ae = "" + new URL("assets/inference-worker-Dj9tu4Yg.js", import.meta.url).href, O = class {
|
|
594
617
|
worker;
|
|
595
618
|
nextRequestId = 1;
|
|
596
619
|
pendingRequests = /* @__PURE__ */ new Map();
|
|
@@ -743,19 +766,32 @@ function R(e, t, n) {
|
|
|
743
766
|
return Math.min(Math.max(e, t), n);
|
|
744
767
|
}
|
|
745
768
|
//#endregion
|
|
769
|
+
//#region src/runtime-assets.ts
|
|
770
|
+
var z = {
|
|
771
|
+
sdk: {
|
|
772
|
+
"detector-320.onnx.enc": new URL("./assets/sdk/detector-320.onnx.enc", import.meta.url).href,
|
|
773
|
+
"detector-416.onnx.enc": new URL("./assets/sdk/detector-416.onnx.enc", import.meta.url).href,
|
|
774
|
+
"detector-640.onnx.enc": new URL("./assets/sdk/detector-640.onnx.enc", import.meta.url).href
|
|
775
|
+
},
|
|
776
|
+
ort: {
|
|
777
|
+
mjs: new URL("./assets/ort/ort-wasm-simd-threaded.mjs", import.meta.url).href,
|
|
778
|
+
wasm: new URL("./assets/ort/ort-wasm-simd-threaded.wasm", import.meta.url).href
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
//#endregion
|
|
746
782
|
//#region src/video.ts
|
|
747
|
-
function
|
|
783
|
+
function B(e) {
|
|
748
784
|
return e.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA && e.videoWidth > 0 && e.videoHeight > 0 && !e.paused && !e.ended;
|
|
749
785
|
}
|
|
750
|
-
function
|
|
751
|
-
return
|
|
786
|
+
function V(e, t = 1e4) {
|
|
787
|
+
return H(e) ? Promise.resolve() : new Promise((n, r) => {
|
|
752
788
|
let i = window.setTimeout(() => {
|
|
753
789
|
o(), r(/* @__PURE__ */ Error("Timed out waiting for webcam video metadata."));
|
|
754
790
|
}, t), a = window.setInterval(s, 100), o = () => {
|
|
755
791
|
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);
|
|
756
792
|
};
|
|
757
793
|
function s() {
|
|
758
|
-
|
|
794
|
+
H(e) && (o(), n());
|
|
759
795
|
}
|
|
760
796
|
let c = () => {
|
|
761
797
|
s();
|
|
@@ -765,12 +801,12 @@ function B(e, t = 1e4) {
|
|
|
765
801
|
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 });
|
|
766
802
|
});
|
|
767
803
|
}
|
|
768
|
-
function
|
|
804
|
+
function H(e) {
|
|
769
805
|
return e.readyState >= HTMLMediaElement.HAVE_METADATA && e.videoWidth > 0 && e.videoHeight > 0;
|
|
770
806
|
}
|
|
771
807
|
//#endregion
|
|
772
808
|
//#region src/service/detect-service.ts
|
|
773
|
-
var
|
|
809
|
+
var U = 700, oe = .25, W = .8, G = class {
|
|
774
810
|
services;
|
|
775
811
|
primaryInferenceWorker;
|
|
776
812
|
rotationInferenceWorker;
|
|
@@ -822,7 +858,7 @@ var H = 700, U = .25, oe = .8, W = class {
|
|
|
822
858
|
let t = !1, n, r = this.services.options.detectionIntervalMs, i = async () => {
|
|
823
859
|
if (!t) {
|
|
824
860
|
try {
|
|
825
|
-
if (!this.services.shouldPauseDetection &&
|
|
861
|
+
if (!this.services.shouldPauseDetection && B(e)) {
|
|
826
862
|
let n = await this.detect(e);
|
|
827
863
|
if (t) return;
|
|
828
864
|
try {
|
|
@@ -853,7 +889,7 @@ var H = 700, U = .25, oe = .8, W = class {
|
|
|
853
889
|
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;
|
|
854
890
|
i.muted = !0, i.playsInline = !0, i.srcObject = t;
|
|
855
891
|
try {
|
|
856
|
-
await Promise.all([i.play(),
|
|
892
|
+
await Promise.all([i.play(), V(i)]);
|
|
857
893
|
} catch (e) {
|
|
858
894
|
throw n.stopStream(t), i.pause(), r ? i.srcObject = null : (i.muted = a, i.playsInline = o, i.srcObject = s), e;
|
|
859
895
|
}
|
|
@@ -879,7 +915,7 @@ var H = 700, U = .25, oe = .8, W = class {
|
|
|
879
915
|
candidate: e,
|
|
880
916
|
observedAt: t
|
|
881
917
|
}))], r.length === 0) return e;
|
|
882
|
-
let i = [...e.phoneDetections, ...r.map(
|
|
918
|
+
let i = [...e.phoneDetections, ...r.map(se)];
|
|
883
919
|
return {
|
|
884
920
|
...e,
|
|
885
921
|
phoneDetected: !0,
|
|
@@ -888,10 +924,10 @@ var H = 700, U = .25, oe = .8, W = class {
|
|
|
888
924
|
};
|
|
889
925
|
}
|
|
890
926
|
isTemporallyConfirmedPhoneCandidate(e, t) {
|
|
891
|
-
return
|
|
927
|
+
return K(e) ? t.some(({ candidate: t }) => q(e, t) && ce(e, t) >= oe) : !1;
|
|
892
928
|
}
|
|
893
929
|
getRecentPhoneCandidateHistory(e) {
|
|
894
|
-
return this.phoneCandidateHistory.filter((t) => e - t.observedAt <=
|
|
930
|
+
return this.phoneCandidateHistory.filter((t) => e - t.observedAt <= U);
|
|
895
931
|
}
|
|
896
932
|
prunePhoneCandidateHistory(e) {
|
|
897
933
|
this.phoneCandidateHistory = this.getRecentPhoneCandidateHistory(e);
|
|
@@ -975,6 +1011,7 @@ var H = 700, U = .25, oe = .8, W = class {
|
|
|
975
1011
|
apiBaseUrl: t.apiBaseUrl,
|
|
976
1012
|
accessToken: e,
|
|
977
1013
|
inputSize: t.inputSize,
|
|
1014
|
+
runtimeAssetUrls: z,
|
|
978
1015
|
runtimeAssetBaseUrl: t.runtimeAssetBaseUrl
|
|
979
1016
|
};
|
|
980
1017
|
if (this.shouldUseParallelPhoneRotationFallback(t)) {
|
|
@@ -984,13 +1021,13 @@ var H = 700, U = .25, oe = .8, W = class {
|
|
|
984
1021
|
await this.getInferenceWorker().load(n);
|
|
985
1022
|
}
|
|
986
1023
|
};
|
|
987
|
-
function
|
|
988
|
-
return e.handOverlapped || e.score >=
|
|
1024
|
+
function K(e) {
|
|
1025
|
+
return e.handOverlapped || e.score >= W;
|
|
989
1026
|
}
|
|
990
|
-
function
|
|
991
|
-
return e.handOverlapped === t.handOverlapped ?
|
|
1027
|
+
function q(e, t) {
|
|
1028
|
+
return e.handOverlapped === t.handOverlapped ? K(t) : !1;
|
|
992
1029
|
}
|
|
993
|
-
function
|
|
1030
|
+
function se(e) {
|
|
994
1031
|
return {
|
|
995
1032
|
classId: e.classId,
|
|
996
1033
|
label: e.label,
|
|
@@ -1002,7 +1039,7 @@ function q(e) {
|
|
|
1002
1039
|
height: e.height
|
|
1003
1040
|
};
|
|
1004
1041
|
}
|
|
1005
|
-
function
|
|
1042
|
+
function ce(e, t) {
|
|
1006
1043
|
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
1044
|
return s <= 0 ? 0 : o / s;
|
|
1008
1045
|
}
|
|
@@ -1011,7 +1048,7 @@ function J(e) {
|
|
|
1011
1048
|
}
|
|
1012
1049
|
//#endregion
|
|
1013
1050
|
//#region src/service/webcam-service.ts
|
|
1014
|
-
var
|
|
1051
|
+
var le = class {
|
|
1015
1052
|
services;
|
|
1016
1053
|
isWebcamRunning = !1;
|
|
1017
1054
|
stopCurrentWebcam;
|
|
@@ -1103,7 +1140,7 @@ var ce = class {
|
|
|
1103
1140
|
removeVisibilityListener() {
|
|
1104
1141
|
typeof document > "u" || document.removeEventListener("visibilitychange", this.handleVisibilityChange);
|
|
1105
1142
|
}
|
|
1106
|
-
},
|
|
1143
|
+
}, ue = class {
|
|
1107
1144
|
auth;
|
|
1108
1145
|
camera;
|
|
1109
1146
|
detectionEvents;
|
|
@@ -1115,7 +1152,7 @@ var ce = class {
|
|
|
1115
1152
|
#t = Y();
|
|
1116
1153
|
#n;
|
|
1117
1154
|
constructor(e) {
|
|
1118
|
-
this.#n = e, this.camera = new te(), this.auth = new w(this), this.detectionEvents = new ie(this), this.detect = new
|
|
1155
|
+
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);
|
|
1119
1156
|
}
|
|
1120
1157
|
get options() {
|
|
1121
1158
|
return Object.freeze({ ...this.#n() });
|
|
@@ -1151,7 +1188,7 @@ var ce = class {
|
|
|
1151
1188
|
}
|
|
1152
1189
|
applyPolicyItems(e, t) {
|
|
1153
1190
|
let n = { ...this.#t };
|
|
1154
|
-
for (let t of e)
|
|
1191
|
+
for (let t of e) fe(n, t);
|
|
1155
1192
|
this.#t = n, this.syncEffectivePhoneConfidenceThreshold(), this.#n().faceConfidenceThreshold = n.faceDetectionThreshold, this.updateRequiredPasswordFromServer(!1);
|
|
1156
1193
|
}
|
|
1157
1194
|
resetAuthenticatedState() {
|
|
@@ -1178,11 +1215,11 @@ function Y() {
|
|
|
1178
1215
|
multiPersonDetectionMode: "auto_lock"
|
|
1179
1216
|
};
|
|
1180
1217
|
}
|
|
1181
|
-
function
|
|
1218
|
+
function de(e) {
|
|
1182
1219
|
return e === "none";
|
|
1183
1220
|
}
|
|
1184
|
-
function
|
|
1185
|
-
let n = t.policy, r = !
|
|
1221
|
+
function fe(e, t) {
|
|
1222
|
+
let n = t.policy, r = !de(t.policy), i = t.seconds * 1e3, a = "sensitivity" in t ? 1 - t.sensitivity / 100 : void 0;
|
|
1186
1223
|
switch (t.basic_event_uuid) {
|
|
1187
1224
|
case x("mobileDevice"):
|
|
1188
1225
|
e.mobileDetectionEnabled = r, e.mobileDetectionLockDuration = i, e.mobileDetectionMode = n, a !== void 0 && (e.mobileDetectionThreshold = a);
|
|
@@ -1210,8 +1247,8 @@ var X = class e {
|
|
|
1210
1247
|
return Z = new e(t), Z;
|
|
1211
1248
|
}
|
|
1212
1249
|
constructor(e) {
|
|
1213
|
-
|
|
1214
|
-
let r =
|
|
1250
|
+
Q(e);
|
|
1251
|
+
let r = _e(), i = f(e.runtimeAssetBaseUrl);
|
|
1215
1252
|
this.#t = {
|
|
1216
1253
|
...e,
|
|
1217
1254
|
apiBaseUrl: c(e.apiBaseUrl),
|
|
@@ -1228,7 +1265,7 @@ var X = class e {
|
|
|
1228
1265
|
phoneRotationFallback: e.phoneRotationFallback ?? !1,
|
|
1229
1266
|
phoneRotationFallbackMinIntervalMs: e.phoneRotationFallbackMinIntervalMs ?? 500,
|
|
1230
1267
|
phoneRotationFallbackExecution: e.phoneRotationFallbackExecution ?? "sequential"
|
|
1231
|
-
}, this.#e = new
|
|
1268
|
+
}, this.#e = new ue(() => this.#t), this.#e.onLoginRequired = () => this.resetLoggedOutState(), Object.freeze(this);
|
|
1232
1269
|
}
|
|
1233
1270
|
async load() {
|
|
1234
1271
|
this.assertUsable(), this.assertAuthenticated("loading detection");
|
|
@@ -1267,6 +1304,28 @@ var X = class e {
|
|
|
1267
1304
|
lastError: void 0
|
|
1268
1305
|
}), t;
|
|
1269
1306
|
}
|
|
1307
|
+
async restoreSession(e) {
|
|
1308
|
+
this.assertUsable();
|
|
1309
|
+
let t;
|
|
1310
|
+
try {
|
|
1311
|
+
t = await this.#e.auth.restoreSession(e);
|
|
1312
|
+
} catch (e) {
|
|
1313
|
+
let t = this.createSdkError("SESSION_TOKEN_FAILED", "MonitorDog SDK session token could not be restored.", e);
|
|
1314
|
+
throw this.transitionToError(t), this.#t.onAuthError?.(t), t;
|
|
1315
|
+
}
|
|
1316
|
+
try {
|
|
1317
|
+
await this.completeAuthenticatedLogin();
|
|
1318
|
+
} catch (e) {
|
|
1319
|
+
let t = this.createSdkError("ACCOUNT_POLICY_FAILED", "MonitorDog account or policy could not be loaded.", e);
|
|
1320
|
+
throw this.rollbackAuthenticatedLogin(), this.transitionToError(t), this.#t.onAuthError?.(t), t;
|
|
1321
|
+
}
|
|
1322
|
+
return this.updateState({
|
|
1323
|
+
session: "authenticated",
|
|
1324
|
+
runtime: this.#r === "stopped" ? "stopped" : "idle",
|
|
1325
|
+
camera: this.#e.webcam.isRunning ? "active" : "idle",
|
|
1326
|
+
lastError: void 0
|
|
1327
|
+
}), t;
|
|
1328
|
+
}
|
|
1270
1329
|
async logout() {
|
|
1271
1330
|
if (this.assertUsable(), this.isDetectorRunning()) throw this.lifecycleError("DETECTOR_RUNNING", "MonitorDog detector is running. Call stop() before logout().");
|
|
1272
1331
|
if (!this.#e.auth.getToken()) {
|
|
@@ -1365,7 +1424,7 @@ var X = class e {
|
|
|
1365
1424
|
});
|
|
1366
1425
|
} catch (e) {
|
|
1367
1426
|
let t = this.createSdkError(this.getStartErrorCode(e), this.getStartErrorMessage(e), e);
|
|
1368
|
-
throw this.transitionToError(t,
|
|
1427
|
+
throw this.transitionToError(t, pe(t.code) ? "blocked" : "idle"), this.#t.onError?.(t), t;
|
|
1369
1428
|
}
|
|
1370
1429
|
}
|
|
1371
1430
|
clearSessionState() {
|
|
@@ -1437,40 +1496,41 @@ var X = class e {
|
|
|
1437
1496
|
return typeof DOMException < "u" && e instanceof DOMException && e.name === "NotReadableError";
|
|
1438
1497
|
}
|
|
1439
1498
|
};
|
|
1440
|
-
function
|
|
1499
|
+
function pe(e) {
|
|
1441
1500
|
return e === "CAMERA_PERMISSION_DENIED" || e === "CAMERA_READ_FAILED";
|
|
1442
1501
|
}
|
|
1443
1502
|
var Z;
|
|
1444
|
-
function
|
|
1503
|
+
function me(e) {
|
|
1445
1504
|
return Z = new X(e), Z;
|
|
1446
1505
|
}
|
|
1447
|
-
async function
|
|
1506
|
+
async function he(e) {
|
|
1448
1507
|
return X.init(e);
|
|
1449
1508
|
}
|
|
1450
|
-
function
|
|
1509
|
+
function ge() {
|
|
1451
1510
|
if (!Z) throw Error("MonitorDog is not configured. Call MonitorDogDetector.init(), createMonitorDogDetector(), or configureMonitorDogDetector() before using getDetector().");
|
|
1452
1511
|
return Z;
|
|
1453
1512
|
}
|
|
1454
|
-
function
|
|
1513
|
+
function _e() {
|
|
1455
1514
|
if (typeof navigator > "u") return !1;
|
|
1456
1515
|
let e = l();
|
|
1457
1516
|
return e === "mobile" || e === "tablet";
|
|
1458
1517
|
}
|
|
1459
|
-
function
|
|
1518
|
+
function Q(e) {
|
|
1460
1519
|
if (!e || typeof e.apiBaseUrl != "string" || e.apiBaseUrl.length === 0) throw Error("MonitorDog apiBaseUrl is required.");
|
|
1461
1520
|
if (typeof e.sessionTokenProvider != "function") throw Error("MonitorDog sessionTokenProvider is required.");
|
|
1521
|
+
if (e.restoreSessionTokenProvider !== void 0 && typeof e.restoreSessionTokenProvider != "function") throw Error("MonitorDog restoreSessionTokenProvider must be a function when provided.");
|
|
1462
1522
|
if (typeof e.onDetect != "function") throw Error("MonitorDog onDetect callback is required.");
|
|
1463
1523
|
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.");
|
|
1464
1524
|
if (e.phoneRotationFallback !== void 0 && typeof e.phoneRotationFallback != "boolean") throw Error("MonitorDog phoneRotationFallback must be a boolean when provided.");
|
|
1465
|
-
if (e.phoneRotationFallbackMinIntervalMs !== void 0 && !
|
|
1525
|
+
if (e.phoneRotationFallbackMinIntervalMs !== void 0 && !ve(e.phoneRotationFallbackMinIntervalMs)) throw Error("MonitorDog phoneRotationFallbackMinIntervalMs must be a non-negative finite number when provided.");
|
|
1466
1526
|
if (e.phoneRotationFallbackExecution !== void 0 && e.phoneRotationFallbackExecution !== "sequential" && e.phoneRotationFallbackExecution !== "parallel") throw Error("MonitorDog phoneRotationFallbackExecution must be \"sequential\" or \"parallel\" when provided.");
|
|
1467
1527
|
$(e.phoneConfidenceThreshold);
|
|
1468
1528
|
}
|
|
1469
|
-
function
|
|
1529
|
+
function ve(e) {
|
|
1470
1530
|
return typeof e == "number" && Number.isFinite(e) && e >= 0;
|
|
1471
1531
|
}
|
|
1472
1532
|
function $(e) {
|
|
1473
1533
|
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.");
|
|
1474
1534
|
}
|
|
1475
1535
|
//#endregion
|
|
1476
|
-
export { X as MonitorDogDetector, p as MonitorDogSdkError,
|
|
1536
|
+
export { X as MonitorDogDetector, p as MonitorDogSdkError, me as configureMonitorDogDetector, he as createMonitorDogDetector, ge as getDetector, m as isMonitorDogSdkError };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("html2canvas")):typeof define==`function`&&define.amd?define([`exports`,`html2canvas`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.MonitorDogDetector={},e.html2canvas))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,c=(e,t,n,o)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=a(t),l=0,u=c.length,d;l<u;l++)d=c[l],!s.call(e,d)&&d!==n&&r(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(o=i(t,d))||o.enumerable});return e};t=((e,t,i)=>(i=e==null?{}:n(o(e)),c(t||!e||!e.__esModule?r(i,`default`,{value:e,enumerable:!0}):i,e)))(t,1);var l=.8,u=.7,d=3e4;function f(e){return typeof e==`string`?e:e.access_token}function p(e){if(typeof e!=`string`)return e.expires_in}function ee(e){if(typeof e!=`string`)return e.expires_at}function te(e){if(e.expiresAt){let t=Date.parse(e.expiresAt);if(!Number.isNaN(t))return t}if(e.expiresIn)return e.expiresIn>1e9?e.expiresIn*1e3:Date.now()+e.expiresIn*1e3}function m(e){return e.replace(/\/+$/,``)}function h(){if(typeof navigator>`u`)return`none`;let e=navigator.userAgent.toLowerCase();return/ipad|tablet/.test(e)?`tablet`:/mobile|iphone|ipod|android/.test(e)?`mobile`:/macintosh|windows|linux/.test(e)?`desktop`:`other`}function g(){if(typeof navigator>`u`)return`none`;let e=navigator.userAgent.toLowerCase(),t=navigator.platform.toLowerCase();return/win/.test(t)||/windows/.test(e)?`windows`:/mac/.test(t)||/mac os/.test(e)?`macos`:/android/.test(e)?`android`:/iphone|ipad|ipod/.test(e)?`ios`:/linux/.test(t)||/linux/.test(e)?`linux`:`other`}function ne(e){return e===`auto`||e===320||e===416||e===640}function re(e,t){let n=e??`auto`;return n===`auto`?t?416:640:n}function _(e){if(e===void 0)return;let t=e.trim();if(t.length===0)throw Error(`MonitorDog runtimeAssetBaseUrl must be a non-empty string when provided.`);let n=t.replace(/\/+$/,``);return n.length===0?`/`:n}var v=class extends Error{code;cause;constructor(e,t,n){super(t),this.name=`MonitorDogSdkError`,this.code=e,this.cause=n}};function y(e){return e instanceof v}function b(e){if(e.faceCount===0)return C(`noFaceDetected`,e);if(e.faceCount>=2)return C(`twoFacesDetected`,e);if(e.phoneCount>=1)return C(`mobileDevice`,e)}function x(e){return{...w(e,new Date().toISOString()),properties:{},webcam_imgs:[],monitor_imgs:[]}}function S(e){return e.phoneCount===0&&e.faceCount===1}function C(e,t){let n=w(e,new Date().toISOString());switch(e){case`noFaceDetected`:return{type:e,payload:{...n,properties:{confidence:0,spots:[]}}};case`twoFacesDetected`:return{type:e,payload:{...n,properties:{confidence:T(t.faceDetections),spots:t.faceDetections}}};case`mobileDevice`:return{type:e,payload:{...n,properties:{confidence:T(t.phoneDetections),spots:t.phoneDetections}}}}}function w(e,t){return{basic_event_uuid:E(e),occured_at:t,sended_at:new Date().toISOString(),device_type:h(),device_os:g(),device_id:`browser`}}function T(e){return e.reduce((e,t)=>Math.max(e,t.score),0)}function E(e){switch(e){case`logout`:return`12ca646a-d832-4581-b03c-48f95627507f`;case`login`:return`4c6f98ea-88d8-4215-9b6a-9b3ccb753465`;case`mobileDevice`:return`027af5c9-297d-4a64-983f-4199ca4b9dad`;case`twoFacesDetected`:return`d555efac-7465-4067-8056-611e95385807`;case`noFaceDetected`:return`e2c48c23-36e2-4253-82b1-7f6565fdcfc3`;default:return``}}var D=`MonitorDog token refresh was superseded.`,ie=300*1e3,ae=class{services;refreshBeforeMs=ie;periodicRefreshIntervalMs=d;token;tokenExpiresAt;refreshPromise;refreshIntervalId;authSessionId=0;sessionEmail;constructor(e){this.services=e}async login(e){let t=await this.fetchSessionToken(e.email);return this.sessionEmail=e.email,this.setSessionTokenPayload(t),await this.sendUserActivityEvent(`login`),t}async logout(){if(this.token)try{await this.sendUserActivityEvent(`logout`)}finally{this.clearTokens()}}getToken(){return this.token}getTokenExpiresAt(){return this.tokenExpiresAt}getSessionEmail(){return this.sessionEmail}isAuthenticated(){return!!this.token}dispose(){this.clearTokens()}assertAuthenticated(){if(!this.token)throw Error(`MonitorDog login is required before detection.`)}async getValidAccessToken(){if(this.shouldRefreshCurrentToken())try{await this.handleAuthRefresh()}catch(e){if(this.token&&this.tokenExpiresAt&&Date.now()<this.tokenExpiresAt)return this.token;throw e}return this.token}async authorizedFetch(e,t={},n=!0){let r=await this.getValidAccessToken(),i=new Headers(t.headers);r&&(i.set(`authorization`,`Bearer ${r}`),i.set(`Device-Access-Token`,r));let a=await fetch(`${this.services.options.apiBaseUrl}${e}`,{...t,headers:i}),o=await this.getApiErrorCode(a);return a.status===400&&o===4221&&this.handleLoginRequired(),n&&this.shouldRefreshAfterAuthError(a,o)?(await this.handleAuthRefresh(),this.authorizedFetch(e,t,!1)):a}setSessionTokenPayload(e){let t=f(e);if(!t||typeof t!=`string`)throw Error(`MonitorDog SDK token response did not include a token.`);this.setTokens({accessToken:t,expiresIn:p(e),expiresAt:ee(e)})}setTokens(e){this.token=e.accessToken,this.tokenExpiresAt=te(e),this.tokenExpiresAt?this.startPeriodicRefresh():this.stopPeriodicRefresh()}clearTokens(){this.authSessionId+=1,this.token=void 0,this.tokenExpiresAt=void 0,this.refreshPromise=void 0,this.sessionEmail=void 0,this.stopPeriodicRefresh()}async refreshToken(){return this.refreshPromise||=this.refreshAccessToken().finally(()=>{this.refreshPromise=void 0}),this.refreshPromise}async handleAuthRefresh(){try{return await this.refreshToken()}catch(e){if(!this.isRefreshSupersededError(e)){let t=this.createSdkError(`SESSION_TOKEN_FAILED`,`MonitorDog SDK session token refresh failed.`,e);this.services.options.onAuthError?.(t),this.isCurrentTokenExpired()&&(this.clearTokens(),this.services.onLoginRequired?.())}throw e}}async refreshAccessToken(){let e=this.authSessionId,t=this.sessionEmail;if(!t)throw Error(`MonitorDog login email is required to refresh SDK token.`);let n=await this.fetchSessionToken(t),r=f(n);if(!r||typeof r!=`string`)throw Error(`MonitorDog SDK token response did not include a token.`);if(e!==this.authSessionId)throw Error(D);return this.setSessionTokenPayload(n),r}startPeriodicRefresh(){this.refreshIntervalId||=setInterval(()=>{this.refreshPeriodically()},this.periodicRefreshIntervalMs)}stopPeriodicRefresh(){this.refreshIntervalId&&=(clearInterval(this.refreshIntervalId),void 0)}async refreshPeriodically(){if(!(!this.token||!this.shouldRefreshCurrentToken()))try{await this.handleAuthRefresh()}catch{}}shouldRefreshCurrentToken(){return!!(this.token&&this.tokenExpiresAt&&Date.now()>=this.tokenExpiresAt-this.refreshBeforeMs)}isCurrentTokenExpired(){return!!(this.tokenExpiresAt&&Date.now()>=this.tokenExpiresAt)}isRefreshSupersededError(e){return e instanceof Error&&e.message===D}async fetchSessionToken(e){let t=this.services.options.sessionTokenProvider;if(!t)throw Error(`MonitorDog sessionTokenProvider is required for SDK login.`);return t({email:e})}async getApiErrorCode(e){if(e.status===400)try{let t=await e.clone().json();if(typeof t==`object`&&t&&`code`in t&&typeof t.code==`number`)return t.code}catch{return}}shouldRefreshAfterAuthError(e,t){return e.status===401?!0:e.status===400&&t===422}handleLoginRequired(){this.clearTokens(),this.services.onLoginRequired?.();let e=this.createSdkError(`NOT_LOGGED_IN`,`MonitorDog login is required.`);throw this.services.options.onAuthError?.(e),e}async sendUserActivityEvent(e){try{let t=await this.authorizedFetch(`/event`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(x(e))});if(!t.ok)throw Error(`MonitorDog ${e} event failed: ${t.status}`)}catch(t){let n=this.createSdkError(oe(e),`MonitorDog ${e} event failed.`,t);if(this.services.options.onAuthError?.(n),e===`logout`)throw n}}createSdkError(e,t,n){return n instanceof v?n:new v(e,t,n)}};function oe(e){return e===`logout`?`LOGOUT_FAILED`:`SESSION_TOKEN_FAILED`}var se=/(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,ce=class{async createWebcamStream(e){if(!navigator.mediaDevices?.getUserMedia)throw Error(`getUserMedia is not available in this browser.`);let t=this.getBaseWebcamConstraints(e),n=await this.createFirstCameraConstraints(t);try{return await this.getUserMedia(n)}catch(e){if(this.isPermissionError(e)||this.isCameraRequestTimeoutError(e))throw e;return this.createFallbackWebcamStream(n,e)}}stopStream(e){e.getTracks().forEach(e=>e.stop())}watchStreamDeviceDisconnect(e,t,n=1e3){let r=e.getVideoTracks()[0],i=r?.getSettings().deviceId;if(!r&&!i)return()=>{};let a=!1,o,s=()=>{a||(a=!0,t())},c=()=>{i&&(o&&clearTimeout(o),o=setTimeout(()=>{o=void 0,this.handleDeviceChange(i,s)},n))};return r?.addEventListener(`ended`,s),navigator.mediaDevices?.addEventListener?.(`devicechange`,c),()=>{o&&clearTimeout(o),r?.removeEventListener(`ended`,s),navigator.mediaDevices?.removeEventListener?.(`devicechange`,c)}}isCameraInUse(e){let t=e?.srcObject;return t instanceof MediaStream?t.getTracks().some(e=>e.readyState===`live`):!1}async getVideoInputDevices(){return navigator.mediaDevices?.enumerateDevices?(await navigator.mediaDevices.enumerateDevices()).filter(e=>e.kind===`videoinput`):[]}async getRealVideoInputDevices(){let e=await this.getVideoInputDevices(),t=e.filter(e=>!this.isVirtualCamera(e));return t.length>0?t:e}async createFallbackWebcamStream(e,t){let n=await this.getRealVideoInputDevices();if(n.length===0)throw t;let r=n[0],i=t;if(!r?.deviceId)throw i;let a=await this.getWebcamNaturalAspectRatio(r.deviceId),o=this.generateResolutionList(a,720);for(let t of o)try{return await this.getUserMedia(this.createDeviceConstraints(e,r.deviceId,t))}catch(e){i=e}throw i}async handleDeviceChange(e,t){try{(await this.getVideoInputDevices()).some(t=>t.deviceId===e)||t()}catch{}}getBaseWebcamConstraints(e){return e??{audio:!1,video:{facingMode:`user`}}}async createFirstCameraConstraints(e){let t=typeof e.video==`object`?e.video:{};if(`deviceId`in t||`facingMode`in t)return e;let n=(await this.getRealVideoInputDevices())[0];return n?.deviceId?this.createDeviceConstraints(e,n.deviceId):e}async getWebcamNaturalAspectRatio(e){let t;try{t=await this.getUserMedia({audio:!1,video:{deviceId:{exact:e}}});let n=t.getVideoTracks()[0]?.getSettings();if(n?.width&&n.height)return n.width/n.height}catch{}finally{t?.getTracks().forEach(e=>e.stop())}return 16/9}generateResolutionList(e,t){return[t,640,600,480,320,240].map(t=>({width:t,height:Math.max(1,Math.round(t/e))})).filter(e=>e.width<=t&&e.height>=120&&e.height<=1080)}createDeviceConstraints(e,t,n){let r=typeof e.video==`object`?e.video:{};return{...e,audio:e.audio??!1,video:{...r,deviceId:{exact:t},...n?{width:{min:n.width,ideal:n.width},height:{min:n.height,ideal:n.height}}:{}}}}isVirtualCamera(e){let t=e.label.toLowerCase();return t?se.test(t):!1}isPermissionError(e){return e instanceof DOMException&&(e.name===`NotAllowedError`||e.name===`SecurityError`)}getUserMedia(e,t=15e3){let n=!1,r,i=navigator.mediaDevices.getUserMedia(e).then(e=>{if(n)throw this.stopStream(e),Error(`Camera permission request timed out.`);return e}),a=new Promise((e,i)=>{r=setTimeout(()=>{n=!0,i(Error(`Camera permission request timed out.`))},t)});return Promise.race([i,a]).finally(()=>{r&&clearTimeout(r)})}isCameraRequestTimeoutError(e){return e instanceof Error&&e.message===`Camera permission request timed out.`}};function O(e){if(e.videoWidth===0||e.videoHeight===0)throw Error(`Video frame is not ready for capture.`);let t=document.createElement(`canvas`),n=t.getContext(`2d`);if(!n)throw Error(`2D canvas context is not available.`);return t.width=e.videoWidth,t.height=e.videoHeight,n.drawImage(e,0,0,t.width,t.height),new Promise((e,n)=>{t.toBlob(t=>{if(!t){n(Error(`Failed to capture video frame.`));return}e(t)},`image/jpeg`,.9)})}async function k(){if(typeof document>`u`||!document.body)return null;let e=await(0,t.default)(document.body,{backgroundColor:`#ffffff`,useCORS:!0});return new Promise(t=>{e.toBlob(t,`image/jpeg`,.9)})}var A=class e{static NO_FACE_STARTUP_GRACE_MS=1500;services;detectionEventLocked=!1;detectionEventInFlight=!1;detectionEventLockTimeoutId;noFaceStartedAt;suppressNoFaceUntil=0;constructor(e){this.services=e}async handleDetectionResult(e,t){if(!this.services.options.eventReportingEnabled){this.reset();return}if(S(e)){this.noFaceStartedAt=void 0,this.clearLock();return}if(this.detectionEventLocked||this.detectionEventInFlight)return;let n=b(e);if(!n){this.noFaceStartedAt=void 0;return}if(!(n.type===`noFaceDetected`&&!this.hasNoFaceDelayElapsed())&&(n.type!==`noFaceDetected`&&(this.noFaceStartedAt=void 0),this.shouldSendEvent(n.type,e))){this.lock(n.type),this.detectionEventInFlight=!0;try{let e=await this.uploadWebcamImage(t);e&&(n.payload.webcam_imgs=e);let r=await this.uploadMonitorImage();if(r&&(n.payload.monitor_imgs=r),this.services.options.debug){console.log(n.payload);return}let i=await this.services.auth.authorizedFetch(`/event`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(n.payload)});if(!i.ok)throw Error(`MonitorDog event request failed: ${i.status}`)}finally{this.detectionEventInFlight=!1}}}reset(){this.clearLock(),this.noFaceStartedAt=void 0,this.suppressNoFaceUntil=0}resetForWebcamStartup(){this.clearLock(),this.noFaceStartedAt=void 0,this.suppressNoFaceUntil=Date.now()+e.NO_FACE_STARTUP_GRACE_MS}clearTransientState(){this.noFaceStartedAt=void 0}async uploadWebcamImage(e){if(!(e instanceof HTMLVideoElement)||e.videoWidth===0||e.videoHeight===0)return;let t=await O(e);return this.uploadImage(t,`webcam.jpg`)}async uploadMonitorImage(){let e=this.services.options.captureMonitorImage?await this.services.options.captureMonitorImage():await k();if(!e)return;let t=typeof File<`u`&&e instanceof File?e.name:`monitor.jpg`;return this.uploadImage(e,t)}async uploadImage(e,t){let n=new FormData;n.append(`files`,e,t);let r=await this.services.auth.authorizedFetch(`/file/image`,{method:`POST`,body:n});if(!r.ok)throw Error(`MonitorDog image upload failed: ${r.status}`);return r.json()}shouldSendEvent(e,t){switch(e){case`mobileDevice`:return this.services.userPreferences.mobileDetectionEnabled&&j(t.phoneDetections)>=this.services.options.confidenceThreshold;case`twoFacesDetected`:return this.services.userPreferences.multiPersonDetectionEnabled&&j(t.faceDetections)>=this.services.userPreferences.faceDetectionThreshold;case`noFaceDetected`:return this.services.userPreferences.noPersonDetectionEnabled}}lock(e){this.clearLock(),this.detectionEventLocked=!0;let t=this.getLockDuration(e);if(t<=0){this.detectionEventLocked=!1;return}this.detectionEventLockTimeoutId=setTimeout(()=>{this.detectionEventLocked=!1,this.detectionEventLockTimeoutId=void 0},t)}clearLock(){this.detectionEventLockTimeoutId&&=(clearTimeout(this.detectionEventLockTimeoutId),void 0),this.detectionEventLocked=!1}hasNoFaceDelayElapsed(){if(Date.now()<this.suppressNoFaceUntil)return this.noFaceStartedAt=void 0,!1;if(this.services.noFaceEventDelayMs<=0)return!0;let e=Date.now();return this.noFaceStartedAt===void 0?(this.noFaceStartedAt=e,!1):e-this.noFaceStartedAt>=this.services.noFaceEventDelayMs}getLockDuration(e){switch(e){case`mobileDevice`:return this.services.userPreferences.mobileDetectionLockDuration;case`twoFacesDetected`:return this.services.userPreferences.multiPersonLockDuration;case`noFaceDetected`:return this.services.userPreferences.noPersonLockDuration}}};function j(e){return e.reduce((e,t)=>Math.max(e,t.score),0)}var M=``+(typeof document>`u`&&typeof location>`u`?require("url").pathToFileURL(__dirname+`/assets/inference-worker-KC9Jl3J4.js`).href:new URL(`assets/inference-worker-KC9Jl3J4.js`,typeof document>`u`?location.href:document.currentScript&&document.currentScript.tagName.toUpperCase()===`SCRIPT`&&document.currentScript.src||document.baseURI).href),N=class{worker;nextRequestId=1;pendingRequests=new Map;async load(e){let t={id:this.nextRequestId,type:`load`,model:e};await this.request(t)}run(e){let t=e.source.kind===`bitmap`?[e.source.bitmap]:[e.source.data.buffer];return this.request({id:this.nextRequestId,type:`run`,source:e.source,inputSize:e.inputSize,inputType:e.inputType,confidenceThreshold:e.confidenceThreshold,faceConfidenceThreshold:e.faceConfidenceThreshold,iouThreshold:e.iouThreshold,maxDetections:e.maxDetections,debug:e.debug,inputRotation:e.inputRotation??`none`,phoneRotationFallback:e.phoneRotationFallback,phoneRotationFallbackMinIntervalMs:e.phoneRotationFallbackMinIntervalMs},t)}terminate(){this.rejectPendingRequests(Error(`Inference worker was terminated.`)),this.worker?.terminate(),this.worker=void 0}request(e,t=[]){let n=this.getWorker();return this.nextRequestId+=1,new Promise((r,i)=>{this.pendingRequests.set(e.id,{resolve:r,reject:i}),n.postMessage(e,t)})}getWorker(){return this.worker||(this.worker=new Worker(M,{name:`MonitorDogInference`,type:`module`}),this.worker.addEventListener(`message`,this.handleMessage),this.worker.addEventListener(`error`,this.handleError),this.worker.addEventListener(`messageerror`,this.handleError)),this.worker}handleMessage=e=>{let t=e.data,n=this.pendingRequests.get(t.id);if(n){if(this.pendingRequests.delete(t.id),!t.ok){n.reject(Error(t.error));return}n.resolve(t.result)}};handleError=e=>{let t=e instanceof ErrorEvent?e.message:`Inference worker message failed.`;this.rejectPendingRequests(Error(t)),this.worker?.terminate(),this.worker=void 0};rejectPendingRequests(e){for(let t of this.pendingRequests.values())t.reject(e);this.pendingRequests.clear()}};async function P(e){let{sourceWidth:t,sourceHeight:n}=F(e);if(e instanceof ImageData)return{kind:`rgba`,data:new Uint8ClampedArray(e.data),sourceWidth:t,sourceHeight:n};if(I()&&L())try{return{kind:`bitmap`,bitmap:await createImageBitmap(e),sourceWidth:t,sourceHeight:n}}catch{}return R(e,t,n)}function F(e){return e instanceof ImageData?{sourceWidth:e.width,sourceHeight:e.height}:e instanceof HTMLVideoElement?{sourceWidth:e.videoWidth,sourceHeight:e.videoHeight}:e instanceof HTMLImageElement?{sourceWidth:e.naturalWidth,sourceHeight:e.naturalHeight}:{sourceWidth:e.width,sourceHeight:e.height}}function I(){return typeof createImageBitmap==`function`}function L(){return typeof OffscreenCanvas==`function`}function R(e,t,n){let r=document.createElement(`canvas`),i=r.getContext(`2d`);if(!i)throw Error(`2D canvas context is not available.`);return r.width=t,r.height=n,i.drawImage(e,0,0,t,n),{kind:`rgba`,data:i.getImageData(0,0,t,n).data,sourceWidth:t,sourceHeight:n}}function z(e,t,n){return e.map(e=>H(e,t,n))}function B(e,t,n){return e.map(e=>H(e,t,n))}function V(e,t,n,r){if(e.phoneDetected)return e;let i=[...e.phoneCandidates,...B(t.phoneCandidates,n,r)];if(t.phoneDetections.length===0)return i.length===e.phoneCandidates.length?e:{...e,phoneCandidates:i};let a=z(t.phoneDetections,n,r);return{...e,phoneDetected:a.length>0,phoneCount:a.length,phoneDetections:a,phoneCandidates:i}}function H(e,t,n){return{...e,x:U(t-(e.x+e.width),0,t),y:U(n-(e.y+e.height),0,n)}}function U(e,t,n){return Math.min(Math.max(e,t),n)}function W(e){return e.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA&&e.videoWidth>0&&e.videoHeight>0&&!e.paused&&!e.ended}function G(e,t=1e4){return K(e)?Promise.resolve():new Promise((n,r)=>{let i=window.setTimeout(()=>{o(),r(Error(`Timed out waiting for webcam video metadata.`))},t),a=window.setInterval(s,100),o=()=>{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)};function s(){K(e)&&(o(),n())}let c=()=>{s()},l=()=>{o(),r(Error(`Failed to load webcam video stream.`))};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})})}function K(e){return e.readyState>=HTMLMediaElement.HAVE_METADATA&&e.videoWidth>0&&e.videoHeight>0}var le=700,ue=.25,de=.8,fe=class{services;primaryInferenceWorker;rotationInferenceWorker;loadPromise;lastInferenceMemoryErrorAt=0;lastParallelPhoneRotationFallbackAt=-1/0;phoneCandidateHistory=[];constructor(e){this.services=e}async load(){this.loadPromise||=this.loadInferenceWorker(),await this.loadPromise}async detect(e){await this.load();let t=this.services.options,n=t.debug?performance.now():0,r=t.debug?performance.now():0,i=r,a;if(this.shouldUseParallelPhoneRotationFallback(t)&&this.shouldRunParallelPhoneRotationFallback(t)){let[n,r]=await Promise.all([P(e),P(e)]);i=t.debug?performance.now():0,a=await this.runParallelPhoneRotationFallback(n,r,t)}else{let n=await P(e);i=t.debug?performance.now():0,a=await this.runWorkerInference(this.getInferenceWorker(),n,t,{inputRotation:`none`,phoneRotationFallback:t.phoneRotationFallback&&t.phoneRotationFallbackExecution===`sequential`})}let o=this.confirmTemporalPhoneCandidates(a);if(t.debug){let e=performance.now();console.info(`[MonitorDog] detect frame`,{sourceMs:J(i-r),workerRoundtripMs:J(e-i),totalMs:J(e-n)})}return o}toPublicResult(e){return{faceDetected:e.faceDetected,phoneDetected:e.phoneDetected,faceCount:e.faceCount,phoneCount:e.phoneCount,faceDetections:e.faceDetections,phoneDetections:e.phoneDetections}}detectVideo(e){let t=!1,n,r=this.services.options.detectionIntervalMs,i=async()=>{if(!t){try{if(!this.services.shouldPauseDetection&&W(e)){let n=await this.detect(e);if(t)return;try{await this.services.options.onDetect({...this.toPublicResult(n),video:e,timestamp:e.currentTime})}catch(e){this.services.options.onError?.(e)}if(t)return;await this.services.detectionEvents.handleDetectionResult(n,e).catch(e=>{this.services.options.onError?.(e)}),S(n)&&this.services.detectionEvents.clearTransientState()}}catch(e){this.handleDetectionLoopError(e)}t||(n=setTimeout(i,r))}};return i(),{stop:()=>{t=!0,this.resetPhoneCandidateHistory(),n&&clearTimeout(n)}}}async startWebcamDetection(){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;i.muted=!0,i.playsInline=!0,i.srcObject=t;try{await Promise.all([i.play(),G(i)])}catch(e){throw n.stopStream(t),i.pause(),r?i.srcObject=null:(i.muted=a,i.playsInline=o,i.srcObject=s),e}this.services.detectionEvents.resetForWebcamStartup();let c=this.detectVideo(i),l=!1,u=n.watchStreamDeviceDisconnect(t,()=>{d(),this.services.onCameraDisconnect?.()}),d=()=>{l||(l=!0,u(),c.stop(),this.services.detectionEvents.reset(),n.stopStream(t),i.pause(),r?i.srcObject=null:(i.muted=a,i.playsInline=o,i.srcObject=s))};return{stream:t,video:i,stop:d}}dispose(){this.primaryInferenceWorker?.terminate(),this.rotationInferenceWorker?.terminate(),this.primaryInferenceWorker=void 0,this.rotationInferenceWorker=void 0,this.loadPromise=void 0,this.lastParallelPhoneRotationFallbackAt=-1/0,this.resetPhoneCandidateHistory(),this.services.detectionEvents.reset()}confirmTemporalPhoneCandidates(e){if(e.phoneCandidates.length===0)return this.prunePhoneCandidateHistory(performance.now()),e;let t=performance.now(),n=this.getRecentPhoneCandidateHistory(t),r=e.phoneCandidates.filter(e=>this.isTemporallyConfirmedPhoneCandidate(e,n));if(this.phoneCandidateHistory=[...n,...e.phoneCandidates.map(e=>({candidate:e,observedAt:t}))],r.length===0)return e;let i=[...e.phoneDetections,...r.map(me)];return{...e,phoneDetected:!0,phoneCount:i.length,phoneDetections:i}}isTemporallyConfirmedPhoneCandidate(e,t){return q(e)?t.some(({candidate:t})=>pe(e,t)&&he(e,t)>=ue):!1}getRecentPhoneCandidateHistory(e){return this.phoneCandidateHistory.filter(t=>e-t.observedAt<=le)}prunePhoneCandidateHistory(e){this.phoneCandidateHistory=this.getRecentPhoneCandidateHistory(e)}resetPhoneCandidateHistory(){this.phoneCandidateHistory=[]}async runParallelPhoneRotationFallback(e,t,n){let r=e.sourceWidth,i=e.sourceHeight,[a,o]=await Promise.all([this.runWorkerInference(this.getInferenceWorker(),e,n,{inputRotation:`none`,phoneRotationFallback:!1}),this.runWorkerInference(this.getRotationInferenceWorker(),t,n,{inputRotation:`rotate180`,phoneRotationFallback:!1})]);return V(a,o,r,i)}runWorkerInference(e,t,n,r){return e.run({source:t,inputSize:n.inputSize,inputType:n.inputType,confidenceThreshold:n.confidenceThreshold,faceConfidenceThreshold:n.faceConfidenceThreshold,iouThreshold:n.iouThreshold,maxDetections:n.maxDetections,debug:!!n.debug,inputRotation:r.inputRotation,phoneRotationFallback:r.phoneRotationFallback,phoneRotationFallbackMinIntervalMs:n.phoneRotationFallbackMinIntervalMs})}handleDetectionLoopError(e){this.isInferenceMemoryError(e)&&this.recoverFromInferenceMemoryError(),this.services.options.onError?.(e)}recoverFromInferenceMemoryError(){this.degradeModelForMemoryPressure(),this.resetInferenceWorker();let e=Date.now();e-this.lastInferenceMemoryErrorAt<1e4||(this.lastInferenceMemoryErrorAt=e)}resetInferenceWorker(){this.primaryInferenceWorker?.terminate(),this.rotationInferenceWorker?.terminate(),this.primaryInferenceWorker=void 0,this.rotationInferenceWorker=void 0,this.loadPromise=void 0,this.lastParallelPhoneRotationFallbackAt=-1/0}degradeModelForMemoryPressure(){this.services.degradeInferenceModelForMemoryPressure()}isInferenceMemoryError(e){let t=e instanceof Error?e.message:String(e);return/out of memory|oom|memory access out of bounds|cannot enlarge memory|array buffer allocation|bad allocation|allocation failed/i.test(t)}getInferenceWorker(){return this.primaryInferenceWorker||=new N,this.primaryInferenceWorker}getRotationInferenceWorker(){return this.rotationInferenceWorker||=new N,this.rotationInferenceWorker}shouldUseParallelPhoneRotationFallback(e){return e.phoneRotationFallback&&e.phoneRotationFallbackExecution===`parallel`}shouldRunParallelPhoneRotationFallback(e){let t=performance.now();return t-this.lastParallelPhoneRotationFallbackAt<e.phoneRotationFallbackMinIntervalMs?!1:(this.lastParallelPhoneRotationFallbackAt=t,!0)}async loadInferenceWorker(){try{await this.loadInferenceWorkerWithOptions()}catch(e){if(!this.isInferenceMemoryError(e))throw e;this.recoverFromInferenceMemoryError();try{await this.loadInferenceWorkerWithOptions()}catch(e){throw this.recoverFromInferenceMemoryError(),e}}}async loadInferenceWorkerWithOptions(){let e=await this.services.auth.getValidAccessToken();if(!e)throw Error(`MonitorDog login is required before loading detection.`);let t=this.services.options,n={apiBaseUrl:t.apiBaseUrl,accessToken:e,inputSize:t.inputSize,runtimeAssetBaseUrl:t.runtimeAssetBaseUrl};if(this.shouldUseParallelPhoneRotationFallback(t)){await Promise.all([this.getInferenceWorker().load(n),this.getRotationInferenceWorker().load(n)]);return}await this.getInferenceWorker().load(n)}};function q(e){return e.handOverlapped||e.score>=de}function pe(e,t){return e.handOverlapped===t.handOverlapped?q(t):!1}function me(e){return{classId:e.classId,label:e.label,score:e.score,confidence:e.confidence,x:e.x,y:e.y,width:e.width,height:e.height}}function he(e,t){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;return s<=0?0:o/s}function J(e){return Math.round(e*10)/10}var ge=class{services;isWebcamRunning=!1;stopCurrentWebcam;startPromise;shouldRun=!1;resumeWhenUnpaused=!1;handleVisibilityChange=()=>{this.syncPauseState()};constructor(e){this.services=e,this.services.onCameraDisconnect=()=>this.handleCameraDisconnect()}get isRunning(){return this.isWebcamRunning}get isStarting(){return!!this.startPromise}async start(){if(this.services.auth.assertAuthenticated(),this.shouldRun=!0,this.addVisibilityListener(),!this.isWebcamRunning){if(this.services.shouldPauseDetection){this.resumeWhenUnpaused=!0;return}await this.ensureStarted()}}stop(){this.shouldRun=!1,this.resumeWhenUnpaused=!1,this.removeVisibilityListener(),this.services.detectionEvents.reset(),this.stopWebcam()}async retryConnection(){await this.start()}async syncPauseState(){if(this.shouldRun){if(this.services.shouldPauseDetection){this.isWebcamRunning&&(this.resumeWhenUnpaused=!0,this.stopWebcam());return}if(this.resumeWhenUnpaused&&!this.isWebcamRunning){this.resumeWhenUnpaused=!1;try{await this.ensureStarted()}catch{this.shouldRun=!1}}}}syncBackgroundPreference(){this.services.options.runInBackground?this.removeVisibilityListener():this.shouldRun&&this.addVisibilityListener(),this.syncPauseState()}async ensureStarted(){this.isWebcamRunning||(this.startPromise||=this.startWebcam().finally(()=>{this.startPromise=void 0}),await this.startPromise)}async startWebcam(){try{let e=await this.services.detect.startWebcamDetection();if(!this.shouldRun){e.stop();return}this.isWebcamRunning=!0,this.stopCurrentWebcam=e.stop}catch(e){throw this.services.options.onError?.(e),e}}stopWebcam(){this.stopCurrentWebcam?.(),this.stopCurrentWebcam=void 0,this.isWebcamRunning=!1}async handleCameraDisconnect(){if(this.isWebcamRunning&&(this.stopWebcam(),this.shouldRun)){if(this.services.shouldPauseDetection){this.resumeWhenUnpaused=!0;return}try{await this.ensureStarted()}catch(e){this.services.options.onError?.(e)}}}addVisibilityListener(){this.services.options.runInBackground||typeof document>`u`||document.addEventListener(`visibilitychange`,this.handleVisibilityChange)}removeVisibilityListener(){typeof document>`u`||document.removeEventListener(`visibilitychange`,this.handleVisibilityChange)}},_e=class{auth;camera;detectionEvents;detect;webcam;onCameraDisconnect;onLoginRequired;#e=0;#t=Y();#n;constructor(e){this.#n=e,this.camera=new ce,this.auth=new ae(this),this.detectionEvents=new A(this),this.detect=new fe(this),this.webcam=new ge(this)}get options(){return Object.freeze({...this.#n()})}get noFaceEventDelayMs(){return this.#e}get userPreferences(){return Object.freeze({...this.#t})}updateNoFaceEventDelayFromServer(e){this.#e=e}updateRequiredPasswordFromServer(e){this.#n().requiredPassword=e}setPhoneConfidenceThreshold(e){this.#n().phoneConfidenceThreshold=e,this.syncEffectivePhoneConfidenceThreshold()}degradeInferenceModelForMemoryPressure(){let e=this.#n();if(e.inputSize>416){e.inputSize=416;return}e.inputSize>320&&(e.inputSize=320)}get shouldPauseForHiddenPage(){return!this.options.runInBackground&&typeof document<`u`&&document.hidden}get shouldPauseDetection(){return this.shouldPauseForHiddenPage}applyPolicyItems(e,t){let n={...this.#t};for(let t of e)ye(n,t);this.#t=n,this.syncEffectivePhoneConfidenceThreshold(),this.#n().faceConfidenceThreshold=n.faceDetectionThreshold,this.updateRequiredPasswordFromServer(!1)}resetAuthenticatedState(){this.#e=0,this.#t=Y(),this.#n().requiredPassword=!1,this.syncEffectivePhoneConfidenceThreshold(),this.#n().faceConfidenceThreshold=this.#t.faceDetectionThreshold}syncEffectivePhoneConfidenceThreshold(){let e=this.#n();e.confidenceThreshold=e.phoneConfidenceThreshold??this.#t.mobileDetectionThreshold}};function Y(){return{mobileDetectionThreshold:.8,faceDetectionThreshold:.8,language:`en`,mobileDetectionEnabled:!0,noPersonDetectionEnabled:!0,multiPersonDetectionEnabled:!0,noPersonLockDuration:0,multiPersonLockDuration:0,mobileDetectionLockDuration:0,mobileDetectionMode:`auto_lock`,noPersonDetectionMode:`auto_lock`,multiPersonDetectionMode:`auto_lock`}}function ve(e){return e===`none`}function ye(e,t){let n=t.policy,r=!ve(t.policy),i=t.seconds*1e3,a=`sensitivity`in t?1-t.sensitivity/100:void 0;switch(t.basic_event_uuid){case E(`mobileDevice`):e.mobileDetectionEnabled=r,e.mobileDetectionLockDuration=i,e.mobileDetectionMode=n,a!==void 0&&(e.mobileDetectionThreshold=a);break;case E(`twoFacesDetected`):e.multiPersonDetectionEnabled=r,e.multiPersonLockDuration=i,e.multiPersonDetectionMode=n,a!==void 0&&(e.faceDetectionThreshold=a);break;case E(`noFaceDetected`):e.noPersonDetectionEnabled=r,e.noPersonLockDuration=i,e.noPersonDetectionMode=n;break;default:break}}var X=class e{#e;#t;#n=`anonymous`;#r=`idle`;#i=`idle`;#a;#o;static async init(t){return Z=new e(t),Z}constructor(e){Q(e);let t=we(),n=_(e.runtimeAssetBaseUrl);this.#t={...e,apiBaseUrl:m(e.apiBaseUrl),runtimeAssetBaseUrl:n,confidenceThreshold:e.phoneConfidenceThreshold??.8,faceConfidenceThreshold:l,iouThreshold:u,maxDetections:100,inputSize:re(e.modelInputSize,t),inputType:`float32`,detectionIntervalMs:e.detectionIntervalMs??300,requiredPassword:!1,eventReportingEnabled:e.eventReportingEnabled??!0,phoneRotationFallback:e.phoneRotationFallback??!1,phoneRotationFallbackMinIntervalMs:e.phoneRotationFallbackMinIntervalMs??500,phoneRotationFallbackExecution:e.phoneRotationFallbackExecution??`sequential`},this.#e=new _e(()=>this.#t),this.#e.onLoginRequired=()=>this.resetLoggedOutState(),Object.freeze(this)}async load(){this.assertUsable(),this.assertAuthenticated(`loading detection`);try{this.updateState({runtime:`loading`,lastError:void 0}),await this.#e.detect.load(),this.updateState({runtime:`idle`,lastError:void 0})}catch(e){let t=this.createSdkError(`MODEL_LOAD_FAILED`,`MonitorDog detection model failed to load.`,e);throw this.transitionToError(t),this.#t.onError?.(t),t}}async login(e){this.assertUsable();let t;try{t=await this.#e.auth.login(e)}catch(e){let t=this.createSdkError(`SESSION_TOKEN_FAILED`,`MonitorDog SDK session token could not be created.`,e);throw this.transitionToError(t),this.#t.onAuthError?.(t),t}try{await this.completeAuthenticatedLogin()}catch(e){let t=this.createSdkError(`ACCOUNT_POLICY_FAILED`,`MonitorDog account or policy could not be loaded.`,e);throw this.rollbackAuthenticatedLogin(),this.transitionToError(t),this.#t.onAuthError?.(t),t}return this.updateState({session:`authenticated`,runtime:this.#r===`stopped`?`stopped`:`idle`,camera:this.#e.webcam.isRunning?`active`:`idle`,lastError:void 0}),t}async logout(){if(this.assertUsable(),this.isDetectorRunning())throw this.lifecycleError(`DETECTOR_RUNNING`,`MonitorDog detector is running. Call stop() before logout().`);if(!this.#e.auth.getToken()){this.clearSessionState();return}try{await this.#e.auth.logout(),this.clearSessionState()}catch(e){let t=this.createSdkError(`LOGOUT_FAILED`,`MonitorDog logout failed.`,e);throw this.transitionToError(t),this.#t.onAuthError?.(t),t}finally{this.#e.auth.getToken()||(this.#n=`anonymous`)}}async start(){this.assertUsable(),this.assertAuthenticated(`starting detection`),!this.isDetectorRunning()&&(this.#o||=this.startRuntime().finally(()=>{this.#o=void 0}),await this.#o)}stop(){this.assertUsable(),this.hasRuntimeToStop()&&(this.stopLocalRuntime(),this.updateState({runtime:this.#n===`authenticated`?`stopped`:`idle`,camera:`idle`,lastError:void 0}))}setRunInBackground(e){this.assertUsable(),this.#t.runInBackground=e,this.#e.webcam.syncBackgroundPreference()}setEventReportingEnabled(e){this.assertUsable(),this.#t.eventReportingEnabled=e,e||this.#e.detectionEvents.reset()}setPhoneConfidenceThreshold(e){this.assertUsable(),$(e),this.#e.setPhoneConfidenceThreshold(e)}getUserPreferences(){return this.assertUsable(),this.#e.userPreferences}getState(){return Object.freeze({session:this.#n,runtime:this.#r,camera:this.#i,tokenExpiresAt:this.#e.auth.getTokenExpiresAt(),email:this.#e.auth.getSessionEmail(),lastError:this.#a})}dispose(){this.#r!==`disposed`&&(this.stopLocalRuntime(),this.#e.detect.dispose(),this.#e.auth.dispose(),this.#e.resetAuthenticatedState(),this.updateState({session:`anonymous`,runtime:`disposed`,camera:`idle`,lastError:void 0}))}async completeAuthenticatedLogin(){let e=await this.#e.auth.authorizedFetch(`/account/me`,{method:`GET`,headers:{"content-type":`application/json`}});if(!e.ok)throw Error(`MonitorDog account request failed: ${e.status}`);let t=await e.json(),n=await this.#e.auth.authorizedFetch(`/account/${t.uuid}/lock_policy`,{method:`GET`,headers:{"content-type":`application/json`}});if(!n.ok)throw Error(`MonitorDog lock policy request failed: ${n.status}`);let r=await n.json();this.#e.applyPolicyItems(r,t)}resetLoggedOutState(){this.stopLocalRuntime(),this.#e.detect.dispose(),this.#e.resetAuthenticatedState(),this.updateState({session:`anonymous`,runtime:`idle`,camera:`idle`,lastError:void 0})}rollbackAuthenticatedLogin(){this.#e.auth.dispose(),this.#e.resetAuthenticatedState()}async startRuntime(){try{this.updateState({runtime:`loading`,camera:`idle`,lastError:void 0}),await this.#e.detect.load(),this.updateState({runtime:`starting`,camera:`requesting`}),await this.#e.webcam.start(),this.updateState({runtime:`running`,camera:this.#e.shouldPauseDetection?`idle`:`active`,lastError:void 0})}catch(e){let t=this.createSdkError(this.getStartErrorCode(e),this.getStartErrorMessage(e),e);throw this.transitionToError(t,be(t.code)?`blocked`:`idle`),this.#t.onError?.(t),t}}clearSessionState(){this.#e.resetAuthenticatedState(),this.updateState({session:`anonymous`,runtime:`idle`,camera:`idle`,lastError:void 0})}stopLocalRuntime(){this.#e.webcam.stop()}assertUsable(){if(this.#r===`disposed`)throw this.lifecycleError(`ALREADY_DISPOSED`,`MonitorDog detector instance has already been disposed.`,void 0,`disposed`)}assertAuthenticated(e){if(!this.#e.auth.isAuthenticated())throw this.lifecycleError(`NOT_LOGGED_IN`,`MonitorDog login is required before ${e}.`)}lifecycleError(e,t,n,r=`error`){let i=this.createSdkError(e,t,n);return r===`error`?this.transitionToError(i):this.updateState({runtime:r,lastError:i},!0),i}transitionToError(e,t=this.#i){this.updateState({runtime:`error`,camera:t,lastError:e},!0)}updateState(e,t=!1){let n=!1;e.session!==void 0&&e.session!==this.#n&&(this.#n=e.session,n=!0),e.runtime!==void 0&&e.runtime!==this.#r&&(this.#r=e.runtime,n=!0),e.camera!==void 0&&e.camera!==this.#i&&(this.#i=e.camera,n=!0),`lastError`in e&&e.lastError!==this.#a&&(this.#a=e.lastError,n=!0),(n||t)&&this.notifyStatusChange()}notifyStatusChange(){try{this.#t.onStatusChange?.(this.getState())}catch(e){this.#t.onError?.(e)}}createSdkError(e,t,n){return y(n)?n:new v(e,t,n)}isDetectorRunning(){return this.#r===`running`||this.#r===`starting`||!!this.#o||this.#e.webcam.isRunning||this.#e.webcam.isStarting}hasRuntimeToStop(){return this.#r===`running`||this.#r===`starting`||this.#i!==`idle`||!!this.#o||this.#e.webcam.isRunning||this.#e.webcam.isStarting}getStartErrorCode(e){return this.isCameraPermissionError(e)?`CAMERA_PERMISSION_DENIED`:this.isCameraReadError(e)?`CAMERA_READ_FAILED`:this.#r===`loading`?`MODEL_LOAD_FAILED`:`RUNTIME_START_FAILED`}getStartErrorMessage(e){switch(this.getStartErrorCode(e)){case`CAMERA_PERMISSION_DENIED`:return`MonitorDog camera permission was denied.`;case`CAMERA_READ_FAILED`:return`MonitorDog camera could not be read.`;case`MODEL_LOAD_FAILED`:return`MonitorDog detection model failed to load.`;default:return`MonitorDog detector runtime failed to start.`}}isCameraPermissionError(e){return typeof DOMException<`u`&&e instanceof DOMException&&(e.name===`NotAllowedError`||e.name===`SecurityError`)}isCameraReadError(e){return typeof DOMException<`u`&&e instanceof DOMException&&e.name===`NotReadableError`}};function be(e){return e===`CAMERA_PERMISSION_DENIED`||e===`CAMERA_READ_FAILED`}var Z;function xe(e){return Z=new X(e),Z}async function Se(e){return X.init(e)}function Ce(){if(!Z)throw Error(`MonitorDog is not configured. Call MonitorDogDetector.init(), createMonitorDogDetector(), or configureMonitorDogDetector() before using getDetector().`);return Z}function we(){if(typeof navigator>`u`)return!1;let e=h();return e===`mobile`||e===`tablet`}function Q(e){if(!e||typeof e.apiBaseUrl!=`string`||e.apiBaseUrl.length===0)throw Error(`MonitorDog apiBaseUrl is required.`);if(typeof e.sessionTokenProvider!=`function`)throw Error(`MonitorDog sessionTokenProvider is required.`);if(typeof e.onDetect!=`function`)throw Error(`MonitorDog onDetect callback is required.`);if(e.runtimeAssetBaseUrl!==void 0&&_(e.runtimeAssetBaseUrl),e.modelInputSize!==void 0&&!ne(e.modelInputSize))throw Error(`MonitorDog modelInputSize must be "auto", 320, 416, or 640.`);if(e.phoneRotationFallback!==void 0&&typeof e.phoneRotationFallback!=`boolean`)throw Error(`MonitorDog phoneRotationFallback must be a boolean when provided.`);if(e.phoneRotationFallbackMinIntervalMs!==void 0&&!Te(e.phoneRotationFallbackMinIntervalMs))throw Error(`MonitorDog phoneRotationFallbackMinIntervalMs must be a non-negative finite number when provided.`);if(e.phoneRotationFallbackExecution!==void 0&&e.phoneRotationFallbackExecution!==`sequential`&&e.phoneRotationFallbackExecution!==`parallel`)throw Error(`MonitorDog phoneRotationFallbackExecution must be "sequential" or "parallel" when provided.`);$(e.phoneConfidenceThreshold)}function Te(e){return typeof e==`number`&&Number.isFinite(e)&&e>=0}function $(e){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.`)}e.MonitorDogDetector=X,e.MonitorDogSdkError=v,e.configureMonitorDogDetector=xe,e.createMonitorDogDetector=Se,e.getDetector=Ce,e.isMonitorDogSdkError=y});
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("html2canvas")):typeof define==`function`&&define.amd?define([`exports`,`html2canvas`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.MonitorDogDetector={},e.html2canvas))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,c=(e,t,n,o)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=a(t),l=0,u=c.length,d;l<u;l++)d=c[l],!s.call(e,d)&&d!==n&&r(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(o=i(t,d))||o.enumerable});return e};t=((e,t,i)=>(i=e==null?{}:n(o(e)),c(t||!e||!e.__esModule?r(i,`default`,{value:e,enumerable:!0}):i,e)))(t,1);var l=.8,u=.7,d=3e4;function f(e){return typeof e==`string`?e:e.access_token}function p(e){if(typeof e!=`string`)return e.expires_in}function ee(e){if(typeof e!=`string`)return e.expires_at}function te(e){if(e.expiresAt){let t=Date.parse(e.expiresAt);if(!Number.isNaN(t))return t}if(e.expiresIn)return e.expiresIn>1e9?e.expiresIn*1e3:Date.now()+e.expiresIn*1e3}function m(e){return e.replace(/\/+$/,``)}function h(){if(typeof navigator>`u`)return`none`;let e=navigator.userAgent.toLowerCase();return/ipad|tablet/.test(e)?`tablet`:/mobile|iphone|ipod|android/.test(e)?`mobile`:/macintosh|windows|linux/.test(e)?`desktop`:`other`}function g(){if(typeof navigator>`u`)return`none`;let e=navigator.userAgent.toLowerCase(),t=navigator.platform.toLowerCase();return/win/.test(t)||/windows/.test(e)?`windows`:/mac/.test(t)||/mac os/.test(e)?`macos`:/android/.test(e)?`android`:/iphone|ipad|ipod/.test(e)?`ios`:/linux/.test(t)||/linux/.test(e)?`linux`:`other`}function ne(e){return e===`auto`||e===320||e===416||e===640}function re(e,t){let n=e??`auto`;return n===`auto`?t?416:640:n}function _(e){if(e===void 0)return;let t=e.trim();if(t.length===0)throw Error(`MonitorDog runtimeAssetBaseUrl must be a non-empty string when provided.`);let n=t.replace(/\/+$/,``);return n.length===0?`/`:n}var v=class extends Error{code;cause;constructor(e,t,n){super(t),this.name=`MonitorDogSdkError`,this.code=e,this.cause=n}};function y(e){return e instanceof v}function b(e){if(e.faceCount===0)return C(`noFaceDetected`,e);if(e.faceCount>=2)return C(`twoFacesDetected`,e);if(e.phoneCount>=1)return C(`mobileDevice`,e)}function x(e){return{...w(e,new Date().toISOString()),properties:{},webcam_imgs:[],monitor_imgs:[]}}function S(e){return e.phoneCount===0&&e.faceCount===1}function C(e,t){let n=w(e,new Date().toISOString());switch(e){case`noFaceDetected`:return{type:e,payload:{...n,properties:{confidence:0,spots:[]}}};case`twoFacesDetected`:return{type:e,payload:{...n,properties:{confidence:T(t.faceDetections),spots:t.faceDetections}}};case`mobileDevice`:return{type:e,payload:{...n,properties:{confidence:T(t.phoneDetections),spots:t.phoneDetections}}}}}function w(e,t){return{basic_event_uuid:E(e),occured_at:t,sended_at:new Date().toISOString(),device_type:h(),device_os:g(),device_id:`browser`}}function T(e){return e.reduce((e,t)=>Math.max(e,t.score),0)}function E(e){switch(e){case`logout`:return`12ca646a-d832-4581-b03c-48f95627507f`;case`login`:return`4c6f98ea-88d8-4215-9b6a-9b3ccb753465`;case`mobileDevice`:return`027af5c9-297d-4a64-983f-4199ca4b9dad`;case`twoFacesDetected`:return`d555efac-7465-4067-8056-611e95385807`;case`noFaceDetected`:return`e2c48c23-36e2-4253-82b1-7f6565fdcfc3`;default:return``}}var D=`MonitorDog token refresh was superseded.`,ie=300*1e3,ae=class{services;refreshBeforeMs=ie;periodicRefreshIntervalMs=d;token;tokenExpiresAt;refreshPromise;refreshIntervalId;authSessionId=0;sessionEmail;sessionTokenRefresher;constructor(e){this.services=e}async login(e){let t=await this.fetchSessionToken(e.email);return this.establishSession(t,{email:e.email,refresh:()=>this.fetchSessionToken(e.email)}),await this.sendUserActivityEvent(`login`),t}async restoreSession(e){let t=this.services.options.restoreSessionTokenProvider;if(t){let n=await t();return this.establishSession(n,{email:e?.email,refresh:t}),n}if(!e?.email)throw Error(`MonitorDog restoreSession requires restoreSessionTokenProvider or an email.`);let n=await this.fetchSessionToken(e.email);return this.establishSession(n,{email:e.email,refresh:()=>this.fetchSessionToken(e.email)}),n}async logout(){if(this.token)try{await this.sendUserActivityEvent(`logout`)}finally{this.clearTokens()}}getToken(){return this.token}getTokenExpiresAt(){return this.tokenExpiresAt}getSessionEmail(){return this.sessionEmail}isAuthenticated(){return!!this.token}dispose(){this.clearTokens()}assertAuthenticated(){if(!this.token)throw Error(`MonitorDog login is required before detection.`)}async getValidAccessToken(){if(this.shouldRefreshCurrentToken())try{await this.handleAuthRefresh()}catch(e){if(this.token&&this.tokenExpiresAt&&Date.now()<this.tokenExpiresAt)return this.token;throw e}return this.token}async authorizedFetch(e,t={},n=!0){let r=await this.getValidAccessToken(),i=new Headers(t.headers);r&&(i.set(`authorization`,`Bearer ${r}`),i.set(`Device-Access-Token`,r));let a=await fetch(`${this.services.options.apiBaseUrl}${e}`,{...t,headers:i}),o=await this.getApiErrorCode(a);return a.status===400&&o===4221&&this.handleLoginRequired(),n&&this.shouldRefreshAfterAuthError(a,o)?(await this.handleAuthRefresh(),this.authorizedFetch(e,t,!1)):a}setSessionTokenPayload(e){let t=f(e);if(!t||typeof t!=`string`)throw Error(`MonitorDog SDK token response did not include a token.`);this.setTokens({accessToken:t,expiresIn:p(e),expiresAt:ee(e)})}establishSession(e,t){this.authSessionId+=1,this.sessionEmail=t.email,this.sessionTokenRefresher=t.refresh,this.setSessionTokenPayload(e)}setTokens(e){this.token=e.accessToken,this.tokenExpiresAt=te(e),this.tokenExpiresAt?this.startPeriodicRefresh():this.stopPeriodicRefresh()}clearTokens(){this.authSessionId+=1,this.token=void 0,this.tokenExpiresAt=void 0,this.refreshPromise=void 0,this.sessionEmail=void 0,this.sessionTokenRefresher=void 0,this.stopPeriodicRefresh()}async refreshToken(){return this.refreshPromise||=this.refreshAccessToken().finally(()=>{this.refreshPromise=void 0}),this.refreshPromise}async handleAuthRefresh(){try{return await this.refreshToken()}catch(e){if(!this.isRefreshSupersededError(e)){let t=this.createSdkError(`SESSION_TOKEN_FAILED`,`MonitorDog SDK session token refresh failed.`,e);this.services.options.onAuthError?.(t),this.isCurrentTokenExpired()&&(this.clearTokens(),this.services.onLoginRequired?.())}throw e}}async refreshAccessToken(){let e=this.authSessionId,t=this.sessionTokenRefresher;if(!t)throw Error(`MonitorDog SDK session refresh source is not available.`);let n=await t(),r=f(n);if(!r||typeof r!=`string`)throw Error(`MonitorDog SDK token response did not include a token.`);if(e!==this.authSessionId)throw Error(D);return this.setSessionTokenPayload(n),r}startPeriodicRefresh(){this.refreshIntervalId||=setInterval(()=>{this.refreshPeriodically()},this.periodicRefreshIntervalMs)}stopPeriodicRefresh(){this.refreshIntervalId&&=(clearInterval(this.refreshIntervalId),void 0)}async refreshPeriodically(){if(!(!this.token||!this.shouldRefreshCurrentToken()))try{await this.handleAuthRefresh()}catch{}}shouldRefreshCurrentToken(){return!!(this.token&&this.tokenExpiresAt&&Date.now()>=this.tokenExpiresAt-this.refreshBeforeMs)}isCurrentTokenExpired(){return!!(this.tokenExpiresAt&&Date.now()>=this.tokenExpiresAt)}isRefreshSupersededError(e){return e instanceof Error&&e.message===D}async fetchSessionToken(e){let t=this.services.options.sessionTokenProvider;if(!t)throw Error(`MonitorDog sessionTokenProvider is required for SDK login.`);return t({email:e})}async getApiErrorCode(e){if(e.status===400)try{let t=await e.clone().json();if(typeof t==`object`&&t&&`code`in t&&typeof t.code==`number`)return t.code}catch{return}}shouldRefreshAfterAuthError(e,t){return e.status===401?!0:e.status===400&&t===422}handleLoginRequired(){this.clearTokens(),this.services.onLoginRequired?.();let e=this.createSdkError(`NOT_LOGGED_IN`,`MonitorDog login is required.`);throw this.services.options.onAuthError?.(e),e}async sendUserActivityEvent(e){try{let t=await this.authorizedFetch(`/event`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(x(e))});if(!t.ok)throw Error(`MonitorDog ${e} event failed: ${t.status}`)}catch(t){let n=this.createSdkError(oe(e),`MonitorDog ${e} event failed.`,t);if(this.services.options.onAuthError?.(n),e===`logout`)throw n}}createSdkError(e,t,n){return n instanceof v?n:new v(e,t,n)}};function oe(e){return e===`logout`?`LOGOUT_FAILED`:`SESSION_TOKEN_FAILED`}var se=/(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,ce=class{async createWebcamStream(e){if(!navigator.mediaDevices?.getUserMedia)throw Error(`getUserMedia is not available in this browser.`);let t=this.getBaseWebcamConstraints(e),n=await this.createFirstCameraConstraints(t);try{return await this.getUserMedia(n)}catch(e){if(this.isPermissionError(e)||this.isCameraRequestTimeoutError(e))throw e;return this.createFallbackWebcamStream(n,e)}}stopStream(e){e.getTracks().forEach(e=>e.stop())}watchStreamDeviceDisconnect(e,t,n=1e3){let r=e.getVideoTracks()[0],i=r?.getSettings().deviceId;if(!r&&!i)return()=>{};let a=!1,o,s=()=>{a||(a=!0,t())},c=()=>{i&&(o&&clearTimeout(o),o=setTimeout(()=>{o=void 0,this.handleDeviceChange(i,s)},n))};return r?.addEventListener(`ended`,s),navigator.mediaDevices?.addEventListener?.(`devicechange`,c),()=>{o&&clearTimeout(o),r?.removeEventListener(`ended`,s),navigator.mediaDevices?.removeEventListener?.(`devicechange`,c)}}isCameraInUse(e){let t=e?.srcObject;return t instanceof MediaStream?t.getTracks().some(e=>e.readyState===`live`):!1}async getVideoInputDevices(){return navigator.mediaDevices?.enumerateDevices?(await navigator.mediaDevices.enumerateDevices()).filter(e=>e.kind===`videoinput`):[]}async getRealVideoInputDevices(){let e=await this.getVideoInputDevices(),t=e.filter(e=>!this.isVirtualCamera(e));return t.length>0?t:e}async createFallbackWebcamStream(e,t){let n=await this.getRealVideoInputDevices();if(n.length===0)throw t;let r=n[0],i=t;if(!r?.deviceId)throw i;let a=await this.getWebcamNaturalAspectRatio(r.deviceId),o=this.generateResolutionList(a,720);for(let t of o)try{return await this.getUserMedia(this.createDeviceConstraints(e,r.deviceId,t))}catch(e){i=e}throw i}async handleDeviceChange(e,t){try{(await this.getVideoInputDevices()).some(t=>t.deviceId===e)||t()}catch{}}getBaseWebcamConstraints(e){return e??{audio:!1,video:{facingMode:`user`}}}async createFirstCameraConstraints(e){let t=typeof e.video==`object`?e.video:{};if(`deviceId`in t||`facingMode`in t)return e;let n=(await this.getRealVideoInputDevices())[0];return n?.deviceId?this.createDeviceConstraints(e,n.deviceId):e}async getWebcamNaturalAspectRatio(e){let t;try{t=await this.getUserMedia({audio:!1,video:{deviceId:{exact:e}}});let n=t.getVideoTracks()[0]?.getSettings();if(n?.width&&n.height)return n.width/n.height}catch{}finally{t?.getTracks().forEach(e=>e.stop())}return 16/9}generateResolutionList(e,t){return[t,640,600,480,320,240].map(t=>({width:t,height:Math.max(1,Math.round(t/e))})).filter(e=>e.width<=t&&e.height>=120&&e.height<=1080)}createDeviceConstraints(e,t,n){let r=typeof e.video==`object`?e.video:{};return{...e,audio:e.audio??!1,video:{...r,deviceId:{exact:t},...n?{width:{min:n.width,ideal:n.width},height:{min:n.height,ideal:n.height}}:{}}}}isVirtualCamera(e){let t=e.label.toLowerCase();return t?se.test(t):!1}isPermissionError(e){return e instanceof DOMException&&(e.name===`NotAllowedError`||e.name===`SecurityError`)}getUserMedia(e,t=15e3){let n=!1,r,i=navigator.mediaDevices.getUserMedia(e).then(e=>{if(n)throw this.stopStream(e),Error(`Camera permission request timed out.`);return e}),a=new Promise((e,i)=>{r=setTimeout(()=>{n=!0,i(Error(`Camera permission request timed out.`))},t)});return Promise.race([i,a]).finally(()=>{r&&clearTimeout(r)})}isCameraRequestTimeoutError(e){return e instanceof Error&&e.message===`Camera permission request timed out.`}};function O(e){if(e.videoWidth===0||e.videoHeight===0)throw Error(`Video frame is not ready for capture.`);let t=document.createElement(`canvas`),n=t.getContext(`2d`);if(!n)throw Error(`2D canvas context is not available.`);return t.width=e.videoWidth,t.height=e.videoHeight,n.drawImage(e,0,0,t.width,t.height),new Promise((e,n)=>{t.toBlob(t=>{if(!t){n(Error(`Failed to capture video frame.`));return}e(t)},`image/jpeg`,.9)})}async function k(){if(typeof document>`u`||!document.body)return null;let e=await(0,t.default)(document.body,{backgroundColor:`#ffffff`,useCORS:!0});return new Promise(t=>{e.toBlob(t,`image/jpeg`,.9)})}var A=class e{static NO_FACE_STARTUP_GRACE_MS=1500;services;detectionEventLocked=!1;detectionEventInFlight=!1;detectionEventLockTimeoutId;noFaceStartedAt;suppressNoFaceUntil=0;constructor(e){this.services=e}async handleDetectionResult(e,t){if(!this.services.options.eventReportingEnabled){this.reset();return}if(S(e)){this.noFaceStartedAt=void 0,this.clearLock();return}if(this.detectionEventLocked||this.detectionEventInFlight)return;let n=b(e);if(!n){this.noFaceStartedAt=void 0;return}if(!(n.type===`noFaceDetected`&&!this.hasNoFaceDelayElapsed())&&(n.type!==`noFaceDetected`&&(this.noFaceStartedAt=void 0),this.shouldSendEvent(n.type,e))){this.lock(n.type),this.detectionEventInFlight=!0;try{let e=await this.uploadWebcamImage(t);e&&(n.payload.webcam_imgs=e);let r=await this.uploadMonitorImage();if(r&&(n.payload.monitor_imgs=r),this.services.options.debug){console.log(n.payload);return}let i=await this.services.auth.authorizedFetch(`/event`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(n.payload)});if(!i.ok)throw Error(`MonitorDog event request failed: ${i.status}`)}finally{this.detectionEventInFlight=!1}}}reset(){this.clearLock(),this.noFaceStartedAt=void 0,this.suppressNoFaceUntil=0}resetForWebcamStartup(){this.clearLock(),this.noFaceStartedAt=void 0,this.suppressNoFaceUntil=Date.now()+e.NO_FACE_STARTUP_GRACE_MS}clearTransientState(){this.noFaceStartedAt=void 0}async uploadWebcamImage(e){if(!(e instanceof HTMLVideoElement)||e.videoWidth===0||e.videoHeight===0)return;let t=await O(e);return this.uploadImage(t,`webcam.jpg`)}async uploadMonitorImage(){let e=this.services.options.captureMonitorImage?await this.services.options.captureMonitorImage():await k();if(!e)return;let t=typeof File<`u`&&e instanceof File?e.name:`monitor.jpg`;return this.uploadImage(e,t)}async uploadImage(e,t){let n=new FormData;n.append(`files`,e,t);let r=await this.services.auth.authorizedFetch(`/file/image`,{method:`POST`,body:n});if(!r.ok)throw Error(`MonitorDog image upload failed: ${r.status}`);return r.json()}shouldSendEvent(e,t){switch(e){case`mobileDevice`:return this.services.userPreferences.mobileDetectionEnabled&&j(t.phoneDetections)>=this.services.options.confidenceThreshold;case`twoFacesDetected`:return this.services.userPreferences.multiPersonDetectionEnabled&&j(t.faceDetections)>=this.services.userPreferences.faceDetectionThreshold;case`noFaceDetected`:return this.services.userPreferences.noPersonDetectionEnabled}}lock(e){this.clearLock(),this.detectionEventLocked=!0;let t=this.getLockDuration(e);if(t<=0){this.detectionEventLocked=!1;return}this.detectionEventLockTimeoutId=setTimeout(()=>{this.detectionEventLocked=!1,this.detectionEventLockTimeoutId=void 0},t)}clearLock(){this.detectionEventLockTimeoutId&&=(clearTimeout(this.detectionEventLockTimeoutId),void 0),this.detectionEventLocked=!1}hasNoFaceDelayElapsed(){if(Date.now()<this.suppressNoFaceUntil)return this.noFaceStartedAt=void 0,!1;if(this.services.noFaceEventDelayMs<=0)return!0;let e=Date.now();return this.noFaceStartedAt===void 0?(this.noFaceStartedAt=e,!1):e-this.noFaceStartedAt>=this.services.noFaceEventDelayMs}getLockDuration(e){switch(e){case`mobileDevice`:return this.services.userPreferences.mobileDetectionLockDuration;case`twoFacesDetected`:return this.services.userPreferences.multiPersonLockDuration;case`noFaceDetected`:return this.services.userPreferences.noPersonLockDuration}}};function j(e){return e.reduce((e,t)=>Math.max(e,t.score),0)}var M=``+(typeof document>`u`&&typeof location>`u`?require("url").pathToFileURL(__dirname+`/assets/inference-worker-Dj9tu4Yg.js`).href:new URL(`assets/inference-worker-Dj9tu4Yg.js`,typeof document>`u`?location.href:document.currentScript&&document.currentScript.tagName.toUpperCase()===`SCRIPT`&&document.currentScript.src||document.baseURI).href),N=class{worker;nextRequestId=1;pendingRequests=new Map;async load(e){let t={id:this.nextRequestId,type:`load`,model:e};await this.request(t)}run(e){let t=e.source.kind===`bitmap`?[e.source.bitmap]:[e.source.data.buffer];return this.request({id:this.nextRequestId,type:`run`,source:e.source,inputSize:e.inputSize,inputType:e.inputType,confidenceThreshold:e.confidenceThreshold,faceConfidenceThreshold:e.faceConfidenceThreshold,iouThreshold:e.iouThreshold,maxDetections:e.maxDetections,debug:e.debug,inputRotation:e.inputRotation??`none`,phoneRotationFallback:e.phoneRotationFallback,phoneRotationFallbackMinIntervalMs:e.phoneRotationFallbackMinIntervalMs},t)}terminate(){this.rejectPendingRequests(Error(`Inference worker was terminated.`)),this.worker?.terminate(),this.worker=void 0}request(e,t=[]){let n=this.getWorker();return this.nextRequestId+=1,new Promise((r,i)=>{this.pendingRequests.set(e.id,{resolve:r,reject:i}),n.postMessage(e,t)})}getWorker(){return this.worker||(this.worker=new Worker(M,{name:`MonitorDogInference`,type:`module`}),this.worker.addEventListener(`message`,this.handleMessage),this.worker.addEventListener(`error`,this.handleError),this.worker.addEventListener(`messageerror`,this.handleError)),this.worker}handleMessage=e=>{let t=e.data,n=this.pendingRequests.get(t.id);if(n){if(this.pendingRequests.delete(t.id),!t.ok){n.reject(Error(t.error));return}n.resolve(t.result)}};handleError=e=>{let t=e instanceof ErrorEvent?e.message:`Inference worker message failed.`;this.rejectPendingRequests(Error(t)),this.worker?.terminate(),this.worker=void 0};rejectPendingRequests(e){for(let t of this.pendingRequests.values())t.reject(e);this.pendingRequests.clear()}};async function P(e){let{sourceWidth:t,sourceHeight:n}=F(e);if(e instanceof ImageData)return{kind:`rgba`,data:new Uint8ClampedArray(e.data),sourceWidth:t,sourceHeight:n};if(I()&&L())try{return{kind:`bitmap`,bitmap:await createImageBitmap(e),sourceWidth:t,sourceHeight:n}}catch{}return R(e,t,n)}function F(e){return e instanceof ImageData?{sourceWidth:e.width,sourceHeight:e.height}:e instanceof HTMLVideoElement?{sourceWidth:e.videoWidth,sourceHeight:e.videoHeight}:e instanceof HTMLImageElement?{sourceWidth:e.naturalWidth,sourceHeight:e.naturalHeight}:{sourceWidth:e.width,sourceHeight:e.height}}function I(){return typeof createImageBitmap==`function`}function L(){return typeof OffscreenCanvas==`function`}function R(e,t,n){let r=document.createElement(`canvas`),i=r.getContext(`2d`);if(!i)throw Error(`2D canvas context is not available.`);return r.width=t,r.height=n,i.drawImage(e,0,0,t,n),{kind:`rgba`,data:i.getImageData(0,0,t,n).data,sourceWidth:t,sourceHeight:n}}function z(e,t,n){return e.map(e=>H(e,t,n))}function B(e,t,n){return e.map(e=>H(e,t,n))}function V(e,t,n,r){if(e.phoneDetected)return e;let i=[...e.phoneCandidates,...B(t.phoneCandidates,n,r)];if(t.phoneDetections.length===0)return i.length===e.phoneCandidates.length?e:{...e,phoneCandidates:i};let a=z(t.phoneDetections,n,r);return{...e,phoneDetected:a.length>0,phoneCount:a.length,phoneDetections:a,phoneCandidates:i}}function H(e,t,n){return{...e,x:U(t-(e.x+e.width),0,t),y:U(n-(e.y+e.height),0,n)}}function U(e,t,n){return Math.min(Math.max(e,t),n)}var W={sdk:{"detector-320.onnx.enc":new URL(`./assets/sdk/detector-320.onnx.enc`,typeof document>`u`?typeof location>`u`?require("url").pathToFileURL(__dirname+`/monitordog-detector.umd.cjs`).href:location.href:document.currentScript&&document.currentScript.src||document.baseURI).href,"detector-416.onnx.enc":new URL(`./assets/sdk/detector-416.onnx.enc`,typeof document>`u`?typeof location>`u`?require("url").pathToFileURL(__dirname+`/monitordog-detector.umd.cjs`).href:location.href:document.currentScript&&document.currentScript.src||document.baseURI).href,"detector-640.onnx.enc":new URL(`./assets/sdk/detector-640.onnx.enc`,typeof document>`u`?typeof location>`u`?require("url").pathToFileURL(__dirname+`/monitordog-detector.umd.cjs`).href:location.href:document.currentScript&&document.currentScript.src||document.baseURI).href},ort:{mjs:new URL(`./assets/ort/ort-wasm-simd-threaded.mjs`,typeof document>`u`?typeof location>`u`?require("url").pathToFileURL(__dirname+`/monitordog-detector.umd.cjs`).href:location.href:document.currentScript&&document.currentScript.src||document.baseURI).href,wasm:new URL(`./assets/ort/ort-wasm-simd-threaded.wasm`,typeof document>`u`?typeof location>`u`?require("url").pathToFileURL(__dirname+`/monitordog-detector.umd.cjs`).href:location.href:document.currentScript&&document.currentScript.src||document.baseURI).href}};function G(e){return e.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA&&e.videoWidth>0&&e.videoHeight>0&&!e.paused&&!e.ended}function le(e,t=1e4){return K(e)?Promise.resolve():new Promise((n,r)=>{let i=window.setTimeout(()=>{o(),r(Error(`Timed out waiting for webcam video metadata.`))},t),a=window.setInterval(s,100),o=()=>{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)};function s(){K(e)&&(o(),n())}let c=()=>{s()},l=()=>{o(),r(Error(`Failed to load webcam video stream.`))};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})})}function K(e){return e.readyState>=HTMLMediaElement.HAVE_METADATA&&e.videoWidth>0&&e.videoHeight>0}var ue=700,de=.25,fe=.8,pe=class{services;primaryInferenceWorker;rotationInferenceWorker;loadPromise;lastInferenceMemoryErrorAt=0;lastParallelPhoneRotationFallbackAt=-1/0;phoneCandidateHistory=[];constructor(e){this.services=e}async load(){this.loadPromise||=this.loadInferenceWorker(),await this.loadPromise}async detect(e){await this.load();let t=this.services.options,n=t.debug?performance.now():0,r=t.debug?performance.now():0,i=r,a;if(this.shouldUseParallelPhoneRotationFallback(t)&&this.shouldRunParallelPhoneRotationFallback(t)){let[n,r]=await Promise.all([P(e),P(e)]);i=t.debug?performance.now():0,a=await this.runParallelPhoneRotationFallback(n,r,t)}else{let n=await P(e);i=t.debug?performance.now():0,a=await this.runWorkerInference(this.getInferenceWorker(),n,t,{inputRotation:`none`,phoneRotationFallback:t.phoneRotationFallback&&t.phoneRotationFallbackExecution===`sequential`})}let o=this.confirmTemporalPhoneCandidates(a);if(t.debug){let e=performance.now();console.info(`[MonitorDog] detect frame`,{sourceMs:J(i-r),workerRoundtripMs:J(e-i),totalMs:J(e-n)})}return o}toPublicResult(e){return{faceDetected:e.faceDetected,phoneDetected:e.phoneDetected,faceCount:e.faceCount,phoneCount:e.phoneCount,faceDetections:e.faceDetections,phoneDetections:e.phoneDetections}}detectVideo(e){let t=!1,n,r=this.services.options.detectionIntervalMs,i=async()=>{if(!t){try{if(!this.services.shouldPauseDetection&&G(e)){let n=await this.detect(e);if(t)return;try{await this.services.options.onDetect({...this.toPublicResult(n),video:e,timestamp:e.currentTime})}catch(e){this.services.options.onError?.(e)}if(t)return;await this.services.detectionEvents.handleDetectionResult(n,e).catch(e=>{this.services.options.onError?.(e)}),S(n)&&this.services.detectionEvents.clearTransientState()}}catch(e){this.handleDetectionLoopError(e)}t||(n=setTimeout(i,r))}};return i(),{stop:()=>{t=!0,this.resetPhoneCandidateHistory(),n&&clearTimeout(n)}}}async startWebcamDetection(){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;i.muted=!0,i.playsInline=!0,i.srcObject=t;try{await Promise.all([i.play(),le(i)])}catch(e){throw n.stopStream(t),i.pause(),r?i.srcObject=null:(i.muted=a,i.playsInline=o,i.srcObject=s),e}this.services.detectionEvents.resetForWebcamStartup();let c=this.detectVideo(i),l=!1,u=n.watchStreamDeviceDisconnect(t,()=>{d(),this.services.onCameraDisconnect?.()}),d=()=>{l||(l=!0,u(),c.stop(),this.services.detectionEvents.reset(),n.stopStream(t),i.pause(),r?i.srcObject=null:(i.muted=a,i.playsInline=o,i.srcObject=s))};return{stream:t,video:i,stop:d}}dispose(){this.primaryInferenceWorker?.terminate(),this.rotationInferenceWorker?.terminate(),this.primaryInferenceWorker=void 0,this.rotationInferenceWorker=void 0,this.loadPromise=void 0,this.lastParallelPhoneRotationFallbackAt=-1/0,this.resetPhoneCandidateHistory(),this.services.detectionEvents.reset()}confirmTemporalPhoneCandidates(e){if(e.phoneCandidates.length===0)return this.prunePhoneCandidateHistory(performance.now()),e;let t=performance.now(),n=this.getRecentPhoneCandidateHistory(t),r=e.phoneCandidates.filter(e=>this.isTemporallyConfirmedPhoneCandidate(e,n));if(this.phoneCandidateHistory=[...n,...e.phoneCandidates.map(e=>({candidate:e,observedAt:t}))],r.length===0)return e;let i=[...e.phoneDetections,...r.map(he)];return{...e,phoneDetected:!0,phoneCount:i.length,phoneDetections:i}}isTemporallyConfirmedPhoneCandidate(e,t){return q(e)?t.some(({candidate:t})=>me(e,t)&&ge(e,t)>=de):!1}getRecentPhoneCandidateHistory(e){return this.phoneCandidateHistory.filter(t=>e-t.observedAt<=ue)}prunePhoneCandidateHistory(e){this.phoneCandidateHistory=this.getRecentPhoneCandidateHistory(e)}resetPhoneCandidateHistory(){this.phoneCandidateHistory=[]}async runParallelPhoneRotationFallback(e,t,n){let r=e.sourceWidth,i=e.sourceHeight,[a,o]=await Promise.all([this.runWorkerInference(this.getInferenceWorker(),e,n,{inputRotation:`none`,phoneRotationFallback:!1}),this.runWorkerInference(this.getRotationInferenceWorker(),t,n,{inputRotation:`rotate180`,phoneRotationFallback:!1})]);return V(a,o,r,i)}runWorkerInference(e,t,n,r){return e.run({source:t,inputSize:n.inputSize,inputType:n.inputType,confidenceThreshold:n.confidenceThreshold,faceConfidenceThreshold:n.faceConfidenceThreshold,iouThreshold:n.iouThreshold,maxDetections:n.maxDetections,debug:!!n.debug,inputRotation:r.inputRotation,phoneRotationFallback:r.phoneRotationFallback,phoneRotationFallbackMinIntervalMs:n.phoneRotationFallbackMinIntervalMs})}handleDetectionLoopError(e){this.isInferenceMemoryError(e)&&this.recoverFromInferenceMemoryError(),this.services.options.onError?.(e)}recoverFromInferenceMemoryError(){this.degradeModelForMemoryPressure(),this.resetInferenceWorker();let e=Date.now();e-this.lastInferenceMemoryErrorAt<1e4||(this.lastInferenceMemoryErrorAt=e)}resetInferenceWorker(){this.primaryInferenceWorker?.terminate(),this.rotationInferenceWorker?.terminate(),this.primaryInferenceWorker=void 0,this.rotationInferenceWorker=void 0,this.loadPromise=void 0,this.lastParallelPhoneRotationFallbackAt=-1/0}degradeModelForMemoryPressure(){this.services.degradeInferenceModelForMemoryPressure()}isInferenceMemoryError(e){let t=e instanceof Error?e.message:String(e);return/out of memory|oom|memory access out of bounds|cannot enlarge memory|array buffer allocation|bad allocation|allocation failed/i.test(t)}getInferenceWorker(){return this.primaryInferenceWorker||=new N,this.primaryInferenceWorker}getRotationInferenceWorker(){return this.rotationInferenceWorker||=new N,this.rotationInferenceWorker}shouldUseParallelPhoneRotationFallback(e){return e.phoneRotationFallback&&e.phoneRotationFallbackExecution===`parallel`}shouldRunParallelPhoneRotationFallback(e){let t=performance.now();return t-this.lastParallelPhoneRotationFallbackAt<e.phoneRotationFallbackMinIntervalMs?!1:(this.lastParallelPhoneRotationFallbackAt=t,!0)}async loadInferenceWorker(){try{await this.loadInferenceWorkerWithOptions()}catch(e){if(!this.isInferenceMemoryError(e))throw e;this.recoverFromInferenceMemoryError();try{await this.loadInferenceWorkerWithOptions()}catch(e){throw this.recoverFromInferenceMemoryError(),e}}}async loadInferenceWorkerWithOptions(){let e=await this.services.auth.getValidAccessToken();if(!e)throw Error(`MonitorDog login is required before loading detection.`);let t=this.services.options,n={apiBaseUrl:t.apiBaseUrl,accessToken:e,inputSize:t.inputSize,runtimeAssetUrls:W,runtimeAssetBaseUrl:t.runtimeAssetBaseUrl};if(this.shouldUseParallelPhoneRotationFallback(t)){await Promise.all([this.getInferenceWorker().load(n),this.getRotationInferenceWorker().load(n)]);return}await this.getInferenceWorker().load(n)}};function q(e){return e.handOverlapped||e.score>=fe}function me(e,t){return e.handOverlapped===t.handOverlapped?q(t):!1}function he(e){return{classId:e.classId,label:e.label,score:e.score,confidence:e.confidence,x:e.x,y:e.y,width:e.width,height:e.height}}function ge(e,t){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;return s<=0?0:o/s}function J(e){return Math.round(e*10)/10}var _e=class{services;isWebcamRunning=!1;stopCurrentWebcam;startPromise;shouldRun=!1;resumeWhenUnpaused=!1;handleVisibilityChange=()=>{this.syncPauseState()};constructor(e){this.services=e,this.services.onCameraDisconnect=()=>this.handleCameraDisconnect()}get isRunning(){return this.isWebcamRunning}get isStarting(){return!!this.startPromise}async start(){if(this.services.auth.assertAuthenticated(),this.shouldRun=!0,this.addVisibilityListener(),!this.isWebcamRunning){if(this.services.shouldPauseDetection){this.resumeWhenUnpaused=!0;return}await this.ensureStarted()}}stop(){this.shouldRun=!1,this.resumeWhenUnpaused=!1,this.removeVisibilityListener(),this.services.detectionEvents.reset(),this.stopWebcam()}async retryConnection(){await this.start()}async syncPauseState(){if(this.shouldRun){if(this.services.shouldPauseDetection){this.isWebcamRunning&&(this.resumeWhenUnpaused=!0,this.stopWebcam());return}if(this.resumeWhenUnpaused&&!this.isWebcamRunning){this.resumeWhenUnpaused=!1;try{await this.ensureStarted()}catch{this.shouldRun=!1}}}}syncBackgroundPreference(){this.services.options.runInBackground?this.removeVisibilityListener():this.shouldRun&&this.addVisibilityListener(),this.syncPauseState()}async ensureStarted(){this.isWebcamRunning||(this.startPromise||=this.startWebcam().finally(()=>{this.startPromise=void 0}),await this.startPromise)}async startWebcam(){try{let e=await this.services.detect.startWebcamDetection();if(!this.shouldRun){e.stop();return}this.isWebcamRunning=!0,this.stopCurrentWebcam=e.stop}catch(e){throw this.services.options.onError?.(e),e}}stopWebcam(){this.stopCurrentWebcam?.(),this.stopCurrentWebcam=void 0,this.isWebcamRunning=!1}async handleCameraDisconnect(){if(this.isWebcamRunning&&(this.stopWebcam(),this.shouldRun)){if(this.services.shouldPauseDetection){this.resumeWhenUnpaused=!0;return}try{await this.ensureStarted()}catch(e){this.services.options.onError?.(e)}}}addVisibilityListener(){this.services.options.runInBackground||typeof document>`u`||document.addEventListener(`visibilitychange`,this.handleVisibilityChange)}removeVisibilityListener(){typeof document>`u`||document.removeEventListener(`visibilitychange`,this.handleVisibilityChange)}},ve=class{auth;camera;detectionEvents;detect;webcam;onCameraDisconnect;onLoginRequired;#e=0;#t=Y();#n;constructor(e){this.#n=e,this.camera=new ce,this.auth=new ae(this),this.detectionEvents=new A(this),this.detect=new pe(this),this.webcam=new _e(this)}get options(){return Object.freeze({...this.#n()})}get noFaceEventDelayMs(){return this.#e}get userPreferences(){return Object.freeze({...this.#t})}updateNoFaceEventDelayFromServer(e){this.#e=e}updateRequiredPasswordFromServer(e){this.#n().requiredPassword=e}setPhoneConfidenceThreshold(e){this.#n().phoneConfidenceThreshold=e,this.syncEffectivePhoneConfidenceThreshold()}degradeInferenceModelForMemoryPressure(){let e=this.#n();if(e.inputSize>416){e.inputSize=416;return}e.inputSize>320&&(e.inputSize=320)}get shouldPauseForHiddenPage(){return!this.options.runInBackground&&typeof document<`u`&&document.hidden}get shouldPauseDetection(){return this.shouldPauseForHiddenPage}applyPolicyItems(e,t){let n={...this.#t};for(let t of e)be(n,t);this.#t=n,this.syncEffectivePhoneConfidenceThreshold(),this.#n().faceConfidenceThreshold=n.faceDetectionThreshold,this.updateRequiredPasswordFromServer(!1)}resetAuthenticatedState(){this.#e=0,this.#t=Y(),this.#n().requiredPassword=!1,this.syncEffectivePhoneConfidenceThreshold(),this.#n().faceConfidenceThreshold=this.#t.faceDetectionThreshold}syncEffectivePhoneConfidenceThreshold(){let e=this.#n();e.confidenceThreshold=e.phoneConfidenceThreshold??this.#t.mobileDetectionThreshold}};function Y(){return{mobileDetectionThreshold:.8,faceDetectionThreshold:.8,language:`en`,mobileDetectionEnabled:!0,noPersonDetectionEnabled:!0,multiPersonDetectionEnabled:!0,noPersonLockDuration:0,multiPersonLockDuration:0,mobileDetectionLockDuration:0,mobileDetectionMode:`auto_lock`,noPersonDetectionMode:`auto_lock`,multiPersonDetectionMode:`auto_lock`}}function ye(e){return e===`none`}function be(e,t){let n=t.policy,r=!ye(t.policy),i=t.seconds*1e3,a=`sensitivity`in t?1-t.sensitivity/100:void 0;switch(t.basic_event_uuid){case E(`mobileDevice`):e.mobileDetectionEnabled=r,e.mobileDetectionLockDuration=i,e.mobileDetectionMode=n,a!==void 0&&(e.mobileDetectionThreshold=a);break;case E(`twoFacesDetected`):e.multiPersonDetectionEnabled=r,e.multiPersonLockDuration=i,e.multiPersonDetectionMode=n,a!==void 0&&(e.faceDetectionThreshold=a);break;case E(`noFaceDetected`):e.noPersonDetectionEnabled=r,e.noPersonLockDuration=i,e.noPersonDetectionMode=n;break;default:break}}var X=class e{#e;#t;#n=`anonymous`;#r=`idle`;#i=`idle`;#a;#o;static async init(t){return Z=new e(t),Z}constructor(e){Te(e);let t=we(),n=_(e.runtimeAssetBaseUrl);this.#t={...e,apiBaseUrl:m(e.apiBaseUrl),runtimeAssetBaseUrl:n,confidenceThreshold:e.phoneConfidenceThreshold??.8,faceConfidenceThreshold:l,iouThreshold:u,maxDetections:100,inputSize:re(e.modelInputSize,t),inputType:`float32`,detectionIntervalMs:e.detectionIntervalMs??300,requiredPassword:!1,eventReportingEnabled:e.eventReportingEnabled??!0,phoneRotationFallback:e.phoneRotationFallback??!1,phoneRotationFallbackMinIntervalMs:e.phoneRotationFallbackMinIntervalMs??500,phoneRotationFallbackExecution:e.phoneRotationFallbackExecution??`sequential`},this.#e=new ve(()=>this.#t),this.#e.onLoginRequired=()=>this.resetLoggedOutState(),Object.freeze(this)}async load(){this.assertUsable(),this.assertAuthenticated(`loading detection`);try{this.updateState({runtime:`loading`,lastError:void 0}),await this.#e.detect.load(),this.updateState({runtime:`idle`,lastError:void 0})}catch(e){let t=this.createSdkError(`MODEL_LOAD_FAILED`,`MonitorDog detection model failed to load.`,e);throw this.transitionToError(t),this.#t.onError?.(t),t}}async login(e){this.assertUsable();let t;try{t=await this.#e.auth.login(e)}catch(e){let t=this.createSdkError(`SESSION_TOKEN_FAILED`,`MonitorDog SDK session token could not be created.`,e);throw this.transitionToError(t),this.#t.onAuthError?.(t),t}try{await this.completeAuthenticatedLogin()}catch(e){let t=this.createSdkError(`ACCOUNT_POLICY_FAILED`,`MonitorDog account or policy could not be loaded.`,e);throw this.rollbackAuthenticatedLogin(),this.transitionToError(t),this.#t.onAuthError?.(t),t}return this.updateState({session:`authenticated`,runtime:this.#r===`stopped`?`stopped`:`idle`,camera:this.#e.webcam.isRunning?`active`:`idle`,lastError:void 0}),t}async restoreSession(e){this.assertUsable();let t;try{t=await this.#e.auth.restoreSession(e)}catch(e){let t=this.createSdkError(`SESSION_TOKEN_FAILED`,`MonitorDog SDK session token could not be restored.`,e);throw this.transitionToError(t),this.#t.onAuthError?.(t),t}try{await this.completeAuthenticatedLogin()}catch(e){let t=this.createSdkError(`ACCOUNT_POLICY_FAILED`,`MonitorDog account or policy could not be loaded.`,e);throw this.rollbackAuthenticatedLogin(),this.transitionToError(t),this.#t.onAuthError?.(t),t}return this.updateState({session:`authenticated`,runtime:this.#r===`stopped`?`stopped`:`idle`,camera:this.#e.webcam.isRunning?`active`:`idle`,lastError:void 0}),t}async logout(){if(this.assertUsable(),this.isDetectorRunning())throw this.lifecycleError(`DETECTOR_RUNNING`,`MonitorDog detector is running. Call stop() before logout().`);if(!this.#e.auth.getToken()){this.clearSessionState();return}try{await this.#e.auth.logout(),this.clearSessionState()}catch(e){let t=this.createSdkError(`LOGOUT_FAILED`,`MonitorDog logout failed.`,e);throw this.transitionToError(t),this.#t.onAuthError?.(t),t}finally{this.#e.auth.getToken()||(this.#n=`anonymous`)}}async start(){this.assertUsable(),this.assertAuthenticated(`starting detection`),!this.isDetectorRunning()&&(this.#o||=this.startRuntime().finally(()=>{this.#o=void 0}),await this.#o)}stop(){this.assertUsable(),this.hasRuntimeToStop()&&(this.stopLocalRuntime(),this.updateState({runtime:this.#n===`authenticated`?`stopped`:`idle`,camera:`idle`,lastError:void 0}))}setRunInBackground(e){this.assertUsable(),this.#t.runInBackground=e,this.#e.webcam.syncBackgroundPreference()}setEventReportingEnabled(e){this.assertUsable(),this.#t.eventReportingEnabled=e,e||this.#e.detectionEvents.reset()}setPhoneConfidenceThreshold(e){this.assertUsable(),$(e),this.#e.setPhoneConfidenceThreshold(e)}getUserPreferences(){return this.assertUsable(),this.#e.userPreferences}getState(){return Object.freeze({session:this.#n,runtime:this.#r,camera:this.#i,tokenExpiresAt:this.#e.auth.getTokenExpiresAt(),email:this.#e.auth.getSessionEmail(),lastError:this.#a})}dispose(){this.#r!==`disposed`&&(this.stopLocalRuntime(),this.#e.detect.dispose(),this.#e.auth.dispose(),this.#e.resetAuthenticatedState(),this.updateState({session:`anonymous`,runtime:`disposed`,camera:`idle`,lastError:void 0}))}async completeAuthenticatedLogin(){let e=await this.#e.auth.authorizedFetch(`/account/me`,{method:`GET`,headers:{"content-type":`application/json`}});if(!e.ok)throw Error(`MonitorDog account request failed: ${e.status}`);let t=await e.json(),n=await this.#e.auth.authorizedFetch(`/account/${t.uuid}/lock_policy`,{method:`GET`,headers:{"content-type":`application/json`}});if(!n.ok)throw Error(`MonitorDog lock policy request failed: ${n.status}`);let r=await n.json();this.#e.applyPolicyItems(r,t)}resetLoggedOutState(){this.stopLocalRuntime(),this.#e.detect.dispose(),this.#e.resetAuthenticatedState(),this.updateState({session:`anonymous`,runtime:`idle`,camera:`idle`,lastError:void 0})}rollbackAuthenticatedLogin(){this.#e.auth.dispose(),this.#e.resetAuthenticatedState()}async startRuntime(){try{this.updateState({runtime:`loading`,camera:`idle`,lastError:void 0}),await this.#e.detect.load(),this.updateState({runtime:`starting`,camera:`requesting`}),await this.#e.webcam.start(),this.updateState({runtime:`running`,camera:this.#e.shouldPauseDetection?`idle`:`active`,lastError:void 0})}catch(e){let t=this.createSdkError(this.getStartErrorCode(e),this.getStartErrorMessage(e),e);throw this.transitionToError(t,xe(t.code)?`blocked`:`idle`),this.#t.onError?.(t),t}}clearSessionState(){this.#e.resetAuthenticatedState(),this.updateState({session:`anonymous`,runtime:`idle`,camera:`idle`,lastError:void 0})}stopLocalRuntime(){this.#e.webcam.stop()}assertUsable(){if(this.#r===`disposed`)throw this.lifecycleError(`ALREADY_DISPOSED`,`MonitorDog detector instance has already been disposed.`,void 0,`disposed`)}assertAuthenticated(e){if(!this.#e.auth.isAuthenticated())throw this.lifecycleError(`NOT_LOGGED_IN`,`MonitorDog login is required before ${e}.`)}lifecycleError(e,t,n,r=`error`){let i=this.createSdkError(e,t,n);return r===`error`?this.transitionToError(i):this.updateState({runtime:r,lastError:i},!0),i}transitionToError(e,t=this.#i){this.updateState({runtime:`error`,camera:t,lastError:e},!0)}updateState(e,t=!1){let n=!1;e.session!==void 0&&e.session!==this.#n&&(this.#n=e.session,n=!0),e.runtime!==void 0&&e.runtime!==this.#r&&(this.#r=e.runtime,n=!0),e.camera!==void 0&&e.camera!==this.#i&&(this.#i=e.camera,n=!0),`lastError`in e&&e.lastError!==this.#a&&(this.#a=e.lastError,n=!0),(n||t)&&this.notifyStatusChange()}notifyStatusChange(){try{this.#t.onStatusChange?.(this.getState())}catch(e){this.#t.onError?.(e)}}createSdkError(e,t,n){return y(n)?n:new v(e,t,n)}isDetectorRunning(){return this.#r===`running`||this.#r===`starting`||!!this.#o||this.#e.webcam.isRunning||this.#e.webcam.isStarting}hasRuntimeToStop(){return this.#r===`running`||this.#r===`starting`||this.#i!==`idle`||!!this.#o||this.#e.webcam.isRunning||this.#e.webcam.isStarting}getStartErrorCode(e){return this.isCameraPermissionError(e)?`CAMERA_PERMISSION_DENIED`:this.isCameraReadError(e)?`CAMERA_READ_FAILED`:this.#r===`loading`?`MODEL_LOAD_FAILED`:`RUNTIME_START_FAILED`}getStartErrorMessage(e){switch(this.getStartErrorCode(e)){case`CAMERA_PERMISSION_DENIED`:return`MonitorDog camera permission was denied.`;case`CAMERA_READ_FAILED`:return`MonitorDog camera could not be read.`;case`MODEL_LOAD_FAILED`:return`MonitorDog detection model failed to load.`;default:return`MonitorDog detector runtime failed to start.`}}isCameraPermissionError(e){return typeof DOMException<`u`&&e instanceof DOMException&&(e.name===`NotAllowedError`||e.name===`SecurityError`)}isCameraReadError(e){return typeof DOMException<`u`&&e instanceof DOMException&&e.name===`NotReadableError`}};function xe(e){return e===`CAMERA_PERMISSION_DENIED`||e===`CAMERA_READ_FAILED`}var Z;function Q(e){return Z=new X(e),Z}async function Se(e){return X.init(e)}function Ce(){if(!Z)throw Error(`MonitorDog is not configured. Call MonitorDogDetector.init(), createMonitorDogDetector(), or configureMonitorDogDetector() before using getDetector().`);return Z}function we(){if(typeof navigator>`u`)return!1;let e=h();return e===`mobile`||e===`tablet`}function Te(e){if(!e||typeof e.apiBaseUrl!=`string`||e.apiBaseUrl.length===0)throw Error(`MonitorDog apiBaseUrl is required.`);if(typeof e.sessionTokenProvider!=`function`)throw Error(`MonitorDog sessionTokenProvider is required.`);if(e.restoreSessionTokenProvider!==void 0&&typeof e.restoreSessionTokenProvider!=`function`)throw Error(`MonitorDog restoreSessionTokenProvider must be a function when provided.`);if(typeof e.onDetect!=`function`)throw Error(`MonitorDog onDetect callback is required.`);if(e.runtimeAssetBaseUrl!==void 0&&_(e.runtimeAssetBaseUrl),e.modelInputSize!==void 0&&!ne(e.modelInputSize))throw Error(`MonitorDog modelInputSize must be "auto", 320, 416, or 640.`);if(e.phoneRotationFallback!==void 0&&typeof e.phoneRotationFallback!=`boolean`)throw Error(`MonitorDog phoneRotationFallback must be a boolean when provided.`);if(e.phoneRotationFallbackMinIntervalMs!==void 0&&!Ee(e.phoneRotationFallbackMinIntervalMs))throw Error(`MonitorDog phoneRotationFallbackMinIntervalMs must be a non-negative finite number when provided.`);if(e.phoneRotationFallbackExecution!==void 0&&e.phoneRotationFallbackExecution!==`sequential`&&e.phoneRotationFallbackExecution!==`parallel`)throw Error(`MonitorDog phoneRotationFallbackExecution must be "sequential" or "parallel" when provided.`);$(e.phoneConfidenceThreshold)}function Ee(e){return typeof e==`number`&&Number.isFinite(e)&&e>=0}function $(e){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.`)}e.MonitorDogDetector=X,e.MonitorDogSdkError=v,e.configureMonitorDogDetector=Q,e.createMonitorDogDetector=Se,e.getDetector=Ce,e.isMonitorDogSdkError=y});
|
|
@@ -4,4 +4,8 @@ export declare function resolveModelInputSize(modelInputSize: MonitorDogModelInp
|
|
|
4
4
|
export declare function normalizeRuntimeAssetBaseUrl(runtimeAssetBaseUrl: string | undefined): string | undefined;
|
|
5
5
|
export declare function resolveRuntimeAssetPath(runtimeAssetBaseUrl: string, assetPath: string): string;
|
|
6
6
|
export declare function resolveRuntimeSdkAssetUrl(filename: string, runtimeAssetBaseUrl: string | undefined, defaultUrl: string): string;
|
|
7
|
-
export
|
|
7
|
+
export type RuntimeOrtWasmPaths = {
|
|
8
|
+
mjs: string;
|
|
9
|
+
wasm: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function resolveRuntimeOrtWasmPaths(runtimeAssetBaseUrl: string | undefined, defaultUrls: RuntimeOrtWasmPaths): RuntimeOrtWasmPaths;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MonitorDogLoginRequest, MonitorDogSessionToken } from "../types";
|
|
1
|
+
import type { MonitorDogLoginRequest, MonitorDogRestoreSessionRequest, MonitorDogSessionToken } from "../types";
|
|
2
2
|
import type { ServiceContainer } from "./container";
|
|
3
3
|
export declare class AuthService {
|
|
4
4
|
private readonly services;
|
|
@@ -10,8 +10,10 @@ export declare class AuthService {
|
|
|
10
10
|
private refreshIntervalId?;
|
|
11
11
|
private authSessionId;
|
|
12
12
|
private sessionEmail?;
|
|
13
|
+
private sessionTokenRefresher?;
|
|
13
14
|
constructor(services: ServiceContainer);
|
|
14
15
|
login(request: MonitorDogLoginRequest): Promise<MonitorDogSessionToken>;
|
|
16
|
+
restoreSession(request?: MonitorDogRestoreSessionRequest): Promise<MonitorDogSessionToken>;
|
|
15
17
|
logout(): Promise<void>;
|
|
16
18
|
getToken(): string | undefined;
|
|
17
19
|
getTokenExpiresAt(): number | undefined;
|
|
@@ -22,6 +24,7 @@ export declare class AuthService {
|
|
|
22
24
|
getValidAccessToken(): Promise<string | undefined>;
|
|
23
25
|
authorizedFetch(path: string, init?: RequestInit, retry?: boolean): Promise<Response>;
|
|
24
26
|
private setSessionTokenPayload;
|
|
27
|
+
private establishSession;
|
|
25
28
|
private setTokens;
|
|
26
29
|
private clearTokens;
|
|
27
30
|
private refreshToken;
|