@milldr/crono 0.6.1 → 0.8.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/README.md CHANGED
@@ -283,6 +283,50 @@ crono diary -r 7d --json
283
283
  # → [{"date":"2026-02-11","calories":1847,"protein":168,"carbs":142,"fat":58}, ...]
284
284
  ```
285
285
 
286
+ ### `crono biometrics`
287
+
288
+ Log biometrics to Cronometer (weight, body fat percentage, blood pressure). Defaults to today if no date is specified.
289
+
290
+ ```bash
291
+ crono biometrics [options]
292
+ ```
293
+
294
+ **Options:**
295
+
296
+ | Flag | Long | Description |
297
+ | ---- | --------------------- | ------------------------------------ |
298
+ | `-w` | `--weight <value>` | Weight value |
299
+ | `-b` | `--body-fat <value>` | Body fat percentage |
300
+ | `-s` | `--systolic <value>` | Systolic blood pressure (mmHg) |
301
+ | `-d` | `--diastolic <value>` | Diastolic blood pressure (mmHg) |
302
+ | | `--date <date>` | Date (YYYY-MM-DD, yesterday, -1d) |
303
+ | `-u` | `--unit <unit>` | Weight unit (kg or lbs), default: kg |
304
+
305
+ At least one biometric value is required. Blood pressure requires both systolic and diastolic values.
306
+
307
+ **Examples:**
308
+
309
+ ```bash
310
+ # Log weight in kg (default)
311
+ crono biometrics --weight 90
312
+
313
+ # Log weight in lbs
314
+ crono biometrics --weight 198 --unit lbs
315
+
316
+ # Log body fat percentage
317
+ crono biometrics --body-fat 19
318
+
319
+ # Log blood pressure
320
+ crono biometrics --systolic 130 --diastolic 76
321
+
322
+ # Log weight for yesterday
323
+ crono biometrics --weight 90 --date yesterday
324
+
325
+ # Log multiple biometrics (requires multiple commands)
326
+ crono biometrics --weight 90
327
+ crono biometrics --body-fat 19
328
+ ```
329
+
286
330
  ### `crono recipes`
287
331
 
288
332
  List your custom recipes from Cronometer.
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/automation/runner.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,gBAAgB,EAEhB,wBAAwB,EAQzB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,wBAAwB,GACtC,gBAAgB,CAyFlB"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/automation/runner.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,gBAAgB,EAEhB,wBAAwB,EASzB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,wBAAwB,GACtC,gBAAgB,CA4GlB"}
@@ -1,6 +1,7 @@
1
1
  import * as p from "@clack/prompts";
2
2
  import { getCredential } from "../credentials.js";
3
3
  import { buildAddCustomFoodCode } from "../kernel/add-custom-food.js";
4
+ import { buildBiometricsCode } from "../kernel/biometrics.js";
4
5
  import { buildDiaryCode } from "../kernel/diary.js";
5
6
  import { buildLogFoodCode } from "../kernel/log-food.js";
6
7
  import { buildRecipesCode } from "../kernel/recipes.js";
@@ -54,6 +55,18 @@ export function createAutomationClient(createRuntime) {
54
55
  }
55
56
  return data.recipes ?? [];
56
57
  }),
58
+ logBiometric: (entry, onStatus) => withLoggedInRuntime(createRuntime, onStatus, async (runtime) => {
59
+ const typeLabel = entry.type === "weight"
60
+ ? "weight"
61
+ : entry.type === "bodyfat"
62
+ ? "body fat"
63
+ : "blood pressure";
64
+ onStatus?.(`Logging ${typeLabel}...`);
65
+ const data = await executeAutomation(runtime, buildBiometricsCode(entry), 60);
66
+ if (!data.success) {
67
+ throw new Error(`Biometric logging failed: ${data.error ?? "Unknown error"}`);
68
+ }
69
+ }),
57
70
  };
58
71
  }
59
72
  async function withLoggedInRuntime(createRuntime, onStatus, run) {
@@ -96,7 +109,11 @@ async function autoLogin(runtime, username, password, onStatus) {
96
109
  "Please wait a few minutes and try again.");
97
110
  }
98
111
  throw new Error(`Auto-login failed: ${data.error ?? data.loginError ?? "Login verification failed"}.\n` +
99
- "Your credentials may be incorrect. Run `crono login` to update them.");
112
+ "Your credentials may be incorrect run `crono login` to update them.\n" +
113
+ "If they are known good, Cronometer is most likely throttling logins: it\n" +
114
+ "then serves the logged-out marketing page with no error text, which\n" +
115
+ "surfaces as this message. Wait a few minutes before trying again;\n" +
116
+ "retrying in a loop extends the throttle.");
100
117
  }
101
118
  }
102
119
  async function manualLogin(runtime) {
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/automation/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/automation/runner.ts"],"names":[],"mappings":"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"}
@@ -43,6 +43,14 @@ export interface LogFoodEntry {
43
43
  export interface RecipeData {
44
44
  name: string;
45
45
  }
46
+ export interface BiometricEntry {
47
+ type: "weight" | "bodyfat" | "bloodpressure";
48
+ value?: number;
49
+ unit?: string;
50
+ systolic?: number;
51
+ diastolic?: number;
52
+ date: string;
53
+ }
46
54
  export interface AutomationClient {
47
55
  addQuickEntry(entry: MacroEntry, onStatus?: (msg: string) => void): Promise<void>;
48
56
  getWeight(dates: string[], onStatus?: (msg: string) => void): Promise<WeightData[]>;
@@ -50,6 +58,7 @@ export interface AutomationClient {
50
58
  addCustomFood(entry: CustomFoodEntry, onStatus?: (msg: string) => void): Promise<void>;
51
59
  logFood(entry: LogFoodEntry, onStatus?: (msg: string) => void): Promise<void>;
52
60
  getRecipes(onStatus?: (msg: string) => void): Promise<RecipeData[]>;
61
+ logBiometric(entry: BiometricEntry, onStatus?: (msg: string) => void): Promise<void>;
53
62
  }
54
63
  export interface PlaywrightExecutionResponse<T = unknown> {
55
64
  success: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/automation/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/automation/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface BiometricsOptions {
2
+ weight?: number;
3
+ bodyFat?: number;
4
+ systolic?: number;
5
+ diastolic?: number;
6
+ date?: string;
7
+ unit?: string;
8
+ }
9
+ export declare function biometrics(options: BiometricsOptions): Promise<void>;
10
+ //# sourceMappingURL=biometrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biometrics.d.ts","sourceRoot":"","sources":["../../src/commands/biometrics.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsG1E"}
@@ -0,0 +1,81 @@
1
+ import * as p from "@clack/prompts";
2
+ import { getAutomationClient } from "../automation/client.js";
3
+ import { formatKernelError } from "../kernel/errors.js";
4
+ import { parseDate, todayStr } from "../utils/date.js";
5
+ export async function biometrics(options) {
6
+ // Validate at least one biometric is provided
7
+ if (options.weight === undefined &&
8
+ options.bodyFat === undefined &&
9
+ (options.systolic === undefined || options.diastolic === undefined)) {
10
+ p.log.error("At least one biometric required: --weight, --body-fat, or both --systolic and --diastolic");
11
+ process.exit(1);
12
+ }
13
+ // Validate blood pressure requires both values
14
+ if ((options.systolic !== undefined && options.diastolic === undefined) ||
15
+ (options.systolic === undefined && options.diastolic !== undefined)) {
16
+ p.log.error("Blood pressure requires both --systolic and --diastolic");
17
+ process.exit(1);
18
+ }
19
+ // Validate weight unit
20
+ const unit = options.unit?.toLowerCase() || "kg";
21
+ if (unit !== "kg" && unit !== "lbs") {
22
+ p.log.error('Weight unit must be "kg" or "lbs"');
23
+ process.exit(1);
24
+ }
25
+ // Resolve date
26
+ let targetDate;
27
+ try {
28
+ targetDate = options.date ? parseDate(options.date) : todayStr();
29
+ }
30
+ catch (error) {
31
+ p.log.error(String(error instanceof Error ? error.message : error));
32
+ process.exit(1);
33
+ }
34
+ p.intro("🍎 crono biometrics");
35
+ const s = p.spinner();
36
+ s.start("Connecting...");
37
+ try {
38
+ const client = await getAutomationClient();
39
+ // Log weight if provided
40
+ if (options.weight !== undefined) {
41
+ await client.logBiometric({
42
+ type: "weight",
43
+ value: options.weight,
44
+ unit,
45
+ date: targetDate,
46
+ }, (msg) => s.message(msg));
47
+ }
48
+ // Log body fat if provided
49
+ if (options.bodyFat !== undefined) {
50
+ await client.logBiometric({
51
+ type: "bodyfat",
52
+ value: options.bodyFat,
53
+ date: targetDate,
54
+ }, (msg) => s.message(msg));
55
+ }
56
+ // Log blood pressure if provided
57
+ if (options.systolic !== undefined && options.diastolic !== undefined) {
58
+ await client.logBiometric({
59
+ type: "bloodpressure",
60
+ systolic: options.systolic,
61
+ diastolic: options.diastolic,
62
+ date: targetDate,
63
+ }, (msg) => s.message(msg));
64
+ }
65
+ s.stop("Done.");
66
+ const logged = [];
67
+ if (options.weight !== undefined)
68
+ logged.push(`Weight: ${options.weight} ${unit}`);
69
+ if (options.bodyFat !== undefined)
70
+ logged.push(`Body Fat: ${options.bodyFat}%`);
71
+ if (options.systolic !== undefined && options.diastolic !== undefined)
72
+ logged.push(`Blood Pressure: ${options.systolic}/${options.diastolic} mmHg`);
73
+ p.outro(`Logged biometrics for ${targetDate}:\n ${logged.join("\n ")}`);
74
+ }
75
+ catch (error) {
76
+ s.stop("Failed.");
77
+ p.log.error(`Failed to log biometrics: ${formatKernelError(error)}`);
78
+ process.exit(1);
79
+ }
80
+ }
81
+ //# sourceMappingURL=biometrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biometrics.js","sourceRoot":"","sources":["../../src/commands/biometrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAWvD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAA0B;IACzD,8CAA8C;IAC9C,IACE,OAAO,CAAC,MAAM,KAAK,SAAS;QAC5B,OAAO,CAAC,OAAO,KAAK,SAAS;QAC7B,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,EACnE,CAAC;QACD,CAAC,CAAC,GAAG,CAAC,KAAK,CACT,2FAA2F,CAC5F,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,+CAA+C;IAC/C,IACE,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;QACnE,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,EACnE,CAAC;QACD,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,uBAAuB;IACvB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,IAAI,CAAC;IACjD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACpC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,eAAe;IACf,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACnE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAE/B,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAEzB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,mBAAmB,EAAE,CAAC;QAE3C,yBAAyB;QACzB,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,MAAM,CAAC,YAAY,CACvB;gBACE,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,OAAO,CAAC,MAAM;gBACrB,IAAI;gBACJ,IAAI,EAAE,UAAU;aACjB,EACD,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CACxB,CAAC;QACJ,CAAC;QAED,2BAA2B;QAC3B,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAClC,MAAM,MAAM,CAAC,YAAY,CACvB;gBACE,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,OAAO,CAAC,OAAO;gBACtB,IAAI,EAAE,UAAU;aACjB,EACD,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CACxB,CAAC;QACJ,CAAC;QAED,iCAAiC;QACjC,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACtE,MAAM,MAAM,CAAC,YAAY,CACvB;gBACE,IAAI,EAAE,eAAe;gBACrB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,IAAI,EAAE,UAAU;aACjB,EACD,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CACxB,CAAC;QACJ,CAAC;QAED,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEhB,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;YAC9B,MAAM,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QACnD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;YAC/B,MAAM,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC;QAC/C,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS;YACnE,MAAM,CAAC,IAAI,CACT,mBAAmB,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,SAAS,OAAO,CAChE,CAAC;QAEJ,CAAC,CAAC,KAAK,CAAC,yBAAyB,UAAU,QAAQ,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,6BAA6B,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import { diary } from "./commands/diary.js";
9
9
  import { weight } from "./commands/weight.js";
10
10
  import { exportCmd } from "./commands/export.js";
11
11
  import { recipes } from "./commands/recipes.js";
12
+ import { biometrics } from "./commands/biometrics.js";
12
13
  const require = createRequire(import.meta.url);
13
14
  const { version } = require("../package.json");
14
15
  const program = new Command();
@@ -91,5 +92,17 @@ program
91
92
  .action(async (options) => {
92
93
  await recipes(options);
93
94
  });
95
+ program
96
+ .command("biometrics")
97
+ .description("Log biometrics to Cronometer (weight, body fat, blood pressure)")
98
+ .option("-w, --weight <value>", "Weight value", parseFloat)
99
+ .option("-b, --body-fat <value>", "Body fat percentage", parseFloat)
100
+ .option("-s, --systolic <value>", "Systolic blood pressure (mmHg)", parseFloat)
101
+ .option("-d, --diastolic <value>", "Diastolic blood pressure (mmHg)", parseFloat)
102
+ .option("--date <date>", "Date (YYYY-MM-DD, yesterday, -1d)")
103
+ .option("-u, --unit <unit>", "Weight unit (kg or lbs)", "kg")
104
+ .action(async (options) => {
105
+ await biometrics(options);
106
+ });
94
107
  program.parse();
95
108
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Playwright code generator for Cronometer biometrics logging.
3
+ *
4
+ * Supports logging weight, body fat percentage, and blood pressure.
5
+ */
6
+ export interface BiometricEntry {
7
+ type: "weight" | "bodyfat" | "bloodpressure";
8
+ value?: number;
9
+ unit?: string;
10
+ systolic?: number;
11
+ diastolic?: number;
12
+ date: string;
13
+ }
14
+ /**
15
+ * Generate Playwright code for logging a biometric to Cronometer.
16
+ * Navigates to the diary, clicks BIOMETRIC button, selects the biometric type,
17
+ * fills in values, and adds to diary.
18
+ */
19
+ export declare function buildBiometricsCode(entry: BiometricEntry): string;
20
+ //# sourceMappingURL=biometrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biometrics.d.ts","sourceRoot":"","sources":["../../src/kernel/biometrics.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,eAAe,CAAC;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAsFjE"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Playwright code generator for Cronometer biometrics logging.
3
+ *
4
+ * Supports logging weight, body fat percentage, and blood pressure.
5
+ */
6
+ /**
7
+ * Generate Playwright code for logging a biometric to Cronometer.
8
+ * Navigates to the diary, clicks BIOMETRIC button, selects the biometric type,
9
+ * fills in values, and adds to diary.
10
+ */
11
+ export function buildBiometricsCode(entry) {
12
+ const { type, value, unit, systolic, diastolic } = entry;
13
+ const biometricName = type === "weight"
14
+ ? "Weight"
15
+ : type === "bodyfat"
16
+ ? "Body Fat"
17
+ : "Blood Pressure";
18
+ return `
19
+ // Navigate to dashboard first (where the BIOMETRIC button is)
20
+ await page.goto('https://cronometer.com/#dashboard', { waitUntil: 'domcontentloaded', timeout: 15000 });
21
+ await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {});
22
+ await page.waitForTimeout(2000);
23
+
24
+ // Check if logged in
25
+ const url = page.url();
26
+ if (url.includes('/login') || url.includes('/signin')) {
27
+ return { success: false, error: 'Not logged in. Login may have failed.' };
28
+ }
29
+
30
+ // Wait for the quick add panel to appear
31
+ try {
32
+ await page.waitForSelector('text="Quick Add to Diary"', { timeout: 10000 });
33
+ } catch {
34
+ return { success: false, error: 'Dashboard quick add panel not found' };
35
+ }
36
+ await page.waitForTimeout(500);
37
+
38
+ // Wait for and click BIOMETRIC button
39
+ try {
40
+ await page.waitForSelector('button:has-text("BIOMETRIC"), button:has-text("Biometric")', { timeout: 10000 });
41
+ } catch {
42
+ return { success: false, error: 'Could not find BIOMETRIC button' };
43
+ }
44
+
45
+ const biometricButton = page.getByRole('button', { name: /BIOMETRIC/i });
46
+ if (await biometricButton.count() === 0) {
47
+ return { success: false, error: 'BIOMETRIC button not found' };
48
+ }
49
+ await biometricButton.first().click();
50
+ await page.waitForTimeout(1000);
51
+
52
+ // Wait for biometric dialog
53
+ try {
54
+ await page.waitForSelector('text="Add Biometric"', { timeout: 5000 });
55
+ } catch {
56
+ return { success: false, error: 'Add Biometric dialog did not appear' };
57
+ }
58
+ await page.waitForTimeout(300);
59
+
60
+ // Click the biometric type (Weight, Body Fat, or Blood Pressure)
61
+ // Look for the biometric item by finding text with the name and clicking its container
62
+ const biometricItem = page.locator('.biometric-content-panel.pretty-row').filter({ hasText: '${biometricName}' }).first();
63
+ const itemCount = await biometricItem.count();
64
+
65
+ if (itemCount === 0) {
66
+ return { success: false, error: 'Could not find ${biometricName} in biometric list' };
67
+ }
68
+
69
+ await biometricItem.click();
70
+ await page.waitForTimeout(1000);
71
+
72
+ ${type === "weight" ? buildWeightInputCode(value, unit) : ""}
73
+ ${type === "bodyfat" ? buildBodyFatInputCode(value) : ""}
74
+ ${type === "bloodpressure" ? buildBloodPressureInputCode(systolic, diastolic) : ""}
75
+
76
+ // Wait for ADD TO DIARY button to become enabled, then click it
77
+ const addButton = page.getByRole('button', { name: /add.*diary/i });
78
+
79
+ // Wait for button to be enabled
80
+ await page.waitForTimeout(500);
81
+ const isEnabled = await addButton.isEnabled().catch(() => false);
82
+ if (!isEnabled) {
83
+ return { success: false, error: 'Add to Diary button is disabled. Value may not have been filled correctly.' };
84
+ }
85
+
86
+ await addButton.click();
87
+
88
+ // Wait for dialog to close
89
+ await page.waitForSelector('text="Add Biometric"', { state: 'hidden', timeout: 5000 }).catch(() => {});
90
+ await page.waitForTimeout(500);
91
+
92
+ return { success: true };
93
+ `;
94
+ }
95
+ function buildWeightInputCode(value, unit) {
96
+ return `
97
+ // Fill weight value using getByRole
98
+ const weightInput = page.getByRole('textbox', { name: 'Weight' });
99
+ if (await weightInput.count() === 0) {
100
+ return { success: false, error: 'Could not find weight input field' };
101
+ }
102
+ await weightInput.fill(String(${value}));
103
+ // Press Tab to trigger validation and move focus
104
+ await weightInput.press('Tab');
105
+ await page.waitForTimeout(500);
106
+
107
+ // Select unit if not kg
108
+ if ('${unit}' === 'lbs') {
109
+ const unitButton = page.getByRole('button', { name: /Unit.*kg/i });
110
+ if (await unitButton.count() > 0) {
111
+ await unitButton.click();
112
+ await page.waitForTimeout(300);
113
+ // Select lbs from dropdown
114
+ const lbsOption = page.getByText('lbs', { exact: true });
115
+ if (await lbsOption.count() > 0) {
116
+ await lbsOption.click();
117
+ }
118
+ }
119
+ }
120
+ await page.waitForTimeout(500);
121
+ `;
122
+ }
123
+ function buildBodyFatInputCode(value) {
124
+ return `
125
+ // Fill body fat percentage using getByRole
126
+ const bodyFatInput = page.getByRole('textbox', { name: 'Body Fat' });
127
+ if (await bodyFatInput.count() === 0) {
128
+ return { success: false, error: 'Could not find body fat input field' };
129
+ }
130
+ await bodyFatInput.fill(String(${value}));
131
+ // Press Tab to trigger validation and move focus
132
+ await bodyFatInput.press('Tab');
133
+ await page.waitForTimeout(500);
134
+ `;
135
+ }
136
+ function buildBloodPressureInputCode(systolic, diastolic) {
137
+ return `
138
+ // Fill blood pressure values
139
+ // After clicking "Blood Pressure", there should be exactly 2 visible textbox inputs
140
+ const allTextboxes = page.getByRole('textbox');
141
+ const visibleInputs = [];
142
+
143
+ for (let i = 0; i < await allTextboxes.count(); i++) {
144
+ const input = allTextboxes.nth(i);
145
+ if (await input.isVisible()) {
146
+ const placeholder = await input.getAttribute('placeholder');
147
+ // Skip the search box
148
+ if (!placeholder || !placeholder.toLowerCase().includes('search')) {
149
+ visibleInputs.push(i);
150
+ }
151
+ }
152
+ }
153
+
154
+ if (visibleInputs.length < 2) {
155
+ return { success: false, error: 'Could not find systolic and diastolic input fields. Found ' + visibleInputs.length + ' inputs.' };
156
+ }
157
+
158
+ // Fill systolic (first BP input)
159
+ const systolicInput = allTextboxes.nth(visibleInputs[0]);
160
+ await systolicInput.fill(String(${systolic}));
161
+ await systolicInput.press('Tab');
162
+ await page.waitForTimeout(300);
163
+
164
+ // Fill diastolic (second BP input)
165
+ const diastolicInput = allTextboxes.nth(visibleInputs[1]);
166
+ await diastolicInput.fill(String(${diastolic}));
167
+ await diastolicInput.press('Tab');
168
+ await page.waitForTimeout(500);
169
+ `;
170
+ }
171
+ //# sourceMappingURL=biometrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biometrics.js","sourceRoot":"","sources":["../../src/kernel/biometrics.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAqB;IACvD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAEzD,MAAM,aAAa,GACjB,IAAI,KAAK,QAAQ;QACf,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,IAAI,KAAK,SAAS;YAClB,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,gBAAgB,CAAC;IAEzB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mGA4C0F,aAAa;;;;wDAIxD,aAAa;;;;;;MAM/D,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,KAAM,EAAE,IAAK,CAAC,CAAC,CAAC,CAAC,EAAE;MAC5D,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAM,CAAC,CAAC,CAAC,CAAC,EAAE;MACvD,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,2BAA2B,CAAC,QAAS,EAAE,SAAU,CAAC,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;GAmBrF,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa,EAAE,IAAY;IACvD,OAAO;;;;;;oCAM2B,KAAK;;;;;;WAM9B,IAAI;;;;;;;;;;;;;GAaZ,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAa;IAC1C,OAAO;;;;;;qCAM4B,KAAK;;;;GAIvC,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAClC,QAAgB,EAChB,SAAiB;IAEjB,OAAO;;;;;;;;;;;;;;;;;;;;;;;sCAuB6B,QAAQ;;;;;;uCAMP,SAAS;;;GAG7C,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/kernel/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAGhB,eAAe,EACf,SAAS,EACT,YAAY,EACZ,UAAU,EAEV,UAAU,EACX,MAAM,wBAAwB,CAAC;AAGhC,MAAM,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAC5C,YAAY,EACV,eAAe,EACf,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,GACX,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAe7D"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/kernel/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAGhB,eAAe,EACf,SAAS,EACT,YAAY,EACZ,UAAU,EAEV,UAAU,EACX,MAAM,wBAAwB,CAAC;AAsBhC,MAAM,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAC5C,YAAY,EACV,eAAe,EACf,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,GACX,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAe7D"}
@@ -4,6 +4,23 @@
4
4
  import Kernel from "@onkernel/sdk";
5
5
  import { createAutomationClient } from "../automation/runner.js";
6
6
  import { getCredential } from "../credentials.js";
7
+ /**
8
+ * Client-side HTTP timeout for Kernel API requests.
9
+ *
10
+ * The SDK defaults to 60s, but automations are dispatched with `timeout_sec`
11
+ * values up to 120s (see `addCustomFood`). When the client gives up first the
12
+ * browser keeps going, so Cronometer commits the change while crono reports
13
+ * failure — and a retry then duplicates the data. Keep this comfortably above
14
+ * the largest `timeout_sec` used by any automation.
15
+ */
16
+ const KERNEL_REQUEST_TIMEOUT_MS = 10 * 60 * 1000;
17
+ /**
18
+ * Lifetime of a remote browser session.
19
+ *
20
+ * A single command can spend ~60s logging in before a 120s automation even
21
+ * starts, so the previous 120s budget could expire mid-operation.
22
+ */
23
+ const BROWSER_SESSION_TIMEOUT_SEC = 300;
7
24
  /**
8
25
  * Create a Kernel client for Cronometer automation.
9
26
  *
@@ -18,7 +35,7 @@ export async function getKernelClient() {
18
35
  " export KERNEL_API_KEY=your-key-here");
19
36
  }
20
37
  process.env["KERNEL_API_KEY"] = apiKey;
21
- const kernel = new Kernel();
38
+ const kernel = new Kernel({ timeout: KERNEL_REQUEST_TIMEOUT_MS });
22
39
  return createAutomationClient(createKernelRuntimeFactory(kernel));
23
40
  }
24
41
  function createKernelRuntimeFactory(kernel) {
@@ -26,7 +43,7 @@ function createKernelRuntimeFactory(kernel) {
26
43
  const browser = await kernel.browsers.create({
27
44
  headless: hasAutoCredentials,
28
45
  stealth: true,
29
- timeout_seconds: hasAutoCredentials ? 120 : 300,
46
+ timeout_seconds: BROWSER_SESSION_TIMEOUT_SEC,
30
47
  });
31
48
  return {
32
49
  liveViewUrl: browser.browser_live_view_url,
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/kernel/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,MAAM,MAAM,eAAe,CAAC;AACnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAYjE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAWlD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,MAAM,GACV,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,6BAA6B;YAC3B,uDAAuD;YACvD,uCAAuC,CAC1C,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IAE5B,OAAO,sBAAsB,CAAC,0BAA0B,CAAC,MAAM,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,0BAA0B,CAAC,MAAc;IAChD,OAAO,KAAK,EAAE,kBAA2B,EAAE,EAAE;QAC3C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC3C,QAAQ,EAAE,kBAAkB;YAC5B,OAAO,EAAE,IAAI;YACb,eAAe,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;SAChD,CAAC,CAAC;QAEH,OAAO;YACL,WAAW,EAAE,OAAO,CAAC,qBAAqB;YAC1C,OAAO,EAAE,KAAK,EACZ,IAAY,EACZ,UAAU,GAAG,EAAE,EAC0B,EAAE;gBAC3C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CACvD,OAAO,CAAC,UAAU,EAClB;oBACE,IAAI;oBACJ,WAAW,EAAE,UAAU;iBACxB,CACF,CAAC;gBACF,OAAO,QAA0C,CAAC;YACpD,CAAC;YACD,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBACvD,CAAC;gBAAC,MAAM,CAAC;oBACP,+CAA+C;gBACjD,CAAC;YACH,CAAC;SAC0B,CAAC;IAChC,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/kernel/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,MAAM,MAAM,eAAe,CAAC;AACnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAYjE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD;;;;;;;;GAQG;AACH,MAAM,yBAAyB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAWxC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,MAAM,GACV,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,6BAA6B;YAC3B,uDAAuD;YACvD,uCAAuC,CAC1C,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC,CAAC;IAElE,OAAO,sBAAsB,CAAC,0BAA0B,CAAC,MAAM,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,0BAA0B,CAAC,MAAc;IAChD,OAAO,KAAK,EAAE,kBAA2B,EAAE,EAAE;QAC3C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC3C,QAAQ,EAAE,kBAAkB;YAC5B,OAAO,EAAE,IAAI;YACb,eAAe,EAAE,2BAA2B;SAC7C,CAAC,CAAC;QAEH,OAAO;YACL,WAAW,EAAE,OAAO,CAAC,qBAAqB;YAC1C,OAAO,EAAE,KAAK,EACZ,IAAY,EACZ,UAAU,GAAG,EAAE,EAC0B,EAAE;gBAC3C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CACvD,OAAO,CAAC,UAAU,EAClB;oBACE,IAAI;oBACJ,WAAW,EAAE,UAAU;iBACxB,CACF,CAAC;gBACF,OAAO,QAA0C,CAAC;YACpD,CAAC;YACD,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBACvD,CAAC;gBAAC,MAAM,CAAC;oBACP,+CAA+C;gBACjD,CAAC;YACH,CAAC;SAC0B,CAAC;IAChC,CAAC,CAAC;AACJ,CAAC"}
@@ -19,6 +19,12 @@ export declare function buildNavigateToLoginCode(): string;
19
19
  * Generate Playwright code that automates Cronometer login.
20
20
  * Fills email/password, submits, and verifies login succeeded.
21
21
  * Credentials are embedded via JSON.stringify for safe escaping.
22
+ *
23
+ * Navigates directly to /login/. An earlier version loaded the marketing
24
+ * homepage and clicked its "Log In" link, but that click frequently does not
25
+ * navigate — and because the loop recorded a successful *click* it also
26
+ * suppressed the direct-navigation fallback, leaving the form unreachable and
27
+ * failing with "Could not find email input on https://cronometer.com/".
22
28
  */
23
29
  export declare function buildAutoLoginCode(username: string, password: string): string;
24
30
  //# sourceMappingURL=login.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/kernel/login.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAc5C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAKjD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiH7E"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/kernel/login.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAW5C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAKjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAyG7E"}
@@ -16,10 +16,7 @@ export function buildLoginCheckCode() {
16
16
  await page.waitForTimeout(1000);
17
17
  const url = page.url();
18
18
  ${buildLoginPresentedCheckCode()}
19
- const diaryPresented = await page.evaluate(() => {
20
- return !!document.querySelector('i.diary-date-previous, i.diary-date-next') ||
21
- /Energy\\s+\\d+\\.?\\d*\\s*kcal/i.test(document.body.innerText);
22
- }).catch(() => false);
19
+ ${buildDiaryPresentedCheckCode()}
23
20
  const isLoggedIn = url.includes('#diary') && !url.includes('/login') && !url.includes('/signin') && !loginPresented && diaryPresented;
24
21
  return { success: true, loggedIn: isLoggedIn, url, loginPresented, diaryPresented };
25
22
  `;
@@ -38,35 +35,23 @@ export function buildNavigateToLoginCode() {
38
35
  * Generate Playwright code that automates Cronometer login.
39
36
  * Fills email/password, submits, and verifies login succeeded.
40
37
  * Credentials are embedded via JSON.stringify for safe escaping.
38
+ *
39
+ * Navigates directly to /login/. An earlier version loaded the marketing
40
+ * homepage and clicked its "Log In" link, but that click frequently does not
41
+ * navigate — and because the loop recorded a successful *click* it also
42
+ * suppressed the direct-navigation fallback, leaving the form unreachable and
43
+ * failing with "Could not find email input on https://cronometer.com/".
41
44
  */
42
45
  export function buildAutoLoginCode(username, password) {
43
46
  const safeUser = JSON.stringify(username);
44
47
  const safePass = JSON.stringify(password);
45
48
  return `
46
- // Navigate to cronometer.com and click through to the login page
47
- await page.goto('https://cronometer.com', { waitUntil: 'domcontentloaded', timeout: 15000 });
48
- await page.waitForLoadState('networkidle', { timeout: 8000 }).catch(() => {});
49
-
50
- // Click the "Log In" link in the top navigation
51
- const loginLinkSelectors = ['a[href="/login/"]', 'a[href="/login"]', 'a:has-text("Log In")', 'a:has-text("Login")'];
52
- let clickedLogin = false;
53
- for (const sel of loginLinkSelectors) {
54
- try {
55
- const el = page.locator(sel);
56
- if (await el.count() > 0) {
57
- await el.first().click();
58
- clickedLogin = true;
59
- break;
60
- }
61
- } catch {}
62
- }
63
- if (!clickedLogin) {
64
- // Fallback: navigate directly
65
- await page.goto('https://cronometer.com/login/', { waitUntil: 'domcontentloaded', timeout: 15000 });
66
- }
49
+ // Navigate straight to the login page.
50
+ await page.goto('https://cronometer.com/login/', { waitUntil: 'domcontentloaded', timeout: 20000 });
51
+ await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {});
67
52
 
68
53
  // Wait for login page to load
69
- await page.waitForSelector('input[type="email"], input[name="username"], input[name="email"], #email, #username', { timeout: 10000 }).catch(() => {});
54
+ await page.waitForSelector('input[type="email"], input[name="username"], input[name="email"], #email, #username', { timeout: 15000 }).catch(() => {});
70
55
 
71
56
  // Fill email — try multiple selectors
72
57
  const emailSelectors = ['input[type="email"]', 'input[name="username"]', 'input[name="email"]', '#email', '#username'];
@@ -119,13 +104,23 @@ export function buildAutoLoginCode(username, password) {
119
104
  return { success: false, loggedIn: false, url: page.url(), error: 'Could not find submit button on ' + page.url() };
120
105
  }
121
106
 
122
- // Wait for navigation after login
107
+ // Wait for navigation after login. The GWT app then needs a moment to swap
108
+ // the login UI for the app shell — checking too early made a login that had
109
+ // actually succeeded report "Login verification failed".
123
110
  await page.waitForURL(u => !u.href.includes('/login') && !u.href.includes('/signin'), { timeout: 15000 }).catch(() => {});
124
- await page.waitForTimeout(500);
111
+ await page.waitForTimeout(3000);
112
+ await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {});
113
+
114
+ // Confirm with a positive signal — that the diary actually renders — rather
115
+ // than relying only on the absence of login UI, which races the app's boot.
116
+ await page.goto('https://cronometer.com/#diary', { waitUntil: 'domcontentloaded', timeout: 20000 }).catch(() => {});
117
+ await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => {});
118
+ await page.waitForTimeout(2000);
125
119
 
126
120
  const url = page.url();
127
121
  ${buildLoginPresentedCheckCode()}
128
- const loggedIn = !url.includes('/login') && !url.includes('/signin') && !loginPresented;
122
+ ${buildDiaryPresentedCheckCode()}
123
+ const loggedIn = !url.includes('/login') && !url.includes('/signin') && (diaryPresented || !loginPresented);
129
124
 
130
125
  // If still on login page, check for error messages (rate limit, wrong creds, etc.)
131
126
  let loginError = null;
@@ -152,6 +147,18 @@ export function buildAutoLoginCode(username, password) {
152
147
  return { success: true, loggedIn, url, loginError };
153
148
  `;
154
149
  }
150
+ /**
151
+ * Generate code that sets `diaryPresented` — a positive signal that the diary
152
+ * UI actually rendered, rather than the mere absence of login UI.
153
+ */
154
+ function buildDiaryPresentedCheckCode() {
155
+ return `
156
+ const diaryPresented = await page.evaluate(() => {
157
+ return !!document.querySelector('i.diary-date-previous, i.diary-date-next') ||
158
+ /Energy\\s+\\d+\\.?\\d*\\s*kcal/i.test(document.body.innerText);
159
+ }).catch(() => false);
160
+ `;
161
+ }
155
162
  function buildLoginPresentedCheckCode() {
156
163
  return `
157
164
  const loginPresented = await page.evaluate(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/kernel/login.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO;;;;;MAKH,4BAA4B,EAAE;;;;;;;GAOjC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB;IACtC,OAAO;;;GAGN,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,QAAgB;IACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAE1C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kCAiCyB,QAAQ;;;;;;;;;;;;;;;;;kCAiBR,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAgCpC,4BAA4B,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BjC,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;GAoBN,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/kernel/login.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO;;;;;MAKH,4BAA4B,EAAE;MAC9B,4BAA4B,EAAE;;;GAGjC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB;IACtC,OAAO;;;GAGN,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,QAAgB;IACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAE1C,OAAO;;;;;;;;;;;;;;;kCAeyB,QAAQ;;;;;;;;;;;;;;;;;kCAiBR,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAyCpC,4BAA4B,EAAE;MAC9B,4BAA4B,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BjC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,4BAA4B;IACnC,OAAO;;;;;GAKN,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;GAoBN,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milldr/crono",
3
- "version": "0.6.1",
3
+ "version": "0.8.0",
4
4
  "description": "CLI for Cronometer automation via Kernel.sh",
5
5
  "type": "module",
6
6
  "bin": {