@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.
- package/CHANGELOG.md +80 -0
- package/dist/agent-cli.js +2 -2
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent.d.ts +5 -3
- package/dist/agent.js +31 -10
- package/dist/agent.js.map +1 -1
- package/dist/built-ins/commands.d.ts +8 -0
- package/dist/{built-ins.js → built-ins/commands.js} +4 -4
- package/dist/built-ins/commands.js.map +1 -0
- package/dist/built-ins/doctor-rows.d.ts +4 -0
- package/dist/{doctor-rows.js → built-ins/doctor-rows.js} +18 -26
- package/dist/built-ins/doctor-rows.js.map +1 -0
- package/dist/built-ins/doctor.d.ts +5 -0
- package/dist/{doctor.js → built-ins/doctor.js} +27 -20
- package/dist/built-ins/doctor.js.map +1 -0
- package/dist/{global-install.js → built-ins/global-install.js} +1 -1
- package/dist/built-ins/global-install.js.map +1 -0
- package/dist/{npm.d.ts → built-ins/npm.d.ts} +5 -2
- package/dist/{npm.js → built-ins/npm.js} +25 -33
- package/dist/built-ins/npm.js.map +1 -0
- package/dist/built-ins/semver.js.map +1 -0
- package/dist/built-ins/skills.d.ts +18 -0
- package/dist/built-ins/skills.js +97 -0
- package/dist/built-ins/skills.js.map +1 -0
- package/dist/{update.d.ts → built-ins/update.d.ts} +3 -2
- package/dist/{update.js → built-ins/update.js} +28 -18
- package/dist/built-ins/update.js.map +1 -0
- package/dist/{upgrade-notes.js → built-ins/upgrade-notes.js} +1 -1
- package/dist/built-ins/upgrade-notes.js.map +1 -0
- package/dist/clock.d.ts +1 -0
- package/dist/clock.js.map +1 -1
- package/dist/command-spec.d.ts +17 -2
- package/dist/command-spec.js +30 -9
- package/dist/command-spec.js.map +1 -1
- package/dist/confirm.js +6 -2
- package/dist/confirm.js.map +1 -1
- package/dist/context.d.ts +139 -0
- package/dist/context.js +2 -0
- package/dist/context.js.map +1 -0
- package/dist/cost.js +2 -2
- package/dist/cost.js.map +1 -1
- package/dist/define.d.ts +100 -87
- package/dist/define.js +3 -1
- package/dist/define.js.map +1 -1
- package/dist/errno.d.ts +8 -4
- package/dist/errno.js +21 -4
- package/dist/errno.js.map +1 -1
- package/dist/error-table.d.ts +6 -1
- package/dist/error-table.js +5 -1
- package/dist/error-table.js.map +1 -1
- package/dist/errors.d.ts +11 -2
- package/dist/errors.js +21 -8
- package/dist/errors.js.map +1 -1
- package/dist/execute.d.ts +9 -2
- package/dist/execute.js +10 -3
- package/dist/execute.js.map +1 -1
- package/dist/exit-classes.js +38 -38
- package/dist/exit-classes.js.map +1 -1
- package/dist/files.d.ts +30 -8
- package/dist/files.js +104 -17
- package/dist/files.js.map +1 -1
- package/dist/help-json.d.ts +2 -2
- package/dist/help-json.js +6 -2
- package/dist/help-json.js.map +1 -1
- package/dist/help.d.ts +1 -1
- package/dist/help.js +14 -9
- package/dist/help.js.map +1 -1
- package/dist/index.d.ts +12 -5
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/input.d.ts +7 -1
- package/dist/input.js +33 -4
- package/dist/input.js.map +1 -1
- package/dist/interrupts.d.ts +7 -2
- package/dist/interrupts.js +29 -15
- package/dist/interrupts.js.map +1 -1
- package/dist/invocation.d.ts +10 -5
- package/dist/invocation.js +24 -11
- package/dist/invocation.js.map +1 -1
- package/dist/list.d.ts +12 -3
- package/dist/list.js +38 -6
- package/dist/list.js.map +1 -1
- package/dist/manifest.d.ts +17 -0
- package/dist/manifest.js +24 -0
- package/dist/manifest.js.map +1 -0
- package/dist/operator.d.ts +5 -0
- package/dist/operator.js +15 -0
- package/dist/operator.js.map +1 -0
- package/dist/output.d.ts +6 -4
- package/dist/output.js +5 -6
- package/dist/output.js.map +1 -1
- package/dist/outputs.d.ts +24 -1
- package/dist/outputs.js +58 -2
- package/dist/outputs.js.map +1 -1
- package/dist/parse-input.d.ts +11 -2
- package/dist/parse-input.js +78 -27
- package/dist/parse-input.js.map +1 -1
- package/dist/project.d.ts +3 -2
- package/dist/project.js +11 -10
- package/dist/project.js.map +1 -1
- package/dist/route.d.ts +1 -1
- package/dist/route.js +2 -1
- package/dist/route.js.map +1 -1
- package/dist/run-cli.d.ts +8 -33
- package/dist/run-cli.js +50 -157
- package/dist/run-cli.js.map +1 -1
- package/dist/run-command.d.ts +11 -0
- package/dist/run-command.js +234 -0
- package/dist/run-command.js.map +1 -0
- package/dist/run-options.d.ts +48 -0
- package/dist/run-options.js +2 -0
- package/dist/run-options.js.map +1 -0
- package/dist/run-process.js +7 -4
- package/dist/run-process.js.map +1 -1
- package/dist/secrets.d.ts +10 -6
- package/dist/secrets.js +8 -9
- package/dist/secrets.js.map +1 -1
- package/dist/side-task.d.ts +27 -0
- package/dist/side-task.js +31 -0
- package/dist/side-task.js.map +1 -0
- package/dist/spawn.d.ts +29 -6
- package/dist/spawn.js +126 -29
- package/dist/spawn.js.map +1 -1
- package/dist/spill.d.ts +4 -3
- package/dist/spill.js +1 -7
- package/dist/spill.js.map +1 -1
- package/dist/stdin.d.ts +33 -0
- package/dist/stdin.js +92 -0
- package/dist/stdin.js.map +1 -0
- package/dist/style.d.ts +1 -1
- package/dist/tokenize.d.ts +3 -0
- package/dist/tokenize.js +5 -4
- package/dist/tokenize.js.map +1 -1
- package/dist/tools.d.ts +6 -3
- package/dist/tools.js +18 -11
- package/dist/tools.js.map +1 -1
- package/dist/usage.d.ts +2 -0
- package/dist/usage.js +12 -1
- package/dist/usage.js.map +1 -1
- package/dist/version.d.ts +3 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- package/package.json +1 -1
- package/dist/built-ins.d.ts +0 -3
- package/dist/built-ins.js.map +0 -1
- package/dist/doctor-rows.d.ts +0 -3
- package/dist/doctor-rows.js.map +0 -1
- package/dist/doctor.d.ts +0 -4
- package/dist/doctor.js.map +0 -1
- package/dist/global-install.js.map +0 -1
- package/dist/npm.js.map +0 -1
- package/dist/semver.js.map +0 -1
- package/dist/skills.d.ts +0 -11
- package/dist/skills.js +0 -58
- package/dist/skills.js.map +0 -1
- package/dist/update.js.map +0 -1
- package/dist/upgrade-notes.js.map +0 -1
- /package/dist/{global-install.d.ts → built-ins/global-install.d.ts} +0 -0
- /package/dist/{semver.d.ts → built-ins/semver.d.ts} +0 -0
- /package/dist/{semver.js → built-ins/semver.js} +0 -0
- /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 {
|
|
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 {
|
|
8
|
-
import type { ContextSpawn } from "./spawn.js";
|
|
6
|
+
import type { SideTaskRun } from "./side-task.js";
|
|
9
7
|
import type { Style } from "./style.js";
|
|
10
|
-
|
|
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
|
-
/**
|
|
98
|
-
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
|
|
192
|
-
|
|
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() {
|
package/dist/define.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"
|
|
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 "./
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
18
|
-
|
|
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;
|
|
1
|
+
{"version":3,"file":"errno.js","sourceRoot":"","sources":["../src/errno.ts"],"names":[],"mappings":"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"}
|
package/dist/error-table.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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 {};
|
package/dist/error-table.js
CHANGED
|
@@ -3,7 +3,11 @@ import { CliError } from "./errors.js";
|
|
|
3
3
|
export function defineErrors(table) {
|
|
4
4
|
return table;
|
|
5
5
|
}
|
|
6
|
-
/**
|
|
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
|
}
|
package/dist/error-table.js.map
CHANGED
|
@@ -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;
|
|
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 "./
|
|
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
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
/**
|
|
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
|
|
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);
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/execute.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type {
|
|
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 {
|
|
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
|
-
|
|
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
|