feat: workout library read tools (get_workouts, get_workout) #4

Closed
opened 2026-07-20 19:26:39 +00:00 by Chris Farhood · 1 comment
Owner

Part of the 0.3.0 coaching-context milestone. Expose the reusable workout
library — distinct from the calendar events we already handle.

Tools

  • get_workoutsGET /athlete/{id}/workouts — list library workouts (optionally by folder)
  • get_workoutGET /athlete/{id}/workouts/{id} — a single library workout's structure

Notes

  • Read-only for 0.3.0 (create/update/delete + folders deferred). Register + tests.
Part of the **0.3.0** coaching-context milestone. Expose the reusable workout library — distinct from the calendar *events* we already handle. ### Tools - `get_workouts` — `GET /athlete/{id}/workouts` — list library workouts (optionally by folder) - `get_workout` — `GET /athlete/{id}/workouts/{id}` — a single library workout's structure ### Notes - Read-only for 0.3.0 (create/update/delete + folders deferred). Register + tests.
Chris Farhood added this to the 0.3.0 milestone 2026-07-20 19:26:39 +00:00
Author
Owner

Implementation plan (0.3.0) — intended delivery model: Claude Opus 4.8

Branch: feat/coaching-context; one conventional feat: commit for this issue.

Endpoints (verified)

  • GET /athlete/{id}/workouts -> Workout[]no server-side folder filter (the path takes no query params), so any folder filtering is client-side via each workout's folder_id.
  • GET /athlete/{id}/workouts/{workoutId}workoutId is an integer -> full Workout incl. workout_doc.

Workout schema (28 props, key ones to render)

id, name, description, type, sub_type, indoor, moving_time, distance, icu_training_load, icu_intensity, target, carbs_per_hour, folder_id, tags, workout_doc

New module: tools/workouts.py

  1. get_workouts(folder_id: int | None = None, type: str | None = None) — list the library; optional client-side filters on folder_id/type (documented as client-side). Compact per-row formatter: id, name, type, load, moving_time, folder_id.
  2. get_workout(workout_id: int) — full detail. Render workout_doc steps human-readably: reuse the step vocabulary documented in add_or_update_event (power/hr/pace + %ftp/zones units, reps/nested steps, warmup/cooldown/freeride flags). New format_workout_details in utils/formatting.py; the existing format_workout helper is a good base but too thin — extend, don't fork.

Notes

  • Read-only in 0.3.0; create/update/delete + folder CRUD + /folders/{id}/workouts explicitly deferred to a 0.4.0 issue.
  • workout_doc can nest (reps + steps) — the renderer must recurse; cap depth defensively.

Tests (tests/test_workouts.py)

  • Request shape (int coercion in URL), client-side filter behavior, nested workout_doc rendering fixture, empty library, error dict, CredentialError. Coverage gate >=90%.

Estimate

~300 LOC incl. tests.

## Implementation plan (0.3.0) — intended delivery model: Claude Opus 4.8 **Branch:** `feat/coaching-context`; one conventional `feat:` commit for this issue. ### Endpoints (verified) - `GET /athlete/{id}/workouts` -> `Workout[]` — **no server-side folder filter** (the path takes no query params), so any folder filtering is client-side via each workout's `folder_id`. - `GET /athlete/{id}/workouts/{workoutId}` — `workoutId` is an **integer** -> full `Workout` incl. `workout_doc`. ### Workout schema (28 props, key ones to render) `id, name, description, type, sub_type, indoor, moving_time, distance, icu_training_load, icu_intensity, target, carbs_per_hour, folder_id, tags, workout_doc` ### New module: `tools/workouts.py` 1. **`get_workouts(folder_id: int | None = None, type: str | None = None)`** — list the library; optional client-side filters on `folder_id`/`type` (documented as client-side). Compact per-row formatter: id, name, type, load, moving_time, folder_id. 2. **`get_workout(workout_id: int)`** — full detail. Render `workout_doc` steps human-readably: reuse the step vocabulary documented in `add_or_update_event` (power/hr/pace + `%ftp`/zones units, reps/nested steps, warmup/cooldown/freeride flags). New `format_workout_details` in `utils/formatting.py`; the existing `format_workout` helper is a good base but too thin — extend, don't fork. ### Notes - Read-only in 0.3.0; create/update/delete + folder CRUD + `/folders/{id}/workouts` explicitly deferred to a 0.4.0 issue. - `workout_doc` can nest (`reps` + `steps`) — the renderer must recurse; cap depth defensively. ### Tests (`tests/test_workouts.py`) - Request shape (int coercion in URL), client-side filter behavior, nested `workout_doc` rendering fixture, empty library, error dict, CredentialError. Coverage gate >=90%. ### Estimate ~300 LOC incl. tests.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: farhoodlabs/intervalsicu-mcp#4