@robbeverhelst/do 1.283.0 → 1.285.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.
Files changed (2) hide show
  1. package/dist/do.js +198 -6
  2. package/package.json +1 -1
package/dist/do.js CHANGED
@@ -5822,6 +5822,7 @@ var journalImportItems = pgTable("journal_import_items", {
5822
5822
  body: text("body"),
5823
5823
  rating: doublePrecision("rating"),
5824
5824
  ratingQuestion: text("rating_question"),
5825
+ sleep: doublePrecision("sleep"),
5825
5826
  highlight: text("highlight"),
5826
5827
  milestoneCandidate: boolean("milestone_candidate").notNull().default(false),
5827
5828
  health: boolean("health").notNull().default(false),
@@ -22474,6 +22475,7 @@ var journalImportItemInputSchema = object({
22474
22475
  body: string2().trim().min(1).max(20000).nullish(),
22475
22476
  rating: number2().min(1).max(10).nullish(),
22476
22477
  ratingQuestion: string2().trim().min(1).max(80).nullish(),
22478
+ sleep: number2().min(0).max(24).nullish(),
22477
22479
  highlight: string2().trim().min(1).max(200).nullish(),
22478
22480
  milestoneCandidate: boolean3().default(false),
22479
22481
  health: boolean3().default(false),
@@ -22502,6 +22504,7 @@ var journalImportItemSchema = object({
22502
22504
  body: string2().nullable(),
22503
22505
  rating: number2().nullable(),
22504
22506
  ratingQuestion: string2().nullable(),
22507
+ sleep: number2().nullable().default(null),
22505
22508
  highlight: string2().nullable(),
22506
22509
  milestoneCandidate: boolean3(),
22507
22510
  health: boolean3(),
@@ -22526,6 +22529,7 @@ var journalImportOverviewSchema = object({
22526
22529
  ratings: number2().int(),
22527
22530
  unclearRatings: array(string2()),
22528
22531
  milestoneCandidates: number2().int(),
22532
+ sleep: number2().int().default(0),
22529
22533
  health: number2().int(),
22530
22534
  links: number2().int()
22531
22535
  }),
@@ -23548,7 +23552,8 @@ var foodWeekSchema = object({
23548
23552
  points: array(object({ day: civilDate, value: number2() })),
23549
23553
  trend: array(object({ day: civilDate, value: number2() })),
23550
23554
  latest: number2().nullable(),
23551
- perWeek: number2().nullable()
23555
+ perWeek: number2().nullable(),
23556
+ source: metricSourceSchema.nullable()
23552
23557
  }),
23553
23558
  numbers: object({
23554
23559
  completeDays: number2().int(),
@@ -25305,6 +25310,7 @@ var runQuestSchema = object({
25305
25310
  status: runQuestStatusSchema.default("active"),
25306
25311
  objective: text5.nullish(),
25307
25312
  hint: shortText.nullish(),
25313
+ reward: shortText.nullish(),
25308
25314
  place: shortText.nullish(),
25309
25315
  steps: array(object({
25310
25316
  text: shortText.pipe(string2().min(1)),
@@ -25318,7 +25324,8 @@ var runQuestSchema = object({
25318
25324
  }).strict();
25319
25325
  var runNextStepsSchema = object({
25320
25326
  items: array(shortText.pipe(string2().min(1))).max(3),
25321
- pinned: boolean3().default(false)
25327
+ pinned: boolean3().default(false),
25328
+ note: text5.nullish()
25322
25329
  }).strict();
25323
25330
  var runChoiceSchema = object({
25324
25331
  ref: ref.nullish(),
@@ -25336,7 +25343,7 @@ var runChoiceSchema = object({
25336
25343
  var runHomeSchema = object({
25337
25344
  ref: ref.nullish(),
25338
25345
  name,
25339
- role: _enum2(["home", "collector", "storage", "planned"]).default("home"),
25346
+ role: _enum2(["home", "collector", "storage", "planned", "later"]).default("home"),
25340
25347
  place: shortText.nullish(),
25341
25348
  upgrades: array(object({ name, done: boolean3().default(false) }).strict()).max(40).optional(),
25342
25349
  steward: shortText.nullish(),
@@ -26002,10 +26009,78 @@ var animalLogInputSchema = discriminatedUnion("kind", [
26002
26009
  occurredAt: occurredAtSchema
26003
26010
  }).strict()
26004
26011
  ]);
26012
+ var animalVetVisitSourceSchema = _enum2(["sticker", "photo", "said"]);
26013
+ var visitTextSchema = string2().trim().min(1).max(120);
26014
+ var visitCostSchema = object({
26015
+ amount: number2().positive().max(1e5),
26016
+ currency: string2().trim().length(3).default("EUR")
26017
+ }).strict();
26018
+ var animalVetVisitInputSchema = object({
26019
+ id: ulidSchema,
26020
+ at: exports_coerce.date().optional(),
26021
+ vetContactId: ulidSchema.optional(),
26022
+ clinician: visitTextSchema.optional(),
26023
+ reason: visitTextSchema.optional(),
26024
+ vaccine: object({ name: visitTextSchema, source: animalVetVisitSourceSchema.optional() }).strict().optional(),
26025
+ dewormer: visitTextSchema.optional(),
26026
+ weight: object({
26027
+ value: number2().positive().max(200000),
26028
+ unit: _enum2(["g", "kg"]).default("kg")
26029
+ }).strict().optional(),
26030
+ nextDates: array(object({
26031
+ id: ulidSchema,
26032
+ label: visitTextSchema,
26033
+ date: string2().regex(/^\d{4}-\d{2}-\d{2}$/, "expected YYYY-MM-DD")
26034
+ }).strict()).max(5).default([]),
26035
+ files: array(object({ id: ulidSchema, name: visitTextSchema.optional() }).strict()).max(5).default([]),
26036
+ cost: visitCostSchema.optional()
26037
+ }).strict();
26038
+ var animalVetVisitPatchSchema = object({
26039
+ vetContactId: ulidSchema.nullable().optional(),
26040
+ clinician: visitTextSchema.nullable().optional(),
26041
+ reason: visitTextSchema.nullable().optional(),
26042
+ vaccine: object({ name: visitTextSchema, source: animalVetVisitSourceSchema.optional() }).strict().nullable().optional(),
26043
+ dewormer: visitTextSchema.nullable().optional(),
26044
+ cost: visitCostSchema.nullable().optional()
26045
+ }).strict().refine((v) => Object.keys(v).length > 0, { message: "Change at least one field." });
26046
+ var animalVetVisitSchema = object({
26047
+ id: ulidSchema,
26048
+ animal: object({
26049
+ id: ulidSchema,
26050
+ title: string2(),
26051
+ speciesKey: string2().nullable(),
26052
+ speciesClass: animalClassSchema.nullable()
26053
+ }),
26054
+ at: exports_coerce.date(),
26055
+ vet: nodeRefSchema.nullable(),
26056
+ clinician: string2().nullable(),
26057
+ reason: string2().nullable(),
26058
+ vaccine: object({ name: string2(), source: animalVetVisitSourceSchema.nullable() }).nullable(),
26059
+ dewormer: string2().nullable(),
26060
+ weight: object({
26061
+ grams: number2(),
26062
+ deltaGrams: number2().nullable(),
26063
+ since: string2().nullable()
26064
+ }).nullable(),
26065
+ keyDates: array(object({ id: string2(), label: string2(), date: string2() })),
26066
+ files: array(object({ id: string2(), name: string2() })),
26067
+ cost: object({ amount: number2(), currency: string2() }).nullable(),
26068
+ byAgent: boolean3(),
26069
+ undone: boolean3()
26070
+ });
26005
26071
  var animalTimelineEntrySchema = object({
26006
26072
  id: string2(),
26007
26073
  at: exports_coerce.date(),
26008
- kind: _enum2(["weight", "length", "eggs", "note", "period_started", "period_ended", "key_date"]),
26074
+ kind: _enum2([
26075
+ "weight",
26076
+ "length",
26077
+ "eggs",
26078
+ "note",
26079
+ "vet_visit",
26080
+ "period_started",
26081
+ "period_ended",
26082
+ "key_date"
26083
+ ]),
26009
26084
  animalId: ulidSchema,
26010
26085
  animalTitle: string2(),
26011
26086
  value: number2().nullable(),
@@ -26057,7 +26132,8 @@ var animalHandoverTripSchema = object({
26057
26132
  houseNote: string2().nullable(),
26058
26133
  holidayMode: animalHolidayModeSchema,
26059
26134
  sharedUntil: string2().nullable(),
26060
- agentNote: string2().nullable()
26135
+ agentNote: string2().nullable(),
26136
+ calendar: string2().nullable()
26061
26137
  });
26062
26138
  var animalHandoverAnimalSchema = object({
26063
26139
  id: ulidSchema,
@@ -26074,6 +26150,7 @@ var animalHandoverAnimalSchema = object({
26074
26150
  var animalHandoverContactSchema = object({
26075
26151
  id: ulidSchema,
26076
26152
  title: string2(),
26153
+ kind: _enum2(["vet", "member"]),
26077
26154
  label: string2().nullable(),
26078
26155
  phone: string2().nullable()
26079
26156
  });
@@ -26088,6 +26165,7 @@ var animalHandoverSchema = object({
26088
26165
  contacts: array(animalHandoverContactSchema),
26089
26166
  supplies: array(animalHandoverSupplySchema),
26090
26167
  habits: array(animalHandoverHabitSchema),
26168
+ sensors: boolean3(),
26091
26169
  generatedAt: exports_coerce.date()
26092
26170
  });
26093
26171
  var animalHolidayModeInputSchema = animalHolidayModeSchema.partial().extend({ periodId: ulidSchema }).strict().refine((v) => Object.keys(v).length > 1, { message: "Turn at least one switch." });
@@ -28361,7 +28439,7 @@ function parseCapture2(input, now) {
28361
28439
 
28362
28440
  // src/meta.ts
28363
28441
  var CLI_NAME = "do";
28364
- var VERSION = "1.283.0";
28442
+ var VERSION = "1.285.0";
28365
28443
  var API_PREFIX = "/api/v1";
28366
28444
  var DEFAULT_API_URL = "http://localhost:3001";
28367
28445
 
@@ -29845,6 +29923,41 @@ var HEALTH = /\b(symptoms?|stomach|nausea|headaches?|migraine|doctor|GP|medicati
29845
29923
  var NOISE = /\b(PR monitor|GitHub daily|deploy(?:ment)? watch\w*|cron|heartbeat|sales prospects?)\b/i;
29846
29924
  var MILESTONE = /\b(first|went live|is live|win:|moved in|arrived|wedding|engaged)\b/i;
29847
29925
  var PR_REF = /\bPR\s*#\d+/gi;
29926
+ var SLEPT = /\bslept\s*~?\s*(\d{1,2})\s*h(?:\s*(\d{1,2}))?/i;
29927
+ var SLEEP_HOURS = /\bsleep\s*:?\s*~?\s*(\d{1,2}(?:\.\d+)?)\s*h\b/i;
29928
+ var atClock = (word) => [
29929
+ new RegExp(`\\b${word}\\b\\D{0,12}?(\\d{1,2})[:.h](\\d{2})`, "i"),
29930
+ new RegExp(`(\\d{1,2})[:.h](\\d{2})\\D{0,6}?\\b${word}\\b`, "i")
29931
+ ];
29932
+ var BED_AT = atClock("(?:bed|asleep|lights out)");
29933
+ var WOKE_AT = atClock("(?:woke(?: up)?|wake(?: up)?|awake|got up|up at)");
29934
+ function sleepOf(raw) {
29935
+ const lines = raw.map(plain);
29936
+ for (const line of lines) {
29937
+ const slept = SLEPT.exec(line);
29938
+ if (slept)
29939
+ return Number(slept[1]) + Number(slept[2] ?? 0) / 60;
29940
+ const hours = SLEEP_HOURS.exec(line);
29941
+ if (hours)
29942
+ return Number(hours[1]);
29943
+ }
29944
+ const clock = (patterns) => {
29945
+ for (const line of lines) {
29946
+ for (const re of patterns) {
29947
+ const m = re.exec(line);
29948
+ if (m)
29949
+ return Number(m[1]) * 60 + Number(m[2]);
29950
+ }
29951
+ }
29952
+ return null;
29953
+ };
29954
+ const bed = clock(BED_AT);
29955
+ const woke = clock(WOKE_AT);
29956
+ if (bed === null || woke === null)
29957
+ return null;
29958
+ const minutes = (woke - bed + 24 * 60) % (24 * 60);
29959
+ return minutes >= 120 && minutes <= 16 * 60 ? Math.round(minutes / 60 * 100) / 100 : null;
29960
+ }
29848
29961
  var TASK_DONE = /^\s*[-*]\s*\[x\]/i;
29849
29962
  function section(text, heading) {
29850
29963
  const lines = text.split(/\r?\n/);
@@ -29910,6 +30023,7 @@ function parseDailyNote(path, day, text) {
29910
30023
  }
29911
30024
  const milestoneLine = all.find((l) => MILESTONE.test(l) && !HEALTH.test(l) && !NOISE.test(l) && plain(l).length > 0);
29912
30025
  const highlight = milestoneLine ? firstSentence(plain(milestoneLine), 80) : null;
30026
+ const sleep = sleepOf(all);
29913
30027
  const prs = (text.match(PR_REF) ?? []).length;
29914
30028
  const tasks = all.filter((l) => TASK_DONE.test(l)).length;
29915
30029
  return {
@@ -29922,6 +30036,7 @@ function parseDailyNote(path, day, text) {
29922
30036
  body,
29923
30037
  rating,
29924
30038
  ratingQuestion,
30039
+ ...sleep !== null ? { sleep } : {},
29925
30040
  highlight,
29926
30041
  milestoneCandidate: Boolean(highlight),
29927
30042
  health,
@@ -33333,6 +33448,54 @@ var COMMAND_SPECS = [
33333
33448
  returns: "AnimalTimelineEntry",
33334
33449
  notes: 'POST /api/v1/animals/{id}/log (`animal_log`). `do animals log <hens> eggs 2`, `do animals log <dog> weight 37.8 --unit kg`, `do animals log <hen> note "eating again"`. Eggs are the day\'s count: logging again that day replaces it.'
33335
33450
  },
33451
+ {
33452
+ path: ["animals", "vet-visit"],
33453
+ summary: "Log a vet visit in one call: where, the vaccine, the dewormer, the weight, the next dates, the photos, the cost.",
33454
+ args: [{ name: "id", required: true, description: "Animal ULID." }],
33455
+ flags: [
33456
+ {
33457
+ name: "data",
33458
+ type: "string",
33459
+ description: "JSON: { vetContactId?, clinician?, reason?, vaccine?: { name, source? }, dewormer?, weight?: { value, unit? }, nextDates?: [{ label, date }], files?: [{ id, name? }], cost?: { amount, currency? }, at? }. The visit's and each date's ids are minted."
33460
+ }
33461
+ ],
33462
+ scopes: ["animals:write"],
33463
+ returns: "AnimalVetVisit",
33464
+ notes: 'POST /api/v1/animals/{id}/vet-visits (`animal_vet_visit`, mockup 03). The visit is the receipt: post it with `receipt: { nodeId: <visit id> }`. `do animals vet-visit <dog> --data \'{"reason":"booster","vaccine":{"name":"DHPPi + L4","source":"sticker"},"weight":{"value":37.8}}\'`.'
33465
+ },
33466
+ {
33467
+ path: ["animals", "vet-visit-get"],
33468
+ summary: "Read a vet visit as its receipt reads.",
33469
+ args: [{ name: "visitId", required: true, description: "Vet visit ULID." }],
33470
+ flags: [],
33471
+ scopes: ["animals:read"],
33472
+ returns: "AnimalVetVisit",
33473
+ notes: "GET /api/v1/animals/vet-visits/{visitId}."
33474
+ },
33475
+ {
33476
+ path: ["animals", "vet-visit-edit"],
33477
+ summary: "Put a vet visit's fields right (the receipt's Edit).",
33478
+ args: [{ name: "visitId", required: true, description: "Vet visit ULID." }],
33479
+ flags: [
33480
+ {
33481
+ name: "data",
33482
+ type: "string",
33483
+ description: "JSON: any of vetContactId, clinician, reason, vaccine, dewormer, cost (null clears one)."
33484
+ }
33485
+ ],
33486
+ scopes: ["animals:write"],
33487
+ returns: "AnimalVetVisit",
33488
+ notes: "PATCH /api/v1/animals/vet-visits/{visitId}. The newest version wins."
33489
+ },
33490
+ {
33491
+ path: ["animals", "vet-visit-undo"],
33492
+ summary: "Take a vet visit back (the receipt's Undo).",
33493
+ args: [{ name: "visitId", required: true, description: "Vet visit ULID." }],
33494
+ flags: [],
33495
+ scopes: ["animals:write"],
33496
+ returns: "AnimalVetVisit",
33497
+ notes: "POST /api/v1/animals/vet-visits/{visitId}/undo. The visit, its weight, its key dates and the filed photos all go back."
33498
+ },
33336
33499
  {
33337
33500
  path: ["runs", "change"],
33338
33501
  summary: "Apply a chat update to a run: its changes, with a receipt and Undo.",
@@ -38293,6 +38456,35 @@ var HANDLERS = {
38293
38456
  const body = parseInput(animalLogInputSchema, { ...fact, ...at ? { occurredAt: at } : {} });
38294
38457
  return { data: await requireClient().post(`/animals/${id}/log`, body), render: renderRecord };
38295
38458
  },
38459
+ "animals vet-visit": async ({ args, flags, requireClient }) => {
38460
+ const id = requireArg(args, 0, "animal id");
38461
+ const raw = readDataFlag(flags);
38462
+ const body = parseInput(animalVetVisitInputSchema, {
38463
+ id: ulid3(),
38464
+ ...raw,
38465
+ nextDates: (raw.nextDates ?? []).map((d) => ({ id: ulid3(), ...d }))
38466
+ });
38467
+ return {
38468
+ data: await requireClient().post(`/animals/${id}/vet-visits`, body),
38469
+ render: renderRecord
38470
+ };
38471
+ },
38472
+ "animals vet-visit-get": async ({ args, requireClient }) => ({
38473
+ data: await requireClient().get(`/animals/vet-visits/${requireArg(args, 0, "visit id")}`),
38474
+ render: renderRecord
38475
+ }),
38476
+ "animals vet-visit-edit": async ({ args, flags, requireClient }) => {
38477
+ const visitId = requireArg(args, 0, "visit id");
38478
+ const body = parseInput(animalVetVisitPatchSchema, readDataFlag(flags));
38479
+ return {
38480
+ data: await requireClient().patch(`/animals/vet-visits/${visitId}`, body),
38481
+ render: renderRecord
38482
+ };
38483
+ },
38484
+ "animals vet-visit-undo": async ({ args, requireClient }) => ({
38485
+ data: await requireClient().post(`/animals/vet-visits/${requireArg(args, 0, "visit id")}/undo`, {}),
38486
+ render: renderRecord
38487
+ }),
38296
38488
  "runs change": async ({ args, flags, requireClient }) => {
38297
38489
  const id = requireArg(args, 0, "run id");
38298
38490
  const body = { ...readDataFlag(flags) };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robbeverhelst/do",
3
- "version": "1.283.0",
3
+ "version": "1.285.0",
4
4
  "private": false,
5
5
  "description": "do — the agent-drivable CLI over the public /api/v1 surface",
6
6
  "homepage": "https://github.com/robbeverhelst/do/tree/main/apps/cli",