@duyquangnvx/agent-cli 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/dist/agent-cli.js +2 -2
  3. package/dist/agent-cli.js.map +1 -1
  4. package/dist/agent.d.ts +5 -3
  5. package/dist/agent.js +31 -10
  6. package/dist/agent.js.map +1 -1
  7. package/dist/built-ins/commands.d.ts +8 -0
  8. package/dist/{built-ins.js → built-ins/commands.js} +4 -4
  9. package/dist/built-ins/commands.js.map +1 -0
  10. package/dist/built-ins/doctor-rows.d.ts +4 -0
  11. package/dist/{doctor-rows.js → built-ins/doctor-rows.js} +18 -26
  12. package/dist/built-ins/doctor-rows.js.map +1 -0
  13. package/dist/built-ins/doctor.d.ts +5 -0
  14. package/dist/{doctor.js → built-ins/doctor.js} +27 -20
  15. package/dist/built-ins/doctor.js.map +1 -0
  16. package/dist/{global-install.js → built-ins/global-install.js} +1 -1
  17. package/dist/built-ins/global-install.js.map +1 -0
  18. package/dist/{npm.d.ts → built-ins/npm.d.ts} +5 -2
  19. package/dist/{npm.js → built-ins/npm.js} +25 -33
  20. package/dist/built-ins/npm.js.map +1 -0
  21. package/dist/built-ins/semver.js.map +1 -0
  22. package/dist/built-ins/skills.d.ts +18 -0
  23. package/dist/built-ins/skills.js +97 -0
  24. package/dist/built-ins/skills.js.map +1 -0
  25. package/dist/{update.d.ts → built-ins/update.d.ts} +3 -2
  26. package/dist/{update.js → built-ins/update.js} +28 -18
  27. package/dist/built-ins/update.js.map +1 -0
  28. package/dist/{upgrade-notes.js → built-ins/upgrade-notes.js} +1 -1
  29. package/dist/built-ins/upgrade-notes.js.map +1 -0
  30. package/dist/clock.d.ts +1 -0
  31. package/dist/clock.js.map +1 -1
  32. package/dist/command-spec.d.ts +17 -2
  33. package/dist/command-spec.js +30 -9
  34. package/dist/command-spec.js.map +1 -1
  35. package/dist/confirm.js +6 -2
  36. package/dist/confirm.js.map +1 -1
  37. package/dist/context.d.ts +139 -0
  38. package/dist/context.js +2 -0
  39. package/dist/context.js.map +1 -0
  40. package/dist/cost.js +2 -2
  41. package/dist/cost.js.map +1 -1
  42. package/dist/define.d.ts +100 -87
  43. package/dist/define.js +3 -1
  44. package/dist/define.js.map +1 -1
  45. package/dist/errno.d.ts +8 -4
  46. package/dist/errno.js +21 -4
  47. package/dist/errno.js.map +1 -1
  48. package/dist/error-table.d.ts +6 -1
  49. package/dist/error-table.js +5 -1
  50. package/dist/error-table.js.map +1 -1
  51. package/dist/errors.d.ts +11 -2
  52. package/dist/errors.js +21 -8
  53. package/dist/errors.js.map +1 -1
  54. package/dist/execute.d.ts +9 -2
  55. package/dist/execute.js +10 -3
  56. package/dist/execute.js.map +1 -1
  57. package/dist/exit-classes.js +38 -38
  58. package/dist/exit-classes.js.map +1 -1
  59. package/dist/files.d.ts +30 -8
  60. package/dist/files.js +104 -17
  61. package/dist/files.js.map +1 -1
  62. package/dist/help-json.d.ts +2 -2
  63. package/dist/help-json.js +6 -2
  64. package/dist/help-json.js.map +1 -1
  65. package/dist/help.d.ts +1 -1
  66. package/dist/help.js +14 -9
  67. package/dist/help.js.map +1 -1
  68. package/dist/index.d.ts +12 -5
  69. package/dist/index.js +6 -2
  70. package/dist/index.js.map +1 -1
  71. package/dist/input.d.ts +7 -1
  72. package/dist/input.js +33 -4
  73. package/dist/input.js.map +1 -1
  74. package/dist/interrupts.d.ts +7 -2
  75. package/dist/interrupts.js +29 -15
  76. package/dist/interrupts.js.map +1 -1
  77. package/dist/invocation.d.ts +10 -5
  78. package/dist/invocation.js +24 -11
  79. package/dist/invocation.js.map +1 -1
  80. package/dist/list.d.ts +12 -3
  81. package/dist/list.js +38 -6
  82. package/dist/list.js.map +1 -1
  83. package/dist/manifest.d.ts +17 -0
  84. package/dist/manifest.js +24 -0
  85. package/dist/manifest.js.map +1 -0
  86. package/dist/operator.d.ts +5 -0
  87. package/dist/operator.js +15 -0
  88. package/dist/operator.js.map +1 -0
  89. package/dist/output.d.ts +6 -4
  90. package/dist/output.js +5 -6
  91. package/dist/output.js.map +1 -1
  92. package/dist/outputs.d.ts +24 -1
  93. package/dist/outputs.js +58 -2
  94. package/dist/outputs.js.map +1 -1
  95. package/dist/parse-input.d.ts +11 -2
  96. package/dist/parse-input.js +78 -27
  97. package/dist/parse-input.js.map +1 -1
  98. package/dist/project.d.ts +3 -2
  99. package/dist/project.js +11 -10
  100. package/dist/project.js.map +1 -1
  101. package/dist/route.d.ts +1 -1
  102. package/dist/route.js +2 -1
  103. package/dist/route.js.map +1 -1
  104. package/dist/run-cli.d.ts +8 -33
  105. package/dist/run-cli.js +50 -157
  106. package/dist/run-cli.js.map +1 -1
  107. package/dist/run-command.d.ts +11 -0
  108. package/dist/run-command.js +234 -0
  109. package/dist/run-command.js.map +1 -0
  110. package/dist/run-options.d.ts +48 -0
  111. package/dist/run-options.js +2 -0
  112. package/dist/run-options.js.map +1 -0
  113. package/dist/run-process.js +7 -4
  114. package/dist/run-process.js.map +1 -1
  115. package/dist/secrets.d.ts +10 -6
  116. package/dist/secrets.js +8 -9
  117. package/dist/secrets.js.map +1 -1
  118. package/dist/side-task.d.ts +27 -0
  119. package/dist/side-task.js +31 -0
  120. package/dist/side-task.js.map +1 -0
  121. package/dist/spawn.d.ts +29 -6
  122. package/dist/spawn.js +126 -29
  123. package/dist/spawn.js.map +1 -1
  124. package/dist/spill.d.ts +4 -3
  125. package/dist/spill.js +1 -7
  126. package/dist/spill.js.map +1 -1
  127. package/dist/stdin.d.ts +33 -0
  128. package/dist/stdin.js +92 -0
  129. package/dist/stdin.js.map +1 -0
  130. package/dist/style.d.ts +1 -1
  131. package/dist/tokenize.d.ts +3 -0
  132. package/dist/tokenize.js +5 -4
  133. package/dist/tokenize.js.map +1 -1
  134. package/dist/tools.d.ts +6 -3
  135. package/dist/tools.js +18 -11
  136. package/dist/tools.js.map +1 -1
  137. package/dist/usage.d.ts +2 -0
  138. package/dist/usage.js +12 -1
  139. package/dist/usage.js.map +1 -1
  140. package/dist/version.d.ts +3 -0
  141. package/dist/version.js +7 -0
  142. package/dist/version.js.map +1 -0
  143. package/package.json +1 -1
  144. package/dist/built-ins.d.ts +0 -3
  145. package/dist/built-ins.js.map +0 -1
  146. package/dist/doctor-rows.d.ts +0 -3
  147. package/dist/doctor-rows.js.map +0 -1
  148. package/dist/doctor.d.ts +0 -4
  149. package/dist/doctor.js.map +0 -1
  150. package/dist/global-install.js.map +0 -1
  151. package/dist/npm.js.map +0 -1
  152. package/dist/semver.js.map +0 -1
  153. package/dist/skills.d.ts +0 -11
  154. package/dist/skills.js +0 -58
  155. package/dist/skills.js.map +0 -1
  156. package/dist/update.js.map +0 -1
  157. package/dist/upgrade-notes.js.map +0 -1
  158. /package/dist/{global-install.d.ts → built-ins/global-install.d.ts} +0 -0
  159. /package/dist/{semver.d.ts → built-ins/semver.d.ts} +0 -0
  160. /package/dist/{semver.js → built-ins/semver.js} +0 -0
  161. /package/dist/{upgrade-notes.d.ts → built-ins/upgrade-notes.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver.js","sourceRoot":"","sources":["../../src/built-ins/semver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { Context } from "../context.js";
2
+ import type { CommandTreeCli } from "../define.js";
3
+ import { type Standing } from "./semver.js";
4
+ export type SkillState = Standing | "unversioned" | "unreadable";
5
+ export interface SkillCopy {
6
+ readonly path: string;
7
+ readonly version: string | undefined;
8
+ readonly state: SkillState;
9
+ }
10
+ type SkillCli = Pick<CommandTreeCli, "name" | "skill">;
11
+ type SkillPlace = Pick<Context, "cwd" | "env" | "packageRoot">;
12
+ export interface SkillReport {
13
+ readonly copies: readonly SkillCopy[];
14
+ /** The command line that brings every copy to the version, when one can. */
15
+ readonly fix: string | undefined;
16
+ }
17
+ export declare function skillReport(cli: SkillCli, version: string, ctx: SkillPlace): Promise<SkillReport>;
18
+ export {};
@@ -0,0 +1,97 @@
1
+ import { readFile, realpath } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { isMissingFile } from "../errors.js";
5
+ import { manifestAt } from "../manifest.js";
6
+ import { isVersion, standingOf } from "./semver.js";
7
+ // Everything here mirrors how the skills@1.7.2 installer (`npx skills`) behaves.
8
+ const SKILL_DIRS = [
9
+ [".claude", "skills"],
10
+ [".agents", "skills"],
11
+ ];
12
+ /** The branch a release moves to the released commit, which holds the skill of that version. */
13
+ const RELEASE_BRANCH = "release";
14
+ // npm's `owner/repo`, `github:owner/repo` and `gitlab:group/repo`, the shorthands the installer also reads.
15
+ const SHORTHAND = /^(?:(?:github:)?[\w.-]+\/[\w.-]+|gitlab:[\w.-]+(?:\/[\w.-]+)+)$/;
16
+ const GIT_URL_PROTOCOLS = new Set(["https:", "http:", "ssh:", "git:"]);
17
+ const SCP_STYLE = /^[\w.-]+@[\w.-]+:[\w./-]+$/;
18
+ const FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---/;
19
+ const METADATA_VERSION = /^metadata:[ \t]*\r?\n(?:[ \t]+.*\r?\n)*?[ \t]+version:[ \t]*["']?([^"'\s]+)["']?[ \t]*$/m;
20
+ /** The version a SKILL.md's frontmatter `metadata.version` states. */
21
+ function skillVersionIn(skill) {
22
+ const frontmatter = FRONTMATTER.exec(skill)?.[1];
23
+ return frontmatter === undefined ? undefined : METADATA_VERSION.exec(`${frontmatter}\n`)?.[1];
24
+ }
25
+ function homeOf(env) {
26
+ return env.HOME ?? env.USERPROFILE ?? homedir();
27
+ }
28
+ async function copyAt(path, version) {
29
+ let skill;
30
+ try {
31
+ skill = await readFile(join(path, "SKILL.md"), "utf8");
32
+ }
33
+ catch (error) {
34
+ if (isMissingFile(error)) {
35
+ return undefined;
36
+ }
37
+ return { path, version: undefined, state: "unreadable" };
38
+ }
39
+ const stated = skillVersionIn(skill);
40
+ if (stated === undefined || !isVersion(stated) || !isVersion(version)) {
41
+ return { path, version: stated, state: "unversioned" };
42
+ }
43
+ return { path, version: stated, state: standingOf(stated, version) };
44
+ }
45
+ async function skillCopies(cliName, version, { cwd, env }) {
46
+ const roots = [cwd, homeOf(env)];
47
+ const paths = roots.flatMap((root) => SKILL_DIRS.map((dir) => join(root, ...dir, cliName)));
48
+ const seen = new Set();
49
+ const copies = [];
50
+ for (const path of paths) {
51
+ const copy = await copyAt(path, version);
52
+ // The project may be home itself, or one skill dir a link to the other.
53
+ const real = copy === undefined ? undefined : await realpath(path);
54
+ if (copy !== undefined && real !== undefined && !seen.has(real)) {
55
+ seen.add(real);
56
+ copies.push(copy);
57
+ }
58
+ }
59
+ return copies;
60
+ }
61
+ // The installer clones a non-GitHub source only when it ends in `.git`, and takes the branch from `#ref`.
62
+ function sourceFromRepository(repository) {
63
+ if (SHORTHAND.test(repository))
64
+ return `${repository}#${RELEASE_BRANCH}`;
65
+ const url = repository.replace(/^git\+/, "");
66
+ const isGitUrl = URL.canParse(url) && GIT_URL_PROTOCOLS.has(new URL(url).protocol);
67
+ if (!isGitUrl && !SCP_STYLE.test(url))
68
+ return undefined;
69
+ return `${url.endsWith(".git") ? url : `${url}.git`}#${RELEASE_BRANCH}`;
70
+ }
71
+ /** What the installer installs the CLI's skill from: the declared source, else the package's repository. */
72
+ function skillSource({ skill }, packageRoot) {
73
+ if (skill !== undefined)
74
+ return skill.source;
75
+ const { repository } = manifestAt(packageRoot);
76
+ return repository === undefined ? undefined : sourceFromRepository(repository);
77
+ }
78
+ // `skills update` skips a copy it did not install, which is how most unversioned copies got there.
79
+ // A copy ahead gets no fix: doctor's registry row already says when the CLI itself is behind.
80
+ function fixFor(cliName, copies, source) {
81
+ const has = (wanted) => copies.some(({ state }) => state === wanted);
82
+ const update = `npx -y skills update ${cliName}`;
83
+ // `--skill` installs only this CLI's skill from a repo that holds several.
84
+ const add = source === undefined ? undefined : `npx -y skills add ${source} --skill ${cliName} -g`;
85
+ if (copies.length === 0) {
86
+ return add;
87
+ }
88
+ if (has("unversioned") && add !== undefined) {
89
+ return has("behind") ? `${update} && ${add}` : add;
90
+ }
91
+ return has("behind") || has("unversioned") ? update : undefined;
92
+ }
93
+ export async function skillReport(cli, version, ctx) {
94
+ const copies = await skillCopies(cli.name, version, ctx);
95
+ return { copies, fix: fixFor(cli.name, copies, skillSource(cli, ctx.packageRoot)) };
96
+ }
97
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/built-ins/skills.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
- import { type Command, type CommandTreeCli, type GlobalInstall } from "./define.js";
1
+ import { type Command, type CommandTreeCli, type GlobalInstall } from "../define.js";
2
+ import type { Launch } from "./commands.js";
2
3
  /** The built-in `update`, for a CLI installed globally with npm. */
3
- export declare function updateCommand(cli: CommandTreeCli, install: GlobalInstall, bin: string | undefined): Command;
4
+ export declare function updateCommand(cli: CommandTreeCli, install: GlobalInstall, { bin, node }: Launch): Command;
@@ -1,11 +1,11 @@
1
1
  import * as z from "zod";
2
- import { defineCommand } from "./define.js";
3
- import { CliError } from "./errors.js";
2
+ import { defineCommand } from "../define.js";
3
+ import { CliError } from "../errors.js";
4
+ import { INTERRUPTED } from "../interrupts.js";
4
5
  import { globalInstallOf } from "./global-install.js";
5
- import { INTERRUPTED } from "./interrupts.js";
6
6
  import { installGlobally, latestVersion, npmContext } from "./npm.js";
7
7
  import { standingOf } from "./semver.js";
8
- import { skillUpdateCommand } from "./skills.js";
8
+ import { skillReport } from "./skills.js";
9
9
  import { upgradeNotes } from "./upgrade-notes.js";
10
10
  const updateSchema = z.object({
11
11
  from: z.string(),
@@ -21,15 +21,19 @@ function nothingToInstall({ from, latest }) {
21
21
  }
22
22
  function renderUpdate(cli, install, update) {
23
23
  const { installed } = update;
24
- if (installed === null) {
25
- return nothingToInstall(update);
26
- }
27
- return [
28
- `installed ${install.package}@${installed.version} with the npm under ${installed.prefix}, replacing ${update.from}`,
29
- ...update.upgrades.map(({ version, notes }) => `\nchanges in ${version}:\n${notes}`),
30
- "",
31
- ...update.next.map((command) => `next: ${command}, so the ${cli.name} skill describes ${installed.version}`),
32
- ].join("\n");
24
+ const head = installed === null
25
+ ? [nothingToInstall(update)]
26
+ : [
27
+ `installed ${install.package}@${installed.version} with the npm under ${installed.prefix}, replacing ${update.from}`,
28
+ ...update.upgrades.map(({ version, notes }) => `\nchanges in ${version}:\n${notes}`),
29
+ ];
30
+ const next = update.next.map((command) => `next: ${command}, so the ${cli.name} skill describes ${update.latest}`);
31
+ return (next.length === 0 ? head : [...head, "", ...next]).join("\n");
32
+ }
33
+ // Compared with the latest release even when nothing was installed: its skill is what the installer gives.
34
+ async function skillNext(cli, latest, ctx) {
35
+ const { fix } = await skillReport(cli, latest, ctx);
36
+ return fix === undefined ? [] : [fix];
33
37
  }
34
38
  // The install ran to its end, so the run reports it rather than asking for a rerun.
35
39
  function interruptedAfterInstall(plan) {
@@ -40,7 +44,7 @@ function interruptedAfterInstall(plan) {
40
44
  });
41
45
  }
42
46
  /** The built-in `update`, for a CLI installed globally with npm. */
43
- export function updateCommand(cli, install, bin) {
47
+ export function updateCommand(cli, install, { bin, node }) {
44
48
  return defineCommand({
45
49
  name: "update",
46
50
  description: "install the latest version of this CLI from its registry",
@@ -51,7 +55,7 @@ export function updateCommand(cli, install, bin) {
51
55
  effect: "write",
52
56
  output: updateSchema,
53
57
  plan: async (_input, ctx) => {
54
- const npm = npmContext(cli, install, ctx);
58
+ const npm = npmContext(cli, install, ctx, node);
55
59
  const copy = await globalInstallOf(bin, npm);
56
60
  return {
57
61
  package: install.package,
@@ -64,17 +68,23 @@ export function updateCommand(cli, install, bin) {
64
68
  apply: async (plan, ctx) => {
65
69
  const { from, latest, prefix } = plan;
66
70
  if (standingOf(from, latest) !== "behind") {
67
- return { from, latest, installed: null, upgrades: [], next: [] };
71
+ return {
72
+ from,
73
+ latest,
74
+ installed: null,
75
+ upgrades: [],
76
+ next: await skillNext(cli, latest, ctx),
77
+ };
68
78
  }
69
79
  ctx.signal.throwIfAborted();
70
80
  ctx.progress(`installing ${plan.package}@${latest} with the npm under ${prefix}…`);
71
- await ctx.runToEnd(`installing ${plan.package}@${latest}`, () => installGlobally(latest, npmContext(cli, install, ctx)));
81
+ await ctx.runToEnd(`installing ${plan.package}@${latest}`, () => installGlobally(latest, npmContext(cli, install, ctx, node)));
72
82
  const update = {
73
83
  from,
74
84
  latest,
75
85
  installed: { version: latest, prefix },
76
86
  upgrades: await upgradeNotes(plan.packageDir, from, latest),
77
- next: [skillUpdateCommand(cli.name)],
87
+ next: await skillNext(cli, latest, ctx),
78
88
  };
79
89
  if (ctx.signal.aborted) {
80
90
  ctx.deliver(update);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/built-ins/update.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { isMissingFile } from "./errors.js";
3
+ import { isMissingFile } from "../errors.js";
4
4
  import { compareVersions, isVersion } from "./semver.js";
5
5
  const RELEASE_HEADING = /^## v?(\S+)/;
6
6
  function releasesIn(changelog) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-notes.js","sourceRoot":"","sources":["../../src/built-ins/upgrade-notes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOzD,MAAM,eAAe,GAAG,aAAa,CAAC;AAEtC,SAAS,UAAU,CAAC,SAAiB;IACnC,MAAM,QAAQ,GAA2C,EAAE,CAAC;IAC5D,IAAI,OAAyD,CAAC;IAC9D,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACjC,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YAClE,IAAI,OAAO,KAAK,SAAS;gBAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAkB,EAClB,IAAY,EACZ,EAAU;IAEV,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,aAAa,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACpC,MAAM,KAAK,CAAC;IACd,CAAC;IACD,OAAO,UAAU,CAAC,SAAS,CAAC;SACzB,MAAM,CACL,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,CACzF;SACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3D,CAAC"}
package/dist/clock.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /** Time as the Runtime sees it; a test replaces it through `runCli` to run every wait instantly. */
2
2
  export interface Clock {
3
+ /** Milliseconds since the Unix epoch, as `Date.now()`. */
3
4
  now(): number;
4
5
  /** Resolves after `ms`, or rejects with the signal's reason once it aborts. */
5
6
  sleep(ms: number, signal?: AbortSignal): Promise<void>;
package/dist/clock.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"clock.js","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;IACrB,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CACpB,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC9B,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;YAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzB,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC;CACL,CAAC;AAEF,gFAAgF;AAChF,MAAM,UAAU,KAAK,CAAC,KAAY,EAAE,EAAU,EAAE,MAAmB,EAAE,IAAgB;IACnF,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAc,EAAE,EAAE;QACpD,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,KAAK,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,KAAY,EACZ,KAAmD,EACnD,UAAkB,EAClB,MAAmB;IAEnB,SAAS,CAAC;QACR,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,MAAM,KAAK,EAAE,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACtC,MAAM,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"clock.js","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;IACrB,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CACpB,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC9B,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;YAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzB,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC;CACL,CAAC;AAEF,gFAAgF;AAChF,MAAM,UAAU,KAAK,CAAC,KAAY,EAAE,EAAU,EAAE,MAAmB,EAAE,IAAgB;IACnF,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAc,EAAE,EAAE;QACpD,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,KAAK,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,KAAY,EACZ,KAAmD,EACnD,UAAkB,EAClB,MAAmB;IAEnB,SAAS,CAAC;QACR,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,MAAM,KAAK,EAAE,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACtC,MAAM,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
@@ -7,8 +7,15 @@ import { type ListSpec } from "./list.js";
7
7
  export interface CommandSpec {
8
8
  readonly kind: "command";
9
9
  readonly commandLine: string;
10
+ /** The keys that lead from the root to the Command; empty for a single-Command CLI. */
11
+ readonly path: readonly string[];
10
12
  readonly command: Command;
13
+ /** Whether the Runtime added it, as `doctor`. */
14
+ readonly builtIn: boolean;
11
15
  readonly description: string;
16
+ readonly help: string | undefined;
17
+ readonly hidden: boolean;
18
+ readonly operator: boolean;
12
19
  readonly effect: Command["effect"];
13
20
  readonly examples: readonly Example[];
14
21
  readonly args: readonly InputField[];
@@ -24,5 +31,13 @@ export interface GroupSpec {
24
31
  readonly commands: Readonly<Record<string, SpecNode>>;
25
32
  }
26
33
  export type SpecNode = CommandSpec | GroupSpec;
27
- export declare function commandSpec(commandLine: string, command: Command): CommandSpec;
28
- export declare function groupSpec(commandLine: string, commands: Commands): GroupSpec;
34
+ /** The group's Commands and groups that help and suggestions may name: hidden Commands left out. */
35
+ export declare function visibleCommands({ commands }: GroupSpec): Readonly<Record<string, SpecNode>>;
36
+ interface SpecPlace {
37
+ readonly path: readonly string[];
38
+ readonly builtIn: boolean;
39
+ }
40
+ export declare function commandSpec(commandLine: string, command: Command, { path, builtIn }?: SpecPlace): CommandSpec;
41
+ /** The root group of a multi-Command CLI: the author's Commands, then the Built-in Commands. */
42
+ export declare function groupSpec(commandLine: string, commands: Commands, builtIns: Commands): GroupSpec;
43
+ export {};
@@ -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 };
@@ -13,13 +17,19 @@ function declaredOf(command) {
13
17
  cost: command.cost !== undefined,
14
18
  };
15
19
  }
16
- export function commandSpec(commandLine, command) {
20
+ const SINGLE_COMMAND = { path: [], builtIn: false };
21
+ export function commandSpec(commandLine, command, { path, builtIn } = SINGLE_COMMAND) {
17
22
  const list = command.rows === undefined ? undefined : listSpec(command.rows);
18
23
  return {
19
24
  kind: "command",
20
25
  commandLine,
26
+ path,
21
27
  command,
28
+ builtIn,
22
29
  description: command.description,
30
+ help: command.help,
31
+ hidden: command.hidden === true,
32
+ operator: command.operator === true,
23
33
  effect: command.effect,
24
34
  examples: command.examples,
25
35
  args: argFields(command.args),
@@ -29,14 +39,25 @@ export function commandSpec(commandLine, command) {
29
39
  output: list?.output ?? command.output,
30
40
  };
31
41
  }
32
- export function groupSpec(commandLine, commands) {
33
- return {
34
- kind: "group",
35
- commandLine,
36
- commands: Object.fromEntries(Object.entries(commands).map(([key, node]) => [key, specOf(`${commandLine} ${key}`, node)])),
37
- };
42
+ function group(commandLine, commands) {
43
+ return { kind: "group", commandLine, commands };
44
+ }
45
+ /** The root group of a multi-Command CLI: the author's Commands, then the Built-in Commands. */
46
+ export function groupSpec(commandLine, commands, builtIns) {
47
+ return group(commandLine, {
48
+ ...specsOf(commandLine, commands, { path: [], builtIn: false }),
49
+ ...specsOf(commandLine, builtIns, { path: [], builtIn: true }),
50
+ });
51
+ }
52
+ function specsOf(commandLine, commands, { path, builtIn }) {
53
+ return Object.fromEntries(Object.entries(commands).map(([key, node]) => [
54
+ key,
55
+ specOf(`${commandLine} ${key}`, node, { path: [...path, key], builtIn }),
56
+ ]));
38
57
  }
39
- function specOf(commandLine, node) {
40
- return isCommand(node) ? commandSpec(commandLine, node) : groupSpec(commandLine, node);
58
+ function specOf(commandLine, node, place) {
59
+ return isCommand(node)
60
+ ? commandSpec(commandLine, node, place)
61
+ : group(commandLine, specsOf(commandLine, node, place));
41
62
  }
42
63
  //# sourceMappingURL=command-spec.js.map
@@ -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;AA0BvC,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,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"}
1
+ {"version":3,"file":"command-spec.js","sourceRoot":"","sources":["../src/command-spec.ts"],"names":[],"mappings":"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"}
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 { commandLineWith } from "./invocation.js";
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 hint = `to confirm, run \`${commandLineWith(invocation, CONFIRM_FLAG.flag, expected)}\``;
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,
@@ -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,eAAe,EAAmB,MAAM,iBAAiB,CAAC;AAEnE,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,IAAI,GAAG,qBAAqB,eAAe,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IAC/F,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"}
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,139 @@
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. Spawn it as
30
+ * `ctx.spawn(self[0], [...self.slice(1), "daemon"])`.
31
+ */
32
+ readonly self: readonly string[];
33
+ /**
34
+ * The folder holding this CLI's `package.json`, found from the running bin, for reading files the
35
+ * package ships; run through `runCli` without `bin`, it is found from `cwd`.
36
+ */
37
+ readonly packageRoot: string;
38
+ /**
39
+ * Writes a line to stderr, for long work; it never reaches stdout. Under `--json` the line is
40
+ * `{"progress":"..."}`.
41
+ */
42
+ progress(message: string): void;
43
+ /**
44
+ * Aborts when the run is interrupted (Ctrl-C, SIGTERM, or `runCli`'s `signal`) or hits the
45
+ * Command's run deadline; pass it to `fetch` and the ports. An interrupt fails the run with
46
+ * `INTERRUPTED`, exit 130 for SIGINT or 143 for SIGTERM; a second Ctrl-C ends the process at once.
47
+ */
48
+ readonly signal: AbortSignal;
49
+ /**
50
+ * Returns a signal that aborts with `ctx.signal`, and with `DEADLINE_EXCEEDED` (exit 75) once
51
+ * `ms` have passed. The run reports that deadline for each error, or leaf of an `AggregateError`,
52
+ * that is not a `CliError` and whose `cause` chain holds its abort; any other error is reported
53
+ * as it is, so a `CliError` keeping the abort as `cause` keeps its own code.
54
+ */
55
+ deadline(ms: number): AbortSignal;
56
+ /**
57
+ * Returns a signal that aborts with `DEADLINE_EXCEEDED` (exit 75) once `ms` have passed, and
58
+ * follows neither `ctx.signal` nor the run deadline: it bounds a call inside `runToEnd` that
59
+ * Ctrl-C must not cut short. Its abort is reported as `ctx.deadline`'s is.
60
+ */
61
+ timeout(ms: number): AbortSignal;
62
+ /**
63
+ * Runs a step that must not stop halfway: the run waits for it even when stopped, and then
64
+ * prints `finishing <name>` on stderr.
65
+ */
66
+ runToEnd<T>(name: string, work: () => Promise<T>): Promise<T>;
67
+ /**
68
+ * Records the data done so far, in the shape `render` takes; the last call wins. A run that then
69
+ * fails, hits a deadline or is interrupted prints it on stdout beside its errors on stderr; a
70
+ * returned value replaces it. Delivered data spills like returned data.
71
+ */
72
+ deliver(data: unknown): void;
73
+ /** The outside systems the CLI declared with `agentCli<Ports>()`. */
74
+ readonly ports: Ports;
75
+ /**
76
+ * Reads, lists, removes and atomically writes files and folders, paths resolved against `cwd`. A
77
+ * failure fails the run naming the path: `PERMISSION_DENIED` (exit 2, with a hint on allowing the
78
+ * path in a Coding agent's sandbox), `DISK_FULL` (exit 2), `NOT_FOUND`, `NOT_A_FILE` or
79
+ * `ALREADY_EXISTS` (exit 1); the codes are exported.
80
+ */
81
+ readonly files: Files;
82
+ /**
83
+ * Runs a child process in `cwd` with `env`, killed when the run is interrupted; on Windows every
84
+ * process it started is killed too. A program not found fails the run with `TOOL_MISSING` (exit 2).
85
+ */
86
+ readonly spawn: ContextSpawn;
87
+ /** Deadlines, `poll` and the grace period after an interrupt run on it. */
88
+ readonly clock: Clock;
89
+ /**
90
+ * Calls `check` until it returns a value other than `undefined`, sleeping `intervalMs` between
91
+ * calls; it ends with the abort reason of `ctx.signal` or of the given `signal`.
92
+ */
93
+ poll<T>(check: () => T | undefined | Promise<T | undefined>, options: PollOptions): Promise<T>;
94
+ /**
95
+ * The Project file found by walking up from `cwd`, parsed by the CLI's schema, or `undefined`
96
+ * when there is none. A file the schema rejects fails the run with `PROJECT_INVALID` (exit 2)
97
+ * before the Command runs; the built-in Commands never read it.
98
+ */
99
+ readonly project: Project<Settings> | undefined;
100
+ /**
101
+ * Reads `name` from the env, then from `$XDG_CONFIG_HOME/<cli>/.env` (default `~/.config`), with
102
+ * where it came from; a `.env` it cannot read fails the run with `PERMISSION_DENIED`.
103
+ */
104
+ secret(name: string): Secret | undefined;
105
+ /**
106
+ * The `.env` that `secret` reads: `$XDG_CONFIG_HOME/<cli>/.env`, or `~/.config/<cli>/.env`
107
+ * without it. Name it in a hint that asks for a missing key.
108
+ */
109
+ readonly envFile: string;
110
+ /**
111
+ * Classifies an errno failure of the CLI's own file access, such as a store it opens itself, as
112
+ * `ctx.files` does; any other error comes back unchanged.
113
+ */
114
+ fileError(error: unknown, at: FileAccess): unknown;
115
+ /** Whether the caller passed `--force`; always false for a Command without it. */
116
+ readonly force: boolean;
117
+ /**
118
+ * The command line as the caller typed it, starting with the CLI's name and shell-quoted, with
119
+ * each flag in `remove` dropped along with its value (`--from 3` and `--from=3`, every time it was
120
+ * given) and the words in `add` placed before any `--`. Build every hint that names a command to
121
+ * run with it.
122
+ */
123
+ commandLine(change?: CommandLineChange): string;
124
+ }
125
+ /**
126
+ * The slice of `Context` the ports factory receives, which exists before the ports do; a test that
127
+ * keeps the real factory gives it the test's env and fakes.
128
+ */
129
+ export type PortsBase = Pick<Context, "env" | "cwd" | "packageRoot" | "secret" | "envFile" | "spawn" | "files" | "clock" | "signal" | "progress" | "version" | "build" | "self" | "fileError">;
130
+ export interface Project<Settings = unknown> {
131
+ /** The folder holding the Project file. */
132
+ readonly root: string;
133
+ readonly settings: Settings;
134
+ }
135
+ /** Names the Project file and the schema its JSON must match. */
136
+ export interface ProjectFile<Settings = unknown> {
137
+ readonly file: string;
138
+ readonly schema: z.ZodType<Settings>;
139
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=context.js.map
@@ -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 { commandLineWith } from "./invocation.js";
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 \`${commandLineWith(invocation, YES_FLAG.flag)}\``,
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,eAAe,EAAmB,MAAM,iBAAiB,CAAC;AAEnE,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,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI;KACnF,CAAC,CAAC;AACL,CAAC"}
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"}