@duyquangnvx/agent-cli 0.4.0 → 0.5.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 +46 -0
- package/dist/agent-cli.js +1 -1
- 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.d.ts +6 -1
- package/dist/built-ins.js +3 -3
- package/dist/built-ins.js.map +1 -1
- package/dist/command-spec.d.ts +5 -0
- package/dist/command-spec.js +7 -0
- 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 +102 -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 +35 -80
- package/dist/define.js +3 -1
- package/dist/define.js.map +1 -1
- package/dist/doctor-rows.d.ts +2 -1
- package/dist/doctor-rows.js +15 -10
- package/dist/doctor-rows.js.map +1 -1
- package/dist/doctor.d.ts +2 -1
- package/dist/doctor.js +24 -17
- package/dist/doctor.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/errors.d.ts +2 -1
- package/dist/errors.js +4 -0
- 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 +4 -1
- package/dist/exit-classes.js.map +1 -1
- package/dist/files.d.ts +23 -6
- package/dist/files.js +100 -14
- package/dist/files.js.map +1 -1
- package/dist/help-json.d.ts +1 -1
- package/dist/help-json.js +4 -1
- package/dist/help-json.js.map +1 -1
- package/dist/help.d.ts +1 -1
- package/dist/help.js +11 -7
- package/dist/help.js.map +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.js +4 -1
- 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 +3 -1
- package/dist/interrupts.js +4 -3
- 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.js +5 -2
- package/dist/list.js.map +1 -1
- package/dist/npm.d.ts +5 -2
- package/dist/npm.js +23 -31
- package/dist/npm.js.map +1 -1
- 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 +4 -1
- package/dist/output.js +4 -0
- 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 +68 -26
- package/dist/parse-input.js.map +1 -1
- package/dist/project.d.ts +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 +16 -2
- package/dist/run-cli.js +89 -34
- package/dist/run-cli.js.map +1 -1
- package/dist/run-process.js +3 -2
- package/dist/run-process.js.map +1 -1
- package/dist/secrets.d.ts +5 -4
- package/dist/secrets.js +4 -5
- package/dist/secrets.js.map +1 -1
- package/dist/skill-source.d.ts +4 -0
- package/dist/skill-source.js +42 -0
- package/dist/skill-source.js.map +1 -0
- package/dist/skills.d.ts +2 -1
- package/dist/skills.js +4 -0
- package/dist/skills.js.map +1 -1
- package/dist/spawn.d.ts +22 -5
- 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 +13 -0
- package/dist/stdin.js +55 -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/update.d.ts +2 -1
- package/dist/update.js +3 -3
- package/dist/update.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,52 @@ What changed in each release of `@duyquangnvx/agent-cli` (the Runtime) and `@duy
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## v0.5.0 (2026-10-19)
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- A command-tree CLI may declare `defineCli({ tools })`, the tools `doctor` checks besides its Commands' own. `doctor` reports one row per tool from the CLI's `tools` and every Command's, once per name, a missing one as a problem with its `install` as the fix. A Command still requires only its own `tools`, so the CLI's list never makes a Command refuse with `TOOL_MISSING`.
|
|
12
|
+
- A Command may declare `hidden: true`. It routes and runs when named, and its own `--help` works, but it is left out of text help, `--help --json`, the root examples and "did you mean" suggestions for a misspelt Command.
|
|
13
|
+
- A Command may declare `operator: true`, an Operator Command only a person at a terminal runs. When a Coding agent is detected, the run fails before its input is read, stdin included, with the new Runtime code `NEEDS_OPERATOR` (exit 2, exported as a constant), whose hint is `ask the operator to type: ! <command line as typed>`; `--json` alone does not refuse. Text help marks it `(operator only)` in a listing and with an `Operator Command:` line in its own help, and `--help --json` carries `operator` on every Command, `true` on an Operator Command and `false` on the rest.
|
|
14
|
+
- A Command may declare `help`, a paragraph printed as written after the options in text help. `--help --json` carries it as `help`, which is `null` on a Command without one.
|
|
15
|
+
- `ctx.spawn(command, args, { progress: true })` passes each line of the child's stdout and stderr through `ctx.progress` as it arrives, and still resolves to the whole output, which `check: true` uses for `TOOL_FAILED`. A `Spawn` passed as `runCli`'s `spawn` option receives an `onLine` callback when the caller asked for progress, to emit the child's lines.
|
|
16
|
+
- On Windows, `ctx.spawn` runs a `.cmd` or `.bat` tool, such as one npm installed, found on `PATH` through `PATHEXT` or given by its path. Each argument reaches the tool as given: it is quoted, then escaped for `cmd.exe`, which otherwise expands `%VAR%` and acts on `&`, `|`, `<`, `>`, `^`, `(`, `)` and `!` even inside quotes, twice for a `.cmd` shim that hands its arguments to a second `cmd.exe` parse, as cross-spawn does.
|
|
17
|
+
- A field of a Command's `options` may be a `z.array(...)`, optionally wrapped in optional or default, which collects every occurrence of its flag in order: `--ref a --ref=b --ref c` gives `ref: ["a", "b", "c"]`. Each value is coerced like a scalar option of the element's type, and an issue on one names it, as in `--row "x": ...`. None gives an empty array for the schema to judge, or leaves an optional field out so its default applies. Text help shows the flag as `--ref <value>...`, and `--help --json` gives it the array schema. `defineCommand` throws for an array of booleans. A repeated scalar flag still keeps its last value.
|
|
18
|
+
- `ctx.commandLine({ add?, remove? })` returns the command line as the caller typed it, starting with the CLI's name and shell-quoted, with each flag in `remove` dropped along with its value (`--from 3`, `--from=3`, every time it was given) and the words in `add` placed before any `--`, for a hint naming the exact command to run next. It is the helper the Runtime's own hints (`--confirm`, `--yes`, `--force`, a page's `next`) are built with.
|
|
19
|
+
- A run deadline's `resume(input, commandLine)` receives `ctx.commandLine` as its second argument. A `resume` taking only `input` still type-checks.
|
|
20
|
+
- `ctx.poll(check, { intervalMs, signal })` also stops when `signal` aborts, ending with its reason, so `signal: ctx.deadline(ms)` stops polling at a `--wait` deadline rather than one interval after it.
|
|
21
|
+
- `INTERRUPTED` and `DEADLINE_EXCEEDED` are exported as constants, so a Command tells `ctx.signal.reason` apart and throws its own `INTERRUPTED` with a hint it computes, which wins over the Runtime's. The skill teaches it.
|
|
22
|
+
- A `doctor` row may return `{ state: "skipped", message }` for a check it did not run, such as "not checked: the bridge is down". It shows in text and `--json` and never fails `doctor`.
|
|
23
|
+
- On Ctrl-C or SIGTERM, `doctor` prints the rows finished so far, in text or `--json`, before the run ends with 130 or 143. Rows cut short are left out.
|
|
24
|
+
- With no copy of the skill installed, `doctor`'s `skill` row gives the fix `npx -y skills add <source> --skill <cli name> -g`, which installs only this CLI's skill from a repo holding several, and stays ok. The source is `defineCli({ skill: { source } })` as given, else the package.json `repository` URL with `git+` dropped, `.git` added if missing and `#release` appended, for an `https`, `http`, `ssh` or `git` URL or an scp-style `git@host:group/repo`; a GitHub `owner/repo` shorthand is kept as it is. With no `repository`, one that is neither, or a package.json that cannot be read or parsed, the row gives no fix.
|
|
25
|
+
- `orStdin(schema)` marks one string field of a Command's `args` as also reading stdin: when its operand is exactly `-`, the Runtime reads stdin to its end as UTF-8, before `plan`, `run` or `start`, and the field's schema judges the text, so an empty or invalid text fails with `INVALID_INPUT` like typed text, the issue naming the field `from stdin` instead of quoting the text. Ctrl-C and the run deadline stop a read that never ends; a deadline hit there hints to pipe the text in. When stdin is a terminal, a progress line first says what is read and how to end it (Ctrl-D, or Ctrl-Z then Enter on Windows). Text help shows the field as `<name|->` (`[name|-]` when optional), and `--help --json` marks it `"stdin": true`. `defineCommand` throws for two such args, or for the marker on an option. `runCli` takes `stdin`, a string or a readable stream, read by a `-`; absent, a `-` reads an empty text. The type `StdinSource` is exported.
|
|
26
|
+
- The ports factory's `PortsBase` adds `progress`, `fileError`, `version`, `build` and `self`, which `Context` carries too: a bridge or store writes progress lines (JSON Lines under `--json`) and classifies a failure of its own file as a Command does. `version` and `build` are the CLI's version and bundler stamp as `--version` prints them, `build` absent when unbundled. `self` is the command line that reruns the CLI, `[process.execPath, ...process.execArgv, bin]` from `runCli`'s `bin`, or `[name]`, found on `PATH`, without one, for spawning a hidden Command. The type `BuildStamp` is exported.
|
|
27
|
+
- `ctx.fileError(error, { path, access })` turns an errno failure of a Command's own file access, such as a SQLite store or a log it opens itself, into the Runtime's classified error, with the same codes and hints as `ctx.files`; any other error comes back unchanged. The type `FileAccess` is exported.
|
|
28
|
+
- The Runtime code `NOT_A_FILE` (exit 1), raised for EISDIR, such as `ctx.files.read` of a folder, naming the path. It is exported as a constant.
|
|
29
|
+
- `runCli` takes a `platform` option, which replaces `process.platform` in picking the wording of hints, the `PERMISSION_DENIED` hint and how to end stdin, so a test checks the Windows wording on any OS.
|
|
30
|
+
- `ctx.files.write(path, data, { exclusive, mode })`: `exclusive: true` fails with `ALREADY_EXISTS` when anything is at the path, never leaving half a file there, and `mode` sets the file's permission bits whatever mode an older file had. The type `WriteOptions` is exported.
|
|
31
|
+
- `ctx.files.stat(path)` returns `{ size, id }`, where `id` is the same for every link to one file (device and inode), or `undefined` when nothing is at the path or a part of it is a file. The type `FileStat` is exported.
|
|
32
|
+
- The agent-cli skill's example `links` has `import <text|->`, which saves every link found in a text, read from stdin when given `-`, tags each with every repeated `--tag`, and explains its stdin form in a `help` paragraph. The scaffolded template's `card` takes an optional message to write under the greeting, read from stdin when given `-`, signs the card from every repeated `--from`, and states its cost in a `help` paragraph; its tests cover each.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **Breaking:** `DoctorFinding` is a union over `state`: `ok` (`message`, `fix?`), `problem` (`message`, `fix?`, `code?`) and `skipped` (`message`). A row that throws a `CliError` keeps its code, and `doctor --json` rows carry `code`.
|
|
37
|
+
- **Breaking:** `doctor` fails with one error per non-advisory problem row, with the row's code or `DOCTOR_PROBLEMS` without one, so it exits by the first of 1, 2, 3 and 75 that any of them has, not always 2: an expired session exits 3, a network failure 75. Each error's message is `<cli> doctor found a problem in <row>: <message>`. The report still prints on stdout.
|
|
38
|
+
- **Breaking:** the `Files` interface gains `stat`, and its `write` receives the write options, so every fake passed as `runCli`'s `files` option must implement `stat`. The scaffolded template's fake and the skill's example implement it.
|
|
39
|
+
- **Breaking:** more errno are classified, naming the path: EROFS and EBUSY fail with `PERMISSION_DENIED` (exit 2, with the sandbox hint under a Coding agent), EDQUOT with `DISK_FULL` (exit 2), and ENOTDIR and ENAMETOOLONG with `NOT_FOUND` (exit 1). Each was exit 70 before, so a write Claude Code's Linux sandbox denies with EROFS no longer reads as a bug.
|
|
40
|
+
- **Breaking:** for a Command with `outputs`, after every guard passes and before `apply`, the Runtime creates each output's folder and a temp file in it, so a denied folder fails with `PERMISSION_DENIED` naming the folder before `apply` runs; `--dry-run` and a refused guard create nothing. Without `--force`, the first write to each output during `apply`, through `ctx.files` or a port's `files`, is exclusive: it fails with `ALREADY_EXISTS`, whose hint names the command line with `--force`, if the file appeared meanwhile. A later write to an output the run already wrote replaces it; with `--force` every write replaces.
|
|
41
|
+
- **Breaking:** agent detection follows gh's marker list: `AI_AGENT` (an agent name), `AGENT=amp`, `CODEX_SANDBOX`, `CODEX_CI`, `CODEX_THREAD_ID`, `GEMINI_CLI`, `COPILOT_CLI`, `OPENCODE`, `ANTIGRAVITY_AGENT`, `AUGMENT_AGENT`, `REPL_ID`, `CLAUDE_CODE_IS_COWORK`, `CLAUDECODE`, `CLAUDE_CODE`, `CURSOR_TRACE_ID`, `CURSOR_AGENT`, `CURSOR_EXTENSION_HOST_ROLE=agent-exec`, `TERM_PROGRAM=kiro`, a `.pi/agent` folder on `PATH`, or `GOOSE_PROVIDER`. A marker set to an empty string no longer counts, and `CI` alone no longer counts as an agent, so a usage error in a CI job prints the error and hint without the full help, and a CI job on a TTY gets colour.
|
|
42
|
+
- **Breaking:** under `--json`, stderr is JSON Lines (ADR 0006): each `ctx.progress(message)` writes `{"progress":"<message>"}` as it happens, the Runtime's own progress lines (`finishing <name>`, the `stopping… (Ctrl-C again to quit now)` notice, the stdin announcement) and a spawned child's lines under `progress: true` are written the same way, and a failure's `{"errors":[…]}` stays the last line, so every stderr line parses as JSON. Without `--json`, progress stays plain text. The agent-cli skill and the scaffolded skill say so.
|
|
43
|
+
- On Windows, the `PERMISSION_DENIED` hint says a program may hold the path open, and to close it, then run the same command again.
|
|
44
|
+
- `ctx.files.write` through a symlink replaces the link's target and keeps the link.
|
|
45
|
+
- On Windows, a replacing `ctx.files.write` retries a transient EPERM or EBUSY, such as an antivirus scan holding the file, for about half a second before failing with `PERMISSION_DENIED`.
|
|
46
|
+
- `doctor` and `update` run the npm beside the Node running the CLI (`npm`, or `npm.cmd` on Windows), with that Node first on its `PATH`, so under nvm they install into that Node; with no npm beside it, they run the npm on `PATH` as before. `runCli` gains the option `node`, the path `runProcess` passes as `process.execPath`; absent, npm comes from `PATH`.
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- On Windows, an interrupt kills the child `ctx.spawn` started, or the npm `doctor` and `update` run, together with every process it started (`taskkill /T /F`), so Ctrl-C leaves no orphaned processes.
|
|
51
|
+
- `ctx.files.exists` answers false for a path under a file instead of failing.
|
|
52
|
+
|
|
7
53
|
## v0.4.0 (2026-10-19)
|
|
8
54
|
|
|
9
55
|
### Added
|
package/dist/agent-cli.js
CHANGED
|
@@ -12,7 +12,7 @@ function defineCli(cli) {
|
|
|
12
12
|
if (cli.commands === undefined)
|
|
13
13
|
return cli;
|
|
14
14
|
const { commands } = cli;
|
|
15
|
-
const taken = Object.keys(builtInCommands(cli, undefined)).filter((name) => commands[name] !== undefined);
|
|
15
|
+
const taken = Object.keys(builtInCommands(cli, { bin: undefined, node: undefined })).filter((name) => commands[name] !== undefined);
|
|
16
16
|
if (taken.length > 0) {
|
|
17
17
|
throw new Error(`${cli.name} defines ${taken.join(", ")}, a built-in Command it cannot replace`);
|
|
18
18
|
}
|
package/dist/agent-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-cli.js","sourceRoot":"","sources":["../src/agent-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAIL,gBAAgB,GAGjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAgBnD,SAAS,aAAa,CAAkB,GAAyB;IAC/D,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACpD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,GAAG,GAAG,CAAC,IAAI,aAAa,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,8CAA8C,CAC5F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAkB,GAAyB;IAC3D,aAAa,CAAC,GAAG,CAAC,CAAC;IACnB,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IAC3C,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;IACzB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"agent-cli.js","sourceRoot":"","sources":["../src/agent-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAIL,gBAAgB,GAGjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAgBnD,SAAS,aAAa,CAAkB,GAAyB;IAC/D,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACpD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,GAAG,GAAG,CAAC,IAAI,aAAa,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,8CAA8C,CAC5F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAkB,GAAyB;IAC3D,aAAa,CAAC,GAAG,CAAC,CAAC;IACnB,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IAC3C,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;IACzB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,MAAM,CACzF,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,SAAS,CACvC,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,GAAG,GAAG,CAAC,IAAI,YAAY,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,wCAAwC,CAChF,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAmB,EAAE,SAAS,EAAE,CAAC;AAC3E,CAAC"}
|
package/dist/agent.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { Env } from "./
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { Env } from "./context.js";
|
|
2
|
+
/**
|
|
3
|
+
* Whether a Coding agent, not a person, is running the Agent CLI. Some Coding agents run commands
|
|
4
|
+
* in a PTY, so a TTY alone doesn't mean a person is watching.
|
|
5
|
+
*/
|
|
4
6
|
export declare function isAgent(env: Env): boolean;
|
package/dist/agent.js
CHANGED
|
@@ -1,14 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
"
|
|
1
|
+
const AGENT_NAME = /^[a-zA-Z0-9_-]+$/u;
|
|
2
|
+
const isSet = (name) => (env) => (env[name] ?? "") !== "";
|
|
3
|
+
const equals = (name, value) => (env) => env[name] === value;
|
|
4
|
+
// Copied in order from gh, which keeps it current as agents appear:
|
|
5
|
+
// https://github.com/cli/cli/blob/17142e08db2e300b37e6da1ddcfb651eb6d9c587/internal/agents/detect.go
|
|
6
|
+
const MARKERS = [
|
|
7
|
+
(env) => AGENT_NAME.test(env.AI_AGENT ?? ""),
|
|
8
|
+
equals("AGENT", "amp"),
|
|
9
|
+
isSet("CODEX_SANDBOX"),
|
|
10
|
+
isSet("CODEX_CI"),
|
|
11
|
+
isSet("CODEX_THREAD_ID"),
|
|
12
|
+
isSet("GEMINI_CLI"),
|
|
13
|
+
isSet("COPILOT_CLI"),
|
|
14
|
+
isSet("OPENCODE"),
|
|
15
|
+
isSet("ANTIGRAVITY_AGENT"),
|
|
16
|
+
isSet("AUGMENT_AGENT"),
|
|
17
|
+
isSet("REPL_ID"),
|
|
18
|
+
isSet("CLAUDE_CODE_IS_COWORK"),
|
|
19
|
+
isSet("CLAUDECODE"),
|
|
20
|
+
isSet("CLAUDE_CODE"),
|
|
21
|
+
isSet("CURSOR_TRACE_ID"),
|
|
22
|
+
isSet("CURSOR_AGENT"),
|
|
23
|
+
equals("CURSOR_EXTENSION_HOST_ROLE", "agent-exec"),
|
|
24
|
+
equals("TERM_PROGRAM", "kiro"),
|
|
25
|
+
(env) => ["/.pi/agent", "\\.pi\\agent"].some((dir) => (env.PATH ?? "").includes(dir)),
|
|
26
|
+
isSet("GOOSE_PROVIDER"),
|
|
9
27
|
];
|
|
10
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Whether a Coding agent, not a person, is running the Agent CLI. Some Coding agents run commands
|
|
30
|
+
* in a PTY, so a TTY alone doesn't mean a person is watching.
|
|
31
|
+
*/
|
|
11
32
|
export function isAgent(env) {
|
|
12
|
-
return
|
|
33
|
+
return MARKERS.some((marker) => marker(env));
|
|
13
34
|
}
|
|
14
35
|
//# sourceMappingURL=agent.js.map
|
package/dist/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAG,mBAAmB,CAAC;AAEvC,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;AACvE,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC;AAElF,oEAAoE;AACpE,qGAAqG;AACrG,MAAM,OAAO,GAAuC;IAClD,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC5C,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC;IACtB,KAAK,CAAC,eAAe,CAAC;IACtB,KAAK,CAAC,UAAU,CAAC;IACjB,KAAK,CAAC,iBAAiB,CAAC;IACxB,KAAK,CAAC,YAAY,CAAC;IACnB,KAAK,CAAC,aAAa,CAAC;IACpB,KAAK,CAAC,UAAU,CAAC;IACjB,KAAK,CAAC,mBAAmB,CAAC;IAC1B,KAAK,CAAC,eAAe,CAAC;IACtB,KAAK,CAAC,SAAS,CAAC;IAChB,KAAK,CAAC,uBAAuB,CAAC;IAC9B,KAAK,CAAC,YAAY,CAAC;IACnB,KAAK,CAAC,aAAa,CAAC;IACpB,KAAK,CAAC,iBAAiB,CAAC;IACxB,KAAK,CAAC,cAAc,CAAC;IACrB,MAAM,CAAC,4BAA4B,EAAE,YAAY,CAAC;IAClD,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC;IAC9B,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACrF,KAAK,CAAC,gBAAgB,CAAC;CACxB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,GAAQ;IAC9B,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/C,CAAC"}
|
package/dist/built-ins.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import type { Commands, CommandTreeCli } from "./define.js";
|
|
2
|
+
/** How the CLI was started: the script, and the Node running it. */
|
|
3
|
+
export interface Launch {
|
|
4
|
+
readonly bin: string | undefined;
|
|
5
|
+
readonly node: string | undefined;
|
|
6
|
+
}
|
|
2
7
|
/** The Commands the Runtime adds to a multi-Command CLI: `update` only when it declares an install. */
|
|
3
|
-
export declare function builtInCommands(cli: CommandTreeCli,
|
|
8
|
+
export declare function builtInCommands(cli: CommandTreeCli, launch: Launch): Commands;
|
package/dist/built-ins.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { doctorCommand } from "./doctor.js";
|
|
2
2
|
import { updateCommand } from "./update.js";
|
|
3
3
|
/** The Commands the Runtime adds to a multi-Command CLI: `update` only when it declares an install. */
|
|
4
|
-
export function builtInCommands(cli,
|
|
4
|
+
export function builtInCommands(cli, launch) {
|
|
5
5
|
return {
|
|
6
|
-
doctor: doctorCommand(cli,
|
|
7
|
-
...(cli.install === undefined ? {} : { update: updateCommand(cli, cli.install,
|
|
6
|
+
doctor: doctorCommand(cli, launch),
|
|
7
|
+
...(cli.install === undefined ? {} : { update: updateCommand(cli, cli.install, launch) }),
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
10
|
//# sourceMappingURL=built-ins.js.map
|
package/dist/built-ins.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"built-ins.js","sourceRoot":"","sources":["../src/built-ins.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"built-ins.js","sourceRoot":"","sources":["../src/built-ins.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQ5C,uGAAuG;AACvG,MAAM,UAAU,eAAe,CAAC,GAAmB,EAAE,MAAc;IACjE,OAAO;QACL,MAAM,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC;QAClC,GAAG,CAAC,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;KAC1F,CAAC;AACJ,CAAC"}
|
package/dist/command-spec.d.ts
CHANGED
|
@@ -9,6 +9,9 @@ export interface CommandSpec {
|
|
|
9
9
|
readonly commandLine: string;
|
|
10
10
|
readonly command: Command;
|
|
11
11
|
readonly description: string;
|
|
12
|
+
readonly help: string | undefined;
|
|
13
|
+
readonly hidden: boolean;
|
|
14
|
+
readonly operator: boolean;
|
|
12
15
|
readonly effect: Command["effect"];
|
|
13
16
|
readonly examples: readonly Example[];
|
|
14
17
|
readonly args: readonly InputField[];
|
|
@@ -24,5 +27,7 @@ export interface GroupSpec {
|
|
|
24
27
|
readonly commands: Readonly<Record<string, SpecNode>>;
|
|
25
28
|
}
|
|
26
29
|
export type SpecNode = CommandSpec | GroupSpec;
|
|
30
|
+
/** The group's Commands and groups that help and suggestions may name: hidden Commands left out. */
|
|
31
|
+
export declare function visibleCommands({ commands }: GroupSpec): Readonly<Record<string, SpecNode>>;
|
|
27
32
|
export declare function commandSpec(commandLine: string, command: Command): CommandSpec;
|
|
28
33
|
export declare function groupSpec(commandLine: string, commands: Commands): GroupSpec;
|
package/dist/command-spec.js
CHANGED
|
@@ -3,6 +3,10 @@ import { standardFlagsFor } from "./flags.js";
|
|
|
3
3
|
import { argFields, optionFields } from "./input.js";
|
|
4
4
|
import { listSpec } from "./list.js";
|
|
5
5
|
import { hasPlan } from "./planned.js";
|
|
6
|
+
/** The group's Commands and groups that help and suggestions may name: hidden Commands left out. */
|
|
7
|
+
export function visibleCommands({ commands }) {
|
|
8
|
+
return Object.fromEntries(Object.entries(commands).filter(([, node]) => node.kind === "group" || !node.hidden));
|
|
9
|
+
}
|
|
6
10
|
function declaredOf(command) {
|
|
7
11
|
if (!hasPlan(command)) {
|
|
8
12
|
return { outputs: false, force: undefined, cost: false };
|
|
@@ -20,6 +24,9 @@ export function commandSpec(commandLine, command) {
|
|
|
20
24
|
commandLine,
|
|
21
25
|
command,
|
|
22
26
|
description: command.description,
|
|
27
|
+
help: command.help,
|
|
28
|
+
hidden: command.hidden === true,
|
|
29
|
+
operator: command.operator === true,
|
|
23
30
|
effect: command.effect,
|
|
24
31
|
examples: command.examples,
|
|
25
32
|
args: argFields(command.args),
|
package/dist/command-spec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-spec.js","sourceRoot":"","sources":["../src/command-spec.ts"],"names":[],"mappings":"AACA,OAAO,EAA6C,SAAS,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAoC,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,EAAE,SAAS,EAAmB,YAAY,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAiB,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"command-spec.js","sourceRoot":"","sources":["../src/command-spec.ts"],"names":[],"mappings":"AACA,OAAO,EAA6C,SAAS,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAoC,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,EAAE,SAAS,EAAmB,YAAY,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAiB,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AA6BvC,oGAAoG;AACpG,MAAM,UAAU,eAAe,CAAC,EAAE,QAAQ,EAAa;IACrD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CACrF,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,OAAgB;IAClC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC3D,CAAC;IACD,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO,KAAK,SAAS;QACtC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,IAAI,EAAE,OAAO,CAAC,IAAI,KAAK,SAAS;KACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,WAAmB,EAAE,OAAgB;IAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,OAAO;QACL,IAAI,EAAE,SAAS;QACf,WAAW;QACX,OAAO;QACP,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,EAAE,OAAO,CAAC,MAAM,KAAK,IAAI;QAC/B,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,IAAI;QACnC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;QAC7B,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC;QACtC,aAAa,EAAE,gBAAgB,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC;QAC1E,IAAI;QACJ,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,OAAO,CAAC,MAAM;KACvC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,WAAmB,EAAE,QAAkB;IAC/D,OAAO;QACL,IAAI,EAAE,OAAO;QACb,WAAW;QACX,QAAQ,EAAE,MAAM,CAAC,WAAW,CAC1B,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,WAAW,IAAI,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAC5F;KACF,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,WAAmB,EAAE,IAAwB;IAC3D,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AACzF,CAAC"}
|
package/dist/confirm.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { UsageError } from "./errors.js";
|
|
2
2
|
import { CONFIRM_FLAG } from "./flags.js";
|
|
3
|
-
import {
|
|
3
|
+
import { commandLineOf } from "./invocation.js";
|
|
4
4
|
export const CONFIRMATION_REQUIRED = "CONFIRMATION_REQUIRED";
|
|
5
5
|
export const CONFIRMATION_MISMATCH = "CONFIRMATION_MISMATCH";
|
|
6
6
|
export function checkConfirmation({ invocation, commandLine, given }, expected) {
|
|
7
7
|
if (given === expected) {
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
|
-
const
|
|
10
|
+
const confirmed = commandLineOf(invocation, {
|
|
11
|
+
remove: [CONFIRM_FLAG.flag],
|
|
12
|
+
add: [CONFIRM_FLAG.flag, expected],
|
|
13
|
+
});
|
|
14
|
+
const hint = `to confirm, run \`${confirmed}\``;
|
|
11
15
|
if (given === undefined) {
|
|
12
16
|
throw new UsageError({
|
|
13
17
|
code: CONFIRMATION_REQUIRED,
|
package/dist/confirm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirm.js","sourceRoot":"","sources":["../src/confirm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"confirm.js","sourceRoot":"","sources":["../src/confirm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAC7D,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAQ7D,MAAM,UAAU,iBAAiB,CAC/B,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAgB,EAChD,QAAgB;IAEhB,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IACD,MAAM,SAAS,GAAG,aAAa,CAAC,UAAU,EAAE;QAC1C,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC;QAC3B,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC;KACnC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,qBAAqB,SAAS,IAAI,CAAC;IAChD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,UAAU,CAAC;YACnB,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,KAAK,WAAW,+BAA+B,YAAY,CAAC,IAAI,EAAE;YAC3E,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IACD,MAAM,IAAI,UAAU,CAAC;QACnB,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,GAAG,YAAY,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,mCAAmC,WAAW,IAAI;QACxG,IAAI;KACL,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type * as z from "zod";
|
|
2
|
+
import type { Clock } from "./clock.js";
|
|
3
|
+
import type { FileAccess } from "./errno.js";
|
|
4
|
+
import type { Files } from "./files.js";
|
|
5
|
+
import type { CommandLineChange } from "./invocation.js";
|
|
6
|
+
import type { Secret } from "./secrets.js";
|
|
7
|
+
import type { ContextSpawn } from "./spawn.js";
|
|
8
|
+
export type Env = Readonly<Record<string, string | undefined>>;
|
|
9
|
+
export interface PollOptions {
|
|
10
|
+
readonly intervalMs: number;
|
|
11
|
+
/** Stops the polling when it aborts, as `ctx.signal` does; pass `ctx.deadline(ms)` for a wait. */
|
|
12
|
+
readonly signal?: AbortSignal;
|
|
13
|
+
}
|
|
14
|
+
/** The commit a build was made from and when, stamped by the bundler. */
|
|
15
|
+
export interface BuildStamp {
|
|
16
|
+
readonly sha: string;
|
|
17
|
+
readonly dirty: boolean;
|
|
18
|
+
readonly builtAt: string;
|
|
19
|
+
}
|
|
20
|
+
export interface Context<Ports = unknown, Settings = unknown> {
|
|
21
|
+
readonly cwd: string;
|
|
22
|
+
readonly env: Env;
|
|
23
|
+
/** The CLI's version, as `--version` prints it. */
|
|
24
|
+
readonly version: string;
|
|
25
|
+
/** The bundler's stamp, as `--version` prints it; absent when the CLI runs unbundled. */
|
|
26
|
+
readonly build: BuildStamp | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* The command line that reruns this CLI, to spawn one of its hidden Commands: Node, its flags and
|
|
29
|
+
* the bin, or the CLI's name, found on PATH, when run without a bin.
|
|
30
|
+
*/
|
|
31
|
+
readonly self: readonly string[];
|
|
32
|
+
/** The folder holding this CLI's `package.json`, for reading files shipped in the package. */
|
|
33
|
+
readonly packageRoot: string;
|
|
34
|
+
/** Writes a plain line to stderr, for long work; it never reaches stdout. */
|
|
35
|
+
progress(message: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Aborts when the run is interrupted (Ctrl-C) or hits the Command's run deadline; pass it to
|
|
38
|
+
* `fetch` and child processes.
|
|
39
|
+
*/
|
|
40
|
+
readonly signal: AbortSignal;
|
|
41
|
+
/** Returns a signal that also aborts, with `DEADLINE_EXCEEDED`, once `ms` have passed. */
|
|
42
|
+
deadline(ms: number): AbortSignal;
|
|
43
|
+
/**
|
|
44
|
+
* Runs a step that must not stop halfway: the run waits for it even when stopped, and then
|
|
45
|
+
* prints `finishing <name>` on stderr.
|
|
46
|
+
*/
|
|
47
|
+
runToEnd<T>(name: string, work: () => Promise<T>): Promise<T>;
|
|
48
|
+
/**
|
|
49
|
+
* Records the data done so far, in the shape `render` takes; the last call wins. A run that then
|
|
50
|
+
* fails, hits a deadline or is interrupted prints it; a returned value replaces it.
|
|
51
|
+
*/
|
|
52
|
+
deliver(data: unknown): void;
|
|
53
|
+
/** The outside systems the CLI declared with `agentCli<Ports>()`. */
|
|
54
|
+
readonly ports: Ports;
|
|
55
|
+
/**
|
|
56
|
+
* Reads, lists, removes and atomically writes files and folders, paths resolved against `cwd`; a
|
|
57
|
+
* failure fails the run with `PERMISSION_DENIED`, `DISK_FULL`, `NOT_FOUND`, `NOT_A_FILE` or
|
|
58
|
+
* `ALREADY_EXISTS`.
|
|
59
|
+
*/
|
|
60
|
+
readonly files: Files;
|
|
61
|
+
/**
|
|
62
|
+
* Runs a child process, killed when the run is interrupted; `check: true` fails the run with
|
|
63
|
+
* `TOOL_FAILED` and the tail of its stderr when it exits non-zero.
|
|
64
|
+
*/
|
|
65
|
+
readonly spawn: ContextSpawn;
|
|
66
|
+
/** Deadlines, `poll` and the grace period after an interrupt run on it. */
|
|
67
|
+
readonly clock: Clock;
|
|
68
|
+
/**
|
|
69
|
+
* Calls `check` until it returns a value other than `undefined`, sleeping `intervalMs` between
|
|
70
|
+
* calls; it stops when `ctx.signal` or the given `signal` aborts.
|
|
71
|
+
*/
|
|
72
|
+
poll<T>(check: () => T | undefined | Promise<T | undefined>, options: PollOptions): Promise<T>;
|
|
73
|
+
/** The Project file found by walking up from `cwd`, parsed by the CLI's schema. */
|
|
74
|
+
readonly project: Project<Settings> | undefined;
|
|
75
|
+
/** Reads `name` from the env, then from `$XDG_CONFIG_HOME/<cli>/.env`, with where it came from. */
|
|
76
|
+
secret(name: string): Secret | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Classifies an errno failure of the CLI's own file access, such as a store it opens itself, as
|
|
79
|
+
* `ctx.files` does; any other error comes back unchanged.
|
|
80
|
+
*/
|
|
81
|
+
fileError(error: unknown, at: FileAccess): unknown;
|
|
82
|
+
/** Whether the caller passed `--force`; always false for a Command without it. */
|
|
83
|
+
readonly force: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* The command line as the caller typed it, starting with the CLI's name and shell-quoted, with
|
|
86
|
+
* each flag in `remove` dropped along with its value and the words in `add` placed before any
|
|
87
|
+
* `--`; for the hint that names the command to run next.
|
|
88
|
+
*/
|
|
89
|
+
commandLine(change?: CommandLineChange): string;
|
|
90
|
+
}
|
|
91
|
+
/** The slice of `Context` the ports factory receives, which exists before the ports do. */
|
|
92
|
+
export type PortsBase = Pick<Context, "env" | "cwd" | "packageRoot" | "secret" | "spawn" | "files" | "clock" | "signal" | "progress" | "version" | "build" | "self" | "fileError">;
|
|
93
|
+
export interface Project<Settings = unknown> {
|
|
94
|
+
/** The folder holding the Project file. */
|
|
95
|
+
readonly root: string;
|
|
96
|
+
readonly settings: Settings;
|
|
97
|
+
}
|
|
98
|
+
/** Names the Project file and the schema its JSON must match. */
|
|
99
|
+
export interface ProjectFile<Settings = unknown> {
|
|
100
|
+
readonly file: string;
|
|
101
|
+
readonly schema: z.ZodType<Settings>;
|
|
102
|
+
}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":""}
|
package/dist/cost.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CliError } from "./errors.js";
|
|
2
2
|
import { YES_FLAG } from "./flags.js";
|
|
3
|
-
import {
|
|
3
|
+
import { commandLineOf } from "./invocation.js";
|
|
4
4
|
export const NOT_CONFIRMED = "NOT_CONFIRMED";
|
|
5
5
|
/** Refuses a run whose Plan states a cost the caller has not approved with `--yes`. */
|
|
6
6
|
export function checkCost({ invocation, commandLine, yes }, cost) {
|
|
@@ -10,7 +10,7 @@ export function checkCost({ invocation, commandLine, yes }, cost) {
|
|
|
10
10
|
throw new CliError({
|
|
11
11
|
code: NOT_CONFIRMED,
|
|
12
12
|
message: `\`${commandLine}\` needs ${YES_FLAG.flag}: ${cost}`,
|
|
13
|
-
hint: `to approve the cost, run \`${
|
|
13
|
+
hint: `to approve the cost, run \`${commandLineOf(invocation, { add: [YES_FLAG.flag] })}\``,
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
//# sourceMappingURL=cost.js.map
|
package/dist/cost.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC;AAQ7C,uFAAuF;AACvF,MAAM,UAAU,SAAS,CACvB,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,EAAY,EAC1C,IAAwB;IAExB,IAAI,IAAI,KAAK,SAAS,IAAI,GAAG,EAAE,CAAC;QAC9B,OAAO;IACT,CAAC;IACD,MAAM,IAAI,QAAQ,CAAC;QACjB,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,KAAK,WAAW,YAAY,QAAQ,CAAC,IAAI,KAAK,IAAI,EAAE;QAC7D,IAAI,EAAE,8BAA8B,aAAa,CAAC,UAAU,EAAE,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI;KAC5F,CAAC,CAAC;AACL,CAAC"}
|
package/dist/define.d.ts
CHANGED
|
@@ -1,82 +1,13 @@
|
|
|
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 { Secret } from "./secrets.js";
|
|
8
|
-
import type { ContextSpawn } from "./spawn.js";
|
|
9
6
|
import type { Style } from "./style.js";
|
|
10
|
-
export type Env = Readonly<Record<string, string | undefined>>;
|
|
11
7
|
export interface Example {
|
|
12
8
|
readonly command: string;
|
|
13
9
|
readonly note: string;
|
|
14
10
|
}
|
|
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
11
|
export type InputSchema = z.ZodObject;
|
|
81
12
|
export type NoPorts = Record<never, never>;
|
|
82
13
|
export type NoInput = z.ZodObject<Record<never, never>>;
|
|
@@ -94,13 +25,25 @@ export interface Tool {
|
|
|
94
25
|
/** Bounds a whole run, so a long run stops before the caller's own timeout and can be continued. */
|
|
95
26
|
export interface RunDeadline<In> {
|
|
96
27
|
readonly ms: number;
|
|
97
|
-
/**
|
|
98
|
-
|
|
28
|
+
/**
|
|
29
|
+
* The command line that continues the work, given as the hint of the run's `DEADLINE_EXCEEDED`;
|
|
30
|
+
* `commandLine` is `ctx.commandLine`.
|
|
31
|
+
*/
|
|
32
|
+
resume(input: In, commandLine: Context["commandLine"]): string;
|
|
99
33
|
}
|
|
100
34
|
interface CommandBase<Args extends InputSchema, Options extends InputSchema> {
|
|
101
35
|
readonly name: string;
|
|
102
36
|
readonly description: string;
|
|
37
|
+
/** A paragraph printed after the options in text help, and carried as `help` in help JSON. */
|
|
38
|
+
readonly help?: string;
|
|
103
39
|
readonly examples: readonly Example[];
|
|
40
|
+
/** Left out of help, help JSON, the root examples and suggestions, but still routed and run. */
|
|
41
|
+
readonly hidden?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Only a person at a terminal runs it: under a Coding agent the run fails with `NEEDS_OPERATOR`
|
|
44
|
+
* before `plan`, `run` or `start`, naming the line the operator types.
|
|
45
|
+
*/
|
|
46
|
+
readonly operator?: true;
|
|
104
47
|
/** Missing ones fail the run with `TOOL_MISSING` before `plan`, `run` or `start`. */
|
|
105
48
|
readonly tools?: readonly Tool[];
|
|
106
49
|
readonly args?: Args;
|
|
@@ -171,16 +114,16 @@ interface CliBase<Ports, Settings> {
|
|
|
171
114
|
readonly name: string;
|
|
172
115
|
readonly version: string;
|
|
173
116
|
/** 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
|
-
};
|
|
117
|
+
readonly build?: BuildStamp;
|
|
179
118
|
/** Every code the CLI throws; a code missing here exits 70, as a bug. */
|
|
180
119
|
readonly errors?: ErrorTable;
|
|
181
120
|
/** Builds the real ports when a run first reads `ctx.ports`; `runCli`'s `ports` replaces them in a test. */
|
|
182
121
|
readonly ports?: (base: PortsBase) => Ports;
|
|
183
122
|
readonly project?: ProjectFile<Settings>;
|
|
123
|
+
/** Where `npx skills add` installs the CLI's skill from; read from package.json `repository` when absent. */
|
|
124
|
+
readonly skill?: {
|
|
125
|
+
readonly source: string;
|
|
126
|
+
};
|
|
184
127
|
}
|
|
185
128
|
/** Where an Agent CLI is published and how it is installed; `doctor` and `update` read it. */
|
|
186
129
|
export interface GlobalInstall {
|
|
@@ -188,12 +131,22 @@ export interface GlobalInstall {
|
|
|
188
131
|
readonly package: string;
|
|
189
132
|
readonly registry: string;
|
|
190
133
|
}
|
|
191
|
-
|
|
192
|
-
|
|
134
|
+
/** What a `doctor` row found. A skipped row was not checked, and never fails `doctor`. */
|
|
135
|
+
export type DoctorFinding = {
|
|
136
|
+
readonly state: "ok";
|
|
137
|
+
readonly message: string;
|
|
138
|
+
readonly fix?: string;
|
|
139
|
+
} | {
|
|
140
|
+
readonly state: "problem";
|
|
193
141
|
readonly message: string;
|
|
194
142
|
/** The command that fixes the problem. */
|
|
195
143
|
readonly fix?: string;
|
|
196
|
-
|
|
144
|
+
/** A code of the Error table or the Runtime's that `doctor` fails with; `DOCTOR_PROBLEMS` when absent. */
|
|
145
|
+
readonly code?: string;
|
|
146
|
+
} | {
|
|
147
|
+
readonly state: "skipped";
|
|
148
|
+
readonly message: string;
|
|
149
|
+
};
|
|
197
150
|
/** A row the CLI adds to `doctor`, for a system it depends on. */
|
|
198
151
|
export interface DoctorCheck<Ports = unknown, Settings = unknown> {
|
|
199
152
|
readonly name: string;
|
|
@@ -215,6 +168,8 @@ export interface CommandTreeCli<Ports = unknown, Settings = unknown> extends Cli
|
|
|
215
168
|
readonly node?: string;
|
|
216
169
|
};
|
|
217
170
|
readonly doctor?: readonly DoctorCheck<Ports, Settings>[];
|
|
171
|
+
/** Tools `doctor` checks besides the Commands' own; no Command requires them. */
|
|
172
|
+
readonly tools?: readonly Tool[];
|
|
218
173
|
}
|
|
219
174
|
/** An Agent CLI that is one Command, run with no Command name, as in `tool <args>`. */
|
|
220
175
|
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;AAwS5F,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/doctor-rows.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Launch } from "./built-ins.js";
|
|
1
2
|
import type { CommandTreeCli, DoctorCheck } from "./define.js";
|
|
2
3
|
/** Every row `doctor` reports, in order: the fixed rows around the CLI's own and its tools'. */
|
|
3
|
-
export declare function doctorChecks(cli: CommandTreeCli,
|
|
4
|
+
export declare function doctorChecks(cli: CommandTreeCli, launch: Launch): DoctorCheck[];
|