@robbeverhelst/do 1.306.2 → 1.308.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 +149 -59
  2. package/package.json +1 -1
package/dist/do.js CHANGED
@@ -19928,6 +19928,9 @@ var loginResultSchema = object({
19928
19928
  tenantId: ulidSchema,
19929
19929
  onboardingCompleted: boolean3()
19930
19930
  });
19931
+ var googleIdTokenInputSchema = object({
19932
+ idToken: string2().min(1)
19933
+ });
19931
19934
  var registerInputSchema = object({
19932
19935
  email: string2().email(),
19933
19936
  password: string2().min(8)
@@ -28194,6 +28197,21 @@ var guestListOverviewSchema = object({
28194
28197
  invites: number2().int()
28195
28198
  })
28196
28199
  });
28200
+ var rsvpDigestQuerySchema = object({ since: exports_coerce.date().optional() }).strict();
28201
+ var rsvpDigestSchema = object({
28202
+ guestListId: string2(),
28203
+ since: exports_coerce.date(),
28204
+ households: array(object({
28205
+ householdId: string2().nullable(),
28206
+ household: string2(),
28207
+ answeredAt: exports_coerce.date(),
28208
+ coming: array(string2()),
28209
+ maybe: array(string2()),
28210
+ notComing: array(string2())
28211
+ })),
28212
+ waiting: number2().int().nonnegative(),
28213
+ text: string2()
28214
+ });
28197
28215
  var RSVP_TOKEN_RE = /^rsvp_[A-Za-z0-9_-]{43}$/;
28198
28216
  var RSVP_CODE_ALPHABET = "23456789ABCDEFGHJKMNPQRSTWXYZ";
28199
28217
  var RSVP_CODE_LENGTH = 6;
@@ -28499,7 +28517,7 @@ var mailProviderEventSchema = looseObject({
28499
28517
  }).optional()
28500
28518
  })
28501
28519
  });
28502
- var MAIL_CAMPAIGN_KINDS = ["message", "save_the_date", "invitation"];
28520
+ var MAIL_CAMPAIGN_KINDS = ["message", "save_the_date", "invitation", "reminder"];
28503
28521
  var mailCampaignKindSchema = _enum2(MAIL_CAMPAIGN_KINDS);
28504
28522
  var MAIL_TEMPLATES = [
28505
28523
  "message",
@@ -28562,7 +28580,8 @@ var mailRecipientHouseholdSchema = object({
28562
28580
  name: string2(),
28563
28581
  language: mailLanguageSchema,
28564
28582
  addresses: number2().int().nonnegative(),
28565
- status: householdMailStatusSchema.nullable()
28583
+ status: householdMailStatusSchema.nullable(),
28584
+ link: boolean3().nullable().default(null)
28566
28585
  });
28567
28586
  var mailCampaignViewSchema = mailCampaignSchema.extend({
28568
28587
  households: array(mailRecipientHouseholdSchema),
@@ -31732,6 +31751,21 @@ var guestListOperations = defineOperations({
31732
31751
  response: { description: "`{ toThank, thanked }`." },
31733
31752
  errors: { 404: true }
31734
31753
  },
31754
+ rsvpDigest: {
31755
+ method: "get",
31756
+ path: "/guest-lists/{id}/rsvp-digest",
31757
+ pathParams: list,
31758
+ scopes: ["contacts:read"],
31759
+ tag: "Guests",
31760
+ summary: "The RSVPs that came in",
31761
+ description: "For the agent's daily digest (wedding C8): each household whose answer came in or changed through its RSVP link since `since` (default: the last 24 hours), oldest first, with who's `coming`, `maybe` and `notComing` by name, how many households are still `waiting` (nobody answered yet), and the same as plain lines in `text` (\"Sam & Kai answered. Coming: Sam, Kai.\"). The couple get each answer as a do notification, never a mail.",
31762
+ query: [{ name: "since", description: "An ISO instant; default 24 hours ago." }],
31763
+ querySchema: rsvpDigestQuerySchema,
31764
+ operationId: "get_guest_list_rsvp_digest",
31765
+ status: 200,
31766
+ response: { description: "`{ guestListId, since, households, waiting, text }`." },
31767
+ errors: { 400: true, 404: true }
31768
+ },
31735
31769
  export: {
31736
31770
  method: "get",
31737
31771
  path: "/guest-lists/{id}/exports/{kind}",
@@ -32555,6 +32589,31 @@ var nodeOperations = defineOperations({
32555
32589
  }
32556
32590
  });
32557
32591
 
32592
+ // ../../packages/schema/src/operations/notes.ts
32593
+ var noteOperations = defineOperations({
32594
+ ...crudOperations({
32595
+ segment: "notes",
32596
+ tag: "Notes",
32597
+ noun: "note",
32598
+ read: "notes:read",
32599
+ write: "notes:write",
32600
+ create: createNoteInputSchema,
32601
+ update: updateNoteInputSchema,
32602
+ view: "Note"
32603
+ }),
32604
+ backlinks: {
32605
+ method: "get",
32606
+ path: "/notes/{id}/backlinks",
32607
+ scopes: ["notes:read"],
32608
+ tag: "Notes",
32609
+ summary: "List backlinks",
32610
+ description: "The notes that link to this note.",
32611
+ status: 200,
32612
+ response: { description: "The backlinking notes." },
32613
+ errors: { 404: true }
32614
+ }
32615
+ });
32616
+
32558
32617
  // ../../packages/schema/src/operations/occurrences.ts
32559
32618
  var occurrenceOperations = defineOperations({
32560
32619
  list: {
@@ -34825,7 +34884,7 @@ function parseCapture2(input, now) {
34825
34884
 
34826
34885
  // src/meta.ts
34827
34886
  var CLI_NAME = "do";
34828
- var VERSION = "1.306.2";
34887
+ var VERSION = "1.308.0";
34829
34888
  var API_PREFIX = "/api/v1";
34830
34889
  var DEFAULT_API_URL = "http://localhost:3001";
34831
34890
 
@@ -35358,26 +35417,17 @@ var ENTITIES = [
35358
35417
  createInput: "CreateRoutineInput",
35359
35418
  updateInput: "UpdateRoutineInput"
35360
35419
  }),
35361
- {
35420
+ entityFromOperations(noteOperations, {
35362
35421
  name: "notes",
35363
- path: "/notes",
35364
- readScopes: ["notes:read"],
35365
35422
  returns: "Note",
35366
- canGet: true,
35367
35423
  listFlags: [
35368
35424
  { name: "q", description: "full-text search over the title and body", query: "q" },
35369
35425
  { name: "area", description: "filter to notes filed under this area id", query: "areaId" },
35370
35426
  { name: "tag", description: "filter to notes carrying this tag", query: "tag" }
35371
35427
  ],
35372
- write: {
35373
- scopes: ["notes:write"],
35374
- createSchema: createNoteInputSchema,
35375
- createInput: "CreateNoteInput",
35376
- updateSchema: updateNoteInputSchema,
35377
- updateInput: "UpdateNoteInput",
35378
- canDelete: true
35379
- }
35380
- },
35428
+ createInput: "CreateNoteInput",
35429
+ updateInput: "UpdateNoteInput"
35430
+ }),
35381
35431
  {
35382
35432
  name: "contacts",
35383
35433
  path: "/contacts",
@@ -36458,7 +36508,7 @@ var COMMAND_SPECS = [
36458
36508
  description: "How long it takes, in minutes (overrides an estimate in the text)."
36459
36509
  }
36460
36510
  ],
36461
- scopes: ["tasks:write"],
36511
+ scopes: [...taskOperations.create.scopes],
36462
36512
  returns: "Task",
36463
36513
  grammar: {
36464
36514
  "#tag": "Adds a tag. Repeatable: '#home #urgent'.",
@@ -36474,9 +36524,9 @@ var COMMAND_SPECS = [
36474
36524
  summary: "Show today's actionable tasks (scheduled, due, overdue, in-progress), then the habits and routines due today.",
36475
36525
  args: [],
36476
36526
  flags: [],
36477
- scopes: ["tasks:read"],
36527
+ scopes: [...taskOperations.list.scopes],
36478
36528
  returns: "TodaySummary",
36479
- notes: "Tasks are composed client-side from GET /api/v1/tasks (the local day from your clock); habits and routines come from GET /api/v1/habits/today (your saved time zone's day) under `habits`, left out when the key lacks habits:read."
36529
+ notes: `Tasks are composed client-side from ${routeOf(taskOperations.list)} (the local day from your clock); habits and routines come from ${routeOf(habitOperations.today)} (your saved time zone's day) under \`habits\`, left out when the key lacks habits:read.`
36480
36530
  },
36481
36531
  {
36482
36532
  path: ["today", "earlier"],
@@ -36499,9 +36549,9 @@ var COMMAND_SPECS = [
36499
36549
  { name: "ids", required: true, description: "One or more task ids." }
36500
36550
  ],
36501
36551
  flags: [],
36502
- scopes: ["tasks:write"],
36552
+ scopes: [...todayOperations.rollover.scopes],
36503
36553
  returns: "RolloverResult",
36504
- notes: "POST /api/v1/today/rollover. `later` reads the day from `do today earlier` first. Let go is cancelled, never done, so it stays out of Landed; undo with `do task reopen`."
36554
+ notes: `${routeOf(todayOperations.rollover)}. \`later\` reads the day from \`do today earlier\` first. Let go is cancelled, never done, so it stays out of Landed; undo with \`do task reopen\`.`
36505
36555
  },
36506
36556
  {
36507
36557
  path: ["now"],
@@ -36957,7 +37007,7 @@ var COMMAND_SPECS = [
36957
37007
  description: "When it was finished (ISO); back-dates completedAt. Default: now."
36958
37008
  }
36959
37009
  ],
36960
- scopes: ["tasks:write"],
37010
+ scopes: [...new Set([...taskOperations.get.scopes, ...taskOperations.update.scopes])],
36961
37011
  returns: "Task",
36962
37012
  notes: "Sets completedAt (the basis of Landed); --at corrects it on an already-done task."
36963
37013
  },
@@ -37378,7 +37428,7 @@ var COMMAND_SPECS = [
37378
37428
  ],
37379
37429
  scopes: [...habitOperations.checkInByTitle.scopes],
37380
37430
  returns: "HabitSummary",
37381
- notes: `POST /api/v1/habits/check-in. Title or alias, case-insensitive; several matches \u2192 409 with error.details.candidates (id, title, aliases), none \u2192 404 naming close titles; a habit counted from Google Fit, Strava or GitHub \u2192 409. --set writes the difference to the day's total as its own check-in. An Agent's key records the check-in as that Agent's ("<agent>, 07:12"). --note puts a short note on it ("drill done, felt heavy" \u2192 --note "felt heavy"); the reply's lastCheckIn.id is the check-in, for \`do habit note\` later.`
37431
+ notes: `${routeOf(habitOperations.checkInByTitle)}. Title or alias, case-insensitive; several matches \u2192 409 with error.details.candidates (id, title, aliases), none \u2192 404 naming close titles; a habit counted from Google Fit, Strava or GitHub \u2192 409. --set writes the difference to the day's total as its own check-in. An Agent's key records the check-in as that Agent's ("<agent>, 07:12"). --note puts a short note on it ("drill done, felt heavy" \u2192 --note "felt heavy"); the reply's lastCheckIn.id is the check-in, for \`do habit note\` later.`
37382
37432
  },
37383
37433
  {
37384
37434
  path: ["habit", "alias", "add"],
@@ -37390,7 +37440,7 @@ var COMMAND_SPECS = [
37390
37440
  flags: [],
37391
37441
  scopes: [...habitOperations.addAlias.scopes],
37392
37442
  returns: "HabitSummary",
37393
- notes: "POST /api/v1/habits/:id/aliases. One already there (ignoring case) is a no-op; at most 12."
37443
+ notes: `${routeOf(habitOperations.addAlias)}. One already there (ignoring case) is a no-op; at most 12.`
37394
37444
  },
37395
37445
  {
37396
37446
  path: ["habit", "alias", "rm"],
@@ -37402,7 +37452,7 @@ var COMMAND_SPECS = [
37402
37452
  flags: [],
37403
37453
  scopes: [...habitOperations.removeAlias.scopes],
37404
37454
  returns: "HabitSummary",
37405
- notes: "DELETE /api/v1/habits/:id/aliases/:alias. 404 when the habit doesn't have it."
37455
+ notes: `${routeOf(habitOperations.removeAlias)}. 404 when the habit doesn't have it.`
37406
37456
  },
37407
37457
  {
37408
37458
  path: ["habits", "today"],
@@ -37565,7 +37615,7 @@ var COMMAND_SPECS = [
37565
37615
  ],
37566
37616
  scopes: ["habits:read", "habits:write"],
37567
37617
  returns: "AwayState",
37568
- 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."
37618
+ notes: `${habitOperations.getAway.method.toUpperCase()}/${routeOf(habitOperations.setAway)}. While away, habits leave Now, reminders stop and plants wait; tasks and events carry on. Reading needs habits:read, setting habits:write.`
37569
37619
  },
37570
37620
  {
37571
37621
  path: ["tap-tags", "tap"],
@@ -37852,7 +37902,7 @@ var COMMAND_SPECS = [
37852
37902
  summary: "List the notes/entities whose body [[wikilinks]] reference a note.",
37853
37903
  args: [{ name: "id", required: true, description: "Note (node) ULID." }],
37854
37904
  flags: [],
37855
- scopes: ["notes:read"],
37905
+ scopes: [...noteOperations.backlinks.scopes],
37856
37906
  returns: "Backlink",
37857
37907
  notes: "The reverse of the links a note's body declares; cross-entity."
37858
37908
  },
@@ -38008,7 +38058,7 @@ var COMMAND_SPECS = [
38008
38058
  ],
38009
38059
  scopes: [...worktreeLinkOperations.set.scopes],
38010
38060
  returns: "WorktreeLink",
38011
- notes: "PUT /api/v1/worktree-links/{node}. --host and --worktree are required."
38061
+ notes: `${routeOf(worktreeLinkOperations.set)}. --host and --worktree are required.`
38012
38062
  },
38013
38063
  {
38014
38064
  path: ["worktree-links", "clear"],
@@ -38722,16 +38772,16 @@ var COMMAND_SPECS = [
38722
38772
  summary: "List feature-modules and whether each is enabled for the caller.",
38723
38773
  args: [],
38724
38774
  flags: [],
38725
- scopes: ["settings:read"],
38775
+ scopes: [...settingsOperations.get.scopes],
38726
38776
  returns: "ModuleStatus",
38727
- notes: "Reads enabledModules from GET /api/v1/settings; an empty set means every module is on."
38777
+ notes: `Reads enabledModules from ${routeOf(settingsOperations.get)}; an empty set means every module is on.`
38728
38778
  },
38729
38779
  {
38730
38780
  path: ["modules", "enable"],
38731
38781
  summary: "Enable a feature-module (surfaces it in nav / quick-add / \u2318K).",
38732
38782
  args: [{ name: "key", required: true, description: "Module key (see `do modules list`)." }],
38733
38783
  flags: [],
38734
- scopes: ["settings:read", "settings:write"],
38784
+ scopes: [...new Set([...settingsOperations.get.scopes, ...settingsOperations.update.scopes])],
38735
38785
  returns: "UserSettings",
38736
38786
  notes: "Reads then patches settings; only the module visibility list changes."
38737
38787
  },
@@ -38740,7 +38790,7 @@ var COMMAND_SPECS = [
38740
38790
  summary: "Disable a feature-module (hides its surfaces \u2014 nothing is deleted).",
38741
38791
  args: [{ name: "key", required: true, description: "Module key (see `do modules list`)." }],
38742
38792
  flags: [],
38743
- scopes: ["settings:read", "settings:write"],
38793
+ scopes: [...new Set([...settingsOperations.get.scopes, ...settingsOperations.update.scopes])],
38744
38794
  returns: "UserSettings",
38745
38795
  notes: "Reads then patches settings; only the module visibility list changes."
38746
38796
  },
@@ -38781,7 +38831,7 @@ var COMMAND_SPECS = [
38781
38831
  flags: [],
38782
38832
  scopes: [...collectionOperations.types.scopes],
38783
38833
  returns: "CollectionTypeSummary",
38784
- notes: "The Type registry is code-defined (ADR 0017); served from GET /api/v1/collection/types."
38834
+ notes: `The Type registry is code-defined (ADR 0017); served from ${routeOf(collectionOperations.types)}.`
38785
38835
  },
38786
38836
  {
38787
38837
  path: ["collection", "list"],
@@ -39101,16 +39151,16 @@ var COMMAND_SPECS = [
39101
39151
  summary: "Focus on one Area for the rest of the day: Now, Tasks and Calendar show only it.",
39102
39152
  args: [{ name: "id", required: false, description: "Area ULID (omit with --off)." }],
39103
39153
  flags: [{ name: "off", type: "boolean", description: "Show everything again." }],
39104
- scopes: ["settings:write"],
39154
+ scopes: [...settingsOperations.update.scopes],
39105
39155
  returns: "UserSettings",
39106
- notes: "PATCH /api/v1/settings { focusAreaId }. Clears itself at the end of the member's day (focusUntil); hidden tasks don't move or go overdue."
39156
+ notes: `${routeOf(settingsOperations.update)} { focusAreaId }. Clears itself at the end of the member's day (focusUntil); hidden tasks don't move or go overdue.`
39107
39157
  },
39108
39158
  {
39109
39159
  path: ["areas", "pin"],
39110
39160
  summary: "Pin an Area under Life in the desktop sidebar (up to five).",
39111
39161
  args: [{ name: "id", required: true, description: "Area ULID." }],
39112
39162
  flags: [],
39113
- scopes: ["settings:read", "settings:write"],
39163
+ scopes: [...new Set([...settingsOperations.get.scopes, ...settingsOperations.update.scopes])],
39114
39164
  returns: "UserSettings",
39115
39165
  notes: "Reads then patches settings.pinnedAreaIds; a pinned Area stays where it is."
39116
39166
  },
@@ -39119,7 +39169,7 @@ var COMMAND_SPECS = [
39119
39169
  summary: "Take an Area out of the desktop sidebar.",
39120
39170
  args: [{ name: "id", required: true, description: "Area ULID." }],
39121
39171
  flags: [],
39122
- scopes: ["settings:read", "settings:write"],
39172
+ scopes: [...new Set([...settingsOperations.get.scopes, ...settingsOperations.update.scopes])],
39123
39173
  returns: "UserSettings",
39124
39174
  notes: "Reads then patches settings.pinnedAreaIds."
39125
39175
  },
@@ -40776,6 +40826,17 @@ var COMMAND_SPECS = [
40776
40826
  returns: "ThankYouView",
40777
40827
  notes: 'Log a gift as a gift_received moment with sourceNodeId = the project: `do contact-moments create --data \'{"contactId":"<id>","kind":"gift_received","summary":"a moka pot","sourceNodeId":"<project>"}\'`. Mark the card sent: `do contact-moments update <id> --data \'{"thankedAt":"2027-07-10"}\'`.'
40778
40828
  },
40829
+ {
40830
+ path: ["guest-lists", "rsvp-digest"],
40831
+ summary: "The RSVPs that came in since a moment (default the last 24 hours), for a daily digest.",
40832
+ args: [{ name: "id", required: true, description: "The guest list's id." }],
40833
+ flags: [
40834
+ { name: "since", type: "string", description: "An ISO instant; default 24 hours ago." }
40835
+ ],
40836
+ scopes: [...guestListOperations.rsvpDigest.scopes],
40837
+ returns: "RsvpDigest",
40838
+ notes: "Each household that answered or changed its answer, with who's coming, maybe and not coming by name, how many households still wait, and the same as plain lines in `text`. The couple get each answer as a do notification, never a mail."
40839
+ },
40779
40840
  {
40780
40841
  path: ["guest-lists", "export"],
40781
40842
  summary: "Export for the caterer, the venue, the church or the RSVP answers (CSV) to stdout, or save the floor plan or the paper invitations (PDF) to a file.",
@@ -41105,7 +41166,7 @@ var COMMAND_SPECS = [
41105
41166
  ],
41106
41167
  scopes: [],
41107
41168
  returns: "LoginResult",
41108
- notes: "Writes ~/.config/do/config.json (0600) after a successful GET /api/v1/whoami."
41169
+ notes: `Writes ~/.config/do/config.json (0600) after a successful ${routeOf(whoamiOperations.whoami)}.`
41109
41170
  },
41110
41171
  {
41111
41172
  path: ["config", "set"],
@@ -43319,7 +43380,7 @@ var HANDLERS = {
43319
43380
  ...duration ? { durationMinutes: duration } : {}
43320
43381
  });
43321
43382
  const client = requireClient();
43322
- const task = await client.post("/tasks", input);
43383
+ const task = await client.post(pathOf(taskOperations.create), input);
43323
43384
  if (parsed.recurrence) {
43324
43385
  const rule = parseInput(createRecurrenceRuleInputSchema, {
43325
43386
  templateId: id,
@@ -43334,13 +43395,13 @@ var HANDLERS = {
43334
43395
  const tasks = [];
43335
43396
  let cursor;
43336
43397
  do {
43337
- const page = await client.getPage("/tasks", {
43398
+ const page = await client.getPage(pathOf(taskOperations.list), {
43338
43399
  query: { filter: "all", cursor }
43339
43400
  });
43340
43401
  tasks.push(...page.data);
43341
43402
  cursor = page.nextCursor ?? undefined;
43342
43403
  } while (cursor);
43343
- const habits = await client.get("/habits/today").catch((error) => {
43404
+ const habits = await client.get(pathOf(habitOperations.today)).catch((error) => {
43344
43405
  if (error instanceof CliError && (error.code === "auth" || error.exitCode === EXIT.NOT_FOUND))
43345
43406
  return;
43346
43407
  throw error;
@@ -43378,7 +43439,7 @@ var HANDLERS = {
43378
43439
  to = today.toISOString();
43379
43440
  body = { action: "reschedule", to, taskIds };
43380
43441
  } else if (answer === "later") {
43381
- const earlier = await client.get("/today/from-earlier", {
43442
+ const earlier = await client.get(pathOf(todayOperations.fromEarlier), {
43382
43443
  query: { from: today.toISOString() }
43383
43444
  });
43384
43445
  to = earlier.laterThisWeek;
@@ -43386,7 +43447,7 @@ var HANDLERS = {
43386
43447
  } else {
43387
43448
  body = { action: answer === "someday" ? "someday" : "drop", taskIds };
43388
43449
  }
43389
- const result = await client.post("/today/rollover", body);
43450
+ const result = await client.post(pathOf(todayOperations.rollover), body);
43390
43451
  return {
43391
43452
  data: { answer, ...to ? { to } : {}, ...result },
43392
43453
  render: renderFromEarlierAnswer
@@ -44297,7 +44358,7 @@ var HANDLERS = {
44297
44358
  "notes backlinks": async ({ args, requireClient }) => {
44298
44359
  const id = requireArg(args, 0, "note id");
44299
44360
  return {
44300
- data: await requireClient().get(`/notes/${id}/backlinks`),
44361
+ data: await requireClient().get(pathOf(noteOperations.backlinks, { id })),
44301
44362
  render: renderList
44302
44363
  };
44303
44364
  },
@@ -44305,14 +44366,17 @@ var HANDLERS = {
44305
44366
  const id = requireArg(args, 0, "task id");
44306
44367
  const at = flagString(flags, "at");
44307
44368
  const client = requireClient();
44308
- const current = await client.get(`/tasks/${id}`);
44369
+ const current = await client.get(pathOf(taskOperations.get, { id }));
44309
44370
  if (current.status === "done" && at === undefined)
44310
44371
  return { data: current, render: renderTask };
44311
44372
  const body = parseInput(updateTaskInputSchema, {
44312
44373
  status: "done",
44313
44374
  ...at !== undefined ? { completedAt: at } : {}
44314
44375
  });
44315
- return { data: await client.patch(`/tasks/${id}`, body), render: renderTask };
44376
+ return {
44377
+ data: await client.patch(pathOf(taskOperations.update, { id }), body),
44378
+ render: renderTask
44379
+ };
44316
44380
  },
44317
44381
  "task cancel": async ({ args, requireClient }) => {
44318
44382
  const id = requireArg(args, 0, "task id");
@@ -44717,10 +44781,16 @@ var HANDLERS = {
44717
44781
  if (off && until)
44718
44782
  throw usageError("`do away off` comes back now; it takes no --until");
44719
44783
  if (!off && !until) {
44720
- return { data: await requireClient().get("/habits/away"), render: renderAway };
44784
+ return {
44785
+ data: await requireClient().get(pathOf(habitOperations.getAway)),
44786
+ render: renderAway
44787
+ };
44721
44788
  }
44722
44789
  const input = parseInput(awayInputSchema, { until: off ? null : until });
44723
- return { data: await requireClient().put("/habits/away", input), render: renderAway };
44790
+ return {
44791
+ data: await requireClient().put(pathOf(habitOperations.setAway), input),
44792
+ render: renderAway
44793
+ };
44724
44794
  },
44725
44795
  "routine done": async ({ args, requireClient }) => {
44726
44796
  const id = requireArg(args, 0, "routine id");
@@ -44924,7 +44994,7 @@ var HANDLERS = {
44924
44994
  };
44925
44995
  },
44926
44996
  "modules list": async ({ requireClient }) => {
44927
- const settings = await requireClient().get("/settings");
44997
+ const settings = await requireClient().get(pathOf(settingsOperations.get));
44928
44998
  const enabled = new Set(effectiveEnabledModules(settings.enabledModules));
44929
44999
  const rows = FEATURE_MODULES.map((module) => ({
44930
45000
  key: module.key,
@@ -45203,7 +45273,10 @@ var HANDLERS = {
45203
45273
  if (id === undefined)
45204
45274
  throw usageError("areas focus needs an area id, or --off to show everything");
45205
45275
  const body = parseInput(updateUserSettingsInputSchema, { focusAreaId: id });
45206
- return { data: await requireClient().patch("/settings", body), render: renderRecord };
45276
+ return {
45277
+ data: await requireClient().patch(pathOf(settingsOperations.update), body),
45278
+ render: renderRecord
45279
+ };
45207
45280
  },
45208
45281
  "areas pin": async ({ args, requireClient }) => setAreaPinned(args, requireClient, true),
45209
45282
  "areas unpin": async ({ args, requireClient }) => setAreaPinned(args, requireClient, false),
@@ -45897,7 +45970,7 @@ var HANDLERS = {
45897
45970
  const input = await saveUpload(path);
45898
45971
  if (dryRun)
45899
45972
  return { ...input, screenshot: input.screenshot ? "(png)" : null };
45900
- return requireClient().post(`/runs/${id}/save-header`, input);
45973
+ return requireClient().post(pathOf(runOperations.uploadSaveHeader, { id }), input);
45901
45974
  };
45902
45975
  if (!flagBool(flags, "watch")) {
45903
45976
  return { data: await send(await resolveSave(target)), render: renderRecord };
@@ -46639,6 +46712,17 @@ var HANDLERS = {
46639
46712
  render: renderRecord
46640
46713
  };
46641
46714
  },
46715
+ "guest-lists rsvp-digest": async ({ args, flags, requireClient }) => {
46716
+ const id = requireArg(args, 0, "guest list id");
46717
+ const since = flagString(flags, "since");
46718
+ const query = parseInput(rsvpDigestQuerySchema, since ? { since } : {});
46719
+ return {
46720
+ data: await requireClient().get(pathOf(guestListOperations.rsvpDigest, { id }), {
46721
+ query: query.since ? { since: query.since.toISOString() } : {}
46722
+ }),
46723
+ render: renderRecord
46724
+ };
46725
+ },
46642
46726
  "guest-lists export": async ({ args, flags, requireClient }) => {
46643
46727
  const id = requireArg(args, 0, "guest list id");
46644
46728
  const kind = parseInput(guestExportKindSchema, flagString(flags, "kind") ?? "venue");
@@ -46854,7 +46938,7 @@ var HANDLERS = {
46854
46938
  if (!config.apiKey) {
46855
46939
  throw configError("provide --api-key <key> (or set DO_API_KEY) to log in");
46856
46940
  }
46857
- const auth = await requireClient().get("/whoami");
46941
+ const auth = await requireClient().get(pathOf(whoamiOperations.whoami));
46858
46942
  const path = writeConfigFile(io, { apiUrl: config.apiUrl, apiKey: config.apiKey });
46859
46943
  return {
46860
46944
  data: {
@@ -46932,20 +47016,26 @@ async function setModuleVisibility(args, requireClient, on) {
46932
47016
  throw usageError(`unknown module \`${key}\` \u2014 valid keys: ${MODULE_KEYS.join(", ")}`);
46933
47017
  }
46934
47018
  const client = requireClient();
46935
- const settings = await client.get("/settings");
47019
+ const settings = await client.get(pathOf(settingsOperations.get));
46936
47020
  const enabledModules = setModuleEnabled(settings.enabledModules, key, on);
46937
47021
  const body = parseInput(updateUserSettingsInputSchema, { enabledModules });
46938
- return { data: await client.patch("/settings", body), render: renderRecord };
47022
+ return {
47023
+ data: await client.patch(pathOf(settingsOperations.update), body),
47024
+ render: renderRecord
47025
+ };
46939
47026
  }
46940
47027
  async function setAreaPinned(args, requireClient, pinned) {
46941
47028
  const id = requireArg(args, 0, "area id");
46942
47029
  const client = requireClient();
46943
- const settings = await client.get("/settings");
47030
+ const settings = await client.get(pathOf(settingsOperations.get));
46944
47031
  const rest = (settings.pinnedAreaIds ?? []).filter((x) => x !== id);
46945
47032
  const body = parseInput(updateUserSettingsInputSchema, {
46946
47033
  pinnedAreaIds: pinned ? [...rest, id] : rest
46947
47034
  });
46948
- return { data: await client.patch("/settings", body), render: renderRecord };
47035
+ return {
47036
+ data: await client.patch(pathOf(settingsOperations.update), body),
47037
+ render: renderRecord
47038
+ };
46949
47039
  }
46950
47040
  function parseTitleTags(args) {
46951
47041
  const titleWords = [];
@@ -47269,10 +47359,10 @@ async function postText(io, args) {
47269
47359
  return text;
47270
47360
  }
47271
47361
  async function homeSlug(client) {
47272
- const me = await client.get("/whoami");
47362
+ const me = await client.get(pathOf(whoamiOperations.whoami));
47273
47363
  if (!me.agentId)
47274
47364
  throw usageError("this key isn't an Agent's: pass --thread <slug|id>");
47275
- const { data } = await client.getPage("/agents");
47365
+ const { data } = await client.getPage(pathOf(agentOperations.list));
47276
47366
  const agent = data.find((a) => a.id === me.agentId);
47277
47367
  if (!agent)
47278
47368
  throw usageError("couldn't read the agent's name: pass --thread <slug|id>");
@@ -47282,7 +47372,7 @@ var ULID = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
47282
47372
  async function resolveAgentId(client, agent) {
47283
47373
  if (ULID.test(agent))
47284
47374
  return agent;
47285
- const { data } = await client.getPage("/agents");
47375
+ const { data } = await client.getPage(pathOf(agentOperations.list));
47286
47376
  const wanted = agent.trim().toLowerCase();
47287
47377
  const match = data.find((a) => a.name.toLowerCase() === wanted);
47288
47378
  if (!match) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robbeverhelst/do",
3
- "version": "1.306.2",
3
+ "version": "1.308.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",