@robbeverhelst/do 1.297.0 → 1.298.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 +614 -27
  2. package/package.json +1 -1
package/dist/do.js CHANGED
@@ -4516,6 +4516,21 @@ var sensorLinks = pgTable("sensor_links", {
4516
4516
  index("sensor_links_node_idx").on(t.nodeId)
4517
4517
  ]);
4518
4518
 
4519
+ // ../../packages/schema/src/db/tap-tags.ts
4520
+ var tapTagKind = pgEnum("tap_tag_kind", ["habit", "routine"]);
4521
+ var tapTags = pgTable("tap_tags", {
4522
+ id: text("id").primaryKey(),
4523
+ tenantId: text("tenant_id").notNull().references(() => tenants.id),
4524
+ label: text("label").notNull(),
4525
+ kind: tapTagKind("kind").notNull(),
4526
+ targetId: text("target_id").notNull().references(() => nodes.id),
4527
+ createdBy: text("created_by").references(() => users.id, { onDelete: "set null" }),
4528
+ lastTappedAt: timestamp("last_tapped_at", { withTimezone: true }),
4529
+ lastTappedBy: text("last_tapped_by").references(() => users.id, { onDelete: "set null" }),
4530
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
4531
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
4532
+ }, (t) => [index("tap_tags_tenant_idx").on(t.tenantId), index("tap_tags_target_idx").on(t.targetId)]);
4533
+
4519
4534
  // ../../packages/schema/src/db/planning-rules.ts
4520
4535
  var planningRuleKind = pgEnum("planning_rule_kind", [
4521
4536
  "fixed_time",
@@ -5047,6 +5062,38 @@ var contactCircles = pgTable("contact_circles", {
5047
5062
  primaryKey({ columns: [t.contactId, t.circleId] }),
5048
5063
  index("contact_circles_circle_idx").on(t.circleId)
5049
5064
  ]);
5065
+ var personProposalKind = pgEnum("person_proposal_kind", [
5066
+ "birth",
5067
+ "move",
5068
+ "new_job",
5069
+ "wedding",
5070
+ "engagement",
5071
+ "death",
5072
+ "other"
5073
+ ]);
5074
+ var personProposalStatus = pgEnum("person_proposal_status", [
5075
+ "pending",
5076
+ "accepted",
5077
+ "skipped"
5078
+ ]);
5079
+ var personProposals = pgTable("person_proposals", {
5080
+ id: text("id").primaryKey(),
5081
+ tenantId: text("tenant_id").notNull().references(() => tenants.id),
5082
+ userId: text("user_id").notNull().references(() => users.id),
5083
+ contactId: text("contact_id").notNull().references(() => contacts.id, { onDelete: "cascade" }),
5084
+ kind: personProposalKind("kind").notNull().default("other"),
5085
+ title: text("title").notNull(),
5086
+ source: text("source").notNull(),
5087
+ heardAt: timestamp("heard_at", { withTimezone: true }).notNull(),
5088
+ items: jsonb("items").$type().notNull(),
5089
+ status: personProposalStatus("status").notNull().default("pending"),
5090
+ decidedAt: timestamp("decided_at", { withTimezone: true }),
5091
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5092
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5093
+ }, (t) => [
5094
+ uniqueIndex("person_proposals_source_uniq").on(t.tenantId, t.userId, t.source),
5095
+ index("person_proposals_user_status_idx").on(t.tenantId, t.userId, t.status)
5096
+ ]);
5050
5097
 
5051
5098
  // ../../packages/schema/src/db/files.ts
5052
5099
  var bytea = customType({
@@ -5096,6 +5143,7 @@ var households = pgTable("households", {
5096
5143
  address: jsonb("address").$type(),
5097
5144
  language: text("language").notNull().default("nl"),
5098
5145
  group: boolean("group").notNull().default(false),
5146
+ addressConfirmedAt: timestamp("address_confirmed_at", { withTimezone: true }),
5099
5147
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5100
5148
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5101
5149
  }, (t) => [index("households_tenant_idx").on(t.tenantId)]);
@@ -5109,6 +5157,9 @@ var guestLists = pgTable("guest_lists", {
5109
5157
  rsvpKeyDateId: text("rsvp_key_date_id").references(() => keyDates.id, {
5110
5158
  onDelete: "set null"
5111
5159
  }),
5160
+ finalInfoKeyDateId: text("final_info_key_date_id").references(() => keyDates.id, {
5161
+ onDelete: "set null"
5162
+ }),
5112
5163
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5113
5164
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
5114
5165
  }, (t) => [uniqueIndex("guest_lists_project_uniq").on(t.tenantId, t.projectId)]);
@@ -5162,12 +5213,15 @@ var guests = pgTable("guests", {
5162
5213
  uniqueIndex("guests_list_contact_uniq").on(t.guestListId, t.contactId),
5163
5214
  index("guests_contact_idx").on(t.contactId)
5164
5215
  ]);
5216
+ var rsvpLinkMode = pgEnum("rsvp_link_mode", ["address", "full"]);
5165
5217
  var rsvpLinks = pgTable("rsvp_links", {
5166
5218
  id: text("id").primaryKey(),
5167
5219
  tenantId: text("tenant_id").notNull().references(() => tenants.id),
5168
5220
  guestListId: text("guest_list_id").notNull().references(() => guestLists.id, { onDelete: "cascade" }),
5169
5221
  householdId: text("household_id").notNull().references(() => households.id),
5170
5222
  tokenHash: text("token_hash").notNull().unique(),
5223
+ mode: rsvpLinkMode("mode").notNull().default("full"),
5224
+ tokenSealed: text("token_sealed"),
5171
5225
  expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
5172
5226
  revokedAt: timestamp("revoked_at", { withTimezone: true }),
5173
5227
  lastUsedAt: timestamp("last_used_at", { withTimezone: true }),
@@ -20635,7 +20689,8 @@ var habitTodayItemSchema = object({
20635
20689
  source: habitEntrySourceSchema,
20636
20690
  by: string2().optional(),
20637
20691
  at: exports_coerce.date()
20638
- }).nullable().default(null)
20692
+ }).nullable().default(null),
20693
+ private: boolean3().default(false)
20639
20694
  });
20640
20695
  var habitTodayRoutineSchema = object({
20641
20696
  routineId: ulidSchema,
@@ -22055,6 +22110,29 @@ var animalLostCardStateSchema = object({
22055
22110
  photos: array(animalLostCardPhotoSchema),
22056
22111
  chipOnFile: boolean3()
22057
22112
  });
22113
+ var animalAcquisitionInputSchema = object({
22114
+ pickUpOn: keyDateDaySchema.nullish(),
22115
+ quarantine: boolean3().optional(),
22116
+ extraSteps: array(string2().trim().min(1).max(200)).max(10).optional()
22117
+ }).strict();
22118
+ var animalAcquisitionStepSchema = object({
22119
+ id: ulidSchema,
22120
+ title: string2(),
22121
+ done: boolean3(),
22122
+ quarantine: boolean3()
22123
+ });
22124
+ var animalAcquisitionSchema = object({
22125
+ taskId: ulidSchema,
22126
+ title: string2(),
22127
+ pickUpOn: string2().nullable(),
22128
+ arrived: boolean3(),
22129
+ steps: array(animalAcquisitionStepSchema),
22130
+ blockers: array(string2())
22131
+ });
22132
+ var animalArrivedInputSchema = object({
22133
+ on: keyDateDaySchema.optional(),
22134
+ quarantineMonths: number2().int().min(0).max(12).optional()
22135
+ }).strict();
22058
22136
 
22059
22137
  // ../../packages/schema/src/contracts/sensors.ts
22060
22138
  var sensorProviderValues = ["home_assistant", "unifi"];
@@ -22927,12 +23005,15 @@ var healthProfileSchema = createSelectSchema(healthProfiles, {
22927
23005
  notes: string2().nullable().default(null),
22928
23006
  sex: string2().nullable().default(null)
22929
23007
  });
23008
+ var HEALTH_CONSENT_VERSION = "2026-10-18";
22930
23009
  var healthConsentStateSchema = object({
22931
23010
  granted: boolean3(),
22932
23011
  version: string2().nullable(),
22933
- grantedAt: exports_coerce.date().nullable()
23012
+ grantedAt: exports_coerce.date().nullable(),
23013
+ currentVersion: string2().default(HEALTH_CONSENT_VERSION),
23014
+ renewalNeeded: boolean3().default(false),
23015
+ aiProvider: string2().nullable().default(null)
22934
23016
  });
22935
- var HEALTH_CONSENT_VERSION = "2026-10-18";
22936
23017
  var subject = { subjectNodeId: ulidSchema.nullish() };
22937
23018
  var createHealthConditionInputSchema = object({
22938
23019
  id: ulidSchema.optional(),
@@ -23799,6 +23880,60 @@ var journalWeekSchema = object({
23799
23880
  usual: number2().nullable(),
23800
23881
  numbers: journalWeekNumbersSchema
23801
23882
  });
23883
+ var journalMonthKeySchema = string2().regex(/^\d{4}-(0[1-9]|1[0-2])$/, "must be a month (YYYY-MM)");
23884
+ var journalYearKeySchema = string2().regex(/^\d{4}$/, "must be a year (YYYY)");
23885
+ var journalPeriodKeySchema = union([
23886
+ journalWeekKeySchema,
23887
+ journalMonthKeySchema,
23888
+ journalYearKeySchema
23889
+ ]);
23890
+ function journalPeriodKind(key) {
23891
+ if (journalWeekKeySchema.safeParse(key).success)
23892
+ return "week";
23893
+ if (journalMonthKeySchema.safeParse(key).success)
23894
+ return "month";
23895
+ if (journalYearKeySchema.safeParse(key).success)
23896
+ return "year";
23897
+ return null;
23898
+ }
23899
+ var journalPeriodMilestoneSchema = object({
23900
+ id: string2(),
23901
+ title: string2(),
23902
+ kind: journalMilestoneKindSchema,
23903
+ happenedOn: journalDateSchema,
23904
+ precision: journalMilestonePrecisionSchema,
23905
+ planned: boolean3()
23906
+ });
23907
+ var journalMonthSchema = object({
23908
+ month: journalMonthKeySchema,
23909
+ from: journalDateSchema,
23910
+ to: journalDateSchema,
23911
+ timezone: string2().min(1),
23912
+ recap: journalRecapSchema.nullable(),
23913
+ days: array(journalDayListItemSchema),
23914
+ usual: number2().nullable(),
23915
+ numbers: journalWeekNumbersSchema,
23916
+ milestones: array(journalPeriodMilestoneSchema)
23917
+ });
23918
+ var journalYearMonthSchema = object({
23919
+ month: journalMonthKeySchema,
23920
+ average: number2().nullable(),
23921
+ rated: number2().int().nonnegative(),
23922
+ kept: number2().int().nonnegative(),
23923
+ best: journalDateSchema.nullable()
23924
+ });
23925
+ var journalYearSchema = object({
23926
+ year: journalYearKeySchema,
23927
+ from: journalDateSchema,
23928
+ to: journalDateSchema,
23929
+ timezone: string2().min(1),
23930
+ recap: journalRecapSchema.nullable(),
23931
+ days: array(journalDayListItemSchema),
23932
+ months: array(journalYearMonthSchema),
23933
+ usual: number2().nullable(),
23934
+ numbers: journalWeekNumbersSchema,
23935
+ milestones: array(journalPeriodMilestoneSchema)
23936
+ });
23802
23937
 
23803
23938
  // ../../packages/schema/src/contracts/modules.ts
23804
23939
  var MODULE_KEYS = [
@@ -25258,6 +25393,43 @@ var personNoteUndoResultSchema = object({
25258
25393
  id: ulidSchema,
25259
25394
  removed: number2().int()
25260
25395
  });
25396
+ var personProposalKindSchema = _enum2(personProposalKind.enumValues);
25397
+ var personProposalStatusSchema = _enum2(personProposalStatus.enumValues);
25398
+ var mailSourceSchema = string2().trim().regex(/^gmail:[A-Za-z0-9_-]{1,100}$/, "a mail source is gmail:<message id>");
25399
+ var createPersonProposalInputSchema = object({
25400
+ id: ulidSchema,
25401
+ contactId: ulidSchema.optional(),
25402
+ person: string2().trim().min(1).max(120).optional(),
25403
+ kind: personProposalKindSchema.default("other"),
25404
+ title: string2().trim().min(1).max(200),
25405
+ source: mailSourceSchema,
25406
+ heardAt: exports_coerce.date(),
25407
+ items: array(personNoteItemSchema).min(1).max(10).optional()
25408
+ }).strict().refine((n) => Boolean(n.contactId) !== Boolean(n.person), {
25409
+ message: "name the person by contactId or by person, not both",
25410
+ path: ["contactId"]
25411
+ });
25412
+ var personProposalSchema = object({
25413
+ id: ulidSchema,
25414
+ contactId: ulidSchema,
25415
+ contactTitle: string2(),
25416
+ kind: personProposalKindSchema,
25417
+ title: string2(),
25418
+ source: string2(),
25419
+ heardAt: exports_coerce.date(),
25420
+ items: array(personNoteItemSchema),
25421
+ status: personProposalStatusSchema,
25422
+ decidedAt: exports_coerce.date().nullable(),
25423
+ createdAt: exports_coerce.date()
25424
+ });
25425
+ var personProposalsQuerySchema = object({
25426
+ status: personProposalStatusSchema.optional(),
25427
+ source: mailSourceSchema.optional()
25428
+ });
25429
+ var personProposalAcceptResultSchema = object({
25430
+ proposal: personProposalSchema,
25431
+ receipt: personNoteReceiptSchema
25432
+ });
25261
25433
  var personFindQuerySchema = object({
25262
25434
  q: string2().trim().min(1).max(120),
25263
25435
  limit: exports_coerce.number().int().min(1).max(20).optional()
@@ -25360,6 +25532,7 @@ var peopleOverviewSchema = object({
25360
25532
  phone: string2().nullable().default(null)
25361
25533
  })),
25362
25534
  heardLately: array(contactMomentViewSchema),
25535
+ proposals: array(personProposalSchema).default([]),
25363
25536
  lent: array(object({
25364
25537
  itemId: ulidSchema,
25365
25538
  title: string2(),
@@ -26094,7 +26267,8 @@ var warrantyFieldsSchema = object({
26094
26267
  amount: amount4,
26095
26268
  purchaseDate: keyDateDaySchema,
26096
26269
  warrantyMonths: number2().int().min(0).max(600),
26097
- serial: text4
26270
+ serial: text4,
26271
+ room: text4
26098
26272
  }).partial().strict();
26099
26273
  var payToIban = string2().transform(compactIban).pipe(string2().regex(/^[A-Z]{2}\d{2}[A-Z0-9]{8,30}$/, "expected an IBAN"));
26100
26274
  var payRef = string2().trim().min(1).max(140);
@@ -26351,6 +26525,44 @@ var incidentsQuerySchema = object({
26351
26525
  policyId: ulidSchema.optional()
26352
26526
  });
26353
26527
 
26528
+ // ../../packages/schema/src/contracts/tap-tags.ts
26529
+ var tapTagKindSchema = _enum2(tapTagKind.enumValues);
26530
+ var tapTagViewSchema = object({
26531
+ id: string2(),
26532
+ label: string2(),
26533
+ kind: tapTagKindSchema,
26534
+ targetId: string2(),
26535
+ targetTitle: string2(),
26536
+ path: string2(),
26537
+ lastTappedAt: exports_coerce.date().nullable(),
26538
+ createdAt: exports_coerce.date()
26539
+ });
26540
+ var labelSchema = string2().trim().min(1).max(80);
26541
+ var createTapTagInputSchema = object({
26542
+ id: ulidSchema,
26543
+ label: labelSchema,
26544
+ kind: tapTagKindSchema,
26545
+ targetId: string2().min(1)
26546
+ }).strict();
26547
+ var updateTapTagInputSchema = object({
26548
+ label: labelSchema.optional(),
26549
+ kind: tapTagKindSchema.optional(),
26550
+ targetId: string2().min(1).optional()
26551
+ }).strict().refine((v) => v.kind === undefined === (v.targetId === undefined), {
26552
+ message: "kind and targetId are changed together",
26553
+ path: ["targetId"]
26554
+ }).refine((v) => Object.keys(v).length > 0, { message: "nothing to change" });
26555
+ var tapUndoSchema = discriminatedUnion("kind", [
26556
+ object({ kind: literal("habit_entry"), habitId: string2(), entryId: string2() }),
26557
+ object({ kind: literal("routine_run"), runId: string2(), stepRunIds: array(string2()) })
26558
+ ]);
26559
+ var tapResultSchema = object({
26560
+ tag: tapTagViewSchema,
26561
+ outcome: _enum2(["done", "already"]),
26562
+ line: string2(),
26563
+ undo: tapUndoSchema.nullable()
26564
+ });
26565
+
26354
26566
  // ../../packages/schema/src/contracts/planning-rules.ts
26355
26567
  var PLANNING_RULE_KINDS = planningRuleKind.enumValues;
26356
26568
  var planningRuleKindSchema = _enum2(PLANNING_RULE_KINDS);
@@ -27237,6 +27449,7 @@ var householdAddressSchema = object({
27237
27449
  var householdRowSchema = createSelectSchema(households, {
27238
27450
  address: householdAddressSchema.nullable(),
27239
27451
  group: boolean3().default(false),
27452
+ addressConfirmedAt: exports_coerce.date().nullable(),
27240
27453
  createdAt: exports_coerce.date(),
27241
27454
  updatedAt: exports_coerce.date()
27242
27455
  });
@@ -27264,6 +27477,7 @@ var guestListSchema = createSelectSchema(guestLists, {
27264
27477
  var guestListViewSchema = guestListSchema.extend({
27265
27478
  projectTitle: string2(),
27266
27479
  rsvpBy: keyDateDaySchema.nullable(),
27480
+ finalInfoFrom: keyDateDaySchema.nullable().default(null),
27267
27481
  projectDay: keyDateDaySchema.nullable().default(null)
27268
27482
  });
27269
27483
  var createGuestListInputSchema = object({
@@ -27272,7 +27486,8 @@ var createGuestListInputSchema = object({
27272
27486
  tiers: array(guestTierSchema).min(1).max(6).optional(),
27273
27487
  caps: capsSchema.optional(),
27274
27488
  sides: array(sideSchema).max(4).optional(),
27275
- rsvpBy: keyDateDaySchema.nullish()
27489
+ rsvpBy: keyDateDaySchema.nullish(),
27490
+ finalInfoFrom: keyDateDaySchema.nullish()
27276
27491
  }).strict();
27277
27492
  var updateGuestListInputSchema = createGuestListInputSchema.omit({ id: true, projectId: true }).partial().strict();
27278
27493
  var guestListsQuerySchema = object({ projectId: ulidSchema.optional() });
@@ -27344,6 +27559,7 @@ var guestListOverviewSchema = object({
27344
27559
  householdId: ulidSchema.nullable(),
27345
27560
  title: string2(),
27346
27561
  address: householdAddressSchema.nullable(),
27562
+ addressConfirmedAt: exports_coerce.date().nullable(),
27347
27563
  language: rsvpLanguageSchema,
27348
27564
  group: boolean3().default(false),
27349
27565
  guests: array(guestViewSchema)
@@ -27369,16 +27585,20 @@ var guestListOverviewSchema = object({
27369
27585
  })
27370
27586
  });
27371
27587
  var RSVP_TOKEN_RE = /^rsvp_[A-Za-z0-9_-]{43}$/;
27588
+ var RSVP_LINK_MODES = ["address", "full"];
27589
+ var rsvpLinkModeSchema = _enum2(RSVP_LINK_MODES);
27372
27590
  var rsvpLinkSchema = object({
27373
27591
  id: ulidSchema,
27374
27592
  guestListId: ulidSchema,
27375
27593
  householdId: ulidSchema,
27376
27594
  householdTitle: string2(),
27595
+ mode: rsvpLinkModeSchema,
27377
27596
  expiresAt: exports_coerce.date(),
27378
27597
  revokedAt: exports_coerce.date().nullable(),
27379
27598
  lastUsedAt: exports_coerce.date().nullable(),
27380
27599
  createdAt: exports_coerce.date(),
27381
- live: boolean3()
27600
+ live: boolean3(),
27601
+ revealable: boolean3()
27382
27602
  });
27383
27603
  var mintedRsvpLinkSchema = rsvpLinkSchema.extend({
27384
27604
  token: string2().regex(RSVP_TOKEN_RE),
@@ -27387,6 +27607,7 @@ var mintedRsvpLinkSchema = rsvpLinkSchema.extend({
27387
27607
  var createRsvpLinksInputSchema = object({
27388
27608
  guestListId: ulidSchema,
27389
27609
  householdIds: array(ulidSchema).min(1).max(500).optional(),
27610
+ mode: rsvpLinkModeSchema.optional(),
27390
27611
  expiresAt: exports_coerce.date().optional()
27391
27612
  }).strict();
27392
27613
  var rsvpLinksQuerySchema = object({ guestListId: ulidSchema });
@@ -27398,14 +27619,29 @@ var publicRsvpGuestSchema = object({
27398
27619
  rsvp: answersSchema,
27399
27620
  diet: string2().nullable(),
27400
27621
  plusOne: boolean3(),
27401
- plusOneName: string2().nullable()
27622
+ plusOneName: string2().nullable(),
27623
+ table: string2().nullable().default(null)
27624
+ }).strict();
27625
+ var publicRsvpEventSchema = object({
27626
+ key: guestTierSchema,
27627
+ name: object({ nl: string2().optional(), pt: string2().optional() }),
27628
+ startsAt: exports_coerce.date().nullable(),
27629
+ endsAt: exports_coerce.date().nullable(),
27630
+ placeName: string2().nullable(),
27631
+ address: string2().nullable(),
27632
+ mapUrl: string2().nullable(),
27633
+ dressCode: object({ nl: string2().optional(), pt: string2().optional() }).nullable(),
27634
+ note: object({ nl: string2().optional(), pt: string2().optional() }).nullable()
27402
27635
  }).strict();
27403
27636
  var publicRsvpViewSchema = object({
27637
+ mode: rsvpLinkModeSchema,
27404
27638
  language: rsvpLanguageSchema,
27405
27639
  event: string2(),
27406
27640
  household: string2(),
27407
27641
  rsvpBy: keyDateDaySchema.nullable(),
27642
+ finalInfoFrom: keyDateDaySchema.nullable().default(null),
27408
27643
  tiers: array(guestTierSchema),
27644
+ events: array(publicRsvpEventSchema).default([]),
27409
27645
  guests: array(publicRsvpGuestSchema),
27410
27646
  address: householdAddressSchema.nullable(),
27411
27647
  answeredAt: exports_coerce.date().nullable()
@@ -27417,9 +27653,12 @@ var submitRsvpInputSchema = object({
27417
27653
  diet: string2().trim().max(200).nullish(),
27418
27654
  plusOneName: string2().trim().max(120).nullish(),
27419
27655
  email: string2().trim().email().max(254).nullish()
27420
- }).strict()).min(1).max(30),
27421
- address: householdAddressSchema.nullish()
27422
- }).strict();
27656
+ }).strict()).max(30).default([]),
27657
+ address: householdAddressSchema.nullish(),
27658
+ language: rsvpLanguageSchema.optional()
27659
+ }).strict().refine((i) => i.guests.length > 0 || !!i.address || !!i.language, {
27660
+ message: "nothing to send: answers, an address or a language"
27661
+ });
27423
27662
  var eventTextSchema = (max) => object({
27424
27663
  nl: string2().trim().min(1).max(max).optional(),
27425
27664
  pt: string2().trim().min(1).max(max).optional()
@@ -27829,6 +28068,52 @@ var googleContactsImportResultSchema = object({
27829
28068
  missing: array(string2())
27830
28069
  });
27831
28070
 
28071
+ // ../../packages/schema/src/contracts/github.ts
28072
+ var GITHUB_RESOURCES = ["commits", "pull_requests", "issues"];
28073
+ var githubResourceSchema = _enum2(GITHUB_RESOURCES);
28074
+ var githubBase = {
28075
+ repo: string2().min(1),
28076
+ url: string2().min(1)
28077
+ };
28078
+ var githubCommitValueSchema = object({
28079
+ ...githubBase,
28080
+ sha: string2().min(1),
28081
+ message: string2().default(""),
28082
+ by: _enum2(["human", "agent"]).optional(),
28083
+ agent: string2().nullish()
28084
+ }).strict();
28085
+ var githubPullRequestValueSchema = object({
28086
+ ...githubBase,
28087
+ number: number2().int().positive(),
28088
+ title: string2().default(""),
28089
+ state: string2().min(1),
28090
+ merged: boolean3().default(false)
28091
+ }).strict();
28092
+ var githubIssueValueSchema = object({
28093
+ ...githubBase,
28094
+ number: number2().int().positive(),
28095
+ title: string2().default(""),
28096
+ state: string2().min(1)
28097
+ }).strict();
28098
+ var githubCommitsQuerySchema = object({
28099
+ days: exports_coerce.number().int().refine((d) => d === 7 || d === 30, "7 or 30").default(7)
28100
+ });
28101
+ var githubCommitsDaySchema = object({
28102
+ day: string2(),
28103
+ byYou: number2().int(),
28104
+ byAgents: number2().int()
28105
+ });
28106
+ var githubCommitsSchema = object({
28107
+ days: number2().int(),
28108
+ from: string2(),
28109
+ to: string2(),
28110
+ byYou: number2().int(),
28111
+ byAgents: number2().int(),
28112
+ unsorted: number2().int(),
28113
+ agents: array(object({ name: string2(), count: number2().int() })),
28114
+ perDay: array(githubCommitsDaySchema)
28115
+ });
28116
+
27832
28117
  // ../../packages/schema/src/contracts/calendar.ts
27833
28118
  var calendarEventLinkSchema = createSelectSchema(calendarEventLinks, {
27834
28119
  createdAt: exports_coerce.date(),
@@ -29421,7 +29706,7 @@ function parseCapture2(input, now) {
29421
29706
 
29422
29707
  // src/meta.ts
29423
29708
  var CLI_NAME = "do";
29424
- var VERSION = "1.297.0";
29709
+ var VERSION = "1.298.0";
29425
29710
  var API_PREFIX = "/api/v1";
29426
29711
  var DEFAULT_API_URL = "http://localhost:3001";
29427
29712
 
@@ -30326,6 +30611,22 @@ var ENTITIES = [
30326
30611
  canDelete: true
30327
30612
  }
30328
30613
  },
30614
+ {
30615
+ name: "tap-tags",
30616
+ path: "/tap-tags",
30617
+ readScope: "habits:read",
30618
+ returns: "TapTagView",
30619
+ canGet: true,
30620
+ listFlags: [],
30621
+ write: {
30622
+ scope: "habits:write",
30623
+ createSchema: createTapTagInputSchema,
30624
+ createInput: "CreateTapTagInput",
30625
+ updateSchema: updateTapTagInputSchema,
30626
+ updateInput: "UpdateTapTagInput",
30627
+ canDelete: true
30628
+ }
30629
+ },
30329
30630
  {
30330
30631
  name: "animals",
30331
30632
  path: "/animals",
@@ -30584,7 +30885,8 @@ var HEALTH_COMMAND_SPECS = [
30584
30885
  args: [],
30585
30886
  flags: [],
30586
30887
  scopes: READ,
30587
- returns: "HealthConsentState"
30888
+ returns: "HealthConsentState",
30889
+ notes: "`granted` is on at today's consent text (`currentVersion`); `renewalNeeded` means you agreed to an older text, so writes wait until you agree again in do. `aiProvider` names who processes what the agent reads (null when this deployment names none)."
30588
30890
  },
30589
30891
  {
30590
30892
  path: ["health", "profile"],
@@ -31354,10 +31656,34 @@ var COMMAND_SPECS = [
31354
31656
  returns: "JournalWeek",
31355
31657
  notes: "GET /api/v1/journal/weeks/{week} \u2014 your own week only. `recap` is null until one was written. journal:read is a sensitive scope."
31356
31658
  },
31659
+ {
31660
+ path: ["journal", "month"],
31661
+ summary: "One month of the Journal: its recap, its days, the usual rating, the numbers from Progress and the milestones that happened in it.",
31662
+ args: [{ name: "month", required: true, description: "The month, e.g. 2026-10." }],
31663
+ flags: [],
31664
+ scopes: ["journal:read"],
31665
+ returns: "JournalMonth",
31666
+ notes: "GET /api/v1/journal/months/{month} \u2014 your own month only. `recap` is null until one was written; `usual` is the mean rating over the three months before. journal:read is a sensitive scope."
31667
+ },
31668
+ {
31669
+ path: ["journal", "year"],
31670
+ summary: "One year of the Journal: its recap, its days (the rating pixels), each month's average and best day, the usual, the numbers and the year's milestones.",
31671
+ args: [{ name: "year", required: true, description: "The year, e.g. 2026." }],
31672
+ flags: [],
31673
+ scopes: ["journal:read"],
31674
+ returns: "JournalYear",
31675
+ notes: "GET /api/v1/journal/years/{year} \u2014 your own year only. `recap` is null until one was written; `usual` is the mean rating of the year before. journal:read is a sensitive scope."
31676
+ },
31357
31677
  {
31358
31678
  path: ["journal", "recap"],
31359
- summary: "Write or replace a week's recap: the prose, its best moments and one pattern line.",
31360
- args: [{ name: "week", required: true, description: "The ISO week, e.g. 2026-W42." }],
31679
+ summary: "Write or replace a week's, a month's or a year's recap: the prose, its best moments and one pattern line.",
31680
+ args: [
31681
+ {
31682
+ name: "period",
31683
+ required: true,
31684
+ description: "The ISO week (2026-W42), the month (2026-10) or the year (2026)."
31685
+ }
31686
+ ],
31361
31687
  flags: [
31362
31688
  { name: "body", type: "string", description: "The recap in markdown." },
31363
31689
  {
@@ -31368,7 +31694,7 @@ var COMMAND_SPECS = [
31368
31694
  ],
31369
31695
  scopes: ["journal:write"],
31370
31696
  returns: "JournalWeek",
31371
- notes: "PUT /api/v1/journal/weeks/{week}/recap (journal_write_recap). The body replaces the prose; moments and pattern replace theirs when given (pattern null clears it). Returns the week."
31697
+ notes: "PUT /api/v1/journal/weeks/{week}/recap (journal_write_recap), /api/v1/journal/months/{month}/recap or /api/v1/journal/years/{year}/recap, by the period's shape. The body replaces the prose; moments and pattern replace theirs when given (pattern null clears it). Returns the period (a JournalWeek, JournalMonth or JournalYear)."
31372
31698
  },
31373
31699
  {
31374
31700
  path: ["journal", "write"],
@@ -31535,6 +31861,15 @@ var COMMAND_SPECS = [
31535
31861
  returns: "JournalExport",
31536
31862
  notes: "GET /api/v1/journal/export. Prints `nextSince`; pass it as --since next time. do is the record: the files are read-only copies and are overwritten."
31537
31863
  },
31864
+ {
31865
+ path: ["progress", "commits"],
31866
+ summary: "Your GitHub commits: the ones you made, and your agents' on your account.",
31867
+ args: [],
31868
+ flags: [{ name: "days", type: "string", description: "7 (default) or 30." }],
31869
+ scopes: ["habits:read"],
31870
+ returns: "GithubCommits",
31871
+ notes: "GET /api/v1/progress/commits \u2014 your own only. `byYou`, `byAgents` with `agents` by name, `unsorted` (synced before the split) and `perDay`. Only your own commits count toward Insights and a GitHub-sourced habit."
31872
+ },
31538
31873
  {
31539
31874
  path: ["progress", "questions"],
31540
31875
  summary: "Insights' answers: late nights vs the next day, the morning routine, good runs, bedtime, best days, reading.",
@@ -32232,6 +32567,15 @@ var COMMAND_SPECS = [
32232
32567
  returns: "AwayState",
32233
32568
  notes: "GET/PUT /api/v1/habits/away. While away, habits leave Now, reminders stop and plants wait; tasks and events carry on. Reading needs habits:read, setting habits:write."
32234
32569
  },
32570
+ {
32571
+ path: ["tap-tags", "tap"],
32572
+ summary: "Tap a tag as if the phone read its sticker: check its habit in, or mark today's run of its routine done.",
32573
+ args: [{ name: "id", required: true, description: "The tag id (the ULID in /t/<id>)." }],
32574
+ flags: [],
32575
+ scopes: ["habits:write", "routines:write"],
32576
+ returns: "TapResult",
32577
+ notes: "POST /api/v1/tap-tags/{id}/tap. Acts as the key's member; a second tap within 30 s does nothing (outcome already). The receipt's undo names the check-in (DELETE /habits/{habitId}/entries/{entryId}) or the run's steps (POST /routines/runs/{runId}/undo)."
32578
+ },
32235
32579
  {
32236
32580
  path: ["metrics", "list"],
32237
32581
  summary: "Show weight, sleep, mood, the day rating, energy and bedtime as daily trend lines (no target, no streak).",
@@ -34691,6 +35035,55 @@ var COMMAND_SPECS = [
34691
35035
  returns: "void",
34692
35036
  notes: "DELETE /api/v1/animals/{id}/lost-card. Destructive: a printed QR stops working, so it needs --allow-destructive. Turning it on again makes a new link."
34693
35037
  },
35038
+ {
35039
+ path: ["animals", "acquisition"],
35040
+ summary: "Bringing a planned animal home: its checklist.",
35041
+ args: [{ name: "id", required: true, description: "Animal ULID." }],
35042
+ flags: [],
35043
+ scopes: ["animals:read"],
35044
+ returns: "AnimalAcquisition",
35045
+ notes: 'GET /api/v1/animals/{id}/acquisition. The Task "Bring <name> home", its steps in order, `blockers` to sort before the pick-up (papers its kind needs that aren\'t on file) and `arrived`; 404 when none was planned.'
35046
+ },
35047
+ {
35048
+ path: ["animals", "acquisition-plan"],
35049
+ summary: "Plan bringing a planned animal home: a Task with a step per line of the checklist.",
35050
+ args: [{ name: "id", required: true, description: "Animal ULID." }],
35051
+ flags: [
35052
+ {
35053
+ name: "pick-up",
35054
+ type: "string",
35055
+ description: "The pick-up day, YYYY-MM-DD (the Task's due day)."
35056
+ },
35057
+ {
35058
+ name: "data",
35059
+ type: "string",
35060
+ description: 'JSON: `{ "quarantine": true, "extraSteps": ["Buy a UV lamp"] }`.'
35061
+ }
35062
+ ],
35063
+ scopes: ["animals:write"],
35064
+ returns: "AnimalAcquisition",
35065
+ notes: "POST /api/v1/animals/{id}/acquisition. The steps: the papers its kind needs (DogID, CatID, CITES A, closed ring), the vet check, its home, and the quarantine before it meets the others (on by default for a reptile or a bird). Only a planned animal; one per animal (409)."
35066
+ },
35067
+ {
35068
+ path: ["animals", "arrived"],
35069
+ summary: "A planned animal is home: its status, the quarantine Period, the Task done.",
35070
+ args: [{ name: "id", required: true, description: "Animal ULID." }],
35071
+ flags: [
35072
+ {
35073
+ name: "on",
35074
+ type: "string",
35075
+ description: "The day it came home, YYYY-MM-DD (today by default)."
35076
+ },
35077
+ {
35078
+ name: "quarantine-months",
35079
+ type: "string",
35080
+ description: "How long it stays apart (0\u201312); 3 when its checklist has the quarantine step."
35081
+ }
35082
+ ],
35083
+ scopes: ["animals:write"],
35084
+ returns: "AnimalDetail",
35085
+ notes: "POST /api/v1/animals/{id}/arrived. Sets acquiredOn and the status (`quarantine` with a Period, else `active`); open steps stay open."
35086
+ },
34694
35087
  {
34695
35088
  path: ["runs", "change"],
34696
35089
  summary: "Apply a chat update to a run: its changes, with a receipt and Undo.",
@@ -34891,6 +35284,52 @@ var COMMAND_SPECS = [
34891
35284
  returns: "RunDetail",
34892
35285
  notes: "PATCH /api/v1/runs/{id}/sessions/{sessionId}."
34893
35286
  },
35287
+ {
35288
+ path: ["people", "propose"],
35289
+ summary: "Propose a life event read in the member's mail; nothing is written until they save it.",
35290
+ args: [],
35291
+ flags: [
35292
+ {
35293
+ name: "data",
35294
+ type: "string",
35295
+ description: 'JSON CreatePersonProposalInput, e.g. {"person":"Sam","kind":"birth","title":"Baby girl, Mila","source":"gmail:18c2f0a1b2","heardAt":"2026-10-18T08:00:00Z"}.'
35296
+ }
35297
+ ],
35298
+ scopes: ["contacts:write"],
35299
+ returns: "PersonProposal",
35300
+ notes: "Needs a member's key and PEOPLE_MAIL_PROPOSALS_ENABLED on the server (else forbidden). Kinds: birth, move, new_job, wedding, engagement, death, other. Without items, saving writes one life update (the title, on heardAt). The same mail again returns the proposal it already made. Only the member whose key it is sees it."
35301
+ },
35302
+ {
35303
+ path: ["people", "proposals"],
35304
+ summary: "Your life events from mail: pending, saved or skipped.",
35305
+ args: [],
35306
+ flags: [
35307
+ { name: "status", type: "string", description: "pending, accepted or skipped." },
35308
+ {
35309
+ name: "source",
35310
+ type: "string",
35311
+ description: "gmail:<id>: whether this mail was proposed already (the watch dedupes with it)."
35312
+ }
35313
+ ],
35314
+ scopes: ["contacts:read"],
35315
+ returns: "PersonProposal"
35316
+ },
35317
+ {
35318
+ path: ["people", "accept"],
35319
+ summary: "Save a proposal: write its life update (and its items) on the person.",
35320
+ args: [{ name: "id", required: true, description: "The proposal's id." }],
35321
+ flags: [],
35322
+ scopes: ["contacts:write"],
35323
+ returns: "PersonProposalAcceptResult"
35324
+ },
35325
+ {
35326
+ path: ["people", "skip"],
35327
+ summary: "Skip a proposal: nothing is written, and the mail isn't proposed again.",
35328
+ args: [{ name: "id", required: true, description: "The proposal's id." }],
35329
+ flags: [],
35330
+ scopes: ["contacts:write"],
35331
+ returns: "PersonProposal"
35332
+ },
34894
35333
  {
34895
35334
  path: ["runs", "sessions", "delete"],
34896
35335
  summary: "Delete a session (its changes stay applied; destructive).",
@@ -35282,13 +35721,30 @@ var COMMAND_SPECS = [
35282
35721
  {
35283
35722
  name: "data",
35284
35723
  type: "string",
35285
- description: 'JSON CreateRsvpLinksInput, e.g. {"guestListId":"01\u2026"} (every household without a live link) or with "householdIds":["01\u2026"] (re-mints, revoking the old link).'
35724
+ description: 'JSON CreateRsvpLinksInput, e.g. {"guestListId":"01\u2026"} (every household without a live link), "mode":"address" for the save-the-date (address only), or with "householdIds":["01\u2026"] (re-mints, revoking the old link; prefer `do rsvp-links replace`).'
35286
35725
  }
35287
35726
  ],
35288
35727
  scopes: ["contacts:write"],
35289
35728
  returns: "MintedRsvpLink",
35290
35729
  notes: "A guest in no household gets a household of one first. A link stops at the end of the RSVP deadline day (or after 120 days without one) unless expiresAt says otherwise. Send each household its own `path` on the web app."
35291
35730
  },
35731
+ {
35732
+ path: ["rsvp-links", "token"],
35733
+ summary: "Show a live RSVP link again: the same token it was minted with.",
35734
+ args: [{ name: "id", required: true, description: "The link's id." }],
35735
+ flags: [],
35736
+ scopes: ["contacts:write"],
35737
+ returns: "MintedRsvpLink",
35738
+ notes: "The mail and the paper QR carry this one link. A revoked or expired link is gone; one minted before tokens were kept can't be shown: replace it."
35739
+ },
35740
+ {
35741
+ path: ["rsvp-links", "replace"],
35742
+ summary: "Replace an RSVP link: a new token, and the old link (and its QR) stops working.",
35743
+ args: [{ name: "id", required: true, description: "The link's id." }],
35744
+ flags: [],
35745
+ scopes: ["contacts:write"],
35746
+ returns: "MintedRsvpLink"
35747
+ },
35292
35748
  {
35293
35749
  path: ["rsvp-links", "revoke"],
35294
35750
  summary: "Stop one RSVP link working.",
@@ -36866,14 +37322,32 @@ function renderJournalMilestone(data, mode) {
36866
37322
  return out.join(`
36867
37323
  `);
36868
37324
  }
36869
- function renderJournalWeek(data, mode) {
37325
+ function renderJournalPeriod(data, mode) {
36870
37326
  const d = data;
36871
- const out = [`Week ${d.week?.slice(6) ?? "?"} ${paint(mode, "dim", `${d.from} \u2013 ${d.to}`)}`];
37327
+ const kind = d.week ? "week" : d.month ? "month" : "year";
37328
+ const head = d.week ? `Week ${d.week.slice(6)}` : d.month ?? d.year ?? "?";
37329
+ const out = [`${head} ${paint(mode, "dim", `${d.from} \u2013 ${d.to}`)}`];
36872
37330
  const days = d.days ?? [];
36873
- const ratings = days.flatMap((day) => day.metrics?.rating === undefined ? [] : [`${day.date.slice(5)} ${day.metrics.rating}`]);
36874
- if (ratings.length > 0) {
36875
- const usual = d.usual == null ? "" : paint(mode, "dim", ` (usual ${d.usual})`);
36876
- out.push(`${ratings.join(" \xB7 ")}${usual}`);
37331
+ const usual = d.usual == null ? "" : paint(mode, "dim", ` (usual ${d.usual})`);
37332
+ if (kind === "week") {
37333
+ const ratings = days.flatMap((day) => day.metrics?.rating === undefined ? [] : [`${day.date.slice(5)} ${day.metrics.rating}`]);
37334
+ if (ratings.length > 0)
37335
+ out.push(`${ratings.join(" \xB7 ")}${usual}`);
37336
+ } else if (kind === "month") {
37337
+ const ratings = days.flatMap((day) => day.metrics?.rating === undefined ? [] : [day.metrics.rating]);
37338
+ if (ratings.length > 0) {
37339
+ const avg = Math.round(ratings.reduce((a, b) => a + b, 0) / ratings.length * 10) / 10;
37340
+ out.push(`avg ${avg} \xB7 ${ratings.length} rated${usual}`);
37341
+ }
37342
+ } else {
37343
+ for (const m of d.months ?? []) {
37344
+ if (m.rated === 0 && m.kept === 0)
37345
+ continue;
37346
+ const avg = m.average == null ? "\u2014" : String(m.average);
37347
+ out.push(` ${m.month} avg ${avg} \xB7 ${m.rated} rated \xB7 ${m.kept} kept`);
37348
+ }
37349
+ if (d.usual != null)
37350
+ out.push(paint(mode, "dim", ` usual ${d.usual} the year before`));
36877
37351
  }
36878
37352
  if (d.recap) {
36879
37353
  out.push("", d.recap.body);
@@ -36885,7 +37359,12 @@ function renderJournalWeek(data, mode) {
36885
37359
  if (d.recap.pattern)
36886
37360
  out.push("", `${paint(mode, "dim", "Pattern")} ${d.recap.pattern}`);
36887
37361
  } else {
36888
- out.push("", paint(mode, "dim", "(no recap for this week yet)"));
37362
+ out.push("", paint(mode, "dim", `(no recap for this ${kind} yet)`));
37363
+ }
37364
+ if ((d.milestones ?? []).length > 0) {
37365
+ out.push("", paint(mode, "dim", "Milestones"));
37366
+ for (const m of d.milestones ?? [])
37367
+ out.push(` \u25C6 ${m.title}${paint(mode, "dim", ` \xB7 ${m.happenedOn}`)}`);
36889
37368
  }
36890
37369
  const n = d.numbers;
36891
37370
  if (n) {
@@ -37853,6 +38332,16 @@ var HANDLERS = {
37853
38332
  data: await requireClient().get("/progress/habits"),
37854
38333
  render: renderProgressHabits
37855
38334
  }),
38335
+ "progress commits": async ({ flags, requireClient }) => {
38336
+ const days = flagString(flags, "days");
38337
+ const query = parseInput(githubCommitsQuerySchema, days ? { days } : {});
38338
+ return {
38339
+ data: await requireClient().get("/progress/commits", {
38340
+ query: { days: String(query.days) }
38341
+ }),
38342
+ render: renderRecord
38343
+ };
38344
+ },
37856
38345
  "progress questions": async ({ requireClient }) => ({
37857
38346
  data: await requireClient().get("/progress/questions"),
37858
38347
  render: renderInsightsAnswers
@@ -37945,19 +38434,43 @@ var HANDLERS = {
37945
38434
  const week = journalWeekArg(args, "week");
37946
38435
  return {
37947
38436
  data: await requireClient().get(`/journal/weeks/${week}`),
37948
- render: renderJournalWeek
38437
+ render: renderJournalPeriod
38438
+ };
38439
+ },
38440
+ "journal month": async ({ args, requireClient }) => {
38441
+ const month = args[0] ?? "";
38442
+ if (journalPeriodKind(month) !== "month") {
38443
+ throw usageError("journal month needs a month as YYYY-MM, e.g. `do journal month 2026-10`");
38444
+ }
38445
+ return {
38446
+ data: await requireClient().get(`/journal/months/${month}`),
38447
+ render: renderJournalPeriod
38448
+ };
38449
+ },
38450
+ "journal year": async ({ args, requireClient }) => {
38451
+ const year = args[0] ?? "";
38452
+ if (journalPeriodKind(year) !== "year") {
38453
+ throw usageError("journal year needs a year as YYYY, e.g. `do journal year 2026`");
38454
+ }
38455
+ return {
38456
+ data: await requireClient().get(`/journal/years/${year}`),
38457
+ render: renderJournalPeriod
37949
38458
  };
37950
38459
  },
37951
38460
  "journal recap": async ({ args, flags, requireClient }) => {
37952
- const week = journalWeekArg(args, "recap");
38461
+ const period = args[0] ?? "";
38462
+ const kind = journalPeriodKind(period);
38463
+ if (kind === null) {
38464
+ throw usageError("journal recap needs a week (2026-W42), a month (2026-10) or a year (2026), e.g. `do journal recap 2026-W42`");
38465
+ }
37953
38466
  const body = { ...readDataFlag(flags) };
37954
38467
  const text = flagString(flags, "body");
37955
38468
  if (text !== undefined)
37956
38469
  body.body = text;
37957
38470
  const input = parseInput(journalWriteRecapInputSchema, body);
37958
38471
  return {
37959
- data: await requireClient().put(`/journal/weeks/${week}/recap`, input),
37960
- render: renderJournalWeek
38472
+ data: await requireClient().put(`/journal/${kind}s/${period}/recap`, input),
38473
+ render: renderJournalPeriod
37961
38474
  };
37962
38475
  },
37963
38476
  "journal write": async ({ args, flags, requireClient }) => {
@@ -39040,6 +39553,13 @@ var HANDLERS = {
39040
39553
  });
39041
39554
  return { data: await requireClient().post("/metrics/import", input), render: renderRecord };
39042
39555
  },
39556
+ "tap-tags tap": async ({ args, requireClient }) => {
39557
+ const id = requireArg(args, 0, "tag id");
39558
+ return {
39559
+ data: await requireClient().post(`/tap-tags/${encodeURIComponent(id)}/tap`, {}),
39560
+ render: renderRecord
39561
+ };
39562
+ },
39043
39563
  "agents list": async ({ requireClient }) => ({
39044
39564
  data: await requireClient().getPage("/agents"),
39045
39565
  render: renderList
@@ -40025,6 +40545,35 @@ var HANDLERS = {
40025
40545
  await requireClient().delete(`/animals/${id}/lost-card`);
40026
40546
  return { data: { ok: true, animalId: id }, render: renderRecord };
40027
40547
  },
40548
+ "animals acquisition": async ({ args, requireClient }) => ({
40549
+ data: await requireClient().get(`/animals/${requireArg(args, 0, "animal id")}/acquisition`),
40550
+ render: renderRecord
40551
+ }),
40552
+ "animals acquisition-plan": async ({ args, flags, requireClient }) => {
40553
+ const id = requireArg(args, 0, "animal id");
40554
+ const pickUp = flagString(flags, "pick-up");
40555
+ const body = parseInput(animalAcquisitionInputSchema, {
40556
+ ...readDataFlag(flags),
40557
+ ...pickUp ? { pickUpOn: pickUp } : {}
40558
+ });
40559
+ return {
40560
+ data: await requireClient().post(`/animals/${id}/acquisition`, body),
40561
+ render: renderRecord
40562
+ };
40563
+ },
40564
+ "animals arrived": async ({ args, flags, requireClient }) => {
40565
+ const id = requireArg(args, 0, "animal id");
40566
+ const on = flagString(flags, "on");
40567
+ const months = flagString(flags, "quarantine-months");
40568
+ const body = parseInput(animalArrivedInputSchema, {
40569
+ ...on ? { on } : {},
40570
+ ...months !== undefined ? { quarantineMonths: Number(months) } : {}
40571
+ });
40572
+ return {
40573
+ data: await requireClient().post(`/animals/${id}/arrived`, body),
40574
+ render: renderRecord
40575
+ };
40576
+ },
40028
40577
  "runs change": async ({ args, flags, requireClient }) => {
40029
40578
  const id = requireArg(args, 0, "run id");
40030
40579
  const body = { ...readDataFlag(flags) };
@@ -40489,6 +41038,33 @@ var HANDLERS = {
40489
41038
  render: renderRecord
40490
41039
  };
40491
41040
  },
41041
+ "people propose": async ({ flags, requireClient }) => {
41042
+ const body = parseInput(createPersonProposalInputSchema, {
41043
+ id: ulid3(),
41044
+ ...readDataFlag(flags)
41045
+ });
41046
+ return { data: await requireClient().post("/people/proposals", body), render: renderRecord };
41047
+ },
41048
+ "people proposals": async ({ flags, requireClient }) => {
41049
+ const status = flagString(flags, "status");
41050
+ const source = flagString(flags, "source");
41051
+ const query = parseInput(personProposalsQuerySchema, {
41052
+ ...status ? { status } : {},
41053
+ ...source ? { source } : {}
41054
+ });
41055
+ return {
41056
+ data: await requireClient().get("/people/proposals", { query }),
41057
+ render: renderRecord
41058
+ };
41059
+ },
41060
+ "people accept": async ({ args, requireClient }) => ({
41061
+ data: await requireClient().post(`/people/proposals/${requireArg(args, 0, "proposal id")}/accept`, {}),
41062
+ render: renderRecord
41063
+ }),
41064
+ "people skip": async ({ args, requireClient }) => ({
41065
+ data: await requireClient().post(`/people/proposals/${requireArg(args, 0, "proposal id")}/skip`, {}),
41066
+ render: renderRecord
41067
+ }),
40492
41068
  "people brief": async ({ args, requireClient }) => {
40493
41069
  const id = requireArg(args, 0, "contact id");
40494
41070
  return { data: await requireClient().get(`/people/${id}/brief`), render: renderRecord };
@@ -40722,6 +41298,17 @@ var HANDLERS = {
40722
41298
  const body = parseInput(createRsvpLinksInputSchema, readDataFlag(flags));
40723
41299
  return { data: await requireClient().post("/rsvp-links", body), render: renderRecord };
40724
41300
  },
41301
+ "rsvp-links token": async ({ args, requireClient }) => {
41302
+ const id = requireArg(args, 0, "rsvp link id");
41303
+ return { data: await requireClient().get(`/rsvp-links/${id}/token`), render: renderRecord };
41304
+ },
41305
+ "rsvp-links replace": async ({ args, requireClient }) => {
41306
+ const id = requireArg(args, 0, "rsvp link id");
41307
+ return {
41308
+ data: await requireClient().post(`/rsvp-links/${id}/replace`, {}),
41309
+ render: renderRecord
41310
+ };
41311
+ },
40725
41312
  "rsvp-links revoke": async ({ args, requireClient }) => {
40726
41313
  const id = requireArg(args, 0, "rsvp link id");
40727
41314
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robbeverhelst/do",
3
- "version": "1.297.0",
3
+ "version": "1.298.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",