@milldr/crono 0.4.0 → 0.6.1

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.
Files changed (81) hide show
  1. package/README.md +71 -13
  2. package/dist/automation/client.d.ts +5 -0
  3. package/dist/automation/client.d.ts.map +1 -0
  4. package/dist/automation/client.js +13 -0
  5. package/dist/automation/client.js.map +1 -0
  6. package/dist/automation/runner.d.ts +3 -0
  7. package/dist/automation/runner.d.ts.map +1 -0
  8. package/dist/automation/runner.js +137 -0
  9. package/dist/automation/runner.js.map +1 -0
  10. package/dist/automation/types.d.ts +66 -0
  11. package/dist/automation/types.d.ts.map +1 -0
  12. package/dist/automation/types.js +2 -0
  13. package/dist/automation/types.js.map +1 -0
  14. package/dist/commands/add.js +3 -3
  15. package/dist/commands/add.js.map +1 -1
  16. package/dist/commands/diary.d.ts +1 -1
  17. package/dist/commands/diary.d.ts.map +1 -1
  18. package/dist/commands/diary.js +3 -3
  19. package/dist/commands/diary.js.map +1 -1
  20. package/dist/commands/export.d.ts +1 -0
  21. package/dist/commands/export.d.ts.map +1 -1
  22. package/dist/commands/export.js +45 -3
  23. package/dist/commands/export.js.map +1 -1
  24. package/dist/commands/log.js +3 -3
  25. package/dist/commands/log.js.map +1 -1
  26. package/dist/commands/login.d.ts.map +1 -1
  27. package/dist/commands/login.js +53 -26
  28. package/dist/commands/login.js.map +1 -1
  29. package/dist/commands/quick-add.js +3 -3
  30. package/dist/commands/quick-add.js.map +1 -1
  31. package/dist/commands/recipes.d.ts +5 -0
  32. package/dist/commands/recipes.d.ts.map +1 -0
  33. package/dist/commands/recipes.js +35 -0
  34. package/dist/commands/recipes.js.map +1 -0
  35. package/dist/commands/weight.d.ts.map +1 -1
  36. package/dist/commands/weight.js +3 -3
  37. package/dist/commands/weight.js.map +1 -1
  38. package/dist/config.d.ts +6 -0
  39. package/dist/config.d.ts.map +1 -1
  40. package/dist/config.js +6 -0
  41. package/dist/config.js.map +1 -1
  42. package/dist/cronometer/export.d.ts +1 -1
  43. package/dist/cronometer/export.d.ts.map +1 -1
  44. package/dist/cronometer/export.js +1 -0
  45. package/dist/cronometer/export.js.map +1 -1
  46. package/dist/cronometer/parse.d.ts +14 -0
  47. package/dist/cronometer/parse.d.ts.map +1 -1
  48. package/dist/cronometer/parse.js +62 -0
  49. package/dist/cronometer/parse.js.map +1 -1
  50. package/dist/index.js +10 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/kernel/add-custom-food.d.ts.map +1 -1
  53. package/dist/kernel/add-custom-food.js +6 -127
  54. package/dist/kernel/add-custom-food.js.map +1 -1
  55. package/dist/kernel/client.d.ts +4 -56
  56. package/dist/kernel/client.d.ts.map +1 -1
  57. package/dist/kernel/client.js +29 -274
  58. package/dist/kernel/client.js.map +1 -1
  59. package/dist/kernel/food-dialog.d.ts +13 -0
  60. package/dist/kernel/food-dialog.d.ts.map +1 -0
  61. package/dist/kernel/food-dialog.js +294 -0
  62. package/dist/kernel/food-dialog.js.map +1 -0
  63. package/dist/kernel/log-food.d.ts.map +1 -1
  64. package/dist/kernel/log-food.js +2 -175
  65. package/dist/kernel/log-food.js.map +1 -1
  66. package/dist/kernel/login.d.ts +1 -1
  67. package/dist/kernel/login.d.ts.map +1 -1
  68. package/dist/kernel/login.js +34 -4
  69. package/dist/kernel/login.js.map +1 -1
  70. package/dist/kernel/quick-add.d.ts.map +1 -1
  71. package/dist/kernel/quick-add.js +9 -186
  72. package/dist/kernel/quick-add.js.map +1 -1
  73. package/dist/kernel/recipes.d.ts +10 -0
  74. package/dist/kernel/recipes.d.ts.map +1 -0
  75. package/dist/kernel/recipes.js +38 -0
  76. package/dist/kernel/recipes.js.map +1 -0
  77. package/dist/playwright/client.d.ts +6 -0
  78. package/dist/playwright/client.d.ts.map +1 -0
  79. package/dist/playwright/client.js +41 -0
  80. package/dist/playwright/client.js.map +1 -0
  81. package/package.json +3 -2
@@ -5,6 +5,7 @@
5
5
  * kernel.browsers.playwright.execute(). The code has access to
6
6
  * `page`, `context`, and `browser` from the Playwright environment.
7
7
  */
8
+ import { buildFoodDialogCode } from "./food-dialog.js";
8
9
  /**
9
10
  * Nutrient labels as they appear in Cronometer's nutrition facts editor.
10
11
  */
@@ -171,7 +172,7 @@ export function buildAddCustomFoodCode(entry) {
171
172
  if (!saveClicked) {
172
173
  return { success: false, error: 'Could not find "Save Changes" button' };
173
174
  }
174
- await page.waitForTimeout(1000);
175
+ await page.waitForTimeout(15000);
175
176
 
176
177
  // If --log is set, continue to log the food to diary
177
178
  if (mealLabel) {
@@ -180,132 +181,10 @@ export function buildAddCustomFoodCode(entry) {
180
181
  await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {});
181
182
  await page.waitForTimeout(500);
182
183
 
183
- // Helper: right-click an element from a list of selectors
184
- async function rightClickFirst(selectors, description) {
185
- for (const sel of selectors) {
186
- try {
187
- const el = page.locator(sel);
188
- if (await el.count() > 0) {
189
- await el.first().click({ button: 'right' });
190
- return true;
191
- }
192
- } catch {}
193
- }
194
- return false;
195
- }
196
-
197
- // Right-click the meal category
198
- const mealClicked = await rightClickFirst([
199
- 'text="' + mealLabel + '"',
200
- ':has-text("' + mealLabel + '")',
201
- ], 'meal category');
202
- if (!mealClicked) {
203
- return { success: false, error: 'Food created but could not find meal category "' + mealLabel + '" in diary' };
204
- }
205
- await page.waitForSelector('text="Add Food..."', { timeout: 3000 }).catch(() =>
206
- page.waitForSelector('text="Add Food"', { timeout: 2000 }).catch(() => {})
207
- );
208
-
209
- // Click "Add Food..." in context menu
210
- const addFoodClicked = await clickFirst([
211
- 'text="Add Food..."',
212
- 'text="Add Food\u2026"',
213
- 'text="Add Food"',
214
- '[role="menuitem"]:has-text("Add Food")',
215
- ], 'Add Food menu item');
216
- if (!addFoodClicked) {
217
- return { success: false, error: 'Food created but could not find "Add Food" in context menu' };
218
- }
219
- await page.waitForTimeout(200);
220
-
221
- // Wait for "Add Food to Diary" dialog
222
- try {
223
- await page.waitForSelector('text="Add Food to Diary"', { timeout: 5000 });
224
- } catch {
225
- return { success: false, error: 'Food created but Add Food to Diary dialog did not appear' };
226
- }
227
- await page.waitForTimeout(300);
228
-
229
- // Search for the just-created food
230
- const searchSelectors = [
231
- 'input[placeholder*="Search all foods" i]',
232
- 'input[placeholder*="Search" i]',
233
- 'input[placeholder*="food" i]',
234
- 'input.gwt-TextBox',
235
- 'input[type="text"]',
236
- 'input[type="search"]',
237
- ];
238
- let searched = false;
239
- for (const sel of searchSelectors) {
240
- try {
241
- const el = page.locator(sel);
242
- if (await el.count() > 0) {
243
- await el.first().click();
244
- await page.waitForTimeout(200);
245
- await el.first().fill('');
246
- await page.keyboard.type(foodName, { delay: 50 });
247
- searched = true;
248
- break;
249
- }
250
- } catch {}
251
- }
252
- if (!searched) {
253
- return { success: false, error: 'Food created but could not find search bar in Add Food dialog' };
254
- }
255
- await page.waitForTimeout(300);
256
-
257
- // Click SEARCH
258
- await clickFirst([
259
- 'text="SEARCH"',
260
- 'button:has-text("SEARCH")',
261
- 'button:has-text("Search")',
262
- ], 'SEARCH button');
263
- await page.waitForSelector('td:has-text("' + foodName + '")', { timeout: 8000 }).catch(() => {});
264
-
265
- // Select the search result
266
- const resultSelectors = [
267
- 'td:has-text("' + foodName + '")',
268
- 'tr:has-text("' + foodName + '") td',
269
- '.gwt-HTML:has-text("' + foodName + '")',
270
- 'div:has-text("' + foodName + '"):not(:has(input))',
271
- ];
272
- let resultClicked = false;
273
- for (const sel of resultSelectors) {
274
- try {
275
- const el = page.locator(sel);
276
- if (await el.count() > 0) {
277
- await el.first().click();
278
- resultClicked = true;
279
- break;
280
- }
281
- } catch {}
282
- }
283
- if (!resultClicked) {
284
- return { success: false, error: 'Food created but no search result found for "' + foodName + '"' };
285
- }
286
- await page.waitForTimeout(200);
287
-
288
- // Wait for serving size panel
289
- try {
290
- await page.waitForSelector('text="Serving Size"', { timeout: 5000 });
291
- } catch {
292
- return { success: false, error: 'Food created but Serving Size panel did not appear' };
293
- }
294
- await page.waitForTimeout(500);
295
-
296
- // Click "ADD TO DIARY"
297
- const addClicked = await clickFirst([
298
- 'button:has-text("ADD TO DIARY")',
299
- 'button:has-text("Add to Diary")',
300
- 'text="ADD TO DIARY"',
301
- 'text="Add to Diary"',
302
- 'button[type="submit"]',
303
- ], 'ADD TO DIARY button');
304
- if (!addClicked) {
305
- return { success: false, error: 'Food created but could not find "Add to Diary" button' };
306
- }
307
- await page.waitForSelector('text="Add Food to Diary"', { state: 'hidden', timeout: 8000 }).catch(() => {});
308
- await page.waitForTimeout(300);
184
+ ${buildFoodDialogCode({
185
+ errorPrefix: "Food created but ",
186
+ requireServingSize: false,
187
+ })}
309
188
  }
310
189
 
311
190
  return { success: true };
@@ -1 +1 @@
1
- {"version":3,"file":"add-custom-food.js","sourceRoot":"","sources":["../../src/kernel/add-custom-food.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAA2B;IACrD,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,oBAAoB;IAC3B,GAAG,EAAE,WAAW;CACjB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAsB;IAC3D,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAE3D,MAAM,OAAO,GACX,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACxE,MAAM,SAAS,GAAG,OAAO;QACvB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;QAClE,CAAC,CAAC,IAAI,CAAC;IAET,iFAAiF;IACjF,MAAM,aAAa,GACjB,QAAQ,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAErE,MAAM,SAAS,GAAuC,EAAE,CAAC;IACzD,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;IAC1E,IAAI,OAAO,KAAK,SAAS;QACvB,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACrE,IAAI,KAAK,KAAK,SAAS;QACrB,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACjE,IAAI,GAAG,KAAK,SAAS;QACnB,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAE7D,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAEhD,OAAO;uBACc,QAAQ;wBACP,aAAa;wBACb,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyQlC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"add-custom-food.js","sourceRoot":"","sources":["../../src/kernel/add-custom-food.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAA2B;IACrD,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,oBAAoB;IAC3B,GAAG,EAAE,WAAW;CACjB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAsB;IAC3D,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAE3D,MAAM,OAAO,GACX,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACxE,MAAM,SAAS,GAAG,OAAO;QACvB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;QAClE,CAAC,CAAC,IAAI,CAAC;IAET,iFAAiF;IACjF,MAAM,aAAa,GACjB,QAAQ,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAErE,MAAM,SAAS,GAAuC,EAAE,CAAC;IACzD,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;IAC1E,IAAI,OAAO,KAAK,SAAS;QACvB,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACrE,IAAI,KAAK,KAAK,SAAS;QACrB,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACjE,IAAI,GAAG,KAAK,SAAS;QACnB,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAE7D,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAEhD,OAAO;uBACc,QAAQ;wBACP,aAAa;wBACb,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwInC,mBAAmB,CAAC;QACpB,WAAW,EAAE,mBAAmB;QAChC,kBAAkB,EAAE,KAAK;KAC1B,CAAC;;;;GAIC,CAAC;AACJ,CAAC"}
@@ -1,61 +1,9 @@
1
1
  /**
2
- * Kernel.sh browser automation client for Cronometer.
3
- *
4
- * Orchestrates the SDK to manage browser sessions, handle login,
5
- * and execute Playwright automation for diary entries.
6
- *
7
- * Each operation creates a fresh browser, logs in, performs the
8
- * action, and tears down.
2
+ * Kernel.sh browser automation runtime.
9
3
  */
10
- export interface MacroEntry {
11
- protein?: number;
12
- carbs?: number;
13
- fat?: number;
14
- alcohol?: number;
15
- meal?: string;
16
- date?: string;
17
- }
18
- export interface WeightData {
19
- date: string;
20
- weight: number | null;
21
- unit: string;
22
- }
23
- export interface DiaryData {
24
- date: string;
25
- calories: number;
26
- protein: number;
27
- carbs: number;
28
- fat: number;
29
- targets?: {
30
- calories: number | null;
31
- protein: number | null;
32
- carbs: number | null;
33
- fat: number | null;
34
- } | null;
35
- exercise?: {
36
- caloriesBurned: number;
37
- } | null;
38
- }
39
- export interface CustomFoodEntry {
40
- name: string;
41
- protein?: number;
42
- carbs?: number;
43
- fat?: number;
44
- calories?: number;
45
- log?: string | boolean;
46
- }
47
- export interface LogFoodEntry {
48
- name: string;
49
- meal?: string;
50
- servings?: number;
51
- }
52
- export interface KernelClient {
53
- addQuickEntry(entry: MacroEntry, onStatus?: (msg: string) => void): Promise<void>;
54
- getWeight(dates: string[], onStatus?: (msg: string) => void): Promise<WeightData[]>;
55
- getDiary(dates: string[], onStatus?: (msg: string) => void, scrapeTargets?: boolean): Promise<DiaryData[]>;
56
- addCustomFood(entry: CustomFoodEntry, onStatus?: (msg: string) => void): Promise<void>;
57
- logFood(entry: LogFoodEntry, onStatus?: (msg: string) => void): Promise<void>;
58
- }
4
+ import type { AutomationClient, CustomFoodEntry, DiaryData, LogFoodEntry, MacroEntry, WeightData } from "../automation/types.js";
5
+ export type KernelClient = AutomationClient;
6
+ export type { CustomFoodEntry, DiaryData, LogFoodEntry, MacroEntry, WeightData, };
59
7
  /**
60
8
  * Create a Kernel client for Cronometer automation.
61
9
  *
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/kernel/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgBH,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE;QACR,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;KACpB,GAAG,IAAI,CAAC;IACT,QAAQ,CAAC,EAAE;QACT,cAAc,EAAE,MAAM,CAAC;KACxB,GAAG,IAAI,CAAC;CACV;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CACX,KAAK,EAAE,UAAU,EACjB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC/B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,SAAS,CACP,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC/B,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACzB,QAAQ,CACN,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAChC,aAAa,CAAC,EAAE,OAAO,GACtB,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACxB,aAAa,CACX,KAAK,EAAE,eAAe,EACtB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC/B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/E;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CA6B7D"}
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,21 +1,9 @@
1
1
  /**
2
- * Kernel.sh browser automation client for Cronometer.
3
- *
4
- * Orchestrates the SDK to manage browser sessions, handle login,
5
- * and execute Playwright automation for diary entries.
6
- *
7
- * Each operation creates a fresh browser, logs in, performs the
8
- * action, and tears down.
2
+ * Kernel.sh browser automation runtime.
9
3
  */
10
- import * as p from "@clack/prompts";
11
4
  import Kernel from "@onkernel/sdk";
5
+ import { createAutomationClient } from "../automation/runner.js";
12
6
  import { getCredential } from "../credentials.js";
13
- import { buildAutoLoginCode, buildLoginCheckCode, buildNavigateToLoginCode, } from "./login.js";
14
- import { buildQuickAddCode } from "./quick-add.js";
15
- import { buildAddCustomFoodCode } from "./add-custom-food.js";
16
- import { buildLogFoodCode } from "./log-food.js";
17
- import { buildDiaryCode } from "./diary.js";
18
- import { buildWeightCode } from "./weight.js";
19
7
  /**
20
8
  * Create a Kernel client for Cronometer automation.
21
9
  *
@@ -31,266 +19,33 @@ export async function getKernelClient() {
31
19
  }
32
20
  process.env["KERNEL_API_KEY"] = apiKey;
33
21
  const kernel = new Kernel();
34
- return {
35
- addQuickEntry: (entry, onStatus) => addQuickEntry(kernel, entry, onStatus),
36
- getWeight: (dates, onStatus) => getWeight(kernel, dates, onStatus),
37
- getDiary: (dates, onStatus, scrapeTargets) => getDiary(kernel, dates, onStatus, scrapeTargets),
38
- addCustomFood: (entry, onStatus) => addCustomFood(kernel, entry, onStatus),
39
- logFood: (entry, onStatus) => logFood(kernel, entry, onStatus),
22
+ return createAutomationClient(createKernelRuntimeFactory(kernel));
23
+ }
24
+ function createKernelRuntimeFactory(kernel) {
25
+ return async (hasAutoCredentials) => {
26
+ const browser = await kernel.browsers.create({
27
+ headless: hasAutoCredentials,
28
+ stealth: true,
29
+ timeout_seconds: hasAutoCredentials ? 120 : 300,
30
+ });
31
+ return {
32
+ liveViewUrl: browser.browser_live_view_url,
33
+ execute: async (code, timeoutSec = 60) => {
34
+ const response = await kernel.browsers.playwright.execute(browser.session_id, {
35
+ code,
36
+ timeout_sec: timeoutSec,
37
+ });
38
+ return response;
39
+ },
40
+ close: async () => {
41
+ try {
42
+ await kernel.browsers.deleteByID(browser.session_id);
43
+ }
44
+ catch {
45
+ // Browser may already be cleaned up by Kernel.
46
+ }
47
+ },
48
+ };
40
49
  };
41
50
  }
42
- /**
43
- * Execute the quick-add automation on Cronometer.
44
- * Creates a browser, logs in, performs the quick-add, then tears down.
45
- */
46
- async function addQuickEntry(kernel, entry, onStatus) {
47
- const username = getCredential("cronometer-username");
48
- const password = getCredential("cronometer-password");
49
- const hasAutoCreds = !!(username && password);
50
- const browser = await kernel.browsers.create({
51
- headless: hasAutoCreds,
52
- stealth: true,
53
- timeout_seconds: hasAutoCreds ? 120 : 300,
54
- });
55
- try {
56
- // Log in to Cronometer
57
- if (hasAutoCreds) {
58
- await autoLogin(kernel, browser.session_id, username, password, onStatus);
59
- }
60
- else {
61
- await manualLogin(kernel, browser);
62
- }
63
- // Execute quick-add
64
- onStatus?.("Adding quick entry...");
65
- const result = await kernel.browsers.playwright.execute(browser.session_id, { code: buildQuickAddCode(entry), timeout_sec: 60 });
66
- if (!result.success) {
67
- throw new Error(`Automation failed: ${result.error ?? "Unknown error"}`);
68
- }
69
- const data = result.result;
70
- if (!data.success) {
71
- throw new Error(`Quick add failed: ${data.error ?? "Unknown error"}`);
72
- }
73
- }
74
- finally {
75
- try {
76
- await kernel.browsers.deleteByID(browser.session_id);
77
- }
78
- catch {
79
- // Browser may already be cleaned up by Kernel
80
- }
81
- }
82
- }
83
- /**
84
- * Execute the weight scraping automation on Cronometer.
85
- * Creates a browser, logs in, reads weight data, then tears down.
86
- */
87
- async function getWeight(kernel, dates, onStatus) {
88
- const username = getCredential("cronometer-username");
89
- const password = getCredential("cronometer-password");
90
- const hasAutoCreds = !!(username && password);
91
- const browser = await kernel.browsers.create({
92
- headless: hasAutoCreds,
93
- stealth: true,
94
- timeout_seconds: hasAutoCreds ? 120 : 300,
95
- });
96
- try {
97
- if (hasAutoCreds) {
98
- await autoLogin(kernel, browser.session_id, username, password, onStatus);
99
- }
100
- else {
101
- await manualLogin(kernel, browser);
102
- }
103
- onStatus?.("Reading weight data...");
104
- const result = await kernel.browsers.playwright.execute(browser.session_id, { code: buildWeightCode(dates), timeout_sec: 60 });
105
- if (!result.success) {
106
- throw new Error(`Automation failed: ${result.error ?? "Unknown error"}`);
107
- }
108
- const data = result.result;
109
- if (!data.success) {
110
- throw new Error(`Weight read failed: ${data.error ?? "Unknown error"}`);
111
- }
112
- return data.entries ?? [];
113
- }
114
- finally {
115
- try {
116
- await kernel.browsers.deleteByID(browser.session_id);
117
- }
118
- catch {
119
- // Browser may already be cleaned up by Kernel
120
- }
121
- }
122
- }
123
- /**
124
- * Execute the diary nutrition scraping automation on Cronometer.
125
- * Creates a browser, logs in, reads nutrition data, then tears down.
126
- */
127
- async function getDiary(kernel, dates, onStatus, scrapeTargets) {
128
- const username = getCredential("cronometer-username");
129
- const password = getCredential("cronometer-password");
130
- const hasAutoCreds = !!(username && password);
131
- const browser = await kernel.browsers.create({
132
- headless: hasAutoCreds,
133
- stealth: true,
134
- timeout_seconds: hasAutoCreds ? 120 : 300,
135
- });
136
- try {
137
- if (hasAutoCreds) {
138
- await autoLogin(kernel, browser.session_id, username, password, onStatus);
139
- }
140
- else {
141
- await manualLogin(kernel, browser);
142
- }
143
- onStatus?.("Reading diary data...");
144
- const result = await kernel.browsers.playwright.execute(browser.session_id, { code: buildDiaryCode(dates, scrapeTargets), timeout_sec: 60 });
145
- if (!result.success) {
146
- throw new Error(`Automation failed: ${result.error ?? "Unknown error"}`);
147
- }
148
- const data = result.result;
149
- if (!data.success) {
150
- throw new Error(`Diary read failed: ${data.error ?? "Unknown error"}`);
151
- }
152
- return data.entries ?? [];
153
- }
154
- finally {
155
- try {
156
- await kernel.browsers.deleteByID(browser.session_id);
157
- }
158
- catch {
159
- // Browser may already be cleaned up by Kernel
160
- }
161
- }
162
- }
163
- /**
164
- * Execute the custom food creation automation on Cronometer.
165
- * Creates a browser, logs in, creates the food, optionally logs it, then tears down.
166
- */
167
- async function addCustomFood(kernel, entry, onStatus) {
168
- const username = getCredential("cronometer-username");
169
- const password = getCredential("cronometer-password");
170
- const hasAutoCreds = !!(username && password);
171
- const browser = await kernel.browsers.create({
172
- headless: hasAutoCreds,
173
- stealth: true,
174
- timeout_seconds: hasAutoCreds ? 120 : 300,
175
- });
176
- try {
177
- if (hasAutoCreds) {
178
- await autoLogin(kernel, browser.session_id, username, password, onStatus);
179
- }
180
- else {
181
- await manualLogin(kernel, browser);
182
- }
183
- onStatus?.("Creating custom food...");
184
- const result = await kernel.browsers.playwright.execute(browser.session_id, { code: buildAddCustomFoodCode(entry), timeout_sec: 120 });
185
- if (!result.success) {
186
- throw new Error(`Automation failed: ${result.error ?? "Unknown error"}`);
187
- }
188
- const data = result.result;
189
- if (!data.success) {
190
- throw new Error(`Custom food creation failed: ${data.error ?? "Unknown error"}`);
191
- }
192
- }
193
- finally {
194
- try {
195
- await kernel.browsers.deleteByID(browser.session_id);
196
- }
197
- catch {
198
- // Browser may already be cleaned up by Kernel
199
- }
200
- }
201
- }
202
- /**
203
- * Execute the food logging automation on Cronometer.
204
- * Creates a browser, logs in, searches for the food, logs it, then tears down.
205
- */
206
- async function logFood(kernel, entry, onStatus) {
207
- const username = getCredential("cronometer-username");
208
- const password = getCredential("cronometer-password");
209
- const hasAutoCreds = !!(username && password);
210
- const browser = await kernel.browsers.create({
211
- headless: hasAutoCreds,
212
- stealth: true,
213
- timeout_seconds: hasAutoCreds ? 120 : 300,
214
- });
215
- try {
216
- if (hasAutoCreds) {
217
- await autoLogin(kernel, browser.session_id, username, password, onStatus);
218
- }
219
- else {
220
- await manualLogin(kernel, browser);
221
- }
222
- onStatus?.("Logging food to diary...");
223
- const result = await kernel.browsers.playwright.execute(browser.session_id, { code: buildLogFoodCode(entry), timeout_sec: 60 });
224
- if (!result.success) {
225
- throw new Error(`Automation failed: ${result.error ?? "Unknown error"}`);
226
- }
227
- const data = result.result;
228
- if (!data.success) {
229
- throw new Error(`Food logging failed: ${data.error ?? "Unknown error"}`);
230
- }
231
- }
232
- finally {
233
- try {
234
- await kernel.browsers.deleteByID(browser.session_id);
235
- }
236
- catch {
237
- // Browser may already be cleaned up by Kernel
238
- }
239
- }
240
- }
241
- /**
242
- * Auto-login using stored Cronometer credentials.
243
- */
244
- async function autoLogin(kernel, sessionId, username, password, onStatus) {
245
- onStatus?.("Logging into Cronometer...");
246
- const result = await kernel.browsers.playwright.execute(sessionId, {
247
- code: buildAutoLoginCode(username, password),
248
- timeout_sec: 60,
249
- });
250
- const data = result.result;
251
- if (!result.success || !data.loggedIn) {
252
- const pageError = data.loginError?.toLowerCase() ?? "";
253
- const isRateLimited = pageError.includes("too many") ||
254
- pageError.includes("rate limit") ||
255
- pageError.includes("try again later") ||
256
- pageError.includes("temporarily");
257
- if (isRateLimited) {
258
- throw new Error(`Cronometer is rate-limiting login attempts. ${data.loginError}\n` +
259
- "Please wait a few minutes and try again.");
260
- }
261
- throw new Error(`Auto-login failed: ${data.error ?? data.loginError ?? "Login verification failed"}.\n` +
262
- "Your credentials may be incorrect. Run `crono login` to update them.");
263
- }
264
- }
265
- /**
266
- * Manual login: show a live browser view for the user to log in interactively.
267
- */
268
- async function manualLogin(kernel, browser) {
269
- p.log.warn("No stored Cronometer credentials found.");
270
- p.log.info("Tip: run `crono login` to save credentials for automatic login.");
271
- if (browser.browser_live_view_url) {
272
- p.note(browser.browser_live_view_url, "Browser Live View");
273
- }
274
- await kernel.browsers.playwright.execute(browser.session_id, {
275
- code: buildNavigateToLoginCode(),
276
- timeout_sec: 30,
277
- });
278
- p.log.info("Please log into Cronometer in the browser above.");
279
- const confirmation = await p.text({
280
- message: "Press Enter once you've logged in...",
281
- defaultValue: "",
282
- });
283
- if (p.isCancel(confirmation)) {
284
- throw new Error("Login cancelled by user.");
285
- }
286
- const result = await kernel.browsers.playwright.execute(browser.session_id, {
287
- code: buildLoginCheckCode(),
288
- timeout_sec: 30,
289
- });
290
- const data = result.result;
291
- if (!result.success || !data.loggedIn) {
292
- throw new Error("Login verification failed. Make sure you're fully logged in and try again.");
293
- }
294
- p.log.step("Logged in.");
295
- }
296
51
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/kernel/client.ts"],"names":[],"mappings":"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"}
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"}
@@ -0,0 +1,13 @@
1
+ export interface FoodDialogOptions {
2
+ foodNameVar?: string;
3
+ mealLabelVar?: string;
4
+ errorPrefix?: string;
5
+ itemNameVar?: string;
6
+ requireServingSize?: boolean;
7
+ servingCountVar?: string;
8
+ alwaysUpdateServingSize?: boolean;
9
+ updateServingSize?: boolean;
10
+ verifyDialogDismissed?: boolean;
11
+ }
12
+ export declare function buildFoodDialogCode(options?: FoodDialogOptions): string;
13
+ //# sourceMappingURL=food-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"food-dialog.d.ts","sourceRoot":"","sources":["../../src/kernel/food-dialog.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAqN3E"}