@robbeverhelst/do 1.161.0 → 1.162.1
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.
- package/dist/do.js +438 -26
- package/package.json +1 -1
package/dist/do.js
CHANGED
|
@@ -3574,6 +3574,7 @@ var agents = pgTable("agents", {
|
|
|
3574
3574
|
tenantId: text("tenant_id").notNull().references(() => tenants.id),
|
|
3575
3575
|
name: text("name").notNull(),
|
|
3576
3576
|
revokedAt: timestamp("revoked_at", { withTimezone: true }),
|
|
3577
|
+
trustedDesks: text("trusted_desks").array().notNull().default([]),
|
|
3577
3578
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
3578
3579
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
3579
3580
|
}, (t) => [
|
|
@@ -3599,8 +3600,13 @@ var areas = pgTable("areas", {
|
|
|
3599
3600
|
color: areaColor("color").notNull().default("teal"),
|
|
3600
3601
|
icon: text("icon"),
|
|
3601
3602
|
reviewCadence: reviewCadence("review_cadence"),
|
|
3602
|
-
archivedAt: timestamp("archived_at", { withTimezone: true })
|
|
3603
|
-
|
|
3603
|
+
archivedAt: timestamp("archived_at", { withTimezone: true }),
|
|
3604
|
+
purpose: text("purpose"),
|
|
3605
|
+
standards: jsonb("standards").$type().notNull().default(sql`'[]'::jsonb`)
|
|
3606
|
+
}, (t) => [
|
|
3607
|
+
index("areas_tenant_idx").on(t.tenantId),
|
|
3608
|
+
check("areas_standards_chk", sql`jsonb_typeof(${t.standards}) = 'array' AND jsonb_array_length(${t.standards}) <= 5`)
|
|
3609
|
+
]);
|
|
3604
3610
|
|
|
3605
3611
|
// ../../packages/schema/src/db/core.ts
|
|
3606
3612
|
var routineKind = pgEnum("routine_kind", ["sequence", "time_blocked", "checklist"]);
|
|
@@ -3796,7 +3802,12 @@ var tasks = pgTable("tasks", {
|
|
|
3796
3802
|
completedByUserId: text("completed_by_user_id"),
|
|
3797
3803
|
completedByAgentId: text("completed_by_agent_id"),
|
|
3798
3804
|
placeId: text("place_id").references(() => places.id, { onDelete: "set null" }),
|
|
3799
|
-
filingSuggestion: jsonb("filing_suggestion").$type()
|
|
3805
|
+
filingSuggestion: jsonb("filing_suggestion").$type(),
|
|
3806
|
+
proposedAt: timestamp("proposed_at", { withTimezone: true }),
|
|
3807
|
+
proposedDesk: text("proposed_desk"),
|
|
3808
|
+
notNowUntil: timestamp("not_now_until", { withTimezone: true }),
|
|
3809
|
+
readyAt: timestamp("ready_at", { withTimezone: true }),
|
|
3810
|
+
readyNote: text("ready_note")
|
|
3800
3811
|
}, (t) => [
|
|
3801
3812
|
index("tasks_tenant_project_idx").on(t.tenantId, t.projectId),
|
|
3802
3813
|
index("tasks_tenant_place_idx").on(t.tenantId, t.placeId),
|
|
@@ -3811,6 +3822,8 @@ var tasks = pgTable("tasks", {
|
|
|
3811
3822
|
index("tasks_tenant_scheduled_idx").on(t.tenantId, t.scheduledAt),
|
|
3812
3823
|
index("tasks_tenant_due_idx").on(t.tenantId, t.dueAt),
|
|
3813
3824
|
index("tasks_tenant_completed_idx").on(t.tenantId, t.completedAt),
|
|
3825
|
+
index("tasks_tenant_proposed_idx").on(t.tenantId, t.proposedAt).where(sql`${t.proposedAt} IS NOT NULL`),
|
|
3826
|
+
index("tasks_tenant_ready_idx").on(t.tenantId, t.readyAt).where(sql`${t.readyAt} IS NOT NULL`),
|
|
3814
3827
|
check("tasks_area_xor_project_chk", sql`${t.projectId} IS NULL OR ${t.areaId} IS NULL`)
|
|
3815
3828
|
]);
|
|
3816
3829
|
var habits = pgTable("habits", {
|
|
@@ -18173,13 +18186,20 @@ var reflectionKindSchema = _enum2(reflectionKind.enumValues);
|
|
|
18173
18186
|
|
|
18174
18187
|
// ../../packages/schema/src/contracts/agents.ts
|
|
18175
18188
|
var agentSchema = createSelectSchema(agents, {
|
|
18189
|
+
trustedDesks: array(string2()).default([]),
|
|
18176
18190
|
revokedAt: exports_coerce.date().nullable(),
|
|
18177
18191
|
createdAt: exports_coerce.date(),
|
|
18178
18192
|
updatedAt: exports_coerce.date()
|
|
18179
18193
|
});
|
|
18180
18194
|
var agentNameSchema = string2().trim().min(1).max(60);
|
|
18181
18195
|
var createAgentInputSchema = object({ name: agentNameSchema }).strict();
|
|
18182
|
-
var
|
|
18196
|
+
var deskSchema = string2().trim().toLowerCase().regex(/^[a-z0-9][a-z0-9_-]{0,39}$/, "a desk is a lower-case slug like `finance`");
|
|
18197
|
+
var updateAgentInputSchema = object({
|
|
18198
|
+
name: agentNameSchema.optional(),
|
|
18199
|
+
trustedDesks: array(deskSchema).max(40).transform((desks) => [...new Set(desks)]).optional()
|
|
18200
|
+
}).strict().refine((v) => v.name !== undefined || v.trustedDesks !== undefined, {
|
|
18201
|
+
message: "send a name or trustedDesks"
|
|
18202
|
+
});
|
|
18183
18203
|
var actorKindSchema = _enum2(["member", "agent"]);
|
|
18184
18204
|
var actorRefSchema = object({
|
|
18185
18205
|
kind: actorKindSchema,
|
|
@@ -18342,9 +18362,13 @@ var taskSchema = createSelectSchema(tasks, {
|
|
|
18342
18362
|
startAt: exports_coerce.date().nullable(),
|
|
18343
18363
|
dueAt: exports_coerce.date().nullable(),
|
|
18344
18364
|
completedAt: exports_coerce.date().nullable().default(null),
|
|
18345
|
-
placeId: string2().nullable().default(null)
|
|
18365
|
+
placeId: string2().nullable().default(null),
|
|
18366
|
+
proposedAt: exports_coerce.date().nullable().default(null),
|
|
18367
|
+
proposedDesk: string2().nullable().default(null),
|
|
18368
|
+
notNowUntil: exports_coerce.date().nullable().default(null),
|
|
18369
|
+
readyAt: exports_coerce.date().nullable().default(null),
|
|
18370
|
+
readyNote: string2().nullable().default(null)
|
|
18346
18371
|
});
|
|
18347
|
-
var deskSchema = string2().trim().toLowerCase().regex(/^[a-z0-9][a-z0-9_-]{0,39}$/, "a desk is a lower-case slug like `finance`");
|
|
18348
18372
|
var PARTY_RE = /^(?:(me)|(member|agent):([^/]+?))(?:\/(.+))?$/;
|
|
18349
18373
|
function partySchema(allowDesk) {
|
|
18350
18374
|
return string2().trim().min(1).max(200).transform((raw, ctx) => {
|
|
@@ -18439,7 +18463,12 @@ var createTaskInputSchema = createInsertSchema(tasks, {
|
|
|
18439
18463
|
waitingSince: true,
|
|
18440
18464
|
completedByUserId: true,
|
|
18441
18465
|
completedByAgentId: true,
|
|
18442
|
-
filingSuggestion: true
|
|
18466
|
+
filingSuggestion: true,
|
|
18467
|
+
proposedAt: true,
|
|
18468
|
+
proposedDesk: true,
|
|
18469
|
+
notNowUntil: true,
|
|
18470
|
+
readyAt: true,
|
|
18471
|
+
readyNote: true
|
|
18443
18472
|
}).extend({
|
|
18444
18473
|
title: string2().min(1),
|
|
18445
18474
|
parentId: ulidSchema.nullish(),
|
|
@@ -18449,8 +18478,12 @@ var createTaskInputSchema = createInsertSchema(tasks, {
|
|
|
18449
18478
|
owner: taskOwnerInputSchema.nullish(),
|
|
18450
18479
|
waitingOn: taskWaitingOnInputSchema.nullish(),
|
|
18451
18480
|
source: taskSourceSchema.nullish(),
|
|
18452
|
-
nextStep: taskNextStepSchema.nullish()
|
|
18481
|
+
nextStep: taskNextStepSchema.nullish(),
|
|
18482
|
+
proposed: boolean3().optional(),
|
|
18483
|
+
fromDesk: deskSchema.nullish()
|
|
18453
18484
|
});
|
|
18485
|
+
var taskReadyNoteSchema = string2().trim().min(1).max(500);
|
|
18486
|
+
var markTaskReadyInputSchema = object({ note: taskReadyNoteSchema.nullish() }).strict();
|
|
18454
18487
|
var updateTaskInputSchema = createUpdateSchema(tasks, {
|
|
18455
18488
|
completedAt: completedAtInputSchema,
|
|
18456
18489
|
scheduledAt: exports_coerce.date().nullish(),
|
|
@@ -18473,7 +18506,10 @@ var updateTaskInputSchema = createUpdateSchema(tasks, {
|
|
|
18473
18506
|
waitingSince: true,
|
|
18474
18507
|
completedByUserId: true,
|
|
18475
18508
|
completedByAgentId: true,
|
|
18476
|
-
filingSuggestion: true
|
|
18509
|
+
filingSuggestion: true,
|
|
18510
|
+
proposedAt: true,
|
|
18511
|
+
proposedDesk: true,
|
|
18512
|
+
readyAt: true
|
|
18477
18513
|
}).extend({
|
|
18478
18514
|
title: string2().min(1).optional(),
|
|
18479
18515
|
parentId: ulidSchema.nullish(),
|
|
@@ -18482,7 +18518,11 @@ var updateTaskInputSchema = createUpdateSchema(tasks, {
|
|
|
18482
18518
|
owner: taskOwnerInputSchema.nullish(),
|
|
18483
18519
|
waitingOn: taskWaitingOnInputSchema.nullish(),
|
|
18484
18520
|
source: taskSourceSchema.nullish(),
|
|
18485
|
-
nextStep: taskNextStepSchema.nullish()
|
|
18521
|
+
nextStep: taskNextStepSchema.nullish(),
|
|
18522
|
+
proposed: boolean3().optional(),
|
|
18523
|
+
notNowUntil: exports_coerce.date().nullish(),
|
|
18524
|
+
ready: boolean3().optional(),
|
|
18525
|
+
readyNote: taskReadyNoteSchema.nullish()
|
|
18486
18526
|
}).strict();
|
|
18487
18527
|
var taskListFilterSchema = _enum2(["all", "unsorted", "starred"]);
|
|
18488
18528
|
|
|
@@ -19128,15 +19168,50 @@ var attachedNoteViewSchema = object({
|
|
|
19128
19168
|
var setAttachedNoteInputSchema = object({ body: string2().max(ATTACHED_NOTE_BODY_MAX) }).strict();
|
|
19129
19169
|
|
|
19130
19170
|
// ../../packages/schema/src/contracts/areas.ts
|
|
19131
|
-
var
|
|
19171
|
+
var areaPurposeSchema = string2().trim().max(140).transform((v) => v.length === 0 ? null : v);
|
|
19172
|
+
var areaStandardTextSchema = string2().trim().min(1).max(120);
|
|
19173
|
+
var linkedNodeIdSchema = string2().trim().min(1).max(64);
|
|
19174
|
+
var areaStandardLinkSchema = discriminatedUnion("kind", [
|
|
19175
|
+
object({ kind: literal("habit"), id: linkedNodeIdSchema }).strict(),
|
|
19176
|
+
object({ kind: literal("task"), id: linkedNodeIdSchema }).strict(),
|
|
19177
|
+
object({ kind: literal("metric"), key: metricKeySchema }).strict()
|
|
19178
|
+
]);
|
|
19179
|
+
var areaStandardSchema = object({
|
|
19180
|
+
id: string2(),
|
|
19181
|
+
text: string2(),
|
|
19182
|
+
link: areaStandardLinkSchema.nullable().default(null)
|
|
19183
|
+
});
|
|
19184
|
+
var areaStandardInputSchema = object({
|
|
19185
|
+
id: string2().min(1).max(64).optional(),
|
|
19186
|
+
text: areaStandardTextSchema,
|
|
19187
|
+
link: areaStandardLinkSchema.nullish()
|
|
19188
|
+
}).strict();
|
|
19189
|
+
var addAreaStandardInputSchema = object({ text: areaStandardTextSchema, link: areaStandardLinkSchema.nullish() }).strict();
|
|
19190
|
+
var updateAreaStandardInputSchema = object({
|
|
19191
|
+
text: areaStandardTextSchema.optional(),
|
|
19192
|
+
link: areaStandardLinkSchema.nullable().optional()
|
|
19193
|
+
}).strict();
|
|
19194
|
+
var areaStandardStateSchema = _enum2(["holding", "worth_a_look"]);
|
|
19195
|
+
var areaStandardViewSchema = areaStandardSchema.extend({
|
|
19196
|
+
state: areaStandardStateSchema.nullable(),
|
|
19197
|
+
why: string2().nullable(),
|
|
19198
|
+
heldBy: string2().nullable()
|
|
19199
|
+
});
|
|
19200
|
+
var areaSchema = createSelectSchema(areas, {
|
|
19201
|
+
purpose: string2().nullable().default(null),
|
|
19202
|
+
standards: array(areaStandardSchema).default([])
|
|
19203
|
+
});
|
|
19132
19204
|
var areaIconSchema = string2().trim().min(1).max(64);
|
|
19133
19205
|
var createAreaInputSchema = createInsertSchema(areas, {
|
|
19134
19206
|
id: ulidSchema,
|
|
19135
|
-
icon: areaIconSchema.nullish()
|
|
19136
|
-
|
|
19207
|
+
icon: areaIconSchema.nullish(),
|
|
19208
|
+
purpose: areaPurposeSchema.nullish()
|
|
19209
|
+
}).omit({ tenantId: true, archivedAt: true, standards: true }).extend({ title: string2().min(1) });
|
|
19137
19210
|
var updateAreaInputSchema = createUpdateSchema(areas, {
|
|
19138
19211
|
icon: areaIconSchema.nullish(),
|
|
19139
|
-
archivedAt: exports_coerce.date().nullish()
|
|
19212
|
+
archivedAt: exports_coerce.date().nullish(),
|
|
19213
|
+
purpose: areaPurposeSchema.nullish(),
|
|
19214
|
+
standards: array(areaStandardInputSchema).max(5).optional()
|
|
19140
19215
|
}).omit({ id: true, tenantId: true }).extend({ title: string2().min(1).optional() }).strict();
|
|
19141
19216
|
var areaViewSchema = areaSchema.extend({
|
|
19142
19217
|
title: string2(),
|
|
@@ -19147,12 +19222,14 @@ var areaViewSchema = areaSchema.extend({
|
|
|
19147
19222
|
projectCount: number2().int().min(0),
|
|
19148
19223
|
taskCount: number2().int().min(0),
|
|
19149
19224
|
habitCount: number2().int().min(0),
|
|
19150
|
-
routineCount: number2().int().min(0)
|
|
19225
|
+
routineCount: number2().int().min(0),
|
|
19226
|
+
standardsWorthALook: number2().int().min(0).default(0)
|
|
19151
19227
|
});
|
|
19152
19228
|
var areaProjectSchema = projectViewSchema.extend({
|
|
19153
19229
|
tasks: array(taskViewSchema)
|
|
19154
19230
|
});
|
|
19155
19231
|
var areaDetailSchema = areaViewSchema.extend({
|
|
19232
|
+
standards: array(areaStandardViewSchema).default([]),
|
|
19156
19233
|
projects: array(areaProjectSchema),
|
|
19157
19234
|
habits: array(habitSummarySchema),
|
|
19158
19235
|
routines: array(routineViewSchema),
|
|
@@ -19479,7 +19556,7 @@ function setModuleEnabled(enabled, key, on) {
|
|
|
19479
19556
|
var userSettingsSchema = createSelectSchema(userSettings, {
|
|
19480
19557
|
createdAt: exports_coerce.date(),
|
|
19481
19558
|
updatedAt: exports_coerce.date()
|
|
19482
|
-
});
|
|
19559
|
+
}).omit({ autoRollOverdue: true });
|
|
19483
19560
|
var updateUserSettingsInputSchema = createUpdateSchema(userSettings, {
|
|
19484
19561
|
displayName: string2().trim().max(80).nullish(),
|
|
19485
19562
|
avatarUrl: union([string2().url().max(2048), literal("")]).nullish(),
|
|
@@ -19490,9 +19567,15 @@ var updateUserSettingsInputSchema = createUpdateSchema(userSettings, {
|
|
|
19490
19567
|
accent: settingsAccentSchema.optional(),
|
|
19491
19568
|
sunCity: string2().trim().max(80).transform((city) => city === "" ? null : city).nullish(),
|
|
19492
19569
|
backdrop: backdropIdSchema.nullish(),
|
|
19493
|
-
enabledModules: array(string2().trim().min(1)).transform(normalizeEnabledModules).optional()
|
|
19494
|
-
|
|
19495
|
-
|
|
19570
|
+
enabledModules: array(string2().trim().min(1)).transform(normalizeEnabledModules).optional()
|
|
19571
|
+
}).omit({
|
|
19572
|
+
id: true,
|
|
19573
|
+
tenantId: true,
|
|
19574
|
+
userId: true,
|
|
19575
|
+
createdAt: true,
|
|
19576
|
+
updatedAt: true,
|
|
19577
|
+
autoRollOverdue: true
|
|
19578
|
+
}).strict();
|
|
19496
19579
|
|
|
19497
19580
|
// ../../packages/schema/src/contracts/shopping.ts
|
|
19498
19581
|
var shoppingRecurrenceUnitSchema = _enum2(["day", "week", "month"]);
|
|
@@ -19758,7 +19841,8 @@ var timeBlockTaskSchema = object({
|
|
|
19758
19841
|
id: ulidSchema,
|
|
19759
19842
|
title: string2(),
|
|
19760
19843
|
status: string2(),
|
|
19761
|
-
areaId: string2().nullable()
|
|
19844
|
+
areaId: string2().nullable(),
|
|
19845
|
+
projectId: string2().nullable().optional()
|
|
19762
19846
|
});
|
|
19763
19847
|
var timeBlockViewSchema = timeBlockSchema.extend({
|
|
19764
19848
|
title: string2(),
|
|
@@ -20999,7 +21083,7 @@ function parseCapture2(input, now) {
|
|
|
20999
21083
|
|
|
21000
21084
|
// src/meta.ts
|
|
21001
21085
|
var CLI_NAME = "do";
|
|
21002
|
-
var VERSION = "1.
|
|
21086
|
+
var VERSION = "1.162.1";
|
|
21003
21087
|
var API_PREFIX = "/api/v1";
|
|
21004
21088
|
var DEFAULT_API_URL = "http://localhost:3001";
|
|
21005
21089
|
|
|
@@ -21222,7 +21306,7 @@ var ENTITIES = [
|
|
|
21222
21306
|
listFlags: [
|
|
21223
21307
|
{
|
|
21224
21308
|
name: "filter",
|
|
21225
|
-
description: "all (default), unsorted (the
|
|
21309
|
+
description: "all (default), unsorted (the Inbox's tasks to file: no day, Deadline, Area or Project; never a proposal) or starred",
|
|
21226
21310
|
query: "filter"
|
|
21227
21311
|
},
|
|
21228
21312
|
{ ...AREA_FLAG, description: "only tasks in this area id (a project task by its project's)" },
|
|
@@ -21243,7 +21327,17 @@ var ENTITIES = [
|
|
|
21243
21327
|
description: "waiting on: me, member:<id|email>, agent:<id|name>, any or none"
|
|
21244
21328
|
},
|
|
21245
21329
|
{ name: "completedSince", description: "finished at or after this instant (ISO or date)" },
|
|
21246
|
-
{ name: "completedBefore", description: "finished before this instant (ISO or date)" }
|
|
21330
|
+
{ name: "completedBefore", description: "finished before this instant (ISO or date)" },
|
|
21331
|
+
{
|
|
21332
|
+
name: "proposed",
|
|
21333
|
+
description: "only tasks Proposed by Echo (made by an Agent for a member, not accepted yet); --proposed=false for only the plan",
|
|
21334
|
+
boolean: true
|
|
21335
|
+
},
|
|
21336
|
+
{
|
|
21337
|
+
name: "ready",
|
|
21338
|
+
description: "only open tasks their Owner marked Ready for you; --ready=false for the rest",
|
|
21339
|
+
boolean: true
|
|
21340
|
+
}
|
|
21247
21341
|
],
|
|
21248
21342
|
write: {
|
|
21249
21343
|
scope: "tasks:write",
|
|
@@ -21307,7 +21401,15 @@ var ENTITIES = [
|
|
|
21307
21401
|
readScope: "areas:read",
|
|
21308
21402
|
returns: "AreaView",
|
|
21309
21403
|
canGet: true,
|
|
21310
|
-
listFlags: [
|
|
21404
|
+
listFlags: [
|
|
21405
|
+
{
|
|
21406
|
+
name: "active",
|
|
21407
|
+
description: "only live areas (not archived)",
|
|
21408
|
+
query: "archived",
|
|
21409
|
+
sends: "false"
|
|
21410
|
+
},
|
|
21411
|
+
{ name: "archived", description: "only archived areas", query: "archived", sends: "true" }
|
|
21412
|
+
],
|
|
21311
21413
|
write: {
|
|
21312
21414
|
scope: "areas:write",
|
|
21313
21415
|
createSchema: createAreaInputSchema,
|
|
@@ -21518,6 +21620,11 @@ var PAGINATION_FLAGS = [
|
|
|
21518
21620
|
description: "Opaque keyset cursor from a previous page's nextCursor."
|
|
21519
21621
|
}
|
|
21520
21622
|
];
|
|
21623
|
+
var STANDARD_LINK_FLAGS = [
|
|
21624
|
+
{ name: "habit", type: "string", description: "Held by this habit (its id)." },
|
|
21625
|
+
{ name: "task", type: "string", description: "Held by this recurring task (its id)." },
|
|
21626
|
+
{ name: "metric", type: "string", description: "Held by this Metric: weight, sleep or mood." }
|
|
21627
|
+
];
|
|
21521
21628
|
var GLOBAL_FLAGS = [
|
|
21522
21629
|
{ name: "json", type: "boolean", description: "Emit JSON (automatic when stdout is piped)." },
|
|
21523
21630
|
{ name: "quiet", type: "boolean", description: "Suppress human output (errors still report)." },
|
|
@@ -21578,6 +21685,31 @@ var COMMAND_SPECS = [
|
|
|
21578
21685
|
returns: "TodaySummary",
|
|
21579
21686
|
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."
|
|
21580
21687
|
},
|
|
21688
|
+
{
|
|
21689
|
+
path: ["today", "earlier"],
|
|
21690
|
+
summary: "From earlier: planned tasks of the last 14 days that weren't done, newest first, and the day Later this week lands on.",
|
|
21691
|
+
args: [],
|
|
21692
|
+
flags: [{ name: "area", type: "string", description: "Only tasks in this Area (id)." }],
|
|
21693
|
+
scopes: ["tasks:read"],
|
|
21694
|
+
returns: "FromEarlierResponse",
|
|
21695
|
+
notes: "GET /api/v1/today/from-earlier, from your local day. Nothing here is late: timed tasks, time blocks and agents' work never roll, and a plan older than 14 days just waits where it was filed. Answer with `do today answer`."
|
|
21696
|
+
},
|
|
21697
|
+
{
|
|
21698
|
+
path: ["today", "answer"],
|
|
21699
|
+
summary: "Answer From earlier for one or more tasks: today, later (this week), someday or let-go.",
|
|
21700
|
+
args: [
|
|
21701
|
+
{
|
|
21702
|
+
name: "answer",
|
|
21703
|
+
required: true,
|
|
21704
|
+
description: "today (plan it today) \xB7 later (the quiet day later this week) \xB7 someday (no date, kept in its Area or Project) \xB7 let-go (close it without doing it)."
|
|
21705
|
+
},
|
|
21706
|
+
{ name: "ids", required: true, description: "One or more task ids." }
|
|
21707
|
+
],
|
|
21708
|
+
flags: [],
|
|
21709
|
+
scopes: ["tasks:write"],
|
|
21710
|
+
returns: "RolloverResult",
|
|
21711
|
+
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`."
|
|
21712
|
+
},
|
|
21581
21713
|
{
|
|
21582
21714
|
path: ["now"],
|
|
21583
21715
|
summary: "What needs you now: what's waiting on you, then the day's timeline.",
|
|
@@ -21703,6 +21835,39 @@ var COMMAND_SPECS = [
|
|
|
21703
21835
|
returns: "Task",
|
|
21704
21836
|
notes: "POST /api/v1/tasks/{id}/cancel. Use this, not `task done`, for a dropped task."
|
|
21705
21837
|
},
|
|
21838
|
+
{
|
|
21839
|
+
path: ["tasks", "accept"],
|
|
21840
|
+
summary: "Accept a task Proposed by Echo: it joins the plan as suggested (day, Deadline, Area kept).",
|
|
21841
|
+
args: [{ name: "id", required: true, description: "Task ULID." }],
|
|
21842
|
+
flags: [],
|
|
21843
|
+
scopes: ["tasks:write"],
|
|
21844
|
+
returns: "Task",
|
|
21845
|
+
notes: "POST /api/v1/tasks/{id}/accept (#889). A no-op on a task that isn't a proposal. List proposals with `do tasks list --proposed`."
|
|
21846
|
+
},
|
|
21847
|
+
{
|
|
21848
|
+
path: ["tasks", "dismiss"],
|
|
21849
|
+
summary: "Not now on a task Proposed by Echo: it leaves the Inbox for a week, still proposed.",
|
|
21850
|
+
args: [{ name: "id", required: true, description: "Task ULID." }],
|
|
21851
|
+
flags: [],
|
|
21852
|
+
scopes: ["tasks:write"],
|
|
21853
|
+
returns: "Task",
|
|
21854
|
+
notes: "POST /api/v1/tasks/{id}/not-now (#889); 409 when the task isn't a proposal. Let go is `do task cancel`."
|
|
21855
|
+
},
|
|
21856
|
+
{
|
|
21857
|
+
path: ["tasks", "ready"],
|
|
21858
|
+
summary: "Mark a task Ready for you: its Owner finished something the member should look at (a draft, a link, a worktree).",
|
|
21859
|
+
args: [{ name: "id", required: true, description: "Task ULID." }],
|
|
21860
|
+
flags: [
|
|
21861
|
+
{
|
|
21862
|
+
name: "note",
|
|
21863
|
+
type: "string",
|
|
21864
|
+
description: `What's ready, in a line, with a link when there is one ("Draft ready: 38 hours, 3,420 euro \u2014 https://\u2026"); at most 500 characters. Absent keeps the note already there.`
|
|
21865
|
+
}
|
|
21866
|
+
],
|
|
21867
|
+
scopes: ["tasks:write"],
|
|
21868
|
+
returns: "Task",
|
|
21869
|
+
notes: "POST /api/v1/tasks/{id}/ready (#902); 409 when the task is done or let go. It reaches Now's Needs you with Review (Looks good = done, Send back = `ready: false`). List them with `do tasks list --ready`."
|
|
21870
|
+
},
|
|
21706
21871
|
{
|
|
21707
21872
|
path: ["task", "reopen"],
|
|
21708
21873
|
summary: "Reopen a done or cancelled task (status todo; clears completedAt).",
|
|
@@ -22448,6 +22613,66 @@ var COMMAND_SPECS = [
|
|
|
22448
22613
|
returns: "CollectionCoverBackfillResult",
|
|
22449
22614
|
notes: "Returns { checked, found }; run again while checked is 25 to work through more."
|
|
22450
22615
|
},
|
|
22616
|
+
{
|
|
22617
|
+
path: ["areas", "purpose"],
|
|
22618
|
+
summary: "Set an Area's purpose: one line of what it's for.",
|
|
22619
|
+
args: [
|
|
22620
|
+
{ name: "id", required: true, description: "The Area's id." },
|
|
22621
|
+
{ name: "line", required: false, description: "The purpose, in one line (words join)." }
|
|
22622
|
+
],
|
|
22623
|
+
flags: [{ name: "clear", type: "boolean", description: "Remove the purpose." }],
|
|
22624
|
+
scopes: ["areas:write"],
|
|
22625
|
+
returns: "AreaView",
|
|
22626
|
+
notes: "PATCH /api/v1/areas/:id { purpose }. It shows under the Area's name on the hub."
|
|
22627
|
+
},
|
|
22628
|
+
{
|
|
22629
|
+
path: ["areas", "standards", "list"],
|
|
22630
|
+
summary: "List an Area's standards with how each is doing (holding / worth a look).",
|
|
22631
|
+
args: [{ name: "id", required: true, description: "The Area's id." }],
|
|
22632
|
+
flags: [],
|
|
22633
|
+
scopes: ["areas:read"],
|
|
22634
|
+
returns: "AreaStandardView",
|
|
22635
|
+
notes: "Each linked standard says holding or worth a look with the reason in words; an unlinked one has no state (it's checked by hand in review)."
|
|
22636
|
+
},
|
|
22637
|
+
{
|
|
22638
|
+
path: ["areas", "standards", "add"],
|
|
22639
|
+
summary: "Add a standard (what fine looks like) to an Area; up to five.",
|
|
22640
|
+
args: [
|
|
22641
|
+
{ name: "id", required: true, description: "The Area's id." },
|
|
22642
|
+
{ name: "text", required: true, description: "The standard, a plain sentence (words join)." }
|
|
22643
|
+
],
|
|
22644
|
+
flags: STANDARD_LINK_FLAGS,
|
|
22645
|
+
scopes: ["areas:write"],
|
|
22646
|
+
returns: "AreaDetail",
|
|
22647
|
+
notes: "POST /api/v1/areas/:id/standards. Echo adds standards only after the member said yes; the change list keeps Undo."
|
|
22648
|
+
},
|
|
22649
|
+
{
|
|
22650
|
+
path: ["areas", "standards", "link"],
|
|
22651
|
+
summary: "Change what holds a standard: a habit, a recurring task, a Metric, or none.",
|
|
22652
|
+
args: [
|
|
22653
|
+
{ name: "id", required: true, description: "The Area's id." },
|
|
22654
|
+
{ name: "standard", required: true, description: "The standard's id." }
|
|
22655
|
+
],
|
|
22656
|
+
flags: [
|
|
22657
|
+
...STANDARD_LINK_FLAGS,
|
|
22658
|
+
{ name: "none", type: "boolean", description: "Unlink it: checked by hand in review." }
|
|
22659
|
+
],
|
|
22660
|
+
scopes: ["areas:write"],
|
|
22661
|
+
returns: "AreaDetail",
|
|
22662
|
+
notes: "PATCH /api/v1/areas/:id/standards/:standardId { link }."
|
|
22663
|
+
},
|
|
22664
|
+
{
|
|
22665
|
+
path: ["areas", "standards", "rm"],
|
|
22666
|
+
summary: "Remove a standard from an Area.",
|
|
22667
|
+
args: [
|
|
22668
|
+
{ name: "id", required: true, description: "The Area's id." },
|
|
22669
|
+
{ name: "standard", required: true, description: "The standard's id." }
|
|
22670
|
+
],
|
|
22671
|
+
flags: [],
|
|
22672
|
+
scopes: ["areas:write"],
|
|
22673
|
+
returns: "AreaDetail",
|
|
22674
|
+
notes: "DELETE /api/v1/areas/:id/standards/:standardId."
|
|
22675
|
+
},
|
|
22451
22676
|
{
|
|
22452
22677
|
path: ["places", "import"],
|
|
22453
22678
|
summary: "Import the rooms of the house once from Gaard's house.json.",
|
|
@@ -23140,6 +23365,49 @@ function renderToday(data, mode) {
|
|
|
23140
23365
|
${habits.join(`
|
|
23141
23366
|
`)}` : tasks;
|
|
23142
23367
|
}
|
|
23368
|
+
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
23369
|
+
function plannedDay(at, from) {
|
|
23370
|
+
if (!at)
|
|
23371
|
+
return "earlier";
|
|
23372
|
+
const day = new Date(at);
|
|
23373
|
+
const ago = from ? Math.round((Date.parse(from) - day.getTime()) / DAY_MS) : 7;
|
|
23374
|
+
if (ago <= 1)
|
|
23375
|
+
return "yesterday";
|
|
23376
|
+
if (ago < 7)
|
|
23377
|
+
return day.toLocaleDateString("en-GB", { weekday: "long" });
|
|
23378
|
+
return day.toLocaleDateString("en-GB", { day: "numeric", month: "short" });
|
|
23379
|
+
}
|
|
23380
|
+
function renderFromEarlier(data, mode) {
|
|
23381
|
+
const d = data;
|
|
23382
|
+
const tasks = d.tasks ?? [];
|
|
23383
|
+
if (tasks.length === 0)
|
|
23384
|
+
return paint(mode, "dim", "Nothing from earlier.");
|
|
23385
|
+
const later = d.laterThisWeek ? new Date(d.laterThisWeek).toLocaleDateString("en-GB", { weekday: "long" }) : null;
|
|
23386
|
+
return [
|
|
23387
|
+
paint(mode, "bold", "From earlier \xB7 planned, not done. Nothing is late."),
|
|
23388
|
+
...tasks.map((t) => ` \xB7 ${t.title ?? "(untitled)"} ${paint(mode, "dim", `\u2014 planned ${plannedDay(t.scheduledAt, d.from)}`)} ${paint(mode, "dim", t.id)}`),
|
|
23389
|
+
"",
|
|
23390
|
+
paint(mode, "dim", `Answer with \`do today answer <today|later|someday|let-go> <id\u2026>\`${later ? `; later is ${later}` : ""}.`)
|
|
23391
|
+
].join(`
|
|
23392
|
+
`);
|
|
23393
|
+
}
|
|
23394
|
+
function renderFromEarlierAnswer(data, mode) {
|
|
23395
|
+
const d = data;
|
|
23396
|
+
const n = d.tasks ?? 0;
|
|
23397
|
+
const tasks = `${n} task${n === 1 ? "" : "s"}`;
|
|
23398
|
+
if (n === 0)
|
|
23399
|
+
return paint(mode, "dim", "Nothing changed: those tasks are already done, let go or gone.");
|
|
23400
|
+
switch (d.answer) {
|
|
23401
|
+
case "today":
|
|
23402
|
+
return `Planned for today: ${tasks}.`;
|
|
23403
|
+
case "later":
|
|
23404
|
+
return `Planned ${d.to ? new Date(d.to).toLocaleDateString("en-GB", { weekday: "long" }) : "later this week"}: ${tasks}.`;
|
|
23405
|
+
case "someday":
|
|
23406
|
+
return `Moved to Someday: ${tasks}, kept where they were filed.`;
|
|
23407
|
+
default:
|
|
23408
|
+
return `Let go: ${tasks}. ${paint(mode, "dim", "Changed your mind? `do task reopen <id>`.")}`;
|
|
23409
|
+
}
|
|
23410
|
+
}
|
|
23143
23411
|
var PART_LABEL = {
|
|
23144
23412
|
morning: "Morning",
|
|
23145
23413
|
midday: "Midday",
|
|
@@ -23478,10 +23746,15 @@ function renderNow(data, mode) {
|
|
|
23478
23746
|
const waiting = now.waitingOnYou ?? [];
|
|
23479
23747
|
const head = paint(mode, "bold", `Waiting on ${actorText(now.for)} \xB7 ${waiting.length}`);
|
|
23480
23748
|
const lines = waiting.length ? waiting.map((t) => taskLine(t, mode)) : [paint(mode, "dim", " nothing is waiting on you")];
|
|
23749
|
+
const ready = now.readyForYou ?? [];
|
|
23750
|
+
const readyLines = ready.length ? [
|
|
23751
|
+
paint(mode, "bold", "Ready for you"),
|
|
23752
|
+
...ready.map((t) => taskLine(t, mode) + (t.readyNote ? paint(mode, "dim", ` \u2014 ${t.readyNote}`) : ""))
|
|
23753
|
+
] : [];
|
|
23481
23754
|
const tl = now.timeline ?? {};
|
|
23482
23755
|
const count = (xs) => xs?.length ?? 0;
|
|
23483
23756
|
const timeline = paint(mode, "dim", `Today: ${count(tl.scheduledTasks)} scheduled \xB7 ${count(tl.dueOccurrences)} due \xB7 ${count(tl.overdueTasks) + count(tl.overdueOccurrences)} overdue`);
|
|
23484
|
-
return [head, ...lines, timeline].join(`
|
|
23757
|
+
return [head, ...lines, ...readyLines, timeline].join(`
|
|
23485
23758
|
`);
|
|
23486
23759
|
}
|
|
23487
23760
|
function renderLanded(data, mode) {
|
|
@@ -23618,6 +23891,18 @@ function renderMcpTools(data, mode) {
|
|
|
23618
23891
|
return [paint(mode, "bold", `${tools.length} tools`), ...lines].join(`
|
|
23619
23892
|
`);
|
|
23620
23893
|
}
|
|
23894
|
+
function renderStandards(data, mode) {
|
|
23895
|
+
const list = Array.isArray(data) ? data : [];
|
|
23896
|
+
if (list.length === 0)
|
|
23897
|
+
return paint(mode, "dim", "No standards yet.");
|
|
23898
|
+
return list.map((s) => {
|
|
23899
|
+
const state = s.state === "holding" ? `Holding${s.why ? `: ${s.why}` : ""}` : s.state === "worth_a_look" ? `Worth a look${s.why ? `: ${s.why}` : ""}` : "Checked by hand, in review";
|
|
23900
|
+
const held = s.heldBy ? ` \xB7 ${s.heldBy}` : "";
|
|
23901
|
+
return ` \xB7 ${s.text ?? "(untitled)"}
|
|
23902
|
+
${paint(mode, "dim", `${state}${held} ${s.id ?? ""}`)}`;
|
|
23903
|
+
}).join(`
|
|
23904
|
+
`);
|
|
23905
|
+
}
|
|
23621
23906
|
|
|
23622
23907
|
// src/today.ts
|
|
23623
23908
|
var OPEN_STATUSES = new Set(["todo", "in_progress"]);
|
|
@@ -23734,9 +24019,19 @@ async function dispatchEntity(entity, rest, flags, requireClient) {
|
|
|
23734
24019
|
if (op === "list") {
|
|
23735
24020
|
const query = {};
|
|
23736
24021
|
for (const f of entity.listFlags) {
|
|
24022
|
+
const key = f.query ?? f.name;
|
|
24023
|
+
if (f.sends !== undefined) {
|
|
24024
|
+
if (flags[f.name] === undefined)
|
|
24025
|
+
continue;
|
|
24026
|
+
const other = entity.listFlags.find((o) => o !== f && o.sends !== undefined && (o.query ?? o.name) === key && (o.name in flags));
|
|
24027
|
+
if (other)
|
|
24028
|
+
throw usageError(`--${other.name} and --${f.name} can't be combined`);
|
|
24029
|
+
query[key] = f.sends;
|
|
24030
|
+
continue;
|
|
24031
|
+
}
|
|
23737
24032
|
const value = flags[f.name] === true ? "true" : flagString(flags, f.name);
|
|
23738
24033
|
if (value !== undefined)
|
|
23739
|
-
query[
|
|
24034
|
+
query[key] = value;
|
|
23740
24035
|
else if (f.required)
|
|
23741
24036
|
throw usageError(`\`${entity.name} list\` requires --${f.name}`);
|
|
23742
24037
|
}
|
|
@@ -23865,6 +24160,45 @@ var HANDLERS = {
|
|
|
23865
24160
|
render: renderToday
|
|
23866
24161
|
};
|
|
23867
24162
|
},
|
|
24163
|
+
"today earlier": async ({ flags, io, requireClient }) => {
|
|
24164
|
+
const area = flagString(flags, "area");
|
|
24165
|
+
return {
|
|
24166
|
+
data: await requireClient().get("/today/from-earlier", {
|
|
24167
|
+
query: { from: localDayStart(io.now()).toISOString(), areaId: area }
|
|
24168
|
+
}),
|
|
24169
|
+
render: renderFromEarlier
|
|
24170
|
+
};
|
|
24171
|
+
},
|
|
24172
|
+
"today answer": async ({ args, io, requireClient }) => {
|
|
24173
|
+
const answer = requireArg(args, 0, "answer");
|
|
24174
|
+
const taskIds = args.slice(1);
|
|
24175
|
+
if (!FROM_EARLIER_ANSWERS.includes(answer)) {
|
|
24176
|
+
throw usageError(`answer must be one of ${FROM_EARLIER_ANSWERS.join(", ")} (got \`${answer}\`)`);
|
|
24177
|
+
}
|
|
24178
|
+
if (taskIds.length === 0)
|
|
24179
|
+
throw usageError("today answer needs at least one task id");
|
|
24180
|
+
const client = requireClient();
|
|
24181
|
+
const today = localDayStart(io.now());
|
|
24182
|
+
let body;
|
|
24183
|
+
let to;
|
|
24184
|
+
if (answer === "today") {
|
|
24185
|
+
to = today.toISOString();
|
|
24186
|
+
body = { action: "reschedule", to, taskIds };
|
|
24187
|
+
} else if (answer === "later") {
|
|
24188
|
+
const earlier = await client.get("/today/from-earlier", {
|
|
24189
|
+
query: { from: today.toISOString() }
|
|
24190
|
+
});
|
|
24191
|
+
to = earlier.laterThisWeek;
|
|
24192
|
+
body = { action: "reschedule", to, taskIds };
|
|
24193
|
+
} else {
|
|
24194
|
+
body = { action: answer === "someday" ? "someday" : "drop", taskIds };
|
|
24195
|
+
}
|
|
24196
|
+
const result = await client.post("/today/rollover", body);
|
|
24197
|
+
return {
|
|
24198
|
+
data: { answer, ...to ? { to } : {}, ...result },
|
|
24199
|
+
render: renderFromEarlierAnswer
|
|
24200
|
+
};
|
|
24201
|
+
},
|
|
23868
24202
|
export: async ({ flags, requireClient }) => {
|
|
23869
24203
|
const format = flagString(flags, "format") ?? "json";
|
|
23870
24204
|
if (format !== "json" && format !== "ndjson") {
|
|
@@ -24091,6 +24425,20 @@ var HANDLERS = {
|
|
|
24091
24425
|
const id = requireArg(args, 0, "task id");
|
|
24092
24426
|
return { data: await requireClient().post(`/tasks/${id}/cancel`, {}), render: renderTask };
|
|
24093
24427
|
},
|
|
24428
|
+
"tasks accept": async ({ args, requireClient }) => {
|
|
24429
|
+
const id = requireArg(args, 0, "task id");
|
|
24430
|
+
return { data: await requireClient().post(`/tasks/${id}/accept`, {}), render: renderTask };
|
|
24431
|
+
},
|
|
24432
|
+
"tasks dismiss": async ({ args, requireClient }) => {
|
|
24433
|
+
const id = requireArg(args, 0, "task id");
|
|
24434
|
+
return { data: await requireClient().post(`/tasks/${id}/not-now`, {}), render: renderTask };
|
|
24435
|
+
},
|
|
24436
|
+
"tasks ready": async ({ args, flags, requireClient }) => {
|
|
24437
|
+
const id = requireArg(args, 0, "task id");
|
|
24438
|
+
const note = flagString(flags, "note");
|
|
24439
|
+
const body = parseInput(markTaskReadyInputSchema, note !== undefined ? { note } : {});
|
|
24440
|
+
return { data: await requireClient().post(`/tasks/${id}/ready`, body), render: renderTask };
|
|
24441
|
+
},
|
|
24094
24442
|
"task reopen": async ({ args, requireClient }) => {
|
|
24095
24443
|
const id = requireArg(args, 0, "task id");
|
|
24096
24444
|
const body = parseInput(updateTaskInputSchema, { status: "todo" });
|
|
@@ -24463,6 +24811,51 @@ var HANDLERS = {
|
|
|
24463
24811
|
const result = collectionCoverBackfillResultSchema.parse(await requireClient().post("/collection/covers", undefined));
|
|
24464
24812
|
return { data: result, render: renderRecord };
|
|
24465
24813
|
},
|
|
24814
|
+
"areas purpose": async ({ args, flags, requireClient }) => {
|
|
24815
|
+
const id = requireArg(args, 0, "area id");
|
|
24816
|
+
const line = args.slice(1).join(" ").trim();
|
|
24817
|
+
const clear = flagBool(flags, "clear");
|
|
24818
|
+
if (clear && line)
|
|
24819
|
+
throw usageError("pass a purpose or --clear, not both");
|
|
24820
|
+
if (!clear && !line)
|
|
24821
|
+
throw usageError('areas purpose needs a line, e.g. `do areas purpose <id> "Sleep well, move often"` (or --clear)');
|
|
24822
|
+
const body = parseInput(updateAreaInputSchema, { purpose: clear ? null : line });
|
|
24823
|
+
return { data: await requireClient().patch(`/areas/${id}`, body), render: renderRecord };
|
|
24824
|
+
},
|
|
24825
|
+
"areas standards list": async ({ args, requireClient }) => {
|
|
24826
|
+
const id = requireArg(args, 0, "area id");
|
|
24827
|
+
const area = await requireClient().get(`/areas/${id}`);
|
|
24828
|
+
return { data: area.standards ?? [], render: renderStandards };
|
|
24829
|
+
},
|
|
24830
|
+
"areas standards add": async ({ args, flags, requireClient }) => {
|
|
24831
|
+
const id = requireArg(args, 0, "area id");
|
|
24832
|
+
const text = args.slice(1).join(" ").trim();
|
|
24833
|
+
if (!text)
|
|
24834
|
+
throw usageError('areas standards add needs the standard, e.g. `do areas standards add <id> "Move three times a week" --habit <habitId>`');
|
|
24835
|
+
const link = standardLink(flags);
|
|
24836
|
+
const body = parseInput(addAreaStandardInputSchema, { text, ...link ? { link } : {} });
|
|
24837
|
+
const area = await requireClient().post(`/areas/${id}/standards`, body);
|
|
24838
|
+
return { data: area.standards ?? [], render: renderStandards };
|
|
24839
|
+
},
|
|
24840
|
+
"areas standards link": async ({ args, flags, requireClient }) => {
|
|
24841
|
+
const id = requireArg(args, 0, "area id");
|
|
24842
|
+
const standard = requireArg(args, 1, "standard id");
|
|
24843
|
+
const link = standardLink(flags);
|
|
24844
|
+
const none = flagBool(flags, "none");
|
|
24845
|
+
if (none && link)
|
|
24846
|
+
throw usageError("pass one of --habit, --task, --metric or --none");
|
|
24847
|
+
if (!none && !link)
|
|
24848
|
+
throw usageError("say what holds it: --habit <id>, --task <id>, --metric <key>, or --none");
|
|
24849
|
+
const body = parseInput(updateAreaStandardInputSchema, { link: none ? null : link });
|
|
24850
|
+
const area = await requireClient().patch(`/areas/${id}/standards/${standard}`, body);
|
|
24851
|
+
return { data: area.standards ?? [], render: renderStandards };
|
|
24852
|
+
},
|
|
24853
|
+
"areas standards rm": async ({ args, requireClient }) => {
|
|
24854
|
+
const id = requireArg(args, 0, "area id");
|
|
24855
|
+
const standard = requireArg(args, 1, "standard id");
|
|
24856
|
+
const area = await requireClient().delete(`/areas/${id}/standards/${standard}`);
|
|
24857
|
+
return { data: area.standards ?? [], render: renderStandards };
|
|
24858
|
+
},
|
|
24466
24859
|
"places import": async ({ args, flags, requireClient }) => {
|
|
24467
24860
|
const path = requireArg(args, 0, "house.json path");
|
|
24468
24861
|
let file;
|
|
@@ -24697,6 +25090,21 @@ function isoDay(date) {
|
|
|
24697
25090
|
const day = String(date.getDate()).padStart(2, "0");
|
|
24698
25091
|
return `${date.getFullYear()}-${month}-${day}`;
|
|
24699
25092
|
}
|
|
25093
|
+
function standardLink(flags) {
|
|
25094
|
+
const habit = flagString(flags, "habit");
|
|
25095
|
+
const task = flagString(flags, "task");
|
|
25096
|
+
const metric = flagString(flags, "metric");
|
|
25097
|
+
const given = [habit, task, metric].filter((v) => v !== undefined);
|
|
25098
|
+
if (given.length > 1)
|
|
25099
|
+
throw usageError("pass one of --habit, --task or --metric");
|
|
25100
|
+
if (habit !== undefined)
|
|
25101
|
+
return { kind: "habit", id: habit };
|
|
25102
|
+
if (task !== undefined)
|
|
25103
|
+
return { kind: "task", id: task };
|
|
25104
|
+
if (metric !== undefined)
|
|
25105
|
+
return { kind: "metric", key: metric };
|
|
25106
|
+
return null;
|
|
25107
|
+
}
|
|
24700
25108
|
function requireArg(args, index, name) {
|
|
24701
25109
|
const value = args[index];
|
|
24702
25110
|
if (value === undefined || value.length === 0) {
|
|
@@ -24808,6 +25216,10 @@ function assertDestructiveAllowed(flags, action) {
|
|
|
24808
25216
|
throw new CliError("destructive_blocked", `refusing to ${action} without --allow-destructive (a guardrail for autonomous agents)`, EXIT.USAGE);
|
|
24809
25217
|
}
|
|
24810
25218
|
}
|
|
25219
|
+
var FROM_EARLIER_ANSWERS = ["today", "later", "someday", "let-go"];
|
|
25220
|
+
function localDayStart(now) {
|
|
25221
|
+
return new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
25222
|
+
}
|
|
24811
25223
|
|
|
24812
25224
|
// src/run.ts
|
|
24813
25225
|
async function run(argv, io) {
|
package/package.json
CHANGED