@pose-tracker/react-native-pose-estimation-light 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -15
- package/lib/PoseTrackerProvider.js +3 -0
- package/lib/client.d.ts +10 -0
- package/lib/client.js +8 -0
- package/lib/engine/types.d.ts +5 -0
- package/lib/events/classicMessage.d.ts +2 -2
- package/lib/events/classicMessage.js +4 -1
- package/lib/sdkVersion.d.ts +1 -1
- package/lib/sdkVersion.js +1 -1
- package/lib/types/events.d.ts +36 -1
- package/package.json +1 -1
- package/src/PoseTrackerProvider.tsx +3 -0
- package/src/client.ts +21 -2
- package/src/engine/types.ts +5 -0
- package/src/events/classicMessage.ts +7 -2
- package/src/sdkVersion.ts +1 -1
- package/src/types/events.ts +34 -0
package/README.md
CHANGED
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
# PoseTracker React Native — Light (online) Human Pose Estimation SDK
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
**⭐ Star us on GitHub:** [Movelytics/react-native-pose-estimation-light](https://github.com/Movelytics/react-native-pose-estimation-light) — it helps other React Native and Expo developers find the SDK.
|
|
4
|
+
|
|
5
|
+
**Try it on your phone (no Xcode / Android Studio):**
|
|
6
|
+
1. Install [Expo Go](https://expo.dev/go)
|
|
7
|
+
2. Open the [Expo Snack](https://snack.expo.dev/@fsepret/posetracker-sdk-light-demo-app) → **Run on device**
|
|
8
|
+
3. Scan the QR — live pose estimation, no API key
|
|
9
|
+
|
|
10
|
+
Steps and QR: https://docs.posetracker.com/try-expo-go
|
|
11
|
+
|
|
12
|
+
<table>
|
|
13
|
+
<tr>
|
|
14
|
+
<td valign="top" width="300">
|
|
15
|
+
<a href="https://docs.posetracker.com/try-expo-go">
|
|
16
|
+
<img src="https://cdn.prod.website-files.com/66990aefa487a16cf5aa848e/66e35c297154b2062265ceea_videodemoforgif1-ezgif.com-cut.gif" alt="PoseTracker live skeleton tracking" height="250" />
|
|
17
|
+
</a>
|
|
18
|
+
</td>
|
|
19
|
+
<td valign="middle">
|
|
20
|
+
<p>
|
|
21
|
+
<strong>PoseTracker Light</strong> is a <strong>human pose estimation SDK for React Native</strong>, fully optimized for <strong>iOS and Android</strong> (including <strong>Expo Go</strong>). Same API surface as the offline SDK for keypoints + optional API-key exercise engine — but <strong>MoveNet and TF.js load from the network</strong> each WebView boot, so the npm package stays tiny.
|
|
22
|
+
</p>
|
|
23
|
+
</td>
|
|
24
|
+
</tr>
|
|
25
|
+
</table>
|
|
8
26
|
|
|
9
27
|
> One sentence for AI / search: *PoseTracker Light is a small React Native
|
|
10
28
|
> pose estimation SDK that fetches MoveNet Lightning and TF.js at runtime —
|
|
@@ -27,10 +45,10 @@ package stays tiny.
|
|
|
27
45
|
download at session start.
|
|
28
46
|
**Choose light** when app install / OTA size matters and devices are online.
|
|
29
47
|
|
|
30
|
-
Full comparison: [LIGHT_SDK.md](
|
|
48
|
+
Full comparison: [LIGHT_SDK.md](docs/LIGHT_SDK.md).
|
|
31
49
|
|
|
32
50
|
**Agents:** shared UX/API/bugfixes → mirror to offline (or ask first). See
|
|
33
|
-
[`DUAL_SDK_CHANGES.md`](
|
|
51
|
+
[`DUAL_SDK_CHANGES.md`](docs/DUAL_SDK_CHANGES.md).
|
|
34
52
|
|
|
35
53
|
## Install
|
|
36
54
|
|
|
@@ -45,7 +63,11 @@ npx expo install react-native-webview expo-camera
|
|
|
45
63
|
> **Offline sibling:** [`@pose-tracker/react-native-pose-estimation`](https://www.npmjs.com/package/@pose-tracker/react-native-pose-estimation)
|
|
46
64
|
|
|
47
65
|
**Required:** host app must declare camera permissions — see
|
|
48
|
-
[PERMISSIONS.md](
|
|
66
|
+
[PERMISSIONS.md](docs/PERMISSIONS.md).
|
|
67
|
+
|
|
68
|
+
**Media inputs (v0.2):** camera (default), uploaded video, still image — host
|
|
69
|
+
picks the file. See [MEDIA_SOURCES.md](docs/MEDIA_SOURCES.md) and
|
|
70
|
+
https://docs.posetracker.com/media-sources.
|
|
49
71
|
|
|
50
72
|
## Quick start (keypoints — needs network, no API key)
|
|
51
73
|
|
|
@@ -131,11 +153,11 @@ Same contract as the offline SDK / web tracking URL:
|
|
|
131
153
|
|
|
132
154
|
| Doc | Topic |
|
|
133
155
|
|-----|--------|
|
|
134
|
-
| [LIGHT_SDK.md](
|
|
135
|
-
| [PERMISSIONS.md](
|
|
136
|
-
| [PRELOAD.md](
|
|
137
|
-
| [FEATURES.md](
|
|
138
|
-
| [EVENTS.md](
|
|
156
|
+
| [LIGHT_SDK.md](docs/LIGHT_SDK.md) | Offline vs light, sizes, model URL |
|
|
157
|
+
| [PERMISSIONS.md](docs/PERMISSIONS.md) | Camera permission setup (required) |
|
|
158
|
+
| [PRELOAD.md](docs/PRELOAD.md) | Preload / warm-up / lifecycle |
|
|
159
|
+
| [FEATURES.md](docs/FEATURES.md) | Plan gating, watermark, loading text |
|
|
160
|
+
| [EVENTS.md](docs/EVENTS.md) | Typed events + classic `onMessage` |
|
|
139
161
|
|
|
140
162
|
## FAQ
|
|
141
163
|
|
|
@@ -164,6 +186,8 @@ see [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md).
|
|
|
164
186
|
## Links
|
|
165
187
|
|
|
166
188
|
- Product: https://www.posetracker.com
|
|
167
|
-
-
|
|
168
|
-
-
|
|
189
|
+
- Docs: https://docs.posetracker.com
|
|
190
|
+
- Try on your phone: https://docs.posetracker.com/try-expo-go
|
|
191
|
+
- Expo Snack: https://snack.expo.dev/@fsepret/posetracker-sdk-light-demo-app
|
|
169
192
|
- Light demo: https://github.com/Movelytics/react-native-pose-estimation-light-demo
|
|
193
|
+
- Offline SDK: https://github.com/Movelytics/react-native-pose-estimation
|
package/lib/client.d.ts
CHANGED
|
@@ -102,6 +102,11 @@ export interface PoseTrackerClientOptions extends ConfigureOptions {
|
|
|
102
102
|
* triaging Android GPU issues in the field.
|
|
103
103
|
*/
|
|
104
104
|
onDiagnostic?: (message: string) => void;
|
|
105
|
+
/**
|
|
106
|
+
* @internal PoseTracker QA only — not a supported public API.
|
|
107
|
+
* See `.private/ENGINE_DEBUG_QA.md` (do not document in Mintlify).
|
|
108
|
+
*/
|
|
109
|
+
debugEngine?: boolean;
|
|
105
110
|
}
|
|
106
111
|
/**
|
|
107
112
|
* Per-session options for {@link PoseTrackerClient.startExercise} — the SDK
|
|
@@ -118,6 +123,11 @@ export interface StartExerciseOptions {
|
|
|
118
123
|
userHeightCm?: number;
|
|
119
124
|
/** Device pitch in degrees — jump exercises compensate camera tilt. */
|
|
120
125
|
devicePitchDeg?: number;
|
|
126
|
+
/**
|
|
127
|
+
* @internal PoseTracker QA only — not a supported public API.
|
|
128
|
+
* Defaults to {@link PoseTrackerClientOptions.debugEngine}.
|
|
129
|
+
*/
|
|
130
|
+
debug?: boolean;
|
|
121
131
|
}
|
|
122
132
|
export declare class PoseTrackerClient {
|
|
123
133
|
private status;
|
package/lib/client.js
CHANGED
|
@@ -818,17 +818,21 @@ class PoseTrackerClient {
|
|
|
818
818
|
this.stopExercise();
|
|
819
819
|
this.currentExerciseId = exerciseId;
|
|
820
820
|
this.keypointsSuppressionLogged = false;
|
|
821
|
+
const debug = options.debug ?? this.options.debugEngine === true;
|
|
821
822
|
this.session = this.engine.createSession({
|
|
822
823
|
exercise,
|
|
823
824
|
locale: this.options.locale ?? 'en',
|
|
824
825
|
difficulty: options.difficulty,
|
|
825
826
|
minGrade: this.features.minGrade ?? undefined,
|
|
827
|
+
debug,
|
|
826
828
|
features: {
|
|
827
829
|
angles: this.features.angles,
|
|
828
830
|
recommendations: this.features.recommendations,
|
|
829
831
|
progression: this.features.progression,
|
|
830
832
|
},
|
|
831
833
|
}, (event) => this.emitFromSession(event));
|
|
834
|
+
this.options.onDiagnostic?.(`[posetracker] startExercise id=${exercise.id} difficulty=${options.difficulty ?? 'medium'} ` +
|
|
835
|
+
`debug=${debug} engine=${this.engine.version} minGrade=${this.features.minGrade ?? 'off'}`);
|
|
832
836
|
}
|
|
833
837
|
/** Custom engine session (jump_analysis / air_time_jump). */
|
|
834
838
|
startCustomExercise(custom, options) {
|
|
@@ -1032,6 +1036,10 @@ class PoseTrackerClient {
|
|
|
1032
1036
|
return;
|
|
1033
1037
|
}
|
|
1034
1038
|
const classic = (0, classicMessage_1.toClassicNativeMessage)(event);
|
|
1039
|
+
if (classic == null) {
|
|
1040
|
+
// SDK-only events (e.g. engine_debug) have no classic equivalent.
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1035
1043
|
this.messageListeners.forEach((l) => {
|
|
1036
1044
|
try {
|
|
1037
1045
|
l(classic);
|
package/lib/engine/types.d.ts
CHANGED
|
@@ -36,6 +36,11 @@ export interface EngineSessionOptions {
|
|
|
36
36
|
minGrade?: MinGrade;
|
|
37
37
|
/** Emission flags — engines older than 1.1.0 ignore them (client re-filters). */
|
|
38
38
|
features?: EngineSessionFeatures;
|
|
39
|
+
/**
|
|
40
|
+
* @internal PoseTracker QA only — not a supported public API.
|
|
41
|
+
* Ignored by older engines.
|
|
42
|
+
*/
|
|
43
|
+
debug?: boolean;
|
|
39
44
|
}
|
|
40
45
|
export interface EngineSession {
|
|
41
46
|
/** Feed one estimated pose; the session emits events through the sink. */
|
|
@@ -26,6 +26,6 @@ export declare function anglesToClassicTree(angles: AngleValue[]): {
|
|
|
26
26
|
/**
|
|
27
27
|
* Map a typed SDK event to a classic PoseTracker `sendDataToNative` payload.
|
|
28
28
|
* Returns null for SDK-only events that have no classic equivalent and should
|
|
29
|
-
* not be mirrored (
|
|
29
|
+
* not be mirrored (e.g. `engine_debug` QA snapshots).
|
|
30
30
|
*/
|
|
31
|
-
export declare function toClassicNativeMessage(event: PoseTrackerEvent): ClassicNativeMessage;
|
|
31
|
+
export declare function toClassicNativeMessage(event: PoseTrackerEvent): ClassicNativeMessage | null;
|
|
@@ -49,7 +49,7 @@ function anglesToClassicTree(angles) {
|
|
|
49
49
|
/**
|
|
50
50
|
* Map a typed SDK event to a classic PoseTracker `sendDataToNative` payload.
|
|
51
51
|
* Returns null for SDK-only events that have no classic equivalent and should
|
|
52
|
-
* not be mirrored (
|
|
52
|
+
* not be mirrored (e.g. `engine_debug` QA snapshots).
|
|
53
53
|
*/
|
|
54
54
|
function toClassicNativeMessage(event) {
|
|
55
55
|
switch (event.type) {
|
|
@@ -236,6 +236,9 @@ function toClassicNativeMessage(event) {
|
|
|
236
236
|
totalParts: event.totalParts,
|
|
237
237
|
timestampMs: event.timestampMs,
|
|
238
238
|
};
|
|
239
|
+
case 'engine_debug':
|
|
240
|
+
// SDK-only QA stream — no classic WebView equivalent; skip onMessage.
|
|
241
|
+
return null;
|
|
239
242
|
default: {
|
|
240
243
|
const _exhaustive = event;
|
|
241
244
|
return { type: 'unknown', event: _exhaustive };
|
package/lib/sdkVersion.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** AUTO-GENERATED by scripts/sync-sdk-version.mjs — do not edit. */
|
|
2
|
-
export declare const SDK_VERSION = "0.2.
|
|
2
|
+
export declare const SDK_VERSION = "0.2.2";
|
package/lib/sdkVersion.js
CHANGED
package/lib/types/events.d.ts
CHANGED
|
@@ -154,6 +154,40 @@ export interface ProgressionEvent {
|
|
|
154
154
|
value: number;
|
|
155
155
|
timestampMs: number;
|
|
156
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* @internal PoseTracker QA only — not a supported public API (do not document in Mintlify).
|
|
159
|
+
* Throttled movement / rep-FSM snapshot. See `.private/ENGINE_DEBUG_QA.md`.
|
|
160
|
+
*/
|
|
161
|
+
export interface EngineDebugEvent {
|
|
162
|
+
type: 'engine_debug';
|
|
163
|
+
exerciseId: string;
|
|
164
|
+
engineVersion: string;
|
|
165
|
+
ready: boolean;
|
|
166
|
+
postureHint: string;
|
|
167
|
+
direction?: string;
|
|
168
|
+
missingKeypoints: string[];
|
|
169
|
+
stepIndex: number;
|
|
170
|
+
stepCount: number;
|
|
171
|
+
stepPosition: number | null;
|
|
172
|
+
stepProgression: number;
|
|
173
|
+
progression: number;
|
|
174
|
+
/** Raw FSM rep count (before minGrade gate). */
|
|
175
|
+
rawCount: number;
|
|
176
|
+
/** Public counter after minGrade gate. */
|
|
177
|
+
publicCount: number;
|
|
178
|
+
difficulty: string;
|
|
179
|
+
minGrade: MinGrade | null;
|
|
180
|
+
pointOfView: 'low' | 'up';
|
|
181
|
+
computeError?: string;
|
|
182
|
+
lastSkipReason: string | null;
|
|
183
|
+
posesProcessed: number;
|
|
184
|
+
visibleKeypoints: number;
|
|
185
|
+
knees: {
|
|
186
|
+
left: number | null;
|
|
187
|
+
right: number | null;
|
|
188
|
+
};
|
|
189
|
+
timestampMs: number;
|
|
190
|
+
}
|
|
157
191
|
export interface RecommendationsEvent {
|
|
158
192
|
type: 'recommendations';
|
|
159
193
|
/** Localized form advice strings. */
|
|
@@ -309,7 +343,7 @@ export interface RuntimeDownloadProgressEvent {
|
|
|
309
343
|
partBytes: number;
|
|
310
344
|
timestampMs: number;
|
|
311
345
|
}
|
|
312
|
-
export type PoseTrackerEvent = InitializationEvent | ErrorEvent | WarningEvent | RuntimeDownloadProgressEvent | KeypointsEvent | AnglesEvent | CounterEvent | PostureEvent | ProgressionEvent | RecommendationsEvent | FormScoreEvent | ExerciseSummaryEvent | JumpCalibrationEvent | JumpStartedEvent | JumpHeightEvent | JumpDiscardedEvent | JumpResultEvent | JumpSummaryEvent | QualityChangedEvent | PerformanceWarningEvent;
|
|
346
|
+
export type PoseTrackerEvent = InitializationEvent | ErrorEvent | WarningEvent | RuntimeDownloadProgressEvent | KeypointsEvent | AnglesEvent | CounterEvent | PostureEvent | ProgressionEvent | EngineDebugEvent | RecommendationsEvent | FormScoreEvent | ExerciseSummaryEvent | JumpCalibrationEvent | JumpStartedEvent | JumpHeightEvent | JumpDiscardedEvent | JumpResultEvent | JumpSummaryEvent | QualityChangedEvent | PerformanceWarningEvent;
|
|
313
347
|
export type PoseTrackerEventType = PoseTrackerEvent['type'];
|
|
314
348
|
export type PoseTrackerEventListener = (event: PoseTrackerEvent) => void;
|
|
315
349
|
/**
|
|
@@ -325,6 +359,7 @@ export interface PoseTrackerCallbacks {
|
|
|
325
359
|
onCounter?: (event: CounterEvent) => void;
|
|
326
360
|
onPosture?: (event: PostureEvent) => void;
|
|
327
361
|
onProgression?: (event: ProgressionEvent) => void;
|
|
362
|
+
onEngineDebug?: (event: EngineDebugEvent) => void;
|
|
328
363
|
onRecommendations?: (event: RecommendationsEvent) => void;
|
|
329
364
|
onFormScore?: (event: FormScoreEvent) => void;
|
|
330
365
|
onExerciseSummary?: (event: ExerciseSummaryEvent) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pose-tracker/react-native-pose-estimation-light",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Human pose estimation SDK for React Native (light / online) — MoveNet Lightning via CDN + model URL each session, no bundled weights. iOS & Android (Expo Go). Optional API-key exercise engine.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -281,6 +281,9 @@ export function usePoseTracker(callbacks: PoseTrackerCallbacks = {}): PoseTracke
|
|
|
281
281
|
case 'progression':
|
|
282
282
|
cb.onProgression?.(event);
|
|
283
283
|
break;
|
|
284
|
+
case 'engine_debug':
|
|
285
|
+
cb.onEngineDebug?.(event);
|
|
286
|
+
break;
|
|
284
287
|
case 'recommendations':
|
|
285
288
|
cb.onRecommendations?.(event);
|
|
286
289
|
break;
|
package/src/client.ts
CHANGED
|
@@ -69,7 +69,6 @@ import {
|
|
|
69
69
|
import {
|
|
70
70
|
toClassicNativeMessage,
|
|
71
71
|
type ClassicMessageListener,
|
|
72
|
-
type ClassicNativeMessage,
|
|
73
72
|
} from './events/classicMessage';
|
|
74
73
|
import {
|
|
75
74
|
FREE_PLAN_FEATURES_MESSAGE,
|
|
@@ -164,6 +163,11 @@ export interface PoseTrackerClientOptions extends ConfigureOptions {
|
|
|
164
163
|
* triaging Android GPU issues in the field.
|
|
165
164
|
*/
|
|
166
165
|
onDiagnostic?: (message: string) => void;
|
|
166
|
+
/**
|
|
167
|
+
* @internal PoseTracker QA only — not a supported public API.
|
|
168
|
+
* See `.private/ENGINE_DEBUG_QA.md` (do not document in Mintlify).
|
|
169
|
+
*/
|
|
170
|
+
debugEngine?: boolean;
|
|
167
171
|
}
|
|
168
172
|
|
|
169
173
|
/**
|
|
@@ -181,6 +185,11 @@ export interface StartExerciseOptions {
|
|
|
181
185
|
userHeightCm?: number;
|
|
182
186
|
/** Device pitch in degrees — jump exercises compensate camera tilt. */
|
|
183
187
|
devicePitchDeg?: number;
|
|
188
|
+
/**
|
|
189
|
+
* @internal PoseTracker QA only — not a supported public API.
|
|
190
|
+
* Defaults to {@link PoseTrackerClientOptions.debugEngine}.
|
|
191
|
+
*/
|
|
192
|
+
debug?: boolean;
|
|
184
193
|
}
|
|
185
194
|
|
|
186
195
|
export class PoseTrackerClient {
|
|
@@ -1040,12 +1049,14 @@ export class PoseTrackerClient {
|
|
|
1040
1049
|
this.stopExercise();
|
|
1041
1050
|
this.currentExerciseId = exerciseId;
|
|
1042
1051
|
this.keypointsSuppressionLogged = false;
|
|
1052
|
+
const debug = options.debug ?? this.options.debugEngine === true;
|
|
1043
1053
|
this.session = this.engine.createSession(
|
|
1044
1054
|
{
|
|
1045
1055
|
exercise,
|
|
1046
1056
|
locale: this.options.locale ?? 'en',
|
|
1047
1057
|
difficulty: options.difficulty,
|
|
1048
1058
|
minGrade: this.features.minGrade ?? undefined,
|
|
1059
|
+
debug,
|
|
1049
1060
|
features: {
|
|
1050
1061
|
angles: this.features.angles,
|
|
1051
1062
|
recommendations: this.features.recommendations,
|
|
@@ -1054,6 +1065,10 @@ export class PoseTrackerClient {
|
|
|
1054
1065
|
},
|
|
1055
1066
|
(event) => this.emitFromSession(event),
|
|
1056
1067
|
);
|
|
1068
|
+
this.options.onDiagnostic?.(
|
|
1069
|
+
`[posetracker] startExercise id=${exercise.id} difficulty=${options.difficulty ?? 'medium'} ` +
|
|
1070
|
+
`debug=${debug} engine=${this.engine.version} minGrade=${this.features.minGrade ?? 'off'}`,
|
|
1071
|
+
);
|
|
1057
1072
|
}
|
|
1058
1073
|
|
|
1059
1074
|
/** Custom engine session (jump_analysis / air_time_jump). */
|
|
@@ -1280,7 +1295,11 @@ export class PoseTrackerClient {
|
|
|
1280
1295
|
// Skip the classic-message conversion entirely (per-frame allocation).
|
|
1281
1296
|
return;
|
|
1282
1297
|
}
|
|
1283
|
-
const classic
|
|
1298
|
+
const classic = toClassicNativeMessage(event);
|
|
1299
|
+
if (classic == null) {
|
|
1300
|
+
// SDK-only events (e.g. engine_debug) have no classic equivalent.
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1284
1303
|
this.messageListeners.forEach((l) => {
|
|
1285
1304
|
try {
|
|
1286
1305
|
l(classic);
|
package/src/engine/types.ts
CHANGED
|
@@ -39,6 +39,11 @@ export interface EngineSessionOptions {
|
|
|
39
39
|
minGrade?: MinGrade;
|
|
40
40
|
/** Emission flags — engines older than 1.1.0 ignore them (client re-filters). */
|
|
41
41
|
features?: EngineSessionFeatures;
|
|
42
|
+
/**
|
|
43
|
+
* @internal PoseTracker QA only — not a supported public API.
|
|
44
|
+
* Ignored by older engines.
|
|
45
|
+
*/
|
|
46
|
+
debug?: boolean;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
export interface EngineSession {
|
|
@@ -59,9 +59,11 @@ export function anglesToClassicTree(angles: AngleValue[]): {
|
|
|
59
59
|
/**
|
|
60
60
|
* Map a typed SDK event to a classic PoseTracker `sendDataToNative` payload.
|
|
61
61
|
* Returns null for SDK-only events that have no classic equivalent and should
|
|
62
|
-
* not be mirrored (
|
|
62
|
+
* not be mirrored (e.g. `engine_debug` QA snapshots).
|
|
63
63
|
*/
|
|
64
|
-
export function toClassicNativeMessage(
|
|
64
|
+
export function toClassicNativeMessage(
|
|
65
|
+
event: PoseTrackerEvent,
|
|
66
|
+
): ClassicNativeMessage | null {
|
|
65
67
|
switch (event.type) {
|
|
66
68
|
case 'initialization':
|
|
67
69
|
return {
|
|
@@ -247,6 +249,9 @@ export function toClassicNativeMessage(event: PoseTrackerEvent): ClassicNativeMe
|
|
|
247
249
|
totalParts: event.totalParts,
|
|
248
250
|
timestampMs: event.timestampMs,
|
|
249
251
|
};
|
|
252
|
+
case 'engine_debug':
|
|
253
|
+
// SDK-only QA stream — no classic WebView equivalent; skip onMessage.
|
|
254
|
+
return null;
|
|
250
255
|
default: {
|
|
251
256
|
const _exhaustive: never = event;
|
|
252
257
|
return { type: 'unknown', event: _exhaustive };
|
package/src/sdkVersion.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** AUTO-GENERATED by scripts/sync-sdk-version.mjs — do not edit. */
|
|
2
|
-
export const SDK_VERSION = '0.2.
|
|
2
|
+
export const SDK_VERSION = '0.2.2';
|
package/src/types/events.ts
CHANGED
|
@@ -198,6 +198,38 @@ export interface ProgressionEvent {
|
|
|
198
198
|
timestampMs: number;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
/**
|
|
202
|
+
* @internal PoseTracker QA only — not a supported public API (do not document in Mintlify).
|
|
203
|
+
* Throttled movement / rep-FSM snapshot. See `.private/ENGINE_DEBUG_QA.md`.
|
|
204
|
+
*/
|
|
205
|
+
export interface EngineDebugEvent {
|
|
206
|
+
type: 'engine_debug';
|
|
207
|
+
exerciseId: string;
|
|
208
|
+
engineVersion: string;
|
|
209
|
+
ready: boolean;
|
|
210
|
+
postureHint: string;
|
|
211
|
+
direction?: string;
|
|
212
|
+
missingKeypoints: string[];
|
|
213
|
+
stepIndex: number;
|
|
214
|
+
stepCount: number;
|
|
215
|
+
stepPosition: number | null;
|
|
216
|
+
stepProgression: number;
|
|
217
|
+
progression: number;
|
|
218
|
+
/** Raw FSM rep count (before minGrade gate). */
|
|
219
|
+
rawCount: number;
|
|
220
|
+
/** Public counter after minGrade gate. */
|
|
221
|
+
publicCount: number;
|
|
222
|
+
difficulty: string;
|
|
223
|
+
minGrade: MinGrade | null;
|
|
224
|
+
pointOfView: 'low' | 'up';
|
|
225
|
+
computeError?: string;
|
|
226
|
+
lastSkipReason: string | null;
|
|
227
|
+
posesProcessed: number;
|
|
228
|
+
visibleKeypoints: number;
|
|
229
|
+
knees: { left: number | null; right: number | null };
|
|
230
|
+
timestampMs: number;
|
|
231
|
+
}
|
|
232
|
+
|
|
201
233
|
export interface RecommendationsEvent {
|
|
202
234
|
type: 'recommendations';
|
|
203
235
|
/** Localized form advice strings. */
|
|
@@ -389,6 +421,7 @@ export type PoseTrackerEvent =
|
|
|
389
421
|
| CounterEvent
|
|
390
422
|
| PostureEvent
|
|
391
423
|
| ProgressionEvent
|
|
424
|
+
| EngineDebugEvent
|
|
392
425
|
| RecommendationsEvent
|
|
393
426
|
| FormScoreEvent
|
|
394
427
|
| ExerciseSummaryEvent
|
|
@@ -418,6 +451,7 @@ export interface PoseTrackerCallbacks {
|
|
|
418
451
|
onCounter?: (event: CounterEvent) => void;
|
|
419
452
|
onPosture?: (event: PostureEvent) => void;
|
|
420
453
|
onProgression?: (event: ProgressionEvent) => void;
|
|
454
|
+
onEngineDebug?: (event: EngineDebugEvent) => void;
|
|
421
455
|
onRecommendations?: (event: RecommendationsEvent) => void;
|
|
422
456
|
onFormScore?: (event: FormScoreEvent) => void;
|
|
423
457
|
onExerciseSummary?: (event: ExerciseSummaryEvent) => void;
|