@robbeverhelst/do 1.365.0 → 1.366.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 +247 -29
  2. package/package.json +1 -1
package/dist/do.js CHANGED
@@ -14420,7 +14420,7 @@ var configError = (message) => new CliError("config", message, EXIT.CONFIG);
14420
14420
 
14421
14421
  // src/meta.ts
14422
14422
  var CLI_NAME = "do";
14423
- var VERSION = "1.365.0";
14423
+ var VERSION = "1.366.0";
14424
14424
  var API_PREFIX = "/api/v1";
14425
14425
  var DEFAULT_API_URL = "http://localhost:3001";
14426
14426
 
@@ -18024,6 +18024,7 @@ var habits = pgTable("habits", {
18024
18024
  sourceMetric: text("source_metric"),
18025
18025
  aliases: text("aliases").array().notNull().default(sql`'{}'::text[]`),
18026
18026
  timeOfDay: text("time_of_day"),
18027
+ dayTimes: jsonb("day_times").$type(),
18027
18028
  pausedFrom: date5("paused_from", { mode: "string" }),
18028
18029
  pausedUntil: date5("paused_until", { mode: "string" }),
18029
18030
  remind: boolean4("remind").notNull().default(false),
@@ -18130,7 +18131,8 @@ var routines = pgTable("routines", {
18130
18131
  restingUntil: date5("resting_until", { mode: "string" }),
18131
18132
  icon: text("icon"),
18132
18133
  keptNotice: text("kept_notice"),
18133
- dayTimes: jsonb("day_times").$type().notNull().default({})
18134
+ dayTimes: jsonb("day_times").$type().notNull().default({}),
18135
+ durationMinutes: integer2("duration_minutes")
18134
18136
  }, (t) => [
18135
18137
  index("routines_tenant_idx").on(t.tenantId),
18136
18138
  index("routines_tenant_area_idx").on(t.tenantId, t.areaId)
@@ -19158,9 +19160,11 @@ var saveAgentConnectionInputSchema = object({
19158
19160
  message: "a connection without an endpoint names its agent",
19159
19161
  path: ["agentId"]
19160
19162
  });
19163
+ var ECHO_PAGE_LABEL_MAX = 120;
19161
19164
  var agentPageContextSchema = object({
19162
19165
  route: string2().trim().min(1).max(500).startsWith("/"),
19163
19166
  nodeId: string2().trim().min(1).max(64).nullable(),
19167
+ page: string2().trim().min(1).max(ECHO_PAGE_LABEL_MAX).optional(),
19164
19168
  focusArea: object({
19165
19169
  id: string2().trim().min(1).max(64),
19166
19170
  title: string2().trim().min(1).max(200)
@@ -19540,6 +19544,39 @@ var briefRowSchema = object({
19540
19544
  verb: briefVerbSchema.optional()
19541
19545
  }).strict();
19542
19546
  var BRIEF_ROWS_MAX = 8;
19547
+ var postCardTypeSchema = _enum2([
19548
+ "text",
19549
+ "brief",
19550
+ "report",
19551
+ "table",
19552
+ "chart",
19553
+ "pr",
19554
+ "deploy",
19555
+ "run",
19556
+ "compare",
19557
+ "gallery",
19558
+ "design",
19559
+ "chip",
19560
+ "chips",
19561
+ "invoice",
19562
+ "mail",
19563
+ "link",
19564
+ "file",
19565
+ "voice",
19566
+ "code",
19567
+ "ask",
19568
+ "digest",
19569
+ "handoff",
19570
+ "decision",
19571
+ "answer"
19572
+ ]);
19573
+ var POST_CARD_DATA_MAX = 16000;
19574
+ var postCardSchema = object({
19575
+ type: postCardTypeSchema,
19576
+ data: record(string2(), unknown()).default({}).refine((d) => JSON.stringify(d).length <= POST_CARD_DATA_MAX, {
19577
+ message: `a card's data is at most ${POST_CARD_DATA_MAX} characters as JSON`
19578
+ })
19579
+ });
19543
19580
  var briefSchema = object({
19544
19581
  label: string2().trim().min(1).max(40),
19545
19582
  title: string2().trim().min(1).max(200),
@@ -19652,6 +19689,7 @@ var agentPostInputSchema = object({
19652
19689
  run: postRunSchema.optional(),
19653
19690
  recovered: boolean2().optional(),
19654
19691
  brief: briefSchema.optional(),
19692
+ card: postCardSchema.optional(),
19655
19693
  receipt: postReceiptInputSchema.optional()
19656
19694
  });
19657
19695
  var agentPostEditSchema = object({
@@ -19660,9 +19698,10 @@ var agentPostEditSchema = object({
19660
19698
  final: boolean2().optional(),
19661
19699
  level: postLevelSchema.optional(),
19662
19700
  run: postRunSchema.optional(),
19663
- brief: briefSchema.optional()
19701
+ brief: briefSchema.optional(),
19702
+ card: postCardSchema.optional()
19664
19703
  }).refine((e) => Object.values(e).some((v) => v !== undefined), {
19665
- message: "send text, title, final, level, run or brief"
19704
+ message: "send text, title, final, level, run, brief or card"
19666
19705
  });
19667
19706
  var agentPostResultSchema = object({ postId: ulidSchema, created: boolean2() });
19668
19707
  var promptOptionSchema = object({
@@ -21364,6 +21403,7 @@ var occurrenceSchema = createSelectSchema(occurrences, {
21364
21403
  completedAt: exports_coerce.date().nullable()
21365
21404
  });
21366
21405
  var byDayCodeSchema = _enum2(["MO", "TU", "WE", "TH", "FR", "SA", "SU"]);
21406
+ var weekdayTimesSchema = partialRecord(byDayCodeSchema, string2().regex(/^([01]\d|2[0-3]):[0-5]\d$/));
21367
21407
  var byDayOrdinalSchema = _enum2(["1", "2", "3", "4", "-1"]);
21368
21408
  var byDaySchema = union([
21369
21409
  byDayCodeSchema,
@@ -21428,6 +21468,7 @@ var habitSchema = createSelectSchema(habits, {
21428
21468
  sourceMetric: string2().nullable().default(null),
21429
21469
  aliases: array(string2()).default([]),
21430
21470
  timeOfDay: string2().nullable().default(null),
21471
+ dayTimes: weekdayTimesSchema.nullish(),
21431
21472
  pausedFrom: exports_iso.date().nullable().default(null),
21432
21473
  pausedUntil: exports_iso.date().nullable().default(null),
21433
21474
  remind: boolean2().default(false),
@@ -21501,6 +21542,7 @@ var createHabitInputSchema = createInsertSchema(habits, {
21501
21542
  areaId: ulidSchema.nullish(),
21502
21543
  aliases: habitAliasesSchema.optional(),
21503
21544
  timeOfDay: habitTimeOfDaySchema.nullish(),
21545
+ dayTimes: weekdayTimesSchema.nullish(),
21504
21546
  remind: boolean2().optional(),
21505
21547
  durationMinutes: habitDurationMinutesSchema.nullish(),
21506
21548
  activeMonths: habitActiveMonthsSchema.optional()
@@ -21519,6 +21561,7 @@ var updateHabitInputSchema = createUpdateSchema(habits, {
21519
21561
  areaId: ulidSchema.nullish(),
21520
21562
  aliases: habitAliasesSchema.optional(),
21521
21563
  timeOfDay: habitTimeOfDaySchema.nullish(),
21564
+ dayTimes: weekdayTimesSchema.nullish(),
21522
21565
  remind: boolean2().optional(),
21523
21566
  durationMinutes: habitDurationMinutesSchema.nullish(),
21524
21567
  activeMonths: habitActiveMonthsSchema.optional()
@@ -21641,7 +21684,8 @@ var habitDueDateSchema = object({
21641
21684
  scheduleLabel: string2().min(1),
21642
21685
  daily: boolean2(),
21643
21686
  streakLabel: string2().min(1),
21644
- done: boolean2().default(false)
21687
+ done: boolean2().default(false),
21688
+ entryId: string2().nullable().default(null)
21645
21689
  });
21646
21690
  var habitEntriesQuerySchema = object({
21647
21691
  before: exports_coerce.date().optional(),
@@ -22655,7 +22699,7 @@ var projectDetailSchema = projectViewSchema.extend({
22655
22699
  var attachTaskInputSchema = object({ taskId: ulidSchema });
22656
22700
 
22657
22701
  // ../../packages/schema/src/contracts/routines.ts
22658
- var routineDayTimesSchema = partialRecord(_enum2(["MO", "TU", "WE", "TH", "FR", "SA", "SU"]), string2().regex(/^([01]\d|2[0-3]):[0-5]\d$/));
22702
+ var routineDayTimesSchema = weekdayTimesSchema;
22659
22703
  var routineSchema = createSelectSchema(routines);
22660
22704
  var routineStepSchema = createSelectSchema(routineSteps, {
22661
22705
  createdAt: exports_coerce.date(),
@@ -22745,8 +22789,10 @@ var routineStepInputSchema = object({
22745
22789
  }
22746
22790
  }
22747
22791
  });
22792
+ var routineDurationSchema = number2().int().min(1).max(1440);
22748
22793
  var createRoutineInputSchema = createInsertSchema(routines, {
22749
22794
  id: ulidSchema,
22795
+ durationMinutes: routineDurationSchema.nullish(),
22750
22796
  areaId: ulidSchema.nullish()
22751
22797
  }).omit({ tenantId: true, recurrenceRuleId: true }).extend({
22752
22798
  title: string2().min(1),
@@ -22765,7 +22811,8 @@ var createRoutineInputSchema = createInsertSchema(routines, {
22765
22811
  }
22766
22812
  });
22767
22813
  var updateRoutineInputSchema = createUpdateSchema(routines, {
22768
- areaId: ulidSchema.nullish()
22814
+ areaId: ulidSchema.nullish(),
22815
+ durationMinutes: routineDurationSchema.nullish()
22769
22816
  }).omit({ id: true, tenantId: true, recurrenceRuleId: true }).extend({
22770
22817
  title: string2().min(1).optional(),
22771
22818
  parentId: ulidSchema.nullish(),
@@ -22777,6 +22824,7 @@ var routineViewSchema = routineSchema.extend({
22777
22824
  icon: string2().nullable().default(null),
22778
22825
  keptNotice: string2().nullable().default(null),
22779
22826
  dayTimes: routineDayTimesSchema.default({}),
22827
+ durationMinutes: number2().int().nullish(),
22780
22828
  title: string2(),
22781
22829
  parentId: ulidSchema.nullable(),
22782
22830
  createdAt: exports_coerce.date(),
@@ -24151,6 +24199,7 @@ var timeBlocks = pgTable("time_blocks", {
24151
24199
  taskId: text("task_id").references(() => tasks.id, { onDelete: "set null" }),
24152
24200
  kind: text("kind", { enum: TIME_BLOCK_KINDS }).notNull().default("focus"),
24153
24201
  lifeKind: text("life_kind", { enum: LIFE_BLOCK_KINDS }),
24202
+ label: text("label"),
24154
24203
  plannedStartAt: timestamp("planned_start_at", { withTimezone: true }),
24155
24204
  plannedEndAt: timestamp("planned_end_at", { withTimezone: true }),
24156
24205
  recurrenceRuleId: text("recurrence_rule_id").references(() => recurrenceRules.id),
@@ -24221,6 +24270,7 @@ var blockEvidence = pgTable("block_evidence", {
24221
24270
  // ../../packages/schema/src/contracts/time-blocks.ts
24222
24271
  var TIME_BLOCK_MAX_MINUTES = 24 * 60;
24223
24272
  var timeBlockSchema = createSelectSchema(timeBlocks, {
24273
+ label: string2().nullish(),
24224
24274
  startAt: exports_coerce.date(),
24225
24275
  endAt: exports_coerce.date(),
24226
24276
  plannedStartAt: exports_coerce.date().nullable(),
@@ -24239,12 +24289,14 @@ var lifeBlockKindSchema = _enum2(LIFE_BLOCK_KINDS);
24239
24289
  var lifeBlockShareSchema = _enum2(["details", "busy"]);
24240
24290
  var lifeBlockSharingSchema = partialRecord(lifeBlockKindSchema, lifeBlockShareSchema);
24241
24291
  var SPAN_MESSAGE = `endAt must be after startAt and at most ${TIME_BLOCK_MAX_MINUTES / 60} hours later`;
24292
+ var blockLabelSchema = string2().trim().min(1).max(200);
24242
24293
  var createTimeBlockInputSchema = object({
24243
24294
  id: ulidSchema,
24244
24295
  title: string2().trim().min(1).max(500).optional(),
24245
24296
  taskId: ulidSchema.nullish(),
24246
24297
  lifeKind: lifeBlockKindSchema.optional(),
24247
24298
  routineId: ulidSchema.nullish(),
24299
+ label: blockLabelSchema.nullish(),
24248
24300
  recorded: boolean2().optional(),
24249
24301
  startAt: exports_coerce.date(),
24250
24302
  endAt: exports_coerce.date()
@@ -24266,6 +24318,7 @@ var updateTimeBlockInputSchema = object({
24266
24318
  taskId: ulidSchema.nullish(),
24267
24319
  lifeKind: lifeBlockKindSchema.optional(),
24268
24320
  routineId: ulidSchema.nullish(),
24321
+ label: blockLabelSchema.nullish(),
24269
24322
  startAt: exports_coerce.date().optional(),
24270
24323
  endAt: exports_coerce.date().optional()
24271
24324
  }).strict().refine(validSpan, { message: SPAN_MESSAGE, path: ["endAt"] });
@@ -24285,6 +24338,7 @@ var timeBlockViewSchema = timeBlockSchema.omit({
24285
24338
  recordAskedAt: true
24286
24339
  }).extend({
24287
24340
  title: string2(),
24341
+ label: string2().nullish(),
24288
24342
  task: timeBlockTaskSchema.nullable(),
24289
24343
  status: _enum2(TIME_BLOCK_STATUSES).optional(),
24290
24344
  recordState: _enum2(RECORD_STATES).optional(),
@@ -27253,6 +27307,11 @@ var answerEchoPromptInputSchema = object({
27253
27307
  text: string2().trim().min(1).max(2000).optional(),
27254
27308
  device: echoDeviceSchema.optional()
27255
27309
  }).strict();
27310
+ var echoPostContextSchema = object({
27311
+ route: string2(),
27312
+ nodeId: string2().nullable(),
27313
+ page: string2().optional()
27314
+ });
27256
27315
  var echoPostSchema = object({
27257
27316
  id: string2(),
27258
27317
  threadId: string2(),
@@ -27274,15 +27333,43 @@ var echoPostSchema = object({
27274
27333
  receipt: postReceiptSchema.nullable().default(null),
27275
27334
  createdAt: exports_coerce.date(),
27276
27335
  updatedAt: exports_coerce.date(),
27277
- brief: briefSchema.nullable().default(null)
27336
+ brief: briefSchema.nullable().default(null),
27337
+ card: postCardSchema.nullable().default(null),
27338
+ context: echoPostContextSchema.nullable().default(null)
27278
27339
  });
27279
27340
  var threadPushSchema = _enum2(["needs_you", "all", "off"]);
27341
+ var threadKindSchema = _enum2([
27342
+ "personal",
27343
+ "work",
27344
+ "system",
27345
+ "client",
27346
+ "object",
27347
+ "shared"
27348
+ ]);
27349
+ var threadTopicKindSchema = threadKindSchema.extract([
27350
+ "personal",
27351
+ "work",
27352
+ "system",
27353
+ "client"
27354
+ ]);
27355
+ var threadAnchorTypeSchema = _enum2(["task", "project", "habit", "note"]);
27356
+ var threadAnchorSchema = object({ type: threadAnchorTypeSchema, id: string2() });
27357
+ var threadNotifyLevelSchema = _enum2(["now", "today", "digest", "off"]);
27358
+ var threadMemoryScopeSchema = _enum2(["personal", "work", "none", "isolated", "inherit"]);
27359
+ var threadIconSchema = string2().regex(/^[a-z][a-z0-9-]{0,23}$/, "an icon is a lowercase icon name");
27360
+ var ECHO_THREAD_DESCRIPTION_MAX = 200;
27361
+ var threadDescriptionSchema = string2().trim().max(ECHO_THREAD_DESCRIPTION_MAX);
27280
27362
  var echoBriefCardSchema = echoPostSchema.extend({
27281
27363
  brief: briefSchema,
27282
27364
  threadTitle: string2().nullable(),
27283
27365
  threadSlug: string2().nullable()
27284
27366
  });
27285
27367
  var echoBriefsQuerySchema = object({ since: exports_coerce.date() });
27368
+ var echoNeedSchema = echoPostSchema.extend({
27369
+ threadTitle: string2().nullable(),
27370
+ threadSlug: string2().nullable()
27371
+ });
27372
+ var echoNeedsSchema = object({ needs: array(echoNeedSchema) });
27286
27373
  var echoBriefsSchema = object({ briefs: array(echoBriefCardSchema) });
27287
27374
  var echoRunSchema = echoPostSchema.extend({
27288
27375
  threadTitle: string2().nullable()
@@ -27297,6 +27384,17 @@ var echoThreadSummarySchema = object({
27297
27384
  home: boolean2().default(false),
27298
27385
  areaIds: array(string2()).default([]),
27299
27386
  peopleCapture: boolean2().default(true),
27387
+ kind: threadKindSchema.default("personal"),
27388
+ anchor: threadAnchorSchema.nullable().default(null),
27389
+ parentId: string2().nullable().default(null),
27390
+ icon: string2().default("lock"),
27391
+ description: string2().nullable().default(null),
27392
+ memoryScope: threadMemoryScopeSchema.default("personal"),
27393
+ notifyLevel: threadNotifyLevelSchema.default("now"),
27394
+ lastMessageAt: exports_coerce.date().nullable().default(null),
27395
+ lastLine: string2().nullable().default(null),
27396
+ needsYou: number2().int().nonnegative().default(0),
27397
+ unseen: number2().int().nonnegative().default(0),
27300
27398
  turnCount: number2().int(),
27301
27399
  postCount: number2().int().default(0),
27302
27400
  createdAt: exports_coerce.date(),
@@ -27333,17 +27431,30 @@ var threadAreaIdsSchema = array(string2().min(1)).max(ECHO_THREAD_AREAS_MAX);
27333
27431
  var createStandingThreadInputSchema = object({
27334
27432
  title: threadTitleSchema,
27335
27433
  slug: threadSlugSchema.optional(),
27336
- areaIds: threadAreaIdsSchema.default([])
27434
+ areaIds: threadAreaIdsSchema.default([]),
27435
+ kind: threadTopicKindSchema.optional(),
27436
+ icon: threadIconSchema.optional(),
27437
+ description: threadDescriptionSchema.optional(),
27438
+ memoryScope: threadMemoryScopeSchema.exclude(["inherit"]).optional()
27337
27439
  }).strict();
27338
27440
  var updateEchoThreadInputSchema = object({
27339
27441
  push: threadPushSchema.optional(),
27340
27442
  title: threadTitleSchema.optional(),
27341
27443
  areaIds: threadAreaIdsSchema.optional(),
27342
27444
  archived: boolean2().optional(),
27343
- peopleCapture: boolean2().optional()
27445
+ peopleCapture: boolean2().optional(),
27446
+ kind: threadTopicKindSchema.optional(),
27447
+ icon: threadIconSchema.optional(),
27448
+ description: threadDescriptionSchema.optional(),
27449
+ memoryScope: threadMemoryScopeSchema.optional()
27344
27450
  }).strict().refine((e) => Object.values(e).some((v) => v !== undefined), {
27345
- message: "send push, title, areaIds, archived or peopleCapture"
27451
+ message: "send push, title, areaIds, archived, peopleCapture, kind, icon, description or memoryScope"
27346
27452
  });
27453
+ var createEchoThreadInputSchema = object({
27454
+ title: threadTitleSchema.optional(),
27455
+ anchor: threadAnchorSchema.optional(),
27456
+ parentId: string2().trim().min(1).max(64).optional()
27457
+ }).strict();
27347
27458
 
27348
27459
  // ../../packages/schema/src/operations/echo-threads.ts
27349
27460
  var NO_USER = "The key has no user identity (threads are per member).";
@@ -27354,7 +27465,7 @@ var echoThreadOperations = defineOperations({
27354
27465
  scopes: ["agents:read"],
27355
27466
  tag: "Agents",
27356
27467
  summary: "List agent threads",
27357
- description: "The member's most recent agent threads, newest first: `id`, `title` (the first question), `turnCount`, `createdAt`, `updatedAt`.",
27468
+ description: "The member's most recent agent threads, newest first: `id`, `title` (the first question), `turnCount`, `createdAt`, `updatedAt`. Each also says what it is for (`kind`: `personal`, `work`, `system`, `client`, `object` or `shared`), the do object it hangs on (`anchor`: `{ type, id }`, null for a topic) and the thread it started from (`parentId`), its `icon`, `description` and `memoryScope` (`personal`, `work`, `none`, `isolated`, `inherit`), the most its posts may push in do v2 (`notifyLevel`: `now`, `today`, `digest` or `off`), when its last message was written (`lastMessageAt`) with that message as one plain line (`lastLine`), and how many of the agent's posts there are unseen (`needsYou` for Needs you, `unseen` for any that isn't silent).",
27358
27469
  query: [
27359
27470
  {
27360
27471
  name: "limit",
@@ -27375,7 +27486,9 @@ var echoThreadOperations = defineOperations({
27375
27486
  scopes: ["agents:write"],
27376
27487
  tag: "Agents",
27377
27488
  summary: "Start a new agent thread",
27378
- description: "New conversation: a fresh thread that becomes the member's current one. When the current thread has nothing in it yet, that one is returned instead.",
27489
+ description: "New conversation: a fresh thread that becomes the member's current one. When the current thread has nothing in it yet, that one is returned instead. With a body, a new thread (do v2): loose with a `title`, or on a thing of the Space (`anchor`: `{ type: task|project|habit|note, id }`, a 404 when there is no such live thing; titled after it unless a `title` is given), started from one of the member's threads (`parentId`, else a 404). A thing has one thread per member: asking again returns it.",
27490
+ body: createEchoThreadInputSchema,
27491
+ bodyOptional: true,
27379
27492
  status: 201,
27380
27493
  response: { description: "The new current thread." },
27381
27494
  errors: { 403: NO_USER }
@@ -27428,7 +27541,7 @@ var echoThreadOperations = defineOperations({
27428
27541
  scopes: ["agents:write"],
27429
27542
  tag: "Agents",
27430
27543
  summary: "Change an agent thread",
27431
- description: "What the agent's posts in this thread may push to the member's devices (do-4): `all` (Needs you, and Told quietly), `needs_you` (only what waits on the member) or `off`. For later and Silent posts never push. Returns the thread as the list shows it. Another member's thread is a 404. Rename a thread (`title`), change the Areas a standing thread links (`areaIds`), or archive it (`archived: true`; `false` brings it back). An archived thread leaves the list and its slug no longer reaches it. The home thread (named after the Space's agent) can't be archived.",
27544
+ description: "What the agent's posts in this thread may push to the member's devices (do-4): `all` (Needs you, and Told quietly), `needs_you` (only what waits on the member) or `off`. For later and Silent posts never push. Returns the thread as the list shows it. Another member's thread is a 404. Rename a thread (`title`), change the Areas a standing thread links (`areaIds`), or archive it (`archived: true`; `false` brings it back). An archived thread leaves the list and its slug no longer reaches it. The home thread (named after the Space's agent) can't be archived. Say what a topic is for (`kind`: `personal`, `work`, `system` or `client`); a thread on a thing keeps `object`, a 400. Set its `icon`, its one-line `description` (`\"\"` clears it) and which memory the agent answers with (`memoryScope`: `personal`, `work`, `none`, `isolated` or `inherit`).",
27432
27545
  body: updateEchoThreadInputSchema,
27433
27546
  status: 200,
27434
27547
  response: { description: "The thread as the list shows it, with its `push`." },
@@ -27440,7 +27553,7 @@ var echoThreadOperations = defineOperations({
27440
27553
  scopes: ["agents:write"],
27441
27554
  tag: "Agents",
27442
27555
  summary: "Add a standing thread",
27443
- description: "A standing thread of the member's own (Build, Business), pinned under the agent's home thread. `slug` is what the agent and scripts address it by (`do echo post --thread build`); it defaults to one made from the title. A slug another live thread has is a 409; an archived thread's brings that thread back.",
27556
+ description: "A standing thread of the member's own (Build, Business), pinned under the agent's home thread. `slug` is what the agent and scripts address it by (`do echo post --thread build`); it defaults to one made from the title. `kind` says what it is for (`personal`, `work`, `system` or `client`; `work` when not given), with an `icon` (a v2 icon name), a one-line `description` and its `memoryScope` (`personal`, `work`, `none` or `isolated`). A slug another live thread has is a 409; an archived thread's brings that thread back.",
27444
27557
  body: createStandingThreadInputSchema,
27445
27558
  status: 201,
27446
27559
  response: { description: "The standing thread." },
@@ -43715,13 +43828,15 @@ async function agentPost({
43715
43828
  }
43716
43829
  const text = await postText(io, args);
43717
43830
  const brief = flagString(flags, "brief") === undefined ? undefined : readDataFlag(flags, "brief");
43831
+ const card = flagString(flags, "card") === undefined ? undefined : readDataFlag(flags, "card");
43718
43832
  const edit = flagString(flags, "edit");
43719
43833
  if (edit !== undefined) {
43720
43834
  const body = parseInput(agentPostEditSchema, {
43721
43835
  text,
43722
43836
  ...flagBool(flags, "draft") ? { final: false } : {},
43723
43837
  level: flagString(flags, "level"),
43724
- brief
43838
+ brief,
43839
+ card
43725
43840
  });
43726
43841
  return {
43727
43842
  data: await client.patch(pathOf(agentPostOperations.edit, { postId: edit }), body),
@@ -43734,10 +43849,11 @@ async function agentPost({
43734
43849
  externalId: flagString(flags, "external-id") ?? `cli:${ulid3()}`,
43735
43850
  thread: ULID.test(thread) ? { id: thread.toUpperCase() } : { slug: thread, ...member ? { memberId: member } : {} },
43736
43851
  text,
43737
- kind: flagString(flags, "kind") ?? (brief ? "brief" : undefined),
43852
+ kind: flagString(flags, "kind") ?? (brief ? "brief" : card ? "card" : undefined),
43738
43853
  level: flagString(flags, "level"),
43739
43854
  final: !flagBool(flags, "draft"),
43740
- brief
43855
+ brief,
43856
+ card
43741
43857
  });
43742
43858
  return { data: await client.post(pathOf(agentPostOperations.post), body), render: renderRecord };
43743
43859
  }
@@ -44445,6 +44561,11 @@ var commands = [
44445
44561
  type: "string",
44446
44562
  description: `A brief's sections as JSON: {"label":"HQ brief","title":"\u2026","rows":[{"text":"\u2026","meta":"\u2026","icon":"tasks","verb":{"label":"Start","href":"/tasks"}}]} (a verb has href or say). Makes the post a brief; shows as a card on Now until the day ends.`
44447
44563
  },
44564
+ {
44565
+ name: "card",
44566
+ type: "string",
44567
+ description: `A typed card as JSON: {"type":"pr","data":{\u2026}} (do v2's Echo draws it by type, else the text). Makes the post a card; the same --external-id changes it in place.`
44568
+ },
44448
44569
  { name: "edit", type: "string", description: "Edit this post (its id) instead: its text." },
44449
44570
  { name: "delete", type: "string", description: "Take this post (its id) back." }
44450
44571
  ],
@@ -47680,11 +47801,16 @@ async function echoThreadAdd({ args, flags, requireClient }) {
47680
47801
  throw usageError("missing required argument: <title>");
47681
47802
  const slug = flagString(flags, "slug");
47682
47803
  const areas = flagString(flags, "areas");
47804
+ const kind = flagString(flags, "kind");
47805
+ if (kind !== undefined)
47806
+ topicKind(kind);
47683
47807
  return {
47684
47808
  data: await requireClient().post(pathOf(echoThreadOperations.addStanding), {
47685
47809
  title,
47686
47810
  ...slug ? { slug } : {},
47687
- ...areas === undefined ? {} : { areaIds: splitList(areas) }
47811
+ ...areas === undefined ? {} : { areaIds: splitList(areas) },
47812
+ ...kind ? { kind } : {},
47813
+ ...aboutOf(flags)
47688
47814
  }),
47689
47815
  render: renderEchoThread
47690
47816
  };
@@ -47700,6 +47826,44 @@ async function echoThreadId(client, ref) {
47700
47826
  throw usageError(`no thread \`${ref}\` (see \`do echo threads list\`)`);
47701
47827
  return found.id;
47702
47828
  }
47829
+ var TOPIC_KINDS = ["personal", "work", "system", "client"];
47830
+ function topicKind(value) {
47831
+ if (!TOPIC_KINDS.includes(value)) {
47832
+ throw usageError(`kind is one of ${TOPIC_KINDS.join(", ")}`);
47833
+ }
47834
+ return value;
47835
+ }
47836
+ function anchorOf(value) {
47837
+ const [type, id] = value.split(":");
47838
+ if (!type || !id || !["task", "project", "habit", "note"].includes(type)) {
47839
+ throw usageError("--on is type:id, the type one of task, project, habit, note");
47840
+ }
47841
+ return { type, id };
47842
+ }
47843
+ var KIND_FLAG = {
47844
+ name: "kind",
47845
+ type: "string",
47846
+ description: "What it is for: personal, work (default), system or client."
47847
+ };
47848
+ var ABOUT_FLAGS = [
47849
+ { name: "icon", type: "string", description: "Its icon in the list (`wrench`)." },
47850
+ { name: "about", type: "string", description: "One line on what it is for." },
47851
+ {
47852
+ name: "memory",
47853
+ type: "string",
47854
+ description: "Which memory the agent answers with: personal, work, none or isolated."
47855
+ }
47856
+ ];
47857
+ function aboutOf(flags) {
47858
+ const icon = flagString(flags, "icon");
47859
+ const description = flagString(flags, "about");
47860
+ const memoryScope = flagString(flags, "memory");
47861
+ return {
47862
+ ...icon ? { icon } : {},
47863
+ ...description === undefined ? {} : { description },
47864
+ ...memoryScope ? { memoryScope } : {}
47865
+ };
47866
+ }
47703
47867
  function splitList(value) {
47704
47868
  return value.split(",").map((v) => v.trim()).filter((v) => v.length > 0);
47705
47869
  }
@@ -47743,6 +47907,11 @@ var commands16 = [
47743
47907
  type: "string",
47744
47908
  description: `A brief's sections as JSON: {"label":"HQ brief","title":"\u2026","rows":[{"text":"\u2026","meta":"\u2026","icon":"tasks","verb":{"label":"Start","href":"/tasks"}}]} (a verb has href or say). Makes the post a brief; shows as a card on Now until the day ends.`
47745
47909
  },
47910
+ {
47911
+ name: "card",
47912
+ type: "string",
47913
+ description: `A typed card as JSON: {"type":"pr","data":{\u2026}} (do v2's Echo draws it by type, else the text). Makes the post a card; the same --external-id changes it in place.`
47914
+ },
47746
47915
  { name: "edit", type: "string", description: "Edit this post (its id) instead: its text." },
47747
47916
  { name: "delete", type: "string", description: "Take this post (its id) back." }
47748
47917
  ],
@@ -47801,15 +47970,37 @@ var commands16 = [
47801
47970
  path: ["echo", "threads", "new"],
47802
47971
  summary: "Start a new agent conversation (it becomes the current thread).",
47803
47972
  args: [],
47804
- flags: [],
47973
+ flags: [
47974
+ { name: "title", type: "string", description: "Its name: a loose thread (do v2)." },
47975
+ {
47976
+ name: "on",
47977
+ type: "string",
47978
+ description: "A thing it hangs on, as type:id (task:01J\u2026, project, habit or note)."
47979
+ },
47980
+ {
47981
+ name: "from",
47982
+ type: "string",
47983
+ description: "The thread it starts from (id or slug): a thread on a thing takes its memory."
47984
+ }
47985
+ ],
47805
47986
  scopes: [...echoThreadOperations.create.scopes],
47806
47987
  returns: "EchoThread",
47807
- notes: "When the current thread is still empty, that one is returned instead."
47988
+ notes: "Without flags: when the current thread is still empty, that one is returned instead. A thing has one thread per member: --on again returns it."
47808
47989
  },
47809
- run: async ({ requireClient }) => ({
47810
- data: await requireClient().post(pathOf(echoThreadOperations.create), {}),
47811
- render: renderEchoThread
47812
- })
47990
+ run: async ({ flags, requireClient }) => {
47991
+ const client = requireClient();
47992
+ const title = flagString(flags, "title");
47993
+ const on = flagString(flags, "on");
47994
+ const from = flagString(flags, "from");
47995
+ return {
47996
+ data: await client.post(pathOf(echoThreadOperations.create), {
47997
+ ...title ? { title } : {},
47998
+ ...on === undefined ? {} : { anchor: anchorOf(on) },
47999
+ ...from ? { parentId: await echoThreadId(client, from) } : {}
48000
+ }),
48001
+ render: renderEchoThread
48002
+ };
48003
+ }
47813
48004
  },
47814
48005
  {
47815
48006
  spec: {
@@ -47899,7 +48090,9 @@ var commands16 = [
47899
48090
  type: "string",
47900
48091
  description: "What the agent and scripts address it by (default: from the title)."
47901
48092
  },
47902
- { name: "areas", type: "string", description: "Area ids it covers, comma-separated." }
48093
+ { name: "areas", type: "string", description: "Area ids it covers, comma-separated." },
48094
+ KIND_FLAG,
48095
+ ...ABOUT_FLAGS
47903
48096
  ],
47904
48097
  scopes: [...echoThreadOperations.addStanding.scopes],
47905
48098
  returns: "EchoThread",
@@ -47918,7 +48111,9 @@ var commands16 = [
47918
48111
  type: "string",
47919
48112
  description: "What the agent and scripts address it by (default: from the title)."
47920
48113
  },
47921
- { name: "areas", type: "string", description: "Area ids it covers, comma-separated." }
48114
+ { name: "areas", type: "string", description: "Area ids it covers, comma-separated." },
48115
+ KIND_FLAG,
48116
+ ...ABOUT_FLAGS
47922
48117
  ],
47923
48118
  scopes: [...echoThreadOperations.addStanding.scopes],
47924
48119
  returns: "EchoThread"
@@ -47949,6 +48144,29 @@ var commands16 = [
47949
48144
  };
47950
48145
  }
47951
48146
  },
48147
+ {
48148
+ spec: {
48149
+ path: ["echo", "threads", "kind"],
48150
+ summary: "Say what one of your agent topics is for: personal, work, system or client.",
48151
+ args: [
48152
+ { name: "thread", required: true, description: "Its id, or a standing thread's slug." },
48153
+ { name: "kind", required: true, description: "personal, work, system or client." }
48154
+ ],
48155
+ flags: [],
48156
+ scopes: [...echoThreadOperations.update.scopes],
48157
+ returns: "EchoThreadSummary",
48158
+ notes: "A thread on a thing (a task, a project) keeps its kind, `object`: a 400."
48159
+ },
48160
+ run: async ({ args, requireClient }) => {
48161
+ const client = requireClient();
48162
+ const id = await echoThreadId(client, requireArg(args, 0, "thread"));
48163
+ const kind = topicKind(requireArg(args, 1, "kind"));
48164
+ return {
48165
+ data: await client.patch(pathOf(echoThreadOperations.update, { id }), { kind }),
48166
+ render: renderRecord
48167
+ };
48168
+ }
48169
+ },
47952
48170
  {
47953
48171
  spec: {
47954
48172
  path: ["echo", "threads", "link"],
@@ -51698,7 +51916,7 @@ function renderLogged(data, mode) {
51698
51916
  return rows.map((e) => `${e.at} ${e.what} ${paint(mode, "dim", e.where)}`).join(`
51699
51917
  `);
51700
51918
  }
51701
- var KIND_FLAG = {
51919
+ var KIND_FLAG2 = {
51702
51920
  name: "kind",
51703
51921
  type: "string",
51704
51922
  description: "The kind of an unknown word (pages, eggs, health, note, or a word taught before); remembered for the Space."
@@ -51711,7 +51929,7 @@ var commands28 = [
51711
51929
  args: [{ name: "line", required: true, description: 'The line, e.g. "pages 34".' }],
51712
51930
  flags: [
51713
51931
  { name: "dry-run", type: "boolean", description: "Preview only; write nothing." },
51714
- KIND_FLAG,
51932
+ KIND_FLAG2,
51715
51933
  {
51716
51934
  name: "destination",
51717
51935
  type: "string",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robbeverhelst/do",
3
- "version": "1.365.0",
3
+ "version": "1.366.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",