@robbeverhelst/do 1.364.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 +248 -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.364.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()
@@ -21640,7 +21683,9 @@ var habitDueDateSchema = object({
21640
21683
  time: string2().regex(/^\d{2}:\d{2}$/).nullable(),
21641
21684
  scheduleLabel: string2().min(1),
21642
21685
  daily: boolean2(),
21643
- streakLabel: string2().min(1)
21686
+ streakLabel: string2().min(1),
21687
+ done: boolean2().default(false),
21688
+ entryId: string2().nullable().default(null)
21644
21689
  });
21645
21690
  var habitEntriesQuerySchema = object({
21646
21691
  before: exports_coerce.date().optional(),
@@ -22654,7 +22699,7 @@ var projectDetailSchema = projectViewSchema.extend({
22654
22699
  var attachTaskInputSchema = object({ taskId: ulidSchema });
22655
22700
 
22656
22701
  // ../../packages/schema/src/contracts/routines.ts
22657
- 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;
22658
22703
  var routineSchema = createSelectSchema(routines);
22659
22704
  var routineStepSchema = createSelectSchema(routineSteps, {
22660
22705
  createdAt: exports_coerce.date(),
@@ -22744,8 +22789,10 @@ var routineStepInputSchema = object({
22744
22789
  }
22745
22790
  }
22746
22791
  });
22792
+ var routineDurationSchema = number2().int().min(1).max(1440);
22747
22793
  var createRoutineInputSchema = createInsertSchema(routines, {
22748
22794
  id: ulidSchema,
22795
+ durationMinutes: routineDurationSchema.nullish(),
22749
22796
  areaId: ulidSchema.nullish()
22750
22797
  }).omit({ tenantId: true, recurrenceRuleId: true }).extend({
22751
22798
  title: string2().min(1),
@@ -22764,7 +22811,8 @@ var createRoutineInputSchema = createInsertSchema(routines, {
22764
22811
  }
22765
22812
  });
22766
22813
  var updateRoutineInputSchema = createUpdateSchema(routines, {
22767
- areaId: ulidSchema.nullish()
22814
+ areaId: ulidSchema.nullish(),
22815
+ durationMinutes: routineDurationSchema.nullish()
22768
22816
  }).omit({ id: true, tenantId: true, recurrenceRuleId: true }).extend({
22769
22817
  title: string2().min(1).optional(),
22770
22818
  parentId: ulidSchema.nullish(),
@@ -22776,6 +22824,7 @@ var routineViewSchema = routineSchema.extend({
22776
22824
  icon: string2().nullable().default(null),
22777
22825
  keptNotice: string2().nullable().default(null),
22778
22826
  dayTimes: routineDayTimesSchema.default({}),
22827
+ durationMinutes: number2().int().nullish(),
22779
22828
  title: string2(),
22780
22829
  parentId: ulidSchema.nullable(),
22781
22830
  createdAt: exports_coerce.date(),
@@ -24150,6 +24199,7 @@ var timeBlocks = pgTable("time_blocks", {
24150
24199
  taskId: text("task_id").references(() => tasks.id, { onDelete: "set null" }),
24151
24200
  kind: text("kind", { enum: TIME_BLOCK_KINDS }).notNull().default("focus"),
24152
24201
  lifeKind: text("life_kind", { enum: LIFE_BLOCK_KINDS }),
24202
+ label: text("label"),
24153
24203
  plannedStartAt: timestamp("planned_start_at", { withTimezone: true }),
24154
24204
  plannedEndAt: timestamp("planned_end_at", { withTimezone: true }),
24155
24205
  recurrenceRuleId: text("recurrence_rule_id").references(() => recurrenceRules.id),
@@ -24220,6 +24270,7 @@ var blockEvidence = pgTable("block_evidence", {
24220
24270
  // ../../packages/schema/src/contracts/time-blocks.ts
24221
24271
  var TIME_BLOCK_MAX_MINUTES = 24 * 60;
24222
24272
  var timeBlockSchema = createSelectSchema(timeBlocks, {
24273
+ label: string2().nullish(),
24223
24274
  startAt: exports_coerce.date(),
24224
24275
  endAt: exports_coerce.date(),
24225
24276
  plannedStartAt: exports_coerce.date().nullable(),
@@ -24238,12 +24289,14 @@ var lifeBlockKindSchema = _enum2(LIFE_BLOCK_KINDS);
24238
24289
  var lifeBlockShareSchema = _enum2(["details", "busy"]);
24239
24290
  var lifeBlockSharingSchema = partialRecord(lifeBlockKindSchema, lifeBlockShareSchema);
24240
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);
24241
24293
  var createTimeBlockInputSchema = object({
24242
24294
  id: ulidSchema,
24243
24295
  title: string2().trim().min(1).max(500).optional(),
24244
24296
  taskId: ulidSchema.nullish(),
24245
24297
  lifeKind: lifeBlockKindSchema.optional(),
24246
24298
  routineId: ulidSchema.nullish(),
24299
+ label: blockLabelSchema.nullish(),
24247
24300
  recorded: boolean2().optional(),
24248
24301
  startAt: exports_coerce.date(),
24249
24302
  endAt: exports_coerce.date()
@@ -24265,6 +24318,7 @@ var updateTimeBlockInputSchema = object({
24265
24318
  taskId: ulidSchema.nullish(),
24266
24319
  lifeKind: lifeBlockKindSchema.optional(),
24267
24320
  routineId: ulidSchema.nullish(),
24321
+ label: blockLabelSchema.nullish(),
24268
24322
  startAt: exports_coerce.date().optional(),
24269
24323
  endAt: exports_coerce.date().optional()
24270
24324
  }).strict().refine(validSpan, { message: SPAN_MESSAGE, path: ["endAt"] });
@@ -24284,6 +24338,7 @@ var timeBlockViewSchema = timeBlockSchema.omit({
24284
24338
  recordAskedAt: true
24285
24339
  }).extend({
24286
24340
  title: string2(),
24341
+ label: string2().nullish(),
24287
24342
  task: timeBlockTaskSchema.nullable(),
24288
24343
  status: _enum2(TIME_BLOCK_STATUSES).optional(),
24289
24344
  recordState: _enum2(RECORD_STATES).optional(),
@@ -27252,6 +27307,11 @@ var answerEchoPromptInputSchema = object({
27252
27307
  text: string2().trim().min(1).max(2000).optional(),
27253
27308
  device: echoDeviceSchema.optional()
27254
27309
  }).strict();
27310
+ var echoPostContextSchema = object({
27311
+ route: string2(),
27312
+ nodeId: string2().nullable(),
27313
+ page: string2().optional()
27314
+ });
27255
27315
  var echoPostSchema = object({
27256
27316
  id: string2(),
27257
27317
  threadId: string2(),
@@ -27273,15 +27333,43 @@ var echoPostSchema = object({
27273
27333
  receipt: postReceiptSchema.nullable().default(null),
27274
27334
  createdAt: exports_coerce.date(),
27275
27335
  updatedAt: exports_coerce.date(),
27276
- brief: briefSchema.nullable().default(null)
27336
+ brief: briefSchema.nullable().default(null),
27337
+ card: postCardSchema.nullable().default(null),
27338
+ context: echoPostContextSchema.nullable().default(null)
27277
27339
  });
27278
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);
27279
27362
  var echoBriefCardSchema = echoPostSchema.extend({
27280
27363
  brief: briefSchema,
27281
27364
  threadTitle: string2().nullable(),
27282
27365
  threadSlug: string2().nullable()
27283
27366
  });
27284
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) });
27285
27373
  var echoBriefsSchema = object({ briefs: array(echoBriefCardSchema) });
27286
27374
  var echoRunSchema = echoPostSchema.extend({
27287
27375
  threadTitle: string2().nullable()
@@ -27296,6 +27384,17 @@ var echoThreadSummarySchema = object({
27296
27384
  home: boolean2().default(false),
27297
27385
  areaIds: array(string2()).default([]),
27298
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),
27299
27398
  turnCount: number2().int(),
27300
27399
  postCount: number2().int().default(0),
27301
27400
  createdAt: exports_coerce.date(),
@@ -27332,17 +27431,30 @@ var threadAreaIdsSchema = array(string2().min(1)).max(ECHO_THREAD_AREAS_MAX);
27332
27431
  var createStandingThreadInputSchema = object({
27333
27432
  title: threadTitleSchema,
27334
27433
  slug: threadSlugSchema.optional(),
27335
- 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()
27336
27439
  }).strict();
27337
27440
  var updateEchoThreadInputSchema = object({
27338
27441
  push: threadPushSchema.optional(),
27339
27442
  title: threadTitleSchema.optional(),
27340
27443
  areaIds: threadAreaIdsSchema.optional(),
27341
27444
  archived: boolean2().optional(),
27342
- peopleCapture: boolean2().optional()
27445
+ peopleCapture: boolean2().optional(),
27446
+ kind: threadTopicKindSchema.optional(),
27447
+ icon: threadIconSchema.optional(),
27448
+ description: threadDescriptionSchema.optional(),
27449
+ memoryScope: threadMemoryScopeSchema.optional()
27343
27450
  }).strict().refine((e) => Object.values(e).some((v) => v !== undefined), {
27344
- message: "send push, title, areaIds, archived or peopleCapture"
27451
+ message: "send push, title, areaIds, archived, peopleCapture, kind, icon, description or memoryScope"
27345
27452
  });
27453
+ var createEchoThreadInputSchema = object({
27454
+ title: threadTitleSchema.optional(),
27455
+ anchor: threadAnchorSchema.optional(),
27456
+ parentId: string2().trim().min(1).max(64).optional()
27457
+ }).strict();
27346
27458
 
27347
27459
  // ../../packages/schema/src/operations/echo-threads.ts
27348
27460
  var NO_USER = "The key has no user identity (threads are per member).";
@@ -27353,7 +27465,7 @@ var echoThreadOperations = defineOperations({
27353
27465
  scopes: ["agents:read"],
27354
27466
  tag: "Agents",
27355
27467
  summary: "List agent threads",
27356
- 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).",
27357
27469
  query: [
27358
27470
  {
27359
27471
  name: "limit",
@@ -27374,7 +27486,9 @@ var echoThreadOperations = defineOperations({
27374
27486
  scopes: ["agents:write"],
27375
27487
  tag: "Agents",
27376
27488
  summary: "Start a new agent thread",
27377
- 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,
27378
27492
  status: 201,
27379
27493
  response: { description: "The new current thread." },
27380
27494
  errors: { 403: NO_USER }
@@ -27427,7 +27541,7 @@ var echoThreadOperations = defineOperations({
27427
27541
  scopes: ["agents:write"],
27428
27542
  tag: "Agents",
27429
27543
  summary: "Change an agent thread",
27430
- 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`).",
27431
27545
  body: updateEchoThreadInputSchema,
27432
27546
  status: 200,
27433
27547
  response: { description: "The thread as the list shows it, with its `push`." },
@@ -27439,7 +27553,7 @@ var echoThreadOperations = defineOperations({
27439
27553
  scopes: ["agents:write"],
27440
27554
  tag: "Agents",
27441
27555
  summary: "Add a standing thread",
27442
- 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.",
27443
27557
  body: createStandingThreadInputSchema,
27444
27558
  status: 201,
27445
27559
  response: { description: "The standing thread." },
@@ -43714,13 +43828,15 @@ async function agentPost({
43714
43828
  }
43715
43829
  const text = await postText(io, args);
43716
43830
  const brief = flagString(flags, "brief") === undefined ? undefined : readDataFlag(flags, "brief");
43831
+ const card = flagString(flags, "card") === undefined ? undefined : readDataFlag(flags, "card");
43717
43832
  const edit = flagString(flags, "edit");
43718
43833
  if (edit !== undefined) {
43719
43834
  const body = parseInput(agentPostEditSchema, {
43720
43835
  text,
43721
43836
  ...flagBool(flags, "draft") ? { final: false } : {},
43722
43837
  level: flagString(flags, "level"),
43723
- brief
43838
+ brief,
43839
+ card
43724
43840
  });
43725
43841
  return {
43726
43842
  data: await client.patch(pathOf(agentPostOperations.edit, { postId: edit }), body),
@@ -43733,10 +43849,11 @@ async function agentPost({
43733
43849
  externalId: flagString(flags, "external-id") ?? `cli:${ulid3()}`,
43734
43850
  thread: ULID.test(thread) ? { id: thread.toUpperCase() } : { slug: thread, ...member ? { memberId: member } : {} },
43735
43851
  text,
43736
- kind: flagString(flags, "kind") ?? (brief ? "brief" : undefined),
43852
+ kind: flagString(flags, "kind") ?? (brief ? "brief" : card ? "card" : undefined),
43737
43853
  level: flagString(flags, "level"),
43738
43854
  final: !flagBool(flags, "draft"),
43739
- brief
43855
+ brief,
43856
+ card
43740
43857
  });
43741
43858
  return { data: await client.post(pathOf(agentPostOperations.post), body), render: renderRecord };
43742
43859
  }
@@ -44444,6 +44561,11 @@ var commands = [
44444
44561
  type: "string",
44445
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.`
44446
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
+ },
44447
44569
  { name: "edit", type: "string", description: "Edit this post (its id) instead: its text." },
44448
44570
  { name: "delete", type: "string", description: "Take this post (its id) back." }
44449
44571
  ],
@@ -47679,11 +47801,16 @@ async function echoThreadAdd({ args, flags, requireClient }) {
47679
47801
  throw usageError("missing required argument: <title>");
47680
47802
  const slug = flagString(flags, "slug");
47681
47803
  const areas = flagString(flags, "areas");
47804
+ const kind = flagString(flags, "kind");
47805
+ if (kind !== undefined)
47806
+ topicKind(kind);
47682
47807
  return {
47683
47808
  data: await requireClient().post(pathOf(echoThreadOperations.addStanding), {
47684
47809
  title,
47685
47810
  ...slug ? { slug } : {},
47686
- ...areas === undefined ? {} : { areaIds: splitList(areas) }
47811
+ ...areas === undefined ? {} : { areaIds: splitList(areas) },
47812
+ ...kind ? { kind } : {},
47813
+ ...aboutOf(flags)
47687
47814
  }),
47688
47815
  render: renderEchoThread
47689
47816
  };
@@ -47699,6 +47826,44 @@ async function echoThreadId(client, ref) {
47699
47826
  throw usageError(`no thread \`${ref}\` (see \`do echo threads list\`)`);
47700
47827
  return found.id;
47701
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
+ }
47702
47867
  function splitList(value) {
47703
47868
  return value.split(",").map((v) => v.trim()).filter((v) => v.length > 0);
47704
47869
  }
@@ -47742,6 +47907,11 @@ var commands16 = [
47742
47907
  type: "string",
47743
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.`
47744
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
+ },
47745
47915
  { name: "edit", type: "string", description: "Edit this post (its id) instead: its text." },
47746
47916
  { name: "delete", type: "string", description: "Take this post (its id) back." }
47747
47917
  ],
@@ -47800,15 +47970,37 @@ var commands16 = [
47800
47970
  path: ["echo", "threads", "new"],
47801
47971
  summary: "Start a new agent conversation (it becomes the current thread).",
47802
47972
  args: [],
47803
- 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
+ ],
47804
47986
  scopes: [...echoThreadOperations.create.scopes],
47805
47987
  returns: "EchoThread",
47806
- 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."
47807
47989
  },
47808
- run: async ({ requireClient }) => ({
47809
- data: await requireClient().post(pathOf(echoThreadOperations.create), {}),
47810
- render: renderEchoThread
47811
- })
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
+ }
47812
48004
  },
47813
48005
  {
47814
48006
  spec: {
@@ -47898,7 +48090,9 @@ var commands16 = [
47898
48090
  type: "string",
47899
48091
  description: "What the agent and scripts address it by (default: from the title)."
47900
48092
  },
47901
- { 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
47902
48096
  ],
47903
48097
  scopes: [...echoThreadOperations.addStanding.scopes],
47904
48098
  returns: "EchoThread",
@@ -47917,7 +48111,9 @@ var commands16 = [
47917
48111
  type: "string",
47918
48112
  description: "What the agent and scripts address it by (default: from the title)."
47919
48113
  },
47920
- { 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
47921
48117
  ],
47922
48118
  scopes: [...echoThreadOperations.addStanding.scopes],
47923
48119
  returns: "EchoThread"
@@ -47948,6 +48144,29 @@ var commands16 = [
47948
48144
  };
47949
48145
  }
47950
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
+ },
47951
48170
  {
47952
48171
  spec: {
47953
48172
  path: ["echo", "threads", "link"],
@@ -51697,7 +51916,7 @@ function renderLogged(data, mode) {
51697
51916
  return rows.map((e) => `${e.at} ${e.what} ${paint(mode, "dim", e.where)}`).join(`
51698
51917
  `);
51699
51918
  }
51700
- var KIND_FLAG = {
51919
+ var KIND_FLAG2 = {
51701
51920
  name: "kind",
51702
51921
  type: "string",
51703
51922
  description: "The kind of an unknown word (pages, eggs, health, note, or a word taught before); remembered for the Space."
@@ -51710,7 +51929,7 @@ var commands28 = [
51710
51929
  args: [{ name: "line", required: true, description: 'The line, e.g. "pages 34".' }],
51711
51930
  flags: [
51712
51931
  { name: "dry-run", type: "boolean", description: "Preview only; write nothing." },
51713
- KIND_FLAG,
51932
+ KIND_FLAG2,
51714
51933
  {
51715
51934
  name: "destination",
51716
51935
  type: "string",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robbeverhelst/do",
3
- "version": "1.364.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",