@duyquangnvx/agent-cli 0.4.0 → 0.6.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 (161) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/dist/agent-cli.js +2 -2
  3. package/dist/agent-cli.js.map +1 -1
  4. package/dist/agent.d.ts +5 -3
  5. package/dist/agent.js +31 -10
  6. package/dist/agent.js.map +1 -1
  7. package/dist/built-ins/commands.d.ts +8 -0
  8. package/dist/{built-ins.js → built-ins/commands.js} +4 -4
  9. package/dist/built-ins/commands.js.map +1 -0
  10. package/dist/built-ins/doctor-rows.d.ts +4 -0
  11. package/dist/{doctor-rows.js → built-ins/doctor-rows.js} +18 -26
  12. package/dist/built-ins/doctor-rows.js.map +1 -0
  13. package/dist/built-ins/doctor.d.ts +5 -0
  14. package/dist/{doctor.js → built-ins/doctor.js} +27 -20
  15. package/dist/built-ins/doctor.js.map +1 -0
  16. package/dist/{global-install.js → built-ins/global-install.js} +1 -1
  17. package/dist/built-ins/global-install.js.map +1 -0
  18. package/dist/{npm.d.ts → built-ins/npm.d.ts} +5 -2
  19. package/dist/{npm.js → built-ins/npm.js} +25 -33
  20. package/dist/built-ins/npm.js.map +1 -0
  21. package/dist/built-ins/semver.js.map +1 -0
  22. package/dist/built-ins/skills.d.ts +18 -0
  23. package/dist/built-ins/skills.js +97 -0
  24. package/dist/built-ins/skills.js.map +1 -0
  25. package/dist/{update.d.ts → built-ins/update.d.ts} +3 -2
  26. package/dist/{update.js → built-ins/update.js} +28 -18
  27. package/dist/built-ins/update.js.map +1 -0
  28. package/dist/{upgrade-notes.js → built-ins/upgrade-notes.js} +1 -1
  29. package/dist/built-ins/upgrade-notes.js.map +1 -0
  30. package/dist/clock.d.ts +1 -0
  31. package/dist/clock.js.map +1 -1
  32. package/dist/command-spec.d.ts +17 -2
  33. package/dist/command-spec.js +30 -9
  34. package/dist/command-spec.js.map +1 -1
  35. package/dist/confirm.js +6 -2
  36. package/dist/confirm.js.map +1 -1
  37. package/dist/context.d.ts +139 -0
  38. package/dist/context.js +2 -0
  39. package/dist/context.js.map +1 -0
  40. package/dist/cost.js +2 -2
  41. package/dist/cost.js.map +1 -1
  42. package/dist/define.d.ts +100 -87
  43. package/dist/define.js +3 -1
  44. package/dist/define.js.map +1 -1
  45. package/dist/errno.d.ts +8 -4
  46. package/dist/errno.js +21 -4
  47. package/dist/errno.js.map +1 -1
  48. package/dist/error-table.d.ts +6 -1
  49. package/dist/error-table.js +5 -1
  50. package/dist/error-table.js.map +1 -1
  51. package/dist/errors.d.ts +11 -2
  52. package/dist/errors.js +21 -8
  53. package/dist/errors.js.map +1 -1
  54. package/dist/execute.d.ts +9 -2
  55. package/dist/execute.js +10 -3
  56. package/dist/execute.js.map +1 -1
  57. package/dist/exit-classes.js +38 -38
  58. package/dist/exit-classes.js.map +1 -1
  59. package/dist/files.d.ts +30 -8
  60. package/dist/files.js +104 -17
  61. package/dist/files.js.map +1 -1
  62. package/dist/help-json.d.ts +2 -2
  63. package/dist/help-json.js +6 -2
  64. package/dist/help-json.js.map +1 -1
  65. package/dist/help.d.ts +1 -1
  66. package/dist/help.js +14 -9
  67. package/dist/help.js.map +1 -1
  68. package/dist/index.d.ts +12 -5
  69. package/dist/index.js +6 -2
  70. package/dist/index.js.map +1 -1
  71. package/dist/input.d.ts +7 -1
  72. package/dist/input.js +33 -4
  73. package/dist/input.js.map +1 -1
  74. package/dist/interrupts.d.ts +7 -2
  75. package/dist/interrupts.js +29 -15
  76. package/dist/interrupts.js.map +1 -1
  77. package/dist/invocation.d.ts +10 -5
  78. package/dist/invocation.js +24 -11
  79. package/dist/invocation.js.map +1 -1
  80. package/dist/list.d.ts +12 -3
  81. package/dist/list.js +38 -6
  82. package/dist/list.js.map +1 -1
  83. package/dist/manifest.d.ts +17 -0
  84. package/dist/manifest.js +24 -0
  85. package/dist/manifest.js.map +1 -0
  86. package/dist/operator.d.ts +5 -0
  87. package/dist/operator.js +15 -0
  88. package/dist/operator.js.map +1 -0
  89. package/dist/output.d.ts +6 -4
  90. package/dist/output.js +5 -6
  91. package/dist/output.js.map +1 -1
  92. package/dist/outputs.d.ts +24 -1
  93. package/dist/outputs.js +58 -2
  94. package/dist/outputs.js.map +1 -1
  95. package/dist/parse-input.d.ts +11 -2
  96. package/dist/parse-input.js +78 -27
  97. package/dist/parse-input.js.map +1 -1
  98. package/dist/project.d.ts +3 -2
  99. package/dist/project.js +11 -10
  100. package/dist/project.js.map +1 -1
  101. package/dist/route.d.ts +1 -1
  102. package/dist/route.js +2 -1
  103. package/dist/route.js.map +1 -1
  104. package/dist/run-cli.d.ts +8 -33
  105. package/dist/run-cli.js +50 -157
  106. package/dist/run-cli.js.map +1 -1
  107. package/dist/run-command.d.ts +11 -0
  108. package/dist/run-command.js +234 -0
  109. package/dist/run-command.js.map +1 -0
  110. package/dist/run-options.d.ts +48 -0
  111. package/dist/run-options.js +2 -0
  112. package/dist/run-options.js.map +1 -0
  113. package/dist/run-process.js +7 -4
  114. package/dist/run-process.js.map +1 -1
  115. package/dist/secrets.d.ts +10 -6
  116. package/dist/secrets.js +8 -9
  117. package/dist/secrets.js.map +1 -1
  118. package/dist/side-task.d.ts +27 -0
  119. package/dist/side-task.js +31 -0
  120. package/dist/side-task.js.map +1 -0
  121. package/dist/spawn.d.ts +29 -6
  122. package/dist/spawn.js +126 -29
  123. package/dist/spawn.js.map +1 -1
  124. package/dist/spill.d.ts +4 -3
  125. package/dist/spill.js +1 -7
  126. package/dist/spill.js.map +1 -1
  127. package/dist/stdin.d.ts +33 -0
  128. package/dist/stdin.js +92 -0
  129. package/dist/stdin.js.map +1 -0
  130. package/dist/style.d.ts +1 -1
  131. package/dist/tokenize.d.ts +3 -0
  132. package/dist/tokenize.js +5 -4
  133. package/dist/tokenize.js.map +1 -1
  134. package/dist/tools.d.ts +6 -3
  135. package/dist/tools.js +18 -11
  136. package/dist/tools.js.map +1 -1
  137. package/dist/usage.d.ts +2 -0
  138. package/dist/usage.js +12 -1
  139. package/dist/usage.js.map +1 -1
  140. package/dist/version.d.ts +3 -0
  141. package/dist/version.js +7 -0
  142. package/dist/version.js.map +1 -0
  143. package/package.json +1 -1
  144. package/dist/built-ins.d.ts +0 -3
  145. package/dist/built-ins.js.map +0 -1
  146. package/dist/doctor-rows.d.ts +0 -3
  147. package/dist/doctor-rows.js.map +0 -1
  148. package/dist/doctor.d.ts +0 -4
  149. package/dist/doctor.js.map +0 -1
  150. package/dist/global-install.js.map +0 -1
  151. package/dist/npm.js.map +0 -1
  152. package/dist/semver.js.map +0 -1
  153. package/dist/skills.d.ts +0 -11
  154. package/dist/skills.js +0 -58
  155. package/dist/skills.js.map +0 -1
  156. package/dist/update.js.map +0 -1
  157. package/dist/upgrade-notes.js.map +0 -1
  158. /package/dist/{global-install.d.ts → built-ins/global-install.d.ts} +0 -0
  159. /package/dist/{semver.d.ts → built-ins/semver.d.ts} +0 -0
  160. /package/dist/{semver.js → built-ins/semver.js} +0 -0
  161. /package/dist/{upgrade-notes.d.ts → built-ins/upgrade-notes.d.ts} +0 -0
package/dist/define.d.ts CHANGED
@@ -1,82 +1,16 @@
1
1
  import type * as z from "zod";
2
- import type { Clock } from "./clock.js";
2
+ import type { BuildStamp, Context, PortsBase, ProjectFile } from "./context.js";
3
3
  import type { ErrorTable } from "./error-table.js";
4
- import type { Files } from "./files.js";
5
4
  import { type StandardFlagName } from "./flags.js";
6
5
  import type { Page, PageInput, RowSchema } from "./list.js";
7
- import type { Secret } from "./secrets.js";
8
- import type { ContextSpawn } from "./spawn.js";
6
+ import type { SideTaskRun } from "./side-task.js";
9
7
  import type { Style } from "./style.js";
10
- export type Env = Readonly<Record<string, string | undefined>>;
8
+ /** Shown in help and help JSON. */
11
9
  export interface Example {
10
+ /** A realistic full command line, starting with the CLI's name. */
12
11
  readonly command: string;
13
12
  readonly note: string;
14
13
  }
15
- export interface PollOptions {
16
- readonly intervalMs: number;
17
- }
18
- export interface Context<Ports = unknown, Settings = unknown> {
19
- readonly cwd: string;
20
- readonly env: Env;
21
- /** The folder holding this CLI's `package.json`, for reading files shipped in the package. */
22
- readonly packageRoot: string;
23
- /** Writes a plain line to stderr, for long work; it never reaches stdout. */
24
- progress(message: string): void;
25
- /**
26
- * Aborts when the run is interrupted (Ctrl-C) or hits the Command's run deadline; pass it to
27
- * `fetch` and child processes.
28
- */
29
- readonly signal: AbortSignal;
30
- /** Returns a signal that also aborts, with `DEADLINE_EXCEEDED`, once `ms` have passed. */
31
- deadline(ms: number): AbortSignal;
32
- /**
33
- * Runs a step that must not stop halfway: the run waits for it even when stopped, and then
34
- * prints `finishing <name>` on stderr.
35
- */
36
- runToEnd<T>(name: string, work: () => Promise<T>): Promise<T>;
37
- /**
38
- * Records the data done so far, in the shape `render` takes; the last call wins. A run that then
39
- * fails, hits a deadline or is interrupted prints it; a returned value replaces it.
40
- */
41
- deliver(data: unknown): void;
42
- /** The outside systems the CLI declared with `agentCli<Ports>()`. */
43
- readonly ports: Ports;
44
- /**
45
- * Reads, lists, removes and atomically writes files and folders, paths resolved against `cwd`; a
46
- * failure fails the run with `PERMISSION_DENIED`, `DISK_FULL`, `NOT_FOUND` or `ALREADY_EXISTS`.
47
- */
48
- readonly files: Files;
49
- /**
50
- * Runs a child process, killed when the run is interrupted; `check: true` fails the run with
51
- * `TOOL_FAILED` and the tail of its stderr when it exits non-zero.
52
- */
53
- readonly spawn: ContextSpawn;
54
- /** Deadlines, `poll` and the grace period after an interrupt run on it. */
55
- readonly clock: Clock;
56
- /**
57
- * Calls `check` until it returns a value other than `undefined`, sleeping `intervalMs` between
58
- * calls; it stops when `ctx.signal` aborts.
59
- */
60
- poll<T>(check: () => T | undefined | Promise<T | undefined>, options: PollOptions): Promise<T>;
61
- /** The Project file found by walking up from `cwd`, parsed by the CLI's schema. */
62
- readonly project: Project<Settings> | undefined;
63
- /** Reads `name` from the env, then from `$XDG_CONFIG_HOME/<cli>/.env`, with where it came from. */
64
- secret(name: string): Secret | undefined;
65
- /** Whether the caller passed `--force`; always false for a Command without it. */
66
- readonly force: boolean;
67
- }
68
- /** The slice of `Context` the ports factory receives, which exists before the ports do. */
69
- export type PortsBase = Pick<Context, "env" | "cwd" | "packageRoot" | "secret" | "spawn" | "files" | "clock" | "signal">;
70
- export interface Project<Settings = unknown> {
71
- /** The folder holding the Project file. */
72
- readonly root: string;
73
- readonly settings: Settings;
74
- }
75
- /** Names the Project file and the schema its JSON must match. */
76
- export interface ProjectFile<Settings = unknown> {
77
- readonly file: string;
78
- readonly schema: z.ZodType<Settings>;
79
- }
80
14
  export type InputSchema = z.ZodObject;
81
15
  export type NoPorts = Record<never, never>;
82
16
  export type NoInput = z.ZodObject<Record<never, never>>;
@@ -94,52 +28,103 @@ export interface Tool {
94
28
  /** Bounds a whole run, so a long run stops before the caller's own timeout and can be continued. */
95
29
  export interface RunDeadline<In> {
96
30
  readonly ms: number;
97
- /** The command line that continues the work, given as the hint of the run's `DEADLINE_EXCEEDED`. */
98
- resume(input: In): string;
31
+ /**
32
+ * The command line that continues the work, given as the hint of the run's `DEADLINE_EXCEEDED`;
33
+ * `commandLine` is `ctx.commandLine`. Once the deadline passes, every error of the run becomes
34
+ * `DEADLINE_EXCEEDED`.
35
+ */
36
+ resume(input: In, commandLine: Context["commandLine"]): string;
99
37
  }
100
38
  interface CommandBase<Args extends InputSchema, Options extends InputSchema> {
39
+ /** The word the Command is listed under in `commands`; it labels the Command in errors and spill files. */
101
40
  readonly name: string;
41
+ /** One line, shown in help and help JSON. */
102
42
  readonly description: string;
43
+ /** A paragraph printed after the options in text help, and carried as `help` in help JSON. */
44
+ readonly help?: string;
103
45
  readonly examples: readonly Example[];
104
- /** Missing ones fail the run with `TOOL_MISSING` before `plan`, `run` or `start`. */
46
+ /** Left out of help, help JSON, the root examples and suggestions, but still routed and run. */
47
+ readonly hidden?: boolean;
48
+ /**
49
+ * Only a person at a terminal runs it: under a Coding agent the run fails with `NEEDS_OPERATOR`
50
+ * (exit 2) before its input is read, stdin included, and the hint asks the operator to type the
51
+ * command line after `!`. `--json` alone does not make it refuse.
52
+ */
53
+ readonly operator?: true;
54
+ /**
55
+ * Looked up before `plan`, `run` or `start`, `--dry-run` included: missing ones fail the run with
56
+ * `TOOL_MISSING` (exit 2), naming each with its `install`, and `doctor` checks each.
57
+ */
105
58
  readonly tools?: readonly Tool[];
59
+ /**
60
+ * Positional operands, in the schema's order; each field's `.describe()` is its help. The last
61
+ * field may be a `z.array(...)`, which takes every remaining operand, and one string field may be
62
+ * wrapped in `orStdin`. Input the schema rejects is a usage error (exit 1) before the Command runs.
63
+ */
106
64
  readonly args?: Args;
65
+ /**
66
+ * Flags, a camelCase key typed in kebab-case; each field's `.describe()` is its help. A
67
+ * `z.array(...)` option collects every occurrence of its flag in order, and a repeated scalar flag
68
+ * keeps its last value. Input the schema rejects is a usage error (exit 1) before the Command runs.
69
+ */
107
70
  readonly options?: Options;
108
71
  /** At `ms`, `ctx.signal` aborts and the run ends with `DEADLINE_EXCEEDED` (exit 75). */
109
72
  readonly deadline?: RunDeadline<Input<Args, Options>>;
110
73
  }
111
74
  interface UnpagedCommand<Args extends InputSchema, Options extends InputSchema> extends CommandBase<Args, Options> {
75
+ /** The schema of the data the Command prints, published as JSON Schema in help JSON. */
112
76
  readonly output?: z.ZodType;
113
77
  readonly rows?: never;
114
78
  }
115
79
  export interface ReadCommand<Args extends InputSchema, Options extends InputSchema, Data, Ports = unknown, Settings = unknown> extends UnpagedCommand<Args, Options> {
116
80
  readonly effect: "read";
117
81
  run(input: Input<Args, Options>, ctx: Context<Ports, Settings>): Data | Promise<Data>;
82
+ /**
83
+ * Turns the data into short text; `--json` prints the data itself. `style` colours only when a
84
+ * person watches a terminal or `FORCE_COLOR` is set.
85
+ */
118
86
  render(data: Data, style: Style): string;
119
87
  }
120
- /** A read Command whose data is a page of rows; the Runtime adds `--limit`, `--cursor` and `--fields`. */
88
+ /**
89
+ * A read Command whose data is a page of rows, from `paginate` or `page`; the Runtime adds `--limit`
90
+ * (default 20), `--cursor` and `--fields`, and prints the page as `{ items, next? }`, `next` being
91
+ * the command line for the following page, and as text ends it with a line saying how many rows were
92
+ * shown and either that command line or that no pages remain. A page never spills, and `--fields` keeps only the named fields.
93
+ */
121
94
  export interface ListCommand<Args extends InputSchema, Options extends InputSchema, Row extends RowSchema, Ports = unknown, Settings = unknown> extends CommandBase<Args, Options> {
122
95
  readonly effect: "read";
123
96
  /** The schema of one row; the page's output schema is derived from it. */
124
97
  readonly rows: Row;
125
98
  readonly output?: never;
126
99
  run(input: Flatten<OutputOf<Args> & OutputOf<Options> & PageInput>, ctx: Context<Ports, Settings>): Page<z.output<Row>> | Promise<Page<z.output<Row>>>;
100
+ /** Receives the page; render `page.items`. */
127
101
  render(page: Page<z.output<Row>>, style: Style): string;
128
102
  }
129
- /** A Command that changes something: `plan` has no side effects, `apply` performs the Plan. */
103
+ /**
104
+ * A Command that changes something: `plan` has no side effects, `apply` performs the Plan. The
105
+ * Runtime adds `--dry-run`, which prints the Plan and stops; between `plan` and `apply` it checks
106
+ * `outputs`, then `cost`, then `confirm`, each refusal's hint holding the command line plus its flag.
107
+ */
130
108
  interface PlannedCommand<Args extends InputSchema, Options extends InputSchema, Plan, Data, Ports, Settings> extends UnpagedCommand<Args, Options> {
131
109
  plan(input: Input<Args, Options>, ctx: Context<Ports, Settings>): Plan | Promise<Plan>;
132
110
  apply(plan: Plan, ctx: Context<Ports, Settings>): Data | Promise<Data>;
133
111
  render(data: Data, style: Style): string;
112
+ /**
113
+ * `--dry-run --json` prints the Plan itself, or `{ plan, outputs?, cost }` when the Command
114
+ * declares `outputs` or `cost`; a byte array in it prints as an index-keyed object.
115
+ */
134
116
  renderPlan(plan: Plan, style: Style): string;
135
117
  /**
136
118
  * A sentence stating what the Plan costs, or undefined when it is cheap. Declaring it adds
137
- * `--yes`, which a run must pass whenever it returns a sentence.
119
+ * `--yes`; a run whose cost is a sentence and lacks it refuses with `NOT_CONFIRMED` (exit 2), and
120
+ * `--dry-run` prints `cost: <sentence>`.
138
121
  */
139
122
  cost?(plan: Plan): string | undefined;
140
123
  /**
141
124
  * The files the Plan writes, relative to `ctx.cwd`. Declaring it adds `--force`, without which
142
- * a run refuses with `OUTPUT_EXISTS` when any of them exists.
125
+ * a run refuses with `OUTPUT_EXISTS` (exit 1) when any of them exists, and `--dry-run` lists them.
126
+ * Before `apply` the Runtime creates each one's folder and a temp file in it, so a sandbox denial
127
+ * fails with `PERMISSION_DENIED` first; without `--force` the first write to each is exclusive.
143
128
  */
144
129
  outputs?(plan: Plan): readonly string[];
145
130
  /**
@@ -153,10 +138,16 @@ export interface WriteCommand<Args extends InputSchema, Options extends InputSch
153
138
  }
154
139
  export interface DestructiveCommand<Args extends InputSchema, Options extends InputSchema, Plan, Data, Ports = unknown, Settings = unknown> extends PlannedCommand<Args, Options, Plan, Data, Ports, Settings> {
155
140
  readonly effect: "destructive";
156
- /** The value the caller must repeat as `--confirm`, naming the target the Plan changes. */
141
+ /**
142
+ * The value the caller must repeat as `--confirm`, naming the target the Plan changes; without it
143
+ * the run refuses with exit 1.
144
+ */
157
145
  confirm(plan: Plan): string;
158
146
  }
159
- /** A Command that keeps running, such as a preview server, until Ctrl-C or SIGTERM stops it. */
147
+ /**
148
+ * A Command that keeps running, such as a preview server, until Ctrl-C or SIGTERM stops it with
149
+ * exit 0. Of the Standard flags it gets only `--json`.
150
+ */
160
151
  export interface ServeCommand<Args extends InputSchema, Options extends InputSchema, Data, Ports = unknown, Settings = unknown> extends UnpagedCommand<Args, Options> {
161
152
  readonly effect: "serve";
162
153
  /** Starts the work and returns its data, which prints at once; stop the work on `ctx.signal`. */
@@ -170,17 +161,27 @@ export interface Commands<Ports = unknown, Settings = unknown> {
170
161
  interface CliBase<Ports, Settings> {
171
162
  readonly name: string;
172
163
  readonly version: string;
164
+ /** One line saying what the CLI does, shown under the first line of its help and in help JSON. */
165
+ readonly description: string;
173
166
  /** The commit the build was made from and when, stamped by the bundler; `--version` prints it. */
174
- readonly build?: {
175
- readonly sha: string;
176
- readonly dirty: boolean;
177
- readonly builtAt: string;
178
- };
167
+ readonly build?: BuildStamp;
179
168
  /** Every code the CLI throws; a code missing here exits 70, as a bug. */
180
169
  readonly errors?: ErrorTable;
181
170
  /** Builds the real ports when a run first reads `ctx.ports`; `runCli`'s `ports` replaces them in a test. */
182
171
  readonly ports?: (base: PortsBase) => Ports;
183
172
  readonly project?: ProjectFile<Settings>;
173
+ /** Where `npx skills add` installs the CLI's skill from; read from package.json `repository` when absent. */
174
+ readonly skill?: {
175
+ readonly source: string;
176
+ };
177
+ /**
178
+ * Work that runs beside every Command run, such as a usage count; return `undefined` to decline.
179
+ * It starts once the input is parsed, before `plan`, `run` or `start`, so it also runs for a run a
180
+ * guard refuses, and once the output is written the run waits for it at most `SIDE_TASK_WAIT_MS`.
181
+ * Nothing it throws changes stdout, stderr or the exit code; `<NAME>_DEBUG=1` prints it on stderr.
182
+ * It never runs for help, `--version`, a usage error or a built-in Command.
183
+ */
184
+ sideTask?(run: SideTaskRun<Ports>): Promise<void> | undefined;
184
185
  }
185
186
  /** Where an Agent CLI is published and how it is installed; `doctor` and `update` read it. */
186
187
  export interface GlobalInstall {
@@ -188,12 +189,22 @@ export interface GlobalInstall {
188
189
  readonly package: string;
189
190
  readonly registry: string;
190
191
  }
191
- export interface DoctorFinding {
192
- readonly state: "ok" | "problem";
192
+ /** What a `doctor` row found. A skipped row was not checked, and never fails `doctor`. */
193
+ export type DoctorFinding = {
194
+ readonly state: "ok";
195
+ readonly message: string;
196
+ readonly fix?: string;
197
+ } | {
198
+ readonly state: "problem";
193
199
  readonly message: string;
194
200
  /** The command that fixes the problem. */
195
201
  readonly fix?: string;
196
- }
202
+ /** A code of the Error table or the Runtime's that `doctor` fails with; `DOCTOR_PROBLEMS` when absent. */
203
+ readonly code?: string;
204
+ } | {
205
+ readonly state: "skipped";
206
+ readonly message: string;
207
+ };
197
208
  /** A row the CLI adds to `doctor`, for a system it depends on. */
198
209
  export interface DoctorCheck<Ports = unknown, Settings = unknown> {
199
210
  readonly name: string;
@@ -215,6 +226,8 @@ export interface CommandTreeCli<Ports = unknown, Settings = unknown> extends Cli
215
226
  readonly node?: string;
216
227
  };
217
228
  readonly doctor?: readonly DoctorCheck<Ports, Settings>[];
229
+ /** Tools `doctor` checks besides the Commands' own; no Command requires them. */
230
+ readonly tools?: readonly Tool[];
218
231
  }
219
232
  /** An Agent CLI that is one Command, run with no Command name, as in `tool <args>`. */
220
233
  export interface SingleCommandCli<Ports = unknown, Settings = unknown> extends CliBase<Ports, Settings> {
package/dist/define.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { checkForce, checkNoStandardFlags } from "./flags.js";
2
- import { checkArrayArgLast } from "./input.js";
2
+ import { checkArrayArgLast, checkNoBooleanArrayOption, checkStdinFields } from "./input.js";
3
3
  function checkedCommand(command) {
4
4
  checkNoStandardFlags(command);
5
5
  checkForce(command);
6
6
  checkArrayArgLast(command.name, command.args);
7
+ checkStdinFields(command.name, command.args, command.options);
8
+ checkNoBooleanArrayOption(command.name, command.options);
7
9
  return command;
8
10
  }
9
11
  export function defineCommandFor() {
@@ -1 +1 @@
1
- {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAyB,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA+V/C,SAAS,cAAc,CAA2B,OAAiB;IACjE,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,UAAU,CAAC,OAAO,CAAC,CAAC;IACpB,iBAAiB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAA2B,gBAAgB,EAAE,CAAC;AAExE,0FAA0F;AAC1F,MAAM,UAAU,SAAS,CAAC,IAAwB;IAChD,OAAO,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAyB,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAkW5F,SAAS,cAAc,CAA2B,OAAiB;IACjE,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,UAAU,CAAC,OAAO,CAAC,CAAC;IACpB,iBAAiB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,yBAAyB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAA2B,gBAAgB,EAAE,CAAC;AAExE,0FAA0F;AAC1F,MAAM,UAAU,SAAS,CAAC,IAAwB;IAChD,OAAO,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC;AACzC,CAAC"}
package/dist/errno.d.ts CHANGED
@@ -1,15 +1,19 @@
1
- import type { Env } from "./define.js";
1
+ import type { Env } from "./context.js";
2
2
  export declare const PERMISSION_DENIED = "PERMISSION_DENIED";
3
3
  export declare const DISK_FULL = "DISK_FULL";
4
4
  export declare const NOT_FOUND = "NOT_FOUND";
5
5
  export declare const ALREADY_EXISTS = "ALREADY_EXISTS";
6
- export interface ErrnoContext {
6
+ export declare const NOT_A_FILE = "NOT_A_FILE";
7
+ export interface FileAccess {
7
8
  readonly path: string;
8
9
  /** Whether the failed access read `path` or wrote it; a sandbox grants the two separately. */
9
10
  readonly access: "read" | "write";
11
+ }
12
+ export type FileError = (error: unknown, at: FileAccess) => unknown;
13
+ export interface ErrnoScope {
10
14
  /** The caller's command line, ready to paste. */
11
15
  readonly callerLine: string;
12
16
  readonly env: Env;
17
+ readonly platform: NodeJS.Platform;
13
18
  }
14
- /** The error a file system failure on `path` stands for; any other error comes back unchanged. */
15
- export declare function classifyErrno(error: unknown, context: ErrnoContext): unknown;
19
+ export declare function fileErrorOf(scope: ErrnoScope): FileError;
package/dist/errno.js CHANGED
@@ -4,9 +4,13 @@ export const PERMISSION_DENIED = "PERMISSION_DENIED";
4
4
  export const DISK_FULL = "DISK_FULL";
5
5
  export const NOT_FOUND = "NOT_FOUND";
6
6
  export const ALREADY_EXISTS = "ALREADY_EXISTS";
7
+ export const NOT_A_FILE = "NOT_A_FILE";
7
8
  // The same errnos happen with no sandbox at all (a root-owned folder), so only a detected agent is
8
- // pointed at its sandbox.
9
- function permissionHint({ path, access, callerLine, env }) {
9
+ // pointed at its sandbox. Native Windows has no such sandbox: there a program holding the file denies it.
10
+ function permissionHint({ path, access, callerLine, env, platform }) {
11
+ if (platform === "win32") {
12
+ return `a program may hold ${path} open: close it, then run the same command again`;
13
+ }
10
14
  if (!isAgent(env))
11
15
  return `check the permissions of ${path} and its folder`;
12
16
  const allow = access === "read"
@@ -14,24 +18,31 @@ function permissionHint({ path, access, callerLine, env }) {
14
18
  : `to allow ${path} in the sandbox's write list`;
15
19
  return `your sandbox may block it: ask your user to run \`! ${callerLine}\`, or ${allow}`;
16
20
  }
17
- /** The error a file system failure on `path` stands for; any other error comes back unchanged. */
18
- export function classifyErrno(error, context) {
21
+ export function fileErrorOf(scope) {
22
+ return (error, at) => classifyErrno(error, { ...at, ...scope });
23
+ }
24
+ function classifyErrno(error, context) {
19
25
  const { path } = context;
20
26
  switch (errnoOf(error)) {
21
27
  case "EACCES":
22
28
  case "EPERM":
29
+ case "EROFS":
30
+ case "EBUSY":
23
31
  return new CliError({
24
32
  code: PERMISSION_DENIED,
25
33
  message: `permission denied: ${path}`,
26
34
  hint: permissionHint(context),
27
35
  }, { cause: error });
28
36
  case "ENOSPC":
37
+ case "EDQUOT":
29
38
  return new CliError({
30
39
  code: DISK_FULL,
31
40
  message: `no space left on the disk holding ${path}`,
32
41
  hint: "free space on that disk, then run the same command again",
33
42
  }, { cause: error });
34
43
  case "ENOENT":
44
+ case "ENOTDIR":
45
+ case "ENAMETOOLONG":
35
46
  return new CliError({
36
47
  code: NOT_FOUND,
37
48
  message: `not found: ${path}`,
@@ -43,6 +54,12 @@ export function classifyErrno(error, context) {
43
54
  message: `already exists: ${path}`,
44
55
  hint: `pass another path, or remove ${path}`,
45
56
  }, { cause: error });
57
+ case "EISDIR":
58
+ return new CliError({
59
+ code: NOT_A_FILE,
60
+ message: `not a file: ${path} is a folder`,
61
+ hint: `pass the path of a file, not of the folder ${path}`,
62
+ }, { cause: error });
46
63
  default:
47
64
  return error;
48
65
  }
package/dist/errno.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"errno.js","sourceRoot":"","sources":["../src/errno.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AACrD,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;AACrC,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;AACrC,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAW/C,mGAAmG;AACnG,0BAA0B;AAC1B,SAAS,cAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAgB;IACrE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,4BAA4B,IAAI,iBAAiB,CAAC;IAC5E,MAAM,KAAK,GACT,MAAM,KAAK,MAAM;QACf,CAAC,CAAC,oBAAoB,IAAI,iBAAiB;QAC3C,CAAC,CAAC,YAAY,IAAI,8BAA8B,CAAC;IACrD,OAAO,uDAAuD,UAAU,UAAU,KAAK,EAAE,CAAC;AAC5F,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,OAAqB;IACjE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzB,QAAQ,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,QAAQ,CAAC;QACd,KAAK,OAAO;YACV,OAAO,IAAI,QAAQ,CACjB;gBACE,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,sBAAsB,IAAI,EAAE;gBACrC,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC;aAC9B,EACD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO,IAAI,QAAQ,CACjB;gBACE,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,qCAAqC,IAAI,EAAE;gBACpD,IAAI,EAAE,0DAA0D;aACjE,EACD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO,IAAI,QAAQ,CACjB;gBACE,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,cAAc,IAAI,EAAE;gBAC7B,IAAI,EAAE,cAAc,IAAI,uBAAuB;aAChD,EACD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO,IAAI,QAAQ,CACjB;gBACE,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,mBAAmB,IAAI,EAAE;gBAClC,IAAI,EAAE,gCAAgC,IAAI,EAAE;aAC7C,EACD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"errno.js","sourceRoot":"","sources":["../src/errno.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import type { ExitClass } from "./exit-classes.js";
4
4
  /** The Exit classes a CLI's own code can have; a bug or an interrupt is the Runtime's to tell. */
5
5
  export type DeclaredExitClass = Exclude<ExitClass, "bug" | "interrupted">;
6
6
  export interface ErrorDeclaration {
7
+ /** Who must act, which sets the exit code: `caller` 1, `operator` 2, `source` 3, `wait` 75. */
7
8
  readonly class: DeclaredExitClass;
8
9
  readonly details?: z.ZodType;
9
10
  }
@@ -29,6 +30,10 @@ export type CliErrorInit<Declaration extends ErrorDeclaration> = {
29
30
  readonly message: string;
30
31
  readonly hint: string;
31
32
  } & DetailsInit<Declaration> & RetryInit<Declaration>;
32
- /** A `CliError` for a code of `table`, whose `details` must match the code's schema. */
33
+ /**
34
+ * A `CliError` for a code of `table`, whose `details` must match the code's schema. The `hint`
35
+ * names the next command to run and says whether running it again can help; `retryAt` (ISO 8601)
36
+ * is allowed only on a wait-class code.
37
+ */
33
38
  export declare function cliError<Table extends ErrorTable, Code extends keyof Table & string>(_table: Table, code: Code, init: CliErrorInit<Table[Code]>, options?: ErrorOptions): CliError;
34
39
  export {};
@@ -3,7 +3,11 @@ import { CliError } from "./errors.js";
3
3
  export function defineErrors(table) {
4
4
  return table;
5
5
  }
6
- /** A `CliError` for a code of `table`, whose `details` must match the code's schema. */
6
+ /**
7
+ * A `CliError` for a code of `table`, whose `details` must match the code's schema. The `hint`
8
+ * names the next command to run and says whether running it again can help; `retryAt` (ISO 8601)
9
+ * is allowed only on a wait-class code.
10
+ */
7
11
  export function cliError(_table, code, init, options) {
8
12
  return new CliError({ ...init, code }, options);
9
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"error-table.js","sourceRoot":"","sources":["../src/error-table.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAcvC,oGAAoG;AACpG,MAAM,UAAU,YAAY,CAAiC,KAAY;IACvE,OAAO,KAAK,CAAC;AACf,CAAC;AAmBD,wFAAwF;AACxF,MAAM,UAAU,QAAQ,CACtB,MAAa,EACb,IAAU,EACV,IAA+B,EAC/B,OAAsB;IAEtB,OAAO,IAAI,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC"}
1
+ {"version":3,"file":"error-table.js","sourceRoot":"","sources":["../src/error-table.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAevC,oGAAoG;AACpG,MAAM,UAAU,YAAY,CAAiC,KAAY;IACvE,OAAO,KAAK,CAAC;AACf,CAAC;AAmBD;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,MAAa,EACb,IAAU,EACV,IAA+B,EAC/B,OAAsB;IAEtB,OAAO,IAAI,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Env } from "./define.js";
1
+ import type { Env } from "./context.js";
2
2
  import type { Style } from "./style.js";
3
3
  export interface CliErrorFields {
4
4
  readonly code: string;
@@ -27,13 +27,22 @@ export interface ErrorFormat {
27
27
  readonly json: boolean;
28
28
  readonly env: Env;
29
29
  readonly style: Style;
30
+ /** Where the CLI takes bug reports, read from package.json `bugs` only when a hint names it. */
31
+ readonly bugs?: () => string | undefined;
30
32
  /** Whether `error` is a bug: not a `CliError`, or one whose code nobody declared. */
31
33
  readonly isBug: (error: unknown) => boolean;
32
34
  }
33
35
  export declare function errnoOf(error: unknown): string | undefined;
34
36
  export declare function isMissingFile(error: unknown): boolean;
37
+ export declare function isNothingThere(error: unknown): boolean;
35
38
  export declare function debugVariable(cliName: string): string;
36
39
  export declare function messageOf(error: unknown): string;
37
- /** The errors a run failed with: each one an `AggregateError` holds, or the one it threw. */
40
+ export declare function isDebug({ env, cliName }: Pick<ErrorFormat, "env" | "cliName">): boolean;
41
+ export declare function causesOf(error: unknown): unknown[];
42
+ export declare function traceOf(error: unknown): string;
43
+ /**
44
+ * The errors a run failed with: the leaves of nested `AggregateError`s, or the one it threw. An
45
+ * empty `AggregateError` is a leaf.
46
+ */
38
47
  export declare function errorsOf(error: unknown): readonly unknown[];
39
48
  export declare function formatRuntimeError(error: unknown, format: ErrorFormat): string;
package/dist/errors.js CHANGED
@@ -28,19 +28,27 @@ export function errnoOf(error) {
28
28
  export function isMissingFile(error) {
29
29
  return errnoOf(error) === "ENOENT";
30
30
  }
31
+ // ENOTDIR: a part of the path is a file, so nothing can exist under it.
32
+ export function isNothingThere(error) {
33
+ return isMissingFile(error) || errnoOf(error) === "ENOTDIR";
34
+ }
31
35
  export function debugVariable(cliName) {
32
36
  return `${cliName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_DEBUG`;
33
37
  }
34
38
  export function messageOf(error) {
35
39
  return error instanceof Error ? error.message : String(error);
36
40
  }
37
- function isDebug({ env, cliName }) {
41
+ export function isDebug({ env, cliName }) {
38
42
  return Boolean(env[debugVariable(cliName)]);
39
43
  }
40
44
  function bugHint(format) {
41
- return isDebug(format)
42
- ? "the stack trace shows where it failed"
43
- : `rerun with ${debugVariable(format.cliName)}=1 to see the stack trace`;
45
+ const bugs = format.bugs?.();
46
+ if (isDebug(format)) {
47
+ const where = "the stack trace shows where it failed";
48
+ return bugs === undefined ? where : `${where}; report it at ${bugs}`;
49
+ }
50
+ const rerun = `rerun with ${debugVariable(format.cliName)}=1 to see the stack trace`;
51
+ return bugs === undefined ? rerun : `${rerun}, then report it at ${bugs}`;
44
52
  }
45
53
  function fieldsOf(error, format) {
46
54
  if (error instanceof CliError) {
@@ -49,12 +57,12 @@ function fieldsOf(error, format) {
49
57
  }
50
58
  return { code: INTERNAL_CODE, message: messageOf(error), hint: bugHint(format) };
51
59
  }
52
- function causesOf(error) {
60
+ export function causesOf(error) {
53
61
  return error instanceof Error && error.cause !== undefined
54
62
  ? [error.cause, ...causesOf(error.cause)]
55
63
  : [];
56
64
  }
57
- function traceOf(error) {
65
+ export function traceOf(error) {
58
66
  return error instanceof Error ? (error.stack ?? error.message) : String(error);
59
67
  }
60
68
  /** Under debug: a bug's stack trace, then every error's cause chain. */
@@ -67,9 +75,14 @@ function debugTrace(error, format) {
67
75
  ];
68
76
  return lines.length === 0 ? undefined : lines.join("\n");
69
77
  }
70
- /** The errors a run failed with: each one an `AggregateError` holds, or the one it threw. */
78
+ /**
79
+ * The errors a run failed with: the leaves of nested `AggregateError`s, or the one it threw. An
80
+ * empty `AggregateError` is a leaf.
81
+ */
71
82
  export function errorsOf(error) {
72
- return error instanceof AggregateError && error.errors.length > 0 ? error.errors : [error];
83
+ return error instanceof AggregateError && error.errors.length > 0
84
+ ? error.errors.flatMap(errorsOf)
85
+ : [error];
73
86
  }
74
87
  function errorLines(error, format) {
75
88
  const fields = fieldsOf(error, format);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAaA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,CAAS;IACb,IAAI,CAAS;IACb,OAAO,CAAU;IACjB,OAAO,CAAqB;IAErC,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAkB,EAAE,OAAsB;QAC3F,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAID,0EAA0E;AAC1E,MAAM,OAAO,UAAW,SAAQ,QAAQ;IACtC,YAAY,MAAwB;QAClC,KAAK,CAAC,MAAM,CAAC,CAAC;QACd,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;AAaxC,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAChF,CAAC,CAAC,KAAK,CAAC,IAAI;QACZ,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC;AACrC,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,aAAa,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,QAAQ,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,EAAwC;IAC5E,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,OAAO,CAAC,MAAmB;IAClC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,uCAAuC,CAAC;QACtD,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,kBAAkB,IAAI,EAAE,CAAC;IACvE,CAAC;IACD,MAAM,KAAK,GAAG,cAAc,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,2BAA2B,CAAC;IACrF,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,uBAAuB,IAAI,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc,EAAE,MAAmB;IACnD,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QACxD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IACjG,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QACxD,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC,EAAE,CAAC;AACT,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjF,CAAC;AAED,wEAAwE;AACxE,SAAS,UAAU,CAAC,KAAc,EAAE,MAAmB;IACrD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,KAAK,GAAG;QACZ,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;KAClE,CAAC;IACF,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,KAAK,YAAY,cAAc,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAC/D,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;QAChC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACd,CAAC;AAED,SAAS,UAAU,CAAC,KAAc,EAAE,MAAmB;IACrD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IACzB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC;IACtD,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,IAAI,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAc,EAAE,MAAmB;IACpE,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACpC,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACzB,KAAK,EAAE,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC,CAAC;QACJ,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC;IACpD,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC"}
package/dist/execute.d.ts CHANGED
@@ -1,6 +1,9 @@
1
- import type { Command, Context } from "./define.js";
1
+ import type { Context } from "./context.js";
2
+ import type { Command } from "./define.js";
3
+ import type { Files } from "./files.js";
2
4
  import type { Invocation } from "./invocation.js";
3
5
  import type { PageInput } from "./list.js";
6
+ import { type OutputsGuard } from "./outputs.js";
4
7
  import type { Style } from "./style.js";
5
8
  export interface Outcome {
6
9
  readonly value: unknown;
@@ -19,7 +22,11 @@ export interface ExecuteFlags {
19
22
  readonly commandLine: string;
20
23
  /** Prints a serve Command's data the moment `start` returns it. */
21
24
  readonly started: (outcome: Outcome) => Promise<void>;
25
+ /** The file system under `ctx.files`, unresolved and unclassified, for the outputs probe. */
26
+ readonly files: Files;
27
+ /** Guards the declared outputs of `ctx.files` and the ports' files once every check passes. */
28
+ readonly guardOutputs: OutputsGuard["guard"];
22
29
  }
23
30
  /** Delivered data as the Command prints it, which is the data its `run` or `apply` returns. */
24
31
  export declare function deliveredOutcome(command: Command, data: unknown): Outcome;
25
- export declare function execute(command: Command, input: Record<string, unknown>, ctx: Context, { dryRun, confirm, yes, page, invocation, commandLine, started }: ExecuteFlags): Promise<Outcome>;
32
+ export declare function execute(command: Command, input: Record<string, unknown>, ctx: Context, { dryRun, confirm, yes, page, invocation, commandLine, started, files, guardOutputs, }: ExecuteFlags): Promise<Outcome>;
package/dist/execute.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { untilAborted } from "./abort.js";
2
2
  import { checkConfirmation } from "./confirm.js";
3
3
  import { checkCost } from "./cost.js";
4
- import { checkOutputs } from "./outputs.js";
4
+ import { FORCE_FLAG } from "./flags.js";
5
+ import { checkOutputs, probeOutputs } from "./outputs.js";
5
6
  import { checkTools } from "./tools.js";
6
7
  function outcomeOf(value, render) {
7
8
  return { value, render: (style) => render(value, style) };
@@ -32,7 +33,7 @@ function dryRunOutcome(command, plan) {
32
33
  ].join("\n"),
33
34
  };
34
35
  }
35
- export async function execute(command, input, ctx, { dryRun, confirm, yes, page, invocation, commandLine, started }) {
36
+ export async function execute(command, input, ctx, { dryRun, confirm, yes, page, invocation, commandLine, started, files, guardOutputs, }) {
36
37
  await checkTools(command.tools ?? [], ctx.env);
37
38
  if (command.rows !== undefined) {
38
39
  return outcomeOf(await command.run({ ...input, ...page }, ctx), (data, style) => command.render(data, style));
@@ -49,11 +50,17 @@ export async function execute(command, input, ctx, { dryRun, confirm, yes, page,
49
50
  if (dryRun) {
50
51
  return dryRunOutcome(command, plan);
51
52
  }
52
- await checkOutputs({ invocation, commandLine, force: ctx.force, files: ctx.files }, command.outputs?.(plan));
53
+ const outputs = command.outputs?.(plan);
54
+ await checkOutputs({ invocation, commandLine, force: ctx.force, files: ctx.files }, outputs);
53
55
  checkCost({ invocation, commandLine, yes }, command.cost?.(plan));
54
56
  if (command.effect === "destructive") {
55
57
  checkConfirmation({ invocation, commandLine, given: confirm }, command.confirm(plan));
56
58
  }
59
+ if (outputs !== undefined) {
60
+ await probeOutputs({ files, cwd: ctx.cwd, fileError: ctx.fileError }, outputs);
61
+ if (!ctx.force)
62
+ guardOutputs(outputs, ctx.commandLine({ add: [FORCE_FLAG.flag] }));
63
+ }
57
64
  return outcomeOf(await command.apply(plan, ctx), (data, style) => command.render(data, style));
58
65
  }
59
66
  //# sourceMappingURL=execute.js.map