import os p = "/home/node/.openclaw/mcp-venv/lib/python3.12/site-packages/garmin_mcp/workouts.py" if os.path.exists(p): with open(p, "r") as f: c = f.read() if "_normalize_sport_type" not in c: patch = ''' SPORT_TYPE_MAPPINGS = { "running": {"sportTypeId": 1, "sportTypeKey": "running", "displayOrder": 1}, "cycling": {"sportTypeId": 2, "sportTypeKey": "cycling", "displayOrder": 2}, "other": {"sportTypeId": 3, "sportTypeKey": "other", "displayOrder": 3}, "lap_swimming": {"sportTypeId": 4, "sportTypeKey": "lap_swimming", "displayOrder": 4}, "swimming": {"sportTypeId": 4, "sportTypeKey": "lap_swimming", "displayOrder": 4}, "strength_training": {"sportTypeId": 5, "sportTypeKey": "strength_training", "displayOrder": 5}, "cardio_training": {"sportTypeId": 6, "sportTypeKey": "cardio_training", "displayOrder": 6}, "cardio": {"sportTypeId": 6, "sportTypeKey": "cardio_training", "displayOrder": 6}, "yoga": {"sportTypeId": 7, "sportTypeKey": "yoga", "displayOrder": 8}, "pilates": {"sportTypeId": 8, "sportTypeKey": "pilates", "displayOrder": 9}, "hiit": {"sportTypeId": 9, "sportTypeKey": "hiit", "displayOrder": 7}, "mobility": {"sportTypeId": 11, "sportTypeKey": "mobility", "displayOrder": 11}, "walking": {"sportTypeId": 12, "sportTypeKey": "walking", "displayOrder": 10}, "rucking": {"sportTypeId": 13, "sportTypeKey": "rucking", "displayOrder": 12}, } SPORT_ID_MAPPINGS = {v["sportTypeId"]: v for v in SPORT_TYPE_MAPPINGS.values()} def _resolve_sport_block(st): if isinstance(st, str): k = st.strip().lower() if k in SPORT_TYPE_MAPPINGS: return dict(SPORT_TYPE_MAPPINGS[k]) elif isinstance(st, dict): key = st.get("sportTypeKey") sid = st.get("sportTypeId") if key and str(key).strip().lower() in SPORT_TYPE_MAPPINGS: base = dict(SPORT_TYPE_MAPPINGS[str(key).strip().lower()]) if sid is not None and sid != 0 and sid != base["sportTypeId"]: raise ValueError(f"sportType mismatch: {key} vs {sid}") return base if sid is not None and sid in SPORT_ID_MAPPINGS: return dict(SPORT_ID_MAPPINGS[sid]) return None def _normalize_sport_type(workout_data: dict) -> None: resolved = _resolve_sport_block(workout_data.get("sportType")) segments = workout_data.get("workoutSegments") or [] if not resolved and segments: for seg in segments: resolved = _resolve_sport_block(seg.get("sportType")) if resolved: break if not resolved: raise ValueError("Missing or invalid sportType. Both sportTypeId and sportTypeKey are required.") workout_data["sportType"] = resolved for seg in segments: st = _resolve_sport_block(seg.get("sportType")) seg["sportType"] = st if st else dict(resolved) ''' t = "def _normalize_workout_steps(workout_data: dict) -> None:" if t in c: with open(p, "w") as f: f.write(c.replace(t, patch + t + "\n _normalize_sport_type(workout_data)", 1)) print("Successfully patched garmin_mcp workouts.py!")