@trainheroic-unofficial/athlete-mcp 1.7.1 → 1.7.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.
Files changed (2) hide show
  1. package/dist/server.mjs +15 -10
  2. package/package.json +3 -3
package/dist/server.mjs CHANGED
@@ -1159,8 +1159,10 @@ function toSetResults(results) {
1159
1159
  * `param_2_data_N` string values plus a `param_N_made` flag.
1160
1160
  *
1161
1161
  * `mode` selects which write this is — the same endpoint serves both:
1162
- * - `"log"`: the values ARE a performed result, so `param_N_made` is 1 where the slot has data
1163
- * and the exercise `completed` flag is 1 when any set has logged data.
1162
+ * - `"log"`: the values ARE a performed result, so `param_N_made` is 1 where the slot has reps
1163
+ * entered (`param1`) and the exercise `completed` flag is 1 when any set is performed. A slot
1164
+ * carrying only a weight (`param2`) with no reps is a target, not a performed set, so it stays
1165
+ * un-made — matching the app, which shows no completion checkmark until reps are logged.
1164
1166
  * - `"prescribe"`: the values are prescribed targets, written with every `param_N_made` and
1165
1167
  * `completed` left at 0 so the set is not marked done. This matches what the app sends when a
1166
1168
  * coach edits an athlete's prescribed reps/weight.
@@ -1205,7 +1207,7 @@ function buildExerciseSetPayload(savedWorkoutSetExerciseId, savedWorkoutSetId, w
1205
1207
  if (target) {
1206
1208
  p1 = target.param1 !== void 0 ? String(target.param1) : "";
1207
1209
  p2 = target.param2 !== void 0 ? String(target.param2) : "";
1208
- made = performed && (p1 !== "" || p2 !== "") ? 1 : 0;
1210
+ made = performed && p1 !== "" ? 1 : 0;
1209
1211
  } else if (carryOver && coerceInt(existing?.[`param_${i}_made`]) === 1) {
1210
1212
  p1 = existingSlotData(existing, `param_1_data_${i}`);
1211
1213
  p2 = existingSlotData(existing, `param_2_data_${i}`);
@@ -1233,16 +1235,19 @@ function exerciseHasLoggedData(ex) {
1233
1235
  for (let i = 1; i <= 10; i += 1) if (coerceInt(ex[`param_${i}_made`]) === 1) return true;
1234
1236
  return false;
1235
1237
  }
1236
- /** True when a result carries at least one non-empty param value (so it produces a performed slot). */
1237
- function resultHasData(result) {
1238
- return result.sets.some((s) => s.param1 !== void 0 && String(s.param1) !== "" || s.param2 !== void 0 && String(s.param2) !== "");
1238
+ /** True when a result carries at least one set with reps entered (so it produces a performed slot).
1239
+ * A weight-only set (`param2` set, `param1` blank) is a target, not a performed result, and so does
1240
+ * not count mirroring the `made` rule in {@link buildExerciseSetPayload}. */
1241
+ function resultHasPerformedSet(result) {
1242
+ return result.sets.some((s) => s.param1 !== void 0 && String(s.param1) !== "");
1239
1243
  }
1240
1244
  /**
1241
1245
  * Whether every exercise in a saved workout set now has logged data — either written with data in
1242
1246
  * this call (`loggedIds`) or already carrying a performed slot. Gates the set-completion PUT: a
1243
1247
  * superset/circuit stays open until the last exercise is logged, so completing it on a partial log
1244
- * does not flip its still-empty siblings to "done". An exercise written with only empty values does
1245
- * not count (it would not be marked performed), so an all-empty log never completes the set.
1248
+ * does not flip its still-empty siblings to "done". An exercise written with no reps — empty values,
1249
+ * or a weight (`param2`) with no reps (`param1`) — does not count (it would not be marked performed),
1250
+ * so a no-reps log never completes the set.
1246
1251
  */
1247
1252
  function isSetFullyLogged(exercises, loggedIds) {
1248
1253
  return exercises.every((ex) => {
@@ -1449,7 +1454,7 @@ async function writeSetResults(client, target, workouts, savedWorkoutSetId, resu
1449
1454
  }
1450
1455
  let setCompleted = false;
1451
1456
  if (mode === "log") {
1452
- if (isSetFullyLogged(exercises, new Set(results.filter(resultHasData).map((r) => r.savedWorkoutSetExerciseId)))) {
1457
+ if (isSetFullyLogged(exercises, new Set(results.filter(resultHasPerformedSet).map((r) => r.savedWorkoutSetExerciseId)))) {
1453
1458
  const setBody = {
1454
1459
  ...buildSetCompletePayload(rawSet, exercises.map((e) => coerceInt(e.id)).filter((n) => n !== null), true),
1455
1460
  ...extra
@@ -2052,7 +2057,7 @@ function registerAthleteTrainingTools(server, ctx) {
2052
2057
  }
2053
2058
  //#endregion
2054
2059
  //#region package.json
2055
- var version = "1.7.1";
2060
+ var version = "1.7.2";
2056
2061
  //#endregion
2057
2062
  //#region src/server.ts
2058
2063
  async function main() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trainheroic-unofficial/athlete-mcp",
3
- "version": "1.7.1",
3
+ "version": "1.7.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,8 +21,8 @@
21
21
  "dependencies": {
22
22
  "@modelcontextprotocol/sdk": "^1.29.0",
23
23
  "zod": "^4.4.3",
24
- "@trainheroic-unofficial/core": "1.7.1",
25
- "@trainheroic-unofficial/js": "1.7.1"
24
+ "@trainheroic-unofficial/core": "1.7.2",
25
+ "@trainheroic-unofficial/js": "1.7.2"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^26.0.1",