intervals-icu-mcp-server 0.1.4 → 0.1.6
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/dist/client.d.ts +89 -85
- package/dist/client.js +44 -39
- package/dist/format.d.ts +2 -1
- package/dist/format.js +66 -11
- package/dist/index.js +22 -36
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -7,17 +7,17 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
7
7
|
id: z.ZodString;
|
|
8
8
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
9
9
|
type: z.ZodOptional<z.ZodString>;
|
|
10
|
-
|
|
10
|
+
start_date_local: z.ZodOptional<z.ZodString>;
|
|
11
11
|
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
12
|
-
|
|
12
|
+
elapsed_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
13
13
|
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
total_elevation_gain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
15
|
+
icu_average_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
16
16
|
icu_weighted_avg_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
17
|
-
|
|
17
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
18
18
|
icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
19
19
|
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
20
|
-
|
|
20
|
+
average_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
21
21
|
max_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
22
22
|
average_cadence: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
23
23
|
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -27,6 +27,8 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
27
27
|
trimp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
28
28
|
average_temp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
29
29
|
perceived_exertion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
30
|
+
icu_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
31
|
+
session_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
30
32
|
feel: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
31
33
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
32
34
|
trainer: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
@@ -34,17 +36,17 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
34
36
|
id: z.ZodString;
|
|
35
37
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
36
38
|
type: z.ZodOptional<z.ZodString>;
|
|
37
|
-
|
|
39
|
+
start_date_local: z.ZodOptional<z.ZodString>;
|
|
38
40
|
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
39
|
-
|
|
41
|
+
elapsed_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
40
42
|
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
total_elevation_gain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
44
|
+
icu_average_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
43
45
|
icu_weighted_avg_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
44
|
-
|
|
46
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
45
47
|
icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
46
48
|
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
47
|
-
|
|
49
|
+
average_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
48
50
|
max_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
49
51
|
average_cadence: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
50
52
|
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -54,6 +56,8 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
54
56
|
trimp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
55
57
|
average_temp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
56
58
|
perceived_exertion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
59
|
+
icu_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
60
|
+
session_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
57
61
|
feel: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
58
62
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
59
63
|
trainer: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
@@ -61,17 +65,17 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
61
65
|
id: z.ZodString;
|
|
62
66
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
63
67
|
type: z.ZodOptional<z.ZodString>;
|
|
64
|
-
|
|
68
|
+
start_date_local: z.ZodOptional<z.ZodString>;
|
|
65
69
|
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
66
|
-
|
|
70
|
+
elapsed_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
67
71
|
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
total_elevation_gain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
73
|
+
icu_average_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
70
74
|
icu_weighted_avg_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
71
|
-
|
|
75
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
72
76
|
icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
73
77
|
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
74
|
-
|
|
78
|
+
average_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
75
79
|
max_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
76
80
|
average_cadence: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
77
81
|
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -81,6 +85,8 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
81
85
|
trimp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
82
86
|
average_temp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
83
87
|
perceived_exertion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
88
|
+
icu_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
89
|
+
session_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
84
90
|
feel: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
85
91
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
86
92
|
trainer: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
@@ -160,46 +166,52 @@ export type Wellness = z.infer<typeof WellnessSchema>;
|
|
|
160
166
|
export declare const EventSchema: z.ZodObject<{
|
|
161
167
|
id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
162
168
|
date: z.ZodOptional<z.ZodString>;
|
|
169
|
+
start_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
170
|
+
end_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
171
|
+
category: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
172
|
+
show_as_note: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
163
173
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
164
174
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
165
|
-
|
|
166
|
-
workout: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
167
|
-
priority: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
175
|
+
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
168
176
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
169
177
|
id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
170
178
|
date: z.ZodOptional<z.ZodString>;
|
|
179
|
+
start_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
180
|
+
end_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
181
|
+
category: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
182
|
+
show_as_note: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
171
183
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
172
184
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
173
|
-
|
|
174
|
-
workout: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
175
|
-
priority: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
185
|
+
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
176
186
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
177
187
|
id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
178
188
|
date: z.ZodOptional<z.ZodString>;
|
|
189
|
+
start_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
190
|
+
end_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
191
|
+
category: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
192
|
+
show_as_note: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
179
193
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
180
194
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
181
|
-
|
|
182
|
-
workout: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
183
|
-
priority: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
195
|
+
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
184
196
|
}, z.ZodTypeAny, "passthrough">>;
|
|
185
197
|
export type Event = z.infer<typeof EventSchema>;
|
|
186
198
|
export declare const IntervalSchema: z.ZodObject<{
|
|
187
|
-
icu_intervals: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many"
|
|
188
|
-
icu_groups: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many"
|
|
199
|
+
icu_intervals: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
|
|
200
|
+
icu_groups: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
|
|
189
201
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
190
|
-
icu_intervals: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many"
|
|
191
|
-
icu_groups: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many"
|
|
202
|
+
icu_intervals: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
|
|
203
|
+
icu_groups: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
|
|
192
204
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
193
|
-
icu_intervals: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many"
|
|
194
|
-
icu_groups: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many"
|
|
205
|
+
icu_intervals: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
|
|
206
|
+
icu_groups: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
|
|
195
207
|
}, z.ZodTypeAny, "passthrough">>;
|
|
196
208
|
export interface EventInput {
|
|
197
209
|
name?: string;
|
|
198
210
|
description?: string;
|
|
199
211
|
start_date_local?: string;
|
|
212
|
+
end_date_local?: string;
|
|
200
213
|
category?: string;
|
|
201
214
|
type?: string;
|
|
202
|
-
race?: boolean;
|
|
203
215
|
distance?: number;
|
|
204
216
|
sub_type?: string;
|
|
205
217
|
workout_doc?: unknown;
|
|
@@ -210,99 +222,91 @@ export declare const AthleteSchema: z.ZodObject<{
|
|
|
210
222
|
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
211
223
|
sex: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
212
224
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
213
|
-
|
|
225
|
+
icu_date_of_birth: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
214
226
|
city: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
215
227
|
country: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
216
|
-
icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
217
|
-
icu_lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
218
228
|
icu_resting_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
219
229
|
icu_weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
220
|
-
icu_vo2max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
221
230
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
222
231
|
id: z.ZodOptional<z.ZodString>;
|
|
223
232
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
224
233
|
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
225
234
|
sex: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
226
235
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
227
|
-
|
|
236
|
+
icu_date_of_birth: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
228
237
|
city: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
229
238
|
country: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
230
|
-
icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
231
|
-
icu_lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
232
239
|
icu_resting_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
233
240
|
icu_weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
234
|
-
icu_vo2max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
235
241
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
236
242
|
id: z.ZodOptional<z.ZodString>;
|
|
237
243
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
238
244
|
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
239
245
|
sex: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
240
246
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
241
|
-
|
|
247
|
+
icu_date_of_birth: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
242
248
|
city: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
243
249
|
country: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
244
|
-
icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
245
|
-
icu_lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
246
250
|
icu_resting_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
247
251
|
icu_weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
248
|
-
icu_vo2max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
249
252
|
}, z.ZodTypeAny, "passthrough">>;
|
|
250
253
|
export type Athlete = z.infer<typeof AthleteSchema>;
|
|
251
|
-
export declare const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
ctlLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
264
|
-
atlLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
265
|
-
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
266
|
-
ctl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
267
|
-
atl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
268
|
-
tsb: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
269
|
-
rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
270
|
-
ctlLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
271
|
-
atlLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
272
|
-
}, z.ZodTypeAny, "passthrough">>;
|
|
273
|
-
export type AthleteSummary = z.infer<typeof AthleteSummarySchema>;
|
|
274
|
-
export declare const ZonesSchema: z.ZodObject<{
|
|
275
|
-
power: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
|
|
276
|
-
hr: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
|
|
277
|
-
pace: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
|
|
254
|
+
export declare const SportSettingsSchema: z.ZodObject<{
|
|
255
|
+
types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
256
|
+
ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
257
|
+
lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
258
|
+
max_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
259
|
+
threshold_pace: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
260
|
+
power_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
261
|
+
power_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
262
|
+
hr_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
263
|
+
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
264
|
+
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
265
|
+
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
278
266
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
267
|
+
types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
268
|
+
ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
269
|
+
lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
270
|
+
max_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
271
|
+
threshold_pace: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
272
|
+
power_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
273
|
+
power_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
274
|
+
hr_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
275
|
+
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
276
|
+
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
277
|
+
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
282
278
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
279
|
+
types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
280
|
+
ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
281
|
+
lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
282
|
+
max_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
283
|
+
threshold_pace: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
284
|
+
power_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
285
|
+
power_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
286
|
+
hr_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
287
|
+
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
288
|
+
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
289
|
+
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
286
290
|
}, z.ZodTypeAny, "passthrough">>;
|
|
287
|
-
export type
|
|
291
|
+
export type SportSettings = z.infer<typeof SportSettingsSchema>;
|
|
288
292
|
export declare const WorkoutSchema: z.ZodObject<{
|
|
289
293
|
id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
290
294
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
291
295
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
292
296
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
293
|
-
|
|
297
|
+
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
294
298
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
295
299
|
id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
296
300
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
297
301
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
298
302
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
299
|
-
|
|
303
|
+
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
300
304
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
301
305
|
id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
302
306
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
303
307
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
304
308
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
305
|
-
|
|
309
|
+
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
306
310
|
}, z.ZodTypeAny, "passthrough">>;
|
|
307
311
|
export type Workout = z.infer<typeof WorkoutSchema>;
|
|
308
312
|
export interface WorkoutInput {
|
|
@@ -352,8 +356,8 @@ export declare function createEvent(config: ClientConfig, input: EventInput): Pr
|
|
|
352
356
|
export declare function updateEvent(config: ClientConfig, eventId: string, input: EventInput): Promise<Event>;
|
|
353
357
|
export declare function deleteEvent(config: ClientConfig, eventId: string): Promise<void>;
|
|
354
358
|
export declare function getAthleteProfile(config: ClientConfig): Promise<Athlete>;
|
|
355
|
-
export declare function getAthleteZones(config: ClientConfig): Promise<
|
|
356
|
-
export declare function getAthleteSummary(config: ClientConfig): Promise<
|
|
359
|
+
export declare function getAthleteZones(config: ClientConfig): Promise<SportSettings[]>;
|
|
360
|
+
export declare function getAthleteSummary(config: ClientConfig): Promise<AthleteFitness | undefined>;
|
|
357
361
|
export declare function getWellnessDay(config: ClientConfig, date: string): Promise<Wellness>;
|
|
358
362
|
export declare function updateWellness(config: ClientConfig, date: string, input: WellnessInput): Promise<Wellness>;
|
|
359
363
|
export declare function getActivityStreams(config: ClientConfig, activityId: string, types?: string[]): Promise<Record<string, unknown[]>>;
|
package/dist/client.js
CHANGED
|
@@ -28,17 +28,17 @@ export const ActivitySchema = z.object({
|
|
|
28
28
|
id: z.string(),
|
|
29
29
|
name: z.string().nullable().optional(),
|
|
30
30
|
type: z.string().optional(),
|
|
31
|
-
|
|
31
|
+
start_date_local: z.string().optional(),
|
|
32
32
|
distance: z.number().nullable().optional(),
|
|
33
|
-
|
|
33
|
+
elapsed_time: z.number().nullable().optional(),
|
|
34
34
|
moving_time: z.number().nullable().optional(),
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
total_elevation_gain: z.number().nullable().optional(),
|
|
36
|
+
icu_average_watts: z.number().nullable().optional(),
|
|
37
37
|
icu_weighted_avg_watts: z.number().nullable().optional(),
|
|
38
|
-
|
|
38
|
+
icu_training_load: z.number().nullable().optional(),
|
|
39
39
|
icu_ftp: z.number().nullable().optional(),
|
|
40
40
|
icu_intensity: z.number().nullable().optional(),
|
|
41
|
-
|
|
41
|
+
average_heartrate: z.number().nullable().optional(),
|
|
42
42
|
max_heartrate: z.number().nullable().optional(),
|
|
43
43
|
average_cadence: z.number().nullable().optional(),
|
|
44
44
|
calories: z.number().nullable().optional(),
|
|
@@ -48,6 +48,8 @@ export const ActivitySchema = z.object({
|
|
|
48
48
|
trimp: z.number().nullable().optional(),
|
|
49
49
|
average_temp: z.number().nullable().optional(),
|
|
50
50
|
perceived_exertion: z.number().nullable().optional(),
|
|
51
|
+
icu_rpe: z.number().nullable().optional(),
|
|
52
|
+
session_rpe: z.number().nullable().optional(),
|
|
51
53
|
feel: z.number().nullable().optional(),
|
|
52
54
|
description: z.string().nullable().optional(),
|
|
53
55
|
trainer: z.boolean().nullable().optional(),
|
|
@@ -79,15 +81,17 @@ export const WellnessSchema = z.object({
|
|
|
79
81
|
export const EventSchema = z.object({
|
|
80
82
|
id: z.union([z.string(), z.number()]),
|
|
81
83
|
date: z.string().optional(),
|
|
84
|
+
start_date_local: z.string().nullable().optional(),
|
|
85
|
+
end_date_local: z.string().nullable().optional(),
|
|
86
|
+
category: z.string().nullable().optional(),
|
|
87
|
+
show_as_note: z.boolean().nullable().optional(),
|
|
82
88
|
name: z.string().nullable().optional(),
|
|
83
89
|
description: z.string().nullable().optional(),
|
|
84
|
-
|
|
85
|
-
workout: z.unknown().nullable().optional(),
|
|
86
|
-
priority: z.string().nullable().optional(),
|
|
90
|
+
color: z.string().nullable().optional(),
|
|
87
91
|
}).passthrough();
|
|
88
92
|
export const IntervalSchema = z.object({
|
|
89
|
-
icu_intervals: z.array(z.record(z.unknown())).optional(),
|
|
90
|
-
icu_groups: z.array(z.record(z.unknown())).optional(),
|
|
93
|
+
icu_intervals: z.array(z.record(z.unknown())).nullable().optional(),
|
|
94
|
+
icu_groups: z.array(z.record(z.unknown())).nullable().optional(),
|
|
91
95
|
}).passthrough();
|
|
92
96
|
export const AthleteSchema = z.object({
|
|
93
97
|
id: z.string().optional(),
|
|
@@ -95,34 +99,31 @@ export const AthleteSchema = z.object({
|
|
|
95
99
|
email: z.string().nullable().optional(),
|
|
96
100
|
sex: z.string().nullable().optional(),
|
|
97
101
|
weight: z.number().nullable().optional(),
|
|
98
|
-
|
|
102
|
+
icu_date_of_birth: z.string().nullable().optional(),
|
|
99
103
|
city: z.string().nullable().optional(),
|
|
100
104
|
country: z.string().nullable().optional(),
|
|
101
|
-
icu_ftp: z.number().nullable().optional(),
|
|
102
|
-
icu_lthr: z.number().nullable().optional(),
|
|
103
105
|
icu_resting_hr: z.number().nullable().optional(),
|
|
104
106
|
icu_weight: z.number().nullable().optional(),
|
|
105
|
-
icu_vo2max: z.number().nullable().optional(),
|
|
106
107
|
}).passthrough();
|
|
107
|
-
export const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
108
|
+
export const SportSettingsSchema = z.object({
|
|
109
|
+
types: z.array(z.string()).nullable().optional(),
|
|
110
|
+
ftp: z.number().nullable().optional(),
|
|
111
|
+
lthr: z.number().nullable().optional(),
|
|
112
|
+
max_hr: z.number().nullable().optional(),
|
|
113
|
+
threshold_pace: z.number().nullable().optional(),
|
|
114
|
+
power_zones: z.array(z.number()).nullable().optional(),
|
|
115
|
+
power_zone_names: z.array(z.string()).nullable().optional(),
|
|
116
|
+
hr_zones: z.array(z.number()).nullable().optional(),
|
|
117
|
+
hr_zone_names: z.array(z.string()).nullable().optional(),
|
|
118
|
+
pace_zones: z.array(z.number()).nullable().optional(),
|
|
119
|
+
pace_zone_names: z.array(z.string()).nullable().optional(),
|
|
119
120
|
}).passthrough();
|
|
120
121
|
export const WorkoutSchema = z.object({
|
|
121
122
|
id: z.union([z.string(), z.number()]).optional(),
|
|
122
123
|
name: z.string().nullable().optional(),
|
|
123
124
|
description: z.string().nullable().optional(),
|
|
124
125
|
type: z.string().nullable().optional(),
|
|
125
|
-
|
|
126
|
+
updated: z.string().nullable().optional(),
|
|
126
127
|
}).passthrough();
|
|
127
128
|
// ---- API methods ---- //
|
|
128
129
|
export async function getActivities(config, params) {
|
|
@@ -161,10 +162,7 @@ export async function getEventById(config, eventId) {
|
|
|
161
162
|
export async function getNotesByDate(config, date) {
|
|
162
163
|
const data = await request(`/athlete/${config.athleteId}/events`, config, { oldest: date, newest: date });
|
|
163
164
|
const events = z.array(EventSchema).parse(data);
|
|
164
|
-
return events.filter((e) =>
|
|
165
|
-
const raw = e;
|
|
166
|
-
return raw["category"] === "NOTE" || (!e.race && !e.workout);
|
|
167
|
-
});
|
|
165
|
+
return events.filter((e) => e.category === "NOTE" || e.show_as_note === true);
|
|
168
166
|
}
|
|
169
167
|
async function mutate(method, path, config, body) {
|
|
170
168
|
const url = `${BASE_URL}${path}`;
|
|
@@ -202,12 +200,14 @@ export async function getAthleteProfile(config) {
|
|
|
202
200
|
return AthleteSchema.parse(data);
|
|
203
201
|
}
|
|
204
202
|
export async function getAthleteZones(config) {
|
|
205
|
-
const data = await request(`/athlete/${config.athleteId}/
|
|
206
|
-
return
|
|
203
|
+
const data = await request(`/athlete/${config.athleteId}/sport-settings`, config);
|
|
204
|
+
return z.array(SportSettingsSchema).parse(data);
|
|
207
205
|
}
|
|
208
206
|
export async function getAthleteSummary(config) {
|
|
209
|
-
const
|
|
210
|
-
|
|
207
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
208
|
+
const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
|
|
209
|
+
const entries = await getAthleteFitness(config, { startDate: weekAgo, endDate: today });
|
|
210
|
+
return entries.at(-1);
|
|
211
211
|
}
|
|
212
212
|
export async function getWellnessDay(config, date) {
|
|
213
213
|
const data = await request(`/athlete/${config.athleteId}/wellness/${date}`, config);
|
|
@@ -222,7 +222,12 @@ export async function getActivityStreams(config, activityId, types) {
|
|
|
222
222
|
if (types?.length)
|
|
223
223
|
params["types"] = types.join(",");
|
|
224
224
|
const data = await request(`/activity/${activityId}/streams.json`, config, params);
|
|
225
|
-
|
|
225
|
+
const result = {};
|
|
226
|
+
for (const stream of data) {
|
|
227
|
+
if (stream.type)
|
|
228
|
+
result[stream.type] = stream.data ?? [];
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
226
231
|
}
|
|
227
232
|
export async function getActivityPowerCurves(config, activityId) {
|
|
228
233
|
return request(`/activity/${activityId}/power-curves`, config);
|
|
@@ -240,7 +245,7 @@ export async function bulkCreateEvents(config, events) {
|
|
|
240
245
|
return z.array(EventSchema).parse(data);
|
|
241
246
|
}
|
|
242
247
|
export async function bulkDeleteEvents(config, eventIds) {
|
|
243
|
-
await mutate("
|
|
248
|
+
await mutate("PUT", `/athlete/${config.athleteId}/events/bulk-delete`, config, eventIds.map((id) => ({ id: Number(id) })));
|
|
244
249
|
}
|
|
245
250
|
export const AthleteFitnessSchema = z.object({
|
|
246
251
|
date: z.string().optional(),
|
|
@@ -254,7 +259,7 @@ export const AthleteFitnessSchema = z.object({
|
|
|
254
259
|
weight: z.number().nullable().optional(),
|
|
255
260
|
}).passthrough();
|
|
256
261
|
export async function getAthleteFitness(config, params) {
|
|
257
|
-
const data = await request(`/athlete/${config.athleteId}/athlete-summary.json`, config, {
|
|
262
|
+
const data = await request(`/athlete/${config.athleteId}/athlete-summary.json`, config, { start: params.startDate, end: params.endDate });
|
|
258
263
|
const all = z.array(AthleteFitnessSchema).parse(data);
|
|
259
264
|
return all.filter((e) => e["athlete_id"] === config.athleteId);
|
|
260
265
|
}
|
package/dist/format.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { Activity, Wellness, Event } from "./client.js";
|
|
1
|
+
import type { Activity, Wellness, Event, SportSettings } from "./client.js";
|
|
2
2
|
export declare function formatActivity(a: Activity): string;
|
|
3
3
|
export declare function formatWellness(date: string, w: Wellness): string;
|
|
4
4
|
export declare function formatEvent(e: Event): string;
|
|
5
|
+
export declare function formatSportZones(s: SportSettings): string;
|
|
5
6
|
export declare function formatIntervalRow(interval: Record<string, unknown>, idx: number): string;
|
package/dist/format.js
CHANGED
|
@@ -4,26 +4,26 @@ function n(v, unit = "") {
|
|
|
4
4
|
return `${v}${unit}`;
|
|
5
5
|
}
|
|
6
6
|
export function formatActivity(a) {
|
|
7
|
-
const startTime = a.
|
|
8
|
-
? new Date(a.
|
|
7
|
+
const startTime = a.start_date_local
|
|
8
|
+
? new Date(a.start_date_local).toLocaleString()
|
|
9
9
|
: "Unknown";
|
|
10
10
|
const lines = [
|
|
11
11
|
`**${a.name ?? "Unnamed"}** (${a.id})`,
|
|
12
12
|
`Type: ${n(a.type)} | Date: ${startTime}`,
|
|
13
|
-
`Distance: ${n(a.distance, " m")} | Duration: ${n(a.
|
|
14
|
-
`Elevation: ${n(a.
|
|
13
|
+
`Distance: ${n(a.distance, " m")} | Duration: ${n(a.elapsed_time, " s")} | Moving: ${n(a.moving_time, " s")}`,
|
|
14
|
+
`Elevation: ${n(a.total_elevation_gain, " m")}`,
|
|
15
15
|
"",
|
|
16
16
|
"Power:",
|
|
17
|
-
` Avg: ${n(a.
|
|
18
|
-
` Training Load: ${n(a.
|
|
17
|
+
` Avg: ${n(a.icu_average_watts, " W")} | Weighted Avg: ${n(a.icu_weighted_avg_watts, " W")} | FTP: ${n(a.icu_ftp, " W")}`,
|
|
18
|
+
` Training Load: ${n(a.icu_training_load)} | Intensity: ${n(a.icu_intensity)}`,
|
|
19
19
|
"",
|
|
20
20
|
"Heart Rate:",
|
|
21
|
-
` Avg: ${n(a.
|
|
21
|
+
` Avg: ${n(a.average_heartrate, " bpm")} | Max: ${n(a.max_heartrate, " bpm")}`,
|
|
22
22
|
"",
|
|
23
23
|
"Other:",
|
|
24
24
|
` Cadence: ${n(a.average_cadence, " rpm")} | Calories: ${n(a.calories)} | Speed: ${n(a.average_speed, " m/s")}`,
|
|
25
25
|
` Temp: ${n(a.average_temp, "°C")} | Trainer: ${a.trainer ? "Yes" : "No"}`,
|
|
26
|
-
` RPE: ${n(a.perceived_exertion)}/10 | Feel: ${n(a.feel)}/10`,
|
|
26
|
+
` RPE: ${n(a.icu_rpe ?? a.perceived_exertion)}/10 | Feel: ${n(a.feel)}/10`,
|
|
27
27
|
"",
|
|
28
28
|
"Fitness:",
|
|
29
29
|
` CTL: ${n(a.icu_ctl)} | ATL: ${n(a.icu_atl)} | TRIMP: ${n(a.trimp)}`,
|
|
@@ -62,16 +62,71 @@ export function formatWellness(date, w) {
|
|
|
62
62
|
.trimEnd();
|
|
63
63
|
}
|
|
64
64
|
export function formatEvent(e) {
|
|
65
|
-
const
|
|
65
|
+
const category = e.category ?? "";
|
|
66
|
+
const type = category.startsWith("RACE")
|
|
67
|
+
? "Race"
|
|
68
|
+
: category === "WORKOUT"
|
|
69
|
+
? "Workout"
|
|
70
|
+
: category === "NOTE" || e.show_as_note
|
|
71
|
+
? "Note"
|
|
72
|
+
: "Event";
|
|
73
|
+
const start = e.start_date_local ?? e.date ?? "Unknown";
|
|
74
|
+
const dateLabel = e.end_date_local && e.end_date_local !== e.start_date_local
|
|
75
|
+
? `${start} to ${e.end_date_local}`
|
|
76
|
+
: start;
|
|
66
77
|
return [
|
|
67
78
|
`**${e.name ?? "Unnamed"}** (${e.id})`,
|
|
68
|
-
`Type: ${type} | Date: ${
|
|
79
|
+
`Type: ${type} | Date: ${dateLabel}`,
|
|
80
|
+
e.category ? `Category: ${e.category}` : "",
|
|
69
81
|
e.description ? `Description: ${e.description}` : "",
|
|
70
|
-
e.priority ? `Priority: ${e.priority}` : "",
|
|
71
82
|
]
|
|
72
83
|
.filter(Boolean)
|
|
73
84
|
.join("\n");
|
|
74
85
|
}
|
|
86
|
+
function zoneRanges(breakpoints, names) {
|
|
87
|
+
const count = names?.length ?? (breakpoints?.length ?? 0) + 1;
|
|
88
|
+
const ranges = [];
|
|
89
|
+
let from = 0;
|
|
90
|
+
for (let i = 0; i < count; i++) {
|
|
91
|
+
const raw = breakpoints && i < breakpoints.length ? breakpoints[i] : null;
|
|
92
|
+
// Intervals.icu caps the top zone with a 999 sentinel meaning "no upper bound".
|
|
93
|
+
const to = raw != null && raw < 900 ? raw : null;
|
|
94
|
+
ranges.push({ name: names?.[i] ?? `Z${i + 1}`, from, to });
|
|
95
|
+
if (to != null)
|
|
96
|
+
from = to;
|
|
97
|
+
}
|
|
98
|
+
return ranges;
|
|
99
|
+
}
|
|
100
|
+
export function formatSportZones(s) {
|
|
101
|
+
const title = s.types?.length ? s.types.join(", ") : "Default";
|
|
102
|
+
const lines = [`## ${title}`, ""];
|
|
103
|
+
if (s.power_zones?.length) {
|
|
104
|
+
lines.push(`Power Zones${s.ftp != null ? ` (FTP: ${s.ftp}W)` : ""}:`);
|
|
105
|
+
for (const z of zoneRanges(s.power_zones, s.power_zone_names)) {
|
|
106
|
+
const abs = s.ftp != null ? ` (${Math.round((s.ftp * z.from) / 100)}-${z.to != null ? Math.round((s.ftp * z.to) / 100) + "W" : "W+"})` : "";
|
|
107
|
+
const pct = z.to != null ? `${z.from}-${z.to}%` : `${z.from}%+`;
|
|
108
|
+
lines.push(` ${z.name}: ${pct}${abs}`);
|
|
109
|
+
}
|
|
110
|
+
lines.push("");
|
|
111
|
+
}
|
|
112
|
+
if (s.hr_zones?.length) {
|
|
113
|
+
lines.push(`HR Zones${s.lthr != null ? ` (LTHR: ${s.lthr}bpm)` : ""}:`);
|
|
114
|
+
for (const z of zoneRanges(s.hr_zones, s.hr_zone_names)) {
|
|
115
|
+
const abs = s.lthr != null ? ` (${Math.round((s.lthr * z.from) / 100)}-${z.to != null ? Math.round((s.lthr * z.to) / 100) + "bpm" : "bpm+"})` : "";
|
|
116
|
+
const pct = z.to != null ? `${z.from}-${z.to}%` : `${z.from}%+`;
|
|
117
|
+
lines.push(` ${z.name}: ${pct}${abs}`);
|
|
118
|
+
}
|
|
119
|
+
lines.push("");
|
|
120
|
+
}
|
|
121
|
+
if (s.pace_zones?.length) {
|
|
122
|
+
lines.push("Pace Zones (% of threshold pace):");
|
|
123
|
+
for (const z of zoneRanges(s.pace_zones, s.pace_zone_names)) {
|
|
124
|
+
const pct = z.to != null ? `${z.from}-${z.to}%` : `${z.from}%+`;
|
|
125
|
+
lines.push(` ${z.name}: ${pct}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return lines.join("\n").trimEnd();
|
|
129
|
+
}
|
|
75
130
|
export function formatIntervalRow(interval, idx) {
|
|
76
131
|
const label = interval["label"] ?? `Interval ${idx}`;
|
|
77
132
|
const type = interval["type"] ?? "Unknown";
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
5
5
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { getActivities, getActivityDetails, getActivityIntervals, getWellness, getEvents, getEventById, getNotesByDate, createEvent, updateEvent, deleteEvent, getAthleteProfile, getAthleteZones, getAthleteSummary, getWellnessDay, updateWellness, getActivityStreams, getActivityPowerCurves, listWorkouts, createWorkout, bulkCreateEvents, bulkDeleteEvents, getAthleteFitness, } from "./client.js";
|
|
8
|
-
import { formatActivity, formatWellness, formatEvent, formatIntervalRow, } from "./format.js";
|
|
8
|
+
import { formatActivity, formatWellness, formatEvent, formatIntervalRow, formatSportZones, } from "./format.js";
|
|
9
9
|
function getConfig(args) {
|
|
10
10
|
const apiKey = args["api_key"] ?? process.env.API_KEY ?? "";
|
|
11
11
|
const athleteId = args["athlete_id"] ??
|
|
@@ -119,11 +119,11 @@ const TOOLS = [
|
|
|
119
119
|
required: ["start_date_local"],
|
|
120
120
|
properties: {
|
|
121
121
|
start_date_local: { type: "string", description: "Date/time in ISO 8601 format, e.g. 2024-06-01T08:00:00" },
|
|
122
|
+
end_date_local: { type: "string", description: "End date in ISO 8601 format for a multi-day event (e.g. a NOTE, HOLIDAY, SICK, or INJURED entry spanning several days), e.g. 2024-06-05" },
|
|
122
123
|
name: { type: "string", description: "Event name" },
|
|
123
124
|
description: { type: "string", description: "Event description. To create a structured workout, write it in Intervals.icu's Workout Builder plain-text syntax — Intervals.icu parses this into the workout structure (steps, duration, zones) automatically. Syntax: each step is a line starting with '-', e.g. '-10m 50-60%' (duration as h/m/s combos like '1h20m', '3m30s', '20s'; intensity as a %FTP value/range, or a zone like 'z1'/'z4'). Append 'power=Ns' to set the power-smoothing window (power=10s for steady efforts, power=3s or power=1s for short hard efforts/sprints/kicks). HR-based targets: 'z4 90% hr'. Optional cadence suffix: '85-95rpm'. Repeats: put 'Nx' on its own line, then the repeated step lines, then a blank line before the next block. Example: \"- Warmup 10m 50%\\n\\n4x\\n- Hard 4m 105% power=10s\\n- Easy 2m 50%\\n\\n- Cooldown 5m 50%\\n\"" },
|
|
124
|
-
category: { type: "string", description: "Event category: WORKOUT, NOTE, RACE_A, RACE_B, RACE_C (race priority A/B/C)" },
|
|
125
|
+
category: { type: "string", description: "Event category: WORKOUT, NOTE, RACE_A, RACE_B, RACE_C (race priority A/B/C — this is what makes it a race, there is no separate race flag), PLAN, HOLIDAY, SICK, INJURED, TARGET, and others" },
|
|
125
126
|
type: { type: "string", description: "Activity type: Ride, Run, Swim, WeightTraining, etc." },
|
|
126
|
-
race: { type: "boolean", description: "Mark as a race event (default: false)" },
|
|
127
127
|
distance: { type: "number", description: "Distance in meters (e.g. 100000 for 100km)" },
|
|
128
128
|
sub_type: { type: "string", description: "Race category/sub-type (e.g. A, B, C)" },
|
|
129
129
|
workout_doc: { type: "object", description: "Pre-computed Intervals.icu workout_doc (as returned by get_event_by_id/list_workouts on an existing structured workout) to copy verbatim onto this event. Hand-written partial docs won't render correctly — prefer setting `description` with the Workout Builder syntax and omitting this field so Intervals.icu computes it." },
|
|
@@ -141,11 +141,11 @@ const TOOLS = [
|
|
|
141
141
|
properties: {
|
|
142
142
|
event_id: { type: "string", description: "The event ID to update" },
|
|
143
143
|
start_date_local: { type: "string", description: "New date/time (moves the event), e.g. 2024-06-05T08:00:00" },
|
|
144
|
+
end_date_local: { type: "string", description: "New end date for a multi-day event (e.g. a NOTE, HOLIDAY, SICK, or INJURED entry spanning several days), e.g. 2024-06-08" },
|
|
144
145
|
name: { type: "string", description: "New event name" },
|
|
145
146
|
description: { type: "string", description: "New description. Use Intervals.icu's Workout Builder plain-text syntax to have Intervals.icu recompute the workout structure — steps as '-<duration> <intensity>' lines (duration as h/m/s combos, intensity as %FTP or a zone like 'z1'), optional 'power=Ns' smoothing suffix, 'Nx' repeat blocks, HR targets ('z4 90% hr'), cadence suffix ('85-95rpm'). Example: \"- Warmup 10m 50%\\n\\n4x\\n- Hard 4m 105% power=10s\\n- Easy 2m 50%\\n\\n- Cooldown 5m 50%\\n\"" },
|
|
146
147
|
category: { type: "string", description: "New category" },
|
|
147
148
|
type: { type: "string", description: "New activity type" },
|
|
148
|
-
race: { type: "boolean", description: "Toggle race flag" },
|
|
149
149
|
distance: { type: "number", description: "Distance in meters (e.g. 100000 for 100km)" },
|
|
150
150
|
sub_type: { type: "string", description: "Race category/sub-type (e.g. A, B, C)" },
|
|
151
151
|
workout_doc: { type: "object", description: "Pre-computed Intervals.icu workout_doc to copy verbatim. Hand-written partial docs won't render correctly — prefer updating `description` with Workout Builder syntax instead." },
|
|
@@ -169,7 +169,7 @@ const TOOLS = [
|
|
|
169
169
|
},
|
|
170
170
|
{
|
|
171
171
|
name: "get_athlete_profile",
|
|
172
|
-
description: "Get athlete profile
|
|
172
|
+
description: "Get athlete profile: name, sex, DOB, weight, resting HR, city/country. For FTP/LTHR/zones use get_athlete_zones.",
|
|
173
173
|
inputSchema: {
|
|
174
174
|
type: "object",
|
|
175
175
|
properties: {
|
|
@@ -345,7 +345,6 @@ const TOOLS = [
|
|
|
345
345
|
description: { type: "string", description: "Use Workout Builder plain-text syntax for a structured workout — '-<duration> <intensity>' step lines, 'Nx' repeat blocks, optional 'power=Ns' smoothing suffix, HR targets ('z4 90% hr'), cadence suffix ('85-95rpm'). Example: \"- Warmup 10m 50%\\n\\n4x\\n- Hard 4m 105% power=10s\\n- Easy 2m 50%\\n\\n- Cooldown 5m 50%\\n\"" },
|
|
346
346
|
category: { type: "string" },
|
|
347
347
|
type: { type: "string" },
|
|
348
|
-
race: { type: "boolean" },
|
|
349
348
|
workout_doc: { type: "object", description: "Pre-computed workout_doc to copy verbatim; prefer `description` with Workout Builder syntax instead" },
|
|
350
349
|
},
|
|
351
350
|
},
|
|
@@ -511,9 +510,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
511
510
|
name: args["name"],
|
|
512
511
|
description: args["description"],
|
|
513
512
|
start_date_local: z.string().parse(args["start_date_local"]),
|
|
513
|
+
end_date_local: args["end_date_local"],
|
|
514
514
|
category: args["category"],
|
|
515
515
|
type: args["type"],
|
|
516
|
-
race: args["race"],
|
|
517
516
|
distance: args["distance"],
|
|
518
517
|
sub_type: args["sub_type"],
|
|
519
518
|
workout_doc: args["workout_doc"],
|
|
@@ -524,7 +523,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
524
523
|
const eventId = z.string().parse(args["event_id"]);
|
|
525
524
|
const config = getConfig(args);
|
|
526
525
|
const input = {};
|
|
527
|
-
for (const key of ["name", "description", "start_date_local", "
|
|
526
|
+
for (const key of ["name", "description", "start_date_local", "end_date_local", "category", "type", "distance", "sub_type", "workout_doc"]) {
|
|
528
527
|
if (args[key] !== undefined)
|
|
529
528
|
input[key] = args[key];
|
|
530
529
|
}
|
|
@@ -543,47 +542,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
543
542
|
const lines = [
|
|
544
543
|
`**${athlete.name ?? "Athlete"}** (${athlete.id ?? config.athleteId})`,
|
|
545
544
|
athlete.email ? `Email: ${athlete.email}` : "",
|
|
546
|
-
`Sex: ${athlete.sex ?? "N/A"} | DOB: ${athlete.
|
|
545
|
+
`Sex: ${athlete.sex ?? "N/A"} | DOB: ${athlete.icu_date_of_birth ?? "N/A"} | City: ${athlete.city ?? "N/A"}, ${athlete.country ?? "N/A"}`,
|
|
547
546
|
"",
|
|
548
|
-
"
|
|
549
|
-
|
|
550
|
-
` Weight: ${athlete.icu_weight ?? athlete.weight ?? "N/A"} kg | VO2max: ${athlete.icu_vo2max ?? "N/A"}`,
|
|
551
|
-
` Resting HR: ${athlete.icu_resting_hr ?? "N/A"} bpm`,
|
|
547
|
+
`Weight: ${athlete.icu_weight ?? athlete.weight ?? "N/A"} kg | Resting HR: ${athlete.icu_resting_hr ?? "N/A"} bpm`,
|
|
548
|
+
"(FTP/LTHR/zones are per-sport — use get_athlete_zones for those)",
|
|
552
549
|
].filter(Boolean).join("\n");
|
|
553
550
|
return { content: [{ type: "text", text: lines }] };
|
|
554
551
|
}
|
|
555
552
|
case "get_athlete_zones": {
|
|
556
553
|
const config = getConfig(args);
|
|
557
|
-
const
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
zoneList.forEach((z, i) => {
|
|
564
|
-
const name = z["name"] ?? `Zone ${i + 1}`;
|
|
565
|
-
const min = z["min"] ?? z["from"] ?? "";
|
|
566
|
-
const max = z["max"] ?? z["to"] ?? "";
|
|
567
|
-
lines.push(` Z${i + 1} ${name}: ${min}–${max}`);
|
|
568
|
-
});
|
|
569
|
-
lines.push("");
|
|
570
|
-
};
|
|
571
|
-
formatZones("Power", zones.power);
|
|
572
|
-
formatZones("Heart Rate", zones.hr);
|
|
573
|
-
formatZones("Pace", zones.pace);
|
|
574
|
-
if (!lines.length)
|
|
575
|
-
lines.push("No zone data available.");
|
|
576
|
-
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
554
|
+
const sportSettings = await getAthleteZones(config);
|
|
555
|
+
if (!sportSettings.length) {
|
|
556
|
+
return { content: [{ type: "text", text: "No zone data available." }] };
|
|
557
|
+
}
|
|
558
|
+
const text = sportSettings.map(formatSportZones).join("\n\n---\n\n");
|
|
559
|
+
return { content: [{ type: "text", text }] };
|
|
577
560
|
}
|
|
578
561
|
case "get_athlete_summary": {
|
|
579
562
|
const config = getConfig(args);
|
|
580
563
|
const summary = await getAthleteSummary(config);
|
|
564
|
+
if (!summary) {
|
|
565
|
+
return { content: [{ type: "text", text: "No fitness data available." }] };
|
|
566
|
+
}
|
|
581
567
|
const text = [
|
|
582
568
|
"## Current Fitness Snapshot",
|
|
583
569
|
"",
|
|
584
|
-
`CTL (Fitness): ${summary.
|
|
585
|
-
`ATL (Fatigue): ${summary.
|
|
586
|
-
`TSB (Form): ${summary.
|
|
570
|
+
`CTL (Fitness): ${summary.fitness ?? "N/A"}`,
|
|
571
|
+
`ATL (Fatigue): ${summary.fatigue ?? "N/A"}`,
|
|
572
|
+
`TSB (Form): ${summary.form ?? "N/A"}`,
|
|
587
573
|
`Ramp Rate: ${summary.rampRate ?? "N/A"}`,
|
|
588
574
|
].join("\n");
|
|
589
575
|
return { content: [{ type: "text", text }] };
|