things-api 0.10.0 → 0.11.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.
- package/README.md +38 -12
- package/dist/cli/clock.d.ts +8 -0
- package/dist/cli/clock.js +24 -0
- package/dist/cli/clock.js.map +1 -0
- package/dist/cli/commands/area.js +8 -9
- package/dist/cli/commands/area.js.map +1 -1
- package/dist/cli/commands/install-skill.d.ts +45 -0
- package/dist/cli/commands/install-skill.js +207 -0
- package/dist/cli/commands/install-skill.js.map +1 -0
- package/dist/cli/commands/project.js +7 -6
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/reads.d.ts +15 -2
- package/dist/cli/commands/reads.js +45 -17
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/setup.js +7 -2
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/show.js +6 -6
- package/dist/cli/commands/show.js.map +1 -1
- package/dist/cli/commands/todo.js +14 -8
- package/dist/cli/commands/todo.js.map +1 -1
- package/dist/cli/commands/writes.js +29 -32
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/glyphs.d.ts +16 -0
- package/dist/cli/glyphs.js +23 -0
- package/dist/cli/glyphs.js.map +1 -1
- package/dist/cli/help.js +56 -6
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.js +33 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/move-hint.d.ts +45 -0
- package/dist/cli/move-hint.js +196 -0
- package/dist/cli/move-hint.js.map +1 -0
- package/dist/cli/period.d.ts +2 -8
- package/dist/cli/period.js +44 -30
- package/dist/cli/period.js.map +1 -1
- package/dist/cli/read-driver.js +11 -1
- package/dist/cli/read-driver.js.map +1 -1
- package/dist/cli/render.js +16 -7
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/skill-check.d.ts +21 -0
- package/dist/cli/skill-check.js +82 -0
- package/dist/cli/skill-check.js.map +1 -0
- package/dist/cli/skill.d.ts +62 -0
- package/dist/cli/skill.js +142 -0
- package/dist/cli/skill.js.map +1 -0
- package/dist/cli/tag-filters.d.ts +6 -2
- package/dist/cli/tag-filters.js +8 -6
- package/dist/cli/tag-filters.js.map +1 -1
- package/dist/cli/verb-hint.js +27 -2
- package/dist/cli/verb-hint.js.map +1 -1
- package/dist/cli/version.d.ts +4 -0
- package/dist/cli/version.js +18 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/client.d.ts +35 -12
- package/dist/client.js +42 -18
- package/dist/client.js.map +1 -1
- package/dist/contracts.d.ts +11 -1
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +550 -506
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/clock.d.ts +61 -0
- package/dist/model/clock.js +71 -0
- package/dist/model/clock.js.map +1 -0
- package/dist/model/dates.d.ts +26 -3
- package/dist/model/dates.js +84 -3
- package/dist/model/dates.js.map +1 -1
- package/dist/model/entities.d.ts +17 -3
- package/dist/model/entities.js.map +1 -1
- package/dist/model/mappers.d.ts +2 -2
- package/dist/model/mappers.js +25 -7
- package/dist/model/mappers.js.map +1 -1
- package/dist/read/area-view.d.ts +1 -1
- package/dist/read/area-view.js +8 -6
- package/dist/read/area-view.js.map +1 -1
- package/dist/read/detail.d.ts +1 -1
- package/dist/read/detail.js +11 -4
- package/dist/read/detail.js.map +1 -1
- package/dist/read/log-boundary.d.ts +1 -1
- package/dist/read/log-boundary.js +13 -3
- package/dist/read/log-boundary.js.map +1 -1
- package/dist/read/project-view.d.ts +1 -1
- package/dist/read/project-view.js +8 -6
- package/dist/read/project-view.js.map +1 -1
- package/dist/read/queries.d.ts +3 -1
- package/dist/read/queries.js +27 -5
- package/dist/read/queries.js.map +1 -1
- package/dist/read/snapshot.d.ts +1 -1
- package/dist/read/snapshot.js +9 -2
- package/dist/read/snapshot.js.map +1 -1
- package/dist/read/truncation.d.ts +1 -1
- package/dist/read/truncation.js +2 -2
- package/dist/read/truncation.js.map +1 -1
- package/dist/read/views.d.ts +12 -11
- package/dist/read/views.js +48 -43
- package/dist/read/views.js.map +1 -1
- package/dist/write/accessibility-probe.d.ts +1 -1
- package/dist/write/accessibility-probe.js +8 -0
- package/dist/write/accessibility-probe.js.map +1 -1
- package/dist/write/automation-probe.d.ts +1 -1
- package/dist/write/automation-probe.js +8 -0
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/batch.js +3 -2
- package/dist/write/batch.js.map +1 -1
- package/dist/write/commands.d.ts +1 -1
- package/dist/write/commands.js +54 -15
- package/dist/write/commands.js.map +1 -1
- package/dist/write/guards.d.ts +1 -1
- package/dist/write/guards.js +23 -0
- package/dist/write/guards.js.map +1 -1
- package/dist/write/pipeline.d.ts +54 -2
- package/dist/write/pipeline.js +112 -20
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/planner.js +8 -1
- package/dist/write/planner.js.map +1 -1
- package/dist/write/pre-state.d.ts +37 -0
- package/dist/write/pre-state.js +42 -0
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/recurrence-rule-blob.d.ts +65 -0
- package/dist/write/recurrence-rule-blob.js +150 -0
- package/dist/write/recurrence-rule-blob.js.map +1 -0
- package/dist/write/vectors/registry.d.ts +5 -7
- package/dist/write/vectors/registry.js +49 -2
- package/dist/write/vectors/registry.js.map +1 -1
- package/dist/write/vectors/simulator.d.ts +44 -0
- package/dist/write/vectors/simulator.js +1136 -0
- package/dist/write/vectors/simulator.js.map +1 -0
- package/dist/write/vectors/types.d.ts +35 -0
- package/dist/write/vectors/ui-certification.d.ts +9 -3
- package/dist/write/vectors/ui-certification.js +3 -6
- package/dist/write/vectors/ui-certification.js.map +1 -1
- package/dist/write/vectors/ui-recipes.d.ts +13 -0
- package/dist/write/vectors/ui-recipes.js +52 -0
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui.d.ts +15 -0
- package/dist/write/vectors/ui.js +54 -6
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/verify/delta.d.ts +110 -1
- package/dist/write/verify/delta.js +177 -15
- package/dist/write/verify/delta.js.map +1 -1
- package/dist/write/verify/poller.d.ts +7 -1
- package/dist/write/verify/poller.js +20 -1
- package/dist/write/verify/poller.js.map +1 -1
- package/package.json +18 -3
- package/skills/things-cli/SKILL.md +53 -0
- package/skills/things-cli/references/contracts.md +41 -0
- package/skills/things-cli/references/gui.md +11 -0
- package/skills/things-cli/references/model.md +51 -0
package/dist/cli/help.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CLI_VERSION } from "./version.js";
|
|
2
|
+
import { ExitCode } from "../index.js";
|
|
2
3
|
/** The index groups, in display order. Every top-level command lands in one. */
|
|
3
4
|
export const HELP_GROUPS = [
|
|
4
5
|
{
|
|
@@ -15,7 +16,16 @@ export const HELP_GROUPS = [
|
|
|
15
16
|
},
|
|
16
17
|
{
|
|
17
18
|
title: "Setup & diagnostics",
|
|
18
|
-
commands: [
|
|
19
|
+
commands: [
|
|
20
|
+
"config",
|
|
21
|
+
"doctor",
|
|
22
|
+
"capabilities",
|
|
23
|
+
"setup",
|
|
24
|
+
"install-skill",
|
|
25
|
+
"mcp",
|
|
26
|
+
"snapshot",
|
|
27
|
+
"legend",
|
|
28
|
+
],
|
|
19
29
|
},
|
|
20
30
|
];
|
|
21
31
|
/**
|
|
@@ -54,6 +64,7 @@ export const INDEX = {
|
|
|
54
64
|
doctor: { args: "", desc: "check environment health and pending setup" },
|
|
55
65
|
capabilities: { args: "", desc: "what each write operation supports" },
|
|
56
66
|
setup: { args: "<verb>", desc: "one-time setup (install the Shortcuts)" },
|
|
67
|
+
"install-skill": { args: "", desc: "install the agent skill for coding agents" },
|
|
57
68
|
mcp: { args: "", desc: "serve the Model Context Protocol server on stdio" },
|
|
58
69
|
snapshot: { args: "", desc: "full normalized dump of every record" },
|
|
59
70
|
legend: { args: "", desc: "the symbols and colors list output uses" },
|
|
@@ -136,15 +147,16 @@ export function renderTopLevelHelp(program, width) {
|
|
|
136
147
|
lines.push("");
|
|
137
148
|
}
|
|
138
149
|
lines.push("Global options (accepted by most commands)");
|
|
139
|
-
lines.push(`${" --json".padEnd(col)}emit
|
|
150
|
+
lines.push(`${" --json".padEnd(col)}emit {apiVersion, ok, kind, data, meta}; payload=.data; entity id=.uuid (not .id)`);
|
|
140
151
|
lines.push(`${" --db <path>".padEnd(col)}read from an explicit database path`);
|
|
141
152
|
lines.push(`${" -h, --help".padEnd(col)}help for things, or for any <command>`);
|
|
142
|
-
lines.push(`${" -V, --version".padEnd(col)}print the version (${
|
|
153
|
+
lines.push(`${" -V, --version".padEnd(col)}print the version (${CLI_VERSION})`);
|
|
143
154
|
lines.push("");
|
|
144
155
|
lines.push("Run `things <command> --help` for the behavior and options of any command.");
|
|
145
156
|
lines.push("Most commands take a ref (uuid, prefix, share link, or name) — see `things help ids`.");
|
|
146
|
-
lines.push("Guides: `things help <topic>` — agent, filters, ids, output, writes.");
|
|
157
|
+
lines.push("Guides: `things help <topic>` — agent, filters, ids, output, repeating, writes.");
|
|
147
158
|
lines.push("New to Things? Start with `things help agent`.");
|
|
159
|
+
lines.push("Agent skill available: run `things install-skill`.");
|
|
148
160
|
return lines.join("\n");
|
|
149
161
|
}
|
|
150
162
|
// ── Topics ───────────────────────────────────────────────────────────────────
|
|
@@ -163,6 +175,7 @@ const AGENT_NOTE_BULLETS = [
|
|
|
163
175
|
"Symbols & colors in list output: run `things legend` (add --json for the table).",
|
|
164
176
|
"Every write supports --dry-run: preview the planned change and its expected effect without executing anything.",
|
|
165
177
|
"Failures are loud: a change that does not take effect exits 3; refused changes exit 4 with machine-readable remediation.",
|
|
178
|
+
"An agent skill is available: `things install-skill`. On human output the tool reads your installed skill under ~/.agents and ~/.claude and notes (once, on stderr) when it is well behind this binary; silence it with THINGS_API_NO_SKILL_CHECK=1.",
|
|
166
179
|
];
|
|
167
180
|
function renderAgentTopic(width) {
|
|
168
181
|
const room = Math.max(40, width);
|
|
@@ -297,9 +310,46 @@ cancel, move, …) is not a command — it points you at the typed form
|
|
|
297
310
|
|
|
298
311
|
Discover every operation and the flags it needs: \`things capabilities\`.
|
|
299
312
|
A few operations need the bundled Shortcuts: \`things setup shortcuts\`.`,
|
|
313
|
+
repeating: `REPEATING — rules for recurring to-dos and projects
|
|
314
|
+
|
|
315
|
+
Verbs: \`things todo|project make-repeating <ref>\` (turn an existing item into a
|
|
316
|
+
repeater), \`things project create-repeating "<title>"\`, \`… reschedule-repeat <ref>\`
|
|
317
|
+
(change a rule in place). Every rule takes \`--frequency <daily|weekly|monthly|yearly>\`
|
|
318
|
+
and a required \`--interval <n>\` (\`--interval 1\` = every unit). Repeating operations
|
|
319
|
+
require \`--allow-disruptive\`, including \`--dry-run\` previews.
|
|
320
|
+
|
|
321
|
+
Two modes:
|
|
322
|
+
fixed (default) occurrences land on calendar dates. NOTE: this REPLACES the
|
|
323
|
+
item — the response returns the new uuids (see below).
|
|
324
|
+
--after-completion next occurrence lands N units after you complete the current
|
|
325
|
+
one. The item keeps its uuid.
|
|
326
|
+
|
|
327
|
+
Shaping the rule (compose with the frequency):
|
|
328
|
+
--weekdays mon,thu,fri weekly: MULTIPLE days in ONE rule — never make two
|
|
329
|
+
repeaters for "every Thursday and Friday"
|
|
330
|
+
--on-day <1-31|last> monthly/yearly: a date anchor
|
|
331
|
+
--on-weekday <day> --on-ordinal <1-5|last> nth-weekday anchor; yearly adds
|
|
332
|
+
--yearly-month <1-12> e.g. last Sunday of December, every year:
|
|
333
|
+
--frequency yearly --yearly-month 12
|
|
334
|
+
--on-weekday sunday --on-ordinal last
|
|
335
|
+
--ends-after <n> | --ends-on YYYY-MM-DD stop bounds
|
|
336
|
+
--reminder HH:mm · --deadline · --start-days-earlier <n>
|
|
337
|
+
|
|
338
|
+
make-repeating returns a \`repeating\` block: \`instanceUuid\` is the visible current
|
|
339
|
+
occurrence (use it to reach the item), \`templateUuid\` the recurring rule (use it as
|
|
340
|
+
the <ref> for \`reschedule-repeat\`), and \`replacedUuid\` the original when it was
|
|
341
|
+
replaced. Typical chain: \`things todo add "<title>" --json\`, then
|
|
342
|
+
\`things todo make-repeating <returned-uuid> --frequency … --allow-disruptive\`.`,
|
|
300
343
|
};
|
|
301
344
|
/** The valid topic names, in the order the "unknown topic" hint lists them. */
|
|
302
|
-
export const TOPIC_NAMES = [
|
|
345
|
+
export const TOPIC_NAMES = [
|
|
346
|
+
"agent",
|
|
347
|
+
"filters",
|
|
348
|
+
"ids",
|
|
349
|
+
"output",
|
|
350
|
+
"repeating",
|
|
351
|
+
"writes",
|
|
352
|
+
];
|
|
303
353
|
/** Render one topic to `width`, or null when `name` is not a topic. */
|
|
304
354
|
export function renderTopic(name, width) {
|
|
305
355
|
if (name === "agent")
|
package/dist/cli/help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/main.js
CHANGED
|
@@ -15,20 +15,25 @@ import { registerAreaCommands } from "./commands/area.js";
|
|
|
15
15
|
import { registerProjectCommands } from "./commands/project.js";
|
|
16
16
|
import { registerReadCommands } from "./commands/reads.js";
|
|
17
17
|
import { registerSetup } from "./commands/setup.js";
|
|
18
|
+
import { registerInstallSkill } from "./commands/install-skill.js";
|
|
18
19
|
import { registerShowCommands } from "./commands/show.js";
|
|
19
20
|
import { registerSnapshot } from "./commands/snapshot.js";
|
|
20
21
|
import { registerTodoCommands } from "./commands/todo.js";
|
|
21
22
|
import { registerWriteCommands } from "./commands/writes.js";
|
|
22
23
|
import { resolveInvocation } from "./resolve-invocation.js";
|
|
23
24
|
import { runVerbHint } from "./verb-hint.js";
|
|
25
|
+
import { detectMoveHint, runMoveHint } from "./move-hint.js";
|
|
26
|
+
import { setRenderClock } from "./clock.js";
|
|
27
|
+
import { maybeEmitSkillDriftNote } from "./skill-check.js";
|
|
24
28
|
import { resolveWidth, setFitWidth } from "./width.js";
|
|
25
|
-
import {
|
|
29
|
+
import { CLI_VERSION } from "./version.js";
|
|
30
|
+
import { ExitCode, resolveClock } from "../index.js";
|
|
26
31
|
export function buildProgram() {
|
|
27
32
|
const program = new Command();
|
|
28
33
|
program
|
|
29
34
|
.name("things")
|
|
30
35
|
.description("Programmatic interface to Things 3 (Cultured Code)")
|
|
31
|
-
.version(
|
|
36
|
+
.version(CLI_VERSION)
|
|
32
37
|
// Unknown-command typos are answered with "did you mean …" (default on;
|
|
33
38
|
// stated for the record — most top-level typos route through the bare-noun
|
|
34
39
|
// did-you-mean instead, this covers the subcommand groups).
|
|
@@ -41,6 +46,7 @@ export function buildProgram() {
|
|
|
41
46
|
registerTodoCommands(program);
|
|
42
47
|
registerWriteCommands(program);
|
|
43
48
|
registerSetup(program);
|
|
49
|
+
registerInstallSkill(program);
|
|
44
50
|
registerSnapshot(program);
|
|
45
51
|
registerMcp(program);
|
|
46
52
|
// The signpost index + `help [topic]` replace the multi-scroll epilog; the
|
|
@@ -60,6 +66,22 @@ export function runCli() {
|
|
|
60
66
|
columns: process.stdout.columns,
|
|
61
67
|
isTTY: process.stdout.isTTY === true,
|
|
62
68
|
}));
|
|
69
|
+
// Resolve the consumer clock ONCE (THINGS_TZ / THINGS_NOW) so the human
|
|
70
|
+
// renderers and period parsers evaluate dates in the same zone the library
|
|
71
|
+
// does. A malformed value is NOT fatal here: the command's own client-open
|
|
72
|
+
// re-resolves it and surfaces the usage error with --json awareness — so
|
|
73
|
+
// leave the render clock on the host default if resolution throws.
|
|
74
|
+
try {
|
|
75
|
+
const clock = resolveClock({ env: process.env });
|
|
76
|
+
setRenderClock({ now: clock.now, zone: clock.zone });
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// handled by the command path (openThings → runRead/runWrite usage error)
|
|
80
|
+
}
|
|
81
|
+
// Passive skill-drift notice: one stderr line when the installed agent skill
|
|
82
|
+
// is well behind this binary's bundled copy (human paths only, never --json /
|
|
83
|
+
// mcp; kill switch THINGS_API_NO_SKILL_CHECK=1). Silent on any error/absence.
|
|
84
|
+
maybeEmitSkillDriftNote({ argv: process.argv.slice(2), env: process.env });
|
|
63
85
|
const program = buildProgram();
|
|
64
86
|
program.exitOverride((err) => {
|
|
65
87
|
process.exit(err.exitCode === 0 ? ExitCode.Ok : ExitCode.Usage);
|
|
@@ -75,6 +97,15 @@ export function runCli() {
|
|
|
75
97
|
runVerbHint(program, resolved.argv);
|
|
76
98
|
return;
|
|
77
99
|
}
|
|
100
|
+
// A namespaced `move` carrying scheduling intent (`todo move X --when today`,
|
|
101
|
+
// `todo move X someday`) is answered with the command that actually schedules
|
|
102
|
+
// an item, instead of a bare unknown-option / excess-argument usage error
|
|
103
|
+
// (docs/design/cli-grammar.md). Never fires on a valid container move.
|
|
104
|
+
const moveHint = detectMoveHint(program, resolved.argv);
|
|
105
|
+
if (moveHint !== null) {
|
|
106
|
+
runMoveHint(moveHint);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
78
109
|
program.parse(resolved.argv, { from: "user" });
|
|
79
110
|
}
|
|
80
111
|
// Direct-run detection must survive the npm .bin symlink (argv[1] ends with
|
package/dist/cli/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AACA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The scheduling-intent hint for a namespaced `move` (docs/design/cli-grammar.md).
|
|
3
|
+
* `things todo move <ref>` and `things project move <ref>` take CONTAINER
|
|
4
|
+
* destinations only (--area/--project/--heading; todo also --inbox/--detach).
|
|
5
|
+
* An agent carrying scheduling intent ("move X to Someday") reaches for
|
|
6
|
+
* spellings `move` does not accept — `--to someday`, `--when today`,
|
|
7
|
+
* `--someday`, or a bare `someday` positional — and would otherwise land on a
|
|
8
|
+
* bare unknown-option / excess-argument usage error that never names the
|
|
9
|
+
* command which actually schedules an item.
|
|
10
|
+
*
|
|
11
|
+
* This runs BEFORE commander parses (like the bare-verb hint) and, when it
|
|
12
|
+
* recognizes scheduling vocabulary on a `move` invocation, answers with the
|
|
13
|
+
* concrete command that works:
|
|
14
|
+
*
|
|
15
|
+
* - a scheduling term (`someday`/`today`/`evening`/`anytime`/a date), as a
|
|
16
|
+
* flag value or a stray positional → `things <group> update <ref> --when <value>`.
|
|
17
|
+
* - a bare `inbox` positional on `todo move` → `things todo move <ref> --inbox`
|
|
18
|
+
* (the real Inbox-return; `--when inbox` is not a thing).
|
|
19
|
+
*
|
|
20
|
+
* It NEVER fires on a valid move: every trapped spelling is already a usage
|
|
21
|
+
* error, so the accepted grammar is unchanged. Exit class stays Usage (2);
|
|
22
|
+
* under `--json` the suggestion rides `error.details.suggestions`.
|
|
23
|
+
*/
|
|
24
|
+
import type { Command } from "commander";
|
|
25
|
+
/** The corrected command this hint points at. */
|
|
26
|
+
export interface MoveHint {
|
|
27
|
+
group: "todo" | "project";
|
|
28
|
+
/** Whether the caller asked for a --json envelope. */
|
|
29
|
+
json: boolean;
|
|
30
|
+
/** Inbox return vs. a schedule change — selects the wording. */
|
|
31
|
+
intent: "schedule" | "inbox";
|
|
32
|
+
/** The full, runnable suggestion (already shell-quoted). */
|
|
33
|
+
suggestion: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Classify a `<group> move` invocation for scheduling intent. Returns the
|
|
37
|
+
* corrected-command hint when a trapped spelling is present, else null (the
|
|
38
|
+
* invocation falls through to commander unchanged).
|
|
39
|
+
*/
|
|
40
|
+
export declare function detectMoveHint(program: Command, argv: string[]): MoveHint | null;
|
|
41
|
+
/**
|
|
42
|
+
* Emit the scheduling-intent hint and set the Usage exit code. Never opens the
|
|
43
|
+
* write pipeline — it only rewrites the failing invocation into a working one.
|
|
44
|
+
*/
|
|
45
|
+
export declare function runMoveHint(hint: MoveHint): void;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { errorEnvelope, ExitCode } from "../index.js";
|
|
2
|
+
import { indexPastLeadingFlags } from "./resolve-invocation.js";
|
|
3
|
+
import { shellQuote } from "./shell-quote.js";
|
|
4
|
+
/** The write groups whose `move` subcommand this hint guards. */
|
|
5
|
+
const MOVE_GROUPS = new Set(["todo", "project"]);
|
|
6
|
+
/**
|
|
7
|
+
* Flag spellings that signal scheduling intent on a `move` — none is a real
|
|
8
|
+
* `move` option, so their presence is always a usage error we can improve.
|
|
9
|
+
* `--inbox` is deliberately absent: it is a genuine `todo move` destination.
|
|
10
|
+
*/
|
|
11
|
+
const SCHEDULING_FLAGS = new Set([
|
|
12
|
+
"--to",
|
|
13
|
+
"--when",
|
|
14
|
+
"--someday",
|
|
15
|
+
"--today",
|
|
16
|
+
"--evening",
|
|
17
|
+
"--anytime",
|
|
18
|
+
"--date",
|
|
19
|
+
"--schedule",
|
|
20
|
+
]);
|
|
21
|
+
/** Scheduling flags that carry their term as the NEXT token (or `--flag=term`). */
|
|
22
|
+
const VALUE_SCHEDULING_FLAGS = new Set(["--to", "--when", "--date", "--schedule"]);
|
|
23
|
+
/** Boolean-style scheduling flags whose name IS the `--when` term. */
|
|
24
|
+
const FLAG_TERM = {
|
|
25
|
+
"--someday": "someday",
|
|
26
|
+
"--today": "today",
|
|
27
|
+
"--evening": "evening",
|
|
28
|
+
"--anytime": "anytime",
|
|
29
|
+
};
|
|
30
|
+
/** Recognized `--when` terms (a date is matched separately). */
|
|
31
|
+
const WHEN_TERMS = new Set(["today", "evening", "anytime", "someday"]);
|
|
32
|
+
/** Positional destinations that read as scheduling intent, not a container. */
|
|
33
|
+
const SCHEDULING_POSITIONALS = new Set(["someday", "today", "evening", "anytime", "inbox"]);
|
|
34
|
+
/** A bare `YYYY-MM-DD` — a valid `--when` value, never a container name. */
|
|
35
|
+
function isDate(token) {
|
|
36
|
+
return /^\d{4}-\d{2}-\d{2}$/.test(token);
|
|
37
|
+
}
|
|
38
|
+
/** Long/short flag names of `<group> move` that consume the following token. */
|
|
39
|
+
function valueFlagsFor(program, group) {
|
|
40
|
+
const names = new Set();
|
|
41
|
+
const groupCmd = program.commands.find((c) => c.name() === group);
|
|
42
|
+
const moveCmd = groupCmd?.commands.find((c) => c.name() === "move");
|
|
43
|
+
if (moveCmd === undefined)
|
|
44
|
+
return names;
|
|
45
|
+
for (const opt of moveCmd.options) {
|
|
46
|
+
// Commander marks value-taking options `<x>` (required) or `[x]` (optional).
|
|
47
|
+
if (opt.required === true || opt.optional === true) {
|
|
48
|
+
if (opt.long !== undefined)
|
|
49
|
+
names.add(opt.long);
|
|
50
|
+
if (opt.short !== undefined)
|
|
51
|
+
names.add(opt.short);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return names;
|
|
55
|
+
}
|
|
56
|
+
/** Map a raw scheduling term to a valid `--when` value (park by default). */
|
|
57
|
+
function whenValue(term) {
|
|
58
|
+
if (term !== null && (WHEN_TERMS.has(term.toLowerCase()) || isDate(term))) {
|
|
59
|
+
return term.toLowerCase() === term ? term : term.toLowerCase();
|
|
60
|
+
}
|
|
61
|
+
return "someday";
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Walk the tokens after `<group> move`, skipping global/known value flags so
|
|
65
|
+
* their values are never misread as a positional destination (`--heading
|
|
66
|
+
* someday` moves under a heading literally named "someday" — not a trap).
|
|
67
|
+
*/
|
|
68
|
+
function scan(tokens, valueFlags) {
|
|
69
|
+
const positionals = [];
|
|
70
|
+
let flagTerm = null;
|
|
71
|
+
let flagIntent = false;
|
|
72
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
73
|
+
const tok = tokens[i] ?? "";
|
|
74
|
+
if (tok.startsWith("-")) {
|
|
75
|
+
const eq = tok.indexOf("=");
|
|
76
|
+
const name = eq >= 0 ? tok.slice(0, eq) : tok;
|
|
77
|
+
const inline = eq >= 0 ? tok.slice(eq + 1) : undefined;
|
|
78
|
+
if (SCHEDULING_FLAGS.has(name)) {
|
|
79
|
+
if (!flagIntent) {
|
|
80
|
+
if (VALUE_SCHEDULING_FLAGS.has(name)) {
|
|
81
|
+
flagTerm = inline ?? tokens[i + 1] ?? null;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
flagTerm = FLAG_TERM[name] ?? null;
|
|
85
|
+
}
|
|
86
|
+
flagIntent = true;
|
|
87
|
+
}
|
|
88
|
+
if (VALUE_SCHEDULING_FLAGS.has(name) && inline === undefined)
|
|
89
|
+
i++; // consume its term
|
|
90
|
+
}
|
|
91
|
+
else if (valueFlags.has(name) && inline === undefined) {
|
|
92
|
+
i++; // a known value flag — skip its value, it is not a positional
|
|
93
|
+
}
|
|
94
|
+
// boolean / unknown flags carry no positional to protect
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
positionals.push(tok);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
ref: positionals[0] ?? null,
|
|
102
|
+
dest: positionals[1] ?? null,
|
|
103
|
+
flagTerm,
|
|
104
|
+
flagIntent,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Classify a `<group> move` invocation for scheduling intent. Returns the
|
|
109
|
+
* corrected-command hint when a trapped spelling is present, else null (the
|
|
110
|
+
* invocation falls through to commander unchanged).
|
|
111
|
+
*/
|
|
112
|
+
export function detectMoveHint(program, argv) {
|
|
113
|
+
const at = indexPastLeadingFlags(argv);
|
|
114
|
+
if (at === null)
|
|
115
|
+
return null;
|
|
116
|
+
const group = argv[at];
|
|
117
|
+
if (group === undefined || !MOVE_GROUPS.has(group))
|
|
118
|
+
return null;
|
|
119
|
+
if (argv[at + 1] !== "move")
|
|
120
|
+
return null;
|
|
121
|
+
const g = group;
|
|
122
|
+
const s = scan(argv.slice(at + 2), valueFlagsFor(program, group));
|
|
123
|
+
const json = argv.includes("--json");
|
|
124
|
+
const refEcho = s.ref !== null ? shellQuote(s.ref) : "<ref>";
|
|
125
|
+
// Precedence: an explicit scheduling FLAG wins over a positional read.
|
|
126
|
+
if (s.flagIntent) {
|
|
127
|
+
return {
|
|
128
|
+
group: g,
|
|
129
|
+
json,
|
|
130
|
+
intent: "schedule",
|
|
131
|
+
suggestion: `things ${g} update ${refEcho} --when ${whenValue(s.flagTerm)}`,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// A stray positional destination that reads as scheduling vocabulary.
|
|
135
|
+
const dest = s.dest;
|
|
136
|
+
if (dest === null)
|
|
137
|
+
return null;
|
|
138
|
+
const lower = dest.toLowerCase();
|
|
139
|
+
if (lower === "inbox") {
|
|
140
|
+
// Only to-dos have an Inbox, and its return is a flag (`--when inbox` is not
|
|
141
|
+
// a thing). A project has no Inbox — leave that to commander.
|
|
142
|
+
if (g !== "todo")
|
|
143
|
+
return null;
|
|
144
|
+
return {
|
|
145
|
+
group: g,
|
|
146
|
+
json,
|
|
147
|
+
intent: "inbox",
|
|
148
|
+
suggestion: `things todo move ${refEcho} --inbox`,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (SCHEDULING_POSITIONALS.has(lower) || isDate(dest)) {
|
|
152
|
+
return {
|
|
153
|
+
group: g,
|
|
154
|
+
json,
|
|
155
|
+
intent: "schedule",
|
|
156
|
+
suggestion: `things ${g} update ${refEcho} --when ${whenValue(dest)}`,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
/** The lead line naming what `move` does — scheduling vs. Inbox framing. */
|
|
162
|
+
function leadLine(hint) {
|
|
163
|
+
return hint.intent === "inbox"
|
|
164
|
+
? `error: \`things ${hint.group} move\` takes a container flag, not a positional destination.`
|
|
165
|
+
: `error: \`things ${hint.group} move\` changes an item's container, not its schedule.`;
|
|
166
|
+
}
|
|
167
|
+
/** The action line inviting the corrected command. */
|
|
168
|
+
function actionLine(hint) {
|
|
169
|
+
return hint.intent === "inbox"
|
|
170
|
+
? `to send an item back to the Inbox use: ${hint.suggestion}`
|
|
171
|
+
: `to schedule or park an item use: ${hint.suggestion}`;
|
|
172
|
+
}
|
|
173
|
+
/** Human render: the framing line, the corrected command, the container reminder. */
|
|
174
|
+
function renderHuman(hint) {
|
|
175
|
+
return [
|
|
176
|
+
leadLine(hint),
|
|
177
|
+
actionLine(hint),
|
|
178
|
+
`move changes containers (--area/--project/--heading).`,
|
|
179
|
+
].join("\n");
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Emit the scheduling-intent hint and set the Usage exit code. Never opens the
|
|
183
|
+
* write pipeline — it only rewrites the failing invocation into a working one.
|
|
184
|
+
*/
|
|
185
|
+
export function runMoveHint(hint) {
|
|
186
|
+
if (hint.json) {
|
|
187
|
+
const meta = { dbVersion: null, fingerprint: "unknown", elapsedMs: 0 };
|
|
188
|
+
const message = `${leadLine(hint).replace(/^error: /, "")} ${actionLine(hint)}`;
|
|
189
|
+
process.stdout.write(`${JSON.stringify(errorEnvelope({ code: "usage", message, details: { suggestions: [hint.suggestion] } }, meta))}\n`);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
process.stderr.write(`${renderHuman(hint)}\n`);
|
|
193
|
+
}
|
|
194
|
+
process.exitCode = ExitCode.Usage;
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=move-hint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"move-hint.js","sourceRoot":"","sources":["../../src/cli/move-hint.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/period.d.ts
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Period-and-calendar grammar shared by the read views: the `--since`/`--until`
|
|
3
|
-
* whole-period parsers, the relative-period (`3d`/`2w`/`1m`/`1y`) grammar, and
|
|
4
|
-
* the Upcoming date-bucket labeller. Fully pure — no CLI or app imports — so
|
|
5
|
-
* the renderers and command registrations can both draw on it.
|
|
6
|
-
*/
|
|
7
1
|
declare const FULL_MONTHS: readonly ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
8
2
|
export { FULL_MONTHS };
|
|
9
3
|
/**
|
|
@@ -19,14 +13,14 @@ export declare function doublePeriod(period: string): string;
|
|
|
19
13
|
* periods (`2w`, `1m`, `1y`) count FORWARD from now through the end of the
|
|
20
14
|
* landing day; anything else parses as an instant.
|
|
21
15
|
*/
|
|
22
|
-
export declare function parsePeriodEnd(s: string, now?: Date): Date;
|
|
16
|
+
export declare function parsePeriodEnd(s: string, now?: Date, zone?: string): Date;
|
|
23
17
|
/**
|
|
24
18
|
* `--since` accepting the same vocabulary at the period's START: `2024` =
|
|
25
19
|
* Jan 1 2024 00:00, `2024-03` = Mar 1, `2024-03-05` = that midnight;
|
|
26
20
|
* relative periods (`2w`, `1m`) count BACKWARD from now to the landing
|
|
27
21
|
* day's midnight; anything else parses as an instant.
|
|
28
22
|
*/
|
|
29
|
-
export declare function parsePeriodStart(s: string, now?: Date): Date;
|
|
23
|
+
export declare function parsePeriodStart(s: string, now?: Date, zone?: string): Date;
|
|
30
24
|
/**
|
|
31
25
|
* GUI-style Upcoming bucket for a date, granularity decaying with distance:
|
|
32
26
|
* individual days for the next week ("Wed Jul 15"), the remainder of the
|
package/dist/cli/period.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Period-and-calendar grammar shared by the read views: the `--since`/`--until`
|
|
3
3
|
* whole-period parsers, the relative-period (`3d`/`2w`/`1m`/`1y`) grammar, and
|
|
4
|
-
* the Upcoming date-bucket labeller.
|
|
5
|
-
* the
|
|
4
|
+
* the Upcoming date-bucket labeller. The only library dependency is the pair of
|
|
5
|
+
* zone-aware date helpers (through the single entry point) so a `--since 2w` is
|
|
6
|
+
* counted in the CONSUMER'S calendar, not the host's — byte-identical to the
|
|
7
|
+
* host math when no zone is in effect.
|
|
6
8
|
*/
|
|
9
|
+
import { dayBoundInstant, localToday } from "../index.js";
|
|
7
10
|
const FULL_MONTHS = [
|
|
8
11
|
"January",
|
|
9
12
|
"February",
|
|
@@ -40,19 +43,45 @@ export { FULL_MONTHS };
|
|
|
40
43
|
* bound (each command's natural direction; the flag name carries it).
|
|
41
44
|
*/
|
|
42
45
|
const RELATIVE_PERIOD = /^(\d+)([dwmy])$/i;
|
|
43
|
-
|
|
46
|
+
/** Format a UTC-anchored Date's date fields as `YYYY-MM-DD`. */
|
|
47
|
+
function isoFromUtc(dt) {
|
|
48
|
+
return `${String(dt.getUTCFullYear()).padStart(4, "0")}-${String(dt.getUTCMonth() + 1).padStart(2, "0")}-${String(dt.getUTCDate()).padStart(2, "0")}`;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The target CALENDAR date for a relative period, counted from a base ISO date
|
|
52
|
+
* (the consumer's today) — days/weeks add days, months/years use the JS Date
|
|
53
|
+
* overflow the host arithmetic always used (Jan 31 + 1m → Mar 3). Pure calendar
|
|
54
|
+
* math on the date fields (UTC-anchored so the host zone never intrudes), so it
|
|
55
|
+
* is zone-agnostic once the base date is chosen.
|
|
56
|
+
*/
|
|
57
|
+
function relativeTargetIso(m, baseIso, sign) {
|
|
58
|
+
const [y, mo, d] = baseIso.split("-").map(Number);
|
|
59
|
+
const dt = new Date(Date.UTC(y ?? 1970, (mo ?? 1) - 1, d ?? 1));
|
|
44
60
|
const n = sign * Number(m[1]);
|
|
45
61
|
const unit = (m[2] ?? "").toLowerCase();
|
|
46
|
-
const d = new Date(now);
|
|
47
62
|
if (unit === "d")
|
|
48
|
-
|
|
63
|
+
dt.setUTCDate(dt.getUTCDate() + n);
|
|
49
64
|
else if (unit === "w")
|
|
50
|
-
|
|
65
|
+
dt.setUTCDate(dt.getUTCDate() + 7 * n);
|
|
51
66
|
else if (unit === "m")
|
|
52
|
-
|
|
67
|
+
dt.setUTCMonth(dt.getUTCMonth() + n);
|
|
53
68
|
else
|
|
54
|
-
|
|
55
|
-
return
|
|
69
|
+
dt.setUTCFullYear(dt.getUTCFullYear() + n);
|
|
70
|
+
return isoFromUtc(dt);
|
|
71
|
+
}
|
|
72
|
+
/** The ISO date at a whole absolute period's START or END edge (`2024` → Jan 1 / Dec 31, etc.). */
|
|
73
|
+
function absolutePeriodIso(m, edge) {
|
|
74
|
+
const year = Number(m[1]);
|
|
75
|
+
if (m[2] === undefined)
|
|
76
|
+
return edge === "start" ? `${m[1]}-01-01` : `${m[1]}-12-31`;
|
|
77
|
+
const month = Number(m[2]) - 1;
|
|
78
|
+
if (m[3] === undefined) {
|
|
79
|
+
if (edge === "start")
|
|
80
|
+
return `${m[1]}-${m[2]}-01`;
|
|
81
|
+
const lastDay = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
|
|
82
|
+
return `${m[1]}-${m[2]}-${String(lastDay).padStart(2, "0")}`;
|
|
83
|
+
}
|
|
84
|
+
return `${m[1]}-${m[2]}-${m[3]}`;
|
|
56
85
|
}
|
|
57
86
|
/**
|
|
58
87
|
* Double a relative period for a "wider window" suggestion: `1m`→`2m`,
|
|
@@ -72,23 +101,15 @@ export function doublePeriod(period) {
|
|
|
72
101
|
* periods (`2w`, `1m`, `1y`) count FORWARD from now through the end of the
|
|
73
102
|
* landing day; anything else parses as an instant.
|
|
74
103
|
*/
|
|
75
|
-
export function parsePeriodEnd(s, now = new Date()) {
|
|
104
|
+
export function parsePeriodEnd(s, now = new Date(), zone) {
|
|
76
105
|
const rel = RELATIVE_PERIOD.exec(s.trim());
|
|
77
106
|
if (rel !== null) {
|
|
78
|
-
|
|
79
|
-
return new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59, 999);
|
|
107
|
+
return dayBoundInstant(relativeTargetIso(rel, localToday(now, zone), 1), "end", zone);
|
|
80
108
|
}
|
|
81
109
|
const m = /^(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?$/.exec(s.trim());
|
|
82
110
|
if (m === null)
|
|
83
111
|
return new Date(s);
|
|
84
|
-
|
|
85
|
-
// Day 0 of month n+1 = the last day of month n.
|
|
86
|
-
if (m[2] === undefined)
|
|
87
|
-
return new Date(year, 11, 31, 23, 59, 59, 999);
|
|
88
|
-
const month = Number(m[2]) - 1;
|
|
89
|
-
if (m[3] === undefined)
|
|
90
|
-
return new Date(year, month + 1, 0, 23, 59, 59, 999);
|
|
91
|
-
return new Date(year, month, Number(m[3]), 23, 59, 59, 999);
|
|
112
|
+
return dayBoundInstant(absolutePeriodIso(m, "end"), "end", zone);
|
|
92
113
|
}
|
|
93
114
|
/**
|
|
94
115
|
* `--since` accepting the same vocabulary at the period's START: `2024` =
|
|
@@ -96,22 +117,15 @@ export function parsePeriodEnd(s, now = new Date()) {
|
|
|
96
117
|
* relative periods (`2w`, `1m`) count BACKWARD from now to the landing
|
|
97
118
|
* day's midnight; anything else parses as an instant.
|
|
98
119
|
*/
|
|
99
|
-
export function parsePeriodStart(s, now = new Date()) {
|
|
120
|
+
export function parsePeriodStart(s, now = new Date(), zone) {
|
|
100
121
|
const rel = RELATIVE_PERIOD.exec(s.trim());
|
|
101
122
|
if (rel !== null) {
|
|
102
|
-
|
|
103
|
-
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
123
|
+
return dayBoundInstant(relativeTargetIso(rel, localToday(now, zone), -1), "start", zone);
|
|
104
124
|
}
|
|
105
125
|
const m = /^(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?$/.exec(s.trim());
|
|
106
126
|
if (m === null)
|
|
107
127
|
return new Date(s);
|
|
108
|
-
|
|
109
|
-
if (m[2] === undefined)
|
|
110
|
-
return new Date(year, 0, 1);
|
|
111
|
-
const month = Number(m[2]) - 1;
|
|
112
|
-
if (m[3] === undefined)
|
|
113
|
-
return new Date(year, month, 1);
|
|
114
|
-
return new Date(year, month, Number(m[3]));
|
|
128
|
+
return dayBoundInstant(absolutePeriodIso(m, "start"), "start", zone);
|
|
115
129
|
}
|
|
116
130
|
/**
|
|
117
131
|
* GUI-style Upcoming bucket for a date, granularity decaying with distance:
|