@incodetech/core 2.1.1 → 2.2.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/dist/{3dAvatarProvider-BwOmTMOy.esm.js → 3dAvatarProvider-g02DTFqT.esm.js} +811 -880
  2. package/dist/Actor-iTq7YY48.d.ts +1 -0
  3. package/dist/BrowserDiagnosticsCryptoProvider-CriIh1Gt.esm.js +95 -0
  4. package/dist/BrowserLazyImportProvider-BhoA957O.esm.js +114 -0
  5. package/dist/{BrowserStorageProvider-CBHBhKQN.esm.js → BrowserStorageProvider-k-FDkC4W.esm.js} +2 -4
  6. package/dist/{BrowserTimerProvider-CHloo0eQ.esm.js → BrowserTimerProvider-BXhgNxLt.esm.js} +1 -2
  7. package/dist/{BrowserVisibilityObserverProvider-GBS6XSii.esm.js → BrowserVisibilityObserverProvider-BX1BiLDK.esm.js} +1 -2
  8. package/dist/Face2DProvider-UUQt_vRC.esm.js +437 -0
  9. package/dist/{createFaceAvatar-CpdYp9Iy.d.ts → FaceDetectionProvider-Mh6q3EbA.d.ts} +107 -159
  10. package/dist/IBrowserEnvironmentCapability-DEaRRk-R.esm.js +9 -0
  11. package/dist/IFaceAvatarCapability-BrL19G0s.d.ts +23 -0
  12. package/dist/IFeatureManagementCapability-DdEUp6tB.d.ts +1125 -0
  13. package/dist/IIdCaptureCapability-DHTT3FC2.d.ts +237 -0
  14. package/dist/IStorageCapability-ORkQfK3F.d.ts +242 -0
  15. package/dist/{ITimerCapability-DJ73P4RK.esm.js → ITimerCapability-DgdDzp8G.esm.js} +1 -2
  16. package/dist/{Manager-goNPc_h_.d.ts → Manager-CQQ99QOI.d.ts} +1 -0
  17. package/dist/{MotionSensorProvider-BHuHoYvJ.esm.js → MotionSensorProvider-DGiV77J_.esm.js} +2 -37
  18. package/dist/{OpenViduRecordingProvider-CK6A5kiU.esm.js → OpenViduRecordingProvider-Du98qevC.esm.js} +2 -4
  19. package/dist/PrivacyLensProvider-D8PS7AJa.esm.js +405 -0
  20. package/dist/StateMachine-EDpYWy0i.d.ts +6 -0
  21. package/dist/{StreamCanvasCapture-CAqUdVkM.esm.js → StreamCanvasCapture-D2XcXCZ4.esm.js} +2 -4
  22. package/dist/{addressSearch-D7msRieq.esm.js → addressSearch-DQyrvDQj.esm.js} +10 -21
  23. package/dist/ae-signature.d.ts +4 -6
  24. package/dist/ae-signature.esm.js +10 -11
  25. package/dist/antifraud.d.ts +1 -6
  26. package/dist/antifraud.esm.js +3 -8
  27. package/dist/{antifraudManager-5KA84wtF.esm.js → antifraudManager-B8Plzf7a.esm.js} +11 -8
  28. package/dist/{antifraudManager-DCiNI6np.d.ts → antifraudManager-BY36bS12.d.ts} +3 -3
  29. package/dist/{antifraudStateMachine-BQVw46N5.esm.js → antifraudStateMachine-r4VxSBS4.esm.js} +5 -7
  30. package/dist/api-Bx3gKW_y.esm.js +129 -0
  31. package/dist/{apiError-DkOXfFBu.esm.js → apiError-DZfAyExM.esm.js} +25 -3
  32. package/dist/authentication.d.ts +3 -19
  33. package/dist/authentication.esm.js +3 -35
  34. package/dist/{authenticationManager-BeT6tNZm.d.ts → authenticationManager-BBMGTcwW.d.ts} +3 -4
  35. package/dist/{authenticationManager-BryLnSaF.esm.js → authenticationManager-DscbQwIl.esm.js} +7 -10
  36. package/dist/{authenticationStateMachine-DbdxfGHx.esm.js → authenticationStateMachine-SyuM00Fa.esm.js} +11 -15
  37. package/dist/avatar.d.ts +2 -2
  38. package/dist/avatar.esm.js +2 -3
  39. package/dist/avatar2dWarm-DqucNFX4.esm.js +1330 -0
  40. package/dist/avatarStats-CdUOb3VD.esm.js +136 -0
  41. package/dist/{backCameraStream-ChrMTJv-.esm.js → backCameraStream-CUeYm5eu.esm.js} +20 -8
  42. package/dist/browser-DlFgHpoC-DnyrCR8r.esm.js +1513 -0
  43. package/dist/callback-645_omgz.d.ts +133 -0
  44. package/dist/camera-_2sXMXiF.esm.js +140 -0
  45. package/dist/camera.d.ts +19 -2
  46. package/dist/camera.esm.js +2 -6
  47. package/dist/{canvas-Pi10hG_l.esm.js → canvas-E1zGkel4.esm.js} +1 -2
  48. package/dist/certificate-issuance.d.ts +34 -39
  49. package/dist/certificate-issuance.esm.js +4 -11
  50. package/dist/{certificateIssuanceStateMachine-DlZQT1_u.esm.js → certificateIssuanceStateMachine-COd7_l2T.esm.js} +7 -11
  51. package/dist/consent.d.ts +1 -4
  52. package/dist/consent.esm.js +3 -8
  53. package/dist/{consentManager-BwNu-uC-.esm.js → consentManager-BApTlfA0.esm.js} +5 -7
  54. package/dist/{consentManager-B4PMGXW-.d.ts → consentManager-uhDPdU6i.d.ts} +55 -61
  55. package/dist/{consentStateMachine-BOkVFiU7.esm.js → consentStateMachine-WD-S-Yhs.esm.js} +5 -7
  56. package/dist/{cpf-16m_cGAM.esm.js → cpf-BIADjddF.esm.js} +1 -2
  57. package/dist/createFaceAvatar-BEj18KXi.d.ts +50 -0
  58. package/dist/createFaceAvatar-DQKaRise.esm.js +103 -0
  59. package/dist/cross-document-data-match.d.ts +2 -26
  60. package/dist/cross-document-data-match.esm.js +2 -71
  61. package/dist/crossDocumentDataMatchManager-Dq8Z3SOg.d.ts +41 -0
  62. package/dist/crossDocumentDataMatchManager-OmYvyung.esm.js +84 -0
  63. package/dist/curp-validation.d.ts +1 -11
  64. package/dist/curp-validation.esm.js +3 -8
  65. package/dist/{curpValidationManager-CoqODZx5.d.ts → curpValidationManager-DVGr7Fq7.d.ts} +4 -6
  66. package/dist/{curpValidationManager-Cbji2inV.esm.js → curpValidationManager-UZxcrsrz.esm.js} +11 -7
  67. package/dist/{curpValidationStateMachine-Dlw4qfFb.esm.js → curpValidationStateMachine-9KwnqeoB.esm.js} +22 -14
  68. package/dist/custom-fields.d.ts +2 -5
  69. package/dist/custom-fields.esm.js +24 -11
  70. package/dist/custom-watchlist.d.ts +1 -3
  71. package/dist/custom-watchlist.esm.js +11 -10
  72. package/dist/{customWatchlistStateMachine-D8w0mNxm.esm.js → customWatchlistStateMachine-B_ey3TFj.esm.js} +5 -7
  73. package/dist/{dateUtils-BW6mBV6p.esm.js → dateUtils-CvG0FvK8.esm.js} +1 -2
  74. package/dist/{deepsightService-CViys6T4.esm.js → deepsightLoader-DcWjMC6A.esm.js} +68 -14
  75. package/dist/{deepsightService-BuTOFTr8.d.ts → deepsightService-DLVQS_RH.d.ts} +41 -2
  76. package/dist/device.d.ts +10 -2
  77. package/dist/device.esm.js +21 -21
  78. package/dist/document-capture.d.ts +3 -1816
  79. package/dist/document-capture.esm.js +3 -245
  80. package/dist/document-upload.d.ts +48 -55
  81. package/dist/document-upload.esm.js +8 -14
  82. package/dist/documentCaptureManager-B4Kivr8_.d.ts +2062 -0
  83. package/dist/documentCaptureManager-DszmcU-l.esm.js +296 -0
  84. package/dist/{documentCaptureStateMachine-BkTvU3yq.esm.js → documentCaptureStateMachine-D2jBwwVb.esm.js} +66 -40
  85. package/dist/dynamic-forms.d.ts +2 -4
  86. package/dist/dynamic-forms.esm.js +3 -9
  87. package/dist/{dynamicFormsManager-CHXUBNs4.esm.js → dynamicFormsManager-BoZ2-OUI.esm.js} +48 -9
  88. package/dist/{dynamicFormsManager-CKZkE7Wo.d.ts → dynamicFormsManager-fhK0yINk.d.ts} +22 -46
  89. package/dist/{dynamicFormsStateMachine-DJ1HGZff.esm.js → dynamicFormsStateMachine-D0RzkoEV.esm.js} +161 -34
  90. package/dist/ekyb.d.ts +5 -137
  91. package/dist/ekyb.esm.js +4 -179
  92. package/dist/ekybManager-DTvfxAOZ.esm.js +178 -0
  93. package/dist/ekybManager-Dzswb_b8.d.ts +114 -0
  94. package/dist/{ekybStateMachine-D9GzA4MW.esm.js → ekybStateMachine-BlTIozb6.esm.js} +16 -193
  95. package/dist/ekyc.d.ts +2 -79
  96. package/dist/ekyc.esm.js +4 -154
  97. package/dist/ekycManager-BFpHbBoT.d.ts +97 -0
  98. package/dist/ekycManager-oTstTJuL.esm.js +156 -0
  99. package/dist/{ekycStateMachine-DnVRiu3s.esm.js → ekycStateMachine-DHvksnrr.esm.js} +141 -423
  100. package/dist/ekycUtils-Dew1rBG0.esm.js +223 -0
  101. package/dist/electronic-signature.d.ts +3 -5
  102. package/dist/electronic-signature.esm.js +2 -10
  103. package/dist/{index-36QX_21w.d.ts → electronicSignatureManager-CcUXQZS7.d.ts} +220 -251
  104. package/dist/{electronicSignatureManager-DESRgObX.esm.js → electronicSignatureManager-DRYlHPjT.esm.js} +47 -33
  105. package/dist/email.d.ts +1 -5
  106. package/dist/email.esm.js +3 -10
  107. package/dist/{emailManager-CMS4q_r6.d.ts → emailManager-CADXW_9X.d.ts} +4 -7
  108. package/dist/{emailManager-B9Vrv3Ma.esm.js → emailManager-tE-YvNtS.esm.js} +76 -12
  109. package/dist/{emailStateMachine-CbmKFVSi.esm.js → emailStateMachine-Bm894MHB.esm.js} +7 -9
  110. package/dist/{endpoints-CwrFQfW7.esm.js → endpoints-CCzL3XD_.esm.js} +55 -6
  111. package/dist/{events-1wxZ97yf.esm.js → events-CxfNJVZW.esm.js} +43 -176
  112. package/dist/events.d.ts +28 -10
  113. package/dist/events.esm.js +2 -4
  114. package/dist/extensibility.d.ts +37 -37
  115. package/dist/extensibility.esm.js +31 -80
  116. package/dist/{externalFetch-hvmz_npP.esm.js → externalFetch-BKBThAUC.esm.js} +2 -4
  117. package/dist/face-match.d.ts +2 -225
  118. package/dist/face-match.esm.js +3 -173
  119. package/dist/{faceCaptureManagerFactory-C9TiGbkA.esm.js → faceCaptureManagerFactory-BDAsBCkh.esm.js} +52 -31
  120. package/dist/{faceCaptureManagerFactory-DiJ64oem.d.ts → faceCaptureManagerFactory-BxWPpxyd.d.ts} +63 -24
  121. package/dist/{faceCaptureSetup-BqhqfFHL.esm.js → faceCaptureSetup-C7Qv79fA.esm.js} +57 -36
  122. package/dist/faceMatchManager-BXp2WUT-.esm.js +201 -0
  123. package/dist/faceMatchManager-BnvrZM2F.d.ts +268 -0
  124. package/dist/{faceMatchStateMachine-MDb30gCm.esm.js → faceMatchStateMachine-CJiO2yLO.esm.js} +14 -10
  125. package/dist/feature-management-DS_Nj5Gg.esm.js +615 -0
  126. package/dist/feature-management.d.ts +173 -0
  127. package/dist/feature-management.esm.js +2 -0
  128. package/dist/field-comparison.d.ts +1 -4
  129. package/dist/field-comparison.esm.js +2 -7
  130. package/dist/{fieldComparisonManager-OLKVsG2Z.d.ts → fieldComparisonManager-CBvEGxFx.d.ts} +3 -5
  131. package/dist/{fieldComparisonManager-Cw4uzD7S.esm.js → fieldComparisonManager-DhnYdYZ2.esm.js} +6 -11
  132. package/dist/fiscal-qr.d.ts +1 -6
  133. package/dist/fiscal-qr.esm.js +14 -29
  134. package/dist/flow-events.d.ts +2 -9
  135. package/dist/flow.d.ts +59 -21
  136. package/dist/flow.esm.js +132 -49
  137. package/dist/{flowCompletionService-B6P6_EF3.esm.js → flowCompletionService-BSe3p7pg.esm.js} +4 -6
  138. package/dist/flowServices-unhF9V9F.esm.js +620 -0
  139. package/dist/geolocation.d.ts +1 -4
  140. package/dist/geolocation.esm.js +3 -9
  141. package/dist/{geolocationManager-CF6-NizA.esm.js → geolocationManager-Bv9MSVNr.esm.js} +44 -16
  142. package/dist/geolocationManager-Cz744E5S.d.ts +506 -0
  143. package/dist/{geolocationStateMachine-CD2XJs1b.esm.js → geolocationStateMachine-BxD6JK1M.esm.js} +53 -28
  144. package/dist/{getBrowser-1yNcfFZR.esm.js → getBrowser-Cb8Zgrgp.esm.js} +1 -2
  145. package/dist/getBrowser-DNrQeL4T.esm.js +16 -0
  146. package/dist/getDeviceClass-9y-kbVDw.esm.js +19 -0
  147. package/dist/{getDeviceClass-C-Dg6IsJ.esm.js → getDeviceClass-CeBiEayS.esm.js} +1 -2
  148. package/dist/getParsedUserAgent-pJjATANs.esm.js +1622 -0
  149. package/dist/government-validation.d.ts +3 -6
  150. package/dist/government-validation.esm.js +7 -13
  151. package/dist/{governmentValidationStateMachine-BE5wiQ7Y.esm.js → governmentValidationStateMachine-BYKYUdza.esm.js} +8 -11
  152. package/dist/home.d.ts +14 -22
  153. package/dist/home.esm.js +3 -8
  154. package/dist/http.d.ts +0 -1
  155. package/dist/http.esm.js +2 -4
  156. package/dist/id-ocr.d.ts +8 -7
  157. package/dist/id-ocr.esm.js +20 -9
  158. package/dist/id-selfie-flow.d.ts +179 -0
  159. package/dist/id-selfie-flow.esm.js +917 -0
  160. package/dist/id-verification.d.ts +2 -191
  161. package/dist/id-verification.esm.js +3 -43
  162. package/dist/id.d.ts +7 -18
  163. package/dist/id.esm.js +47 -53
  164. package/dist/{idCaptureDefaults-CZajItdO.esm.js → idCaptureDefaults-WeHbQM7W.esm.js} +54 -17
  165. package/dist/idCaptureManager-BjU-Wyow.d.ts +429 -0
  166. package/dist/{idCaptureManager-DASPUMtC.esm.js → idCaptureManager-BjiBSrHm.esm.js} +173 -34
  167. package/dist/idCaptureServices-CFDwqTtQ.esm.js +396 -0
  168. package/dist/{idCaptureStateMachine-DZ2ZTSxu.esm.js → idCaptureStateMachine-CRwQh8jc.esm.js} +438 -585
  169. package/dist/{idOcrManager-Tm4LzKR0.esm.js → idOcrManager-CvJZhmBR.esm.js} +4 -7
  170. package/dist/{idOcrManager-DLfAjDZn.d.ts → idOcrManager-DXc_xRN7.d.ts} +62 -229
  171. package/dist/{idOcrStateMachine-BJxZCxwS.esm.js → idOcrStateMachine-Bq_e3l4E.esm.js} +15 -20
  172. package/dist/idVerificationManager-BB4Pj_N6.d.ts +197 -0
  173. package/dist/idVerificationManager-CduNXhWd.esm.js +51 -0
  174. package/dist/{idVerificationStateMachine-DXN9WcdM.esm.js → idVerificationStateMachine-GEQWUPU2.esm.js} +5 -7
  175. package/dist/identity-reuse.d.ts +1 -4
  176. package/dist/identity-reuse.esm.js +3 -8
  177. package/dist/{identityReuseManager-LjkPvSQN.esm.js → identityReuseManager-D5vXknnJ.esm.js} +24 -7
  178. package/dist/{identityReuseManager-CLVOYxcp.d.ts → identityReuseManager-v2TH5g7e.d.ts} +38 -43
  179. package/dist/{identityReuseStateMachine-Bp-zONoV.esm.js → identityReuseStateMachine-AubRPhIi.esm.js} +6 -8
  180. package/dist/index-B8weJxmL.d.ts +1 -0
  181. package/dist/index-BKOWUhxG.d.ts +258 -0
  182. package/dist/{index-DrpWp15Z.d.ts → index-CLMF0QLQ.d.ts} +3 -3
  183. package/dist/index.d.ts +1 -3
  184. package/dist/index.esm.js +2 -15
  185. package/dist/{invokeOnCaptureCallback-CCS2Ruzi.esm.js → invokeOnCaptureCallback-1m1VJ3Q4.esm.js} +2 -4
  186. package/dist/{lib-Bjd6nOLG.esm.js → lib-DAyUtOTj.esm.js} +1510 -1589
  187. package/dist/mandatory-consent.d.ts +2 -10
  188. package/dist/mandatory-consent.esm.js +3 -8
  189. package/dist/{mandatoryConsentManager-DeBmOHcQ.d.ts → mandatoryConsentManager-B29kR0XA.d.ts} +60 -85
  190. package/dist/{mandatoryConsentManager-DZ26sg4B.esm.js → mandatoryConsentManager-BeELm1zS.esm.js} +4 -7
  191. package/dist/{mandatoryConsentStateMachine-_44ZoDSh.esm.js → mandatoryConsentStateMachine-zroQGzwb.esm.js} +5 -7
  192. package/dist/manualReviewService-D4IkipnN.esm.js +15 -0
  193. package/dist/{mediaRecorderOptions-CClCKAiF.esm.js → mediaRecorderOptions-dALSV8af.esm.js} +2 -4
  194. package/dist/{mediapipeShared-Bcmkzs3x.esm.js → mediapipeShared-B6oNoXEQ.esm.js} +21 -9
  195. package/dist/{onDeviceFaceResults-DILtthks.esm.js → onDeviceFaceResults-f81FVdQs.esm.js} +30 -87
  196. package/dist/openviduLazy-CCDpFWg1.esm.js +10 -0
  197. package/dist/{otp-B1YeyRXu.d.ts → otp-CEWfTj9v.d.ts} +0 -1
  198. package/dist/{otp-uaXiKt_R.esm.js → otp-D2k3PeSL.esm.js} +3 -14
  199. package/dist/{permissionGuards-BNOe4Tnu.esm.js → permissionGuards-KINpmKtI.esm.js} +2 -4
  200. package/dist/{permissionServices-C_kxhNeo.esm.js → permissionServices-UvUcOSRb.esm.js} +35 -28
  201. package/dist/personhood.d.ts +13 -20
  202. package/dist/personhood.esm.js +153 -85
  203. package/dist/phone.d.ts +1 -5
  204. package/dist/phone.esm.js +3 -10
  205. package/dist/{phoneManager-_KtitbUA.d.ts → phoneManager-BBU8Lq0O.d.ts} +4 -7
  206. package/dist/{phoneManager-CRblfdcI.esm.js → phoneManager-Cpiai2IM.esm.js} +82 -12
  207. package/dist/{phoneStateMachine-DjFGWMjQ.esm.js → phoneStateMachine-E1fUUcNM.esm.js} +7 -9
  208. package/dist/{platform-0Ot-bF_a.esm.js → platform-BJrm5nzZ.esm.js} +31 -11
  209. package/dist/privacyLensWorker-DI-Rg83h.esm.js +355 -0
  210. package/dist/qe-signature.d.ts +4 -6
  211. package/dist/qe-signature.esm.js +10 -11
  212. package/dist/{recordingService-CxaYkITO.esm.js → recordingService-CFpfdXSS.esm.js} +13 -31
  213. package/dist/redirect-to-mobile.d.ts +2 -6
  214. package/dist/redirect-to-mobile.esm.js +3 -10
  215. package/dist/{redirectToMobileManager-dv29o_LS.d.ts → redirectToMobileManager-BD2PvT5B.d.ts} +8 -44
  216. package/dist/{redirectToMobileManager-DbuNUlru.esm.js → redirectToMobileManager-C0dfc7f6.esm.js} +28 -8
  217. package/dist/{redirectToMobileStateMachine-BRaIJWOM.esm.js → redirectToMobileStateMachine-C9SYCJcH.esm.js} +74 -18
  218. package/dist/rolldown-runtime-FZ4Itg2g.esm.js +42 -0
  219. package/dist/{runChildModule-kojSv3MH.esm.js → runChildModule-DpvgAGFA.esm.js} +10 -9
  220. package/dist/{WasmUtilProvider-BgzcXBdl.esm.js → safeStorage-Ep56I-f_.esm.js} +98 -473
  221. package/dist/selfie.d.ts +8 -21
  222. package/dist/selfie.esm.js +40 -47
  223. package/dist/selfieErrorUtils-C2PYBVsp.esm.js +90 -0
  224. package/dist/{selfieManager-B1Px3GGa.esm.js → selfieManager-Br4onIMy.esm.js} +7 -10
  225. package/dist/{selfieManager-4juKfrHG.d.ts → selfieManager-DwlCppg0.d.ts} +3 -4
  226. package/dist/{selfieStateMachine-D0TS93Tu.esm.js → selfieStateMachine-CNGs8vFK.esm.js} +14 -29
  227. package/dist/{session-CLsU2Jnb.esm.js → session-CX2H3tmI.esm.js} +16 -7
  228. package/dist/session.d.ts +12 -10
  229. package/dist/session.esm.js +5 -15
  230. package/dist/sessionInitializer-CV6Rj_dn.esm.js +1865 -0
  231. package/dist/{setup-CfNsYAeB.esm.js → setup-CYdVacqv.esm.js} +319 -137
  232. package/dist/{setup-CmA2apmN.d.ts → setup-DywQeePQ.d.ts} +186 -4
  233. package/dist/signature.d.ts +2 -96
  234. package/dist/signature.esm.js +3 -108
  235. package/dist/signatureManager-DGBSWz2_.d.ts +106 -0
  236. package/dist/signatureManager-DdPgcmou.esm.js +113 -0
  237. package/dist/{signatureStateMachine-CdhlMih-.esm.js → signatureStateMachine-Cf73DGWO.esm.js} +5 -7
  238. package/dist/spawn-D9jgw9pW.d.ts +1441 -0
  239. package/dist/src-0Jurt29N.esm.js +4482 -0
  240. package/dist/{stats-BVy52wLy.esm.js → stats-B0nFKawG.esm.js} +3 -5
  241. package/dist/stats.esm.js +2 -5
  242. package/dist/topLevelStateName-B5i2avbh.esm.js +41 -0
  243. package/dist/{tri-CFAPtAUM.esm.js → tri-4RsGrIt6.esm.js} +3 -119
  244. package/dist/tri.d.ts +2 -2
  245. package/dist/tri.esm-BIjHhBJ2.esm.js +2620 -0
  246. package/dist/tri.esm.js +2 -4
  247. package/dist/trueSight-B8G85W4z.esm.js +1 -0
  248. package/dist/trueSightService-6dTpiaTh.esm.js +1894 -0
  249. package/dist/trust-graph.d.ts +4 -5
  250. package/dist/trust-graph.esm.js +13 -9
  251. package/dist/types-BEwVKkLJ.d.ts +15 -0
  252. package/dist/{types-BKLb3C42.esm.js → types-BN5RPPIZ.esm.js} +1 -2
  253. package/dist/types-BSBzhHRH.d.ts +57 -0
  254. package/dist/types-BX_XkMsQ2.d.ts +21 -0
  255. package/dist/types-BfHiko5D.d.ts +48 -0
  256. package/dist/{types-D8Cl1N2Z.d.ts → types-BfgmV7s72.d.ts} +2 -2
  257. package/dist/types-CJ7Yl9K-2.d.ts +164 -0
  258. package/dist/types-DPIDuhut.d.ts +40 -0
  259. package/dist/types-DVmXIdzW.d.ts +82 -0
  260. package/dist/types-DelMqZLe.d.ts +105 -0
  261. package/dist/types-EELWyWpd.d.ts +6 -0
  262. package/dist/{types-fO6KIdol.d.ts → types-Hmd7U0JA.d.ts} +80 -6
  263. package/dist/{types-BUgeB2X6.d.ts → types-KPvmag_B.d.ts} +7 -7
  264. package/dist/types-M6eb82ra2.d.ts +589 -0
  265. package/dist/{types-DV3wkhQ4.d.ts → types-Vb4P9ovf.d.ts} +1 -3
  266. package/dist/{urlUtils-CpiYwn7w.esm.js → urlUtils-D6phjq1-.esm.js} +1 -2
  267. package/dist/{video-ZY92rkel.esm.js → video-BtSWtHy1.esm.js} +1 -2
  268. package/dist/video-selfie.d.ts +71 -117
  269. package/dist/video-selfie.esm.js +575 -643
  270. package/dist/videoSelfieCameraWarmer-h_VUk5Vu.esm.js +651 -0
  271. package/dist/videoSelfieStepDetector-D3oo2ofo.d.ts +123 -0
  272. package/dist/wasm.d.ts +2 -4
  273. package/dist/wasm.esm.js +4 -15
  274. package/dist/wasmDefaults-DTUrftxR.esm.js +125 -0
  275. package/dist/{wasmDsFlagSync-Ch0mFJNT.esm.js → wasmDsFlagSync-BqUCwLY8.esm.js} +2 -4
  276. package/dist/wasmWebClient-DM8lkb0z.esm.js +407 -0
  277. package/dist/watchlist-for-business.d.ts +1 -3
  278. package/dist/watchlist-for-business.esm.js +9 -9
  279. package/dist/watchlist.d.ts +1 -52
  280. package/dist/watchlist.esm.js +3 -70
  281. package/dist/{watchlistForBusinessStateMachine-R1Yp1g5A.esm.js → watchlistForBusinessStateMachine-BcBMkMvV.esm.js} +5 -7
  282. package/dist/watchlistManager-CjSMmbyq.esm.js +83 -0
  283. package/dist/watchlistManager-DLXef90v.d.ts +68 -0
  284. package/dist/{watchlistStateMachine-D07UVq1m.esm.js → watchlistStateMachine-Bl7Wy9Cm.esm.js} +5 -7
  285. package/dist/workflow.d.ts +239 -203
  286. package/dist/workflow.esm.js +156 -101
  287. package/dist/xstate-actors.esm-CtI5S0f4.esm.js +310 -0
  288. package/dist/{xstate.esm-nY3M5UYm.esm.js → xstate.esm-Cf4e0Cfd.esm.js} +136 -610
  289. package/package.json +14 -9
  290. package/dist/Actor-BwgmOPkb.d.ts +0 -2
  291. package/dist/Face2DProvider-CZU11g6r.esm.js +0 -824
  292. package/dist/FaceDetectionProvider-CPWg-PAH.d.ts +0 -119
  293. package/dist/IWasmUtilCapability-DaSNxgA8.d.ts +0 -150
  294. package/dist/PrivacyLensProvider-B_zrV25p.esm.js +0 -339
  295. package/dist/StateMachine-D5WO6lHS.d.ts +0 -2
  296. package/dist/StreamCanvasCapture-DHaWferF.d.ts +0 -42
  297. package/dist/ae-signature-Pp4oCAHD.esm.js +0 -12
  298. package/dist/api-DsbUi7TO.esm.js +0 -72
  299. package/dist/browser-DlFgHpoC-Br3G10gw.esm.js +0 -1425
  300. package/dist/browserSimulation-DZwEy9bu.esm.js +0 -2804
  301. package/dist/camera-CxxXV0VN.esm.js +0 -79
  302. package/dist/canvas-90BqS0NF.d.ts +0 -112
  303. package/dist/chunk-CIKcdghV.esm.js +0 -49
  304. package/dist/clientLifecycle-VyzRfALg.esm.js +0 -534
  305. package/dist/cpf-ocr.d.ts +0 -10
  306. package/dist/cpf-ocr.esm.js +0 -8
  307. package/dist/cpfOcrManager-9eM4z4o7.esm.js +0 -190
  308. package/dist/cpfOcrManager-C5U9E0hf.d.ts +0 -216
  309. package/dist/createFaceAvatar-BZSg2MNo.esm.js +0 -46
  310. package/dist/deepsightLoader-CU_tiLMx.esm.js +0 -62
  311. package/dist/flowServices-DkQmOkLV.esm.js +0 -208
  312. package/dist/geolocationManager-DaHYFkVO.d.ts +0 -156
  313. package/dist/getDeviceClass-DIjnTPjR.esm.js +0 -14
  314. package/dist/http-CnsKEaJY.esm.js +0 -0
  315. package/dist/idCaptureManager-CwuXtVu6.d.ts +0 -1013
  316. package/dist/index-BAyZ8_iI.d.ts +0 -93
  317. package/dist/openviduLazy-jPgABwrt.esm.js +0 -3
  318. package/dist/openviduLazy-wEojM41w.esm.js +0 -12
  319. package/dist/qe-signature-BnWIpR-O.esm.js +0 -12
  320. package/dist/sessionInitializer-Dj7-aJaP.esm.js +0 -547
  321. package/dist/tri.esm-DDJ1zOqG.esm.js +0 -2593
  322. package/dist/types-BcF-fii5.d.ts +0 -5
  323. package/dist/videoSelfieSteps-Djpv7cjb.esm.js +0 -58
  324. /package/dist/{IVisibilityObserverCapability-BZ1rE7ly.d.ts → IVisibilityObserverCapability-D4tvIB5v.d.ts} +0 -0
  325. /package/dist/{camera-CKU96nwJ.d.ts → camera-9wWD-pwg.d.ts} +0 -0
  326. /package/dist/{flowCompletionService-BOSTlAWo.d.ts → flowCompletionService-BlAHsKyv.d.ts} +0 -0
  327. /package/dist/{types-BgjMAEXl.d.ts → types-Bk_6dmDa.d.ts} +0 -0
  328. /package/dist/{warmup-Dd0iq6KF.d.ts → warmup-Dv2alr2-.d.ts} +0 -0
@@ -0,0 +1,1330 @@
1
+ import { i as detectWorkerSourceInstrumentation, o as createFramePacer } from "./privacyLensWorker-DI-Rg83h.esm.js";
2
+ //#region ../infra/src/avatar/2d-default-avatar/assets.ts
3
+ /**
4
+ * 2D avatar MediaPipe asset resolution — **self-contained** (no shared
5
+ * `avatarDefaults`; owns its asset config). No VRM here — 2D satin face.
6
+ * See docs/features/FACE_AVATAR.md → Isolation and ownership.
7
+ *
8
+ * Prebuilt tasks-vision ESM + wasm + the face-landmarker model. Public CDNs for
9
+ * development; production should self-host.
10
+ */
11
+ const DEFAULT_MEDIAPIPE_MODULE_URL = "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.35";
12
+ const DEFAULT_FACE_LANDMARKER_MODEL_URL = "https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task";
13
+ function valid(value) {
14
+ return typeof value === "string" && value.trim() !== "";
15
+ }
16
+ function resolveAvatar2DAssets(overrides) {
17
+ const moduleUrl = valid(overrides?.mediapipeModulePath) ? overrides.mediapipeModulePath : DEFAULT_MEDIAPIPE_MODULE_URL;
18
+ return {
19
+ mediapipeModulePath: moduleUrl,
20
+ mediapipeWasmPath: valid(overrides?.mediapipeWasmPath) ? overrides.mediapipeWasmPath : `${moduleUrl}/wasm`,
21
+ faceLandmarkerModelPath: valid(overrides?.faceLandmarkerModelPath) ? overrides.faceLandmarkerModelPath : DEFAULT_FACE_LANDMARKER_MODEL_URL
22
+ };
23
+ }
24
+ //#endregion
25
+ //#region ../infra/src/avatar/renderers/SatinSmileyRenderer.ts
26
+ /**
27
+ * The satin-smiley drawing core. SELF-CONTAINED (serialized via toString into
28
+ * the avatar-2d worker blob): no module-level references — all constants,
29
+ * palettes and helpers are inside; keep it free of spread/async helpers.
30
+ */
31
+ function createSatinSmileyCore(canvas) {
32
+ const SPRITE = 512;
33
+ const HEAD_CX = 256;
34
+ const HEAD_CY = 256;
35
+ const HEAD_R = 150;
36
+ const HALO_R = 178;
37
+ const EYE_Y = 218;
38
+ const EYE_DX = 56;
39
+ const EYE_RX = 12;
40
+ const NOSE_Y0 = 258;
41
+ const NOSE_Y1 = 292;
42
+ const MOUTH_Y = 330;
43
+ const MOUTH_HALF = 44;
44
+ const YAW_PARALLAX = 90;
45
+ const PITCH_PARALLAX = 72;
46
+ const REST_SMILE = .35;
47
+ const PALETTE_ALPHA_30 = .08;
48
+ const PRESENCE_ALPHA_30 = .12;
49
+ const REF_FRAME_MS = 1e3 / 30;
50
+ const MAX_RENDER_DT_MS = 500;
51
+ const RENDER_DT_SEED_MS = REF_FRAME_MS;
52
+ const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
53
+ const hexToRgb = (hex) => {
54
+ const h = hex.replace("#", "");
55
+ return [
56
+ parseInt(h.slice(0, 2), 16),
57
+ parseInt(h.slice(2, 4), 16),
58
+ parseInt(h.slice(4, 6), 16)
59
+ ];
60
+ };
61
+ const rgb = (c) => `rgb(${c[0] | 0}, ${c[1] | 0}, ${c[2] | 0})`;
62
+ const rgba = (c, a) => `rgba(${c[0] | 0}, ${c[1] | 0}, ${c[2] | 0}, ${a})`;
63
+ const buildPalette = (stops, occlusion, contact, feature, halo) => ({
64
+ stops: [
65
+ hexToRgb(stops[0]),
66
+ hexToRgb(stops[1]),
67
+ hexToRgb(stops[2]),
68
+ hexToRgb(stops[3])
69
+ ],
70
+ occlusion: hexToRgb(occlusion),
71
+ contact: hexToRgb(contact),
72
+ feature: hexToRgb(feature),
73
+ halo: hexToRgb(halo)
74
+ });
75
+ const PALETTES = {
76
+ detecting: buildPalette([
77
+ "#f4f9ff",
78
+ "#dbeafe",
79
+ "#cbe0fb",
80
+ "#aacdf3"
81
+ ], "#6f9fd8", "#3a5f8f", "#007aff", "#2f86f0"),
82
+ success: buildPalette([
83
+ "#f0fdf4",
84
+ "#dcfce7",
85
+ "#bbf7d0",
86
+ "#86c79a"
87
+ ], "#3f7a52", "#1f5132", "#15803d", "#22c55e"),
88
+ error: buildPalette([
89
+ "#fff1f1",
90
+ "#fee2e2",
91
+ "#fecaca",
92
+ "#e89a9a"
93
+ ], "#8c4a4a", "#5f1e1e", "#b91c1c", "#dc2626")
94
+ };
95
+ const clonePalette = (p) => ({
96
+ stops: [
97
+ p.stops[0].slice(),
98
+ p.stops[1].slice(),
99
+ p.stops[2].slice(),
100
+ p.stops[3].slice()
101
+ ],
102
+ occlusion: p.occlusion.slice(),
103
+ contact: p.contact.slice(),
104
+ feature: p.feature.slice(),
105
+ halo: p.halo.slice()
106
+ });
107
+ const easeRgb = (cur, target, t) => {
108
+ cur[0] += (target[0] - cur[0]) * t;
109
+ cur[1] += (target[1] - cur[1]) * t;
110
+ cur[2] += (target[2] - cur[2]) * t;
111
+ };
112
+ /** Ease every channel of `cur` toward `target` in place (state crossfade). */
113
+ const easePaletteToward = (cur, target, t) => {
114
+ for (let i = 0; i < 4; i += 1) easeRgb(cur.stops[i], target.stops[i], t);
115
+ easeRgb(cur.occlusion, target.occlusion, t);
116
+ easeRgb(cur.contact, target.contact, t);
117
+ easeRgb(cur.feature, target.feature, t);
118
+ easeRgb(cur.halo, target.halo, t);
119
+ };
120
+ /** Frame-rate-independent EMA factor for a 30fps-authored alpha. */
121
+ const dtAlpha = (refAlpha, dtMs) => {
122
+ if (refAlpha <= 0) return 0;
123
+ if (refAlpha >= 1) return 1;
124
+ const tau = -33.333333333333336 / Math.log(1 - refAlpha);
125
+ return 1 - Math.exp(-dtMs / tau);
126
+ };
127
+ /** Dev override: read directly on main; bridged via setOverrideState in workers. */
128
+ const resolveGlobalOverride = () => {
129
+ const v = globalThis.__incodeAvatarState;
130
+ return v === "detecting" || v === "success" || v === "error" ? v : null;
131
+ };
132
+ let ctx = canvas.getContext("2d");
133
+ const size = canvas.width;
134
+ let presence = 0;
135
+ let faceState = "detecting";
136
+ let overrideState = null;
137
+ const eased = clonePalette(PALETTES.detecting);
138
+ let lastRenderAt = 0;
139
+ let ballGradients = null;
140
+ let specGradient = null;
141
+ const resolveBallGradients = (c2d) => {
142
+ const p = eased;
143
+ const parts = [];
144
+ parts.push(p.contact[0], p.contact[1], p.contact[2]);
145
+ for (let i = 0; i < 4; i += 1) parts.push(p.stops[i][0], p.stops[i][1], p.stops[i][2]);
146
+ parts.push(p.occlusion[0], p.occlusion[1], p.occlusion[2]);
147
+ const key = parts.map((v) => v | 0).join(",");
148
+ if (ballGradients && ballGradients.key === key) return ballGradients;
149
+ const contact = c2d.createRadialGradient(256, 424, 0, 256, 424, 122);
150
+ contact.addColorStop(0, rgba(p.contact, .28));
151
+ contact.addColorStop(1, rgba(p.contact, 0));
152
+ const body = c2d.createRadialGradient(HEAD_CX - HEAD_R * .28, HEAD_CY - HEAD_R * .34, HEAD_R * .08, HEAD_CX, HEAD_CY, HEAD_R * 1.05);
153
+ body.addColorStop(0, rgb(p.stops[0]));
154
+ body.addColorStop(.45, rgb(p.stops[1]));
155
+ body.addColorStop(.8, rgb(p.stops[2]));
156
+ body.addColorStop(1, rgb(p.stops[3]));
157
+ const occlusion = c2d.createRadialGradient(HEAD_CX, HEAD_CY, HEAD_R * .68, HEAD_CX, HEAD_CY, HEAD_R);
158
+ occlusion.addColorStop(0, rgba(p.occlusion, 0));
159
+ occlusion.addColorStop(1, rgba(p.occlusion, .22));
160
+ ballGradients = {
161
+ key,
162
+ contact,
163
+ body,
164
+ occlusion
165
+ };
166
+ return ballGradients;
167
+ };
168
+ /** Soft 3D-shaded ball via cached runtime gradients (state colours ease). */
169
+ const drawBall = (c2d) => {
170
+ const g = resolveBallGradients(c2d);
171
+ c2d.fillStyle = g.contact;
172
+ c2d.beginPath();
173
+ c2d.ellipse(256, 424, 122, 26, 0, 0, Math.PI * 2);
174
+ c2d.fill();
175
+ c2d.fillStyle = g.body;
176
+ c2d.beginPath();
177
+ c2d.arc(HEAD_CX, HEAD_CY, HEAD_R, 0, Math.PI * 2);
178
+ c2d.fill();
179
+ c2d.fillStyle = g.occlusion;
180
+ c2d.beginPath();
181
+ c2d.arc(HEAD_CX, HEAD_CY, HEAD_R, 0, Math.PI * 2);
182
+ c2d.fill();
183
+ if (!specGradient) {
184
+ const spec = c2d.createRadialGradient(200, 190, 0, 200, 190, 64);
185
+ spec.addColorStop(0, "rgba(255, 255, 255, 0.85)");
186
+ spec.addColorStop(1, "rgba(255, 255, 255, 0)");
187
+ specGradient = spec;
188
+ }
189
+ c2d.fillStyle = specGradient;
190
+ c2d.beginPath();
191
+ c2d.ellipse(200, 190, 64, 48, 0, 0, Math.PI * 2);
192
+ c2d.fill();
193
+ };
194
+ /**
195
+ * Dashed halo ring — a STATIC face-placement guide, the avatar-mode
196
+ * counterpart of the white silhouette outline in the normal video view:
197
+ * it marks where the user should put their face, so it must NOT move or
198
+ * scale with the tracked pose (the smiley moves within it; a too-close
199
+ * ball outgrowing the static ring reads as the same "back up" cue the
200
+ * video outline gives). Fixed centre, fixed radius, always on.
201
+ */
202
+ const drawHalo = (c2d, s, k) => {
203
+ c2d.save();
204
+ c2d.translate(s / 2, s / 2);
205
+ c2d.globalAlpha = .9;
206
+ c2d.strokeStyle = rgb(eased.halo);
207
+ c2d.lineWidth = 4 * k;
208
+ c2d.lineCap = "round";
209
+ c2d.setLineDash([15 * k, 12 * k]);
210
+ c2d.beginPath();
211
+ c2d.arc(0, 0, HALO_R * k, 0, Math.PI * 2);
212
+ c2d.stroke();
213
+ c2d.setLineDash([]);
214
+ c2d.restore();
215
+ };
216
+ /** One eye: a near-round dot (open) that flattens to a line as blink → 1. */
217
+ const drawEye = (c2d, cx, cy, blink, color) => {
218
+ const ry = 2.5 + (1 - blink) * 14;
219
+ c2d.fillStyle = color;
220
+ c2d.beginPath();
221
+ c2d.ellipse(cx, cy, EYE_RX, ry, 0, 0, Math.PI * 2);
222
+ c2d.fill();
223
+ };
224
+ /** Nose: a short, rounded vertical line under the eyes (personhood cue). */
225
+ const drawNose = (c2d, color) => {
226
+ c2d.strokeStyle = color;
227
+ c2d.lineWidth = 8;
228
+ c2d.lineCap = "round";
229
+ c2d.beginPath();
230
+ c2d.moveTo(HEAD_CX, NOSE_Y0);
231
+ c2d.lineTo(HEAD_CX, NOSE_Y1);
232
+ c2d.stroke();
233
+ };
234
+ /** Mouth: a rounded line — flat at rest, bowing up with smile, down on frown. */
235
+ const drawMouth = (c2d, smile, color) => {
236
+ const cy = MOUTH_Y;
237
+ const curve = 2 + smile * 32;
238
+ const lift = smile * 10;
239
+ c2d.strokeStyle = color;
240
+ c2d.lineWidth = 11;
241
+ c2d.lineCap = "round";
242
+ c2d.beginPath();
243
+ c2d.moveTo(HEAD_CX - MOUTH_HALF, cy - lift);
244
+ c2d.quadraticCurveTo(HEAD_CX, cy + curve, 300, cy - lift);
245
+ c2d.stroke();
246
+ };
247
+ return {
248
+ setState(state) {
249
+ faceState = state;
250
+ },
251
+ setOverrideState(state) {
252
+ overrideState = state;
253
+ },
254
+ dispose() {
255
+ ctx = null;
256
+ ballGradients = null;
257
+ specGradient = null;
258
+ },
259
+ render(frame) {
260
+ const c2d = ctx;
261
+ if (!c2d) return;
262
+ const s = size;
263
+ c2d.clearRect(0, 0, s, s);
264
+ const nowMs = performance.now();
265
+ const dtMs = clamp(lastRenderAt > 0 ? nowMs - lastRenderAt : RENDER_DT_SEED_MS, 1, MAX_RENDER_DT_MS);
266
+ lastRenderAt = nowMs;
267
+ const state = overrideState ?? resolveGlobalOverride() ?? faceState;
268
+ easePaletteToward(eased, PALETTES[state], dtAlpha(PALETTE_ALPHA_30, dtMs));
269
+ const target = frame.tracked ? 1 : 0;
270
+ presence += (target - presence) * dtAlpha(PRESENCE_ALPHA_30, dtMs);
271
+ const faceAlpha = presence;
272
+ const k = s / SPRITE;
273
+ const slideX = frame.rootOffset.x * s * .03;
274
+ const slideY = frame.rootOffset.y * s * .03;
275
+ const scale = 1 + clamp(frame.depth, -.6, .8) * .35;
276
+ const yaw = clamp(frame.headEuler.y, -.9, .9);
277
+ const pitch = clamp(frame.headEuler.x, -.9, .9);
278
+ drawHalo(c2d, s, k);
279
+ c2d.save();
280
+ c2d.translate(s / 2 + slideX, s / 2 + slideY);
281
+ c2d.rotate(frame.headEuler.z);
282
+ c2d.scale(scale * k, scale * k);
283
+ c2d.translate(-512 / 2, -512 / 2);
284
+ if (faceAlpha > .02) {
285
+ c2d.globalAlpha = faceAlpha;
286
+ drawBall(c2d);
287
+ const featX = yaw * YAW_PARALLAX;
288
+ const featY = pitch * PITCH_PARALLAX;
289
+ c2d.save();
290
+ c2d.translate(HEAD_CX, HEAD_CY);
291
+ c2d.scale(1 - Math.abs(yaw) * .24, 1 - Math.abs(pitch) * .12);
292
+ c2d.translate(-256, -256);
293
+ c2d.translate(featX, featY);
294
+ const feat = rgb(eased.feature);
295
+ let blinkL = clamp(frame.blink.left, 0, 1);
296
+ let blinkR = clamp(frame.blink.right, 0, 1);
297
+ if (state === "success") {
298
+ blinkL = 0;
299
+ blinkR = .85;
300
+ }
301
+ drawEye(c2d, HEAD_CX - EYE_DX, EYE_Y, blinkL, feat);
302
+ drawEye(c2d, 312, EYE_Y, blinkR, feat);
303
+ drawNose(c2d, feat);
304
+ let mouth = Math.max(REST_SMILE, clamp(frame.smile ?? 0, 0, 1));
305
+ if (state === "success") mouth = 1;
306
+ else if (state === "error") mouth = -.55;
307
+ drawMouth(c2d, mouth, feat);
308
+ c2d.restore();
309
+ c2d.globalAlpha = 1;
310
+ }
311
+ c2d.restore();
312
+ }
313
+ };
314
+ }
315
+ /**
316
+ * Main-thread wrapper: owns a DOM `<canvas>` and delegates to the shared
317
+ * drawing core. Public shape unchanged for existing consumers (`incode-2d`,
318
+ * `avatar-2d` main path).
319
+ */
320
+ var SatinSmileyRenderer = class {
321
+ constructor(size = 512) {
322
+ this.core = null;
323
+ this.pendingState = "detecting";
324
+ this.canvas = document.createElement("canvas");
325
+ this.canvas.width = size;
326
+ this.canvas.height = size;
327
+ }
328
+ getCanvas() {
329
+ return this.canvas;
330
+ }
331
+ /** Set the verdict state (detecting/success/error); colours ease toward it. */
332
+ setState(state) {
333
+ this.pendingState = state;
334
+ this.core?.setState(state);
335
+ }
336
+ init() {
337
+ this.core = createSatinSmileyCore(this.canvas);
338
+ this.core.setState(this.pendingState);
339
+ }
340
+ dispose() {
341
+ this.core?.dispose();
342
+ this.core = null;
343
+ }
344
+ render(frame) {
345
+ this.core?.render(frame);
346
+ }
347
+ };
348
+ //#endregion
349
+ //#region ../infra/src/avatar/2d-default-avatar/pose.ts
350
+ const AVATAR2D_POSE_CONFIG = {
351
+ yawGain: 2.2,
352
+ pitchUpGain: 3.4,
353
+ pitchDownGain: 2.6,
354
+ rollGain: 1,
355
+ rotMax: .9,
356
+ lateralGain: 1.6,
357
+ lateralMax: 1,
358
+ depthGain: 2,
359
+ depthMax: .8,
360
+ signYaw: 1,
361
+ signPitch: 1,
362
+ signRoll: 1,
363
+ signX: 1,
364
+ signY: 1
365
+ };
366
+ const AVATAR2D_DEADZONE = {
367
+ rot: .005,
368
+ roll: .006,
369
+ pos: .03,
370
+ depth: .1
371
+ };
372
+ /**
373
+ * Below this face-size ratio the detector emits sporadic single-frame outlier
374
+ * spikes ("the avatar jumps") that the deadzone (idle-only) and the EMA (delays,
375
+ * doesn't reject) both miss; run the {@link Median} first in that regime. At/above
376
+ * it, the face is near and exp smoothing alone is enough. (FACE_AVATAR.md → Pose pipeline.)
377
+ */
378
+ const MEDIAN_FACE_RATIO = .35;
379
+ /**
380
+ * Single-axis rolling-window median for outlier rejection. Returns the latest
381
+ * sample until the window fills (no start-up lag spike), then the middle of the
382
+ * sorted window. The buffer stays in insertion order so `shift()` evicts the
383
+ * OLDEST sample, not the smallest. Ported from the incode-personhood-widget
384
+ * `MedianFilter` — **copied, not shared** (POC isolation; renderer is the only
385
+ * shared surface). Use three independent instances (one per axis).
386
+ *
387
+ * SELF-CONTAINED (window size is a ctor arg, `slice()` not spread) — it is
388
+ * `toString()`-serialized into the avatar-2d worker.
389
+ */
390
+ var Median = class {
391
+ constructor(windowSize = 7) {
392
+ this.buf = [];
393
+ this.windowSize = windowSize;
394
+ }
395
+ reset() {
396
+ this.buf = [];
397
+ }
398
+ filter(x) {
399
+ this.buf.push(x);
400
+ if (this.buf.length > this.windowSize) this.buf.shift();
401
+ if (this.buf.length < this.windowSize) return x;
402
+ const sorted = this.buf.slice().sort((a, b) => a - b);
403
+ return sorted[Math.floor(sorted.length / 2)];
404
+ }
405
+ };
406
+ /**
407
+ * Caps on the auto-calibrated neutral so calibration cancels small device/framing
408
+ * bias but NOT the user's real starting orientation. Yaw/roll only (straight ≈ 0
409
+ * for both); pitch + position are left unbounded (pitch has a person-specific
410
+ * baseline; position is genuine framing) — bounding those risks an "always looks
411
+ * down/off-centre" artifact. Tune on device.
412
+ */
413
+ const AVATAR2D_NEUTRAL_BIAS = {
414
+ yaw: .06,
415
+ roll: .05
416
+ };
417
+ /**
418
+ * Extract the compact payload from a FaceLandmarker result. Returns null when
419
+ * no usable face. **SELF-CONTAINED** — no module refs (the mesh indices are
420
+ * inlined: nose tip 4, left eye outer 33 / inner 133, right eye outer 263 /
421
+ * inner 362, forehead 10, chin 152 — see the LM_* docs above) — because it is
422
+ * `toString()`-serialized into the avatar-2d worker; it is also the first half
423
+ * of the main-thread {@link computeRawPose}. Keep it free of spread/helpers.
424
+ */
425
+ function extractCompactFace(result) {
426
+ const lm = result.faceLandmarks && result.faceLandmarks[0];
427
+ if (!lm) return null;
428
+ const nose = lm[4];
429
+ const eyeLo = lm[33];
430
+ const eyeLi = lm[133];
431
+ const eyeRo = lm[263];
432
+ const eyeRi = lm[362];
433
+ const forehead = lm[10];
434
+ const chin = lm[152];
435
+ if (!nose || !eyeLo || !eyeLi || !eyeRo || !eyeRi || !forehead || !chin) return null;
436
+ let minX = Infinity;
437
+ let minY = Infinity;
438
+ let maxX = -Infinity;
439
+ let maxY = -Infinity;
440
+ for (let i = 0; i < lm.length; i += 1) {
441
+ const p = lm[i];
442
+ if (p.x < minX) minX = p.x;
443
+ if (p.x > maxX) maxX = p.x;
444
+ if (p.y < minY) minY = p.y;
445
+ if (p.y > maxY) maxY = p.y;
446
+ }
447
+ let blinkL = 0;
448
+ let blinkR = 0;
449
+ let jawOpen = 0;
450
+ let smileL = 0;
451
+ let smileR = 0;
452
+ const shapes = result.faceBlendshapes && result.faceBlendshapes[0];
453
+ const categories = shapes && shapes.categories || [];
454
+ for (const c of categories) if (c.categoryName === "eyeBlinkLeft") blinkL = c.score;
455
+ else if (c.categoryName === "eyeBlinkRight") blinkR = c.score;
456
+ else if (c.categoryName === "jawOpen") jawOpen = c.score;
457
+ else if (c.categoryName === "mouthSmileLeft") smileL = c.score;
458
+ else if (c.categoryName === "mouthSmileRight") smileR = c.score;
459
+ return {
460
+ nx: nose.x,
461
+ ny: nose.y,
462
+ lox: eyeLo.x,
463
+ loy: eyeLo.y,
464
+ lix: eyeLi.x,
465
+ liy: eyeLi.y,
466
+ rox: eyeRo.x,
467
+ roy: eyeRo.y,
468
+ rix: eyeRi.x,
469
+ riy: eyeRi.y,
470
+ foreheadY: forehead.y,
471
+ chinY: chin.y,
472
+ bboxW: maxX - minX,
473
+ bboxH: maxY - minY,
474
+ blinkL,
475
+ blinkR,
476
+ jawOpen,
477
+ smile: (smileL + smileR) / 2
478
+ };
479
+ }
480
+ /**
481
+ * Raw pose from a compact face, in **pixel space** (multiply normalized coords
482
+ * by the DETECT input width/height — worker and main must use the same dims as
483
+ * calibration) so distances/angles aren't skewed on non-square frames.
484
+ * Returns null on a non-finite frame (NaN guard).
485
+ */
486
+ function rawPoseFromCompact(c, width, height) {
487
+ const nx = c.nx * width;
488
+ const ny = c.ny * height;
489
+ const lx = (c.lox + c.lix) / 2 * width;
490
+ const ly = (c.loy + c.liy) / 2 * height;
491
+ const rx = (c.rox + c.rix) / 2 * width;
492
+ const ry = (c.roy + c.riy) / 2 * height;
493
+ const fy = c.foreheadY * height;
494
+ const cy = c.chinY * height;
495
+ const eyeMidX = (lx + rx) / 2;
496
+ const eyeMidY = (ly + ry) / 2;
497
+ const faceMidY = (fy + cy) / 2;
498
+ const eyeDist = Math.hypot(rx - lx, ry - ly) || 1e-4;
499
+ const faceH = Math.abs(cy - fy) || 1e-4;
500
+ const yaw = (nx - eyeMidX) / eyeDist;
501
+ const pitch = (ny - faceMidY) / faceH;
502
+ const roll = Math.atan2(ry - ly, rx - lx);
503
+ if (!Number.isFinite(yaw) || !Number.isFinite(pitch) || !Number.isFinite(roll) || !Number.isFinite(eyeMidX) || !Number.isFinite(eyeDist)) return null;
504
+ let faceSizeRatio;
505
+ if (width > 0 && height > 0) {
506
+ const bw = c.bboxW * width;
507
+ const bh = c.bboxH * height;
508
+ if (bw > 0 && bh > 0) faceSizeRatio = Math.sqrt(bw * bh) / Math.min(width, height);
509
+ }
510
+ return {
511
+ yaw,
512
+ pitch,
513
+ roll,
514
+ eyeMidX,
515
+ eyeMidY,
516
+ eyeDist,
517
+ faceH,
518
+ faceSizeRatio
519
+ };
520
+ }
521
+ /**
522
+ * Map a raw pose (relative to neutral) into head euler + offset + depth.
523
+ * SELF-CONTAINED (deadzones arrive as a param; clamp/deadzone inlined) — it is
524
+ * `toString()`-serialized into the avatar-2d worker.
525
+ */
526
+ function mapToPose(raw, neutral, cfg, dz) {
527
+ const deadzone = (v, d) => Math.abs(v) <= d ? 0 : v - Math.sign(v) * d;
528
+ const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
529
+ let dRoll = raw.roll - neutral.roll;
530
+ dRoll = Math.atan2(Math.sin(dRoll), Math.cos(dRoll));
531
+ const dist = neutral.dist || 1e-4;
532
+ const dPitch = deadzone(raw.pitch - neutral.pitch, dz.rot);
533
+ const pitchGain = dPitch < 0 ? cfg.pitchUpGain : cfg.pitchDownGain;
534
+ const dYaw = deadzone(raw.yaw - neutral.yaw, dz.rot);
535
+ const dRollDz = deadzone(dRoll, dz.roll);
536
+ const relX = deadzone((raw.eyeMidX - neutral.cx) / dist, dz.pos);
537
+ const relY = deadzone((raw.eyeMidY - neutral.cy) / dist, dz.pos);
538
+ const faceHN = neutral.faceH || 1e-4;
539
+ const relZ = deadzone((raw.faceH - neutral.faceH) / faceHN, dz.depth);
540
+ return {
541
+ headEuler: {
542
+ x: clamp(dPitch * pitchGain * cfg.signPitch, -cfg.rotMax, cfg.rotMax),
543
+ y: clamp(dYaw * cfg.yawGain * cfg.signYaw, -cfg.rotMax, cfg.rotMax),
544
+ z: clamp(dRollDz * cfg.rollGain * cfg.signRoll, -cfg.rotMax, cfg.rotMax)
545
+ },
546
+ rootOffset: {
547
+ x: clamp(relX * cfg.lateralGain * cfg.signX, -cfg.lateralMax, cfg.lateralMax),
548
+ y: clamp(relY * cfg.lateralGain * cfg.signY, -cfg.lateralMax, cfg.lateralMax)
549
+ },
550
+ depth: clamp(relZ * cfg.depthGain, -cfg.depthMax, cfg.depthMax)
551
+ };
552
+ }
553
+ //#endregion
554
+ //#region ../infra/src/avatar/2d-default-avatar/avatar2dCore.ts
555
+ /**
556
+ * Avatar-2d shared cores (ENG-49806 render-in-worker refactor).
557
+ *
558
+ * The lens's `privacyLensGlCore.ts` pattern applied to the 2D avatar: the
559
+ * pieces of the pipeline that must run in BOTH transports (main thread and the
560
+ * worker) live here as **self-contained, `toString()`-serializable factories**
561
+ * with a single source of truth:
562
+ *
563
+ * - {@link createAvatar2DPoseCore} — compact-face ingestion → median outlier
564
+ * rejection → averaged-neutral calibration (velocity-gated, time-boxed) →
565
+ * face-lost gate → dt-corrected EMA smoothing → the pose to render.
566
+ *
567
+ * Serialization rules (same as the lens): factory bodies must not reference
568
+ * ANY module-level binding — tuning constants arrive via the JSON-injectable
569
+ * {@link AVATAR2D_POSE_CORE_DEFAULTS} config, and cross-function calls go
570
+ * through the `deps` object (minifier-safe). Types are fine (they vanish).
571
+ */
572
+ /**
573
+ * The pose-pipeline tuning, single home (both transports; the worker builder
574
+ * JSON-injects it). `dtSeedMs` is derived from the effective maxFps at start.
575
+ */
576
+ const AVATAR2D_POSE_CORE_DEFAULTS = {
577
+ pose: AVATAR2D_POSE_CONFIG,
578
+ deadzone: AVATAR2D_DEADZONE,
579
+ neutralBias: AVATAR2D_NEUTRAL_BIAS,
580
+ medianWindow: 7,
581
+ medianFaceRatio: MEDIAN_FACE_RATIO,
582
+ medianMaxGapMs: 120,
583
+ neutralFrames: 20,
584
+ calMotionYawPitch: .012,
585
+ calMotionRoll: .02,
586
+ calFallbackMult: 3,
587
+ calMinFrames: 1,
588
+ calMaxMs: 300,
589
+ faceLostMs: 600,
590
+ faceLostMinMisses: 2,
591
+ faceLostHardMs: 3e3,
592
+ headAlpha: .4,
593
+ posAlpha: .35,
594
+ depthAlpha: .2,
595
+ exprAlpha: .5,
596
+ refFrameMs: 1e3 / 30,
597
+ maxEmaDtMs: 100,
598
+ dtSeedMs: 1e3 / 30
599
+ };
600
+ /** Main-thread deps instance (the worker builder assembles its own). */
601
+ function createAvatar2DPoseCoreDeps() {
602
+ return {
603
+ rawPoseFromCompact,
604
+ mapToPose,
605
+ createMedian: (windowSize) => new Median(windowSize)
606
+ };
607
+ }
608
+ /**
609
+ * The pose pipeline, transport-agnostic. SELF-CONTAINED (serialized via
610
+ * toString into the worker blob): everything arrives via `cfg` / `deps`.
611
+ */
612
+ function createAvatar2DPoseCore(cfg, deps) {
613
+ const neutralPose = () => ({
614
+ tracked: false,
615
+ headEuler: {
616
+ x: 0,
617
+ y: 0,
618
+ z: 0
619
+ },
620
+ rootOffset: {
621
+ x: 0,
622
+ y: 0
623
+ },
624
+ depth: 0,
625
+ blink: {
626
+ left: 0,
627
+ right: 0
628
+ },
629
+ mouthOpen: 0,
630
+ smile: 0
631
+ });
632
+ const copyPoseInto = (dst, src) => {
633
+ dst.tracked = src.tracked;
634
+ dst.headEuler.x = src.headEuler.x;
635
+ dst.headEuler.y = src.headEuler.y;
636
+ dst.headEuler.z = src.headEuler.z;
637
+ dst.rootOffset.x = src.rootOffset.x;
638
+ dst.rootOffset.y = src.rootOffset.y;
639
+ dst.depth = src.depth;
640
+ dst.blink.left = src.blink.left;
641
+ dst.blink.right = src.blink.right;
642
+ dst.mouthOpen = src.mouthOpen;
643
+ dst.smile = src.smile;
644
+ };
645
+ const clampValue = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
646
+ const dtAlpha = (refAlpha, dtMs) => {
647
+ if (refAlpha <= 0) return 0;
648
+ if (refAlpha >= 1) return 1;
649
+ const tau = -cfg.refFrameMs / Math.log(1 - refAlpha);
650
+ return 1 - Math.exp(-dtMs / tau);
651
+ };
652
+ const current = neutralPose();
653
+ let target = neutralPose();
654
+ let lastFaceAt = 0;
655
+ let missedDetects = 0;
656
+ let lastTickAt = 0;
657
+ let calibrated = false;
658
+ let nFrames = 0;
659
+ let calAttempts = 0;
660
+ let calStartAt = 0;
661
+ let prevCalYaw = NaN;
662
+ let prevCalPitch = NaN;
663
+ let prevCalRoll = NaN;
664
+ let seeded = false;
665
+ const sum = {
666
+ yaw: 0,
667
+ pitch: 0,
668
+ roll: 0,
669
+ cx: 0,
670
+ cy: 0,
671
+ dist: 0,
672
+ faceH: 0
673
+ };
674
+ let neutral = {
675
+ yaw: 0,
676
+ pitch: 0,
677
+ roll: 0,
678
+ cx: 0,
679
+ cy: 0,
680
+ dist: 1,
681
+ faceH: 1
682
+ };
683
+ const medYaw = deps.createMedian(cfg.medianWindow);
684
+ const medPitch = deps.createMedian(cfg.medianWindow);
685
+ const medRoll = deps.createMedian(cfg.medianWindow);
686
+ return {
687
+ ingest(face, width, height, now) {
688
+ let landed = false;
689
+ const raw0 = face ? deps.rawPoseFromCompact(face, width, height) : null;
690
+ if (face && raw0) {
691
+ landed = true;
692
+ const small = !(now - lastFaceAt > cfg.medianMaxGapMs) && raw0.faceSizeRatio !== void 0 && raw0.faceSizeRatio < cfg.medianFaceRatio;
693
+ let raw = raw0;
694
+ if (small) raw = {
695
+ yaw: medYaw.filter(raw0.yaw),
696
+ pitch: medPitch.filter(raw0.pitch),
697
+ roll: medRoll.filter(raw0.roll),
698
+ eyeMidX: raw0.eyeMidX,
699
+ eyeMidY: raw0.eyeMidY,
700
+ eyeDist: raw0.eyeDist,
701
+ faceH: raw0.faceH,
702
+ faceSizeRatio: raw0.faceSizeRatio
703
+ };
704
+ else {
705
+ medYaw.reset();
706
+ medPitch.reset();
707
+ medRoll.reset();
708
+ }
709
+ lastFaceAt = now;
710
+ if (!calibrated) {
711
+ calAttempts += 1;
712
+ if (calStartAt === 0) calStartAt = now;
713
+ const dRollMotion = Math.atan2(Math.sin(raw.roll - prevCalRoll), Math.cos(raw.roll - prevCalRoll));
714
+ const moved = Number.isFinite(prevCalYaw) && (Math.abs(raw.yaw - prevCalYaw) > cfg.calMotionYawPitch || Math.abs(raw.pitch - prevCalPitch) > cfg.calMotionYawPitch || Math.abs(dRollMotion) > cfg.calMotionRoll);
715
+ prevCalYaw = raw.yaw;
716
+ prevCalPitch = raw.pitch;
717
+ prevCalRoll = raw.roll;
718
+ const fallback = calAttempts >= cfg.neutralFrames * cfg.calFallbackMult || now - calStartAt > cfg.calMaxMs;
719
+ if (!moved || fallback) {
720
+ nFrames += 1;
721
+ sum.yaw += raw.yaw;
722
+ sum.pitch += raw.pitch;
723
+ sum.roll += raw.roll;
724
+ sum.cx += raw.eyeMidX;
725
+ sum.cy += raw.eyeMidY;
726
+ sum.dist += raw.eyeDist;
727
+ sum.faceH += raw.faceH;
728
+ }
729
+ const timeBoxed = nFrames >= cfg.calMinFrames && now - calStartAt > cfg.calMaxMs;
730
+ if (nFrames >= cfg.neutralFrames || timeBoxed) {
731
+ const n = nFrames;
732
+ neutral = {
733
+ yaw: clampValue(sum.yaw / n, -cfg.neutralBias.yaw, cfg.neutralBias.yaw),
734
+ pitch: sum.pitch / n,
735
+ roll: clampValue(sum.roll / n, -cfg.neutralBias.roll, cfg.neutralBias.roll),
736
+ cx: sum.cx / n,
737
+ cy: sum.cy / n,
738
+ dist: sum.dist / n || 1,
739
+ faceH: sum.faceH / n || 1
740
+ };
741
+ calibrated = true;
742
+ }
743
+ }
744
+ if (calibrated) {
745
+ const mapped = deps.mapToPose(raw, neutral, cfg.pose, cfg.deadzone);
746
+ target = {
747
+ tracked: true,
748
+ headEuler: {
749
+ x: mapped.headEuler.x,
750
+ y: mapped.headEuler.y,
751
+ z: mapped.headEuler.z
752
+ },
753
+ rootOffset: {
754
+ x: mapped.rootOffset.x,
755
+ y: mapped.rootOffset.y
756
+ },
757
+ depth: mapped.depth,
758
+ blink: {
759
+ left: face.blinkL,
760
+ right: face.blinkR
761
+ },
762
+ mouthOpen: face.jawOpen,
763
+ smile: face.smile
764
+ };
765
+ if (!seeded) {
766
+ copyPoseInto(current, target);
767
+ seeded = true;
768
+ }
769
+ }
770
+ }
771
+ missedDetects = landed ? 0 : missedDetects + 1;
772
+ },
773
+ tick(now) {
774
+ const dtMs = clampValue(lastTickAt > 0 ? now - lastTickAt : cfg.dtSeedMs, 1, cfg.maxEmaDtMs);
775
+ lastTickAt = now;
776
+ if (now - lastFaceAt > cfg.faceLostMs && missedDetects >= cfg.faceLostMinMisses || now - lastFaceAt > cfg.faceLostHardMs) target = neutralPose();
777
+ const ha = dtAlpha(cfg.headAlpha, dtMs);
778
+ const pa = dtAlpha(cfg.posAlpha, dtMs);
779
+ const da = dtAlpha(cfg.depthAlpha, dtMs);
780
+ const ea = dtAlpha(cfg.exprAlpha, dtMs);
781
+ const c = current;
782
+ const t = target;
783
+ c.tracked = t.tracked;
784
+ c.headEuler.x += (t.headEuler.x - c.headEuler.x) * ha;
785
+ c.headEuler.y += (t.headEuler.y - c.headEuler.y) * ha;
786
+ c.headEuler.z += (t.headEuler.z - c.headEuler.z) * ha;
787
+ c.rootOffset.x += (t.rootOffset.x - c.rootOffset.x) * pa;
788
+ c.rootOffset.y += (t.rootOffset.y - c.rootOffset.y) * pa;
789
+ c.depth += (t.depth - c.depth) * da;
790
+ c.blink.left += (t.blink.left - c.blink.left) * ea;
791
+ c.blink.right += (t.blink.right - c.blink.right) * ea;
792
+ c.mouthOpen += (t.mouthOpen - c.mouthOpen) * ea;
793
+ c.smile += (t.smile - c.smile) * ea;
794
+ return current;
795
+ }
796
+ };
797
+ }
798
+ //#endregion
799
+ //#region ../infra/src/avatar/2d-default-avatar/avatar2dWorker.ts
800
+ /**
801
+ * Worker mode for the 2D avatar (ENG-49806) — TWO workers, full pipeline
802
+ * off-main.
803
+ *
804
+ * Under a saturated main thread (the synchronous WASM capture pipeline runs
805
+ * back-to-back on throttled/low-tier devices) ANY main-thread loop is starved
806
+ * to single-digit fps no matter how cheap its frame is. And on low-tier
807
+ * silicon a SINGLE worker is not enough either: one MediaPipe inference costs
808
+ * ~200-250ms on a Cortex-A53 under capture contention, blocking that worker's
809
+ * own render loop to ~8fps (measured on a Galaxy A04e; adaptive cadence alone
810
+ * capped inference duty at 50% but every inference still froze the ball
811
+ * mid-drift). So the pipeline is SPLIT:
812
+ *
813
+ * - RENDER worker — pose core + SatinSmiley on the transferred
814
+ * `OffscreenCanvas`, worker-rAF loop + tolerance pacer. Its frame costs
815
+ * ~0.3ms and NOTHING in it ever blocks → ~25-30fps even on the A04e.
816
+ * - TRACK worker — camera track (cloned) → `MediaStreamTrackProcessor` →
817
+ * `VideoFrame` downscale → FaceLandmarker, at an adaptive cadence (EMA'd
818
+ * cost × 2 — never more than ~50% of its own thread). Each detect posts a
819
+ * tiny compact-face message over a `MessageChannel` DIRECTLY to the render
820
+ * worker (never through the contended main thread).
821
+ *
822
+ * The main thread only bridges dev flags and verdict-state cues, and
823
+ * re-publishes the render worker's stats snapshots.
824
+ *
825
+ * Boot keeps the instant-mount contract (sub-second halo): the render
826
+ * worker's `'started'` handshake covers only its core init (ms). The track
827
+ * worker's MediaPipe bring-up (module + ~3.7MB model + WASM compile) runs in
828
+ * the background — or, better, ALREADY RAN during the tutorial via the warm
829
+ * registry (`avatar2dWarm.ts` warms a track worker; the provider adopts it).
830
+ * Tracking failure leaves the avatar in the searching state ('trackingFatal'
831
+ * logged) — the face stays concealed either way.
832
+ *
833
+ * Support: Chromium 94+ (Chrome/Edge/Android WebView/Samsung Internet) — the
834
+ * low-tier Android target segment. Safari/Firefox and strict-CSP hosts fall
835
+ * back to the main-thread path automatically (`Face2DProvider`).
836
+ *
837
+ * Packaging: like the lens, both worker scripts are assembled AT RUNTIME from
838
+ * `Function.prototype.toString()` of the self-contained factories and loaded
839
+ * via Blob URLs — no separate worker chunks, bundler-agnostic. They are
840
+ * CLASSIC workers (NOT `{ type: 'module' }`): MediaPipe's wasm glue loads
841
+ * itself via `importScripts()`, which module workers lack — booting
842
+ * tasks-vision in a module worker dies with "ModuleFactory not set". The
843
+ * tasks-vision ESM is instead dynamic-imported via a Function-constructed
844
+ * `import()` (see `avatar2dTrackWorkerMain`) — supported in Chromium classic
845
+ * dedicated workers, the only environment these workers run in (probe-gated).
846
+ * No `window.Module` shield is needed in-worker — ml-wasm-kit never runs
847
+ * there.
848
+ */
849
+ /**
850
+ * Whether the worker path is available in this environment. Anything missing
851
+ * (Safari's worker-only MSTP shape, Firefox, old WebView) routes to the
852
+ * main-thread fallback.
853
+ */
854
+ function canUseAvatar2DWorker() {
855
+ const g = globalThis;
856
+ if (typeof g.MediaStreamTrackProcessor !== "function" || typeof g.Worker !== "function" || typeof g.MessageChannel !== "function" || typeof g.HTMLCanvasElement !== "function") return false;
857
+ return "transferControlToOffscreen" in g.HTMLCanvasElement.prototype;
858
+ }
859
+ /**
860
+ * RENDER worker logic. SELF-CONTAINED (serialized via toString into the
861
+ * blob): everything arrives via `deps` / messages; no module refs. The loop
862
+ * is worker-rAF when available (Chromium exposes it in dedicated workers),
863
+ * else setTimeout ~60Hz; the tolerance-based pacer enforces maxFps. Pose
864
+ * updates arrive on the channel port and are ingested on receipt — nothing
865
+ * in this worker ever blocks longer than a canvas-2D draw (~0.3ms).
866
+ */
867
+ function avatar2dRenderWorkerMain(scope, deps) {
868
+ let stopped = false;
869
+ let poseCore = null;
870
+ let smiley = null;
871
+ let pacer = null;
872
+ let port = null;
873
+ let statsEnabled = false;
874
+ let rafId = null;
875
+ let timerId = null;
876
+ const PUBLISH_MS = 500;
877
+ const GAP_WINDOW = 128;
878
+ let renderedTotal = 0;
879
+ let dropped = 0;
880
+ let winStart = NaN;
881
+ let winFrames = 0;
882
+ let drawSum = 0;
883
+ let detectSum = 0;
884
+ let detectCount = 0;
885
+ const gaps = [];
886
+ let lastFrameAt = NaN;
887
+ let trackingStatus = "loading";
888
+ let detectsRun = 0;
889
+ let facesFound = 0;
890
+ let lastDims = "";
891
+ let debugIntervalMs = 0;
892
+ const publishStats = (nowMs) => {
893
+ const elapsed = nowMs - winStart;
894
+ if (!(elapsed > 0)) return;
895
+ const fps = Math.round(winFrames / elapsed * 1e3 * 10) / 10;
896
+ const snapshot = {
897
+ variant: "avatar-2d",
898
+ mode: "worker",
899
+ avatarFps: fps,
900
+ renderedFps: fps,
901
+ renderedTotal,
902
+ droppedByThrottle: dropped,
903
+ tsMs: nowMs
904
+ };
905
+ if (winFrames > 0) snapshot.drawMsAvg = Math.round(drawSum / winFrames * 100) / 100;
906
+ if (detectCount > 0) snapshot.uploadMsAvg = Math.round(detectSum / detectCount * 100) / 100;
907
+ if (gaps.length > 0) {
908
+ const sorted = gaps.slice().sort((a, b) => a - b);
909
+ const idx = Math.min(sorted.length - 1, Math.floor(sorted.length * .95));
910
+ snapshot.frameGapP95Ms = Math.round(sorted[idx] * 10) / 10;
911
+ }
912
+ snapshot.debug = "landmarker=" + trackingStatus + " dims=" + (lastDims || "?") + " faces=" + facesFound + "/" + detectsRun + " detInt=" + Math.round(debugIntervalMs) + "ms";
913
+ scope.postMessage({
914
+ type: "stats",
915
+ snapshot
916
+ });
917
+ winStart = nowMs;
918
+ winFrames = 0;
919
+ drawSum = 0;
920
+ detectSum = 0;
921
+ detectCount = 0;
922
+ };
923
+ const renderTick = () => {
924
+ if (stopped || !poseCore || !smiley || !pacer) return;
925
+ if (typeof requestAnimationFrame === "function") rafId = requestAnimationFrame(renderTick);
926
+ else timerId = setTimeout(renderTick, 16);
927
+ const now = performance.now();
928
+ if (!pacer.shouldRender(now)) {
929
+ if (statsEnabled) dropped += 1;
930
+ return;
931
+ }
932
+ const frameStart = statsEnabled ? performance.now() : 0;
933
+ smiley.render(poseCore.tick(now));
934
+ if (statsEnabled) {
935
+ renderedTotal += 1;
936
+ if (Number.isNaN(winStart)) winStart = now;
937
+ else {
938
+ winFrames += 1;
939
+ drawSum += performance.now() - frameStart;
940
+ }
941
+ if (!Number.isNaN(lastFrameAt)) {
942
+ gaps.push(now - lastFrameAt);
943
+ if (gaps.length > GAP_WINDOW) gaps.shift();
944
+ }
945
+ lastFrameAt = now;
946
+ if (now - winStart >= PUBLISH_MS) publishStats(now);
947
+ }
948
+ };
949
+ const onPortMessage = (event) => {
950
+ const msg = event.data;
951
+ if (msg.kind === "face") {
952
+ if (poseCore) poseCore.ingest(msg.face, msg.width, msg.height, performance.now());
953
+ detectsRun += 1;
954
+ if (msg.face) facesFound += 1;
955
+ lastDims = msg.width + "x" + msg.height;
956
+ debugIntervalMs = msg.detIntervalMs;
957
+ if (statsEnabled) {
958
+ detectSum += msg.detectMs;
959
+ detectCount += 1;
960
+ }
961
+ } else if (msg.kind === "tracking") trackingStatus = msg.status === "up" ? "up" : "FAILED";
962
+ };
963
+ scope.onmessage = (event) => {
964
+ const msg = event.data;
965
+ if (msg.type === "start") {
966
+ try {
967
+ smiley = deps.createSmileyCore(msg.canvas);
968
+ poseCore = deps.createPoseCore(msg.poseConfig);
969
+ pacer = deps.createPacer(msg.maxFps, 8);
970
+ port = msg.port;
971
+ port.onmessage = onPortMessage;
972
+ } catch (error) {
973
+ scope.postMessage({
974
+ type: "fatal",
975
+ message: String(error)
976
+ });
977
+ return;
978
+ }
979
+ statsEnabled = msg.statsEnabled;
980
+ scope.postMessage({ type: "started" });
981
+ renderTick();
982
+ } else if (msg.type === "state") smiley?.setState(msg.state);
983
+ else if (msg.type === "override") smiley?.setOverrideState(msg.state);
984
+ else if (msg.type === "statsEnabled") {
985
+ if (msg.value && !statsEnabled) {
986
+ winStart = NaN;
987
+ lastFrameAt = NaN;
988
+ }
989
+ statsEnabled = msg.value;
990
+ } else if (msg.type === "stop") {
991
+ stopped = true;
992
+ if (rafId != null && typeof cancelAnimationFrame === "function") cancelAnimationFrame(rafId);
993
+ if (timerId != null) clearTimeout(timerId);
994
+ try {
995
+ port?.close();
996
+ } catch {}
997
+ port = null;
998
+ smiley?.dispose();
999
+ smiley = null;
1000
+ scope.postMessage({ type: "stopped" });
1001
+ }
1002
+ };
1003
+ }
1004
+ /**
1005
+ * TRACK worker logic. SELF-CONTAINED (serialized via toString into the
1006
+ * blob). Detect pump: sequential read → adaptive cadence gate → downscale →
1007
+ * detect → post compact face to the render worker's port → close. MSTP
1008
+ * buffers at most one frame internally, so reads always yield the freshest
1009
+ * frame, and closing every frame promptly keeps the camera's frame pool
1010
+ * healthy — an unclosed VideoFrame can stall the CAPTURE pipeline, which the
1011
+ * avatar must never do (cosmetic-only invariant).
1012
+ */
1013
+ function avatar2dTrackWorkerMain(scope, deps) {
1014
+ let stopped = false;
1015
+ let reader = null;
1016
+ let landmarker = null;
1017
+ let port = null;
1018
+ let inputCanvas = null;
1019
+ let inputCtx = null;
1020
+ let landmarkerPromise = null;
1021
+ let lastPaths = null;
1022
+ const initLandmarker = (paths) => (async () => {
1023
+ lastPaths = {
1024
+ mediapipeModulePath: paths.mediapipeModulePath,
1025
+ mediapipeWasmPath: paths.mediapipeWasmPath,
1026
+ faceLandmarkerModelPath: paths.faceLandmarkerModelPath
1027
+ };
1028
+ try {
1029
+ const modelBytesPromise = fetch(paths.faceLandmarkerModelPath).then((res) => {
1030
+ if (!res.ok) throw new Error(`model fetch HTTP ${res.status}`);
1031
+ return res.arrayBuffer();
1032
+ }).then((buf) => new Uint8Array(buf)).catch(() => null);
1033
+ const tasksVision = await new Function("u", "return import(u)")(paths.mediapipeModulePath);
1034
+ const fileset = await tasksVision.FilesetResolver.forVisionTasks(paths.mediapipeWasmPath);
1035
+ const modelBytes = await modelBytesPromise;
1036
+ landmarker = await tasksVision.FaceLandmarker.createFromOptions(fileset, {
1037
+ baseOptions: {
1038
+ ...modelBytes ? { modelAssetBuffer: modelBytes } : { modelAssetPath: paths.faceLandmarkerModelPath },
1039
+ delegate: "CPU"
1040
+ },
1041
+ runningMode: "VIDEO",
1042
+ numFaces: 1,
1043
+ outputFaceBlendshapes: true,
1044
+ outputFacialTransformationMatrixes: false
1045
+ });
1046
+ } catch (error) {
1047
+ scope.postMessage({
1048
+ type: "trackingFatal",
1049
+ message: String(error)
1050
+ });
1051
+ return false;
1052
+ }
1053
+ if (stopped) {
1054
+ try {
1055
+ landmarker.close();
1056
+ } catch {}
1057
+ landmarker = null;
1058
+ return false;
1059
+ }
1060
+ try {
1061
+ const warmupCanvas = new OffscreenCanvas(320, 240);
1062
+ const warmupCtx = warmupCanvas.getContext("2d");
1063
+ if (warmupCtx) {
1064
+ warmupCtx.fillRect(0, 0, 320, 240);
1065
+ landmarker.detectForVideo(warmupCanvas, performance.now());
1066
+ }
1067
+ } catch {}
1068
+ return true;
1069
+ })();
1070
+ const detectPump = async (cfg) => {
1071
+ let lastDetectAt = -Infinity;
1072
+ let detectCostEma = 0;
1073
+ let minIntervalMs = cfg.detectMinIntervalMs;
1074
+ const SEARCH_MISSES = 3;
1075
+ const SEARCH_MIN_INTERVAL_MS = 330;
1076
+ const SEARCH_DUTY_FACTOR = 4;
1077
+ let noFaceStreak = 0;
1078
+ const MAX_DETECT_THROWS = 30;
1079
+ let detectThrows = 0;
1080
+ while (!stopped && reader && landmarker && port) {
1081
+ let result;
1082
+ try {
1083
+ result = await reader.read();
1084
+ } catch {
1085
+ break;
1086
+ }
1087
+ if (result.done) break;
1088
+ const frame = result.value;
1089
+ try {
1090
+ const now = performance.now();
1091
+ if (now - lastDetectAt < minIntervalMs - cfg.detectIntervalToleranceMs) continue;
1092
+ const fw = frame.displayWidth;
1093
+ const fh = frame.displayHeight;
1094
+ if (!(fw > 0 && fh > 0)) continue;
1095
+ lastDetectAt = now;
1096
+ const scale = Math.min(1, cfg.detectMaxEdge / Math.max(fw, fh));
1097
+ const dw = Math.max(1, Math.round(fw * scale));
1098
+ const dh = Math.max(1, Math.round(fh * scale));
1099
+ if (!inputCanvas || inputCanvas.width !== dw || inputCanvas.height !== dh) {
1100
+ inputCanvas = new OffscreenCanvas(dw, dh);
1101
+ inputCtx = inputCanvas.getContext("2d");
1102
+ }
1103
+ if (!inputCtx) continue;
1104
+ inputCtx.drawImage(frame, 0, 0, dw, dh);
1105
+ let detected = null;
1106
+ try {
1107
+ detected = landmarker.detectForVideo(inputCanvas, now);
1108
+ detectThrows = 0;
1109
+ } catch {
1110
+ detected = null;
1111
+ detectThrows += 1;
1112
+ }
1113
+ const face = detected ? deps.extractCompact(detected) : null;
1114
+ const detectCost = performance.now() - now;
1115
+ const reacquired = face !== null && noFaceStreak >= SEARCH_MISSES;
1116
+ noFaceStreak = face ? 0 : noFaceStreak + 1;
1117
+ detectCostEma = detectCostEma === 0 || reacquired ? detectCost : detectCostEma + (detectCost - detectCostEma) * .3;
1118
+ minIntervalMs = noFaceStreak >= SEARCH_MISSES ? Math.max(SEARCH_MIN_INTERVAL_MS, detectCostEma * SEARCH_DUTY_FACTOR) : Math.max(cfg.detectMinIntervalMs, detectCostEma * 1.5);
1119
+ port.postMessage({
1120
+ kind: "face",
1121
+ face,
1122
+ width: dw,
1123
+ height: dh,
1124
+ detectMs: detectCost,
1125
+ detIntervalMs: minIntervalMs
1126
+ });
1127
+ } catch {} finally {
1128
+ frame.close();
1129
+ }
1130
+ if (detectThrows >= MAX_DETECT_THROWS && !stopped && lastPaths) {
1131
+ detectThrows = 0;
1132
+ try {
1133
+ landmarker?.close();
1134
+ } catch {}
1135
+ landmarker = null;
1136
+ landmarkerPromise = initLandmarker(lastPaths);
1137
+ if (!await landmarkerPromise) break;
1138
+ }
1139
+ }
1140
+ };
1141
+ scope.onmessage = (event) => {
1142
+ const msg = event.data;
1143
+ if (msg.type === "warm") {
1144
+ if (!landmarkerPromise) {
1145
+ landmarkerPromise = initLandmarker(msg);
1146
+ landmarkerPromise.then((ok) => {
1147
+ if (ok) scope.postMessage({ type: "warmed" });
1148
+ });
1149
+ }
1150
+ } else if (msg.type === "start") {
1151
+ port = msg.port;
1152
+ (async () => {
1153
+ let ok = landmarkerPromise ? await landmarkerPromise : false;
1154
+ if (!ok && !stopped) {
1155
+ landmarkerPromise = initLandmarker(msg);
1156
+ ok = await landmarkerPromise;
1157
+ }
1158
+ if (!ok || stopped || !landmarker || !port) {
1159
+ try {
1160
+ port?.postMessage({
1161
+ kind: "tracking",
1162
+ status: "failed"
1163
+ });
1164
+ } catch {}
1165
+ return;
1166
+ }
1167
+ port.postMessage({
1168
+ kind: "tracking",
1169
+ status: "up"
1170
+ });
1171
+ reader = msg.readable.getReader();
1172
+ detectPump({
1173
+ detectMaxEdge: msg.detectMaxEdge,
1174
+ detectMinIntervalMs: msg.detectMinIntervalMs,
1175
+ detectIntervalToleranceMs: msg.detectIntervalToleranceMs
1176
+ });
1177
+ })();
1178
+ } else if (msg.type === "stop") {
1179
+ stopped = true;
1180
+ try {
1181
+ reader?.cancel();
1182
+ } catch {}
1183
+ try {
1184
+ landmarker?.close();
1185
+ } catch {}
1186
+ landmarker = null;
1187
+ try {
1188
+ port?.close();
1189
+ } catch {}
1190
+ port = null;
1191
+ scope.postMessage({ type: "stopped" });
1192
+ }
1193
+ };
1194
+ }
1195
+ /**
1196
+ * Assemble the RENDER worker script (pose core + smiley core + pacer + main).
1197
+ * Everything referenced must be self-contained (see module doc); the deps
1198
+ * wiring re-creates the same composition `createAvatar2DPoseCoreDeps`
1199
+ * provides on the main thread. Runtime config travels in the 'start' message.
1200
+ */
1201
+ function buildAvatar2DRenderWorkerSource() {
1202
+ return [
1203
+ "\"use strict\";",
1204
+ `const rawPoseFromCompact = ${rawPoseFromCompact.toString()};`,
1205
+ `const mapToPose = ${mapToPose.toString()};`,
1206
+ `const Median = ${Median.toString()};`,
1207
+ `const createPoseCoreImpl = ${createAvatar2DPoseCore.toString()};`,
1208
+ `const createSmileyCore = ${createSatinSmileyCore.toString()};`,
1209
+ `const createPacer = ${createFramePacer.toString()};`,
1210
+ `const workerMain = ${avatar2dRenderWorkerMain.toString()};`,
1211
+ `workerMain(self, {
1212
+ createPoseCore: (cfg) =>
1213
+ createPoseCoreImpl(cfg, {
1214
+ rawPoseFromCompact,
1215
+ mapToPose,
1216
+ createMedian: (windowSize) => new Median(windowSize),
1217
+ }),
1218
+ createSmileyCore,
1219
+ createPacer,
1220
+ });`
1221
+ ].join("\n");
1222
+ }
1223
+ /** Assemble the TRACK worker script (compact-face extraction + main). */
1224
+ function buildAvatar2DTrackWorkerSource() {
1225
+ return [
1226
+ "\"use strict\";",
1227
+ `const extractCompact = ${extractCompactFace.toString()};`,
1228
+ `const workerMain = ${avatar2dTrackWorkerMain.toString()};`,
1229
+ "workerMain(self, { extractCompact });"
1230
+ ].join("\n");
1231
+ }
1232
+ //#endregion
1233
+ //#region ../infra/src/avatar/2d-default-avatar/avatar2dWarm.ts
1234
+ /**
1235
+ * Pre-capture warm-up registry for the avatar-2d worker (ENG-49806 AC#1).
1236
+ *
1237
+ * The heavy part of avatar start is the MediaPipe bring-up (module + ~3.7MB
1238
+ * model download + WASM compile) — seconds on a low-tier device, which made
1239
+ * the smiley LOSE THE RACE against a fast capture on the Galaxy-A04e-class
1240
+ * target. `warmAvatar2D()` boots the real avatar worker during the tutorial
1241
+ * phase and runs that bring-up WITHOUT camera or canvas (cosmetic-only by
1242
+ * construction — no media is touched); the provider then ADOPTS the warm
1243
+ * worker at capture start via `takeWarmAvatar2DWorker()` and tracking engages
1244
+ * near-instantly.
1245
+ *
1246
+ * Lifecycle: one warm entry at a time (keyed by the resolved asset URLs —
1247
+ * idempotent re-warms are no-ops; different assets replace the entry). The
1248
+ * entry is consumed on adoption, released explicitly by the capture machine's
1249
+ * terminal states, and self-disposes after WARM_TTL_MS as the backstop for
1250
+ * teardown paths that never reach either (e.g. the host unmounting the module
1251
+ * mid-tutorial).
1252
+ */
1253
+ /** Idle warm workers self-dispose after this long without adoption. */
1254
+ const WARM_TTL_MS = 5 * 6e4;
1255
+ let entry = null;
1256
+ function assetsKey(assets) {
1257
+ return assets.mediapipeModulePath + "\n" + assets.mediapipeWasmPath + "\n" + assets.faceLandmarkerModelPath;
1258
+ }
1259
+ /**
1260
+ * Boot the avatar-2d worker and start its MediaPipe bring-up in the
1261
+ * background. Fire-and-forget and never throws; environments without the
1262
+ * worker path (probe fail, CSP, instrumented source) silently no-op — the
1263
+ * capture-time fallback chain is unchanged.
1264
+ */
1265
+ function warmAvatar2D(overrides) {
1266
+ try {
1267
+ if (!canUseAvatar2DWorker()) return;
1268
+ const assets = resolveAvatar2DAssets(overrides ?? {});
1269
+ const key = assetsKey(assets);
1270
+ if (entry?.key === key) return;
1271
+ releaseAvatar2DWarmup();
1272
+ const source = buildAvatar2DTrackWorkerSource();
1273
+ if (detectWorkerSourceInstrumentation(source)) return;
1274
+ let blobUrl = null;
1275
+ let worker;
1276
+ try {
1277
+ blobUrl = URL.createObjectURL(new Blob([source], { type: "text/javascript" }));
1278
+ worker = new Worker(blobUrl);
1279
+ } catch {
1280
+ if (blobUrl) URL.revokeObjectURL(blobUrl);
1281
+ return;
1282
+ }
1283
+ if (blobUrl) URL.revokeObjectURL(blobUrl);
1284
+ const ttlId = setTimeout(() => {
1285
+ if (entry?.worker === worker) releaseAvatar2DWarmup();
1286
+ }, WARM_TTL_MS);
1287
+ entry = {
1288
+ worker,
1289
+ key,
1290
+ blobUrl: null,
1291
+ ttlId
1292
+ };
1293
+ worker.onerror = () => {
1294
+ if (entry?.worker === worker) releaseAvatar2DWarmup();
1295
+ };
1296
+ const warmMsg = {
1297
+ type: "warm",
1298
+ mediapipeModulePath: assets.mediapipeModulePath,
1299
+ mediapipeWasmPath: assets.mediapipeWasmPath,
1300
+ faceLandmarkerModelPath: assets.faceLandmarkerModelPath
1301
+ };
1302
+ worker.postMessage(warmMsg);
1303
+ } catch {}
1304
+ }
1305
+ /**
1306
+ * Hand the warm worker (if any, and only for the SAME resolved assets) to the
1307
+ * provider. The caller owns it from here — the registry forgets the entry and
1308
+ * detaches its listeners.
1309
+ */
1310
+ function takeWarmAvatar2DWorker(assets) {
1311
+ if (!entry || entry.key !== assetsKey(assets)) return null;
1312
+ const { worker, blobUrl, ttlId } = entry;
1313
+ entry = null;
1314
+ clearTimeout(ttlId);
1315
+ if (blobUrl) URL.revokeObjectURL(blobUrl);
1316
+ worker.onmessage = null;
1317
+ worker.onerror = null;
1318
+ return worker;
1319
+ }
1320
+ /** Dispose an un-adopted warm worker (terminal machine states; re-warm). */
1321
+ function releaseAvatar2DWarmup() {
1322
+ if (!entry) return;
1323
+ const { worker, blobUrl, ttlId } = entry;
1324
+ entry = null;
1325
+ clearTimeout(ttlId);
1326
+ if (blobUrl) URL.revokeObjectURL(blobUrl);
1327
+ worker.terminate();
1328
+ }
1329
+ //#endregion
1330
+ export { createAvatar2DPoseCore as a, SatinSmileyRenderer as c, AVATAR2D_POSE_CORE_DEFAULTS as i, resolveAvatar2DAssets as l, buildAvatar2DTrackWorkerSource as n, createAvatar2DPoseCoreDeps as o, canUseAvatar2DWorker as r, releaseAvatar2DWarmup, extractCompactFace as s, buildAvatar2DRenderWorkerSource as t, takeWarmAvatar2DWorker, warmAvatar2D };