@duyquangnvx/agent-cli 0.2.1 → 0.4.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 (130) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/dist/abort.d.ts +2 -0
  3. package/dist/abort.js +11 -0
  4. package/dist/abort.js.map +1 -0
  5. package/dist/agent-cli.d.ts +17 -0
  6. package/dist/agent-cli.js +28 -0
  7. package/dist/agent-cli.js.map +1 -0
  8. package/dist/agent.d.ts +4 -0
  9. package/dist/agent.js +14 -0
  10. package/dist/agent.js.map +1 -0
  11. package/dist/built-ins.d.ts +1 -2
  12. package/dist/built-ins.js +0 -10
  13. package/dist/built-ins.js.map +1 -1
  14. package/dist/clock.d.ts +10 -0
  15. package/dist/clock.js +35 -0
  16. package/dist/clock.js.map +1 -0
  17. package/dist/command-spec.js +12 -1
  18. package/dist/command-spec.js.map +1 -1
  19. package/dist/confirm.d.ts +2 -0
  20. package/dist/confirm.js +4 -2
  21. package/dist/confirm.js.map +1 -1
  22. package/dist/cost.d.ts +9 -0
  23. package/dist/cost.js +16 -0
  24. package/dist/cost.js.map +1 -0
  25. package/dist/define.d.ts +145 -32
  26. package/dist/define.js +9 -2
  27. package/dist/define.js.map +1 -1
  28. package/dist/doctor-rows.d.ts +2 -2
  29. package/dist/doctor-rows.js +45 -5
  30. package/dist/doctor-rows.js.map +1 -1
  31. package/dist/doctor.d.ts +2 -1
  32. package/dist/doctor.js +31 -29
  33. package/dist/doctor.js.map +1 -1
  34. package/dist/errno.d.ts +15 -0
  35. package/dist/errno.js +50 -0
  36. package/dist/errno.js.map +1 -0
  37. package/dist/error-table.d.ts +34 -0
  38. package/dist/error-table.js +10 -0
  39. package/dist/error-table.js.map +1 -0
  40. package/dist/errors.d.ts +17 -12
  41. package/dist/errors.js +59 -38
  42. package/dist/errors.js.map +1 -1
  43. package/dist/execute.d.ts +7 -3
  44. package/dist/execute.js +38 -5
  45. package/dist/execute.js.map +1 -1
  46. package/dist/exit-classes.d.ts +31 -0
  47. package/dist/exit-classes.js +108 -0
  48. package/dist/exit-classes.js.map +1 -0
  49. package/dist/files.d.ts +31 -0
  50. package/dist/files.js +95 -0
  51. package/dist/files.js.map +1 -0
  52. package/dist/flags.d.ts +21 -3
  53. package/dist/flags.js +41 -4
  54. package/dist/flags.js.map +1 -1
  55. package/dist/global-install.d.ts +1 -0
  56. package/dist/global-install.js +2 -2
  57. package/dist/global-install.js.map +1 -1
  58. package/dist/help-json.d.ts +2 -1
  59. package/dist/help-json.js +18 -2
  60. package/dist/help-json.js.map +1 -1
  61. package/dist/help.d.ts +4 -2
  62. package/dist/help.js +62 -6
  63. package/dist/help.js.map +1 -1
  64. package/dist/index.d.ts +11 -4
  65. package/dist/index.js +3 -2
  66. package/dist/index.js.map +1 -1
  67. package/dist/input.d.ts +4 -0
  68. package/dist/input.js +24 -2
  69. package/dist/input.js.map +1 -1
  70. package/dist/interrupts.d.ts +17 -3
  71. package/dist/interrupts.js +43 -25
  72. package/dist/interrupts.js.map +1 -1
  73. package/dist/invocation.d.ts +7 -2
  74. package/dist/invocation.js +11 -3
  75. package/dist/invocation.js.map +1 -1
  76. package/dist/list.d.ts +1 -0
  77. package/dist/list.js +4 -2
  78. package/dist/list.js.map +1 -1
  79. package/dist/npm.d.ts +5 -0
  80. package/dist/npm.js +19 -17
  81. package/dist/npm.js.map +1 -1
  82. package/dist/output.d.ts +18 -4
  83. package/dist/output.js +65 -23
  84. package/dist/output.js.map +1 -1
  85. package/dist/outputs.d.ts +11 -0
  86. package/dist/outputs.js +22 -0
  87. package/dist/outputs.js.map +1 -0
  88. package/dist/package-root.d.ts +6 -0
  89. package/dist/package-root.js +17 -0
  90. package/dist/package-root.js.map +1 -0
  91. package/dist/parse-input.d.ts +2 -0
  92. package/dist/parse-input.js +41 -8
  93. package/dist/parse-input.js.map +1 -1
  94. package/dist/planned.d.ts +6 -0
  95. package/dist/planned.js +5 -0
  96. package/dist/planned.js.map +1 -0
  97. package/dist/project.d.ts +4 -0
  98. package/dist/project.js +48 -0
  99. package/dist/project.js.map +1 -0
  100. package/dist/route.d.ts +2 -0
  101. package/dist/route.js +2 -1
  102. package/dist/route.js.map +1 -1
  103. package/dist/run-cli.d.ts +24 -5
  104. package/dist/run-cli.js +126 -18
  105. package/dist/run-cli.js.map +1 -1
  106. package/dist/run-process.js +6 -3
  107. package/dist/run-process.js.map +1 -1
  108. package/dist/secrets.d.ts +19 -0
  109. package/dist/secrets.js +32 -0
  110. package/dist/secrets.js.map +1 -0
  111. package/dist/spawn.d.ts +29 -0
  112. package/dist/spawn.js +79 -0
  113. package/dist/spawn.js.map +1 -0
  114. package/dist/spill.d.ts +16 -0
  115. package/dist/spill.js +65 -0
  116. package/dist/spill.js.map +1 -0
  117. package/dist/style.js +5 -12
  118. package/dist/style.js.map +1 -1
  119. package/dist/tail.d.ts +2 -0
  120. package/dist/tail.js +5 -0
  121. package/dist/tail.js.map +1 -0
  122. package/dist/tools.d.ts +6 -0
  123. package/dist/tools.js +69 -0
  124. package/dist/tools.js.map +1 -0
  125. package/dist/update.js +7 -7
  126. package/dist/update.js.map +1 -1
  127. package/dist/usage.d.ts +3 -0
  128. package/dist/usage.js +6 -3
  129. package/dist/usage.js.map +1 -1
  130. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errno.js","sourceRoot":"","sources":["../src/errno.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AACrD,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;AACrC,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;AACrC,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAW/C,mGAAmG;AACnG,0BAA0B;AAC1B,SAAS,cAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAgB;IACrE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,4BAA4B,IAAI,iBAAiB,CAAC;IAC5E,MAAM,KAAK,GACT,MAAM,KAAK,MAAM;QACf,CAAC,CAAC,oBAAoB,IAAI,iBAAiB;QAC3C,CAAC,CAAC,YAAY,IAAI,8BAA8B,CAAC;IACrD,OAAO,uDAAuD,UAAU,UAAU,KAAK,EAAE,CAAC;AAC5F,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,OAAqB;IACjE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzB,QAAQ,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,QAAQ,CAAC;QACd,KAAK,OAAO;YACV,OAAO,IAAI,QAAQ,CACjB;gBACE,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,sBAAsB,IAAI,EAAE;gBACrC,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC;aAC9B,EACD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO,IAAI,QAAQ,CACjB;gBACE,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,qCAAqC,IAAI,EAAE;gBACpD,IAAI,EAAE,0DAA0D;aACjE,EACD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO,IAAI,QAAQ,CACjB;gBACE,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,cAAc,IAAI,EAAE;gBAC7B,IAAI,EAAE,cAAc,IAAI,uBAAuB;aAChD,EACD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO,IAAI,QAAQ,CACjB;gBACE,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,mBAAmB,IAAI,EAAE;gBAClC,IAAI,EAAE,gCAAgC,IAAI,EAAE;aAC7C,EACD,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type * as z from "zod";
2
+ import { CliError } from "./errors.js";
3
+ import type { ExitClass } from "./exit-classes.js";
4
+ /** The Exit classes a CLI's own code can have; a bug or an interrupt is the Runtime's to tell. */
5
+ export type DeclaredExitClass = Exclude<ExitClass, "bug" | "interrupted">;
6
+ export interface ErrorDeclaration {
7
+ readonly class: DeclaredExitClass;
8
+ readonly details?: z.ZodType;
9
+ }
10
+ /** A CLI's error codes, each with the class that must act on it and the facts it carries. */
11
+ export type ErrorTable = Readonly<Record<string, ErrorDeclaration>>;
12
+ /** Keeps each code's literal class and `details` schema, so `cliError` can type its throw sites. */
13
+ export declare function defineErrors<const Table extends ErrorTable>(table: Table): Table;
14
+ type DetailsInit<Declaration> = Declaration extends {
15
+ readonly details: infer Schema;
16
+ } ? Schema extends z.ZodType ? {
17
+ readonly details: z.output<Schema>;
18
+ } : never : {
19
+ readonly details?: never;
20
+ };
21
+ type RetryInit<Declaration> = Declaration extends {
22
+ readonly class: "wait";
23
+ } ? {
24
+ readonly retryAt?: string;
25
+ } : {
26
+ readonly retryAt?: never;
27
+ };
28
+ export type CliErrorInit<Declaration extends ErrorDeclaration> = {
29
+ readonly message: string;
30
+ readonly hint: string;
31
+ } & DetailsInit<Declaration> & RetryInit<Declaration>;
32
+ /** A `CliError` for a code of `table`, whose `details` must match the code's schema. */
33
+ export declare function cliError<Table extends ErrorTable, Code extends keyof Table & string>(_table: Table, code: Code, init: CliErrorInit<Table[Code]>, options?: ErrorOptions): CliError;
34
+ export {};
@@ -0,0 +1,10 @@
1
+ import { CliError } from "./errors.js";
2
+ /** Keeps each code's literal class and `details` schema, so `cliError` can type its throw sites. */
3
+ export function defineErrors(table) {
4
+ return table;
5
+ }
6
+ /** A `CliError` for a code of `table`, whose `details` must match the code's schema. */
7
+ export function cliError(_table, code, init, options) {
8
+ return new CliError({ ...init, code }, options);
9
+ }
10
+ //# sourceMappingURL=error-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-table.js","sourceRoot":"","sources":["../src/error-table.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAcvC,oGAAoG;AACpG,MAAM,UAAU,YAAY,CAAiC,KAAY;IACvE,OAAO,KAAK,CAAC;AACf,CAAC;AAmBD,wFAAwF;AACxF,MAAM,UAAU,QAAQ,CACtB,MAAa,EACb,IAAU,EACV,IAA+B,EAC/B,OAAsB;IAEtB,OAAO,IAAI,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -1,34 +1,39 @@
1
1
  import type { Env } from "./define.js";
2
2
  import type { Style } from "./style.js";
3
- export interface CliErrorDetails {
3
+ export interface CliErrorFields {
4
4
  readonly code: string;
5
5
  readonly message: string;
6
6
  readonly hint: string;
7
- readonly retryable: boolean;
7
+ /** Facts the caller acts on without parsing the message, shaped by the code's schema. */
8
+ readonly details?: unknown;
9
+ /** ISO 8601: when a wait-class failure may pass, set only when the source said so. */
10
+ readonly retryAt?: string;
8
11
  }
9
12
  export declare class CliError extends Error {
10
13
  readonly code: string;
11
14
  readonly hint: string;
12
- readonly retryable: boolean;
13
- constructor({ code, message, hint, retryable }: CliErrorDetails, options?: ErrorOptions);
15
+ readonly details: unknown;
16
+ readonly retryAt: string | undefined;
17
+ constructor({ code, message, hint, details, retryAt }: CliErrorFields, options?: ErrorOptions);
14
18
  }
15
- export type UsageErrorDetails = Omit<CliErrorDetails, "retryable">;
16
- /** The caller called the Agent CLI wrong; retrying the same call can't succeed. */
19
+ export type UsageErrorFields = Pick<CliErrorFields, "code" | "message" | "hint">;
20
+ /** The caller called the Agent CLI wrong; the same call can't succeed. */
17
21
  export declare class UsageError extends CliError {
18
- constructor(details: UsageErrorDetails);
22
+ constructor(fields: UsageErrorFields);
19
23
  }
24
+ export declare const INTERNAL_CODE = "INTERNAL";
20
25
  export interface ErrorFormat {
21
26
  readonly cliName: string;
22
27
  readonly json: boolean;
23
28
  readonly env: Env;
24
29
  readonly style: Style;
30
+ /** Whether `error` is a bug: not a `CliError`, or one whose code nobody declared. */
31
+ readonly isBug: (error: unknown) => boolean;
25
32
  }
33
+ export declare function errnoOf(error: unknown): string | undefined;
26
34
  export declare function isMissingFile(error: unknown): boolean;
27
35
  export declare function debugVariable(cliName: string): string;
28
36
  export declare function messageOf(error: unknown): string;
37
+ /** The errors a run failed with: each one an `AggregateError` holds, or the one it threw. */
38
+ export declare function errorsOf(error: unknown): readonly unknown[];
29
39
  export declare function formatRuntimeError(error: unknown, format: ErrorFormat): string;
30
- /** A failure that still prints the Command's data on stdout, as `doctor` does with its rows. */
31
- export declare class FailureWithData extends CliError {
32
- readonly data: unknown;
33
- constructor(details: CliErrorDetails, data: unknown);
34
- }
package/dist/errors.js CHANGED
@@ -1,25 +1,32 @@
1
1
  export class CliError extends Error {
2
2
  code;
3
3
  hint;
4
- retryable;
5
- constructor({ code, message, hint, retryable }, options) {
4
+ details;
5
+ retryAt;
6
+ constructor({ code, message, hint, details, retryAt }, options) {
6
7
  super(message, options);
7
8
  this.name = "CliError";
8
9
  this.code = code;
9
10
  this.hint = hint;
10
- this.retryable = retryable;
11
+ this.details = details;
12
+ this.retryAt = retryAt;
11
13
  }
12
14
  }
13
- /** The caller called the Agent CLI wrong; retrying the same call can't succeed. */
15
+ /** The caller called the Agent CLI wrong; the same call can't succeed. */
14
16
  export class UsageError extends CliError {
15
- constructor(details) {
16
- super({ ...details, retryable: false });
17
+ constructor(fields) {
18
+ super(fields);
17
19
  this.name = "UsageError";
18
20
  }
19
21
  }
20
- const INTERNAL_CODE = "INTERNAL";
22
+ export const INTERNAL_CODE = "INTERNAL";
23
+ export function errnoOf(error) {
24
+ return error instanceof Error && "code" in error && typeof error.code === "string"
25
+ ? error.code
26
+ : undefined;
27
+ }
21
28
  export function isMissingFile(error) {
22
- return error instanceof Error && "code" in error && error.code === "ENOENT";
29
+ return errnoOf(error) === "ENOENT";
23
30
  }
24
31
  export function debugVariable(cliName) {
25
32
  return `${cliName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_DEBUG`;
@@ -30,43 +37,57 @@ export function messageOf(error) {
30
37
  function isDebug({ env, cliName }) {
31
38
  return Boolean(env[debugVariable(cliName)]);
32
39
  }
33
- function detailsOf(error, format) {
40
+ function bugHint(format) {
41
+ return isDebug(format)
42
+ ? "the stack trace shows where it failed"
43
+ : `rerun with ${debugVariable(format.cliName)}=1 to see the stack trace`;
44
+ }
45
+ function fieldsOf(error, format) {
34
46
  if (error instanceof CliError) {
35
- const { code, message, hint, retryable } = error;
36
- return { code, message, hint, retryable };
47
+ const { code, message, hint, details, retryAt } = error;
48
+ return { code, message, hint: format.isBug(error) ? bugHint(format) : hint, details, retryAt };
37
49
  }
38
- return {
39
- code: INTERNAL_CODE,
40
- message: messageOf(error),
41
- hint: isDebug(format)
42
- ? "the stack trace shows where it failed"
43
- : `rerun with ${debugVariable(format.cliName)}=1 to see the stack trace`,
44
- retryable: false,
45
- };
50
+ return { code: INTERNAL_CODE, message: messageOf(error), hint: bugHint(format) };
46
51
  }
47
- function stackOf(error, format) {
48
- return isDebug(format) && !(error instanceof CliError) && error instanceof Error
49
- ? error.stack
50
- : undefined;
52
+ function causesOf(error) {
53
+ return error instanceof Error && error.cause !== undefined
54
+ ? [error.cause, ...causesOf(error.cause)]
55
+ : [];
51
56
  }
52
- export function formatRuntimeError(error, format) {
53
- const details = detailsOf(error, format);
54
- const stack = stackOf(error, format);
55
- if (format.json) {
56
- return `${JSON.stringify({ ...details, stack })}\n`;
57
- }
57
+ function traceOf(error) {
58
+ return error instanceof Error ? (error.stack ?? error.message) : String(error);
59
+ }
60
+ /** Under debug: a bug's stack trace, then every error's cause chain. */
61
+ function debugTrace(error, format) {
62
+ if (!isDebug(format))
63
+ return undefined;
64
+ const lines = [
65
+ ...(format.isBug(error) ? [traceOf(error)] : []),
66
+ ...causesOf(error).map((cause) => `caused by: ${traceOf(cause)}`),
67
+ ];
68
+ return lines.length === 0 ? undefined : lines.join("\n");
69
+ }
70
+ /** The errors a run failed with: each one an `AggregateError` holds, or the one it threw. */
71
+ export function errorsOf(error) {
72
+ return error instanceof AggregateError && error.errors.length > 0 ? error.errors : [error];
73
+ }
74
+ function errorLines(error, format) {
75
+ const fields = fieldsOf(error, format);
76
+ const stack = debugTrace(error, format);
58
77
  const { style } = format;
59
- const label = style.red(error instanceof CliError ? "error:" : "internal error:");
78
+ const label = style.red(format.isBug(error) ? "internal error:" : "error:");
60
79
  const trace = stack === undefined ? "" : `${stack}\n`;
61
- return `${label} ${details.message}\n${trace}${style.cyan("hint:")} ${details.hint}\n`;
80
+ return `${label} ${fields.message}\n${trace}${style.cyan("hint:")} ${fields.hint}\n`;
62
81
  }
63
- /** A failure that still prints the Command's data on stdout, as `doctor` does with its rows. */
64
- export class FailureWithData extends CliError {
65
- data;
66
- constructor(details, data) {
67
- super(details);
68
- this.name = "FailureWithData";
69
- this.data = data;
82
+ export function formatRuntimeError(error, format) {
83
+ const errors = errorsOf(error);
84
+ if (format.json) {
85
+ const printed = errors.map((each) => ({
86
+ ...fieldsOf(each, format),
87
+ stack: debugTrace(each, format),
88
+ }));
89
+ return `${JSON.stringify({ errors: printed })}\n`;
70
90
  }
91
+ return errors.map((each) => errorLines(each, format)).join("");
71
92
  }
72
93
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/dist/execute.d.ts CHANGED
@@ -10,12 +10,16 @@ export interface ExecuteFlags {
10
10
  readonly dryRun: boolean;
11
11
  /** The target the caller named with `--confirm`, if any. */
12
12
  readonly confirm: string | undefined;
13
+ /** Whether the caller approved the cost with `--yes`. */
14
+ readonly yes: boolean;
13
15
  /** The page a List Command's `run` receives with its input. */
14
16
  readonly page: PageInput;
15
17
  /** The caller's command line and the Command's, for the hint of a confirmation error. */
16
18
  readonly invocation: Invocation;
17
19
  readonly commandLine: string;
20
+ /** Prints a serve Command's data the moment `start` returns it. */
21
+ readonly started: (outcome: Outcome) => Promise<void>;
18
22
  }
19
- /** How the Command prints data it fails with, which is the data its `run` or `apply` returns. */
20
- export declare function renderOf(command: Command): (data: unknown, style: Style) => string;
21
- export declare function execute(command: Command, input: Record<string, unknown>, ctx: Context, { dryRun, confirm, page, invocation, commandLine }: ExecuteFlags): Promise<Outcome>;
23
+ /** Delivered data as the Command prints it, which is the data its `run` or `apply` returns. */
24
+ export declare function deliveredOutcome(command: Command, data: unknown): Outcome;
25
+ export declare function execute(command: Command, input: Record<string, unknown>, ctx: Context, { dryRun, confirm, yes, page, invocation, commandLine, started }: ExecuteFlags): Promise<Outcome>;
package/dist/execute.js CHANGED
@@ -1,23 +1,56 @@
1
+ import { untilAborted } from "./abort.js";
1
2
  import { checkConfirmation } from "./confirm.js";
3
+ import { checkCost } from "./cost.js";
4
+ import { checkOutputs } from "./outputs.js";
5
+ import { checkTools } from "./tools.js";
2
6
  function outcomeOf(value, render) {
3
7
  return { value, render: (style) => render(value, style) };
4
8
  }
5
- /** How the Command prints data it fails with, which is the data its `run` or `apply` returns. */
6
- export function renderOf(command) {
9
+ /** Delivered data as the Command prints it, which is the data its `run` or `apply` returns. */
10
+ export function deliveredOutcome(command, data) {
7
11
  // The union of render signatures only accepts the intersection of their data types.
8
- return (data, style) => command.render(data, style);
12
+ return outcomeOf(data, command.render);
9
13
  }
10
- export async function execute(command, input, ctx, { dryRun, confirm, page, invocation, commandLine }) {
14
+ function dryRunOutcome(command, plan) {
15
+ const renderPlan = (style) => command.renderPlan(plan, style);
16
+ if (command.outputs === undefined && command.cost === undefined) {
17
+ return { value: plan, render: renderPlan };
18
+ }
19
+ const outputs = command.outputs?.(plan);
20
+ const cost = command.cost?.(plan);
21
+ return {
22
+ // A costed Command's dry run keeps one JSON shape, with `cost: null` when the run is cheap.
23
+ value: {
24
+ plan,
25
+ ...(outputs === undefined ? {} : { outputs }),
26
+ ...(command.cost === undefined ? {} : { cost: cost ?? null }),
27
+ },
28
+ render: (style) => [
29
+ renderPlan(style),
30
+ ...(outputs === undefined ? [] : ["outputs:", ...outputs.map((path) => ` ${path}`)]),
31
+ ...(cost === undefined ? [] : [`cost: ${cost}`]),
32
+ ].join("\n"),
33
+ };
34
+ }
35
+ export async function execute(command, input, ctx, { dryRun, confirm, yes, page, invocation, commandLine, started }) {
36
+ await checkTools(command.tools ?? [], ctx.env);
11
37
  if (command.rows !== undefined) {
12
38
  return outcomeOf(await command.run({ ...input, ...page }, ctx), (data, style) => command.render(data, style));
13
39
  }
14
40
  if (command.effect === "read") {
15
41
  return outcomeOf(await command.run(input, ctx), (data, style) => command.render(data, style));
16
42
  }
43
+ if (command.effect === "serve") {
44
+ const data = await command.start(input, ctx);
45
+ await started(outcomeOf(data, (value, style) => command.render(value, style)));
46
+ return untilAborted(ctx.signal);
47
+ }
17
48
  const plan = await command.plan(input, ctx);
18
49
  if (dryRun) {
19
- return outcomeOf(plan, (value, style) => command.renderPlan(value, style));
50
+ return dryRunOutcome(command, plan);
20
51
  }
52
+ await checkOutputs({ invocation, commandLine, force: ctx.force, files: ctx.files }, command.outputs?.(plan));
53
+ checkCost({ invocation, commandLine, yes }, command.cost?.(plan));
21
54
  if (command.effect === "destructive") {
22
55
  checkConfirmation({ invocation, commandLine, given: confirm }, command.confirm(plan));
23
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"execute.js","sourceRoot":"","sources":["../src/execute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAsBjD,SAAS,SAAS,CAAQ,KAAY,EAAE,MAA8C;IACpF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,QAAQ,CAAC,OAAgB;IACvC,oFAAoF;IACpF,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAE,OAAO,CAAC,MAAkD,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACnG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,OAAgB,EAChB,KAA8B,EAC9B,GAAY,EACZ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAgB;IAEhE,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAC9E,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAC5B,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAChG,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5C,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;QACrC,iBAAiB,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,SAAS,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;AACjG,CAAC"}
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../src/execute.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { Cli } from "./define.js";
2
+ import type { DeclaredExitClass, ErrorTable } from "./error-table.js";
3
+ /** Who must act on a failure (ADR 0005), which sets the exit code. */
4
+ export type ExitClass = "caller" | "operator" | "source" | "wait" | "bug" | "interrupted";
5
+ export declare const SIGNAL_EXIT_CODES: {
6
+ readonly SIGINT: 130;
7
+ readonly SIGTERM: 143;
8
+ };
9
+ export type StopSignal = keyof typeof SIGNAL_EXIT_CODES;
10
+ export declare const EXIT_CODES: {
11
+ readonly caller: 1;
12
+ readonly operator: 2;
13
+ readonly source: 3;
14
+ readonly wait: 75;
15
+ readonly bug: 70;
16
+ };
17
+ /** The codes of `errors` that the Runtime already declares, which a CLI cannot redeclare. */
18
+ export declare function runtimeCodesIn(errors: ErrorTable): string[];
19
+ export declare function isBug(error: unknown, errors: ErrorTable): boolean;
20
+ /**
21
+ * The classes other than bug and interrupt that a run of `cli` can end in: those of the Runtime's
22
+ * codes it can reach, and those of its own table.
23
+ */
24
+ export declare function reachableExitClasses(cli: Cli): Set<DeclaredExitClass>;
25
+ /** The signal named by an interrupt's abort reason; any other reason counts as Ctrl-C. */
26
+ export declare function stopSignalOf(reason: unknown): StopSignal;
27
+ /**
28
+ * The exit code of a run that failed with `error`, given the CLI's error table; `stop` is the
29
+ * signal that interrupted it, if any.
30
+ */
31
+ export declare function exitCodeOf(error: unknown, errors: ErrorTable, stop: AbortSignal | undefined): number;
@@ -0,0 +1,108 @@
1
+ import { CONFIRMATION_MISMATCH, CONFIRMATION_REQUIRED } from "./confirm.js";
2
+ import { NOT_CONFIRMED } from "./cost.js";
3
+ import { DOCTOR_PROBLEMS } from "./doctor.js";
4
+ import { ALREADY_EXISTS, DISK_FULL, NOT_FOUND, PERMISSION_DENIED } from "./errno.js";
5
+ import { CliError, errorsOf, INTERNAL_CODE, UsageError } from "./errors.js";
6
+ import { NOT_GLOBAL_INSTALL } from "./global-install.js";
7
+ import { DEADLINE_EXCEEDED, INTERRUPTED } from "./interrupts.js";
8
+ import { UNKNOWN_FIELD } from "./list.js";
9
+ import { INSTALL_FAILED, NO_LATEST, NPM_FAILED, REGISTRY_AUTH, REGISTRY_UNREACHABLE, } from "./npm.js";
10
+ import { OUTPUT_EXISTS } from "./outputs.js";
11
+ import { PROJECT_INVALID } from "./project.js";
12
+ import { TOOL_FAILED } from "./spawn.js";
13
+ import { TOOL_MISSING } from "./tools.js";
14
+ import { INVALID_INPUT, UNKNOWN_COMMAND, UNKNOWN_OPTION } from "./usage.js";
15
+ export const SIGNAL_EXIT_CODES = { SIGINT: 130, SIGTERM: 143 };
16
+ export const EXIT_CODES = {
17
+ caller: 1,
18
+ operator: 2,
19
+ source: 3,
20
+ wait: 75,
21
+ bug: 70,
22
+ };
23
+ // Built on call: the modules that throw these codes import this one back (through output.ts), so
24
+ // their constants are not initialised yet while this module loads.
25
+ /** The codes the Runtime and its built-in Commands raise, each with the class that must act on it. */
26
+ function runtimeCodes() {
27
+ return {
28
+ [INVALID_INPUT]: "caller",
29
+ [UNKNOWN_OPTION]: "caller",
30
+ [UNKNOWN_COMMAND]: "caller",
31
+ [UNKNOWN_FIELD]: "caller",
32
+ [CONFIRMATION_REQUIRED]: "caller",
33
+ [CONFIRMATION_MISMATCH]: "caller",
34
+ [NOT_CONFIRMED]: "operator",
35
+ [OUTPUT_EXISTS]: "caller",
36
+ [INTERRUPTED]: "interrupted",
37
+ [DEADLINE_EXCEEDED]: "wait",
38
+ [INTERNAL_CODE]: "bug",
39
+ [PERMISSION_DENIED]: "operator",
40
+ [DISK_FULL]: "operator",
41
+ [NOT_FOUND]: "caller",
42
+ [ALREADY_EXISTS]: "caller",
43
+ [TOOL_FAILED]: "operator",
44
+ [TOOL_MISSING]: "operator",
45
+ [PROJECT_INVALID]: "operator",
46
+ [DOCTOR_PROBLEMS]: "operator",
47
+ [NOT_GLOBAL_INSTALL]: "operator",
48
+ [REGISTRY_UNREACHABLE]: "operator",
49
+ [REGISTRY_AUTH]: "operator",
50
+ [INSTALL_FAILED]: "operator",
51
+ [NPM_FAILED]: "operator",
52
+ [NO_LATEST]: "source",
53
+ };
54
+ }
55
+ /** The codes of `errors` that the Runtime already declares, which a CLI cannot redeclare. */
56
+ export function runtimeCodesIn(errors) {
57
+ return Object.keys(errors).filter((code) => Object.hasOwn(runtimeCodes(), code));
58
+ }
59
+ // A code that neither the Runtime nor the CLI declares was thrown by mistake: a bug.
60
+ function exitClassOfOne(error, errors) {
61
+ if (!(error instanceof CliError))
62
+ return "bug";
63
+ if (error instanceof UsageError)
64
+ return "caller";
65
+ return runtimeCodes()[error.code] ?? errors[error.code]?.class ?? "bug";
66
+ }
67
+ export function isBug(error, errors) {
68
+ return exitClassOfOne(error, errors) === "bug";
69
+ }
70
+ // Of several errors, the class that must act first decides; any bug makes the whole run one.
71
+ const ACT_FIRST = ["caller", "operator", "source", "wait", "interrupted"];
72
+ function exitClassOf(error, errors) {
73
+ const classes = errorsOf(error).map((each) => exitClassOfOne(each, errors));
74
+ if (classes.includes("bug"))
75
+ return "bug";
76
+ return ACT_FIRST.find((exitClass) => classes.includes(exitClass)) ?? "bug";
77
+ }
78
+ /**
79
+ * The classes other than bug and interrupt that a run of `cli` can end in: those of the Runtime's
80
+ * codes it can reach, and those of its own table.
81
+ */
82
+ export function reachableExitClasses(cli) {
83
+ // Any CLI can write files or refuse an unconfirmed cost (the operator's); only `update` fails as
84
+ // the source's, when the registry has no release.
85
+ const runtime = [
86
+ "caller",
87
+ "operator",
88
+ "wait",
89
+ ...(cli.commands !== undefined && cli.install !== undefined ? ["source"] : []),
90
+ ];
91
+ const own = Object.values(cli.errors ?? {}).map((declaration) => declaration.class);
92
+ return new Set([...runtime, ...own]);
93
+ }
94
+ /** The signal named by an interrupt's abort reason; any other reason counts as Ctrl-C. */
95
+ export function stopSignalOf(reason) {
96
+ return reason === "SIGTERM" ? "SIGTERM" : "SIGINT";
97
+ }
98
+ /**
99
+ * The exit code of a run that failed with `error`, given the CLI's error table; `stop` is the
100
+ * signal that interrupted it, if any.
101
+ */
102
+ export function exitCodeOf(error, errors, stop) {
103
+ const exitClass = exitClassOf(error, errors);
104
+ return exitClass === "interrupted"
105
+ ? SIGNAL_EXIT_CODES[stopSignalOf(stop?.reason)]
106
+ : EXIT_CODES[exitClass];
107
+ }
108
+ //# sourceMappingURL=exit-classes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-classes.js","sourceRoot":"","sources":["../src/exit-classes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { Env } from "./define.js";
2
+ export interface MkdirOptions {
3
+ /** Fail with `ALREADY_EXISTS` when the folder itself exists. */
4
+ readonly exclusive?: boolean;
5
+ }
6
+ /** The file system as Commands use it; a test replaces it through `runCli`. */
7
+ export interface Files {
8
+ /** Writes `data` to the absolute `path` whole or not at all, creating missing parent folders. */
9
+ write(path: string, data: string | Uint8Array): Promise<void>;
10
+ /** Whether anything exists at the absolute `path`. */
11
+ exists(path: string): Promise<boolean>;
12
+ read(path: string): Promise<Uint8Array>;
13
+ /** The names in the absolute `folder`. */
14
+ list(folder: string): Promise<string[]>;
15
+ /** Removes a file, or a folder and everything in it; a missing `path` is a success. */
16
+ remove(path: string): Promise<void>;
17
+ /** Creates the folder and its missing parents; an existing folder is a success unless `exclusive`. */
18
+ mkdir(path: string, options?: MkdirOptions): Promise<void>;
19
+ }
20
+ /** Real files for one run: the first write to each folder sweeps the temp files of dead writers. */
21
+ export declare function realFiles(): Files;
22
+ export interface FilesScope {
23
+ readonly cwd: string;
24
+ readonly env: Env;
25
+ readonly callerLine: string;
26
+ }
27
+ /**
28
+ * `files` resolving paths against `cwd`, its failures classified by errno; `list` drops the
29
+ * Runtime's temp files and sorts.
30
+ */
31
+ export declare function classifiedFiles(files: Files, { cwd, env, callerLine }: FilesScope): Files;
package/dist/files.js ADDED
@@ -0,0 +1,95 @@
1
+ import { access, mkdir, readdir, readFile, rename, rm, writeFile } from "node:fs/promises";
2
+ import { basename, dirname, join, resolve } from "node:path";
3
+ import { classifyErrno } from "./errno.js";
4
+ import { errnoOf, isMissingFile } from "./errors.js";
5
+ const TEMP_FILE = /^\..+\.agent-cli-(\d+)\.tmp$/;
6
+ function tempPathOf(path) {
7
+ return join(dirname(path), `.${basename(path)}.agent-cli-${process.pid}.tmp`);
8
+ }
9
+ function isAlive(pid) {
10
+ try {
11
+ process.kill(pid, 0);
12
+ return true;
13
+ }
14
+ catch (error) {
15
+ // EPERM: the process exists but belongs to another user.
16
+ return errnoOf(error) === "EPERM";
17
+ }
18
+ }
19
+ async function sweep(folder) {
20
+ const names = await readdir(folder);
21
+ const dead = names.filter((name) => {
22
+ const pid = TEMP_FILE.exec(name)?.[1];
23
+ return pid !== undefined && !isAlive(Number(pid));
24
+ });
25
+ await Promise.all(dead.map((name) => rm(join(folder, name), { force: true })));
26
+ }
27
+ /** Real files for one run: the first write to each folder sweeps the temp files of dead writers. */
28
+ export function realFiles() {
29
+ const swept = new Set();
30
+ return {
31
+ exists: async (path) => {
32
+ try {
33
+ await access(path);
34
+ return true;
35
+ }
36
+ catch (error) {
37
+ if (isMissingFile(error))
38
+ return false;
39
+ throw error;
40
+ }
41
+ },
42
+ write: async (path, data) => {
43
+ const folder = dirname(path);
44
+ await mkdir(folder, { recursive: true });
45
+ if (!swept.has(folder)) {
46
+ await sweep(folder);
47
+ swept.add(folder);
48
+ }
49
+ const temp = tempPathOf(path);
50
+ try {
51
+ await writeFile(temp, data);
52
+ await rename(temp, path);
53
+ }
54
+ catch (error) {
55
+ await rm(temp, { force: true });
56
+ throw error;
57
+ }
58
+ },
59
+ read: (path) => readFile(path),
60
+ list: (folder) => readdir(folder),
61
+ remove: (path) => rm(path, { recursive: true, force: true }),
62
+ mkdir: async (path, options) => {
63
+ if (options?.exclusive !== true) {
64
+ await mkdir(path, { recursive: true });
65
+ return;
66
+ }
67
+ await mkdir(dirname(path), { recursive: true });
68
+ await mkdir(path);
69
+ },
70
+ };
71
+ }
72
+ /**
73
+ * `files` resolving paths against `cwd`, its failures classified by errno; `list` drops the
74
+ * Runtime's temp files and sorts.
75
+ */
76
+ export function classifiedFiles(files, { cwd, env, callerLine }) {
77
+ async function at(access, path, work) {
78
+ const target = resolve(cwd, path);
79
+ try {
80
+ return await work(target);
81
+ }
82
+ catch (error) {
83
+ throw classifyErrno(error, { path: target, access, callerLine, env });
84
+ }
85
+ }
86
+ return {
87
+ exists: (path) => at("read", path, (target) => files.exists(target)),
88
+ write: (path, data) => at("write", path, (target) => files.write(target, data)),
89
+ read: (path) => at("read", path, (target) => files.read(target)),
90
+ list: (folder) => at("read", folder, async (target) => (await files.list(target)).filter((name) => !TEMP_FILE.test(name)).sort()),
91
+ remove: (path) => at("write", path, (target) => files.remove(target)),
92
+ mkdir: (path, options) => at("write", path, (target) => files.mkdir(target, options)),
93
+ };
94
+ }
95
+ //# sourceMappingURL=files.js.map