intervals-icu-mcp-server 0.2.0 → 0.3.0
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 +266 -0
- package/dist/client.js +69 -0
- package/dist/format.js +56 -25
- package/dist/index.js +59 -2
- package/package.json +2 -2
package/dist/client.d.ts
CHANGED
|
@@ -32,6 +32,60 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
32
32
|
feel: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
33
33
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
34
34
|
trainer: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
35
|
+
decoupling: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
36
|
+
icu_efficiency_factor: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
37
|
+
icu_power_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
38
|
+
icu_variability_index: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
39
|
+
icu_pm_cp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
40
|
+
icu_rolling_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
41
|
+
polarization_index: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
42
|
+
icu_zone_times: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
43
|
+
id: z.ZodString;
|
|
44
|
+
secs: z.ZodNumber;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
id: string;
|
|
47
|
+
secs: number;
|
|
48
|
+
}, {
|
|
49
|
+
id: string;
|
|
50
|
+
secs: number;
|
|
51
|
+
}>, "many">>>;
|
|
52
|
+
icu_hr_zone_times: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
53
|
+
total_elevation_loss: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
54
|
+
max_speed: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
55
|
+
min_altitude: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
56
|
+
max_altitude: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
57
|
+
icu_joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
58
|
+
icu_hrr: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
59
|
+
hrr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
60
|
+
start_bpm: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
61
|
+
end_bpm: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
62
|
+
}, "strip", z.ZodTypeAny, {
|
|
63
|
+
hrr?: number | null | undefined;
|
|
64
|
+
start_bpm?: number | null | undefined;
|
|
65
|
+
end_bpm?: number | null | undefined;
|
|
66
|
+
}, {
|
|
67
|
+
hrr?: number | null | undefined;
|
|
68
|
+
start_bpm?: number | null | undefined;
|
|
69
|
+
end_bpm?: number | null | undefined;
|
|
70
|
+
}>>>;
|
|
71
|
+
strain_score: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
72
|
+
hr_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
73
|
+
power_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
74
|
+
gear: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
75
|
+
id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
76
|
+
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
77
|
+
}, "strip", z.ZodTypeAny, {
|
|
78
|
+
id?: string | null | undefined;
|
|
79
|
+
name?: string | null | undefined;
|
|
80
|
+
}, {
|
|
81
|
+
id?: string | null | undefined;
|
|
82
|
+
name?: string | null | undefined;
|
|
83
|
+
}>>>;
|
|
84
|
+
device_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
85
|
+
power_meter: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
86
|
+
source: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
87
|
+
compliance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
88
|
+
icu_chat_id: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
35
89
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
36
90
|
id: z.ZodString;
|
|
37
91
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -61,6 +115,60 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
61
115
|
feel: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
62
116
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
63
117
|
trainer: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
118
|
+
decoupling: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
119
|
+
icu_efficiency_factor: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
120
|
+
icu_power_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
121
|
+
icu_variability_index: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
122
|
+
icu_pm_cp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
123
|
+
icu_rolling_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
124
|
+
polarization_index: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
125
|
+
icu_zone_times: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
126
|
+
id: z.ZodString;
|
|
127
|
+
secs: z.ZodNumber;
|
|
128
|
+
}, "strip", z.ZodTypeAny, {
|
|
129
|
+
id: string;
|
|
130
|
+
secs: number;
|
|
131
|
+
}, {
|
|
132
|
+
id: string;
|
|
133
|
+
secs: number;
|
|
134
|
+
}>, "many">>>;
|
|
135
|
+
icu_hr_zone_times: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
136
|
+
total_elevation_loss: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
137
|
+
max_speed: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
138
|
+
min_altitude: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
139
|
+
max_altitude: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
140
|
+
icu_joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
141
|
+
icu_hrr: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
142
|
+
hrr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
143
|
+
start_bpm: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
144
|
+
end_bpm: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
145
|
+
}, "strip", z.ZodTypeAny, {
|
|
146
|
+
hrr?: number | null | undefined;
|
|
147
|
+
start_bpm?: number | null | undefined;
|
|
148
|
+
end_bpm?: number | null | undefined;
|
|
149
|
+
}, {
|
|
150
|
+
hrr?: number | null | undefined;
|
|
151
|
+
start_bpm?: number | null | undefined;
|
|
152
|
+
end_bpm?: number | null | undefined;
|
|
153
|
+
}>>>;
|
|
154
|
+
strain_score: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
155
|
+
hr_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
156
|
+
power_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
157
|
+
gear: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
158
|
+
id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
159
|
+
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
160
|
+
}, "strip", z.ZodTypeAny, {
|
|
161
|
+
id?: string | null | undefined;
|
|
162
|
+
name?: string | null | undefined;
|
|
163
|
+
}, {
|
|
164
|
+
id?: string | null | undefined;
|
|
165
|
+
name?: string | null | undefined;
|
|
166
|
+
}>>>;
|
|
167
|
+
device_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
168
|
+
power_meter: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
169
|
+
source: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
170
|
+
compliance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
171
|
+
icu_chat_id: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
64
172
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
65
173
|
id: z.ZodString;
|
|
66
174
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -90,6 +198,60 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
90
198
|
feel: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
91
199
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
92
200
|
trainer: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
201
|
+
decoupling: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
202
|
+
icu_efficiency_factor: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
203
|
+
icu_power_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
204
|
+
icu_variability_index: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
205
|
+
icu_pm_cp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
206
|
+
icu_rolling_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
207
|
+
polarization_index: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
208
|
+
icu_zone_times: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
209
|
+
id: z.ZodString;
|
|
210
|
+
secs: z.ZodNumber;
|
|
211
|
+
}, "strip", z.ZodTypeAny, {
|
|
212
|
+
id: string;
|
|
213
|
+
secs: number;
|
|
214
|
+
}, {
|
|
215
|
+
id: string;
|
|
216
|
+
secs: number;
|
|
217
|
+
}>, "many">>>;
|
|
218
|
+
icu_hr_zone_times: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
219
|
+
total_elevation_loss: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
220
|
+
max_speed: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
221
|
+
min_altitude: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
222
|
+
max_altitude: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
223
|
+
icu_joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
224
|
+
icu_hrr: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
225
|
+
hrr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
226
|
+
start_bpm: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
227
|
+
end_bpm: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
228
|
+
}, "strip", z.ZodTypeAny, {
|
|
229
|
+
hrr?: number | null | undefined;
|
|
230
|
+
start_bpm?: number | null | undefined;
|
|
231
|
+
end_bpm?: number | null | undefined;
|
|
232
|
+
}, {
|
|
233
|
+
hrr?: number | null | undefined;
|
|
234
|
+
start_bpm?: number | null | undefined;
|
|
235
|
+
end_bpm?: number | null | undefined;
|
|
236
|
+
}>>>;
|
|
237
|
+
strain_score: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
238
|
+
hr_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
239
|
+
power_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
240
|
+
gear: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
241
|
+
id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
242
|
+
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
243
|
+
}, "strip", z.ZodTypeAny, {
|
|
244
|
+
id?: string | null | undefined;
|
|
245
|
+
name?: string | null | undefined;
|
|
246
|
+
}, {
|
|
247
|
+
id?: string | null | undefined;
|
|
248
|
+
name?: string | null | undefined;
|
|
249
|
+
}>>>;
|
|
250
|
+
device_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
251
|
+
power_meter: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
252
|
+
source: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
253
|
+
compliance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
254
|
+
icu_chat_id: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
93
255
|
}, z.ZodTypeAny, "passthrough">>;
|
|
94
256
|
export type Activity = z.infer<typeof ActivitySchema>;
|
|
95
257
|
export declare const WellnessSchema: z.ZodObject<{
|
|
@@ -115,6 +277,24 @@ export declare const WellnessSchema: z.ZodObject<{
|
|
|
115
277
|
bodyFat: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
116
278
|
spO2: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
117
279
|
comments: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
280
|
+
rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
281
|
+
avgSleepingHR: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
282
|
+
sportInfo: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
283
|
+
type: z.ZodOptional<z.ZodString>;
|
|
284
|
+
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
285
|
+
wPrime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
286
|
+
pMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
287
|
+
}, "strip", z.ZodTypeAny, {
|
|
288
|
+
type?: string | undefined;
|
|
289
|
+
eftp?: number | null | undefined;
|
|
290
|
+
wPrime?: number | null | undefined;
|
|
291
|
+
pMax?: number | null | undefined;
|
|
292
|
+
}, {
|
|
293
|
+
type?: string | undefined;
|
|
294
|
+
eftp?: number | null | undefined;
|
|
295
|
+
wPrime?: number | null | undefined;
|
|
296
|
+
pMax?: number | null | undefined;
|
|
297
|
+
}>, "many">>>;
|
|
118
298
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
119
299
|
id: z.ZodOptional<z.ZodString>;
|
|
120
300
|
ctl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -138,6 +318,24 @@ export declare const WellnessSchema: z.ZodObject<{
|
|
|
138
318
|
bodyFat: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
139
319
|
spO2: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
140
320
|
comments: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
321
|
+
rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
322
|
+
avgSleepingHR: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
323
|
+
sportInfo: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
324
|
+
type: z.ZodOptional<z.ZodString>;
|
|
325
|
+
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
326
|
+
wPrime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
327
|
+
pMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
328
|
+
}, "strip", z.ZodTypeAny, {
|
|
329
|
+
type?: string | undefined;
|
|
330
|
+
eftp?: number | null | undefined;
|
|
331
|
+
wPrime?: number | null | undefined;
|
|
332
|
+
pMax?: number | null | undefined;
|
|
333
|
+
}, {
|
|
334
|
+
type?: string | undefined;
|
|
335
|
+
eftp?: number | null | undefined;
|
|
336
|
+
wPrime?: number | null | undefined;
|
|
337
|
+
pMax?: number | null | undefined;
|
|
338
|
+
}>, "many">>>;
|
|
141
339
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
142
340
|
id: z.ZodOptional<z.ZodString>;
|
|
143
341
|
ctl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -161,6 +359,24 @@ export declare const WellnessSchema: z.ZodObject<{
|
|
|
161
359
|
bodyFat: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
162
360
|
spO2: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
163
361
|
comments: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
362
|
+
rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
363
|
+
avgSleepingHR: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
364
|
+
sportInfo: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
365
|
+
type: z.ZodOptional<z.ZodString>;
|
|
366
|
+
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
367
|
+
wPrime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
368
|
+
pMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
369
|
+
}, "strip", z.ZodTypeAny, {
|
|
370
|
+
type?: string | undefined;
|
|
371
|
+
eftp?: number | null | undefined;
|
|
372
|
+
wPrime?: number | null | undefined;
|
|
373
|
+
pMax?: number | null | undefined;
|
|
374
|
+
}, {
|
|
375
|
+
type?: string | undefined;
|
|
376
|
+
eftp?: number | null | undefined;
|
|
377
|
+
wPrime?: number | null | undefined;
|
|
378
|
+
pMax?: number | null | undefined;
|
|
379
|
+
}>, "many">>>;
|
|
164
380
|
}, z.ZodTypeAny, "passthrough">>;
|
|
165
381
|
export type Wellness = z.infer<typeof WellnessSchema>;
|
|
166
382
|
export declare const EventSchema: z.ZodObject<{
|
|
@@ -173,6 +389,11 @@ export declare const EventSchema: z.ZodObject<{
|
|
|
173
389
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
174
390
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
175
391
|
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
392
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
393
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
394
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
395
|
+
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
396
|
+
paired_activity_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
176
397
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
177
398
|
id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
178
399
|
date: z.ZodOptional<z.ZodString>;
|
|
@@ -183,6 +404,11 @@ export declare const EventSchema: z.ZodObject<{
|
|
|
183
404
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
184
405
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
185
406
|
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
407
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
408
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
409
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
410
|
+
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
411
|
+
paired_activity_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
186
412
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
187
413
|
id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
188
414
|
date: z.ZodOptional<z.ZodString>;
|
|
@@ -193,6 +419,11 @@ export declare const EventSchema: z.ZodObject<{
|
|
|
193
419
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
194
420
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
195
421
|
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
422
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
423
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
424
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
425
|
+
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
426
|
+
paired_activity_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
196
427
|
}, z.ZodTypeAny, "passthrough">>;
|
|
197
428
|
export type Event = z.infer<typeof EventSchema>;
|
|
198
429
|
export declare const IntervalSchema: z.ZodObject<{
|
|
@@ -264,6 +495,10 @@ export declare const SportSettingsSchema: z.ZodObject<{
|
|
|
264
495
|
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
265
496
|
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
266
497
|
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
498
|
+
w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
499
|
+
sweet_spot_min: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
500
|
+
sweet_spot_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
501
|
+
best_effort_distances: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
267
502
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
268
503
|
types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
269
504
|
ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -276,6 +511,10 @@ export declare const SportSettingsSchema: z.ZodObject<{
|
|
|
276
511
|
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
277
512
|
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
278
513
|
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
514
|
+
w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
515
|
+
sweet_spot_min: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
516
|
+
sweet_spot_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
517
|
+
best_effort_distances: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
279
518
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
280
519
|
types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
281
520
|
ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -288,6 +527,10 @@ export declare const SportSettingsSchema: z.ZodObject<{
|
|
|
288
527
|
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
289
528
|
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
290
529
|
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
530
|
+
w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
531
|
+
sweet_spot_min: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
532
|
+
sweet_spot_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
533
|
+
best_effort_distances: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
291
534
|
}, z.ZodTypeAny, "passthrough">>;
|
|
292
535
|
export type SportSettings = z.infer<typeof SportSettingsSchema>;
|
|
293
536
|
export declare const WorkoutSchema: z.ZodObject<{
|
|
@@ -296,18 +539,27 @@ export declare const WorkoutSchema: z.ZodObject<{
|
|
|
296
539
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
297
540
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
298
541
|
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
542
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
543
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
544
|
+
joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
299
545
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
300
546
|
id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
301
547
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
302
548
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
303
549
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
304
550
|
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
551
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
552
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
553
|
+
joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
305
554
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
306
555
|
id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
307
556
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
308
557
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
309
558
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
310
559
|
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
560
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
561
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
562
|
+
joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
311
563
|
}, z.ZodTypeAny, "passthrough">>;
|
|
312
564
|
export type Workout = z.infer<typeof WorkoutSchema>;
|
|
313
565
|
export interface WorkoutInput {
|
|
@@ -371,6 +623,8 @@ export declare const MessageSchema: z.ZodObject<{
|
|
|
371
623
|
export type Message = z.infer<typeof MessageSchema>;
|
|
372
624
|
export declare function getActivityMessages(config: ClientConfig, activityId: string): Promise<Message[]>;
|
|
373
625
|
export declare function addActivityMessage(config: ClientConfig, activityId: string, content: string): Promise<void>;
|
|
626
|
+
export declare function deleteActivityMessage(config: ClientConfig, activityId: string, messageId: number): Promise<void>;
|
|
627
|
+
export declare function updateActivityMessage(config: ClientConfig, activityId: string, messageId: number, content: string): Promise<void>;
|
|
374
628
|
export declare function getWellness(config: ClientConfig, params: {
|
|
375
629
|
startDate: string;
|
|
376
630
|
endDate: string;
|
|
@@ -405,6 +659,10 @@ export declare const AthleteFitnessSchema: z.ZodObject<{
|
|
|
405
659
|
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
406
660
|
eftpPerKg: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
407
661
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
662
|
+
count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
663
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
664
|
+
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
665
|
+
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
408
666
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
409
667
|
date: z.ZodOptional<z.ZodString>;
|
|
410
668
|
fitness: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -415,6 +673,10 @@ export declare const AthleteFitnessSchema: z.ZodObject<{
|
|
|
415
673
|
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
416
674
|
eftpPerKg: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
417
675
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
676
|
+
count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
677
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
678
|
+
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
679
|
+
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
418
680
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
419
681
|
date: z.ZodOptional<z.ZodString>;
|
|
420
682
|
fitness: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -425,6 +687,10 @@ export declare const AthleteFitnessSchema: z.ZodObject<{
|
|
|
425
687
|
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
426
688
|
eftpPerKg: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
427
689
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
690
|
+
count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
691
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
692
|
+
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
693
|
+
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
428
694
|
}, z.ZodTypeAny, "passthrough">>;
|
|
429
695
|
export type AthleteFitness = z.infer<typeof AthleteFitnessSchema>;
|
|
430
696
|
export declare function getAthleteFitness(config: ClientConfig, params: {
|
package/dist/client.js
CHANGED
|
@@ -53,6 +53,37 @@ export const ActivitySchema = z.object({
|
|
|
53
53
|
feel: z.number().nullable().optional(),
|
|
54
54
|
description: z.string().nullable().optional(),
|
|
55
55
|
trainer: z.boolean().nullable().optional(),
|
|
56
|
+
decoupling: z.number().nullable().optional(),
|
|
57
|
+
icu_efficiency_factor: z.number().nullable().optional(),
|
|
58
|
+
icu_power_hr: z.number().nullable().optional(),
|
|
59
|
+
icu_variability_index: z.number().nullable().optional(),
|
|
60
|
+
icu_pm_cp: z.number().nullable().optional(),
|
|
61
|
+
icu_rolling_ftp: z.number().nullable().optional(),
|
|
62
|
+
polarization_index: z.number().nullable().optional(),
|
|
63
|
+
icu_zone_times: z.array(z.object({ id: z.string(), secs: z.number() })).nullable().optional(),
|
|
64
|
+
icu_hr_zone_times: z.array(z.number()).nullable().optional(),
|
|
65
|
+
total_elevation_loss: z.number().nullable().optional(),
|
|
66
|
+
max_speed: z.number().nullable().optional(),
|
|
67
|
+
min_altitude: z.number().nullable().optional(),
|
|
68
|
+
max_altitude: z.number().nullable().optional(),
|
|
69
|
+
icu_joules: z.number().nullable().optional(),
|
|
70
|
+
icu_hrr: z.object({
|
|
71
|
+
hrr: z.number().nullable().optional(),
|
|
72
|
+
start_bpm: z.number().nullable().optional(),
|
|
73
|
+
end_bpm: z.number().nullable().optional(),
|
|
74
|
+
}).nullable().optional(),
|
|
75
|
+
strain_score: z.number().nullable().optional(),
|
|
76
|
+
hr_load: z.number().nullable().optional(),
|
|
77
|
+
power_load: z.number().nullable().optional(),
|
|
78
|
+
gear: z.object({
|
|
79
|
+
id: z.string().nullable().optional(),
|
|
80
|
+
name: z.string().nullable().optional(),
|
|
81
|
+
}).nullable().optional(),
|
|
82
|
+
device_name: z.string().nullable().optional(),
|
|
83
|
+
power_meter: z.string().nullable().optional(),
|
|
84
|
+
source: z.string().nullable().optional(),
|
|
85
|
+
compliance: z.number().nullable().optional(),
|
|
86
|
+
icu_chat_id: z.number().nullable().optional(),
|
|
56
87
|
}).passthrough();
|
|
57
88
|
export const WellnessSchema = z.object({
|
|
58
89
|
id: z.string().optional(),
|
|
@@ -77,6 +108,14 @@ export const WellnessSchema = z.object({
|
|
|
77
108
|
bodyFat: z.number().nullable().optional(),
|
|
78
109
|
spO2: z.number().nullable().optional(),
|
|
79
110
|
comments: z.string().nullable().optional(),
|
|
111
|
+
rampRate: z.number().nullable().optional(),
|
|
112
|
+
avgSleepingHR: z.number().nullable().optional(),
|
|
113
|
+
sportInfo: z.array(z.object({
|
|
114
|
+
type: z.string().optional(),
|
|
115
|
+
eftp: z.number().nullable().optional(),
|
|
116
|
+
wPrime: z.number().nullable().optional(),
|
|
117
|
+
pMax: z.number().nullable().optional(),
|
|
118
|
+
})).nullable().optional(),
|
|
80
119
|
}).passthrough();
|
|
81
120
|
export const EventSchema = z.object({
|
|
82
121
|
id: z.union([z.string(), z.number()]),
|
|
@@ -88,6 +127,11 @@ export const EventSchema = z.object({
|
|
|
88
127
|
name: z.string().nullable().optional(),
|
|
89
128
|
description: z.string().nullable().optional(),
|
|
90
129
|
color: z.string().nullable().optional(),
|
|
130
|
+
type: z.string().nullable().optional(),
|
|
131
|
+
moving_time: z.number().nullable().optional(),
|
|
132
|
+
icu_training_load: z.number().nullable().optional(),
|
|
133
|
+
icu_intensity: z.number().nullable().optional(),
|
|
134
|
+
paired_activity_id: z.string().nullable().optional(),
|
|
91
135
|
}).passthrough();
|
|
92
136
|
export const IntervalSchema = z.object({
|
|
93
137
|
icu_intervals: z.array(z.record(z.unknown())).nullable().optional(),
|
|
@@ -117,6 +161,10 @@ export const SportSettingsSchema = z.object({
|
|
|
117
161
|
hr_zone_names: z.array(z.string()).nullable().optional(),
|
|
118
162
|
pace_zones: z.array(z.number()).nullable().optional(),
|
|
119
163
|
pace_zone_names: z.array(z.string()).nullable().optional(),
|
|
164
|
+
w_prime: z.number().nullable().optional(),
|
|
165
|
+
sweet_spot_min: z.number().nullable().optional(),
|
|
166
|
+
sweet_spot_max: z.number().nullable().optional(),
|
|
167
|
+
best_effort_distances: z.array(z.number()).nullable().optional(),
|
|
120
168
|
}).passthrough();
|
|
121
169
|
export const WorkoutSchema = z.object({
|
|
122
170
|
id: z.union([z.string(), z.number()]).optional(),
|
|
@@ -124,6 +172,9 @@ export const WorkoutSchema = z.object({
|
|
|
124
172
|
description: z.string().nullable().optional(),
|
|
125
173
|
type: z.string().nullable().optional(),
|
|
126
174
|
updated: z.string().nullable().optional(),
|
|
175
|
+
moving_time: z.number().nullable().optional(),
|
|
176
|
+
icu_training_load: z.number().nullable().optional(),
|
|
177
|
+
joules: z.number().nullable().optional(),
|
|
127
178
|
}).passthrough();
|
|
128
179
|
// ---- API methods ---- //
|
|
129
180
|
export async function getActivities(config, params) {
|
|
@@ -154,6 +205,20 @@ export async function getActivityMessages(config, activityId) {
|
|
|
154
205
|
export async function addActivityMessage(config, activityId, content) {
|
|
155
206
|
await mutate("POST", `/activity/${activityId}/messages`, config, { content });
|
|
156
207
|
}
|
|
208
|
+
// Intervals.icu has no endpoint to edit a message's content in place — only
|
|
209
|
+
// delete and re-add. Callers wanting an "edit" should use updateActivityMessage,
|
|
210
|
+
// which does both and leaves the old message showing as deleted.
|
|
211
|
+
export async function deleteActivityMessage(config, activityId, messageId) {
|
|
212
|
+
const activity = await getActivityDetails(config, activityId);
|
|
213
|
+
const chatId = activity.icu_chat_id;
|
|
214
|
+
if (chatId == null)
|
|
215
|
+
throw new Error(`Activity ${activityId} has no chat/messages.`);
|
|
216
|
+
await mutate("DELETE", `/chats/${chatId}/messages/${messageId}`, config);
|
|
217
|
+
}
|
|
218
|
+
export async function updateActivityMessage(config, activityId, messageId, content) {
|
|
219
|
+
await deleteActivityMessage(config, activityId, messageId);
|
|
220
|
+
await addActivityMessage(config, activityId, content);
|
|
221
|
+
}
|
|
157
222
|
export async function getWellness(config, params) {
|
|
158
223
|
const data = await request(`/athlete/${config.athleteId}/wellness`, config, { oldest: params.startDate, newest: params.endDate });
|
|
159
224
|
if (Array.isArray(data)) {
|
|
@@ -273,6 +338,10 @@ export const AthleteFitnessSchema = z.object({
|
|
|
273
338
|
eftp: z.number().nullable().optional(),
|
|
274
339
|
eftpPerKg: z.number().nullable().optional(),
|
|
275
340
|
weight: z.number().nullable().optional(),
|
|
341
|
+
count: z.number().nullable().optional(),
|
|
342
|
+
moving_time: z.number().nullable().optional(),
|
|
343
|
+
calories: z.number().nullable().optional(),
|
|
344
|
+
distance: z.number().nullable().optional(),
|
|
276
345
|
}).passthrough();
|
|
277
346
|
export async function getAthleteFitness(config, params) {
|
|
278
347
|
const data = await request(`/athlete/${config.athleteId}/athlete-summary.json`, config, { start: params.startDate, end: params.endDate });
|
package/dist/format.js
CHANGED
|
@@ -3,6 +3,13 @@ function n(v, unit = "") {
|
|
|
3
3
|
return "N/A";
|
|
4
4
|
return `${v}${unit}`;
|
|
5
5
|
}
|
|
6
|
+
function fmtDuration(secs) {
|
|
7
|
+
if (secs == null)
|
|
8
|
+
return "N/A";
|
|
9
|
+
const h = Math.floor(secs / 3600);
|
|
10
|
+
const m = Math.round((secs % 3600) / 60);
|
|
11
|
+
return h > 0 ? `${h}h${m}m` : `${m}m`;
|
|
12
|
+
}
|
|
6
13
|
export function formatActivity(a) {
|
|
7
14
|
const startTime = a.start_date_local
|
|
8
15
|
? new Date(a.start_date_local).toLocaleString()
|
|
@@ -11,37 +18,44 @@ export function formatActivity(a) {
|
|
|
11
18
|
`**${a.name ?? "Unnamed"}** (${a.id})`,
|
|
12
19
|
`Type: ${n(a.type)} | Date: ${startTime}`,
|
|
13
20
|
`Distance: ${n(a.distance, " m")} | Duration: ${n(a.elapsed_time, " s")} | Moving: ${n(a.moving_time, " s")}`,
|
|
14
|
-
`Elevation:
|
|
21
|
+
`Elevation: +${n(a.total_elevation_gain, " m")} / -${n(a.total_elevation_loss, " m")} | Altitude: ${n(a.min_altitude, " m")}-${n(a.max_altitude, " m")}`,
|
|
15
22
|
"",
|
|
16
23
|
"Power:",
|
|
17
24
|
` 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)}`,
|
|
25
|
+
` Training Load: ${n(a.icu_training_load)} | Intensity: ${n(a.icu_intensity)} | VI: ${n(a.icu_variability_index)}`,
|
|
26
|
+
` Critical Power: ${n(a.icu_pm_cp, " W")} | Rolling FTP: ${n(a.icu_rolling_ftp, " W")} | Energy: ${a.icu_joules != null ? `${Math.round(a.icu_joules / 1000)} kJ` : "N/A"}`,
|
|
19
27
|
"",
|
|
20
28
|
"Heart Rate:",
|
|
21
29
|
` Avg: ${n(a.average_heartrate, " bpm")} | Max: ${n(a.max_heartrate, " bpm")}`,
|
|
22
|
-
""
|
|
23
|
-
"Other:",
|
|
24
|
-
` Cadence: ${n(a.average_cadence, " rpm")} | Calories: ${n(a.calories)} | Speed: ${n(a.average_speed, " m/s")}`,
|
|
25
|
-
` Temp: ${n(a.average_temp, "°C")} | Trainer: ${a.trainer ? "Yes" : "No"}`,
|
|
26
|
-
` RPE: ${n(a.icu_rpe ?? a.perceived_exertion)}/10 | Feel: ${n(a.feel)}/5`,
|
|
27
|
-
"",
|
|
28
|
-
"Fitness:",
|
|
29
|
-
` CTL: ${n(a.icu_ctl)} | ATL: ${n(a.icu_atl)} | TRIMP: ${n(a.trimp)}`,
|
|
30
|
+
` Decoupling: ${n(a.decoupling, "%")} | Efficiency Factor: ${n(a.icu_efficiency_factor)} | Pw:Hr: ${n(a.icu_power_hr)}`,
|
|
30
31
|
];
|
|
32
|
+
if (a.icu_hrr?.hrr != null) {
|
|
33
|
+
lines.push(` HR Recovery: -${n(a.icu_hrr.hrr, " bpm")} (${n(a.icu_hrr.start_bpm)} → ${n(a.icu_hrr.end_bpm)} bpm)`);
|
|
34
|
+
}
|
|
35
|
+
if (a.icu_zone_times?.length || a.icu_hr_zone_times?.length) {
|
|
36
|
+
lines.push("", "Zones:");
|
|
37
|
+
if (a.icu_zone_times?.length) {
|
|
38
|
+
lines.push(` Power: ${a.icu_zone_times.map((z) => `${z.id} ${fmtDuration(z.secs)}`).join(" | ")}`);
|
|
39
|
+
}
|
|
40
|
+
if (a.icu_hr_zone_times?.length) {
|
|
41
|
+
lines.push(` HR: ${a.icu_hr_zone_times.map((secs, i) => `Z${i + 1} ${fmtDuration(secs)}`).join(" | ")}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
lines.push("", "Other:", ` Cadence: ${n(a.average_cadence, " rpm")} | Calories: ${n(a.calories)} | Speed: ${n(a.average_speed, " m/s")} (max ${n(a.max_speed, " m/s")})`, ` Temp: ${n(a.average_temp, "°C")} | Trainer: ${a.trainer ? "Yes" : "No"}`, ` RPE: ${n(a.icu_rpe ?? a.perceived_exertion)}/10 | Feel: ${n(a.feel)}/5`, "", "Fitness:", ` CTL: ${n(a.icu_ctl)} | ATL: ${n(a.icu_atl)} | TRIMP: ${n(a.trimp)} | Polarization Index: ${n(a.polarization_index)}`, ` Power Load: ${n(a.power_load)} | HR Load: ${n(a.hr_load)} | Strain: ${n(a.strain_score)}`, "", "Equipment:", ` Gear: ${n(a.gear?.name)} | Device: ${n(a.device_name)} | Power Meter: ${n(a.power_meter)}`, ` Source: ${n(a.source)} | Compliance: ${a.compliance != null ? `${a.compliance}%` : "N/A"}`);
|
|
31
45
|
if (a.description)
|
|
32
46
|
lines.push("", `Description: ${a.description}`);
|
|
33
47
|
return lines.join("\n");
|
|
34
48
|
}
|
|
35
49
|
export function formatWellness(date, w) {
|
|
36
50
|
const sleepHours = w.sleepSecs != null ? (w.sleepSecs / 3600).toFixed(1) + " h" : "N/A";
|
|
37
|
-
|
|
51
|
+
const lines = [
|
|
38
52
|
`**${date}**`,
|
|
39
53
|
"",
|
|
40
54
|
"Training:",
|
|
41
|
-
` CTL: ${n(w.ctl)} | ATL: ${n(w.atl)}`,
|
|
55
|
+
` CTL: ${n(w.ctl)} | ATL: ${n(w.atl)} | Ramp Rate: ${n(w.rampRate)}`,
|
|
42
56
|
"",
|
|
43
57
|
"Vitals:",
|
|
44
|
-
` Weight: ${n(w.weight, " kg")} | Resting HR: ${n(w.restingHR, " bpm")}`,
|
|
58
|
+
` Weight: ${n(w.weight, " kg")} | Resting HR: ${n(w.restingHR, " bpm")} | Avg Sleeping HR: ${n(w.avgSleepingHR, " bpm")}`,
|
|
45
59
|
` HRV: ${n(w.hrv)} | HRV SDNN: ${n(w.hrvSDNN)}`,
|
|
46
60
|
` SpO2: ${n(w.spO2, "%")} | VO2max: ${n(w.vo2max)} | Body Fat: ${n(w.bodyFat, "%")}`,
|
|
47
61
|
"",
|
|
@@ -55,11 +69,13 @@ export function formatWellness(date, w) {
|
|
|
55
69
|
"",
|
|
56
70
|
"Nutrition:",
|
|
57
71
|
` Calories: ${n(w.kcalConsumed, " kcal")} | Steps: ${n(w.steps)}`,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
.
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
];
|
|
73
|
+
if (w.sportInfo?.length) {
|
|
74
|
+
lines.push("", "Sport Fitness (eFTP / W' / pMax):", ...w.sportInfo.map((s) => ` ${s.type ?? "Unknown"}: ${n(s.eftp, " W")} / ${n(s.wPrime, " J")} / ${n(s.pMax, " W")}`));
|
|
75
|
+
}
|
|
76
|
+
if (w.comments)
|
|
77
|
+
lines.push("", `Comments: ${w.comments}`);
|
|
78
|
+
return lines.join("\n").trimEnd();
|
|
63
79
|
}
|
|
64
80
|
export function formatEvent(e) {
|
|
65
81
|
const category = e.category ?? "";
|
|
@@ -74,14 +90,19 @@ export function formatEvent(e) {
|
|
|
74
90
|
const dateLabel = e.end_date_local && e.end_date_local !== e.start_date_local
|
|
75
91
|
? `${start} to ${e.end_date_local}`
|
|
76
92
|
: start;
|
|
77
|
-
|
|
93
|
+
const lines = [
|
|
78
94
|
`**${e.name ?? "Unnamed"}** (${e.id})`,
|
|
79
95
|
`Type: ${type} | Date: ${dateLabel}`,
|
|
80
96
|
e.category ? `Category: ${e.category}` : "",
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
.
|
|
84
|
-
|
|
97
|
+
];
|
|
98
|
+
if (e.type || e.moving_time != null || e.icu_training_load != null || e.icu_intensity != null) {
|
|
99
|
+
lines.push(`Sport: ${n(e.type)} | Planned Duration: ${e.moving_time != null ? fmtDuration(e.moving_time) : "N/A"} | Planned Load: ${n(e.icu_training_load)} | Intensity: ${n(e.icu_intensity)}`);
|
|
100
|
+
}
|
|
101
|
+
if (e.paired_activity_id)
|
|
102
|
+
lines.push(`Completed as: ${e.paired_activity_id}`);
|
|
103
|
+
if (e.description)
|
|
104
|
+
lines.push(`Description: ${e.description}`);
|
|
105
|
+
return lines.filter(Boolean).join("\n");
|
|
85
106
|
}
|
|
86
107
|
export function formatMessage(m) {
|
|
87
108
|
const when = m.created ? new Date(m.created).toLocaleString() : "Unknown time";
|
|
@@ -132,6 +153,13 @@ export function formatSportZones(s) {
|
|
|
132
153
|
const range = z.to != null ? `${z.from}-${z.to} m/s` : `${z.from}+ m/s`;
|
|
133
154
|
lines.push(` ${z.name}: ${range}`);
|
|
134
155
|
}
|
|
156
|
+
lines.push("");
|
|
157
|
+
}
|
|
158
|
+
if (s.w_prime != null || s.sweet_spot_min != null) {
|
|
159
|
+
lines.push(`Power Model: W' ${n(s.w_prime, " J")} | Sweet Spot ${n(s.sweet_spot_min, "%")}-${n(s.sweet_spot_max, "%")}`);
|
|
160
|
+
}
|
|
161
|
+
if (s.best_effort_distances?.length) {
|
|
162
|
+
lines.push(`Best Effort Distances: ${s.best_effort_distances.join(", ")} m`);
|
|
135
163
|
}
|
|
136
164
|
return lines.join("\n").trimEnd();
|
|
137
165
|
}
|
|
@@ -146,10 +174,13 @@ export function formatIntervalRow(interval, idx) {
|
|
|
146
174
|
const avgHr = interval["average_heartrate"] ?? 0;
|
|
147
175
|
const maxHr = interval["max_heartrate"] ?? 0;
|
|
148
176
|
const tl = interval["training_load"] ?? 0;
|
|
177
|
+
const intensity = interval["intensity"];
|
|
178
|
+
const vi = interval["w5s_variability"];
|
|
179
|
+
const decoupling = interval["decoupling"];
|
|
149
180
|
return [
|
|
150
181
|
`[${idx}] ${label} (${type})`,
|
|
151
182
|
` Duration: ${elapsed}s | Distance: ${distance}m`,
|
|
152
|
-
` Power: avg ${avgW}W, w.avg ${wAvg}W, max ${maxW}W | TL: ${tl}`,
|
|
153
|
-
` HR: avg ${avgHr}, max ${maxHr} bpm`,
|
|
183
|
+
` Power: avg ${avgW}W, w.avg ${wAvg}W, max ${maxW}W | TL: ${tl} | Intensity: ${n(intensity)} | VI: ${n(vi)}`,
|
|
184
|
+
` HR: avg ${avgHr}, max ${maxHr} bpm | Decoupling: ${n(decoupling, "%")}`,
|
|
154
185
|
].join("\n");
|
|
155
186
|
}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
4
4
|
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
|
-
import { getActivities, getActivityDetails, getActivityIntervals, getWellness, getEvents, getEventById, getNotesByDate, createEvent, updateEvent, deleteEvent, getAthleteProfile, getAthleteZones, getAthleteSummary, getWellnessDay, updateWellness, getActivityStreams, getActivityPowerCurves, listWorkouts, createWorkout, bulkCreateEvents, bulkDeleteEvents, getAthleteFitness, getActivityMessages, addActivityMessage, } from "./client.js";
|
|
7
|
+
import { getActivities, getActivityDetails, getActivityIntervals, getWellness, getEvents, getEventById, getNotesByDate, createEvent, updateEvent, deleteEvent, getAthleteProfile, getAthleteZones, getAthleteSummary, getWellnessDay, updateWellness, getActivityStreams, getActivityPowerCurves, listWorkouts, createWorkout, bulkCreateEvents, bulkDeleteEvents, getAthleteFitness, getActivityMessages, addActivityMessage, deleteActivityMessage, updateActivityMessage, } from "./client.js";
|
|
8
8
|
import { formatActivity, formatWellness, formatEvent, formatIntervalRow, formatSportZones, formatMessage, } from "./format.js";
|
|
9
9
|
function getConfig(args) {
|
|
10
10
|
const apiKey = args["api_key"] ?? process.env.API_KEY ?? "";
|
|
@@ -309,6 +309,35 @@ const TOOLS = [
|
|
|
309
309
|
},
|
|
310
310
|
},
|
|
311
311
|
},
|
|
312
|
+
{
|
|
313
|
+
name: "update_activity_message",
|
|
314
|
+
description: "Edit a comment/note on an activity. Intervals.icu has no API to edit message content in place, so this deletes the old message and posts a new one with the updated text — the old message will show as \"(deleted)\" and the edited one will appear as a new message at the current time. Use get_activity_messages to find the message_id.",
|
|
315
|
+
inputSchema: {
|
|
316
|
+
type: "object",
|
|
317
|
+
required: ["activity_id", "message_id", "content"],
|
|
318
|
+
properties: {
|
|
319
|
+
activity_id: { type: "string", description: "The activity ID" },
|
|
320
|
+
message_id: { type: "number", description: "ID of the message to edit (from get_activity_messages)" },
|
|
321
|
+
content: { type: "string", description: "New comment text" },
|
|
322
|
+
athlete_id: { type: "string", description: "Athlete ID (defaults to ATHLETE_ID env var)" },
|
|
323
|
+
api_key: { type: "string", description: "API key (defaults to API_KEY env var)" },
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
name: "delete_activity_message",
|
|
329
|
+
description: "Delete a comment/note from an activity's chat thread. The message is soft-deleted (shows as \"(deleted)\") rather than removed entirely. Use get_activity_messages to find the message_id.",
|
|
330
|
+
inputSchema: {
|
|
331
|
+
type: "object",
|
|
332
|
+
required: ["activity_id", "message_id"],
|
|
333
|
+
properties: {
|
|
334
|
+
activity_id: { type: "string", description: "The activity ID" },
|
|
335
|
+
message_id: { type: "number", description: "ID of the message to delete (from get_activity_messages)" },
|
|
336
|
+
athlete_id: { type: "string", description: "Athlete ID (defaults to ATHLETE_ID env var)" },
|
|
337
|
+
api_key: { type: "string", description: "API key (defaults to API_KEY env var)" },
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
},
|
|
312
341
|
{
|
|
313
342
|
name: "list_workouts",
|
|
314
343
|
description: "List all workouts in the athlete's workout library.",
|
|
@@ -608,6 +637,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
608
637
|
`ATL (Fatigue): ${summary.fatigue ?? "N/A"}`,
|
|
609
638
|
`TSB (Form): ${summary.form ?? "N/A"}`,
|
|
610
639
|
`Ramp Rate: ${summary.rampRate ?? "N/A"}`,
|
|
640
|
+
"",
|
|
641
|
+
"## Last 7 Days",
|
|
642
|
+
"",
|
|
643
|
+
`Activities: ${summary.count ?? "N/A"} | Training Load: ${summary.training_load ?? "N/A"}`,
|
|
644
|
+
`Moving Time: ${summary.moving_time != null ? `${(summary.moving_time / 3600).toFixed(1)}h` : "N/A"} | Distance: ${summary.distance != null ? `${(summary.distance / 1000).toFixed(1)} km` : "N/A"} | Calories: ${summary.calories ?? "N/A"}`,
|
|
611
645
|
].join("\n");
|
|
612
646
|
return { content: [{ type: "text", text }] };
|
|
613
647
|
}
|
|
@@ -667,12 +701,35 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
667
701
|
await addActivityMessage(config, activityId, content);
|
|
668
702
|
return { content: [{ type: "text", text: `Comment added to activity ${activityId}.` }] };
|
|
669
703
|
}
|
|
704
|
+
case "update_activity_message": {
|
|
705
|
+
const activityId = z.string().parse(args["activity_id"]);
|
|
706
|
+
const messageId = z.number().parse(args["message_id"]);
|
|
707
|
+
const content = z.string().parse(args["content"]);
|
|
708
|
+
const config = getConfig(args);
|
|
709
|
+
await updateActivityMessage(config, activityId, messageId, content);
|
|
710
|
+
return { content: [{ type: "text", text: `Message ${messageId} on activity ${activityId} replaced with: "${content}"` }] };
|
|
711
|
+
}
|
|
712
|
+
case "delete_activity_message": {
|
|
713
|
+
const activityId = z.string().parse(args["activity_id"]);
|
|
714
|
+
const messageId = z.number().parse(args["message_id"]);
|
|
715
|
+
const config = getConfig(args);
|
|
716
|
+
await deleteActivityMessage(config, activityId, messageId);
|
|
717
|
+
return { content: [{ type: "text", text: `Message ${messageId} deleted from activity ${activityId}.` }] };
|
|
718
|
+
}
|
|
670
719
|
case "list_workouts": {
|
|
671
720
|
const config = getConfig(args);
|
|
672
721
|
const workouts = await listWorkouts(config);
|
|
673
722
|
if (!workouts.length)
|
|
674
723
|
return { content: [{ type: "text", text: "No workouts in library." }] };
|
|
675
|
-
const text = workouts.map(w =>
|
|
724
|
+
const text = workouts.map(w => {
|
|
725
|
+
const duration = w.moving_time != null ? `${Math.round(w.moving_time / 60)}min` : "N/A";
|
|
726
|
+
const kj = w.joules != null ? `${Math.round(w.joules / 1000)} kJ` : "N/A";
|
|
727
|
+
return [
|
|
728
|
+
`**${w.name ?? "Unnamed"}** (${w.id})`,
|
|
729
|
+
w.type ? `Type: ${w.type} | Duration: ${duration} | Load: ${w.icu_training_load ?? "N/A"} | Energy: ${kj}` : "",
|
|
730
|
+
w.description ? `${w.description}` : "",
|
|
731
|
+
].filter(Boolean).join("\n");
|
|
732
|
+
}).join("\n\n---\n\n");
|
|
676
733
|
return { content: [{ type: "text", text }] };
|
|
677
734
|
}
|
|
678
735
|
case "create_workout": {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "intervals-icu-mcp-server",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server for Intervals.icu —
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "MCP server for Intervals.icu — 26 tools for activities, wellness, calendar events, workouts and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"intervals-icu-mcp": "dist/index.js"
|