@pose-tracker/pose-estimation-web 0.1.0 → 0.2.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.
@@ -1,13 +1,13 @@
1
- "use strict";var PoseTracker=(()=>{var ut=Object.create;var le=Object.defineProperty;var ft=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames;var gt=Object.getPrototypeOf,yt=Object.prototype.hasOwnProperty;var Ze=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var xt=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),kt=(t,e)=>{for(var r in e)le(t,r,{get:e[r],enumerable:!0})},et=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of mt(e))!yt.call(t,i)&&i!==r&&le(t,i,{get:()=>e[i],enumerable:!(s=ft(e,i))||s.enumerable});return t};var tt=(t,e,r)=>(r=t!=null?ut(gt(t)):{},et(e||!t||!t.__esModule?le(r,"default",{value:t,enumerable:!0}):r,t)),vt=t=>et(le({},"__esModule",{value:!0}),t);var Me=xt((Yt,ce)=>{"use strict";(function(){"use strict";var t="input is invalid type",e=typeof window=="object",r=e?window:{};r.JS_SHA256_NO_WINDOW&&(e=!1);var s=!e&&typeof self=="object",i=!r.JS_SHA256_NO_NODE_JS&&typeof process=="object"&&process.versions&&process.versions.node&&process.type!="renderer";i?r=global:s&&(r=self);var n=!r.JS_SHA256_NO_COMMON_JS&&typeof ce=="object"&&ce.exports,p=typeof define=="function"&&define.amd,g=!r.JS_SHA256_NO_ARRAY_BUFFER&&typeof ArrayBuffer<"u",a="0123456789abcdef".split(""),S=[-2147483648,8388608,32768,128],b=[24,16,8,0],_=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],k=["hex","array","digest","arrayBuffer"],y=[];(r.JS_SHA256_NO_NODE_JS||!Array.isArray)&&(Array.isArray=function(o){return Object.prototype.toString.call(o)==="[object Array]"}),g&&(r.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW||!ArrayBuffer.isView)&&(ArrayBuffer.isView=function(o){return typeof o=="object"&&o.buffer&&o.buffer.constructor===ArrayBuffer});var C=function(o,h){return function(u){return new x(h,!0).update(u)[o]()}},T=function(o){var h=C("hex",o);i&&(h=N(h,o)),h.create=function(){return new x(o)},h.update=function(f){return h.create().update(f)};for(var u=0;u<k.length;++u){var d=k[u];h[d]=C(d,o)}return h},N=function(o,h){var u=Ze("crypto"),d=Ze("buffer").Buffer,f=h?"sha224":"sha256",c;d.from&&!r.JS_SHA256_NO_BUFFER_FROM?c=d.from:c=function(l){return new d(l)};var v=function(l){if(typeof l=="string")return u.createHash(f).update(l,"utf8").digest("hex");if(l==null)throw new Error(t);return l.constructor===ArrayBuffer&&(l=new Uint8Array(l)),Array.isArray(l)||ArrayBuffer.isView(l)||l.constructor===d?u.createHash(f).update(c(l)).digest("hex"):o(l)};return v},W=function(o,h){return function(u,d){return new F(u,h,!0).update(d)[o]()}},m=function(o){var h=W("hex",o);h.create=function(f){return new F(f,o)},h.update=function(f,c){return h.create(f).update(c)};for(var u=0;u<k.length;++u){var d=k[u];h[d]=W(d,o)}return h};function x(o,h){h?(y[0]=y[16]=y[1]=y[2]=y[3]=y[4]=y[5]=y[6]=y[7]=y[8]=y[9]=y[10]=y[11]=y[12]=y[13]=y[14]=y[15]=0,this.blocks=y):this.blocks=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],o?(this.h0=3238371032,this.h1=914150663,this.h2=812702999,this.h3=4144912697,this.h4=4290775857,this.h5=1750603025,this.h6=1694076839,this.h7=3204075428):(this.h0=1779033703,this.h1=3144134277,this.h2=1013904242,this.h3=2773480762,this.h4=1359893119,this.h5=2600822924,this.h6=528734635,this.h7=1541459225),this.block=this.start=this.bytes=this.hBytes=0,this.finalized=this.hashed=!1,this.first=!0,this.is224=o}x.prototype.update=function(o){if(!this.finalized){var h,u=typeof o;if(u!=="string"){if(u==="object"){if(o===null)throw new Error(t);if(g&&o.constructor===ArrayBuffer)o=new Uint8Array(o);else if(!Array.isArray(o)&&(!g||!ArrayBuffer.isView(o)))throw new Error(t)}else throw new Error(t);h=!0}for(var d,f=0,c,v=o.length,l=this.blocks;f<v;){if(this.hashed&&(this.hashed=!1,l[0]=this.block,this.block=l[16]=l[1]=l[2]=l[3]=l[4]=l[5]=l[6]=l[7]=l[8]=l[9]=l[10]=l[11]=l[12]=l[13]=l[14]=l[15]=0),h)for(c=this.start;f<v&&c<64;++f)l[c>>>2]|=o[f]<<b[c++&3];else for(c=this.start;f<v&&c<64;++f)d=o.charCodeAt(f),d<128?l[c>>>2]|=d<<b[c++&3]:d<2048?(l[c>>>2]|=(192|d>>>6)<<b[c++&3],l[c>>>2]|=(128|d&63)<<b[c++&3]):d<55296||d>=57344?(l[c>>>2]|=(224|d>>>12)<<b[c++&3],l[c>>>2]|=(128|d>>>6&63)<<b[c++&3],l[c>>>2]|=(128|d&63)<<b[c++&3]):(d=65536+((d&1023)<<10|o.charCodeAt(++f)&1023),l[c>>>2]|=(240|d>>>18)<<b[c++&3],l[c>>>2]|=(128|d>>>12&63)<<b[c++&3],l[c>>>2]|=(128|d>>>6&63)<<b[c++&3],l[c>>>2]|=(128|d&63)<<b[c++&3]);this.lastByteIndex=c,this.bytes+=c-this.start,c>=64?(this.block=l[16],this.start=c-64,this.hash(),this.hashed=!0):this.start=c}return this.bytes>4294967295&&(this.hBytes+=this.bytes/4294967296<<0,this.bytes=this.bytes%4294967296),this}},x.prototype.finalize=function(){if(!this.finalized){this.finalized=!0;var o=this.blocks,h=this.lastByteIndex;o[16]=this.block,o[h>>>2]|=S[h&3],this.block=o[16],h>=56&&(this.hashed||this.hash(),o[0]=this.block,o[16]=o[1]=o[2]=o[3]=o[4]=o[5]=o[6]=o[7]=o[8]=o[9]=o[10]=o[11]=o[12]=o[13]=o[14]=o[15]=0),o[14]=this.hBytes<<3|this.bytes>>>29,o[15]=this.bytes<<3,this.hash()}},x.prototype.hash=function(){var o=this.h0,h=this.h1,u=this.h2,d=this.h3,f=this.h4,c=this.h5,v=this.h6,l=this.h7,w=this.blocks,P,R,D,U,E,H,$,G,_e,Pe,ae;for(P=16;P<64;++P)E=w[P-15],R=(E>>>7|E<<25)^(E>>>18|E<<14)^E>>>3,E=w[P-2],D=(E>>>17|E<<15)^(E>>>19|E<<13)^E>>>10,w[P]=w[P-16]+R+w[P-7]+D<<0;for(ae=h&u,P=0;P<64;P+=4)this.first?(this.is224?(G=300032,E=w[0]-1413257819,l=E-150054599<<0,d=E+24177077<<0):(G=704751109,E=w[0]-210244248,l=E-1521486534<<0,d=E+143694565<<0),this.first=!1):(R=(o>>>2|o<<30)^(o>>>13|o<<19)^(o>>>22|o<<10),D=(f>>>6|f<<26)^(f>>>11|f<<21)^(f>>>25|f<<7),G=o&h,U=G^o&u^ae,$=f&c^~f&v,E=l+D+$+_[P]+w[P],H=R+U,l=d+E<<0,d=E+H<<0),R=(d>>>2|d<<30)^(d>>>13|d<<19)^(d>>>22|d<<10),D=(l>>>6|l<<26)^(l>>>11|l<<21)^(l>>>25|l<<7),_e=d&o,U=_e^d&h^G,$=l&f^~l&c,E=v+D+$+_[P+1]+w[P+1],H=R+U,v=u+E<<0,u=E+H<<0,R=(u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10),D=(v>>>6|v<<26)^(v>>>11|v<<21)^(v>>>25|v<<7),Pe=u&d,U=Pe^u&o^_e,$=v&l^~v&f,E=c+D+$+_[P+2]+w[P+2],H=R+U,c=h+E<<0,h=E+H<<0,R=(h>>>2|h<<30)^(h>>>13|h<<19)^(h>>>22|h<<10),D=(c>>>6|c<<26)^(c>>>11|c<<21)^(c>>>25|c<<7),ae=h&u,U=ae^h&d^Pe,$=c&v^~c&l,E=f+D+$+_[P+3]+w[P+3],H=R+U,f=o+E<<0,o=E+H<<0,this.chromeBugWorkAround=!0;this.h0=this.h0+o<<0,this.h1=this.h1+h<<0,this.h2=this.h2+u<<0,this.h3=this.h3+d<<0,this.h4=this.h4+f<<0,this.h5=this.h5+c<<0,this.h6=this.h6+v<<0,this.h7=this.h7+l<<0},x.prototype.hex=function(){this.finalize();var o=this.h0,h=this.h1,u=this.h2,d=this.h3,f=this.h4,c=this.h5,v=this.h6,l=this.h7,w=a[o>>>28&15]+a[o>>>24&15]+a[o>>>20&15]+a[o>>>16&15]+a[o>>>12&15]+a[o>>>8&15]+a[o>>>4&15]+a[o&15]+a[h>>>28&15]+a[h>>>24&15]+a[h>>>20&15]+a[h>>>16&15]+a[h>>>12&15]+a[h>>>8&15]+a[h>>>4&15]+a[h&15]+a[u>>>28&15]+a[u>>>24&15]+a[u>>>20&15]+a[u>>>16&15]+a[u>>>12&15]+a[u>>>8&15]+a[u>>>4&15]+a[u&15]+a[d>>>28&15]+a[d>>>24&15]+a[d>>>20&15]+a[d>>>16&15]+a[d>>>12&15]+a[d>>>8&15]+a[d>>>4&15]+a[d&15]+a[f>>>28&15]+a[f>>>24&15]+a[f>>>20&15]+a[f>>>16&15]+a[f>>>12&15]+a[f>>>8&15]+a[f>>>4&15]+a[f&15]+a[c>>>28&15]+a[c>>>24&15]+a[c>>>20&15]+a[c>>>16&15]+a[c>>>12&15]+a[c>>>8&15]+a[c>>>4&15]+a[c&15]+a[v>>>28&15]+a[v>>>24&15]+a[v>>>20&15]+a[v>>>16&15]+a[v>>>12&15]+a[v>>>8&15]+a[v>>>4&15]+a[v&15];return this.is224||(w+=a[l>>>28&15]+a[l>>>24&15]+a[l>>>20&15]+a[l>>>16&15]+a[l>>>12&15]+a[l>>>8&15]+a[l>>>4&15]+a[l&15]),w},x.prototype.toString=x.prototype.hex,x.prototype.digest=function(){this.finalize();var o=this.h0,h=this.h1,u=this.h2,d=this.h3,f=this.h4,c=this.h5,v=this.h6,l=this.h7,w=[o>>>24&255,o>>>16&255,o>>>8&255,o&255,h>>>24&255,h>>>16&255,h>>>8&255,h&255,u>>>24&255,u>>>16&255,u>>>8&255,u&255,d>>>24&255,d>>>16&255,d>>>8&255,d&255,f>>>24&255,f>>>16&255,f>>>8&255,f&255,c>>>24&255,c>>>16&255,c>>>8&255,c&255,v>>>24&255,v>>>16&255,v>>>8&255,v&255];return this.is224||w.push(l>>>24&255,l>>>16&255,l>>>8&255,l&255),w},x.prototype.array=x.prototype.digest,x.prototype.arrayBuffer=function(){this.finalize();var o=new ArrayBuffer(this.is224?28:32),h=new DataView(o);return h.setUint32(0,this.h0),h.setUint32(4,this.h1),h.setUint32(8,this.h2),h.setUint32(12,this.h3),h.setUint32(16,this.h4),h.setUint32(20,this.h5),h.setUint32(24,this.h6),this.is224||h.setUint32(28,this.h7),o};function F(o,h,u){var d,f=typeof o;if(f==="string"){var c=[],v=o.length,l=0,w;for(d=0;d<v;++d)w=o.charCodeAt(d),w<128?c[l++]=w:w<2048?(c[l++]=192|w>>>6,c[l++]=128|w&63):w<55296||w>=57344?(c[l++]=224|w>>>12,c[l++]=128|w>>>6&63,c[l++]=128|w&63):(w=65536+((w&1023)<<10|o.charCodeAt(++d)&1023),c[l++]=240|w>>>18,c[l++]=128|w>>>12&63,c[l++]=128|w>>>6&63,c[l++]=128|w&63);o=c}else if(f==="object"){if(o===null)throw new Error(t);if(g&&o.constructor===ArrayBuffer)o=new Uint8Array(o);else if(!Array.isArray(o)&&(!g||!ArrayBuffer.isView(o)))throw new Error(t)}else throw new Error(t);o.length>64&&(o=new x(h,!0).update(o).array());var P=[],R=[];for(d=0;d<64;++d){var D=o[d]||0;P[d]=92^D,R[d]=54^D}x.call(this,h,u),this.update(R),this.oKeyPad=P,this.inner=!0,this.sharedMemory=u}F.prototype=new x,F.prototype.finalize=function(){if(x.prototype.finalize.call(this),this.inner){this.inner=!1;var o=this.array();x.call(this,this.is224,this.sharedMemory),this.update(this.oKeyPad),this.update(o),x.prototype.finalize.call(this)}};var M=T();M.sha256=M,M.sha224=T(!0),M.sha256.hmac=m(),M.sha224.hmac=m(!0),n?ce.exports=M:(r.sha256=M.sha256,r.sha224=M.sha224,p&&define(function(){return M}))})()});var Vt={};kt(Vt,{COCO_KEYPOINT_NAMES:()=>I,DEFAULT_MOVENET_LIGHTNING_URL:()=>ye,ONLINE_TFJS_VERSION:()=>me,PoseCamera:()=>Qe,SDK_NAME:()=>q,SDK_VERSION:()=>K,configure:()=>z,createPoseTracker:()=>Ee,defaultTfjsCdnUrls:()=>$e,resolvePoseModel:()=>V,shouldShowWatermark:()=>ne});var K="0.1.0",q="posetracker-web";var j="https://movelytics-strapi-c78a339b7070.herokuapp.com",O=class extends Error{constructor(r,s){super(s);this.code=r;this.name="ConfigureError"}};async function z(t,e={}){let r=(e.baseUrl??j).replace(/\/$/,""),s={...t?{apiToken:t}:{},sdkName:q,sdkVersion:K,targetPlatform:"web",poseModelProfile:e.poseModelProfile??"AdaptiveChoice",locale:e.locale,localVersions:e.localVersions},i;try{i=await fetch(`${r}/api/sdk/configure`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)})}catch(n){throw new O("network",`Handshake request failed: ${String(n)}`)}if(i.status===401||i.status===403)throw new O("invalid_token","Invalid, revoked or unauthorized API token.");if(i.status===429)throw new O("quota_exceeded","API call quota exceeded for the current plan.");if(!i.ok)throw new O("internal",`Handshake failed with HTTP ${i.status}.`);return await i.json()}var Re=tt(Me(),1);var Fe=tt(Me(),1),Te="ptc1:";function Ce(t){return(0,Fe.sha256)(`posetracker-sdk-cache:${t}`)}function wt(t){let e=unescape(encodeURIComponent(t)),r=new Uint8Array(e.length);for(let s=0;s<e.length;s++)r[s]=e.charCodeAt(s);return r}function bt(t){let e="";for(let r=0;r<t.length;r++)e+=String.fromCharCode(t[r]);return decodeURIComponent(escape(e))}function St(t){let e="";for(let r=0;r<t.length;r++)e+=t[r].toString(16).padStart(2,"0");return e}function Et(t){if(t.length%2!==0||/[^0-9a-f]/.test(t))return null;let e=new Uint8Array(t.length/2);for(let r=0;r<e.length;r++)e[r]=parseInt(t.slice(r*2,r*2+2),16);return e}function rt(t,e){let r=new Uint8Array(t.length),s=0,i=0;for(;i<t.length;){let n=Fe.sha256.array(`${e}:${s++}`);for(let p=0;p<n.length&&i<t.length;p++,i++)r[i]=t[i]^n[p]}return r}function de(t,e){return Te+St(rt(wt(t),e))}function pe(t,e){if(!t.startsWith(Te))return null;let r=Et(t.slice(Te.length));if(!r)return null;try{return bt(rt(r,e))}catch{return null}}var Ae="posetracker.web.";function J(){return typeof localStorage>"u"?null:{async getItem(t){try{return localStorage.getItem(Ae+t)}catch{return null}},async setItem(t,e){try{localStorage.setItem(Ae+t,e)}catch{}},async removeItem(t){try{localStorage.removeItem(Ae+t)}catch{}}}}function ot(){let t=J();return t?{read:e=>t.getItem(`file.${e}`),write:(e,r)=>t.setItem(`file.${e}`,r),remove:e=>t.removeItem(`file.${e}`)}:null}function it(){let t=new Map;return{async read(e){return t.has(e)?t.get(e):null},async write(e,r){t.set(e,r)},async remove(e){t.delete(e)}}}function he(){return ot()??it()}var st="posetracker.engine.guard.",Y=class{constructor(e={}){this.lastError=null;this.files=e.fileStore!==void 0?e.fileStore:he(),this.kv=e.keyValueStore!==void 0?e.keyValueStore:J(),this.fetchFn=e.fetchFn??fetch,this.onDiagnostic=e.onDiagnostic,this.onDiagnostic?.(`[posetracker-web] EngineLoader fileStore=${this.files?"yes":"none"} kv=${this.kv?"localStorage":"none"}`)}async clearGuard(e){if(!e||!this.kv)return;let r=`${st}${e.version}.${e.sha256}`;await this.kv.removeItem(r).catch(()=>{})}async load(e,r,s){if(this.lastError=null,!e)return this.lastError="manifest has no engine descriptor",null;let i=`${st}${e.version}.${e.sha256}`;s?.forceRetry&&await this.kv?.removeItem(i).catch(()=>{});let n=await this.kv?.getItem(i);if(n==="probing"||n==="failed")return await this.kv?.setItem(i,"failed"),this.lastError=`engine crash-guard blocked version=${e.version} (state=${n}) \u2014 call configure() again to force retry`,this.onDiagnostic?.(`[posetracker-web] ${this.lastError}`),null;let p=`engine-${e.version}.sealed`,g=await this.files?.read(p);if(g!=null){let a=pe(g,r);if(a!==null&&(0,Re.sha256)(a)===e.sha256){let S=await this.evaluate(a,i);if(S)return this.onDiagnostic?.(`[posetracker-web] engine loaded from cache version=${e.version}`),{engine:S,source:"remote-cache"}}else this.onDiagnostic?.(`[posetracker-web] engine cache purged (unseal/integrity mismatch) key=${p}`),await this.files?.remove(p)}try{this.onDiagnostic?.(`[posetracker-web] downloading engine version=${e.version}\u2026`);let a=await this.fetchFn(e.signedUrl);if(!a.ok)throw new Error(`HTTP ${a.status}`);let S=await a.text(),b=(0,Re.sha256)(S);if(b!==e.sha256)throw new Error(`integrity check failed (got ${b.slice(0,12)}\u2026 expected ${e.sha256.slice(0,12)}\u2026, bytes=${S.length})`);let _=await this.evaluate(S,i);if(_){try{await this.files?.write(p,de(S,r))}catch(k){this.onDiagnostic?.("[posetracker-web] engine cache write failed (non-fatal): "+(k instanceof Error?k.message:String(k)))}return this.onDiagnostic?.(`[posetracker-web] engine loaded from download version=${e.version} bytes=${S.length}`),{engine:_,source:"remote-download"}}}catch(a){this.lastError=a instanceof Error?a.message:String(a),this.onDiagnostic?.(`[posetracker-web] engine download/load failed: ${this.lastError}`)}return this.lastError||(this.lastError="engine evaluate returned null"),null}async evaluate(e,r){await this.kv?.setItem(r,"probing");try{let s={exports:{}};new Function("module","exports",e)(s,s.exports);let n=s.exports.createEngine;if(typeof n!="function")throw new Error(`engine bundle does not export createEngine() (got ${typeof n}, keys=${Object.keys(s.exports).join(",")})`);let p=n();return await this.kv?.setItem(r,"passed"),p}catch(s){return this.lastError="engine evaluate failed: "+(s instanceof Error?s.message:String(s)),this.onDiagnostic?.(`[posetracker-web] ${this.lastError}`),await this.kv?.setItem(r,"failed"),null}}};var De="posetracker.track.queue",_t=100,L=class extends Error{constructor(r,s){super(s);this.code=r;this.name="TrackError"}},X=class{constructor(e={}){this.baseUrl=(e.baseUrl??j).replace(/\/$/,""),this.kv=e.keyValueStore!==void 0?e.keyValueStore:J(),this.fetchFn=e.fetchFn??fetch}async trackMetered(e){return this.post({event:e.event??"camera_start",apiToken:e.apiToken,platform:"web",sdkVersion:K,params:e.params})}async trackAnonymous(e={}){let r={event:e.event??"camera_start",platform:"web",sdkVersion:K,params:e.params,queuedAtMs:Date.now()};try{await this.post({...r}),this.flushQueue()}catch{await this.enqueue(r)}}async flushQueue(){let e=await this.readQueue();if(e.length===0)return;let r=[];for(let s of e)try{await this.post({...s,params:{...s.params??{},queuedAtMs:s.queuedAtMs}})}catch{r.push(s)}await this.writeQueue(r)}async post(e){let r;try{r=await this.fetchFn(`${this.baseUrl}/api/sdk/track`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})}catch(s){throw new L("network",`Usage tracking request failed: ${String(s)}`)}if(r.status===401||r.status===403)throw new L("invalid_token","Invalid, revoked or unauthorized API token.");if(r.status===429)throw new L("quota_exceeded","API call quota exceeded for the current plan.");if(!r.ok)throw new L("internal",`Usage tracking failed with HTTP ${r.status}.`);return await r.json()}async readQueue(){try{let e=await this.kv?.getItem(De);if(!e)return[];let r=JSON.parse(e);return Array.isArray(r)?r:[]}catch{return[]}}async writeQueue(e){try{e.length===0?await this.kv?.removeItem(De):await this.kv?.setItem(De,JSON.stringify(e.slice(-_t)))}catch{}}async enqueue(e){let r=await this.readQueue();r.push(e),await this.writeQueue(r)}};var B=class extends Error{constructor(r,s){super(s);this.code=r;this.name="SkeletonFetchError"}};async function Le(t,e={}){let r=t.trim();if(!r||r==="true"||r==="false")throw new B("invalid","skeleton uuid is required");let s=(e.baseUrl??j).replace(/\/$/,""),i;try{i=await fetch(`${s}/api/sdk/skeleton?uuid=${encodeURIComponent(r)}`)}catch(p){throw new B("network",`Skeleton fetch failed: ${String(p)}`)}if(i.status===404)throw new B("not_found",`Skeleton '${r}' not found`);if(!i.ok)throw new B("network",`Skeleton fetch HTTP ${i.status}`);let n=await i.json();if(!n?.keypoints||!n?.keypoint_lines||!n?.circles||!n?.lines)throw new B("invalid","Skeleton payload incomplete");return{keypoints:n.keypoints,keypoint_lines:n.keypoint_lines,keypoint_angles:n.keypoint_angles??[],circles:n.circles,lines:n.lines,angles:n.angles}}async function Oe(t={}){if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw new Error("getUserMedia is not available in this environment");let e=t.facingMode??"user",r={audio:!1,video:{facingMode:e,width:t.idealWidth?{ideal:t.idealWidth}:void 0,height:t.idealHeight?{ideal:t.idealHeight}:void 0,frameRate:t.idealFrameRate?{ideal:t.idealFrameRate}:void 0}};try{return await navigator.mediaDevices.getUserMedia(r)}catch{return navigator.mediaDevices.getUserMedia({audio:!1,video:{facingMode:e}})}}function Ie(t){if(t)for(let e of t.getTracks())try{e.stop()}catch{}}var Ue={face_squat:"squat",face_pushup:"push_up",face_plank:"plank",face_lunge:"lunge",face_jumping_jack:"jumping_jack",face_low_impact_jack:"low_impact_jack",face_balance_leg:"balance_leg",face_balance_leg_left:"balance_leg_left",face_balance_leg_right:"balance_leg_right",jump:"air_time_jump"};function Ne(t){return Ue[t]??t}function ue(t,e){let r=e.find(n=>n.id===t);if(r)return r;let s=Ne(t),i=Object.entries(Ue).filter(([,n])=>n===s).map(([n])=>n);for(let n of i){let p=e.find(g=>g.id===n);if(p)return p}return e.find(n=>Ne(n.id)===s)}var Pt={left_knee:"from_hip_to_ankle",right_knee:"from_hip_to_ankle",left_hip:"from_knee_to_shoulder",right_hip:"from_knee_to_shoulder",left_shoulder:"from_hip_to_elbow",right_shoulder:"from_hip_to_elbow",left_elbow:"from_shoulder_to_wrist",right_elbow:"from_shoulder_to_wrist"};function Mt(t){let e={left_side:{},right_side:{}};for(let r of t){if(r.side!=="left"&&r.side!=="right")continue;let s=r.side==="left"?e.left_side:e.right_side,n=`${r.id.replace(/^(left_|right_)/,"")}_angle`,p=Pt[r.id]??"value";s[n]||(s[n]={}),s[n][p]=r.degrees,s[n][`score_${p}`]=r.score}return e}function He(t){switch(t.type){case"initialization":return{type:"initialization",message:t.step==="configuring"?"checking you plan and access":t.message??Tt(t.step),ready:t.ready,step:t.step,...t.mode!=null?{mode:t.mode}:{},...t.acceleration!=null?{acceleration:t.acceleration}:{}};case"error":return{type:"error",error:t.code,message:t.message};case"warning":return{type:"warning",error:t.code,message:t.message};case"keypoints":return{type:"keypoints",data:t.keypoints.map(e=>({name:e.name,x:e.x,y:e.y,...e.z!=null?{z:e.z}:{},score:e.score})),score:t.score,timestampMs:t.timestampMs};case"stats":return{type:"stats",fps:t.fps,medianInferenceMs:t.medianInferenceMs,backend:t.backend,keypointsAbove03:t.keypointsAbove03,meanScore:t.meanScore,videoSize:t.videoSize,timestampMs:t.timestampMs};case"angles":return{type:"angles",data:Mt(t.angles),timestampMs:t.timestampMs};case"counter":return{type:"counter",current_count:t.count,...t.formScore!=null?{form_score:{score:t.formScore.score,avg_score:t.formScore.average,grade:t.formScore.grade}}:{},...t.referenceScore!=null?{reference_score:{overallScore:t.referenceScore}}:{},timestampMs:t.timestampMs};case"posture":return{type:"posture",message:t.hint,ready:t.ready,direction:t.direction??"",requirements:{missingKeypoints:t.missingKeypoints},timestampMs:t.timestampMs};case"progression":return{type:"progression",value:t.value,timestampMs:t.timestampMs};case"recommendations":return{type:"recommendations",data:t.recommendations,timestampMs:t.timestampMs};case"form_score":return{type:"form_score",score:t.score,avg_score:t.average,grade:t.grade,timestampMs:t.timestampMs};case"exercise_summary":return{type:"exercise_summary",exercise:t.exercise,counter:t.counter,avg_rep_score:t.averageFormScore,avg_similarity:t.averageSimilarity,grade:t.grade,history:t.history,durationMs:t.durationMs,timestampMs:t.timestampMs};case"jump_calibration":return{type:"jump_calibration",calibrated:t.calibrated,cmPerPixel:t.cmPerPixel,baselineY:t.baselineY,visibleHips:t.visibleHips,message:t.message,timestampMs:t.timestampMs};case"jump_started":return{type:"jump_started",message:t.message,timestampMs:t.timestampMs};case"jump_height":{let{type:e,timestampMs:r,...s}=t;return{type:e,...s,timestampMs:r}}case"jump_discarded":return{type:"jump_discarded",reason:t.reason,userMessage:t.userMessage,timestampMs:t.timestampMs};case"jump_result":{let{type:e,timestampMs:r,...s}=t;return{type:e,...s,timestampMs:r}}case"jump_summary":{let{type:e,timestampMs:r,...s}=t;return{type:e,...s,timestampMs:r}}case"performance_warning":return{type:"error",error:t.code,message:t.message,meanFps:t.meanFps,thresholdFps:t.thresholdFps,activeProfile:t.activeProfile,medianInferenceMs:t.medianInferenceMs,videoSize:t.videoSize,timestampMs:t.timestampMs};case"quality_changed":return{type:"warning",error:"quality_downgraded",message:t.detail,previousProfile:t.previousProfile,activeProfile:t.activeProfile,reason:t.reason,timestampMs:t.timestampMs};case"runtime_download_progress":return{type:"initialization",message:`downloading pose runtime ${t.completedParts+1}/${t.totalParts}`,ready:!1,step:"downloading",part:t.part,completedParts:t.completedParts,totalParts:t.totalParts,timestampMs:t.timestampMs};default:return{type:"unknown",event:t}}}function Tt(t){switch(t){case"configuring":return"checking you plan and access";case"downloading":return"downloading engine";case"warming":return"loading pose model";case"ready":return"running";default:return t}}var I=["nose","left_eye","right_eye","left_ear","right_ear","left_shoulder","right_shoulder","left_elbow","right_elbow","left_wrist","right_wrist","left_hip","right_hip","left_knee","right_knee","left_ankle","right_ankle"];var me="4.22.0",Ft="https://cdn.jsdelivr.net/npm";function $e(t=Ft,e=me){let r=t.replace(/\/$/,"");return{scriptUrls:[`${r}/@tensorflow/tfjs-core@${e}/dist/tf-core.min.js`,`${r}/@tensorflow/tfjs-converter@${e}/dist/tf-converter.min.js`,`${r}/@tensorflow/tfjs-backend-webgl@${e}/dist/tf-backend-webgl.min.js`,`${r}/@tensorflow/tfjs-backend-wasm@${e}/dist/tf-backend-wasm.min.js`],wasmPath:`${r}/@tensorflow/tfjs-backend-wasm@${e}/dist/`}}var fe=null;function Ct(t){try{t.env().set("WEBGL_CPU_FORWARD",!1)}catch{}try{t.env().set("WEBGL_PACK",!1)}catch{}try{t.env().set("WEBGL_FORCE_F16_TEXTURES",!1)}catch{}try{t.env().set("WEBGL_RENDER_FLOAT32_ENABLED",!1)}catch{}try{t.env().set("WEBGL_FLUSH_THRESHOLD",1.75)}catch{}}function At(){return new Function("s","return import(s)")("@tensorflow/tfjs")}async function Q(){if(fe)return fe;if(typeof window<"u"&&window.tf)return fe=window.tf,window.tf;try{let t=await At();return fe=t,t}catch{}throw new Error("TensorFlow.js not found. Install peer `@tensorflow/tfjs` or load CDN scripts (see README) so `window.tf` is available.")}async function Z(t){Ct(t);try{let e=await t.setBackend("webgl");if(await t.ready(),e!==!1&&t.getBackend()==="webgl")return"webgl"}catch{}return await t.setBackend("cpu"),await t.ready(),"cpu"}var nt="2.1.3",Rt="https://cdn.jsdelivr.net/npm",ee=null,te=null;function at(t=Rt,e=nt){return`${t.replace(/\/$/,"")}/@tensorflow-models/pose-detection@${e}/dist/pose-detection.min.js`}function Dt(){return new Function("s","return import(s)")("@tensorflow-models/pose-detection")}function Ke(){if(typeof window>"u")return null;let t=window.poseDetection;return t&&typeof t.createDetector=="function"&&t.SupportedModels?.BlazePose?t:null}function Lt(t){if(typeof document>"u")return Promise.reject(new Error("Cannot inject pose-detection outside a browser document"));let e=Ke();return e?Promise.resolve(e):te||(te=new Promise((r,s)=>{let n=document.querySelector('script[data-pt-pose-detection="1"]'),p=()=>{let a=Ke();if(a){r(a);return}s(new Error("pose-detection CDN script loaded but `window.poseDetection` is missing. Check script order (TF.js first) and network."))};if(n){if(n.dataset.ptLoaded==="1"){p();return}n.addEventListener("load",p,{once:!0}),n.addEventListener("error",()=>s(new Error(`Failed to load pose-detection from ${n.src}`)),{once:!0});return}let g=document.createElement("script");g.src=t,g.async=!0,g.dataset.ptPoseDetection="1",g.onload=()=>{g.dataset.ptLoaded="1",p()},g.onerror=()=>{te=null,s(new Error(`Failed to load pose-detection from ${t}`))},document.head.appendChild(g)}),te)}async function Be(t){if(ee)return ee;let e=Ke();if(e)return ee=e,e;try{let s=await Dt();return ee=s,s}catch{}if(t?.allowCdn!==!1&&typeof window<"u"&&typeof document<"u"){let s=at(t?.cdnBase,t?.version),i=await Lt(s);return ee=i,i}throw new Error('BlazePose requires optional peer `@tensorflow-models/pose-detection`. Install it, load the CDN script so `window.poseDetection` exists, or use model="movenet" / pass a TF.js modelUrl.')}var Ot={nose:"nose",left_eye:"left_eye",right_eye:"right_eye",left_ear:"left_ear",right_ear:"right_ear",left_shoulder:"left_shoulder",right_shoulder:"right_shoulder",left_elbow:"left_elbow",right_elbow:"right_elbow",left_wrist:"left_wrist",right_wrist:"right_wrist",left_hip:"left_hip",right_hip:"right_hip",left_knee:"left_knee",right_knee:"right_knee",left_ankle:"left_ankle",right_ankle:"right_ankle"},re=class{constructor(e){this.modelId="blazepose";this.detector=null;this.backend=null;this.modelType="lite"}getBackend(){return this.backend}async load(){let e=await Q();this.backend=await Z(e);let r=await Be();this.detector=await r.createDetector(r.SupportedModels.BlazePose,{runtime:"tfjs",modelType:this.modelType,enableSmoothing:!0})}async estimate(e,r){if(!this.detector)throw new Error("BlazePose adapter not loaded");if(!(e.videoWidth>0&&e.videoHeight>0))return null;let s=performance.now(),i=await this.detector.estimatePoses(e,{flipHorizontal:!1,maxPoses:1}),n=performance.now()-s,p=i[0];if(!p?.keypoints?.length)return{keypoints:I.map(m=>({name:m,x:0,y:0,score:0})),score:0,inferenceMs:n,videoKeypoints:I.map(m=>({name:m,xPx:0,yPx:0,score:0})),letterbox:{offsetX:0,offsetY:0,drawW:e.videoWidth,drawH:e.videoHeight,vw:e.videoWidth,vh:e.videoHeight}};let g=e.videoWidth||1,a=e.videoHeight||1,S=r.displayWidth||1,b=r.displayHeight||1,_=new Map;for(let m of p.keypoints){let x=String(m.name||"").toLowerCase(),F=Ot[x];F&&_.set(F,{x:m.x,y:m.y,score:typeof m.score=="number"?m.score:0})}let k=I.map(m=>{let x=_.get(m);return{name:m,xPx:x?.x??0,yPx:x?.y??0,score:x?.score??0}}),y=Math.max(S/g,b/a),C=(S-g*y)/2,T=(b-a*y)/2,N=0;return{keypoints:k.map(m=>{let x=m.xPx*y+C,F=m.yPx*y+T,M=S>0?x/S:0,o=b>0?F/b:0;return r.facingMode==="user"&&(M=1-M),N+=m.score,{name:m.name,x:Math.min(1,Math.max(0,M)),y:Math.min(1,Math.max(0,o)),score:m.score}}),score:N/17,inferenceMs:n,videoKeypoints:k,letterbox:{offsetX:0,offsetY:0,drawW:g,drawH:a,vw:g,vh:a}}}dispose(){try{this.detector?.dispose?.()}catch{}this.detector=null}};var A=192,ge=.5;function It(t,e,r){let s=t*A,i=e*A;return{x:(s-r.offsetX)*(r.vw/r.drawW),y:(i-r.offsetY)*(r.vh/r.drawH)}}function lt(t,e,r,s,i){let n=Math.max(r/i.vw,s/i.vh),p=(r-i.vw*n)/2,g=(s-i.vh*n)/2;return{x:t*n+p,y:e*n+g}}var se=class{constructor(e){this.tf=null;this.model=null;this.backend=null;this.offscreen=null;this.offCtx=null;this.smoothed=null;this.letterbox={offsetX:0,offsetY:0,drawW:A,drawH:A,vw:1,vh:1};if(!e.resolved.modelUrl)throw new Error(e.resolved.unsupportedReason??"MoveNet requires a modelUrl");this.modelId=e.resolved.modelId,this.modelUrl=e.resolved.modelUrl}getBackend(){return this.backend}async load(){this.tf=await Q(),this.backend=await Z(this.tf),this.model=await this.tf.loadGraphModel(this.modelUrl);let e=this.tf.zeros([1,A,A,3],"int32"),r=this.model.execute(e);(Array.isArray(r)?r[0]:r).dataSync(),e.dispose(),Array.isArray(r)?r.forEach(i=>i.dispose()):r.dispose()}poseCanvasCtx(){if(this.offscreen||(this.offscreen=document.createElement("canvas"),this.offscreen.width=A,this.offscreen.height=A,this.offCtx=this.offscreen.getContext("2d",{willReadFrequently:!0})),!this.offCtx)throw new Error("2d context unavailable");return this.offCtx}prepareInput(e){let r=e.videoWidth||1,s=e.videoHeight||1,i=Math.min(A/r,A/s),n=r*i,p=s*i,g=(A-n)/2,a=(A-p)/2;this.letterbox={offsetX:g,offsetY:a,drawW:n,drawH:p,vw:r,vh:s};let S=this.poseCanvasCtx();return S.fillStyle="#000",S.fillRect(0,0,A,A),S.drawImage(e,0,0,r,s,g,a,n,p),this.offscreen}smooth(e){if(!this.smoothed)return this.smoothed=e.map(r=>({...r})),this.smoothed;for(let r=0;r<e.length;r++)e[r].score<.1||(this.smoothed[r].xPx=ge*e[r].xPx+(1-ge)*this.smoothed[r].xPx,this.smoothed[r].yPx=ge*e[r].yPx+(1-ge)*this.smoothed[r].yPx,this.smoothed[r].score=e[r].score);return this.smoothed}async estimate(e,r){if(!this.tf||!this.model)throw new Error("MoveNet adapter not loaded");if(!(e.videoWidth>0&&e.videoHeight>0))return null;let s=performance.now(),i=this.prepareInput(e),n=this.tf.tidy(()=>this.tf.expandDims(this.tf.browser.fromPixels(i),0)),p=this.model.execute(n),a=(Array.isArray(p)?p[0]:p).dataSync();n.dispose(),Array.isArray(p)?p.forEach(m=>m.dispose()):p.dispose();let S=performance.now()-s,b=this.letterbox,_=r.displayWidth||1,k=r.displayHeight||1,y=[],C=0;for(let m=0;m<17;m++){let x=Math.min(1,Math.max(0,a[m*3])),F=Math.min(1,Math.max(0,a[m*3+1])),M=a[m*3+2],o=It(F,x,b);y.push({name:I[m],xPx:o.x,yPx:o.y,score:M}),C+=M}let N=this.smooth(y).map((m,x)=>({name:I[x],xPx:m.xPx,yPx:m.yPx,score:m.score})),W=N.map(m=>{let x=lt(m.xPx,m.yPx,_,k,b),F=_>0?x.x/_:0,M=k>0?x.y/k:0;return r.facingMode==="user"&&(F=1-F),{name:m.name,x:Math.min(1,Math.max(0,F)),y:Math.min(1,Math.max(0,M)),score:m.score}});return{raw:a,keypoints:W,score:C/17,inferenceMs:S,videoKeypoints:N,letterbox:b}}dispose(){try{this.model?.dispose()}catch{}this.model=null,this.smoothed=null,this.offscreen=null,this.offCtx=null}};function We(t,e,r,s){return t.map(i=>{let n=lt(i.xPx,i.yPx,r,s,e);return{name:i.name,dx:n.x,dy:n.y,score:i.score}})}function Ve(t){let{resolved:e}=t;if(e.kind==="unsupported"||!e.modelUrl&&e.kind!=="blazepose")throw new Error(e.unsupportedReason??`Model "${e.modelId}" is unavailable.`);return e.kind==="blazepose"?new re(t):new se(t)}var ye="https://app.posetracker.com/scripts/tmp_model_to_remove.json";function V(t={}){let e=typeof t.modelUrl=="string"&&t.modelUrl.trim().length>0?t.modelUrl.trim():null;if(e)return{modelId:typeof t.model=="string"&&t.model.trim().length>0?t.model.trim():"custom",kind:"custom-graph",modelUrl:e};let r=(t.model??"movenet").trim().toLowerCase();return r==="movenet"||r==="movenet-singlepose-lightning"||r==="lightning"?{modelId:"movenet-singlepose-lightning",kind:"movenet-graph",modelUrl:ye}:r==="blazepose"?{modelId:"blazepose",kind:"blazepose",modelUrl:null}:{modelId:r,kind:"unsupported",modelUrl:null,unsupportedReason:`Unknown model "${t.model}". Use "movenet" (default), "blazepose", or pass modelUrl.`}}var oe="AI Loading",je="https://docs.posetracker.com/logo/light.png";var Nt=`
1
+ "use strict";var PoseTracker=(()=>{var Et=Object.create;var de=Object.defineProperty;var bt=Object.getOwnPropertyDescriptor;var _t=Object.getOwnPropertyNames;var Pt=Object.getPrototypeOf,Mt=Object.prototype.hasOwnProperty;var nt=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var Tt=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Ft=(t,e)=>{for(var r in e)de(t,r,{get:e[r],enumerable:!0})},at=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of _t(e))!Mt.call(t,o)&&o!==r&&de(t,o,{get:()=>e[o],enumerable:!(s=bt(e,o))||s.enumerable});return t};var lt=(t,e,r)=>(r=t!=null?Et(Pt(t)):{},at(e||!t||!t.__esModule?de(r,"default",{value:t,enumerable:!0}):r,t)),Ct=t=>at(de({},"__esModule",{value:!0}),t);var Le=Tt((nr,ue)=>{"use strict";(function(){"use strict";var t="input is invalid type",e=typeof window=="object",r=e?window:{};r.JS_SHA256_NO_WINDOW&&(e=!1);var s=!e&&typeof self=="object",o=!r.JS_SHA256_NO_NODE_JS&&typeof process=="object"&&process.versions&&process.versions.node&&process.type!="renderer";o?r=global:s&&(r=self);var n=!r.JS_SHA256_NO_COMMON_JS&&typeof ue=="object"&&ue.exports,d=typeof define=="function"&&define.amd,f=!r.JS_SHA256_NO_ARRAY_BUFFER&&typeof ArrayBuffer<"u",a="0123456789abcdef".split(""),v=[-2147483648,8388608,32768,128],w=[24,16,8,0],E=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],b=["hex","array","digest","arrayBuffer"],y=[];(r.JS_SHA256_NO_NODE_JS||!Array.isArray)&&(Array.isArray=function(i){return Object.prototype.toString.call(i)==="[object Array]"}),f&&(r.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW||!ArrayBuffer.isView)&&(ArrayBuffer.isView=function(i){return typeof i=="object"&&i.buffer&&i.buffer.constructor===ArrayBuffer});var _=function(i,u){return function(m){return new p(u,!0).update(m)[i]()}},P=function(i){var u=_("hex",i);o&&(u=R(u,i)),u.create=function(){return new p(i)},u.update=function(g){return u.create().update(g)};for(var m=0;m<b.length;++m){var h=b[m];u[h]=_(h,i)}return u},R=function(i,u){var m=nt("crypto"),h=nt("buffer").Buffer,g=u?"sha224":"sha256",c;h.from&&!r.JS_SHA256_NO_BUFFER_FROM?c=h.from:c=function(l){return new h(l)};var x=function(l){if(typeof l=="string")return m.createHash(g).update(l,"utf8").digest("hex");if(l==null)throw new Error(t);return l.constructor===ArrayBuffer&&(l=new Uint8Array(l)),Array.isArray(l)||ArrayBuffer.isView(l)||l.constructor===h?m.createHash(g).update(c(l)).digest("hex"):i(l)};return x},D=function(i,u){return function(m,h){return new F(m,u,!0).update(h)[i]()}},O=function(i){var u=D("hex",i);u.create=function(g){return new F(g,i)},u.update=function(g,c){return u.create(g).update(c)};for(var m=0;m<b.length;++m){var h=b[m];u[h]=D(h,i)}return u};function p(i,u){u?(y[0]=y[16]=y[1]=y[2]=y[3]=y[4]=y[5]=y[6]=y[7]=y[8]=y[9]=y[10]=y[11]=y[12]=y[13]=y[14]=y[15]=0,this.blocks=y):this.blocks=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],i?(this.h0=3238371032,this.h1=914150663,this.h2=812702999,this.h3=4144912697,this.h4=4290775857,this.h5=1750603025,this.h6=1694076839,this.h7=3204075428):(this.h0=1779033703,this.h1=3144134277,this.h2=1013904242,this.h3=2773480762,this.h4=1359893119,this.h5=2600822924,this.h6=528734635,this.h7=1541459225),this.block=this.start=this.bytes=this.hBytes=0,this.finalized=this.hashed=!1,this.first=!0,this.is224=i}p.prototype.update=function(i){if(!this.finalized){var u,m=typeof i;if(m!=="string"){if(m==="object"){if(i===null)throw new Error(t);if(f&&i.constructor===ArrayBuffer)i=new Uint8Array(i);else if(!Array.isArray(i)&&(!f||!ArrayBuffer.isView(i)))throw new Error(t)}else throw new Error(t);u=!0}for(var h,g=0,c,x=i.length,l=this.blocks;g<x;){if(this.hashed&&(this.hashed=!1,l[0]=this.block,this.block=l[16]=l[1]=l[2]=l[3]=l[4]=l[5]=l[6]=l[7]=l[8]=l[9]=l[10]=l[11]=l[12]=l[13]=l[14]=l[15]=0),u)for(c=this.start;g<x&&c<64;++g)l[c>>>2]|=i[g]<<w[c++&3];else for(c=this.start;g<x&&c<64;++g)h=i.charCodeAt(g),h<128?l[c>>>2]|=h<<w[c++&3]:h<2048?(l[c>>>2]|=(192|h>>>6)<<w[c++&3],l[c>>>2]|=(128|h&63)<<w[c++&3]):h<55296||h>=57344?(l[c>>>2]|=(224|h>>>12)<<w[c++&3],l[c>>>2]|=(128|h>>>6&63)<<w[c++&3],l[c>>>2]|=(128|h&63)<<w[c++&3]):(h=65536+((h&1023)<<10|i.charCodeAt(++g)&1023),l[c>>>2]|=(240|h>>>18)<<w[c++&3],l[c>>>2]|=(128|h>>>12&63)<<w[c++&3],l[c>>>2]|=(128|h>>>6&63)<<w[c++&3],l[c>>>2]|=(128|h&63)<<w[c++&3]);this.lastByteIndex=c,this.bytes+=c-this.start,c>=64?(this.block=l[16],this.start=c-64,this.hash(),this.hashed=!0):this.start=c}return this.bytes>4294967295&&(this.hBytes+=this.bytes/4294967296<<0,this.bytes=this.bytes%4294967296),this}},p.prototype.finalize=function(){if(!this.finalized){this.finalized=!0;var i=this.blocks,u=this.lastByteIndex;i[16]=this.block,i[u>>>2]|=v[u&3],this.block=i[16],u>=56&&(this.hashed||this.hash(),i[0]=this.block,i[16]=i[1]=i[2]=i[3]=i[4]=i[5]=i[6]=i[7]=i[8]=i[9]=i[10]=i[11]=i[12]=i[13]=i[14]=i[15]=0),i[14]=this.hBytes<<3|this.bytes>>>29,i[15]=this.bytes<<3,this.hash()}},p.prototype.hash=function(){var i=this.h0,u=this.h1,m=this.h2,h=this.h3,g=this.h4,c=this.h5,x=this.h6,l=this.h7,k=this.blocks,M,I,L,H,S,B,V,q,Ce,Ie,ce;for(M=16;M<64;++M)S=k[M-15],I=(S>>>7|S<<25)^(S>>>18|S<<14)^S>>>3,S=k[M-2],L=(S>>>17|S<<15)^(S>>>19|S<<13)^S>>>10,k[M]=k[M-16]+I+k[M-7]+L<<0;for(ce=u&m,M=0;M<64;M+=4)this.first?(this.is224?(q=300032,S=k[0]-1413257819,l=S-150054599<<0,h=S+24177077<<0):(q=704751109,S=k[0]-210244248,l=S-1521486534<<0,h=S+143694565<<0),this.first=!1):(I=(i>>>2|i<<30)^(i>>>13|i<<19)^(i>>>22|i<<10),L=(g>>>6|g<<26)^(g>>>11|g<<21)^(g>>>25|g<<7),q=i&u,H=q^i&m^ce,V=g&c^~g&x,S=l+L+V+E[M]+k[M],B=I+H,l=h+S<<0,h=S+B<<0),I=(h>>>2|h<<30)^(h>>>13|h<<19)^(h>>>22|h<<10),L=(l>>>6|l<<26)^(l>>>11|l<<21)^(l>>>25|l<<7),Ce=h&i,H=Ce^h&u^q,V=l&g^~l&c,S=x+L+V+E[M+1]+k[M+1],B=I+H,x=m+S<<0,m=S+B<<0,I=(m>>>2|m<<30)^(m>>>13|m<<19)^(m>>>22|m<<10),L=(x>>>6|x<<26)^(x>>>11|x<<21)^(x>>>25|x<<7),Ie=m&h,H=Ie^m&i^Ce,V=x&l^~x&g,S=c+L+V+E[M+2]+k[M+2],B=I+H,c=u+S<<0,u=S+B<<0,I=(u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10),L=(c>>>6|c<<26)^(c>>>11|c<<21)^(c>>>25|c<<7),ce=u&m,H=ce^u&h^Ie,V=c&x^~c&l,S=g+L+V+E[M+3]+k[M+3],B=I+H,g=i+S<<0,i=S+B<<0,this.chromeBugWorkAround=!0;this.h0=this.h0+i<<0,this.h1=this.h1+u<<0,this.h2=this.h2+m<<0,this.h3=this.h3+h<<0,this.h4=this.h4+g<<0,this.h5=this.h5+c<<0,this.h6=this.h6+x<<0,this.h7=this.h7+l<<0},p.prototype.hex=function(){this.finalize();var i=this.h0,u=this.h1,m=this.h2,h=this.h3,g=this.h4,c=this.h5,x=this.h6,l=this.h7,k=a[i>>>28&15]+a[i>>>24&15]+a[i>>>20&15]+a[i>>>16&15]+a[i>>>12&15]+a[i>>>8&15]+a[i>>>4&15]+a[i&15]+a[u>>>28&15]+a[u>>>24&15]+a[u>>>20&15]+a[u>>>16&15]+a[u>>>12&15]+a[u>>>8&15]+a[u>>>4&15]+a[u&15]+a[m>>>28&15]+a[m>>>24&15]+a[m>>>20&15]+a[m>>>16&15]+a[m>>>12&15]+a[m>>>8&15]+a[m>>>4&15]+a[m&15]+a[h>>>28&15]+a[h>>>24&15]+a[h>>>20&15]+a[h>>>16&15]+a[h>>>12&15]+a[h>>>8&15]+a[h>>>4&15]+a[h&15]+a[g>>>28&15]+a[g>>>24&15]+a[g>>>20&15]+a[g>>>16&15]+a[g>>>12&15]+a[g>>>8&15]+a[g>>>4&15]+a[g&15]+a[c>>>28&15]+a[c>>>24&15]+a[c>>>20&15]+a[c>>>16&15]+a[c>>>12&15]+a[c>>>8&15]+a[c>>>4&15]+a[c&15]+a[x>>>28&15]+a[x>>>24&15]+a[x>>>20&15]+a[x>>>16&15]+a[x>>>12&15]+a[x>>>8&15]+a[x>>>4&15]+a[x&15];return this.is224||(k+=a[l>>>28&15]+a[l>>>24&15]+a[l>>>20&15]+a[l>>>16&15]+a[l>>>12&15]+a[l>>>8&15]+a[l>>>4&15]+a[l&15]),k},p.prototype.toString=p.prototype.hex,p.prototype.digest=function(){this.finalize();var i=this.h0,u=this.h1,m=this.h2,h=this.h3,g=this.h4,c=this.h5,x=this.h6,l=this.h7,k=[i>>>24&255,i>>>16&255,i>>>8&255,i&255,u>>>24&255,u>>>16&255,u>>>8&255,u&255,m>>>24&255,m>>>16&255,m>>>8&255,m&255,h>>>24&255,h>>>16&255,h>>>8&255,h&255,g>>>24&255,g>>>16&255,g>>>8&255,g&255,c>>>24&255,c>>>16&255,c>>>8&255,c&255,x>>>24&255,x>>>16&255,x>>>8&255,x&255];return this.is224||k.push(l>>>24&255,l>>>16&255,l>>>8&255,l&255),k},p.prototype.array=p.prototype.digest,p.prototype.arrayBuffer=function(){this.finalize();var i=new ArrayBuffer(this.is224?28:32),u=new DataView(i);return u.setUint32(0,this.h0),u.setUint32(4,this.h1),u.setUint32(8,this.h2),u.setUint32(12,this.h3),u.setUint32(16,this.h4),u.setUint32(20,this.h5),u.setUint32(24,this.h6),this.is224||u.setUint32(28,this.h7),i};function F(i,u,m){var h,g=typeof i;if(g==="string"){var c=[],x=i.length,l=0,k;for(h=0;h<x;++h)k=i.charCodeAt(h),k<128?c[l++]=k:k<2048?(c[l++]=192|k>>>6,c[l++]=128|k&63):k<55296||k>=57344?(c[l++]=224|k>>>12,c[l++]=128|k>>>6&63,c[l++]=128|k&63):(k=65536+((k&1023)<<10|i.charCodeAt(++h)&1023),c[l++]=240|k>>>18,c[l++]=128|k>>>12&63,c[l++]=128|k>>>6&63,c[l++]=128|k&63);i=c}else if(g==="object"){if(i===null)throw new Error(t);if(f&&i.constructor===ArrayBuffer)i=new Uint8Array(i);else if(!Array.isArray(i)&&(!f||!ArrayBuffer.isView(i)))throw new Error(t)}else throw new Error(t);i.length>64&&(i=new p(u,!0).update(i).array());var M=[],I=[];for(h=0;h<64;++h){var L=i[h]||0;M[h]=92^L,I[h]=54^L}p.call(this,u,m),this.update(I),this.oKeyPad=M,this.inner=!0,this.sharedMemory=m}F.prototype=new p,F.prototype.finalize=function(){if(p.prototype.finalize.call(this),this.inner){this.inner=!1;var i=this.array();p.call(this,this.is224,this.sharedMemory),this.update(this.oKeyPad),this.update(i),p.prototype.finalize.call(this)}};var T=P();T.sha256=T,T.sha224=P(!0),T.sha256.hmac=O(),T.sha224.hmac=O(!0),n?ue.exports=T:(r.sha256=T.sha256,r.sha224=T.sha224,d&&define(function(){return T}))})()});var tr={};Ft(tr,{COCO_KEYPOINT_NAMES:()=>N,DEFAULT_MOVENET_LIGHTNING_URL:()=>Ee,ONLINE_TFJS_VERSION:()=>we,PoseCamera:()=>it,SDK_NAME:()=>Y,SDK_VERSION:()=>$,configure:()=>G,createPoseTracker:()=>Fe,defaultTfjsCdnUrls:()=>Ge,resolvePoseModel:()=>W,shouldShowWatermark:()=>le});var $="0.2.0",Y="posetracker-web";var z="https://movelytics-strapi-c78a339b7070.herokuapp.com",U=class extends Error{constructor(r,s){super(s);this.code=r;this.name="ConfigureError"}};async function G(t,e={}){let r=(e.baseUrl??z).replace(/\/$/,""),s={...t?{apiToken:t}:{},sdkName:Y,sdkVersion:$,targetPlatform:"web",poseModelProfile:e.poseModelProfile??"AdaptiveChoice",locale:e.locale,localVersions:e.localVersions},o;try{o=await fetch(`${r}/api/sdk/configure`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)})}catch(n){throw new U("network",`Handshake request failed: ${String(n)}`)}if(o.status===401||o.status===403)throw new U("invalid_token","Invalid, revoked or unauthorized API token.");if(o.status===429)throw new U("quota_exceeded","API call quota exceeded for the current plan.");if(!o.ok)throw new U("internal",`Handshake failed with HTTP ${o.status}.`);return await o.json()}var Ue=lt(Le(),1);var Re=lt(Le(),1),Ae="ptc1:";function De(t){return(0,Re.sha256)(`posetracker-sdk-cache:${t}`)}function It(t){let e=unescape(encodeURIComponent(t)),r=new Uint8Array(e.length);for(let s=0;s<e.length;s++)r[s]=e.charCodeAt(s);return r}function Lt(t){let e="";for(let r=0;r<t.length;r++)e+=String.fromCharCode(t[r]);return decodeURIComponent(escape(e))}function At(t){let e="";for(let r=0;r<t.length;r++)e+=t[r].toString(16).padStart(2,"0");return e}function Rt(t){if(t.length%2!==0||/[^0-9a-f]/.test(t))return null;let e=new Uint8Array(t.length/2);for(let r=0;r<e.length;r++)e[r]=parseInt(t.slice(r*2,r*2+2),16);return e}function ct(t,e){let r=new Uint8Array(t.length),s=0,o=0;for(;o<t.length;){let n=Re.sha256.array(`${e}:${s++}`);for(let d=0;d<n.length&&o<t.length;d++,o++)r[o]=t[o]^n[d]}return r}function he(t,e){return Ae+At(ct(It(t),e))}function pe(t,e){if(!t.startsWith(Ae))return null;let r=Rt(t.slice(Ae.length));if(!r)return null;try{return Lt(ct(r,e))}catch{return null}}var Oe="posetracker.web.";function X(){return typeof localStorage>"u"?null:{async getItem(t){try{return localStorage.getItem(Oe+t)}catch{return null}},async setItem(t,e){try{localStorage.setItem(Oe+t,e)}catch{}},async removeItem(t){try{localStorage.removeItem(Oe+t)}catch{}}}}function ut(){let t=X();return t?{read:e=>t.getItem(`file.${e}`),write:(e,r)=>t.setItem(`file.${e}`,r),remove:e=>t.removeItem(`file.${e}`)}:null}function ht(){let t=new Map;return{async read(e){return t.has(e)?t.get(e):null},async write(e,r){t.set(e,r)},async remove(e){t.delete(e)}}}function fe(){return ut()??ht()}var dt="posetracker.engine.guard.",J=class{constructor(e={}){this.lastError=null;this.files=e.fileStore!==void 0?e.fileStore:fe(),this.kv=e.keyValueStore!==void 0?e.keyValueStore:X(),this.fetchFn=e.fetchFn??fetch,this.onDiagnostic=e.onDiagnostic,this.onDiagnostic?.(`[posetracker-web] EngineLoader fileStore=${this.files?"yes":"none"} kv=${this.kv?"localStorage":"none"}`)}async clearGuard(e){if(!e||!this.kv)return;let r=`${dt}${e.version}.${e.sha256}`;await this.kv.removeItem(r).catch(()=>{})}async load(e,r,s){if(this.lastError=null,!e)return this.lastError="manifest has no engine descriptor",null;let o=`${dt}${e.version}.${e.sha256}`;s?.forceRetry&&await this.kv?.removeItem(o).catch(()=>{});let n=await this.kv?.getItem(o);if(n==="probing"||n==="failed")return await this.kv?.setItem(o,"failed"),this.lastError=`engine crash-guard blocked version=${e.version} (state=${n}) \u2014 call configure() again to force retry`,this.onDiagnostic?.(`[posetracker-web] ${this.lastError}`),null;let d=`engine-${e.version}.sealed`,f=await this.files?.read(d);if(f!=null){let a=pe(f,r);if(a!==null&&(0,Ue.sha256)(a)===e.sha256){let v=await this.evaluate(a,o);if(v)return this.onDiagnostic?.(`[posetracker-web] engine loaded from cache version=${e.version}`),{engine:v,source:"remote-cache"}}else this.onDiagnostic?.(`[posetracker-web] engine cache purged (unseal/integrity mismatch) key=${d}`),await this.files?.remove(d)}try{this.onDiagnostic?.(`[posetracker-web] downloading engine version=${e.version}\u2026`);let a=await this.fetchFn(e.signedUrl);if(!a.ok)throw new Error(`HTTP ${a.status}`);let v=await a.text(),w=(0,Ue.sha256)(v);if(w!==e.sha256)throw new Error(`integrity check failed (got ${w.slice(0,12)}\u2026 expected ${e.sha256.slice(0,12)}\u2026, bytes=${v.length})`);let E=await this.evaluate(v,o);if(E){try{await this.files?.write(d,he(v,r))}catch(b){this.onDiagnostic?.("[posetracker-web] engine cache write failed (non-fatal): "+(b instanceof Error?b.message:String(b)))}return this.onDiagnostic?.(`[posetracker-web] engine loaded from download version=${e.version} bytes=${v.length}`),{engine:E,source:"remote-download"}}}catch(a){this.lastError=a instanceof Error?a.message:String(a),this.onDiagnostic?.(`[posetracker-web] engine download/load failed: ${this.lastError}`)}return this.lastError||(this.lastError="engine evaluate returned null"),null}async evaluate(e,r){await this.kv?.setItem(r,"probing");try{let s={exports:{}};new Function("module","exports",e)(s,s.exports);let n=s.exports.createEngine;if(typeof n!="function")throw new Error(`engine bundle does not export createEngine() (got ${typeof n}, keys=${Object.keys(s.exports).join(",")})`);let d=n();return await this.kv?.setItem(r,"passed"),d}catch(s){return this.lastError="engine evaluate failed: "+(s instanceof Error?s.message:String(s)),this.onDiagnostic?.(`[posetracker-web] ${this.lastError}`),await this.kv?.setItem(r,"failed"),null}}};var Ne="posetracker.track.queue",Dt=100,A=class extends Error{constructor(r,s){super(s);this.code=r;this.name="TrackError"}},Q=class{constructor(e={}){this.baseUrl=(e.baseUrl??z).replace(/\/$/,""),this.kv=e.keyValueStore!==void 0?e.keyValueStore:X(),this.fetchFn=e.fetchFn??fetch}async trackMetered(e){return this.post({event:e.event??"camera_start",apiToken:e.apiToken,platform:"web",sdkVersion:$,params:e.params})}async trackAnonymous(e={}){let r={event:e.event??"camera_start",platform:"web",sdkVersion:$,params:e.params,queuedAtMs:Date.now()};try{await this.post({...r}),this.flushQueue()}catch{await this.enqueue(r)}}async flushQueue(){let e=await this.readQueue();if(e.length===0)return;let r=[];for(let s of e)try{await this.post({...s,params:{...s.params??{},queuedAtMs:s.queuedAtMs}})}catch{r.push(s)}await this.writeQueue(r)}async post(e){let r;try{r=await this.fetchFn(`${this.baseUrl}/api/sdk/track`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})}catch(s){throw new A("network",`Usage tracking request failed: ${String(s)}`)}if(r.status===401||r.status===403)throw new A("invalid_token","Invalid, revoked or unauthorized API token.");if(r.status===429)throw new A("quota_exceeded","API call quota exceeded for the current plan.");if(!r.ok)throw new A("internal",`Usage tracking failed with HTTP ${r.status}.`);return await r.json()}async readQueue(){try{let e=await this.kv?.getItem(Ne);if(!e)return[];let r=JSON.parse(e);return Array.isArray(r)?r:[]}catch{return[]}}async writeQueue(e){try{e.length===0?await this.kv?.removeItem(Ne):await this.kv?.setItem(Ne,JSON.stringify(e.slice(-Dt)))}catch{}}async enqueue(e){let r=await this.readQueue();r.push(e),await this.writeQueue(r)}};var K=class extends Error{constructor(r,s){super(s);this.code=r;this.name="SkeletonFetchError"}};async function He(t,e={}){let r=t.trim();if(!r||r==="true"||r==="false")throw new K("invalid","skeleton uuid is required");let s=(e.baseUrl??z).replace(/\/$/,""),o;try{o=await fetch(`${s}/api/sdk/skeleton?uuid=${encodeURIComponent(r)}`)}catch(d){throw new K("network",`Skeleton fetch failed: ${String(d)}`)}if(o.status===404)throw new K("not_found",`Skeleton '${r}' not found`);if(!o.ok)throw new K("network",`Skeleton fetch HTTP ${o.status}`);let n=await o.json();if(!n?.keypoints||!n?.keypoint_lines||!n?.circles||!n?.lines)throw new K("invalid","Skeleton payload incomplete");return{keypoints:n.keypoints,keypoint_lines:n.keypoint_lines,keypoint_angles:n.keypoint_angles??[],circles:n.circles,lines:n.lines,angles:n.angles}}async function Be(t={}){if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw new Error("getUserMedia is not available in this environment");let e=t.facingMode??"user",r={audio:!1,video:{facingMode:e,width:t.idealWidth?{ideal:t.idealWidth}:void 0,height:t.idealHeight?{ideal:t.idealHeight}:void 0,frameRate:t.idealFrameRate?{ideal:t.idealFrameRate}:void 0}};try{return await navigator.mediaDevices.getUserMedia(r)}catch{return navigator.mediaDevices.getUserMedia({audio:!1,video:{facingMode:e}})}}function Ve(t){if(t)for(let e of t.getTracks())try{e.stop()}catch{}}function Z(t){return typeof HTMLVideoElement<"u"&&t instanceof HTMLVideoElement}function pt(t){return typeof HTMLImageElement<"u"&&t instanceof HTMLImageElement}function $e(t){return typeof ImageBitmap<"u"&&t instanceof ImageBitmap}function me(t){return $e(t)?{width:t.width||0,height:t.height||0}:Z(t)?{width:t.videoWidth||0,height:t.videoHeight||0}:{width:t.naturalWidth||t.width||0,height:t.naturalHeight||t.height||0}}async function ge(t){if(typeof t=="string")return{url:t,revoke:()=>{}};let e=URL.createObjectURL(t);return{url:e,revoke:()=>{try{URL.revokeObjectURL(e)}catch{}}}}function Ke(t,e=15e3){return new Promise((r,s)=>{if(t.readyState>=2&&t.videoWidth>0){r();return}let o=()=>{f(),r()},n=()=>{f(),s(new Error("Failed to load video source"))},d=setTimeout(()=>{f(),s(new Error("Timed out waiting for video metadata"))},e),f=()=>{clearTimeout(d),t.removeEventListener("loadeddata",o),t.removeEventListener("error",n)};t.addEventListener("loadeddata",o),t.addEventListener("error",n)})}function ye(t,e=15e3){return new Promise((r,s)=>{if(t.complete&&t.naturalWidth>0){r();return}let o=()=>{f(),r()},n=()=>{f(),s(new Error("Failed to load image source"))},d=setTimeout(()=>{f(),s(new Error("Timed out waiting for image"))},e),f=()=>{clearTimeout(d),t.removeEventListener("load",o),t.removeEventListener("error",n)};t.addEventListener("load",o),t.addEventListener("error",n)})}async function ft(t){let e=document.createElement("canvas");e.width=t.width,e.height=t.height;let r=e.getContext("2d");if(!r)throw new Error("2d context unavailable");r.drawImage(t,0,0);let s=await new Promise((o,n)=>{e.toBlob(d=>d?o(d):n(new Error("toBlob failed")),"image/png")});return ge(s)}function ve(t,e){if(t&&typeof t=="object"&&"type"in t)return t;let r=t==="video"||t==="image"||t==="camera"?t:"camera";if(r==="camera")return{type:"camera",facingMode:e?.facingMode};let s=e?.sourceFile??e?.sourceUrl;if(!s)throw new Error(`PoseSource type "${r}" requires sourceUrl or sourceFile (or pass a full PoseSource object)`);return r==="video"?{type:"video",src:s}:{type:"image",src:s}}var je={face_squat:"squat",face_pushup:"push_up",face_plank:"plank",face_lunge:"lunge",face_jumping_jack:"jumping_jack",face_low_impact_jack:"low_impact_jack",face_balance_leg:"balance_leg",face_balance_leg_left:"balance_leg_left",face_balance_leg_right:"balance_leg_right",jump:"air_time_jump"};function We(t){return je[t]??t}function xe(t,e){let r=e.find(n=>n.id===t);if(r)return r;let s=We(t),o=Object.entries(je).filter(([,n])=>n===s).map(([n])=>n);for(let n of o){let d=e.find(f=>f.id===n);if(d)return d}return e.find(n=>We(n.id)===s)}var Ot={left_knee:"from_hip_to_ankle",right_knee:"from_hip_to_ankle",left_hip:"from_knee_to_shoulder",right_hip:"from_knee_to_shoulder",left_shoulder:"from_hip_to_elbow",right_shoulder:"from_hip_to_elbow",left_elbow:"from_shoulder_to_wrist",right_elbow:"from_shoulder_to_wrist"};function Ut(t){let e={left_side:{},right_side:{}};for(let r of t){if(r.side!=="left"&&r.side!=="right")continue;let s=r.side==="left"?e.left_side:e.right_side,n=`${r.id.replace(/^(left_|right_)/,"")}_angle`,d=Ot[r.id]??"value";s[n]||(s[n]={}),s[n][d]=r.degrees,s[n][`score_${d}`]=r.score}return e}function ze(t){switch(t.type){case"initialization":return{type:"initialization",message:t.step==="configuring"?"checking you plan and access":t.message??Nt(t.step),ready:t.ready,step:t.step,...t.mode!=null?{mode:t.mode}:{},...t.acceleration!=null?{acceleration:t.acceleration}:{}};case"error":return{type:"error",error:t.code,message:t.message};case"warning":return{type:"warning",error:t.code,message:t.message};case"keypoints":return{type:"keypoints",data:t.keypoints.map(e=>({name:e.name,x:e.x,y:e.y,...e.z!=null?{z:e.z}:{},score:e.score})),score:t.score,timestampMs:t.timestampMs};case"stats":return{type:"stats",fps:t.fps,medianInferenceMs:t.medianInferenceMs,backend:t.backend,keypointsAbove03:t.keypointsAbove03,meanScore:t.meanScore,videoSize:t.videoSize,timestampMs:t.timestampMs};case"angles":return{type:"angles",data:Ut(t.angles),timestampMs:t.timestampMs};case"counter":return{type:"counter",current_count:t.count,...t.formScore!=null?{form_score:{score:t.formScore.score,avg_score:t.formScore.average,grade:t.formScore.grade}}:{},...t.referenceScore!=null?{reference_score:{overallScore:t.referenceScore}}:{},timestampMs:t.timestampMs};case"posture":return{type:"posture",message:t.hint,ready:t.ready,direction:t.direction??"",requirements:{missingKeypoints:t.missingKeypoints},timestampMs:t.timestampMs};case"progression":return{type:"progression",value:t.value,timestampMs:t.timestampMs};case"recommendations":return{type:"recommendations",data:t.recommendations,timestampMs:t.timestampMs};case"form_score":return{type:"form_score",score:t.score,avg_score:t.average,grade:t.grade,timestampMs:t.timestampMs};case"exercise_summary":return{type:"exercise_summary",exercise:t.exercise,counter:t.counter,avg_rep_score:t.averageFormScore,avg_similarity:t.averageSimilarity,grade:t.grade,history:t.history,durationMs:t.durationMs,timestampMs:t.timestampMs};case"jump_calibration":return{type:"jump_calibration",calibrated:t.calibrated,cmPerPixel:t.cmPerPixel,baselineY:t.baselineY,visibleHips:t.visibleHips,message:t.message,timestampMs:t.timestampMs};case"jump_started":return{type:"jump_started",message:t.message,timestampMs:t.timestampMs};case"jump_height":{let{type:e,timestampMs:r,...s}=t;return{type:e,...s,timestampMs:r}}case"jump_discarded":return{type:"jump_discarded",reason:t.reason,userMessage:t.userMessage,timestampMs:t.timestampMs};case"jump_result":{let{type:e,timestampMs:r,...s}=t;return{type:e,...s,timestampMs:r}}case"jump_summary":{let{type:e,timestampMs:r,...s}=t;return{type:e,...s,timestampMs:r}}case"performance_warning":return{type:"error",error:t.code,message:t.message,meanFps:t.meanFps,thresholdFps:t.thresholdFps,activeProfile:t.activeProfile,medianInferenceMs:t.medianInferenceMs,videoSize:t.videoSize,timestampMs:t.timestampMs};case"quality_changed":return{type:"warning",error:"quality_downgraded",message:t.detail,previousProfile:t.previousProfile,activeProfile:t.activeProfile,reason:t.reason,timestampMs:t.timestampMs};case"runtime_download_progress":return{type:"initialization",message:`downloading pose runtime ${t.completedParts+1}/${t.totalParts}`,ready:!1,step:"downloading",part:t.part,completedParts:t.completedParts,totalParts:t.totalParts,timestampMs:t.timestampMs};default:return{type:"unknown",event:t}}}function Nt(t){switch(t){case"configuring":return"checking you plan and access";case"downloading":return"downloading engine";case"warming":return"loading pose model";case"ready":return"running";default:return t}}var N=["nose","left_eye","right_eye","left_ear","right_ear","left_shoulder","right_shoulder","left_elbow","right_elbow","left_wrist","right_wrist","left_hip","right_hip","left_knee","right_knee","left_ankle","right_ankle"];var we="4.22.0",Ht="https://cdn.jsdelivr.net/npm";function Ge(t=Ht,e=we){let r=t.replace(/\/$/,"");return{scriptUrls:[`${r}/@tensorflow/tfjs-core@${e}/dist/tf-core.min.js`,`${r}/@tensorflow/tfjs-converter@${e}/dist/tf-converter.min.js`,`${r}/@tensorflow/tfjs-backend-webgl@${e}/dist/tf-backend-webgl.min.js`,`${r}/@tensorflow/tfjs-backend-wasm@${e}/dist/tf-backend-wasm.min.js`],wasmPath:`${r}/@tensorflow/tfjs-backend-wasm@${e}/dist/`}}var ke=null;function Bt(t){try{t.env().set("WEBGL_CPU_FORWARD",!1)}catch{}try{t.env().set("WEBGL_PACK",!1)}catch{}try{t.env().set("WEBGL_FORCE_F16_TEXTURES",!1)}catch{}try{t.env().set("WEBGL_RENDER_FLOAT32_ENABLED",!1)}catch{}try{t.env().set("WEBGL_FLUSH_THRESHOLD",1.75)}catch{}}function Vt(){return new Function("s","return import(s)")("@tensorflow/tfjs")}async function ee(){if(ke)return ke;if(typeof window<"u"&&window.tf)return ke=window.tf,window.tf;try{let t=await Vt();return ke=t,t}catch{}throw new Error("TensorFlow.js not found. Install peer `@tensorflow/tfjs` or load CDN scripts (see README) so `window.tf` is available.")}async function te(t){Bt(t);try{let e=await t.setBackend("webgl");if(await t.ready(),e!==!1&&t.getBackend()==="webgl")return"webgl"}catch{}return await t.setBackend("cpu"),await t.ready(),"cpu"}var mt="2.1.3",$t="https://cdn.jsdelivr.net/npm",re=null,se=null;function gt(t=$t,e=mt){return`${t.replace(/\/$/,"")}/@tensorflow-models/pose-detection@${e}/dist/pose-detection.min.js`}function Kt(){return new Function("s","return import(s)")("@tensorflow-models/pose-detection")}function qe(){if(typeof window>"u")return null;let t=window.poseDetection;return t&&typeof t.createDetector=="function"&&t.SupportedModels?.BlazePose?t:null}function Wt(t){if(typeof document>"u")return Promise.reject(new Error("Cannot inject pose-detection outside a browser document"));let e=qe();return e?Promise.resolve(e):se||(se=new Promise((r,s)=>{let n=document.querySelector('script[data-pt-pose-detection="1"]'),d=()=>{let a=qe();if(a){r(a);return}s(new Error("pose-detection CDN script loaded but `window.poseDetection` is missing. Check script order (TF.js first) and network."))};if(n){if(n.dataset.ptLoaded==="1"){d();return}n.addEventListener("load",d,{once:!0}),n.addEventListener("error",()=>s(new Error(`Failed to load pose-detection from ${n.src}`)),{once:!0});return}let f=document.createElement("script");f.src=t,f.async=!0,f.dataset.ptPoseDetection="1",f.onload=()=>{f.dataset.ptLoaded="1",d()},f.onerror=()=>{se=null,s(new Error(`Failed to load pose-detection from ${t}`))},document.head.appendChild(f)}),se)}async function Ye(t){if(re)return re;let e=qe();if(e)return re=e,e;try{let s=await Kt();return re=s,s}catch{}if(t?.allowCdn!==!1&&typeof window<"u"&&typeof document<"u"){let s=gt(t?.cdnBase,t?.version),o=await Wt(s);return re=o,o}throw new Error('BlazePose requires optional peer `@tensorflow-models/pose-detection`. Install it, load the CDN script so `window.poseDetection` exists, or use model="movenet" / pass a TF.js modelUrl.')}function jt(t){return typeof HTMLVideoElement<"u"&&t instanceof HTMLVideoElement?{vw:t.videoWidth||0,vh:t.videoHeight||0}:typeof HTMLImageElement<"u"&&t instanceof HTMLImageElement?{vw:t.naturalWidth||t.width||0,vh:t.naturalHeight||t.height||0}:typeof HTMLCanvasElement<"u"&&t instanceof HTMLCanvasElement?{vw:t.width||0,vh:t.height||0}:{vw:t.width||0,vh:t.height||0}}var zt={nose:"nose",left_eye:"left_eye",right_eye:"right_eye",left_ear:"left_ear",right_ear:"right_ear",left_shoulder:"left_shoulder",right_shoulder:"right_shoulder",left_elbow:"left_elbow",right_elbow:"right_elbow",left_wrist:"left_wrist",right_wrist:"right_wrist",left_hip:"left_hip",right_hip:"right_hip",left_knee:"left_knee",right_knee:"right_knee",left_ankle:"left_ankle",right_ankle:"right_ankle"},oe=class{constructor(e){this.modelId="blazepose";this.detector=null;this.backend=null;this.modelType="lite"}getBackend(){return this.backend}async load(){let e=await ee();this.backend=await te(e);let r=await Ye();this.detector=await r.createDetector(r.SupportedModels.BlazePose,{runtime:"tfjs",modelType:this.modelType,enableSmoothing:!0})}async estimate(e,r){if(!this.detector)throw new Error("BlazePose adapter not loaded");let s=jt(e);if(!(s.vw>0&&s.vh>0))return null;let o=performance.now(),n=await this.detector.estimatePoses(e,{flipHorizontal:!1,maxPoses:1}),d=performance.now()-o,f=n[0];if(!f?.keypoints?.length)return{keypoints:N.map(p=>({name:p,x:0,y:0,score:0})),score:0,inferenceMs:d,videoKeypoints:N.map(p=>({name:p,xPx:0,yPx:0,score:0})),letterbox:{offsetX:0,offsetY:0,drawW:s.vw,drawH:s.vh,vw:s.vw,vh:s.vh}};let a=s.vw||1,v=s.vh||1,w=r.displayWidth||1,E=r.displayHeight||1,b=new Map;for(let p of f.keypoints){let F=String(p.name||"").toLowerCase(),T=zt[F];T&&b.set(T,{x:p.x,y:p.y,score:typeof p.score=="number"?p.score:0})}let y=N.map(p=>{let F=b.get(p);return{name:p,xPx:F?.x??0,yPx:F?.y??0,score:F?.score??0}}),_=Math.max(w/a,E/v),P=(w-a*_)/2,R=(E-v*_)/2,D=0;return{keypoints:y.map(p=>{let F=p.xPx*_+P,T=p.yPx*_+R,i=w>0?F/w:0,u=E>0?T/E:0;return r.facingMode==="user"&&(i=1-i),D+=p.score,{name:p.name,x:Math.min(1,Math.max(0,i)),y:Math.min(1,Math.max(0,u)),score:p.score}}),score:D/17,inferenceMs:d,videoKeypoints:y,letterbox:{offsetX:0,offsetY:0,drawW:a,drawH:v,vw:a,vh:v}}}dispose(){try{this.detector?.dispose?.()}catch{}this.detector=null}};function yt(t){return typeof HTMLVideoElement<"u"&&t instanceof HTMLVideoElement?{vw:t.videoWidth||0,vh:t.videoHeight||0}:typeof HTMLImageElement<"u"&&t instanceof HTMLImageElement?{vw:t.naturalWidth||t.width||0,vh:t.naturalHeight||t.height||0}:typeof HTMLCanvasElement<"u"&&t instanceof HTMLCanvasElement?{vw:t.width||0,vh:t.height||0}:{vw:t.width||0,vh:t.height||0}}var C=192,Se=.5;function Gt(t,e,r){let s=t*C,o=e*C;return{x:(s-r.offsetX)*(r.vw/r.drawW),y:(o-r.offsetY)*(r.vh/r.drawH)}}function vt(t,e,r,s,o){let n=Math.max(r/o.vw,s/o.vh),d=(r-o.vw*n)/2,f=(s-o.vh*n)/2;return{x:t*n+d,y:e*n+f}}var ie=class{constructor(e){this.tf=null;this.model=null;this.backend=null;this.offscreen=null;this.offCtx=null;this.smoothed=null;this.letterbox={offsetX:0,offsetY:0,drawW:C,drawH:C,vw:1,vh:1};if(!e.resolved.modelUrl)throw new Error(e.resolved.unsupportedReason??"MoveNet requires a modelUrl");this.modelId=e.resolved.modelId,this.modelUrl=e.resolved.modelUrl}getBackend(){return this.backend}async load(){this.tf=await ee(),this.backend=await te(this.tf),this.model=await this.tf.loadGraphModel(this.modelUrl);let e=this.tf.zeros([1,C,C,3],"int32"),r=this.model.execute(e);(Array.isArray(r)?r[0]:r).dataSync(),e.dispose(),Array.isArray(r)?r.forEach(o=>o.dispose()):r.dispose()}poseCanvasCtx(){if(this.offscreen||(this.offscreen=document.createElement("canvas"),this.offscreen.width=C,this.offscreen.height=C,this.offCtx=this.offscreen.getContext("2d",{willReadFrequently:!0})),!this.offCtx)throw new Error("2d context unavailable");return this.offCtx}prepareInput(e){let{vw:r,vh:s}=yt(e),o=r||1,n=s||1,d=Math.min(C/o,C/n),f=o*d,a=n*d,v=(C-f)/2,w=(C-a)/2;this.letterbox={offsetX:v,offsetY:w,drawW:f,drawH:a,vw:o,vh:n};let E=this.poseCanvasCtx();return E.fillStyle="#000",E.fillRect(0,0,C,C),E.drawImage(e,0,0,o,n,v,w,f,a),this.offscreen}smooth(e){if(!this.smoothed)return this.smoothed=e.map(r=>({...r})),this.smoothed;for(let r=0;r<e.length;r++)e[r].score<.1||(this.smoothed[r].xPx=Se*e[r].xPx+(1-Se)*this.smoothed[r].xPx,this.smoothed[r].yPx=Se*e[r].yPx+(1-Se)*this.smoothed[r].yPx,this.smoothed[r].score=e[r].score);return this.smoothed}async estimate(e,r){if(!this.tf||!this.model)throw new Error("MoveNet adapter not loaded");let s=yt(e);if(!(s.vw>0&&s.vh>0))return null;let o=performance.now(),n=this.prepareInput(e),d=this.tf.tidy(()=>this.tf.expandDims(this.tf.browser.fromPixels(n),0)),f=this.model.execute(d),v=(Array.isArray(f)?f[0]:f).dataSync();d.dispose(),Array.isArray(f)?f.forEach(p=>p.dispose()):f.dispose();let w=performance.now()-o,E=this.letterbox,b=r.displayWidth||1,y=r.displayHeight||1,_=[],P=0;for(let p=0;p<17;p++){let F=Math.min(1,Math.max(0,v[p*3])),T=Math.min(1,Math.max(0,v[p*3+1])),i=v[p*3+2],u=Gt(T,F,E);_.push({name:N[p],xPx:u.x,yPx:u.y,score:i}),P+=i}let D=this.smooth(_).map((p,F)=>({name:N[F],xPx:p.xPx,yPx:p.yPx,score:p.score})),O=D.map(p=>{let F=vt(p.xPx,p.yPx,b,y,E),T=b>0?F.x/b:0,i=y>0?F.y/y:0;return r.facingMode==="user"&&(T=1-T),{name:p.name,x:Math.min(1,Math.max(0,T)),y:Math.min(1,Math.max(0,i)),score:p.score}});return{raw:v,keypoints:O,score:P/17,inferenceMs:w,videoKeypoints:D,letterbox:E}}dispose(){try{this.model?.dispose()}catch{}this.model=null,this.smoothed=null,this.offscreen=null,this.offCtx=null}};function Je(t,e,r,s){return t.map(o=>{let n=vt(o.xPx,o.yPx,r,s,e);return{name:o.name,dx:n.x,dy:n.y,score:o.score}})}function Xe(t){let{resolved:e}=t;if(e.kind==="unsupported"||!e.modelUrl&&e.kind!=="blazepose")throw new Error(e.unsupportedReason??`Model "${e.modelId}" is unavailable.`);return e.kind==="blazepose"?new oe(t):new ie(t)}var Ee="https://app.posetracker.com/scripts/tmp_model_to_remove.json";function W(t={}){let e=typeof t.modelUrl=="string"&&t.modelUrl.trim().length>0?t.modelUrl.trim():null;if(e)return{modelId:typeof t.model=="string"&&t.model.trim().length>0?t.model.trim():"custom",kind:"custom-graph",modelUrl:e};let r=(t.model??"movenet").trim().toLowerCase();return r==="movenet"||r==="movenet-singlepose-lightning"||r==="lightning"?{modelId:"movenet-singlepose-lightning",kind:"movenet-graph",modelUrl:Ee}:r==="blazepose"?{modelId:"blazepose",kind:"blazepose",modelUrl:null}:{modelId:r,kind:"unsupported",modelUrl:null,unsupportedReason:`Unknown model "${t.model}". Use "movenet" (default), "blazepose", or pass modelUrl.`}}var ne="AI Loading",Qe="https://docs.posetracker.com/logo/light.png";var qt=`
2
2
  .pt-root {
3
3
  position: relative; width: 100%; height: 100%; min-height: 240px;
4
4
  background: #000; overflow: hidden; isolation: isolate;
5
5
  }
6
- .pt-root video, .pt-root canvas.pt-overlay {
6
+ .pt-root video, .pt-root img.pt-still, .pt-root canvas.pt-overlay {
7
7
  position: absolute; inset: 0; width: 100%; height: 100%;
8
8
  object-fit: cover; opacity: 0; transition: opacity 180ms ease-out;
9
9
  }
10
- .pt-root video { z-index: 1; background: #000; }
10
+ .pt-root video, .pt-root img.pt-still { z-index: 1; background: #000; }
11
11
  .pt-root canvas.pt-overlay { z-index: 2; pointer-events: none; }
12
12
  .pt-boot {
13
13
  position: absolute; inset: 0; z-index: 4;
@@ -63,8 +63,9 @@
63
63
  border-radius: 4px;
64
64
  }
65
65
  .pt-placement.show { display: block; }
66
- `,ct=!1;function Ut(){if(ct||typeof document>"u")return;let t=document.createElement("style");t.setAttribute("data-posetracker","shell"),t.textContent=Nt,document.head.appendChild(t),ct=!0}function ze(t,e={}){Ut();let r=e.loadingText&&e.loadingText.trim()||oe,s=e.logoUrl??je,i=document.createElement("div");i.className="pt-root",i.innerHTML=`
66
+ `,xt=!1;function Yt(){if(xt||typeof document>"u")return;let t=document.createElement("style");t.setAttribute("data-posetracker","shell"),t.textContent=qt,document.head.appendChild(t),xt=!0}function Ze(t,e={}){Yt();let r=e.loadingText&&e.loadingText.trim()||ne,s=e.logoUrl??Qe,o=document.createElement("div");o.className="pt-root",o.innerHTML=`
67
67
  <video playsinline muted autoplay></video>
68
+ <img class="pt-still" alt="" draggable="false" />
68
69
  <canvas class="pt-overlay"></canvas>
69
70
  <div class="pt-boot">
70
71
  <div class="pt-boot-powered">Powered by</div>
@@ -78,7 +79,7 @@
78
79
  <img class="pt-wm-logo" alt="PoseTracker" src="${s}" />
79
80
  </div>
80
81
  <div class="pt-hud"></div>
81
- `,t.appendChild(i);let n=i.querySelector("video"),p=i.querySelector("canvas.pt-overlay"),g=i.querySelector(".pt-boot"),a=i.querySelector(".pt-boot-msg"),S=i.querySelector(".pt-wm"),b=i.querySelector(".pt-hud"),_=i.querySelector(".pt-placement");return{root:i,video:n,canvas:p,boot:g,bootMsg:a,watermark:S,hud:b,placement:_,setBootMessage(k,y=!1){a.textContent=k,a.classList.toggle("is-error",y)},setCameraVisible(k){n.style.opacity=k?"1":"0",p.style.opacity=k?"1":"0",g.classList.toggle("hide",k),k||(a.textContent=r,a.classList.remove("is-error"))},setWatermarkVisible(k){S.classList.toggle("show",k)},setHud(k,y){b.classList.toggle("debug",y),b.textContent=k},setPlacementVisible(k,y=10){if(_.classList.toggle("show",k),k){let C=Math.max(0,Math.min(40,y));_.style.left=`${C}%`,_.style.top=`${C}%`,_.style.right=`${C}%`,_.style.bottom=`${C}%`}},applyMirror(k){let y=k==="user"?"scaleX(-1)":"none";n.style.transform=y,p.style.transform=y},destroy(){i.remove()}}}var Ge={keypoints:["nose","left_eye","right_eye","left_ear","right_ear","left_shoulder","right_shoulder","left_elbow","right_elbow","left_wrist","right_wrist","left_hip","right_hip","left_knee","right_knee","left_ankle","right_ankle"],keypoint_lines:["right_shoulder||left_shoulder","right_hip||left_hip","right_hip||right_shoulder","right_hip||right_knee","right_ankle||right_knee","right_shoulder||right_elbow","right_wrist||right_elbow","left_hip||left_shoulder","left_hip||left_knee","left_ankle||left_knee","left_shoulder||left_elbow","left_wrist||left_elbow"],keypoint_angles:[],angles:{fontColor:"#000000",strokeColor:"#FFC300"},circles:{circleFillColor:"#010A73",circleStrokeColor:"#FFC300",strokeWidth:"4",radius:"8"},lines:{lineStrokeColor:"#010A73",strokeWidth:"4"}};var qe=.3;function Ye(t,e,r,s,i=!0,n){if(t.canvas.width!==r&&(t.canvas.width=r),t.canvas.height!==s&&(t.canvas.height=s),t.clearRect(0,0,r,s),!i)return;let p=n??Ge,g={};for(let T of e)g[T.name]=T;let a=p.lines.lineStrokeColor,S=Number(p.lines.strokeWidth);for(let T of p.keypoint_lines){let[N,W]=String(T).split("||"),m=g[N],x=g[W];!m||!x||m.score<=qe||x.score<=qe||(t.beginPath(),t.moveTo(m.dx,m.dy),t.lineTo(x.dx,x.dy),t.lineWidth=S,t.strokeStyle=a,t.stroke())}let b=p.circles.circleFillColor,_=p.circles.circleStrokeColor,k=Number(p.circles.strokeWidth),y=Number(p.circles.radius),C=new Set(p.keypoints);for(let T of e)!C.has(T.name)||T.score<=qe||(t.beginPath(),t.arc(T.dx,T.dy,y,0,Math.PI*2),t.fillStyle=b,t.fill(),t.lineWidth=k,t.strokeStyle=_,t.stroke())}var dt={angles:!1,recommendations:!1,progression:!1,keypoints:!1,minGrade:null},Ht=new Set(["angles","recommendations","progression","keypoints","minGrade"]),$t={blazepose:'BlazePose as a features flag (use options.model = "blazepose" instead)',poseEngine:"pose engine selection (MediaPipe/PoseLandmarker)",mediapipeModel:"MediaPipe model selection",poseBackend:"pose backend selection",runInWorker:"worker thread selection"},ie="You cannot use developer features. (visit: https://posetracker.gitbook.io/posetracker-api/tracking-endpoint)",Je="Invalid params. Please refer to the documentation and set token=YOUR API_KEY et exercise=A correct exercise. (visit: https://posetracker.gitbook.io/posetracker-api/tracking-endpoint)";function xe(t){let e=$t[t]??`'${t}'`;return`The '${t}' option (${e}) is not available as a features flag. Remove the option, or use options.model / modelUrl for model selection. (visit: https://posetracker.gitbook.io/posetracker-api/tracking-endpoint)`}function Xe(t){if(!t)return{features:{...dt},unsupportedKeys:[]};let e=Object.keys(t).filter(r=>!Ht.has(r));return{features:{angles:t.angles===!0,recommendations:t.recommendations===!0,progression:t.progression===!0,keypoints:t.keypoints===!0,minGrade:t.minGrade??null},unsupportedKeys:e}}function ke(t,e){let r=[];return t.angles&&r.push("angles"),t.recommendations&&r.push("recommendations"),t.progression&&r.push("progression"),t.keypoints&&e.withExercise&&r.push("keypoints"),r}function pt(t){return typeof t=="string"&&t.length>0&&t!=="free"}function ne(t){return!pt(t)}var ve="session.sealed",we="engine.version",Kt=30;function Bt(t){if(typeof t=="string"){let e=document.querySelector(t);if(!e)throw new Error(`PoseTracker mount target not found: ${t}`);return e}return t}function Wt(t){if(!t.length)return null;let e=[...t].sort((r,s)=>r-s);return e[Math.floor(e.length/2)]??null}function be(t){return t.facingMode?t.facingMode:t.position==="back"?"environment":"user"}var Se=class{constructor(e,r={}){this.status="idle";this.mode="keypoints-only";this.lastError=null;this.manifest=null;this.engine=null;this.engineSource=null;this.session=null;this.currentExerciseId=null;this.listeners=new Set;this.typedListeners=new Map;this.messageListeners=new Set;this.stateListeners=new Set;this.preloadPromise=null;this.coldStartMode="basic";this.configurePromise=null;this.handshakePromise=null;this.meteredSessionState="idle";this.lastCameraStartInfo=null;this.sessionErrorStreak=0;this.featureGateReported={unsupported:!1,freeBlock:!1,missingToken:!1};this.keypointsSuppressionLogged=!1;this.shell=null;this.stream=null;this.adapter=null;this.running=!1;this.busy=!1;this.loopToken=0;this.cameraRevealed=!1;this.disposed=!1;this.skeletonDef=null;this.acceleration={state:"unknown",runtime:"unknown",backend:null,glRenderer:null,medianInferenceMs:null};this.inferMs=[];this.fpsWindow=0;this.fpsTimer=0;let s=e??(typeof r.apiToken=="string"?r.apiToken:null)??null;this.opts={...r,onDiagnostic:r.onDiagnostic},this.apiToken=s;let i=Xe(r.features);this.features=i.features,this.unsupportedFeatureKeys=i.unsupportedKeys,this.resolved=V({model:r.model,modelUrl:r.modelUrl}),this.skeletonDef=r.skeletonDef??null,this.coldStartMode=r.coldStart==="full"?"full":"basic",this.files=r.fileStore!==void 0?r.fileStore:he(),this.engineLoader=r.engineLoader??new Y({fileStore:this.files,onDiagnostic:this.opts.onDiagnostic}),this.tracker=r.usageTracker??new X({baseUrl:r.baseUrl}),this.opts.onDiagnostic?.(`[posetracker-web] client created hasApiToken=${!!this.apiToken} features=${JSON.stringify(this.features)}`)}getStatus(){return this.status}getMode(){return this.mode}getError(){return this.lastError}getManifest(){return this.manifest}getPlanType(){return this.manifest?.plan?.plan??null}getFeatures(){return{...this.features}}getEngineSource(){return this.engineSource}getAcceleration(){return this.acceleration.state}getAccelerationDiagnostics(){return{...this.acceleration}}getResolvedModel(){return this.resolved}getColdStartMode(){return this.coldStartMode}addEventListener(e){return this.listeners.add(e),()=>this.listeners.delete(e)}on(e,r){if(e==="*")return this.listeners.add(r),()=>this.listeners.delete(r);let s=this.typedListeners.get(e);return s||(s=new Set,this.typedListeners.set(e,s)),s.add(r),()=>s.delete(r)}addMessageListener(e){return this.messageListeners.add(e),()=>this.messageListeners.delete(e)}onStateChange(e){return this.stateListeners.add(e),()=>this.stateListeners.delete(e)}mount(e){if(this.disposed)throw new Error("PoseTracker disposed");this.shell&&this.shell.destroy();let r=Bt(e);r.innerHTML="",this.shell=ze(r,{loadingText:this.opts.loadingText??oe}),this.shell.setCameraVisible(!1),this.cameraRevealed=!1,this.resolveSkeletonFromOptions()}preload(e){let r=e?.coldStart==="full"?"full":"basic";if(this.coldStartMode=r,this.status==="ready"&&this.preloadPromise)return this.preloadPromise.then(()=>this.ensureColdStartMode(r));if(!this.preloadPromise)this.preloadPromise=this.doPreload().then(()=>this.ensureColdStartMode(r)).catch(s=>{throw this.preloadPromise=null,s});else if(r==="full")return this.preloadPromise.then(()=>this.ensureColdStartMode("full"));return this.preloadPromise}warmup(e){return this.preload(e)}async start(){if(this.disposed)throw new Error("PoseTracker disposed");if(!this.shell)throw new Error("Call mount() before start()");await this.preload({coldStart:this.opts.coldStart==="basic"?"basic":"full"}),this.coldStartMode==="basic"&&await this.ensureColdStartMode("full"),this.beginLoop()}stop(){this.running=!1,this.loopToken+=1,this.busy=!1,Ie(this.stream),this.stream=null,this.shell&&(this.shell.video.srcObject=null,this.shell.setCameraVisible(!1),this.shell.setPlacementVisible(!1),this.cameraRevealed=!1,this.applyWatermark()),this.status!=="error"&&this.setStatus("idle")}async dispose(){this.stopExercise(),this.stop(),this.adapter?.dispose(),this.adapter=null,this.shell?.destroy(),this.shell=null,this.listeners.clear(),this.typedListeners.clear(),this.messageListeners.clear(),this.stateListeners.clear(),this.preloadPromise=null,this.configurePromise=null,this.handshakePromise=null,this.meteredSessionState="idle",this.lastCameraStartInfo=null,this.featureGateReported={unsupported:!1,freeBlock:!1,missingToken:!1},this.keypointsSuppressionLogged=!1,this.engine=null,this.engineSource=null,this.manifest=null,this.mode="keypoints-only",this.setStatus("idle"),this.disposed=!0}configure(e){return e!==void 0&&e!==this.apiToken&&(this.apiToken=e,this.opts.apiToken=e,this.configurePromise=null,this.handshakePromise=null,this.featureGateReported.freeBlock=!1,this.featureGateReported.missingToken=!1),this.mode!=="full-engine"&&(this.configurePromise=null),this.configurePromise||(this.configurePromise=this.tryConfigure({silentStatus:this.status==="ready",forceEngineRetry:!0}).then(r=>(r||(this.configurePromise=null),this.retryMeteredSessionIfRefused(),r)).catch(()=>(this.configurePromise=null,!1))),this.configurePromise}getAvailableExercises(){return this.mode==="full-engine"?this.manifest?.exercises??[]:[]}getAvailableCustomExercises(){return this.mode!=="full-engine"||!this.engine?.listCustomExercises?[]:this.engine.listCustomExercises()}startExercise(e,r={}){if(this.status!=="ready")throw new Error(`Cannot start exercise while status is '${this.status}' \u2014 call preload()/start() first.`);if(this.mode!=="full-engine"||!this.engine)throw new Error("Exercises require full-engine mode (validated API key). The SDK is running keypoints-only \u2014 call configure(apiToken) first.");if(this.meteredSessionState==="refused")throw new Error("API-key features are not available offline: PoseTracker could not track this session. Reconnect and retry.");if(this.unsupportedFeatureKeys.length>0){let n=xe(this.unsupportedFeatureKeys[0]);throw this.reportError({type:"error",code:"feature_not_supported",message:n}),new Error(n)}if(this.getPlanType()==="free"&&ke(this.features,{withExercise:!0}).length>0)throw this.reportError({type:"error",code:"free_plan_feature_blocked",message:ie}),new Error(ie);let s=this.getAvailableExercises(),i=ue(e,s);if(!i){let n=this.getAvailableCustomExercises(),p=n.find(a=>a.id===e)??ue(e,n);if(p){this.startCustomExercise(p,r);return}let g=`Exercise '${e}' is not available in V3 engine`;throw this.reportError({type:"error",code:"invalid_exercise",message:g}),new Error(g)}this.stopExercise(),this.currentExerciseId=e,this.keypointsSuppressionLogged=!1,this.session=this.engine.createSession({exercise:i,locale:this.opts.locale??"en",difficulty:r.difficulty,minGrade:this.features.minGrade??void 0,features:{angles:this.features.angles,recommendations:this.features.recommendations,progression:this.features.progression}},n=>this.emitFromSession(n))}startCustomExercise(e,r){if(!this.engine?.createCustomSession)throw new Error(`The cached engine bundle is too old for custom exercise '${e.id}' \u2014 reconnect so the SDK can update it.`);if(e.id==="jump_analysis"&&(!r.userHeightCm||r.userHeightCm<=0)){let s="User height (userHeightCm) must be provided for jump_analysis exercise";throw this.reportError({type:"error",code:"jump_analysis_missing_height",message:s}),new Error(s)}this.stopExercise(),this.currentExerciseId=e.id,this.keypointsSuppressionLogged=!1,this.session=this.engine.createCustomSession({exerciseId:e.id,locale:this.opts.locale??"en",userHeightCm:r.userHeightCm,devicePitchDeg:r.devicePitchDeg},s=>this.emitFromSession(s))}stopExercise(){try{this.session?.end()}catch(e){this.opts.onDiagnostic?.("[posetracker-web] engine session end() threw: "+(e instanceof Error?e.message:String(e)))}this.session=null,this.currentExerciseId=null,this.sessionErrorStreak=0,this.shell?.setPlacementVisible(!1)}getCurrentExerciseId(){return this.currentExerciseId}fetchSkeleton(e){return Le(e,{baseUrl:this.opts.baseUrl})}async setModel(e,r){let s=this.running;s&&(this.running=!1,this.loopToken+=1,this.busy=!1),this.adapter?.dispose(),this.adapter=null,e!==void 0&&(this.opts.model=e),r!==void 0&&(this.opts.modelUrl=r),this.resolved=V({model:this.opts.model,modelUrl:this.opts.modelUrl}),await this.ensureAdapter(),s&&this.beginLoop()}updateOptions(e){this.opts={...this.opts,...e},e.skeletonDef!==void 0&&(this.skeletonDef=e.skeletonDef),e.skeletonUuid&&this.resolveSkeletonFromOptions(),this.applyWatermark(),this.shell&&(e.facingMode||e.position)&&this.shell.applyMirror(be(this.opts))}ingestPose(e){if(!this.session||this.features.keypoints?this.emit({type:"keypoints",keypoints:e.keypoints,score:e.score,timestampMs:e.timestampMs}):this.keypointsSuppressionLogged||(this.keypointsSuppressionLogged=!0,this.opts.onDiagnostic?.("[posetracker-web] keypoints events paused during exercise (features.keypoints=false)")),this.session)try{this.session.processPose(e),this.sessionErrorStreak=0}catch(r){this.sessionErrorStreak+=1;let s=r instanceof Error?r.message:String(r);if(this.sessionErrorStreak===1&&this.opts.onDiagnostic?.(`[posetracker-web] processPose threw: ${s}`),this.sessionErrorStreak>=Kt){let i=this.currentExerciseId;this.session=null,this.currentExerciseId=null,this.sessionErrorStreak=0,this.reportError({type:"error",code:"internal",message:`Exercise session '${i??"?"}' failed repeatedly (${s}) \u2014 session stopped.`})}}}async doPreload(){this.setStatus("configuring"),await this.resolveManifestOnce(),this.setStatus("downloading"),await this.tryConfigure({silentStatus:!0}),this.tracker.flushQueue();try{this.setStatus("warming"),await this.ensureAdapter(),this.acceleration={...this.acceleration,state:"gpu",runtime:"tfjs-webgl",backend:"webgl"}}catch(e){throw this.reportError({type:"error",code:"model_load_failed",message:e instanceof Error?e.message:String(e)}),this.setStatus("error"),e}this.setStatus("ready"),this.emit({type:"initialization",step:"ready",message:"running",ready:!0,mode:this.mode,acceleration:this.getAcceleration()})}async ensureColdStartMode(e){e==="full"&&this.shell&&await this.ensureCamera()}async ensureAdapter(){if(!this.adapter){if(this.resolved=V({model:this.opts.model,modelUrl:this.opts.modelUrl}),this.resolved.kind==="unsupported")throw new Error(this.resolved.unsupportedReason??"Unsupported model");this.emit({type:"initialization",step:"loading_pose_model",message:"loading pose model",ready:!1}),this.adapter=Ve({resolved:this.resolved}),await this.adapter.load()}}async ensureCamera(){if(!this.shell)throw new Error("Call mount() before opening the camera");if(this.stream)return;this.emit({type:"initialization",step:"accessing_webcam",message:"accessing webcam",ready:!1});try{this.stream=await Oe({facingMode:be(this.opts),idealWidth:this.opts.idealWidth,idealHeight:this.opts.idealHeight})}catch(s){let i=s instanceof Error?s.message:String(s),n=/NotAllowed|Permission|denied/i.test(i);throw this.reportError({type:"error",code:n?"camera_denied":"camera_unavailable",message:i}),this.shell.setBootMessage(n?"Camera permission denied \u2014 allow access in the browser":"Camera unavailable",!0),s}this.shell.video.srcObject=this.stream,this.shell.applyMirror(be(this.opts));try{await this.shell.video.play()}catch{}let e=Date.now(),r=()=>{if(this.revealCamera(),!this.cameraRevealed){if(Date.now()-e>8e3){this.shell?.setBootMessage("camera started but preview is empty \u2014 check permissions",!0);return}setTimeout(r,120)}};setTimeout(r,60),this.handleCameraStart({backend:this.acceleration.backend??"webgl",profileId:null})}beginLoop(){this.running=!0,this.fpsTimer=performance.now(),this.loop(++this.loopToken)}async loop(e){if(e!==this.loopToken||!this.running||!this.adapter||!this.shell||this.disposed)return;let r=this.shell.video;if(!this.busy&&r.readyState>=2&&r.videoWidth>0){this.busy=!0;try{let s=this.shell.canvas.clientWidth||this.shell.root.clientWidth||1,i=this.shell.canvas.clientHeight||this.shell.root.clientHeight||1,n=await this.adapter.estimate(r,{facingMode:be(this.opts),displayWidth:s,displayHeight:i});if(n){let p=this.shell.canvas.getContext("2d");if(p&&this.opts.drawSkeleton!==!1){let S=We(n.videoKeypoints,n.letterbox,s,i);Ye(p,S,s,i,!0,this.skeletonDef)}else p&&this.opts.drawSkeleton===!1&&p.clearRect(0,0,s,i);let g={keypoints:n.keypoints,score:n.score,timestampMs:Date.now()};this.ingestPose(g),this.inferMs.push(n.inferenceMs),this.inferMs.length>30&&this.inferMs.shift(),this.fpsWindow+=1;let a=performance.now();if(a-this.fpsTimer>=1e3){let S=this.fpsWindow;this.fpsWindow=0,this.fpsTimer=a;let b=Wt(this.inferMs);this.acceleration.medianInferenceMs=b;let _=n.keypoints.filter(y=>y.score>=.3).length,k="getBackend"in this.adapter&&typeof this.adapter.getBackend=="function"?this.adapter.getBackend():null;this.acceleration.backend=k,this.opts.debugHud&&this.shell.setHud(`${this.resolved.modelId} \xB7 ${k??"?"} \xB7 ${S} fps \xB7 ${b!=null?Math.round(b)+" ms":"?"} \xB7 kp\u22650.3=${_}/17`,!0),this.emit({type:"stats",fps:S,medianInferenceMs:b,backend:k,keypointsAbove03:_,meanScore:n.score,videoSize:`${r.videoWidth}x${r.videoHeight}`,timestampMs:Date.now()})}}this.revealCamera()}catch(s){let i=s instanceof Error?s.message:String(s);this.emit({type:"error",code:"internal",message:`inference: ${i}`})}this.busy=!1}requestAnimationFrame(()=>{this.loop(e)})}async resolveSkeletonFromOptions(){if(this.opts.skeletonDef){this.skeletonDef=this.opts.skeletonDef;return}let e=this.opts.skeletonUuid?.trim();if(!e||e==="true"||e==="false"){this.skeletonDef=null;return}try{this.skeletonDef=await this.fetchSkeleton(e)}catch{this.skeletonDef=null}}resolveManifestOnce(){return this.handshakePromise||(this.handshakePromise=this.doResolveManifestOnce().then(e=>(e||(this.handshakePromise=null),e))),this.handshakePromise}async doResolveManifestOnce(){let e={poseRuntime:null,engine:await this.files?.read(we).catch(()=>null)??null};if(this.apiToken){let r=await this.resolveManifest(this.apiToken,e);return r&&(this.manifest=r,r.revoked===!0&&await this.handleRevocation("Access revoked by the backend.")),r}try{let r=await z(null,{...this.opts,localVersions:e});return this.manifest=r,r}catch{return null}}async handleRevocation(e){let r=await this.files?.read(we).catch(()=>null);r&&(await this.files?.remove(`engine-${r}.sealed`).catch(()=>{}),await this.files?.remove(we).catch(()=>{})),await this.files?.remove(ve).catch(()=>{}),this.engine=null,this.engineSource=null,this.stopExercise(),this.setMode("keypoints-only"),this.reportError({type:"error",code:"invalid_token",message:e}),this.applyWatermark()}async handleCameraStart(e){this.lastCameraStartInfo=e;let r={backend:e.backend,profileId:e.profileId,poseModelProfile:this.opts.poseModelProfile??"AdaptiveChoice",mode:this.mode,exercise:this.currentExerciseId,model:this.opts.model??"movenet",modelUrl:this.opts.modelUrl??null};if(!this.apiToken){this.tracker.trackAnonymous({event:"camera_start",params:r});return}this.meteredSessionState="pending";try{await this.tracker.trackMetered({event:"camera_start",apiToken:this.apiToken,params:r}),this.meteredSessionState="validated",this.opts.onDiagnostic?.("[posetracker-web] camera_start tracked (metered)")}catch(s){this.meteredSessionState="refused",s instanceof L&&s.code==="network"?this.reportError({type:"error",code:"offline_metered",message:"API-key features are not available offline: PoseTracker cannot count their usage. Keypoints-only keeps running."}):s instanceof L&&s.code==="invalid_token"?await this.handleRevocation("API key invalid or revoked \u2014 engine cache purged."):s instanceof L&&s.code==="quota_exceeded"?this.reportError({type:"error",code:"quota_exceeded",message:s.message}):this.reportError({type:"error",code:"internal",message:`Usage tracking failed: ${s instanceof Error?s.message:String(s)}`})}}retryMeteredSessionIfRefused(){this.meteredSessionState==="refused"&&this.apiToken&&this.lastCameraStartInfo&&this.handleCameraStart(this.lastCameraStartInfo)}async tryConfigure({silentStatus:e,forceEngineRetry:r=!1}){if(this.mode==="full-engine")return!0;if(!this.apiToken)return this.validateRequestedFeatures(),this.setMode("keypoints-only"),this.applyWatermark(),!1;let s=await this.resolveManifestOnce();if(!s||s.revoked===!0)return this.setMode("keypoints-only"),this.applyWatermark(),!1;this.manifest=s,this.validateRequestedFeatures(),e||this.setStatus("downloading");let i=Ce(this.apiToken);r&&s.engine&&await this.engineLoader.clearGuard(s.engine);let n=await this.engineLoader.load(s.engine??null,i,{forceRetry:r});if(!n){let p=this.engineLoader.lastError;return this.reportError({type:"error",code:"engine_load_failed",message:p?`Engine bundle unavailable \u2014 ${p}`:"Engine bundle unavailable \u2014 running keypoints-only."}),this.setMode("keypoints-only"),this.applyWatermark(),!1}return this.engine=n.engine,this.engineSource=n.source,s.engine?.version&&await this.files?.write(we,s.engine.version).catch(()=>{}),this.setMode("full-engine"),this.applyWatermark(),!0}async resolveManifest(e,r){let s=Ce(e);try{let i=await z(e,{...this.opts,localVersions:r});return await this.files?.write(ve,de(JSON.stringify(i),s)).catch(()=>{}),i}catch(i){if(i instanceof O&&i.code==="invalid_token")return await this.handleRevocation(i.message),null;if(i instanceof O&&i.code==="quota_exceeded")return this.reportError({type:"error",code:"quota_exceeded",message:i.message}),null;let n=await this.files?.read(ve);if(n){let p=pe(n,s);if(p)try{return JSON.parse(p)}catch{await this.files?.remove(ve).catch(()=>{})}}return this.reportError({type:"error",code:"network",message:"Handshake unreachable and no cached session \u2014 running keypoints-only."}),null}}validateRequestedFeatures(){this.unsupportedFeatureKeys.length>0&&!this.featureGateReported.unsupported&&(this.featureGateReported.unsupported=!0,this.reportError({type:"error",code:"feature_not_supported",message:xe(this.unsupportedFeatureKeys[0])}));let e=this.features;if(e.angles||e.recommendations||e.progression||e.keypoints){if(!this.apiToken){this.featureGateReported.missingToken||(this.featureGateReported.missingToken=!0,this.reportError({type:"error",code:"invalid_token",message:Je}));return}this.getPlanType()==="free"&&ke(e,{withExercise:!1}).length>0&&!this.featureGateReported.freeBlock&&(this.featureGateReported.freeBlock=!0,this.reportError({type:"error",code:"free_plan_feature_blocked",message:ie}))}}emitFromSession(e){if(!(e.type==="angles"&&!this.features.angles)&&!(e.type==="recommendations"&&!this.features.recommendations)&&!(e.type==="progression"&&!this.features.progression)){if(e.type==="posture"){let r=this.opts.drawPlacementBox!==!1;this.shell?.setPlacementVisible(r&&!e.ready,this.opts.placementPaddingPercent??10)}else e.type==="exercise_summary"&&this.shell?.setPlacementVisible(!1);this.emit(e)}}watermarkOn(){return typeof this.opts.showWatermark=="boolean"?this.opts.showWatermark:this.coldStartMode==="basic"&&!this.stream?!1:ne(this.getPlanType())}applyWatermark(){this.shell?.setWatermarkVisible(this.watermarkOn()&&this.cameraRevealed)}revealCamera(){if(!this.shell||this.cameraRevealed)return;let e=this.shell.video;e.videoWidth>0&&e.videoHeight>0&&requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.cameraRevealed||!this.shell||this.shell.video.videoWidth>0&&(this.cameraRevealed=!0,this.shell.setCameraVisible(!0),this.applyWatermark())})})}setStatus(e){this.status=e,(e==="configuring"||e==="downloading"||e==="warming")&&this.emit({type:"initialization",step:e,message:e==="configuring"?"checking you plan and access":e==="downloading"?"downloading engine":"loading pose model",ready:!1}),this.notifyState()}setMode(e){this.mode!==e&&(this.mode=e,this.notifyState())}reportError(e){this.lastError=e,this.emit(e),this.notifyState()}notifyState(){this.stateListeners.forEach(e=>{try{e()}catch{}})}emit(e){if(this.listeners.forEach(n=>{try{n(e)}catch(p){this.opts.onDiagnostic?.(`[posetracker-web] listener threw on '${e.type}': `+(p instanceof Error?p.message:String(p)))}}),this.typedListeners.get(e.type)?.forEach(n=>{try{n(e)}catch{}}),this.typedListeners.get("*")?.forEach(n=>{try{n(e)}catch{}}),this.messageListeners.size===0)return;let i=He(e);this.messageListeners.forEach(n=>{try{n(i)}catch{}})}};function Ee(t={}){return new Se(t.apiToken,t)}function ht(t,e={}){let r=Ee(e);return r.mount(t),r}var Qe={mount:ht};return vt(Vt);})();
82
+ `,t.appendChild(o);let n=o.querySelector("video"),d=o.querySelector("img.pt-still"),f=o.querySelector("canvas.pt-overlay"),a=o.querySelector(".pt-boot"),v=o.querySelector(".pt-boot-msg"),w=o.querySelector(".pt-wm"),E=o.querySelector(".pt-hud"),b=o.querySelector(".pt-placement");return{root:o,video:n,image:d,canvas:f,boot:a,bootMsg:v,watermark:w,hud:E,placement:b,setBootMessage(y,_=!1){v.textContent=y,v.classList.toggle("is-error",_)},setCameraVisible(y){y?this.setMediaMode(d.src?"image":"video"):this.setMediaMode("none")},setMediaMode(y){let _=y==="video",P=y==="image",R=_||P;n.style.opacity=_?"1":"0",d.style.opacity=P?"1":"0",f.style.opacity=R?"1":"0",a.classList.toggle("hide",R),R||(v.textContent=r,v.classList.remove("is-error"))},setWatermarkVisible(y){w.classList.toggle("show",y)},setHud(y,_){E.classList.toggle("debug",_),E.textContent=y},setPlacementVisible(y,_=10){if(b.classList.toggle("show",y),y){let P=Math.max(0,Math.min(40,_));b.style.left=`${P}%`,b.style.top=`${P}%`,b.style.right=`${P}%`,b.style.bottom=`${P}%`}},applyMirror(y){let _=y==="user"?"scaleX(-1)":"none";n.style.transform=_,d.style.transform="none",f.style.transform=_},destroy(){o.remove()}}}var et={keypoints:["nose","left_eye","right_eye","left_ear","right_ear","left_shoulder","right_shoulder","left_elbow","right_elbow","left_wrist","right_wrist","left_hip","right_hip","left_knee","right_knee","left_ankle","right_ankle"],keypoint_lines:["right_shoulder||left_shoulder","right_hip||left_hip","right_hip||right_shoulder","right_hip||right_knee","right_ankle||right_knee","right_shoulder||right_elbow","right_wrist||right_elbow","left_hip||left_shoulder","left_hip||left_knee","left_ankle||left_knee","left_shoulder||left_elbow","left_wrist||left_elbow"],keypoint_angles:[],angles:{fontColor:"#000000",strokeColor:"#FFC300"},circles:{circleFillColor:"#010A73",circleStrokeColor:"#FFC300",strokeWidth:"4",radius:"8"},lines:{lineStrokeColor:"#010A73",strokeWidth:"4"}};var tt=.3;function rt(t,e,r,s,o=!0,n){if(t.canvas.width!==r&&(t.canvas.width=r),t.canvas.height!==s&&(t.canvas.height=s),t.clearRect(0,0,r,s),!o)return;let d=n??et,f={};for(let P of e)f[P.name]=P;let a=d.lines.lineStrokeColor,v=Number(d.lines.strokeWidth);for(let P of d.keypoint_lines){let[R,D]=String(P).split("||"),O=f[R],p=f[D];!O||!p||O.score<=tt||p.score<=tt||(t.beginPath(),t.moveTo(O.dx,O.dy),t.lineTo(p.dx,p.dy),t.lineWidth=v,t.strokeStyle=a,t.stroke())}let w=d.circles.circleFillColor,E=d.circles.circleStrokeColor,b=Number(d.circles.strokeWidth),y=Number(d.circles.radius),_=new Set(d.keypoints);for(let P of e)!_.has(P.name)||P.score<=tt||(t.beginPath(),t.arc(P.dx,P.dy,y,0,Math.PI*2),t.fillStyle=w,t.fill(),t.lineWidth=b,t.strokeStyle=E,t.stroke())}var kt={angles:!1,recommendations:!1,progression:!1,keypoints:!1,minGrade:null},Jt=new Set(["angles","recommendations","progression","keypoints","minGrade"]),Xt={blazepose:'BlazePose as a features flag (use options.model = "blazepose" instead)',poseEngine:"pose engine selection (MediaPipe/PoseLandmarker)",mediapipeModel:"MediaPipe model selection",poseBackend:"pose backend selection",runInWorker:"worker thread selection"},ae="You cannot use developer features. (visit: https://posetracker.gitbook.io/posetracker-api/tracking-endpoint)",st="Invalid params. Please refer to the documentation and set token=YOUR API_KEY et exercise=A correct exercise. (visit: https://posetracker.gitbook.io/posetracker-api/tracking-endpoint)";function be(t){let e=Xt[t]??`'${t}'`;return`The '${t}' option (${e}) is not available as a features flag. Remove the option, or use options.model / modelUrl for model selection. (visit: https://posetracker.gitbook.io/posetracker-api/tracking-endpoint)`}function ot(t){if(!t)return{features:{...kt},unsupportedKeys:[]};let e=Object.keys(t).filter(r=>!Jt.has(r));return{features:{angles:t.angles===!0,recommendations:t.recommendations===!0,progression:t.progression===!0,keypoints:t.keypoints===!0,minGrade:t.minGrade??null},unsupportedKeys:e}}function _e(t,e){let r=[];return t.angles&&r.push("angles"),t.recommendations&&r.push("recommendations"),t.progression&&r.push("progression"),t.keypoints&&e.withExercise&&r.push("keypoints"),r}function wt(t){return typeof t=="string"&&t.length>0&&t!=="free"}function le(t){return!wt(t)}var Pe="session.sealed",Me="engine.version",Qt=30;function Zt(t){if(typeof t=="string"){let e=document.querySelector(t);if(!e)throw new Error(`PoseTracker mount target not found: ${t}`);return e}return t}function er(t){if(!t.length)return null;let e=[...t].sort((r,s)=>r-s);return e[Math.floor(e.length/2)]??null}function j(t){return t.facingMode?t.facingMode:t.position==="back"?"environment":"user"}var Te=class{constructor(e,r={}){this.status="idle";this.mode="keypoints-only";this.lastError=null;this.manifest=null;this.engine=null;this.engineSource=null;this.session=null;this.currentExerciseId=null;this.listeners=new Set;this.typedListeners=new Map;this.messageListeners=new Set;this.stateListeners=new Set;this.preloadPromise=null;this.coldStartMode="basic";this.configurePromise=null;this.handshakePromise=null;this.meteredSessionState="idle";this.lastCameraStartInfo=null;this.sessionErrorStreak=0;this.featureGateReported={unsupported:!1,freeBlock:!1,missingToken:!1};this.keypointsSuppressionLogged=!1;this.shell=null;this.stream=null;this.poseSource={type:"camera"};this.objectUrlRevoke=null;this.estimateInput=null;this.imageShotPending=!1;this.adapter=null;this.running=!1;this.busy=!1;this.loopToken=0;this.cameraRevealed=!1;this.disposed=!1;this.skeletonDef=null;this.acceleration={state:"unknown",runtime:"unknown",backend:null,glRenderer:null,medianInferenceMs:null};this.inferMs=[];this.fpsWindow=0;this.fpsTimer=0;let s=e??(typeof r.apiToken=="string"?r.apiToken:null)??null;this.opts={...r,onDiagnostic:r.onDiagnostic},this.apiToken=s;let o=ot(r.features);this.features=o.features,this.unsupportedFeatureKeys=o.unsupportedKeys,this.resolved=W({model:r.model,modelUrl:r.modelUrl}),this.skeletonDef=r.skeletonDef??null,this.coldStartMode=r.coldStart==="full"?"full":"basic";try{this.poseSource=ve(r.source,{sourceUrl:r.sourceUrl,sourceFile:r.sourceFile,facingMode:j(r)})}catch{this.poseSource={type:"camera",facingMode:j(r)}}this.files=r.fileStore!==void 0?r.fileStore:fe(),this.engineLoader=r.engineLoader??new J({fileStore:this.files,onDiagnostic:this.opts.onDiagnostic}),this.tracker=r.usageTracker??new Q({baseUrl:r.baseUrl}),this.opts.onDiagnostic?.(`[posetracker-web] client created hasApiToken=${!!this.apiToken} features=${JSON.stringify(this.features)}`)}getStatus(){return this.status}getMode(){return this.mode}getError(){return this.lastError}getManifest(){return this.manifest}getPlanType(){return this.manifest?.plan?.plan??null}getFeatures(){return{...this.features}}getEngineSource(){return this.engineSource}getAcceleration(){return this.acceleration.state}getAccelerationDiagnostics(){return{...this.acceleration}}getResolvedModel(){return this.resolved}getColdStartMode(){return this.coldStartMode}getSource(){return this.poseSource}addEventListener(e){return this.listeners.add(e),()=>this.listeners.delete(e)}on(e,r){if(e==="*")return this.listeners.add(r),()=>this.listeners.delete(r);let s=this.typedListeners.get(e);return s||(s=new Set,this.typedListeners.set(e,s)),s.add(r),()=>s.delete(r)}addMessageListener(e){return this.messageListeners.add(e),()=>this.messageListeners.delete(e)}onStateChange(e){return this.stateListeners.add(e),()=>this.stateListeners.delete(e)}mount(e){if(this.disposed)throw new Error("PoseTracker disposed");this.shell&&this.shell.destroy();let r=Zt(e);r.innerHTML="",this.shell=Ze(r,{loadingText:this.opts.loadingText??ne}),this.shell.setCameraVisible(!1),this.cameraRevealed=!1,this.resolveSkeletonFromOptions()}preload(e){let r=e?.coldStart==="full"?"full":"basic";if(this.coldStartMode=r,this.status==="ready"&&this.preloadPromise)return this.preloadPromise.then(()=>this.ensureColdStartMode(r));if(!this.preloadPromise)this.preloadPromise=this.doPreload().then(()=>this.ensureColdStartMode(r)).catch(s=>{throw this.preloadPromise=null,s});else if(r==="full")return this.preloadPromise.then(()=>this.ensureColdStartMode("full"));return this.preloadPromise}warmup(e){return this.preload(e)}async start(){if(this.disposed)throw new Error("PoseTracker disposed");if(!this.shell)throw new Error("Call mount() before start()");let e=this.poseSource.type==="camera"||this.poseSource.type==="video"||this.poseSource.type==="image";await this.preload({coldStart:this.opts.coldStart==="basic"&&this.poseSource.type==="camera"?"basic":e?"full":"basic"}),(this.coldStartMode==="basic"||!this.estimateInput)&&await this.ensureSource(),this.poseSource.type==="image"&&(this.imageShotPending=!0),this.beginLoop()}async setSource(e,r){if(this.disposed)throw new Error("PoseTracker disposed");let s=this.running;this.stopMediaOnly(),this.poseSource=ve(e,{sourceUrl:r?.sourceUrl??this.opts.sourceUrl,sourceFile:r?.sourceFile??this.opts.sourceFile,facingMode:r?.facingMode??j(this.opts)}),this.opts.source=this.poseSource,this.poseSource.type==="camera"&&this.poseSource.facingMode&&(this.opts.facingMode=this.poseSource.facingMode),this.shell&&(await this.ensureSource(),(s||this.poseSource.type==="image")&&(this.poseSource.type==="image"&&(this.imageShotPending=!0),this.beginLoop()))}async analyze(){if(this.disposed)throw new Error("PoseTracker disposed");if(!this.shell)throw new Error("Call mount() before analyze()");return await this.ensureAdapter(),this.estimateInput||await this.ensureSource(),this.poseSource.type==="image"?(this.imageShotPending=!0,this.running||this.beginLoop(),null):this.runOneFrame()}stop(){this.running=!1,this.loopToken+=1,this.busy=!1,this.imageShotPending=!1,this.stopMediaOnly(),this.shell&&(this.shell.setMediaMode("none"),this.shell.setPlacementVisible(!1),this.cameraRevealed=!1,this.applyWatermark()),this.status!=="error"&&this.setStatus("idle")}stopMediaOnly(){if(Ve(this.stream),this.stream=null,this.estimateInput=null,this.objectUrlRevoke&&(this.objectUrlRevoke(),this.objectUrlRevoke=null),this.shell){try{this.shell.video.pause()}catch{}this.shell.video.removeAttribute("src"),this.shell.video.srcObject=null,this.shell.video.load(),this.shell.image.removeAttribute("src")}}async dispose(){this.stopExercise(),this.stop(),this.adapter?.dispose(),this.adapter=null,this.shell?.destroy(),this.shell=null,this.listeners.clear(),this.typedListeners.clear(),this.messageListeners.clear(),this.stateListeners.clear(),this.preloadPromise=null,this.configurePromise=null,this.handshakePromise=null,this.meteredSessionState="idle",this.lastCameraStartInfo=null,this.featureGateReported={unsupported:!1,freeBlock:!1,missingToken:!1},this.keypointsSuppressionLogged=!1,this.engine=null,this.engineSource=null,this.manifest=null,this.mode="keypoints-only",this.setStatus("idle"),this.disposed=!0}configure(e){return e!==void 0&&e!==this.apiToken&&(this.apiToken=e,this.opts.apiToken=e,this.configurePromise=null,this.handshakePromise=null,this.featureGateReported.freeBlock=!1,this.featureGateReported.missingToken=!1),this.mode!=="full-engine"&&(this.configurePromise=null),this.configurePromise||(this.configurePromise=this.tryConfigure({silentStatus:this.status==="ready",forceEngineRetry:!0}).then(r=>(r||(this.configurePromise=null),this.retryMeteredSessionIfRefused(),r)).catch(()=>(this.configurePromise=null,!1))),this.configurePromise}getAvailableExercises(){return this.mode==="full-engine"?this.manifest?.exercises??[]:[]}getAvailableCustomExercises(){return this.mode!=="full-engine"||!this.engine?.listCustomExercises?[]:this.engine.listCustomExercises()}startExercise(e,r={}){if(this.status!=="ready")throw new Error(`Cannot start exercise while status is '${this.status}' \u2014 call preload()/start() first.`);if(this.mode!=="full-engine"||!this.engine)throw new Error("Exercises require full-engine mode (validated API key). The SDK is running keypoints-only \u2014 call configure(apiToken) first.");if(this.meteredSessionState==="refused")throw new Error("API-key features are not available offline: PoseTracker could not track this session. Reconnect and retry.");if(this.unsupportedFeatureKeys.length>0){let n=be(this.unsupportedFeatureKeys[0]);throw this.reportError({type:"error",code:"feature_not_supported",message:n}),new Error(n)}if(this.getPlanType()==="free"&&_e(this.features,{withExercise:!0}).length>0)throw this.reportError({type:"error",code:"free_plan_feature_blocked",message:ae}),new Error(ae);let s=this.getAvailableExercises(),o=xe(e,s);if(!o){let n=this.getAvailableCustomExercises(),d=n.find(a=>a.id===e)??xe(e,n);if(d){this.startCustomExercise(d,r);return}let f=`Exercise '${e}' is not available in V3 engine`;throw this.reportError({type:"error",code:"invalid_exercise",message:f}),new Error(f)}this.stopExercise(),this.currentExerciseId=e,this.keypointsSuppressionLogged=!1,this.session=this.engine.createSession({exercise:o,locale:this.opts.locale??"en",difficulty:r.difficulty,minGrade:this.features.minGrade??void 0,features:{angles:this.features.angles,recommendations:this.features.recommendations,progression:this.features.progression}},n=>this.emitFromSession(n))}startCustomExercise(e,r){if(!this.engine?.createCustomSession)throw new Error(`The cached engine bundle is too old for custom exercise '${e.id}' \u2014 reconnect so the SDK can update it.`);if(e.id==="jump_analysis"&&(!r.userHeightCm||r.userHeightCm<=0)){let s="User height (userHeightCm) must be provided for jump_analysis exercise";throw this.reportError({type:"error",code:"jump_analysis_missing_height",message:s}),new Error(s)}this.stopExercise(),this.currentExerciseId=e.id,this.keypointsSuppressionLogged=!1,this.session=this.engine.createCustomSession({exerciseId:e.id,locale:this.opts.locale??"en",userHeightCm:r.userHeightCm,devicePitchDeg:r.devicePitchDeg},s=>this.emitFromSession(s))}stopExercise(){try{this.session?.end()}catch(e){this.opts.onDiagnostic?.("[posetracker-web] engine session end() threw: "+(e instanceof Error?e.message:String(e)))}this.session=null,this.currentExerciseId=null,this.sessionErrorStreak=0,this.shell?.setPlacementVisible(!1)}getCurrentExerciseId(){return this.currentExerciseId}fetchSkeleton(e){return He(e,{baseUrl:this.opts.baseUrl})}async setModel(e,r){let s=this.running;s&&(this.running=!1,this.loopToken+=1,this.busy=!1),this.adapter?.dispose(),this.adapter=null,e!==void 0&&(this.opts.model=e),r!==void 0&&(this.opts.modelUrl=r),this.resolved=W({model:this.opts.model,modelUrl:this.opts.modelUrl}),await this.ensureAdapter(),s&&this.beginLoop()}updateOptions(e){this.opts={...this.opts,...e},e.skeletonDef!==void 0&&(this.skeletonDef=e.skeletonDef),e.skeletonUuid&&this.resolveSkeletonFromOptions(),this.applyWatermark(),this.shell&&(e.facingMode||e.position)&&this.shell.applyMirror(j(this.opts))}ingestPose(e){if(!this.session||this.features.keypoints?this.emit({type:"keypoints",keypoints:e.keypoints,score:e.score,timestampMs:e.timestampMs}):this.keypointsSuppressionLogged||(this.keypointsSuppressionLogged=!0,this.opts.onDiagnostic?.("[posetracker-web] keypoints events paused during exercise (features.keypoints=false)")),this.session)try{this.session.processPose(e),this.sessionErrorStreak=0}catch(r){this.sessionErrorStreak+=1;let s=r instanceof Error?r.message:String(r);if(this.sessionErrorStreak===1&&this.opts.onDiagnostic?.(`[posetracker-web] processPose threw: ${s}`),this.sessionErrorStreak>=Qt){let o=this.currentExerciseId;this.session=null,this.currentExerciseId=null,this.sessionErrorStreak=0,this.reportError({type:"error",code:"internal",message:`Exercise session '${o??"?"}' failed repeatedly (${s}) \u2014 session stopped.`})}}}async doPreload(){this.setStatus("configuring"),await this.resolveManifestOnce(),this.setStatus("downloading"),await this.tryConfigure({silentStatus:!0}),this.tracker.flushQueue();try{this.setStatus("warming"),await this.ensureAdapter(),this.acceleration={...this.acceleration,state:"gpu",runtime:"tfjs-webgl",backend:"webgl"}}catch(e){throw this.reportError({type:"error",code:"model_load_failed",message:e instanceof Error?e.message:String(e)}),this.setStatus("error"),e}this.setStatus("ready"),this.emit({type:"initialization",step:"ready",message:"running",ready:!0,mode:this.mode,acceleration:this.getAcceleration()})}async ensureColdStartMode(e){e==="full"&&this.shell&&await this.ensureSource()}async ensureAdapter(){if(!this.adapter){if(this.resolved=W({model:this.opts.model,modelUrl:this.opts.modelUrl}),this.resolved.kind==="unsupported")throw new Error(this.resolved.unsupportedReason??"Unsupported model");this.emit({type:"initialization",step:"loading_pose_model",message:"loading pose model",ready:!1}),this.adapter=Xe({resolved:this.resolved}),await this.adapter.load()}}async ensureSource(){if(!this.shell)throw new Error("Call mount() before opening a pose source");let e=this.poseSource;if(e.type==="camera"){if(this.stream&&this.estimateInput)return;this.emit({type:"initialization",step:"accessing_webcam",message:"accessing webcam (source=camera)",ready:!1});try{this.stream=await Be({facingMode:e.facingMode??j(this.opts),idealWidth:this.opts.idealWidth,idealHeight:this.opts.idealHeight})}catch(r){let s=r instanceof Error?r.message:String(r),o=/NotAllowed|Permission|denied/i.test(s);throw this.reportError({type:"error",code:o?"camera_denied":"camera_unavailable",message:s}),this.shell.setBootMessage(o?"Camera permission denied \u2014 allow access in the browser":"Camera unavailable",!0),r}this.shell.video.srcObject=this.stream,this.shell.applyMirror(e.facingMode??j(this.opts)),this.shell.setMediaMode("video");try{await this.shell.video.play()}catch{}this.estimateInput=this.shell.video,this.scheduleReveal("camera"),this.handleCameraStart({backend:this.acceleration.backend??"webgl",profileId:null});return}if(e.type==="video"){this.emit({type:"initialization",step:"loading_media",message:"loading video (source=video)",ready:!1});try{await this.attachVideoSource(e.src,{autoplay:e.autoplay!==!1,loop:e.loop!==!1,muted:e.muted!==!1})}catch(r){let s=r instanceof Error?r.message:String(r);throw this.reportError({type:"error",code:"media_load_failed",message:s}),this.shell.setBootMessage("Could not load video source",!0),r}this.shell.applyMirror("none"),this.shell.setMediaMode("video"),this.scheduleReveal("video");return}this.emit({type:"initialization",step:"loading_media",message:"loading image (source=image)",ready:!1});try{await this.attachImageSource(e.src)}catch(r){let s=r instanceof Error?r.message:String(r);throw this.reportError({type:"error",code:"media_load_failed",message:s}),this.shell.setBootMessage("Could not load image source",!0),r}this.shell.applyMirror("none"),this.shell.setMediaMode("image"),this.scheduleReveal("image")}scheduleReveal(e){let r=Date.now(),s=()=>{if(this.revealCamera(),!this.cameraRevealed){if(Date.now()-r>8e3){this.shell?.setBootMessage(`${e} loaded but preview is empty \u2014 check the file or CORS`,!0);return}setTimeout(s,120)}};setTimeout(s,60)}async attachVideoSource(e,r){if(!this.shell)throw new Error("no shell");let s=this.shell.video;if(Z(e)){if(e.parentElement&&e!==s){if(this.estimateInput=e,r.autoplay)try{await e.play()}catch{}await Ke(e);return}e.srcObject?s.srcObject=e.srcObject:(e.currentSrc||e.src)&&(s.src=e.currentSrc||e.src)}else{let o=await ge(e);this.objectUrlRevoke=o.revoke,s.src=o.url}if(s.loop=r.loop,s.muted=r.muted,s.playsInline=!0,await Ke(s),r.autoplay)try{await s.play()}catch{}this.estimateInput=s}async attachImageSource(e){if(!this.shell)throw new Error("no shell");if($e(e)){let s=await ft(e);this.objectUrlRevoke=s.revoke,this.shell.image.src=s.url,await ye(this.shell.image),this.estimateInput=e;return}if(pt(e)){if(e.complete&&e.naturalWidth>0){this.shell.image.src=e.currentSrc||e.src,this.estimateInput=e;return}await ye(e),this.shell.image.src=e.currentSrc||e.src,this.estimateInput=e;return}let r=await ge(e);this.objectUrlRevoke=r.revoke,this.shell.image.src=r.url,await ye(this.shell.image),this.estimateInput=this.shell.image}beginLoop(){this.running=!0,this.fpsTimer=performance.now(),this.loop(++this.loopToken)}frameReady(e){let r=me(e);return!(!(r.width>0&&r.height>0)||Z(e)&&(e.readyState<2||this.poseSource.type==="video"&&(e.paused||e.ended)))}async runOneFrame(){if(!this.adapter||!this.shell||!this.estimateInput||!this.frameReady(this.estimateInput))return null;let e=this.estimateInput,r=this.shell.canvas.clientWidth||this.shell.root.clientWidth||1,s=this.shell.canvas.clientHeight||this.shell.root.clientHeight||1,o=this.poseSource.type==="camera"?j(this.opts):"environment",n=await this.adapter.estimate(e,{facingMode:o,displayWidth:r,displayHeight:s});if(!n)return null;let d=this.shell.canvas.getContext("2d");if(d&&this.opts.drawSkeleton!==!1){let v=Je(n.videoKeypoints,n.letterbox,r,s);rt(d,v,r,s,!0,this.skeletonDef)}else d&&this.opts.drawSkeleton===!1&&d.clearRect(0,0,r,s);let f={keypoints:n.keypoints,score:n.score,timestampMs:Date.now()};this.ingestPose(f),this.inferMs.push(n.inferenceMs),this.inferMs.length>30&&this.inferMs.shift(),this.fpsWindow+=1;let a=performance.now();if(a-this.fpsTimer>=1e3){let v=this.fpsWindow;this.fpsWindow=0,this.fpsTimer=a;let w=er(this.inferMs);this.acceleration.medianInferenceMs=w;let E=n.keypoints.filter(_=>_.score>=.3).length,b="getBackend"in this.adapter&&typeof this.adapter.getBackend=="function"?this.adapter.getBackend():null;this.acceleration.backend=b;let y=me(e);this.opts.debugHud&&this.shell.setHud(`${this.resolved.modelId} \xB7 ${this.poseSource.type} \xB7 ${b??"?"} \xB7 ${v} fps \xB7 ${w!=null?Math.round(w)+" ms":"?"} \xB7 kp\u22650.3=${E}/17`,!0),this.emit({type:"stats",fps:v,medianInferenceMs:w,backend:b,keypointsAbove03:E,meanScore:n.score,videoSize:`${y.width}x${y.height}`,timestampMs:Date.now()})}return this.revealCamera(),f}async loop(e){if(e!==this.loopToken||!this.running||!this.adapter||!this.shell||this.disposed)return;let r=this.estimateInput;if(!!r&&!this.busy&&this.frameReady(r)&&(this.poseSource.type!=="image"||this.imageShotPending)){this.busy=!0;try{if(await this.runOneFrame(),this.poseSource.type==="image"){this.imageShotPending=!1,this.running=!1,this.busy=!1;return}}catch(n){let d=n instanceof Error?n.message:String(n);this.emit({type:"error",code:"internal",message:`inference: ${d}`})}this.busy=!1}if(e!==this.loopToken||!this.running)return;let o=r&&Z(r)?r:this.shell.video;if(this.poseSource.type!=="image"&&typeof o.requestVideoFrameCallback=="function"&&(this.poseSource.type==="video"||this.poseSource.type==="camera")){o.requestVideoFrameCallback(()=>{this.loop(e)});return}requestAnimationFrame(()=>{this.loop(e)})}async resolveSkeletonFromOptions(){if(this.opts.skeletonDef){this.skeletonDef=this.opts.skeletonDef;return}let e=this.opts.skeletonUuid?.trim();if(!e||e==="true"||e==="false"){this.skeletonDef=null;return}try{this.skeletonDef=await this.fetchSkeleton(e)}catch{this.skeletonDef=null}}resolveManifestOnce(){return this.handshakePromise||(this.handshakePromise=this.doResolveManifestOnce().then(e=>(e||(this.handshakePromise=null),e))),this.handshakePromise}async doResolveManifestOnce(){let e={poseRuntime:null,engine:await this.files?.read(Me).catch(()=>null)??null};if(this.apiToken){let r=await this.resolveManifest(this.apiToken,e);return r&&(this.manifest=r,r.revoked===!0&&await this.handleRevocation("Access revoked by the backend.")),r}try{let r=await G(null,{...this.opts,localVersions:e});return this.manifest=r,r}catch{return null}}async handleRevocation(e){let r=await this.files?.read(Me).catch(()=>null);r&&(await this.files?.remove(`engine-${r}.sealed`).catch(()=>{}),await this.files?.remove(Me).catch(()=>{})),await this.files?.remove(Pe).catch(()=>{}),this.engine=null,this.engineSource=null,this.stopExercise(),this.setMode("keypoints-only"),this.reportError({type:"error",code:"invalid_token",message:e}),this.applyWatermark()}async handleCameraStart(e){this.lastCameraStartInfo=e;let r={backend:e.backend,profileId:e.profileId,poseModelProfile:this.opts.poseModelProfile??"AdaptiveChoice",mode:this.mode,exercise:this.currentExerciseId,model:this.opts.model??"movenet",modelUrl:this.opts.modelUrl??null};if(!this.apiToken){this.tracker.trackAnonymous({event:"camera_start",params:r});return}this.meteredSessionState="pending";try{await this.tracker.trackMetered({event:"camera_start",apiToken:this.apiToken,params:r}),this.meteredSessionState="validated",this.opts.onDiagnostic?.("[posetracker-web] camera_start tracked (metered)")}catch(s){this.meteredSessionState="refused",s instanceof A&&s.code==="network"?this.reportError({type:"error",code:"offline_metered",message:"API-key features are not available offline: PoseTracker cannot count their usage. Keypoints-only keeps running."}):s instanceof A&&s.code==="invalid_token"?await this.handleRevocation("API key invalid or revoked \u2014 engine cache purged."):s instanceof A&&s.code==="quota_exceeded"?this.reportError({type:"error",code:"quota_exceeded",message:s.message}):this.reportError({type:"error",code:"internal",message:`Usage tracking failed: ${s instanceof Error?s.message:String(s)}`})}}retryMeteredSessionIfRefused(){this.meteredSessionState==="refused"&&this.apiToken&&this.lastCameraStartInfo&&this.handleCameraStart(this.lastCameraStartInfo)}async tryConfigure({silentStatus:e,forceEngineRetry:r=!1}){if(this.mode==="full-engine")return!0;if(!this.apiToken)return this.validateRequestedFeatures(),this.setMode("keypoints-only"),this.applyWatermark(),!1;let s=await this.resolveManifestOnce();if(!s||s.revoked===!0)return this.setMode("keypoints-only"),this.applyWatermark(),!1;this.manifest=s,this.validateRequestedFeatures(),e||this.setStatus("downloading");let o=De(this.apiToken);r&&s.engine&&await this.engineLoader.clearGuard(s.engine);let n=await this.engineLoader.load(s.engine??null,o,{forceRetry:r});if(!n){let d=this.engineLoader.lastError;return this.reportError({type:"error",code:"engine_load_failed",message:d?`Engine bundle unavailable \u2014 ${d}`:"Engine bundle unavailable \u2014 running keypoints-only."}),this.setMode("keypoints-only"),this.applyWatermark(),!1}return this.engine=n.engine,this.engineSource=n.source,s.engine?.version&&await this.files?.write(Me,s.engine.version).catch(()=>{}),this.setMode("full-engine"),this.applyWatermark(),!0}async resolveManifest(e,r){let s=De(e);try{let o=await G(e,{...this.opts,localVersions:r});return await this.files?.write(Pe,he(JSON.stringify(o),s)).catch(()=>{}),o}catch(o){if(o instanceof U&&o.code==="invalid_token")return await this.handleRevocation(o.message),null;if(o instanceof U&&o.code==="quota_exceeded")return this.reportError({type:"error",code:"quota_exceeded",message:o.message}),null;let n=await this.files?.read(Pe);if(n){let d=pe(n,s);if(d)try{return JSON.parse(d)}catch{await this.files?.remove(Pe).catch(()=>{})}}return this.reportError({type:"error",code:"network",message:"Handshake unreachable and no cached session \u2014 running keypoints-only."}),null}}validateRequestedFeatures(){this.unsupportedFeatureKeys.length>0&&!this.featureGateReported.unsupported&&(this.featureGateReported.unsupported=!0,this.reportError({type:"error",code:"feature_not_supported",message:be(this.unsupportedFeatureKeys[0])}));let e=this.features;if(e.angles||e.recommendations||e.progression||e.keypoints){if(!this.apiToken){this.featureGateReported.missingToken||(this.featureGateReported.missingToken=!0,this.reportError({type:"error",code:"invalid_token",message:st}));return}this.getPlanType()==="free"&&_e(e,{withExercise:!1}).length>0&&!this.featureGateReported.freeBlock&&(this.featureGateReported.freeBlock=!0,this.reportError({type:"error",code:"free_plan_feature_blocked",message:ae}))}}emitFromSession(e){if(!(e.type==="angles"&&!this.features.angles)&&!(e.type==="recommendations"&&!this.features.recommendations)&&!(e.type==="progression"&&!this.features.progression)){if(e.type==="posture"){let r=this.opts.drawPlacementBox!==!1;this.shell?.setPlacementVisible(r&&!e.ready,this.opts.placementPaddingPercent??10)}else e.type==="exercise_summary"&&this.shell?.setPlacementVisible(!1);this.emit(e)}}watermarkOn(){return typeof this.opts.showWatermark=="boolean"?this.opts.showWatermark:this.coldStartMode==="basic"&&!this.stream?!1:le(this.getPlanType())}applyWatermark(){this.shell?.setWatermarkVisible(this.watermarkOn()&&this.cameraRevealed)}revealCamera(){if(!this.shell||this.cameraRevealed)return;let e=this.estimateInput;if(!e)return;let r=me(e);r.width>0&&r.height>0&&requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.cameraRevealed||!this.shell||(this.cameraRevealed=!0,this.poseSource.type==="image"?this.shell.setMediaMode("image"):this.shell.setMediaMode("video"),this.applyWatermark())})})}setStatus(e){this.status=e,(e==="configuring"||e==="downloading"||e==="warming")&&this.emit({type:"initialization",step:e,message:e==="configuring"?"checking you plan and access":e==="downloading"?"downloading engine":"loading pose model",ready:!1}),this.notifyState()}setMode(e){this.mode!==e&&(this.mode=e,this.notifyState())}reportError(e){this.lastError=e,this.emit(e),this.notifyState()}notifyState(){this.stateListeners.forEach(e=>{try{e()}catch{}})}emit(e){if(this.listeners.forEach(n=>{try{n(e)}catch(d){this.opts.onDiagnostic?.(`[posetracker-web] listener threw on '${e.type}': `+(d instanceof Error?d.message:String(d)))}}),this.typedListeners.get(e.type)?.forEach(n=>{try{n(e)}catch{}}),this.typedListeners.get("*")?.forEach(n=>{try{n(e)}catch{}}),this.messageListeners.size===0)return;let o=ze(e);this.messageListeners.forEach(n=>{try{n(o)}catch{}})}};function Fe(t={}){return new Te(t.apiToken,t)}function St(t,e={}){let r=Fe(e);return r.mount(t),r}var it={mount:St};return Ct(tr);})();
82
83
  /*! Bundled license information:
83
84
 
84
85
  js-sha256/src/sha256.js:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pose-tracker/pose-estimation-web",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "private": false,
5
5
  "description": "PoseTracker web pose estimation SDK (vanilla) — MoveNet via TensorFlow.js + remote model URL. Exercise engine via API token. No bundled weights.",
6
6
  "type": "module",