@duyquangnvx/agent-cli 0.2.1 → 0.3.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 +49 -0
- package/dist/abort.d.ts +2 -0
- package/dist/abort.js +11 -0
- package/dist/abort.js.map +1 -0
- package/dist/agent-cli.d.ts +17 -0
- package/dist/agent-cli.js +28 -0
- package/dist/agent-cli.js.map +1 -0
- package/dist/agent.d.ts +4 -0
- package/dist/agent.js +14 -0
- package/dist/agent.js.map +1 -0
- package/dist/built-ins.d.ts +1 -2
- package/dist/built-ins.js +0 -10
- package/dist/built-ins.js.map +1 -1
- package/dist/clock.d.ts +10 -0
- package/dist/clock.js +35 -0
- package/dist/clock.js.map +1 -0
- package/dist/command-spec.js +8 -1
- package/dist/command-spec.js.map +1 -1
- package/dist/confirm.d.ts +2 -0
- package/dist/confirm.js +4 -2
- package/dist/confirm.js.map +1 -1
- package/dist/cost.d.ts +9 -0
- package/dist/cost.js +16 -0
- package/dist/cost.js.map +1 -0
- package/dist/define.d.ts +133 -32
- package/dist/define.js +5 -1
- package/dist/define.js.map +1 -1
- package/dist/doctor-rows.d.ts +2 -2
- package/dist/doctor-rows.js +42 -5
- package/dist/doctor-rows.js.map +1 -1
- package/dist/doctor.d.ts +2 -1
- package/dist/doctor.js +26 -28
- package/dist/doctor.js.map +1 -1
- package/dist/errno.d.ts +12 -0
- package/dist/errno.js +40 -0
- package/dist/errno.js.map +1 -0
- package/dist/error-table.d.ts +34 -0
- package/dist/error-table.js +10 -0
- package/dist/error-table.js.map +1 -0
- package/dist/errors.d.ts +17 -12
- package/dist/errors.js +59 -38
- package/dist/errors.js.map +1 -1
- package/dist/execute.d.ts +9 -3
- package/dist/execute.js +38 -5
- package/dist/execute.js.map +1 -1
- package/dist/exit-classes.d.ts +31 -0
- package/dist/exit-classes.js +107 -0
- package/dist/exit-classes.js.map +1 -0
- package/dist/files.d.ts +9 -0
- package/dist/files.js +59 -0
- package/dist/files.js.map +1 -0
- package/dist/flags.d.ts +17 -3
- package/dist/flags.js +26 -4
- package/dist/flags.js.map +1 -1
- package/dist/global-install.d.ts +1 -0
- package/dist/global-install.js +2 -2
- package/dist/global-install.js.map +1 -1
- package/dist/help-json.d.ts +2 -1
- package/dist/help-json.js +18 -2
- package/dist/help-json.js.map +1 -1
- package/dist/help.d.ts +4 -2
- package/dist/help.js +62 -6
- package/dist/help.js.map +1 -1
- package/dist/index.d.ts +10 -4
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/interrupts.d.ts +17 -3
- package/dist/interrupts.js +43 -25
- package/dist/interrupts.js.map +1 -1
- package/dist/invocation.d.ts +7 -2
- package/dist/invocation.js +11 -3
- package/dist/invocation.js.map +1 -1
- package/dist/list.d.ts +1 -0
- package/dist/list.js +4 -2
- package/dist/list.js.map +1 -1
- package/dist/npm.d.ts +5 -0
- package/dist/npm.js +19 -17
- package/dist/npm.js.map +1 -1
- package/dist/output.d.ts +18 -4
- package/dist/output.js +65 -23
- package/dist/output.js.map +1 -1
- package/dist/outputs.d.ts +11 -0
- package/dist/outputs.js +22 -0
- package/dist/outputs.js.map +1 -0
- package/dist/package-root.d.ts +6 -0
- package/dist/package-root.js +17 -0
- package/dist/package-root.js.map +1 -0
- package/dist/parse-input.d.ts +2 -0
- package/dist/parse-input.js +5 -3
- package/dist/parse-input.js.map +1 -1
- package/dist/project.d.ts +4 -0
- package/dist/project.js +48 -0
- package/dist/project.js.map +1 -0
- package/dist/route.d.ts +2 -0
- package/dist/route.js +2 -1
- package/dist/route.js.map +1 -1
- package/dist/run-cli.d.ts +24 -5
- package/dist/run-cli.js +122 -17
- package/dist/run-cli.js.map +1 -1
- package/dist/run-process.js +6 -3
- package/dist/run-process.js.map +1 -1
- package/dist/secrets.d.ts +13 -0
- package/dist/secrets.js +29 -0
- package/dist/secrets.js.map +1 -0
- package/dist/spawn.d.ts +29 -0
- package/dist/spawn.js +79 -0
- package/dist/spawn.js.map +1 -0
- package/dist/spill.d.ts +16 -0
- package/dist/spill.js +60 -0
- package/dist/spill.js.map +1 -0
- package/dist/style.js +5 -12
- package/dist/style.js.map +1 -1
- package/dist/tail.d.ts +2 -0
- package/dist/tail.js +5 -0
- package/dist/tail.js.map +1 -0
- package/dist/tools.d.ts +6 -0
- package/dist/tools.js +69 -0
- package/dist/tools.js.map +1 -0
- package/dist/update.js +7 -7
- package/dist/update.js.map +1 -1
- package/dist/usage.d.ts +3 -0
- package/dist/usage.js +6 -3
- package/dist/usage.js.map +1 -1
- package/package.json +1 -1
package/dist/define.d.ts
CHANGED
|
@@ -1,83 +1,174 @@
|
|
|
1
1
|
import type * as z from "zod";
|
|
2
|
+
import type { Clock } from "./clock.js";
|
|
3
|
+
import type { ErrorTable } from "./error-table.js";
|
|
4
|
+
import type { Files } from "./files.js";
|
|
2
5
|
import { type StandardFlagName } from "./flags.js";
|
|
3
6
|
import type { Page, PageInput, RowSchema } from "./list.js";
|
|
7
|
+
import type { Secret } from "./secrets.js";
|
|
8
|
+
import type { ContextSpawn } from "./spawn.js";
|
|
4
9
|
import type { Style } from "./style.js";
|
|
5
10
|
export type Env = Readonly<Record<string, string | undefined>>;
|
|
6
11
|
export interface Example {
|
|
7
12
|
readonly command: string;
|
|
8
13
|
readonly note: string;
|
|
9
14
|
}
|
|
10
|
-
export interface
|
|
15
|
+
export interface PollOptions {
|
|
16
|
+
readonly intervalMs: number;
|
|
17
|
+
}
|
|
18
|
+
export interface Context<Ports = unknown, Settings = unknown> {
|
|
11
19
|
readonly cwd: string;
|
|
12
20
|
readonly env: Env;
|
|
21
|
+
/** The folder holding this CLI's `package.json`, for reading files shipped in the package. */
|
|
22
|
+
readonly packageRoot: string;
|
|
13
23
|
/** Writes a plain line to stderr, for long work; it never reaches stdout. */
|
|
14
24
|
progress(message: string): void;
|
|
15
|
-
/**
|
|
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
|
+
*/
|
|
16
29
|
readonly signal: AbortSignal;
|
|
17
30
|
/** Returns a signal that also aborts, with `DEADLINE_EXCEEDED`, once `ms` have passed. */
|
|
18
31
|
deadline(ms: number): AbortSignal;
|
|
19
|
-
/**
|
|
20
|
-
|
|
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
|
+
/** Writes files atomically and tells whether one exists; a failure fails the run with `PERMISSION_DENIED`, `DISK_FULL` or `NOT_FOUND`. */
|
|
45
|
+
readonly files: Files;
|
|
46
|
+
/**
|
|
47
|
+
* Runs a child process, killed when the run is interrupted; `check: true` fails the run with
|
|
48
|
+
* `TOOL_FAILED` and the tail of its stderr when it exits non-zero.
|
|
49
|
+
*/
|
|
50
|
+
readonly spawn: ContextSpawn;
|
|
51
|
+
/** Deadlines, `poll` and the grace period after an interrupt run on it. */
|
|
52
|
+
readonly clock: Clock;
|
|
53
|
+
/**
|
|
54
|
+
* Calls `check` until it returns a value other than `undefined`, sleeping `intervalMs` between
|
|
55
|
+
* calls; it stops when `ctx.signal` aborts.
|
|
56
|
+
*/
|
|
57
|
+
poll<T>(check: () => T | undefined | Promise<T | undefined>, options: PollOptions): Promise<T>;
|
|
58
|
+
/** The Project file found by walking up from `cwd`, parsed by the CLI's schema. */
|
|
59
|
+
readonly project: Project<Settings> | undefined;
|
|
60
|
+
/** Reads `name` from the env, then from `$XDG_CONFIG_HOME/<cli>/.env`, with where it came from. */
|
|
61
|
+
secret(name: string): Secret | undefined;
|
|
62
|
+
}
|
|
63
|
+
export interface Project<Settings = unknown> {
|
|
64
|
+
/** The folder holding the Project file. */
|
|
65
|
+
readonly root: string;
|
|
66
|
+
readonly settings: Settings;
|
|
67
|
+
}
|
|
68
|
+
/** Names the Project file and the schema its JSON must match. */
|
|
69
|
+
export interface ProjectFile<Settings = unknown> {
|
|
70
|
+
readonly file: string;
|
|
71
|
+
readonly schema: z.ZodType<Settings>;
|
|
21
72
|
}
|
|
22
73
|
export type InputSchema = z.ZodObject;
|
|
74
|
+
export type NoPorts = Record<never, never>;
|
|
23
75
|
export type NoInput = z.ZodObject<Record<never, never>>;
|
|
24
76
|
type OutputOf<Schema extends InputSchema> = keyof Schema["shape"] extends never ? unknown : z.output<Schema>;
|
|
25
77
|
type Flatten<T> = {
|
|
26
78
|
[K in keyof T]: T[K];
|
|
27
79
|
};
|
|
28
80
|
export type Input<Args extends InputSchema, Options extends InputSchema> = Flatten<OutputOf<Args> & OutputOf<Options>>;
|
|
81
|
+
/** A program a Command runs, looked up on `PATH` before the Command starts. */
|
|
82
|
+
export interface Tool {
|
|
83
|
+
readonly name: string;
|
|
84
|
+
/** The command that installs it, shown when it is missing. */
|
|
85
|
+
readonly install: string;
|
|
86
|
+
}
|
|
87
|
+
/** Bounds a whole run, so a long run stops before the caller's own timeout and can be continued. */
|
|
88
|
+
export interface RunDeadline<In> {
|
|
89
|
+
readonly ms: number;
|
|
90
|
+
/** The command line that continues the work, given as the hint of the run's `DEADLINE_EXCEEDED`. */
|
|
91
|
+
resume(input: In): string;
|
|
92
|
+
}
|
|
29
93
|
interface CommandBase<Args extends InputSchema, Options extends InputSchema> {
|
|
30
94
|
readonly name: string;
|
|
31
95
|
readonly description: string;
|
|
32
96
|
readonly examples: readonly Example[];
|
|
97
|
+
/** Missing ones fail the run with `TOOL_MISSING` before `plan`, `run` or `start`. */
|
|
98
|
+
readonly tools?: readonly Tool[];
|
|
33
99
|
readonly args?: Args;
|
|
34
100
|
readonly options?: Options;
|
|
101
|
+
/** At `ms`, `ctx.signal` aborts and the run ends with `DEADLINE_EXCEEDED` (exit 75). */
|
|
102
|
+
readonly deadline?: RunDeadline<Input<Args, Options>>;
|
|
35
103
|
}
|
|
36
104
|
interface UnpagedCommand<Args extends InputSchema, Options extends InputSchema> extends CommandBase<Args, Options> {
|
|
37
105
|
readonly output?: z.ZodType;
|
|
38
106
|
readonly rows?: never;
|
|
39
107
|
}
|
|
40
|
-
export interface ReadCommand<Args extends InputSchema, Options extends InputSchema, Data> extends UnpagedCommand<Args, Options> {
|
|
108
|
+
export interface ReadCommand<Args extends InputSchema, Options extends InputSchema, Data, Ports = unknown, Settings = unknown> extends UnpagedCommand<Args, Options> {
|
|
41
109
|
readonly effect: "read";
|
|
42
|
-
run(input: Input<Args, Options>, ctx: Context): Data | Promise<Data>;
|
|
110
|
+
run(input: Input<Args, Options>, ctx: Context<Ports, Settings>): Data | Promise<Data>;
|
|
43
111
|
render(data: Data, style: Style): string;
|
|
44
112
|
}
|
|
45
113
|
/** A read Command whose data is a page of rows; the Runtime adds `--limit`, `--cursor` and `--fields`. */
|
|
46
|
-
export interface ListCommand<Args extends InputSchema, Options extends InputSchema, Row extends RowSchema> extends CommandBase<Args, Options> {
|
|
114
|
+
export interface ListCommand<Args extends InputSchema, Options extends InputSchema, Row extends RowSchema, Ports = unknown, Settings = unknown> extends CommandBase<Args, Options> {
|
|
47
115
|
readonly effect: "read";
|
|
48
116
|
/** The schema of one row; the page's output schema is derived from it. */
|
|
49
117
|
readonly rows: Row;
|
|
50
118
|
readonly output?: never;
|
|
51
|
-
run(input: Flatten<OutputOf<Args> & OutputOf<Options> & PageInput>, ctx: Context): Page<z.output<Row>> | Promise<Page<z.output<Row>>>;
|
|
119
|
+
run(input: Flatten<OutputOf<Args> & OutputOf<Options> & PageInput>, ctx: Context<Ports, Settings>): Page<z.output<Row>> | Promise<Page<z.output<Row>>>;
|
|
52
120
|
render(page: Page<z.output<Row>>, style: Style): string;
|
|
53
121
|
}
|
|
54
122
|
/** A Command that changes something: `plan` has no side effects, `apply` performs the Plan. */
|
|
55
|
-
interface PlannedCommand<Args extends InputSchema, Options extends InputSchema, Plan, Data> extends UnpagedCommand<Args, Options> {
|
|
56
|
-
plan(input: Input<Args, Options>, ctx: Context): Plan | Promise<Plan>;
|
|
57
|
-
apply(plan: Plan, ctx: Context): Data | Promise<Data>;
|
|
123
|
+
interface PlannedCommand<Args extends InputSchema, Options extends InputSchema, Plan, Data, Ports, Settings> extends UnpagedCommand<Args, Options> {
|
|
124
|
+
plan(input: Input<Args, Options>, ctx: Context<Ports, Settings>): Plan | Promise<Plan>;
|
|
125
|
+
apply(plan: Plan, ctx: Context<Ports, Settings>): Data | Promise<Data>;
|
|
58
126
|
render(data: Data, style: Style): string;
|
|
59
127
|
renderPlan(plan: Plan, style: Style): string;
|
|
60
|
-
|
|
61
|
-
|
|
128
|
+
/**
|
|
129
|
+
* A sentence stating what the Plan costs, or undefined when it is cheap. Declaring it adds
|
|
130
|
+
* `--yes`, which a run must pass whenever it returns a sentence.
|
|
131
|
+
*/
|
|
132
|
+
cost?(plan: Plan): string | undefined;
|
|
133
|
+
/**
|
|
134
|
+
* The files the Plan writes, relative to `ctx.cwd`. Declaring it adds `--force`, without which
|
|
135
|
+
* a run refuses with `OUTPUT_EXISTS` when any of them exists.
|
|
136
|
+
*/
|
|
137
|
+
outputs?(plan: Plan): readonly string[];
|
|
138
|
+
}
|
|
139
|
+
export interface WriteCommand<Args extends InputSchema, Options extends InputSchema, Plan, Data, Ports = unknown, Settings = unknown> extends PlannedCommand<Args, Options, Plan, Data, Ports, Settings> {
|
|
62
140
|
readonly effect: "write";
|
|
63
141
|
}
|
|
64
|
-
export interface DestructiveCommand<Args extends InputSchema, Options extends InputSchema, Plan, Data> extends PlannedCommand<Args, Options, Plan, Data> {
|
|
142
|
+
export interface DestructiveCommand<Args extends InputSchema, Options extends InputSchema, Plan, Data, Ports = unknown, Settings = unknown> extends PlannedCommand<Args, Options, Plan, Data, Ports, Settings> {
|
|
65
143
|
readonly effect: "destructive";
|
|
66
144
|
/** The value the caller must repeat as `--confirm`, naming the target the Plan changes. */
|
|
67
145
|
confirm(plan: Plan): string;
|
|
68
146
|
}
|
|
69
|
-
|
|
70
|
-
export interface
|
|
71
|
-
readonly
|
|
147
|
+
/** A Command that keeps running, such as a preview server, until Ctrl-C or SIGTERM stops it. */
|
|
148
|
+
export interface ServeCommand<Args extends InputSchema, Options extends InputSchema, Data, Ports = unknown, Settings = unknown> extends UnpagedCommand<Args, Options> {
|
|
149
|
+
readonly effect: "serve";
|
|
150
|
+
/** Starts the work and returns its data, which prints at once; stop the work on `ctx.signal`. */
|
|
151
|
+
start(input: Input<Args, Options>, ctx: Context<Ports, Settings>): Data | Promise<Data>;
|
|
152
|
+
render(data: Data, style: Style): string;
|
|
153
|
+
}
|
|
154
|
+
export type Command<Ports = unknown, Settings = unknown> = ReadCommand<InputSchema, InputSchema, unknown, Ports, Settings> | ListCommand<InputSchema, InputSchema, RowSchema, Ports, Settings> | WriteCommand<InputSchema, InputSchema, unknown, unknown, Ports, Settings> | DestructiveCommand<InputSchema, InputSchema, unknown, unknown, Ports, Settings> | ServeCommand<InputSchema, InputSchema, unknown, Ports, Settings>;
|
|
155
|
+
export interface Commands<Ports = unknown, Settings = unknown> {
|
|
156
|
+
readonly [key: string]: Command<Ports, Settings> | Commands<Ports, Settings>;
|
|
72
157
|
}
|
|
73
|
-
interface CliBase {
|
|
158
|
+
interface CliBase<Ports, Settings> {
|
|
74
159
|
readonly name: string;
|
|
75
160
|
readonly version: string;
|
|
76
|
-
/** The commit the build was made from, stamped by the bundler; `--version` prints it. */
|
|
161
|
+
/** The commit the build was made from and when, stamped by the bundler; `--version` prints it. */
|
|
77
162
|
readonly build?: {
|
|
78
163
|
readonly sha: string;
|
|
79
164
|
readonly dirty: boolean;
|
|
165
|
+
readonly builtAt: string;
|
|
80
166
|
};
|
|
167
|
+
/** Every code the CLI throws; a code missing here exits 70, as a bug. */
|
|
168
|
+
readonly errors?: ErrorTable;
|
|
169
|
+
/** Builds the real ports when a Command runs; `runCli`'s `ports` replaces them in a test. */
|
|
170
|
+
readonly ports?: () => Ports;
|
|
171
|
+
readonly project?: ProjectFile<Settings>;
|
|
81
172
|
}
|
|
82
173
|
/** Where an Agent CLI is published and how it is installed; `doctor` and `update` read it. */
|
|
83
174
|
export interface GlobalInstall {
|
|
@@ -92,14 +183,18 @@ export interface DoctorFinding {
|
|
|
92
183
|
readonly fix?: string;
|
|
93
184
|
}
|
|
94
185
|
/** A row the CLI adds to `doctor`, for a system it depends on. */
|
|
95
|
-
export interface DoctorCheck {
|
|
186
|
+
export interface DoctorCheck<Ports = unknown, Settings = unknown> {
|
|
96
187
|
readonly name: string;
|
|
97
|
-
/**
|
|
98
|
-
|
|
188
|
+
/** How long the row may take before it is reported as a problem; 10 s when absent. */
|
|
189
|
+
readonly deadlineMs?: number;
|
|
190
|
+
/** A problem in an advisory row shows but never fails `doctor`. */
|
|
191
|
+
readonly advisory?: boolean;
|
|
192
|
+
/** `ctx.signal` aborts at the row's deadline. A thrown error is reported as this row's problem. */
|
|
193
|
+
run(ctx: Context<Ports, Settings>): DoctorFinding | Promise<DoctorFinding>;
|
|
99
194
|
}
|
|
100
195
|
/** An Agent CLI whose Commands are reached by name, as in `tool voices list`. */
|
|
101
|
-
export interface CommandTreeCli extends CliBase {
|
|
102
|
-
readonly commands: Commands
|
|
196
|
+
export interface CommandTreeCli<Ports = unknown, Settings = unknown> extends CliBase<Ports, Settings> {
|
|
197
|
+
readonly commands: Commands<Ports, Settings>;
|
|
103
198
|
readonly command?: never;
|
|
104
199
|
/** Absent for a CLI that is not published: `doctor` then checks no install or registry. */
|
|
105
200
|
readonly install?: GlobalInstall;
|
|
@@ -107,14 +202,14 @@ export interface CommandTreeCli extends CliBase {
|
|
|
107
202
|
readonly engines?: {
|
|
108
203
|
readonly node?: string;
|
|
109
204
|
};
|
|
110
|
-
readonly doctor?: readonly DoctorCheck[];
|
|
205
|
+
readonly doctor?: readonly DoctorCheck<Ports, Settings>[];
|
|
111
206
|
}
|
|
112
207
|
/** An Agent CLI that is one Command, run with no Command name, as in `tool <args>`. */
|
|
113
|
-
export interface SingleCommandCli extends CliBase {
|
|
114
|
-
readonly command: Command
|
|
208
|
+
export interface SingleCommandCli<Ports = unknown, Settings = unknown> extends CliBase<Ports, Settings> {
|
|
209
|
+
readonly command: Command<Ports, Settings>;
|
|
115
210
|
readonly commands?: never;
|
|
116
211
|
}
|
|
117
|
-
export type Cli = CommandTreeCli | SingleCommandCli
|
|
212
|
+
export type Cli<Ports = unknown, Settings = unknown> = CommandTreeCli<Ports, Settings> | SingleCommandCli<Ports, Settings>;
|
|
118
213
|
type Kebab<Key extends string> = Key extends `${infer Head}${infer Tail}` ? `${Head extends Lowercase<Head> ? Head : `-${Lowercase<Head>}`}${Kebab<Tail>}` : Key;
|
|
119
214
|
type Taken<Schema extends InputSchema> = Extract<Kebab<Extract<keyof Schema["shape"], string>>, StandardFlagName>;
|
|
120
215
|
type Unreserved<Schema extends InputSchema> = [Taken<Schema>] extends [never] ? unknown : {
|
|
@@ -124,9 +219,15 @@ interface WithoutStandardFlags<Args extends InputSchema, Options extends InputSc
|
|
|
124
219
|
readonly args?: Unreserved<Args>;
|
|
125
220
|
readonly options?: Unreserved<Options>;
|
|
126
221
|
}
|
|
127
|
-
|
|
128
|
-
export
|
|
129
|
-
|
|
130
|
-
|
|
222
|
+
/** Declares a Command whose `ctx.ports` is the CLI's `Ports`. */
|
|
223
|
+
export interface DefineCommand<Ports, Settings = unknown> {
|
|
224
|
+
<Row extends RowSchema, Args extends InputSchema = NoInput, Options extends InputSchema = NoInput>(command: ListCommand<Args, Options, Row, Ports, Settings> & WithoutStandardFlags<Args, Options>): ListCommand<Args, Options, Row, Ports, Settings>;
|
|
225
|
+
<Data, Args extends InputSchema = NoInput, Options extends InputSchema = NoInput>(command: ReadCommand<Args, Options, Data, Ports, Settings> & WithoutStandardFlags<Args, Options>): ReadCommand<Args, Options, Data, Ports, Settings>;
|
|
226
|
+
<Data, Args extends InputSchema = NoInput, Options extends InputSchema = NoInput>(command: ServeCommand<Args, Options, Data, Ports, Settings> & WithoutStandardFlags<Args, Options>): ServeCommand<Args, Options, Data, Ports, Settings>;
|
|
227
|
+
<Plan, Data, Args extends InputSchema = NoInput, Options extends InputSchema = NoInput>(command: WriteCommand<Args, Options, Plan, Data, Ports, Settings> & WithoutStandardFlags<Args, Options>): WriteCommand<Args, Options, Plan, Data, Ports, Settings>;
|
|
228
|
+
<Plan, Data, Args extends InputSchema = NoInput, Options extends InputSchema = NoInput>(command: DestructiveCommand<Args, Options, Plan, Data, Ports, Settings> & WithoutStandardFlags<Args, Options>): DestructiveCommand<Args, Options, Plan, Data, Ports, Settings>;
|
|
229
|
+
}
|
|
230
|
+
export declare function defineCommandFor<Ports, Settings>(): DefineCommand<Ports, Settings>;
|
|
231
|
+
export declare const defineCommand: DefineCommand<unknown>;
|
|
131
232
|
export declare function isCommand(node: Command | Commands): node is Command;
|
|
132
233
|
export {};
|
package/dist/define.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { checkNoStandardFlags } from "./flags.js";
|
|
2
|
-
|
|
2
|
+
function checkedCommand(command) {
|
|
3
3
|
checkNoStandardFlags(command);
|
|
4
4
|
return command;
|
|
5
5
|
}
|
|
6
|
+
export function defineCommandFor() {
|
|
7
|
+
return checkedCommand;
|
|
8
|
+
}
|
|
9
|
+
export const defineCommand = defineCommandFor();
|
|
6
10
|
// A group's values are always objects, so a string `effect` can only belong to a Command.
|
|
7
11
|
export function isCommand(node) {
|
|
8
12
|
return typeof node.effect === "string";
|
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":"AAIA,OAAO,EAAE,oBAAoB,EAAyB,MAAM,YAAY,CAAC;AA+UzE,SAAS,cAAc,CAA2B,OAAiB;IACjE,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,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/doctor-rows.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { CommandTreeCli, DoctorCheck } from "./define.js";
|
|
2
|
-
/**
|
|
3
|
-
export declare function
|
|
2
|
+
/** Every row `doctor` reports, in order: the fixed rows around the CLI's own and its tools'. */
|
|
3
|
+
export declare function doctorChecks(cli: CommandTreeCli, bin: string | undefined): DoctorCheck[];
|
package/dist/doctor-rows.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
1
2
|
import { CliError } from "./errors.js";
|
|
2
|
-
import { globalInstallOf } from "./global-install.js";
|
|
3
|
+
import { globalInstallOf, NOT_GLOBAL_INSTALL } from "./global-install.js";
|
|
3
4
|
import { installCommandLine, latestVersion, npmContext } from "./npm.js";
|
|
5
|
+
import { versionLine } from "./output.js";
|
|
6
|
+
import { PROJECT_INVALID, projectOf } from "./project.js";
|
|
4
7
|
import { engineMinimum, meetsMinimum, standingOf } from "./semver.js";
|
|
5
8
|
import { skillCopies, skillUpdateCommand } from "./skills.js";
|
|
9
|
+
import { toolRows } from "./tools.js";
|
|
6
10
|
function ok(message) {
|
|
7
11
|
return { state: "ok", message };
|
|
8
12
|
}
|
|
13
|
+
function buildRow(cli) {
|
|
14
|
+
return { name: "build", run: () => ok(versionLine(cli)) };
|
|
15
|
+
}
|
|
9
16
|
function nodeRow(cli) {
|
|
10
17
|
return {
|
|
11
18
|
name: "node",
|
|
@@ -34,6 +41,27 @@ function nodeRow(cli) {
|
|
|
34
41
|
},
|
|
35
42
|
};
|
|
36
43
|
}
|
|
44
|
+
function projectRow(projectFile) {
|
|
45
|
+
const { file } = projectFile;
|
|
46
|
+
return {
|
|
47
|
+
name: "project",
|
|
48
|
+
run: (ctx) => {
|
|
49
|
+
let project;
|
|
50
|
+
try {
|
|
51
|
+
project = projectOf(projectFile, ctx.cwd);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof CliError && error.code === PROJECT_INVALID) {
|
|
55
|
+
return { state: "problem", message: error.message };
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
return ok(project === undefined
|
|
60
|
+
? `none found: no ${file} at or above ${ctx.cwd}`
|
|
61
|
+
: join(project.root, file));
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
37
65
|
function installRow(cli, bin) {
|
|
38
66
|
return {
|
|
39
67
|
name: "install",
|
|
@@ -47,7 +75,7 @@ function installRow(cli, bin) {
|
|
|
47
75
|
return ok(`a global npm install under ${copy.prefix}`);
|
|
48
76
|
}
|
|
49
77
|
catch (error) {
|
|
50
|
-
if (error instanceof CliError && error.code ===
|
|
78
|
+
if (error instanceof CliError && error.code === NOT_GLOBAL_INSTALL) {
|
|
51
79
|
return { state: "problem", message: error.message, fix: installCommandLine(install) };
|
|
52
80
|
}
|
|
53
81
|
throw error;
|
|
@@ -108,8 +136,17 @@ function skillRow(cli) {
|
|
|
108
136
|
},
|
|
109
137
|
};
|
|
110
138
|
}
|
|
111
|
-
/**
|
|
112
|
-
export function
|
|
113
|
-
return [
|
|
139
|
+
/** Every row `doctor` reports, in order: the fixed rows around the CLI's own and its tools'. */
|
|
140
|
+
export function doctorChecks(cli, bin) {
|
|
141
|
+
return [
|
|
142
|
+
buildRow(cli),
|
|
143
|
+
nodeRow(cli),
|
|
144
|
+
...(cli.project === undefined ? [] : [projectRow(cli.project)]),
|
|
145
|
+
...(cli.doctor ?? []),
|
|
146
|
+
...toolRows(cli.commands),
|
|
147
|
+
installRow(cli, bin),
|
|
148
|
+
registryRow(cli),
|
|
149
|
+
skillRow(cli),
|
|
150
|
+
];
|
|
114
151
|
}
|
|
115
152
|
//# sourceMappingURL=doctor-rows.js.map
|
package/dist/doctor-rows.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-rows.js","sourceRoot":"","sources":["../src/doctor-rows.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor-rows.js","sourceRoot":"","sources":["../src/doctor-rows.ts"],"names":[],"mappings":"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"}
|
package/dist/doctor.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { type Command, type CommandTreeCli } from "./define.js";
|
|
2
|
-
|
|
2
|
+
export declare const DOCTOR_PROBLEMS = "DOCTOR_PROBLEMS";
|
|
3
|
+
/** The built-in `doctor`: the fixed rows around the CLI's own, each under its own deadline. */
|
|
3
4
|
export declare function doctorCommand(cli: CommandTreeCli, bin: string | undefined): Command;
|
package/dist/doctor.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
+
import { untilAborted } from "./abort.js";
|
|
2
3
|
import { defineCommand, } from "./define.js";
|
|
3
|
-
import {
|
|
4
|
-
import { CliError,
|
|
5
|
-
const
|
|
4
|
+
import { doctorChecks } from "./doctor-rows.js";
|
|
5
|
+
import { CliError, messageOf } from "./errors.js";
|
|
6
|
+
export const DOCTOR_PROBLEMS = "DOCTOR_PROBLEMS";
|
|
7
|
+
const DEFAULT_DEADLINE_MS = 10_000;
|
|
6
8
|
const MS_PER_SECOND = 1000;
|
|
7
9
|
const MIN_LABEL_WIDTH = 8;
|
|
8
10
|
const rowSchema = z.object({
|
|
@@ -15,20 +17,11 @@ const reportSchema = z.object({
|
|
|
15
17
|
rows: z.array(rowSchema),
|
|
16
18
|
next: z.array(z.string()),
|
|
17
19
|
});
|
|
18
|
-
function
|
|
19
|
-
return new Promise((_resolve, reject) => {
|
|
20
|
-
if (signal.aborted) {
|
|
21
|
-
reject(signal.reason);
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
signal.addEventListener("abort", () => reject(signal.reason), { once: true });
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
function problemOf(check, error, { signal, deadline }) {
|
|
20
|
+
function problemOf(check, error, { signal, deadline, ms }) {
|
|
28
21
|
if (!signal.aborted && deadline.aborted && error === deadline.reason) {
|
|
29
22
|
return {
|
|
30
23
|
state: "problem",
|
|
31
|
-
message: `${check.name} did not answer within ${
|
|
24
|
+
message: `${check.name} did not answer within ${ms / MS_PER_SECOND} s`,
|
|
32
25
|
};
|
|
33
26
|
}
|
|
34
27
|
if (error instanceof CliError) {
|
|
@@ -38,7 +31,8 @@ function problemOf(check, error, { signal, deadline }) {
|
|
|
38
31
|
}
|
|
39
32
|
// Racing the deadline ends a row whose check ignores its signal.
|
|
40
33
|
async function rowOf(check, ctx) {
|
|
41
|
-
const
|
|
34
|
+
const ms = check.deadlineMs ?? DEFAULT_DEADLINE_MS;
|
|
35
|
+
const signal = ctx.deadline(ms);
|
|
42
36
|
let finding;
|
|
43
37
|
try {
|
|
44
38
|
finding = await Promise.race([
|
|
@@ -47,9 +41,9 @@ async function rowOf(check, ctx) {
|
|
|
47
41
|
]);
|
|
48
42
|
}
|
|
49
43
|
catch (error) {
|
|
50
|
-
finding = problemOf(check, error, { signal: ctx.signal, deadline: signal });
|
|
44
|
+
finding = problemOf(check, error, { signal: ctx.signal, deadline: signal, ms });
|
|
51
45
|
}
|
|
52
|
-
return { check: check.name, ...finding };
|
|
46
|
+
return { row: { check: check.name, ...finding }, advisory: check.advisory === true };
|
|
53
47
|
}
|
|
54
48
|
function nextOf(rows) {
|
|
55
49
|
return [...new Set(rows.flatMap(({ fix }) => (fix === undefined ? [] : [fix])))];
|
|
@@ -63,18 +57,16 @@ function render({ rows, next }, style) {
|
|
|
63
57
|
});
|
|
64
58
|
return [...lines, ...next.map((fix) => `${"next".padEnd(width)}${fix}`)].join("\n");
|
|
65
59
|
}
|
|
66
|
-
function failure(cliName, report) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
code: "DOCTOR_PROBLEMS",
|
|
60
|
+
function failure(cliName, problems, report) {
|
|
61
|
+
return new CliError({
|
|
62
|
+
code: DOCTOR_PROBLEMS,
|
|
70
63
|
message: `${cliName} doctor found ${problems.length === 1 ? "a problem" : `${problems.length} problems`}: ${problems.join(", ")}`,
|
|
71
64
|
hint: report.next.length === 0
|
|
72
65
|
? "each problem row says what is wrong"
|
|
73
66
|
: "run the commands under next, then run doctor again",
|
|
74
|
-
|
|
75
|
-
}, report);
|
|
67
|
+
});
|
|
76
68
|
}
|
|
77
|
-
/** The built-in `doctor`: the fixed rows
|
|
69
|
+
/** The built-in `doctor`: the fixed rows around the CLI's own, each under its own deadline. */
|
|
78
70
|
export function doctorCommand(cli, bin) {
|
|
79
71
|
return defineCommand({
|
|
80
72
|
name: "doctor",
|
|
@@ -86,11 +78,17 @@ export function doctorCommand(cli, bin) {
|
|
|
86
78
|
effect: "read",
|
|
87
79
|
output: reportSchema,
|
|
88
80
|
run: async (_input, ctx) => {
|
|
89
|
-
const
|
|
90
|
-
|
|
81
|
+
const checked = await Promise.all(doctorChecks(cli, bin).map((check) => rowOf(check, ctx)));
|
|
82
|
+
// Rows cut short by an interrupt report it as their problem, which no row has.
|
|
83
|
+
ctx.signal.throwIfAborted();
|
|
84
|
+
const rows = checked.map(({ row }) => row);
|
|
91
85
|
const report = { rows, next: nextOf(rows) };
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
const problems = checked
|
|
87
|
+
.filter(({ row, advisory }) => row.state === "problem" && !advisory)
|
|
88
|
+
.map(({ row }) => row.check);
|
|
89
|
+
if (problems.length > 0) {
|
|
90
|
+
ctx.deliver(report);
|
|
91
|
+
throw failure(cli.name, problems, report);
|
|
94
92
|
}
|
|
95
93
|
return report;
|
|
96
94
|
},
|
package/dist/doctor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAML,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/errno.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Env } from "./define.js";
|
|
2
|
+
export declare const PERMISSION_DENIED = "PERMISSION_DENIED";
|
|
3
|
+
export declare const DISK_FULL = "DISK_FULL";
|
|
4
|
+
export declare const NOT_FOUND = "NOT_FOUND";
|
|
5
|
+
export interface ErrnoContext {
|
|
6
|
+
readonly path: string;
|
|
7
|
+
/** The caller's command line, ready to paste. */
|
|
8
|
+
readonly callerLine: string;
|
|
9
|
+
readonly env: Env;
|
|
10
|
+
}
|
|
11
|
+
/** The error a file system failure on `path` stands for; any other error comes back unchanged. */
|
|
12
|
+
export declare function classifyErrno(error: unknown, context: ErrnoContext): unknown;
|
package/dist/errno.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { isAgent } from "./agent.js";
|
|
2
|
+
import { CliError, errnoOf } from "./errors.js";
|
|
3
|
+
export const PERMISSION_DENIED = "PERMISSION_DENIED";
|
|
4
|
+
export const DISK_FULL = "DISK_FULL";
|
|
5
|
+
export const NOT_FOUND = "NOT_FOUND";
|
|
6
|
+
// The same errnos happen with no sandbox at all (a root-owned folder), so only a detected agent is
|
|
7
|
+
// pointed at its sandbox.
|
|
8
|
+
function permissionHint({ path, callerLine, env }) {
|
|
9
|
+
return isAgent(env)
|
|
10
|
+
? `your sandbox may block it: ask your user to run \`! ${callerLine}\`, or to allow ${path} in the sandbox's write list`
|
|
11
|
+
: `check the permissions of ${path} and its folder`;
|
|
12
|
+
}
|
|
13
|
+
/** The error a file system failure on `path` stands for; any other error comes back unchanged. */
|
|
14
|
+
export function classifyErrno(error, context) {
|
|
15
|
+
const { path } = context;
|
|
16
|
+
switch (errnoOf(error)) {
|
|
17
|
+
case "EACCES":
|
|
18
|
+
case "EPERM":
|
|
19
|
+
return new CliError({
|
|
20
|
+
code: PERMISSION_DENIED,
|
|
21
|
+
message: `permission denied: ${path}`,
|
|
22
|
+
hint: permissionHint(context),
|
|
23
|
+
}, { cause: error });
|
|
24
|
+
case "ENOSPC":
|
|
25
|
+
return new CliError({
|
|
26
|
+
code: DISK_FULL,
|
|
27
|
+
message: `no space left on the disk holding ${path}`,
|
|
28
|
+
hint: "free space on that disk, then run the same command again",
|
|
29
|
+
}, { cause: error });
|
|
30
|
+
case "ENOENT":
|
|
31
|
+
return new CliError({
|
|
32
|
+
code: NOT_FOUND,
|
|
33
|
+
message: `not found: ${path}`,
|
|
34
|
+
hint: `check that ${path} and its folder exist`,
|
|
35
|
+
}, { cause: error });
|
|
36
|
+
default:
|
|
37
|
+
return error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=errno.js.map
|
|
@@ -0,0 +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;AASrC,mGAAmG;AACnG,0BAA0B;AAC1B,SAAS,cAAc,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAgB;IAC7D,OAAO,OAAO,CAAC,GAAG,CAAC;QACjB,CAAC,CAAC,uDAAuD,UAAU,mBAAmB,IAAI,8BAA8B;QACxH,CAAC,CAAC,4BAA4B,IAAI,iBAAiB,CAAC;AACxD,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;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type * as z from "zod";
|
|
2
|
+
import { CliError } from "./errors.js";
|
|
3
|
+
import type { ExitClass } from "./exit-classes.js";
|
|
4
|
+
/** The Exit classes a CLI's own code can have; a bug or an interrupt is the Runtime's to tell. */
|
|
5
|
+
export type DeclaredExitClass = Exclude<ExitClass, "bug" | "interrupted">;
|
|
6
|
+
export interface ErrorDeclaration {
|
|
7
|
+
readonly class: DeclaredExitClass;
|
|
8
|
+
readonly details?: z.ZodType;
|
|
9
|
+
}
|
|
10
|
+
/** A CLI's error codes, each with the class that must act on it and the facts it carries. */
|
|
11
|
+
export type ErrorTable = Readonly<Record<string, ErrorDeclaration>>;
|
|
12
|
+
/** Keeps each code's literal class and `details` schema, so `cliError` can type its throw sites. */
|
|
13
|
+
export declare function defineErrors<const Table extends ErrorTable>(table: Table): Table;
|
|
14
|
+
type DetailsInit<Declaration> = Declaration extends {
|
|
15
|
+
readonly details: infer Schema;
|
|
16
|
+
} ? Schema extends z.ZodType ? {
|
|
17
|
+
readonly details: z.output<Schema>;
|
|
18
|
+
} : never : {
|
|
19
|
+
readonly details?: never;
|
|
20
|
+
};
|
|
21
|
+
type RetryInit<Declaration> = Declaration extends {
|
|
22
|
+
readonly class: "wait";
|
|
23
|
+
} ? {
|
|
24
|
+
readonly retryAt?: string;
|
|
25
|
+
} : {
|
|
26
|
+
readonly retryAt?: never;
|
|
27
|
+
};
|
|
28
|
+
export type CliErrorInit<Declaration extends ErrorDeclaration> = {
|
|
29
|
+
readonly message: string;
|
|
30
|
+
readonly hint: string;
|
|
31
|
+
} & DetailsInit<Declaration> & RetryInit<Declaration>;
|
|
32
|
+
/** A `CliError` for a code of `table`, whose `details` must match the code's schema. */
|
|
33
|
+
export declare function cliError<Table extends ErrorTable, Code extends keyof Table & string>(_table: Table, code: Code, init: CliErrorInit<Table[Code]>, options?: ErrorOptions): CliError;
|
|
34
|
+
export {};
|