@poe-platform/safe-bash 0.1.442 → 0.1.444

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 (167) hide show
  1. package/dist/safe-bash/browser.js +111 -69
  2. package/dist/safe-bash/browser.js.map +4 -4
  3. package/dist/safe-bash/commands/archive/index.d.ts.map +1 -1
  4. package/dist/safe-bash/commands/archive/index.js +2 -1
  5. package/dist/safe-bash/commands/archive/index.js.map +1 -1
  6. package/dist/safe-bash/commands/archive/internal.d.ts.map +1 -1
  7. package/dist/safe-bash/commands/archive/internal.js +2 -1
  8. package/dist/safe-bash/commands/archive/internal.js.map +1 -1
  9. package/dist/safe-bash/commands/archive/stream.d.ts.map +1 -1
  10. package/dist/safe-bash/commands/archive/stream.js +11 -4
  11. package/dist/safe-bash/commands/archive/stream.js.map +1 -1
  12. package/dist/safe-bash/commands/bytes/checksums/index.d.ts.map +1 -1
  13. package/dist/safe-bash/commands/bytes/checksums/index.js +7 -6
  14. package/dist/safe-bash/commands/bytes/checksums/index.js.map +1 -1
  15. package/dist/safe-bash/commands/bytes/compression/errors.d.ts +2 -0
  16. package/dist/safe-bash/commands/bytes/compression/errors.d.ts.map +1 -0
  17. package/dist/safe-bash/commands/bytes/compression/errors.js +19 -0
  18. package/dist/safe-bash/commands/bytes/compression/errors.js.map +1 -0
  19. package/dist/safe-bash/commands/bytes/compression/files.d.ts.map +1 -1
  20. package/dist/safe-bash/commands/bytes/compression/files.js +5 -2
  21. package/dist/safe-bash/commands/bytes/compression/files.js.map +1 -1
  22. package/dist/safe-bash/commands/bytes/compression/gunzip.d.ts.map +1 -1
  23. package/dist/safe-bash/commands/bytes/compression/gunzip.js +20 -12
  24. package/dist/safe-bash/commands/bytes/compression/gunzip.js.map +1 -1
  25. package/dist/safe-bash/commands/bytes/compression/index.d.ts.map +1 -1
  26. package/dist/safe-bash/commands/bytes/compression/index.js +2 -1
  27. package/dist/safe-bash/commands/bytes/compression/index.js.map +1 -1
  28. package/dist/safe-bash/commands/bytes/compression/stream.d.ts.map +1 -1
  29. package/dist/safe-bash/commands/bytes/compression/stream.js +3 -1
  30. package/dist/safe-bash/commands/bytes/compression/stream.js.map +1 -1
  31. package/dist/safe-bash/commands/bytes/encoding/base.d.ts.map +1 -1
  32. package/dist/safe-bash/commands/bytes/encoding/base.js +3 -2
  33. package/dist/safe-bash/commands/bytes/encoding/base.js.map +1 -1
  34. package/dist/safe-bash/commands/bytes/encoding/shared.d.ts.map +1 -1
  35. package/dist/safe-bash/commands/bytes/encoding/shared.js +3 -2
  36. package/dist/safe-bash/commands/bytes/encoding/shared.js.map +1 -1
  37. package/dist/safe-bash/commands/bytes/encoding/xxd.d.ts.map +1 -1
  38. package/dist/safe-bash/commands/bytes/encoding/xxd.js +8 -7
  39. package/dist/safe-bash/commands/bytes/encoding/xxd.js.map +1 -1
  40. package/dist/safe-bash/commands/column/internal.d.ts.map +1 -1
  41. package/dist/safe-bash/commands/column/internal.js +2 -1
  42. package/dist/safe-bash/commands/column/internal.js.map +1 -1
  43. package/dist/safe-bash/commands/diff-patch/patch-gnu-paths.d.ts.map +1 -1
  44. package/dist/safe-bash/commands/diff-patch/patch-gnu-paths.js +2 -1
  45. package/dist/safe-bash/commands/diff-patch/patch-gnu-paths.js.map +1 -1
  46. package/dist/safe-bash/commands/diff-patch/patch.d.ts.map +1 -1
  47. package/dist/safe-bash/commands/diff-patch/patch.js +3 -2
  48. package/dist/safe-bash/commands/diff-patch/patch.js.map +1 -1
  49. package/dist/safe-bash/commands/diff-patch/shared.d.ts +2 -1
  50. package/dist/safe-bash/commands/diff-patch/shared.d.ts.map +1 -1
  51. package/dist/safe-bash/commands/diff-patch/shared.js +3 -2
  52. package/dist/safe-bash/commands/diff-patch/shared.js.map +1 -1
  53. package/dist/safe-bash/commands/du/budget.d.ts.map +1 -1
  54. package/dist/safe-bash/commands/du/budget.js +3 -1
  55. package/dist/safe-bash/commands/du/budget.js.map +1 -1
  56. package/dist/safe-bash/commands/du/du.d.ts.map +1 -1
  57. package/dist/safe-bash/commands/du/du.js +8 -7
  58. package/dist/safe-bash/commands/du/du.js.map +1 -1
  59. package/dist/safe-bash/commands/du/format.d.ts +2 -1
  60. package/dist/safe-bash/commands/du/format.d.ts.map +1 -1
  61. package/dist/safe-bash/commands/du/format.js +2 -1
  62. package/dist/safe-bash/commands/du/format.js.map +1 -1
  63. package/dist/safe-bash/commands/expr/command.d.ts.map +1 -1
  64. package/dist/safe-bash/commands/expr/command.js +3 -1
  65. package/dist/safe-bash/commands/expr/command.js.map +1 -1
  66. package/dist/safe-bash/commands/find.d.ts.map +1 -1
  67. package/dist/safe-bash/commands/find.js +2 -1
  68. package/dist/safe-bash/commands/find.js.map +1 -1
  69. package/dist/safe-bash/commands/html-to-markdown/index.d.ts.map +1 -1
  70. package/dist/safe-bash/commands/html-to-markdown/index.js +2 -1
  71. package/dist/safe-bash/commands/html-to-markdown/index.js.map +1 -1
  72. package/dist/safe-bash/commands/index.d.ts.map +1 -1
  73. package/dist/safe-bash/commands/index.js +2 -1
  74. package/dist/safe-bash/commands/index.js.map +1 -1
  75. package/dist/safe-bash/commands/internal.d.ts +2 -1
  76. package/dist/safe-bash/commands/internal.d.ts.map +1 -1
  77. package/dist/safe-bash/commands/internal.js +3 -2
  78. package/dist/safe-bash/commands/internal.js.map +1 -1
  79. package/dist/safe-bash/commands/move.d.ts.map +1 -1
  80. package/dist/safe-bash/commands/move.js +2 -1
  81. package/dist/safe-bash/commands/move.js.map +1 -1
  82. package/dist/safe-bash/commands/regex-execution/bounded-provider.d.ts.map +1 -1
  83. package/dist/safe-bash/commands/regex-execution/bounded-provider.js +14 -3
  84. package/dist/safe-bash/commands/regex-execution/bounded-provider.js.map +1 -1
  85. package/dist/safe-bash/commands/regex-execution/matching.d.ts.map +1 -1
  86. package/dist/safe-bash/commands/regex-execution/matching.js +12 -5
  87. package/dist/safe-bash/commands/regex-execution/matching.js.map +1 -1
  88. package/dist/safe-bash/commands/regex-execution/portable.d.ts.map +1 -1
  89. package/dist/safe-bash/commands/regex-execution/portable.js +1 -1
  90. package/dist/safe-bash/commands/regex-execution/portable.js.map +1 -1
  91. package/dist/safe-bash/commands/regex-execution/protocol.d.ts +3 -2
  92. package/dist/safe-bash/commands/regex-execution/protocol.d.ts.map +1 -1
  93. package/dist/safe-bash/commands/regex-execution/protocol.js +4 -3
  94. package/dist/safe-bash/commands/regex-execution/protocol.js.map +1 -1
  95. package/dist/safe-bash/commands/regex-execution/worker.js +6 -3
  96. package/dist/safe-bash/commands/regex-execution/worker.js.map +1 -1
  97. package/dist/safe-bash/commands/safejs/index.d.ts.map +1 -1
  98. package/dist/safe-bash/commands/safejs/index.js +24 -7
  99. package/dist/safe-bash/commands/safejs/index.js.map +1 -1
  100. package/dist/safe-bash/commands/search/options.d.ts +2 -1
  101. package/dist/safe-bash/commands/search/options.d.ts.map +1 -1
  102. package/dist/safe-bash/commands/search/options.js +2 -1
  103. package/dist/safe-bash/commands/search/options.js.map +1 -1
  104. package/dist/safe-bash/commands/search/shared.d.ts.map +1 -1
  105. package/dist/safe-bash/commands/search/shared.js +2 -1
  106. package/dist/safe-bash/commands/search/shared.js.map +1 -1
  107. package/dist/safe-bash/commands/split/names.d.ts.map +1 -1
  108. package/dist/safe-bash/commands/split/names.js +3 -2
  109. package/dist/safe-bash/commands/split/names.js.map +1 -1
  110. package/dist/safe-bash/commands/split/options.d.ts.map +1 -1
  111. package/dist/safe-bash/commands/split/options.js +17 -16
  112. package/dist/safe-bash/commands/split/options.js.map +1 -1
  113. package/dist/safe-bash/commands/split/split.d.ts.map +1 -1
  114. package/dist/safe-bash/commands/split/split.js +2 -1
  115. package/dist/safe-bash/commands/split/split.js.map +1 -1
  116. package/dist/safe-bash/commands/standard.d.ts.map +1 -1
  117. package/dist/safe-bash/commands/standard.js +2 -1
  118. package/dist/safe-bash/commands/standard.js.map +1 -1
  119. package/dist/safe-bash/commands/stream-format/rev.d.ts.map +1 -1
  120. package/dist/safe-bash/commands/stream-format/rev.js +2 -1
  121. package/dist/safe-bash/commands/stream-format/rev.js.map +1 -1
  122. package/dist/safe-bash/commands/table-text/internal.d.ts.map +1 -1
  123. package/dist/safe-bash/commands/table-text/internal.js +3 -2
  124. package/dist/safe-bash/commands/table-text/internal.js.map +1 -1
  125. package/dist/safe-bash/commands/tail-follow.d.ts.map +1 -1
  126. package/dist/safe-bash/commands/tail-follow.js +4 -3
  127. package/dist/safe-bash/commands/tail-follow.js.map +1 -1
  128. package/dist/safe-bash/commands/text-programs/shared.d.ts +2 -1
  129. package/dist/safe-bash/commands/text-programs/shared.d.ts.map +1 -1
  130. package/dist/safe-bash/commands/text-programs/shared.js +3 -2
  131. package/dist/safe-bash/commands/text-programs/shared.js.map +1 -1
  132. package/dist/safe-bash/commands/text.d.ts.map +1 -1
  133. package/dist/safe-bash/commands/text.js +2 -1
  134. package/dist/safe-bash/commands/text.js.map +1 -1
  135. package/dist/safe-bash/commands/tree/io.d.ts.map +1 -1
  136. package/dist/safe-bash/commands/tree/io.js +2 -4
  137. package/dist/safe-bash/commands/tree/io.js.map +1 -1
  138. package/dist/safe-bash/contracts/command.d.ts +5 -0
  139. package/dist/safe-bash/contracts/command.d.ts.map +1 -1
  140. package/dist/safe-bash/contracts/command.js +6 -1
  141. package/dist/safe-bash/contracts/command.js.map +1 -1
  142. package/dist/safe-bash/diagnostics.d.ts +5 -0
  143. package/dist/safe-bash/diagnostics.d.ts.map +1 -0
  144. package/dist/safe-bash/diagnostics.js +22 -0
  145. package/dist/safe-bash/diagnostics.js.map +1 -0
  146. package/dist/safe-bash/plugins/composition.d.ts.map +1 -1
  147. package/dist/safe-bash/plugins/composition.js +2 -1
  148. package/dist/safe-bash/plugins/composition.js.map +1 -1
  149. package/dist/safe-bash/portable.js +238 -150
  150. package/dist/safe-bash/portable.js.map +4 -4
  151. package/dist/safe-bash/shell/arithmetic.d.ts.map +1 -1
  152. package/dist/safe-bash/shell/arithmetic.js +10 -9
  153. package/dist/safe-bash/shell/arithmetic.js.map +1 -1
  154. package/dist/safe-bash/shell/input.d.ts.map +1 -1
  155. package/dist/safe-bash/shell/input.js +2 -1
  156. package/dist/safe-bash/shell/input.js.map +1 -1
  157. package/dist/safe-bash/shell/runtime.d.ts +3 -1
  158. package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
  159. package/dist/safe-bash/shell/runtime.js +52 -38
  160. package/dist/safe-bash/shell/runtime.js.map +1 -1
  161. package/dist/safe-bash/shell/shell.d.ts.map +1 -1
  162. package/dist/safe-bash/shell/shell.js +5 -1
  163. package/dist/safe-bash/shell/shell.js.map +1 -1
  164. package/dist/safe-bash/shell/types.d.ts +3 -1
  165. package/dist/safe-bash/shell/types.d.ts.map +1 -1
  166. package/dist/safe-bash/shell/types.js.map +1 -1
  167. package/package.json +2 -2
@@ -2029,6 +2029,11 @@ function encodeValues(values, output2) {
2029
2029
 
2030
2030
  // packages/safe-bash/src/contracts/command.ts
2031
2031
  var argumentCarriers = /* @__PURE__ */ new WeakSet();
2032
+ var CommandArgumentIdentityError = class extends TypeError {
2033
+ constructor() {
2034
+ super("Command argument identity does not match its carrier");
2035
+ }
2036
+ };
2032
2037
  function argumentAllocation(allocation) {
2033
2038
  const reservations = [];
2034
2039
  const tracked = allocation && {
@@ -2178,7 +2183,7 @@ function getCommandArguments(context2) {
2178
2183
  const carrier = context2.argumentValues;
2179
2184
  if (carrier === void 0) return createCommandArguments(context2.args);
2180
2185
  if (!argumentCarriers.has(carrier)) throw new TypeError("Expected owned command arguments");
2181
- if (carrier.args !== context2.args) throw new TypeError("Command argument identity does not match its carrier");
2186
+ if (carrier.args !== context2.args) throw new CommandArgumentIdentityError();
2182
2187
  return carrier;
2183
2188
  }
2184
2189
  var CommandRegistry = class {
@@ -2690,6 +2695,24 @@ async function writeDiagnostic(sink, value2, signal) {
2690
2695
  // packages/safe-bash/src/commands/internal.ts
2691
2696
  init_platform();
2692
2697
 
2698
+ // packages/safe-bash/src/diagnostics.ts
2699
+ init_platform();
2700
+ var PublicDiagnostic = class extends Error {
2701
+ };
2702
+ function publicDiagnosticMessage(error, onInternalError) {
2703
+ if (error instanceof FsError || error instanceof CommandArgumentIdentityError) return error.message;
2704
+ if (error instanceof PublicDiagnostic && !Object.hasOwn(error, "cause")) return error.message;
2705
+ const original = error instanceof PublicDiagnostic ? error.cause : error;
2706
+ const detail = error instanceof PublicDiagnostic ? error.message : "internal error";
2707
+ try {
2708
+ const pending = onInternalError?.(original);
2709
+ if (pending !== void 0) void Promise.resolve(pending).catch(() => void 0);
2710
+ } catch {
2711
+ return detail;
2712
+ }
2713
+ return detail;
2714
+ }
2715
+
2693
2716
  // packages/safe-bash/src/commands/portable-requirements.ts
2694
2717
  init_platform();
2695
2718
  var inputRequirements = [
@@ -2777,7 +2800,7 @@ var RecordBuffer = class {
2777
2800
  var encoder3 = new TextEncoder();
2778
2801
  var decoder2 = new TextDecoder();
2779
2802
  var bufferLimit = 32 * 1024 * 1024;
2780
- var UsageError = class extends Error {
2803
+ var UsageError = class extends PublicDiagnostic {
2781
2804
  };
2782
2805
  function options(args, short, long = {}, stopAtOperand = false, onOperand) {
2783
2806
  const flags3 = /* @__PURE__ */ new Set();
@@ -2858,7 +2881,7 @@ async function output(context2, text3) {
2858
2881
  }
2859
2882
  async function diagnostic(context2, error) {
2860
2883
  context2.signal.throwIfAborted();
2861
- await writeDiagnostic(context2.stderr, `${context2.command}: ${error instanceof Error ? error.message : String(error)}
2884
+ await writeDiagnostic(context2.stderr, `${context2.command}: ${publicDiagnosticMessage(error, context2.onInternalError)}
2862
2885
  `, context2.signal);
2863
2886
  }
2864
2887
  function define(name2, handler, failureCode = 1) {
@@ -3500,7 +3523,7 @@ async function moveAcrossDevices(context2, source2, target, noClobber, budget) {
3500
3523
  } catch (error) {
3501
3524
  context2.signal.throwIfAborted();
3502
3525
  if (codeOf(error) !== "ENOTSUP" && codeOf(error) !== "EOPNOTSUPP") throw error;
3503
- await diagnostic(context2, new Error(`cannot preserve timestamps for '${entry.target}': operation not supported; retaining copied data`));
3526
+ await diagnostic(context2, new PublicDiagnostic(`cannot preserve timestamps for '${entry.target}': operation not supported; retaining copied data`));
3504
3527
  }
3505
3528
  }
3506
3529
  }
@@ -4532,7 +4555,7 @@ var FollowSession = class {
4532
4555
  if ("reason" in outcome) reject(outcome.reason);
4533
4556
  else resolve(outcome.value);
4534
4557
  };
4535
- const cancel = () => finish({ reason: this.operation.signal.aborted ? this.operation.signal.reason : new Error("Tail follow is closed") });
4558
+ const cancel = () => finish({ reason: this.operation.signal.aborted ? this.operation.signal.reason : new PublicDiagnostic("Tail follow is closed") });
4536
4559
  this.waiting.add(cancel);
4537
4560
  this.operation.signal.addEventListener("abort", cancel, { once: true });
4538
4561
  pending?.then((value2) => finish({ value: value2 }), (reason) => finish({ reason }));
@@ -4736,7 +4759,7 @@ async function followTail(caller, selection, cap, select, scheduler = tailFollow
4736
4759
  entry.offset = 0;
4737
4760
  if (!initial) {
4738
4761
  const message3 = replaced ? "has been replaced; following new file" : entry.error === "ENOENT" ? "has appeared; following new file" : "has become accessible";
4739
- await diagnostic(context2, new Error(`'${entry.name}' ${message3}`));
4762
+ await diagnostic(context2, new PublicDiagnostic(`'${entry.name}' ${message3}`));
4740
4763
  }
4741
4764
  entry.error = void 0;
4742
4765
  return stat;
@@ -4799,7 +4822,7 @@ async function followTail(caller, selection, cap, select, scheduler = tailFollow
4799
4822
  }
4800
4823
  if (!stat) continue;
4801
4824
  if (stat.size < entry.offset) {
4802
- await diagnostic(context2, new Error(`${entry.name}: file truncated`));
4825
+ await diagnostic(context2, new PublicDiagnostic(`${entry.name}: file truncated`));
4803
4826
  entry.offset = 0;
4804
4827
  }
4805
4828
  if (stat.size > entry.offset) round.push({ entry, end: stat.size });
@@ -5738,7 +5761,7 @@ function textCommands() {
5738
5761
  }
5739
5762
  return (async () => {
5740
5763
  if (records4.length && (await compare5(records4.at(-1), bytes3) > 0 || parsed.flags.has("u") && await keyCompare(records4.at(-1), bytes3) === 0)) {
5741
- await diagnostic(context2, new Error(`disorder at record ${records4.length + 1}`));
5764
+ await diagnostic(context2, new PublicDiagnostic(`disorder at record ${records4.length + 1}`));
5742
5765
  return false;
5743
5766
  }
5744
5767
  records4.push(bytes3);
@@ -6722,16 +6745,16 @@ var precedence = {
6722
6745
  function integer2(text3) {
6723
6746
  if (/^0[xX][\da-fA-F]+$/u.test(text3)) return BigInt(text3);
6724
6747
  if (/^0[0-7]+$/u.test(text3)) return BigInt(`0o${text3.slice(1)}`);
6725
- if (/^0\d+$/u.test(text3)) throw new Error("Invalid octal constant");
6748
+ if (/^0\d+$/u.test(text3)) throw new PublicDiagnostic("Invalid octal constant");
6726
6749
  if (/^\d+$/u.test(text3)) return BigInt(text3);
6727
6750
  const match = /^(\d+)#([\da-zA-Z@_]+)$/u.exec(text3);
6728
- if (!match) throw new Error("Invalid arithmetic constant");
6751
+ if (!match) throw new PublicDiagnostic("Invalid arithmetic constant");
6729
6752
  const base = Number(match[1]);
6730
- if (base < 2 || base > 64) throw new Error("Invalid arithmetic base");
6753
+ if (base < 2 || base > 64) throw new PublicDiagnostic("Invalid arithmetic base");
6731
6754
  let value2 = 0n;
6732
6755
  for (const character of match[2]) {
6733
6756
  const digit2 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_".indexOf(base <= 36 ? character.toLowerCase() : character);
6734
- if (digit2 >= base || digit2 < 0) throw new Error("Digit exceeds arithmetic base");
6757
+ if (digit2 >= base || digit2 < 0) throw new PublicDiagnostic("Digit exceeds arithmetic base");
6735
6758
  value2 = BigInt.asIntN(64, value2 * BigInt(base) + BigInt(digit2));
6736
6759
  }
6737
6760
  return value2;
@@ -6883,7 +6906,7 @@ function evaluateArithmetic(program, variables, budget = new ParseBudget()) {
6883
6906
  case ">=":
6884
6907
  return BigInt(left >= right);
6885
6908
  default:
6886
- throw new Error(`Unsupported arithmetic operator ${operator}`);
6909
+ throw new PublicDiagnostic(`Unsupported arithmetic operator ${operator}`);
6887
6910
  }
6888
6911
  };
6889
6912
  try {
@@ -6893,11 +6916,11 @@ function evaluateArithmetic(program, variables, budget = new ParseBudget()) {
6893
6916
  while (pending.length) {
6894
6917
  const frame = pending.pop();
6895
6918
  if (frame.kind === "evaluate") {
6896
- if (++steps > 1e4) throw new Error("Arithmetic operation limit exceeded");
6919
+ if (++steps > 1e4) throw new PublicDiagnostic("Arithmetic operation limit exceeded");
6897
6920
  const node = frame.node;
6898
6921
  if (node.kind === "literal") value2 = node.value;
6899
6922
  else if (node.kind === "name") {
6900
- if (visiting.has(node.name) || visiting.size >= 64) throw new Error("Arithmetic variable recursion");
6923
+ if (visiting.has(node.name) || visiting.size >= 64) throw new PublicDiagnostic("Arithmetic variable recursion");
6901
6924
  visiting.add(node.name);
6902
6925
  pending.push({ kind: "variable", name: node.name }, { kind: "evaluate", node: parseArithmetic(variables[node.name] ?? "0", 0, budget) });
6903
6926
  } else if (node.kind === "conditional") {
@@ -6943,11 +6966,11 @@ function evaluateArithmetic(program, variables, budget = new ParseBudget()) {
6943
6966
  }
6944
6967
  return value2;
6945
6968
  } catch (error) {
6946
- if (error instanceof ArithmeticFailure) throw new Error(`${program.source.trimStart()}: ${error.message} (error token is "${program.source.slice(error.offset)}")`);
6969
+ if (error instanceof ArithmeticFailure) throw new PublicDiagnostic(`${program.source.trimStart()}: ${error.message} (error token is "${program.source.slice(error.offset)}")`);
6947
6970
  if (error instanceof ShellSyntaxError) {
6948
6971
  const offset = error.offset >= program.source.trimEnd().length ? Math.max(0, program.source.trimEnd().length - 1) : error.offset;
6949
6972
  const reason = error.reason === "Invalid arithmetic operand" ? "arithmetic syntax error: operand expected" : "arithmetic syntax error in expression";
6950
- throw new Error(`${program.source.trimStart()}: ${reason} (error token is "${program.source.slice(offset)}")`);
6973
+ throw new PublicDiagnostic(`${program.source.trimStart()}: ${reason} (error token is "${program.source.slice(offset)}")`);
6951
6974
  }
6952
6975
  throw error;
6953
6976
  }
@@ -11947,8 +11970,9 @@ function resolveLimits(...limits) {
11947
11970
  }
11948
11971
  var budgetedSinks = /* @__PURE__ */ new WeakMap();
11949
11972
  var Budget = class {
11950
- constructor(limits, signal) {
11973
+ constructor(limits, signal, onInternalError) {
11951
11974
  this.limits = limits;
11975
+ this.onInternalError = onInternalError;
11952
11976
  this.signal = signal ? AbortSignal.any([signal, this.controller.signal]) : this.controller.signal;
11953
11977
  this.parsing = new ParseBudget(limits.maxParseUnits, this.signal, (error) => this.controller.abort(error));
11954
11978
  this.values = new ValueArena(limits.maxExpansionBytes, limits.maxExpansionFields, () => this.signal.throwIfAborted(), (limit) => this.fail(limit));
@@ -11956,6 +11980,7 @@ var Budget = class {
11956
11980
  this.#armWallClock();
11957
11981
  }
11958
11982
  limits;
11983
+ onInternalError;
11959
11984
  executionScope = Object.freeze({});
11960
11985
  pathLookup = new PathLookup();
11961
11986
  parsing;
@@ -12384,13 +12409,16 @@ function saturatedSum(left, right) {
12384
12409
  function errorCode(error) {
12385
12410
  return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
12386
12411
  }
12387
- function message(error) {
12388
- return error instanceof Error ? error.message : String(error);
12412
+ function message(error, onInternalError) {
12413
+ if (error instanceof ExpansionFailure || error instanceof CommandFailure || error instanceof ArrayFailure || error instanceof BraceExpansionFailure) return error.message;
12414
+ return publicDiagnosticMessage(error, onInternalError);
12389
12415
  }
12390
- function filesystemDiagnostic(error, target) {
12416
+ function filesystemDiagnostic(error, target, onInternalError) {
12391
12417
  const descriptions2 = { ENOENT: "No such file or directory", EACCES: "Permission denied", EPERM: "Operation not permitted", ENOTDIR: "Not a directory", EISDIR: "Is a directory", ELOOP: "Too many levels of symbolic links", ENOSPC: "No space left on device", EROFS: "Read-only file system" };
12392
12418
  const description = descriptions2[errorCode(error) ?? ""];
12393
- return description ? `${target}: ${description}` : void 0;
12419
+ if (!description) return void 0;
12420
+ publicDiagnosticMessage(error, onInternalError);
12421
+ return `${target}: ${description}`;
12394
12422
  }
12395
12423
  function cdUtf8Width(codePoint) {
12396
12424
  return codePoint <= 127 ? 1 : codePoint <= 2047 ? 2 : codePoint <= 65535 ? 3 : 4;
@@ -12428,7 +12456,7 @@ var CdLookup = class {
12428
12456
  probes = 0;
12429
12457
  async charge(amount) {
12430
12458
  this.signal.throwIfAborted();
12431
- if (amount > 8388608 - this.spent) throw new Error("cd: helper work limit exceeded");
12459
+ if (amount > 8388608 - this.spent) throw new PublicDiagnostic("cd: helper work limit exceeded");
12432
12460
  while (amount > 0) {
12433
12461
  const step = Math.min(amount, 128 - this.spent % 128);
12434
12462
  this.spent += step;
@@ -12449,8 +12477,8 @@ var CdLookup = class {
12449
12477
  for (let index = 0; index < value2.length; ) {
12450
12478
  const codePoint = value2.codePointAt(index);
12451
12479
  const width = cdUtf8Width(codePoint);
12452
- if (bytes3 + width > 65536) throw new Error(search ? "cd: CDPATH exceeds 65536 UTF-8 bytes" : "cd: path exceeds 65536 UTF-8 bytes");
12453
- if (search && codePoint === 58 && ++slots > 4096) throw new Error("cd: CDPATH exceeds 4096 components");
12480
+ if (bytes3 + width > 65536) throw new PublicDiagnostic(search ? "cd: CDPATH exceeds 65536 UTF-8 bytes" : "cd: path exceeds 65536 UTF-8 bytes");
12481
+ if (search && codePoint === 58 && ++slots > 4096) throw new PublicDiagnostic("cd: CDPATH exceeds 4096 components");
12454
12482
  await this.charge(width);
12455
12483
  if (search && codePoint === 58) {
12456
12484
  components.push({ start, end: index, bytes: bytes3 - startBytes });
@@ -12471,13 +12499,13 @@ var CdLookup = class {
12471
12499
  const search = eligible && cdpath ? await this.scan(cdpath, true) : void 0;
12472
12500
  const probe = async (component, componentBytes) => {
12473
12501
  const rawBytes = absolute ? targetBytes : component.startsWith("/") ? componentBytes + 1 + targetBytes : cwdBytes + 1 + (component ? componentBytes + 1 : 0) + targetBytes;
12474
- if (rawBytes > 65536) throw new Error("cd: path exceeds 65536 UTF-8 bytes");
12502
+ if (rawBytes > 65536) throw new PublicDiagnostic("cd: path exceeds 65536 UTF-8 bytes");
12475
12503
  await this.charge(2 * rawBytes);
12476
12504
  const raw = absolute ? target : component.startsWith("/") ? `${component}/${target}` : component ? `${cwd}/${component}/${target}` : `${cwd}/${target}`;
12477
12505
  const path = resolvePath(cwd, raw);
12478
12506
  await this.scan(path);
12479
12507
  this.signal.throwIfAborted();
12480
- if (++this.probes > 4097) throw new Error("cd: probe limit exceeded");
12508
+ if (++this.probes > 4097) throw new PublicDiagnostic("cd: probe limit exceeded");
12481
12509
  await this.charge(1);
12482
12510
  this.signal.throwIfAborted();
12483
12511
  const stat = await fs.stat(path, { signal: this.signal });
@@ -12629,7 +12657,7 @@ var DirectoryStackWork = class {
12629
12657
  }
12630
12658
  };
12631
12659
  var closedSink = { async write() {
12632
- throw Object.assign(new Error("Bad file descriptor"), { code: "EBADF" });
12660
+ throw Object.assign(new PublicDiagnostic("Bad file descriptor"), { code: "EBADF" });
12633
12661
  } };
12634
12662
  var closedSource = { [Symbol.asyncIterator]() {
12635
12663
  let closed = false;
@@ -12646,7 +12674,7 @@ var closedSource = { [Symbol.asyncIterator]() {
12646
12674
  return enqueue(() => {
12647
12675
  if (closed) return { done: true, value: void 0 };
12648
12676
  closed = true;
12649
- throw Object.assign(new Error("Bad file descriptor"), { code: "EBADF" });
12677
+ throw Object.assign(new PublicDiagnostic("Bad file descriptor"), { code: "EBADF" });
12650
12678
  });
12651
12679
  },
12652
12680
  return(value2) {
@@ -13113,14 +13141,14 @@ var Runtime = class _Runtime {
13113
13141
  }
13114
13142
  writeVariable(state, name2, value2, origin = "assignment") {
13115
13143
  if (arrayStore(state)?.get(name2)) throw new ArrayFailure(origin === "arithmetic" ? "indexed arithmetic is unsupported" : "indexed write requires prepared publication");
13116
- if (state.readonlyVariables?.has(name2)) throw new Error(`${name2}: readonly variable`);
13144
+ if (state.readonlyVariables?.has(name2)) throw new PublicDiagnostic(`${name2}: readonly variable`);
13117
13145
  if (shellValueByteLength(value2) > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
13118
13146
  if (name2 === "OPTIND" && state.getopts?.integer && origin !== "arithmetic") {
13119
13147
  try {
13120
13148
  value2 = String(evaluateArithmetic(prepareArithmetic(shellValueText(value2) || "0", this.budget.parsing), this.arithmeticVariables(state), this.budget.parsing));
13121
13149
  } catch (error) {
13122
13150
  this.rethrowArithmeticControl(error);
13123
- throw new ExpansionFailure(message(error));
13151
+ throw new ExpansionFailure(message(error, this.budget.onInternalError));
13124
13152
  }
13125
13153
  }
13126
13154
  publishVariable(state, name2, value2);
@@ -13138,7 +13166,7 @@ var Runtime = class _Runtime {
13138
13166
  if (state.variables.OPTIND !== previous) this.syncGetopts(state);
13139
13167
  }
13140
13168
  unsetVariable(state, name2, internal = false) {
13141
- if (state.readonlyVariables?.has(name2)) throw new Error(`${name2}: readonly variable`);
13169
+ if (state.readonlyVariables?.has(name2)) throw new PublicDiagnostic(`${name2}: readonly variable`);
13142
13170
  delete state.variables[name2];
13143
13171
  state.exported.delete(name2);
13144
13172
  if (name2 === "OPTIND" && !internal) this.syncGetopts(state);
@@ -13856,7 +13884,7 @@ var Runtime = class _Runtime {
13856
13884
  }, (prepared) => evaluateArithmetic(prepared, this.arithmeticVariables(state, io.diagnosticLine), this.budget.parsing)) === 0n);
13857
13885
  } catch (error) {
13858
13886
  this.rethrowArithmeticControl(error);
13859
- throw new Error(`((: ${message(error)}`);
13887
+ throw new PublicDiagnostic(`((: ${message(error, this.budget.onInternalError)}`);
13860
13888
  }
13861
13889
  }
13862
13890
  if (command7.kind === "subshell") {
@@ -13951,9 +13979,10 @@ var Runtime = class _Runtime {
13951
13979
  if (command7.kind !== "simple" && command7.kind !== "subshell" && command7.kind !== "arithmetic" && command7.kind !== "conditional") this.errexit(141, state, io);
13952
13980
  return 141;
13953
13981
  }
13982
+ const publicMessage = message(error, this.budget.onInternalError);
13954
13983
  const line = error instanceof ExpansionFailure ? error.line ?? io.diagnosticLine ?? 1 : io.diagnosticLine ?? 1;
13955
13984
  if (error instanceof NounsetFailure || error instanceof ParameterExpansionFailure) {
13956
- const detail = error instanceof ParameterExpansionFailure ? diagnostic4 ?? message(error) : message(error);
13985
+ const detail = error instanceof ParameterExpansionFailure ? diagnostic4 ?? publicMessage : publicMessage;
13957
13986
  try {
13958
13987
  await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${detail}
13959
13988
  `);
@@ -13965,14 +13994,15 @@ var Runtime = class _Runtime {
13965
13994
  }
13966
13995
  throw completedExit(error instanceof ParameterExpansionFailure && !state.isolated ? 127 : 1);
13967
13996
  }
13968
- if (error instanceof ArrayFailure) await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${diagnostic4 ?? message(error)}
13997
+ if (error instanceof ArrayFailure) await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${diagnostic4 ?? publicMessage}
13969
13998
  `);
13970
13999
  else {
13971
14000
  try {
13972
- await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${diagnostic4 ?? message(error)}
14001
+ await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${diagnostic4 ?? publicMessage}
13973
14002
  `);
13974
- } catch {
14003
+ } catch (failure) {
13975
14004
  this.signal.throwIfAborted();
14005
+ publicDiagnosticMessage(failure, this.budget.onInternalError);
13976
14006
  }
13977
14007
  }
13978
14008
  if (error instanceof ExpansionFailure || error instanceof BraceExpansionFailure) throw completedExit(error instanceof ParameterExpansionFailure && !state.isolated ? 127 : 1);
@@ -14080,7 +14110,7 @@ var Runtime = class _Runtime {
14080
14110
  if (error instanceof NounsetFailure) throw error;
14081
14111
  if (error instanceof ParameterExpansionFailure && !isolatedInlineInput) throw error;
14082
14112
  if (error instanceof ParameterExpansionFailure) throw new CommandFailure(error.message, state.isolated ? 1 : 127);
14083
- if (error instanceof ExpansionFailure) throw new Error(error.message);
14113
+ if (error instanceof ExpansionFailure) throw new PublicDiagnostic(error.message);
14084
14114
  throw error;
14085
14115
  }
14086
14116
  if (hereString) {
@@ -14093,18 +14123,18 @@ var Runtime = class _Runtime {
14093
14123
  continue;
14094
14124
  }
14095
14125
  const targets = await this.word(redirect.target, state, currentIO());
14096
- if (targets.length !== 1) throw new Error("Ambiguous redirect");
14126
+ if (targets.length !== 1) throw new PublicDiagnostic("Ambiguous redirect");
14097
14127
  const target = targets[0];
14098
14128
  errorTarget = target;
14099
14129
  if (redirect.operator.endsWith("&")) {
14100
14130
  if (target === "-") descriptors.delete(redirect.descriptor);
14101
14131
  else {
14102
- if (!/^\d+-?$/u.test(target)) throw new Error(`${target}: Bad file descriptor`);
14132
+ if (!/^\d+-?$/u.test(target)) throw new PublicDiagnostic(`${target}: Bad file descriptor`);
14103
14133
  const move = target.endsWith("-");
14104
- if (move && !redirect.move) throw new Error(`${target}: ambiguous redirect`);
14134
+ if (move && !redirect.move) throw new PublicDiagnostic(`${target}: ambiguous redirect`);
14105
14135
  const sourceDescriptor = Number(move ? target.slice(0, -1) : target);
14106
14136
  const descriptor2 = descriptors.get(sourceDescriptor);
14107
- if (!descriptor2 || descriptor2.closed || !move && (redirect.operator === "<&" ? !descriptor2.input : !descriptor2.output)) throw new Error(`${move ? sourceDescriptor : target}: Bad file descriptor`);
14137
+ if (!descriptor2 || descriptor2.closed || !move && (redirect.operator === "<&" ? !descriptor2.input : !descriptor2.output)) throw new PublicDiagnostic(`${move ? sourceDescriptor : target}: Bad file descriptor`);
14108
14138
  descriptors.set(redirect.descriptor, { ...descriptor2 });
14109
14139
  if (move && sourceDescriptor !== redirect.descriptor) {
14110
14140
  descriptors.delete(sourceDescriptor);
@@ -14117,7 +14147,7 @@ var Runtime = class _Runtime {
14117
14147
  if (redirect.operator === "<") {
14118
14148
  await interruptible(this.fs.access(path, 4, options3), this.signal);
14119
14149
  const stat = await interruptible(this.fs.stat(path, options3), this.signal);
14120
- if (stat.type === "directory" && !fileShortcut) throw new Error(`${target}: Is a directory`);
14150
+ if (stat.type === "directory" && !fileShortcut) throw new PublicDiagnostic(`${target}: Is a directory`);
14121
14151
  const source2 = stat.type === "directory" ? toByteSource("") : await fileInput(this.fs, path, this.budget.limits.maxInputBytes, this.signal);
14122
14152
  const input3 = new ShellInput(source2, this.budget, this.signal);
14123
14153
  inputs2.add(input3);
@@ -14379,7 +14409,7 @@ var Runtime = class _Runtime {
14379
14409
  if (!inlineInput) await assign();
14380
14410
  if (fileShortcut) {
14381
14411
  const input3 = io.descriptors?.get(command7.redirects[0].descriptor)?.input;
14382
- if (!input3) throw new Error("Bad file descriptor");
14412
+ if (!input3) throw new PublicDiagnostic("Bad file descriptor");
14383
14413
  await pipeBytes(input3, io.stdout, this.signal);
14384
14414
  return 0;
14385
14415
  }
@@ -14389,7 +14419,7 @@ var Runtime = class _Runtime {
14389
14419
  this.signal.throwIfAborted();
14390
14420
  const original = error instanceof ExecutionFailure ? error.original : error;
14391
14421
  if (special2 && !(original instanceof ShellLimitError) && !(original instanceof ExpansionFailure) && !(original instanceof Flow) && !(original instanceof ShellSyntaxError)) {
14392
- throw new ExecutionFailure(new FatalCommandFailure(message(original), 1), error instanceof ExecutionFailure ? error.io : io, error instanceof ExecutionFailure ? error.diagnostic : void 0);
14422
+ throw new ExecutionFailure(new FatalCommandFailure(message(original, this.budget.onInternalError), 1), error instanceof ExecutionFailure ? error.io : io, error instanceof ExecutionFailure ? error.diagnostic : void 0);
14393
14423
  }
14394
14424
  if (error instanceof ExecutionFailure) throw error;
14395
14425
  throw new ExecutionFailure(error, io);
@@ -14450,6 +14480,7 @@ var Runtime = class _Runtime {
14450
14480
  fs: this.fs,
14451
14481
  signal: this.commandSignal,
14452
14482
  executionScope: this.budget.executionScope,
14483
+ onInternalError: this.budget.onInternalError,
14453
14484
  registerCleanup: (cleanup) => {
14454
14485
  scope.register(cleanup);
14455
14486
  },
@@ -14831,8 +14862,8 @@ ${functionDisplay(name2, state.functions.get(name2))}`;
14831
14862
  }
14832
14863
  const code = errorCode(error);
14833
14864
  if (code === "ENOENT" || code === "ENOTDIR") continue;
14834
- if (code !== "EACCES" && code !== "EPERM") throw new CommandFailure(filesystemDiagnostic(error, target) ?? `${target}: ${message(error)}`, 126);
14835
- denied ??= new CommandFailure(filesystemDiagnostic(error, target) ?? `${target}: ${message(error)}`, 126);
14865
+ if (code !== "EACCES" && code !== "EPERM") throw new CommandFailure(filesystemDiagnostic(error, target, this.budget.onInternalError) ?? `${target}: ${message(error, this.budget.onInternalError)}`, 126);
14866
+ denied ??= new CommandFailure(filesystemDiagnostic(error, target, this.budget.onInternalError) ?? `${target}: ${message(error, this.budget.onInternalError)}`, 126);
14836
14867
  }
14837
14868
  }
14838
14869
  if (denied && !matches3.length && !discovery) throw denied;
@@ -15054,6 +15085,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
15054
15085
  args: argumentValues.args,
15055
15086
  argumentValues,
15056
15087
  executionScope: this.budget.executionScope,
15088
+ onInternalError: this.budget.onInternalError,
15057
15089
  env: Object.assign(/* @__PURE__ */ Object.create(null), incoming.env),
15058
15090
  stdin: input3 ?? incoming.stdin,
15059
15091
  stdout: this.budget.sink(incoming.stdout, runtime.signal),
@@ -15241,7 +15273,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
15241
15273
  this.signal.throwIfAborted();
15242
15274
  if (error instanceof ShellLimitError || error instanceof CommandFailure) throw error;
15243
15275
  if (errorCode(error) === "EFBIG") this.budget.fail("maxSourceBytes");
15244
- throw new CommandFailure(filesystemDiagnostic(error, target) ?? `${target}: ${message(error)}`, errorCode(error) === "ENOENT" ? 127 : 126);
15276
+ throw new CommandFailure(filesystemDiagnostic(error, target, this.budget.onInternalError) ?? `${target}: ${message(error, this.budget.onInternalError)}`, errorCode(error) === "ENOENT" ? 127 : 126);
15245
15277
  }
15246
15278
  if (direct && environmentInterpreter) return this.envShebang(context2, state, io, environmentInterpreter[1], target, args, { path, source: source2 });
15247
15279
  const units = [];
@@ -15386,7 +15418,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
15386
15418
  this.signal.throwIfAborted();
15387
15419
  if (error instanceof ShellLimitError) throw error;
15388
15420
  if (errorCode(error) === "EFBIG") this.budget.fail("maxSourceBytes");
15389
- const diagnostic4 = error instanceof CommandFailure ? error.message : filesystemDiagnostic(error, target) ?? `${target}: ${message(error)}`;
15421
+ const diagnostic4 = error instanceof CommandFailure ? error.message : filesystemDiagnostic(error, target, this.budget.onInternalError) ?? `${target}: ${message(error, this.budget.onInternalError)}`;
15390
15422
  if (special2) throw new FatalCommandFailure(diagnostic4, 1);
15391
15423
  throw new CommandFailure(diagnostic4, error instanceof CommandFailure ? error.status : 1);
15392
15424
  }
@@ -15599,7 +15631,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
15599
15631
  value2 = evaluateArithmetic(prepareArithmetic(args[index], this.budget.parsing), variables, this.budget.parsing);
15600
15632
  } catch (error) {
15601
15633
  this.rethrowArithmeticControl(error);
15602
- throw new Error(`let: ${message(error)}`);
15634
+ throw new PublicDiagnostic(`let: ${message(error, this.budget.onInternalError)}`);
15603
15635
  }
15604
15636
  if ((index - offset + 1) % 128 === 0) await checkpoint();
15605
15637
  }
@@ -15694,7 +15726,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
15694
15726
  this.writeVariable(state, "OPTIND", String(result2.optind), "getopts");
15695
15727
  if (result2.argument.kind === "set") this.writeVariable(state, "OPTARG", result2.argument.value, "getopts");
15696
15728
  else this.unsetVariable(state, "OPTARG", true);
15697
- if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(name2)) throw new Error(`getopts: \`${name2}': not a valid identifier`);
15729
+ if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(name2)) throw new PublicDiagnostic(`getopts: \`${name2}': not a valid identifier`);
15698
15730
  await this.assignVariable(state, name2, result2.option, "getopts");
15699
15731
  return result2.status;
15700
15732
  }
@@ -15717,8 +15749,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
15717
15749
  selected = await new CdLookup(this.signal).find(this.fs, state.cwd, target || ".", state.variables.CDPATH);
15718
15750
  } catch (error) {
15719
15751
  this.signal.throwIfAborted();
15720
- const description = filesystemDiagnostic(error, "");
15721
- const text3 = description ? "" : message(error);
15752
+ const description = filesystemDiagnostic(error, "", this.budget.onInternalError);
15753
+ const text3 = description ? "" : message(error, this.budget.onInternalError);
15722
15754
  diagnose?.(error, cdDiagnostic(description ? [name2, ": ", target, description] : stackHooks && text3.startsWith("cd: ") ? [name2, text3.slice(2)] : [text3]));
15723
15755
  throw error;
15724
15756
  }
@@ -16624,7 +16656,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
16624
16656
  }, (prepared) => evaluateArithmetic(prepared, this.arithmeticVariables(state, io.diagnosticLine ?? part.line), this.budget.parsing)));
16625
16657
  } catch (error) {
16626
16658
  this.rethrowArithmeticControl(error);
16627
- throw new ExpansionFailure(message(error), io.diagnosticLine ?? part.line);
16659
+ throw new ExpansionFailure(message(error, this.budget.onInternalError), io.diagnosticLine ?? part.line);
16628
16660
  }
16629
16661
  }
16630
16662
  if (part.kind === "substitution") {
@@ -16725,7 +16757,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
16725
16757
  alternate = shellValueText(retained);
16726
16758
  if (operator === "?") throw new ParameterExpansionFailure(`${part.name}: ${alternate || (part.operator.startsWith(":") ? "parameter null or not set" : "parameter not set")}`, io.diagnosticLine ?? part.line);
16727
16759
  if (operator === "=") {
16728
- if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(part.name)) throw new Error("Cannot assign special parameter");
16760
+ if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(part.name)) throw new PublicDiagnostic("Cannot assign special parameter");
16729
16761
  this.writeVariable(state, part.name, retained);
16730
16762
  }
16731
16763
  value2 = alternate;
@@ -16783,7 +16815,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
16783
16815
  return { value: evaluateArithmetic(prepareArithmetic(source2, this.budget.parsing), variables, this.budget.parsing), source: source2 };
16784
16816
  } catch (error) {
16785
16817
  this.rethrowArithmeticControl(error);
16786
- throw new ExpansionFailure(`${part.name}: ${message(error)}`, line);
16818
+ throw new ExpansionFailure(`${part.name}: ${message(error, this.budget.onInternalError)}`, line);
16787
16819
  } finally {
16788
16820
  retained?.release();
16789
16821
  }
@@ -17556,7 +17588,7 @@ var ShellInput = class _ShellInput {
17556
17588
  decoder3.decode();
17557
17589
  return { value: text3.finish(), escaped: escaped3, terminated };
17558
17590
  } catch (error) {
17559
- if (error instanceof TypeError && error.message.includes("encoded data")) throw new Error("read: unsupported non-UTF-8 text boundary");
17591
+ if (error instanceof TypeError && error.message.includes("encoded data")) throw new PublicDiagnostic("read: unsupported non-UTF-8 text boundary");
17560
17592
  throw error;
17561
17593
  } finally {
17562
17594
  if (offset < chunk.length) this.#cursor.remainder = chunk.subarray(offset);
@@ -17726,6 +17758,7 @@ var Shell = class {
17726
17758
  #active = /* @__PURE__ */ new Set();
17727
17759
  constructor(options3) {
17728
17760
  if (!options3?.fs) throw new TypeError("Shell requires an explicit filesystem");
17761
+ if (options3.onInternalError !== void 0 && typeof options3.onInternalError !== "function") throw new TypeError("onInternalError must be callable");
17729
17762
  warnIfHostProcessEnv(options3.env);
17730
17763
  resolveLimits(options3.limits);
17731
17764
  this.#options = { ...options3, cwd: resolvePath("/", options3.cwd ?? "/"), env: { ...options3.env }, limits: { ...options3.limits } };
@@ -17789,8 +17822,9 @@ var Shell = class {
17789
17822
  }
17790
17823
  async exec(source2, options3 = {}) {
17791
17824
  if (this.#disposed) throw new Error("Shell is disposed");
17825
+ if (options3.onInternalError !== void 0 && typeof options3.onInternalError !== "function") throw new TypeError("onInternalError must be callable");
17792
17826
  warnIfHostProcessEnv(options3.env);
17793
- const budget = new Budget(resolveLimits(this.#options.limits, options3.limits), options3.signal);
17827
+ const budget = new Budget(resolveLimits(this.#options.limits, options3.limits), options3.signal, options3.onInternalError ?? this.#options.onInternalError);
17794
17828
  const scope = new InvocationScope(options3.signal);
17795
17829
  const cancellationState = new RuntimeCancellationState();
17796
17830
  const owner = new RootInvocationCancellationOwner(scope);
@@ -18222,9 +18256,9 @@ var defaults = Object.freeze({
18222
18256
  workerOldGenerationMb: 128,
18223
18257
  workerStackMb: 4
18224
18258
  });
18225
- var RegexExecutionError = class extends Error {
18226
- constructor(code, message3) {
18227
- super(code === "MATCH" ? message3 : `regex ${code}: ${message3}`);
18259
+ var RegexExecutionError = class extends PublicDiagnostic {
18260
+ constructor(code, message3, options3) {
18261
+ super(code === "MATCH" ? message3 : `regex ${code}: ${message3}`, options3);
18228
18262
  this.code = code;
18229
18263
  this.name = "RegexExecutionError";
18230
18264
  }
@@ -18431,7 +18465,7 @@ var Slot = class {
18431
18465
  if (this.receiver) this.receiver(value2);
18432
18466
  else this.fail(new RegexExecutionError("PROTOCOL", "unexpected idle message"));
18433
18467
  };
18434
- error = (error) => this.fail(new RegexExecutionError("WORKER_ERROR", error.message));
18468
+ error = (error) => this.fail(new RegexExecutionError("WORKER_ERROR", "internal error", { cause: error }));
18435
18469
  messageerror = () => this.fail(new RegexExecutionError("PROTOCOL", "worker message could not be deserialized"));
18436
18470
  exit = (code) => {
18437
18471
  this.exited = true;
@@ -18796,7 +18830,7 @@ async function* requiredFileInput(context2, requirements, mode, file, maxBytes)
18796
18830
  }
18797
18831
 
18798
18832
  // packages/safe-bash/src/commands/text-programs/shared.ts
18799
- var ProgramError = class extends Error {
18833
+ var ProgramError = class extends PublicDiagnostic {
18800
18834
  };
18801
18835
  var Budget3 = class {
18802
18836
  constructor(context2, options3) {
@@ -18885,7 +18919,7 @@ function command(name2, run4) {
18885
18919
  return { exitCode: await run4(context2) };
18886
18920
  } catch (error) {
18887
18921
  context2.signal.throwIfAborted();
18888
- await writeDiagnostic(context2.stderr, `${name2}: ${error instanceof Error ? error.message : String(error)}
18922
+ await writeDiagnostic(context2.stderr, `${name2}: ${publicDiagnosticMessage(error, context2.onInternalError)}
18889
18923
  `, context2.signal);
18890
18924
  return { exitCode: error instanceof ProgramError ? 2 : 1 };
18891
18925
  }
@@ -20426,7 +20460,7 @@ var defaultFileTypes = Object.freeze({
20426
20460
  for (const patterns2 of Object.values(defaultFileTypes)) Object.freeze(patterns2);
20427
20461
 
20428
20462
  // packages/safe-bash/src/commands/search/options.ts
20429
- var SearchError = class extends Error {
20463
+ var SearchError = class extends PublicDiagnostic {
20430
20464
  };
20431
20465
  function count(value2, flag) {
20432
20466
  if (!/^[0-9]+$/u.test(value2) || !Number.isSafeInteger(Number(value2))) throw new SearchError(`${flag} requires a nonnegative integer`);
@@ -20843,7 +20877,7 @@ var Limits = class {
20843
20877
  }
20844
20878
  };
20845
20879
  async function diagnostic2(context2, error) {
20846
- await writeDiagnostic(context2.stderr, `rg: ${error instanceof Error ? error.message : String(error)}
20880
+ await writeDiagnostic(context2.stderr, `rg: ${publicDiagnosticMessage(error, context2.onInternalError)}
20847
20881
  `, context2.signal);
20848
20882
  }
20849
20883
  async function* lines2(source2, limits, state, binary3, nullData) {
@@ -21456,7 +21490,7 @@ var byteLength = Object.getOwnPropertyDescriptor(typedArrayPrototype2, "byteLeng
21456
21490
  var byteOffset = Object.getOwnPropertyDescriptor(typedArrayPrototype2, "byteOffset").get;
21457
21491
  var byteBuffer = Object.getOwnPropertyDescriptor(typedArrayPrototype2, "buffer").get;
21458
21492
  function fail(kind, message3) {
21459
- throw new Error(`bounded regex ${kind}: ${message3}`);
21493
+ throw new PublicDiagnostic(`bounded regex ${kind}: ${message3}`);
21460
21494
  }
21461
21495
  function record3(value2, keys, optional = []) {
21462
21496
  if (value2 === null || typeof value2 !== "object" || Array.isArray(value2)) fail("protocol", "expected a data record");
@@ -21765,7 +21799,8 @@ var CooperativeWorker = class {
21765
21799
  try {
21766
21800
  owned = admit(input3, this.limits, this.#controller.signal);
21767
21801
  } catch (error) {
21768
- failure = error instanceof Error ? error.message.slice(0, 512) : "bounded regex protocol: request admission failed";
21802
+ if (!(error instanceof PublicDiagnostic || error instanceof EreSyntaxError || error instanceof EreUnsupportedError || error instanceof EreProfileLimitError || error instanceof EreUsageUnknownError)) throw error;
21803
+ failure = error.message.slice(0, 512);
21769
21804
  }
21770
21805
  this.#busy = true;
21771
21806
  const task = Promise.resolve().then(async () => {
@@ -21774,7 +21809,13 @@ var CooperativeWorker = class {
21774
21809
  this.#controller.signal.throwIfAborted();
21775
21810
  reply = owned ? await execute2(owned, this.#controller.signal) : { id, error: failure };
21776
21811
  } catch (error) {
21777
- reply = { id, error: error instanceof Error ? error.message.slice(0, 512) : "bounded regex request failed" };
21812
+ if (!(error instanceof PublicDiagnostic || error instanceof EreSyntaxError || error instanceof EreUnsupportedError || error instanceof EreProfileLimitError || error instanceof EreUsageUnknownError)) {
21813
+ owned = void 0;
21814
+ this.#busy = false;
21815
+ for (const listener of this.#listeners.get("error") ?? []) listener(error);
21816
+ return;
21817
+ }
21818
+ reply = { id, error: error.message.slice(0, 512) };
21778
21819
  }
21779
21820
  if (expression && "error" in reply) reply = { id, operation: "expr-match", category: "unsupported", error: reply.error };
21780
21821
  owned = void 0;
@@ -22065,7 +22106,7 @@ function findCommands(execute5, maxDirectoryEntries) {
22065
22106
  };
22066
22107
  const evaluate = args.length ? disjunction() : async () => true;
22067
22108
  if (offset !== args.length) throw new UsageError(`unexpected expression '${args[offset]}'`);
22068
- if (deletes && prunes && !explicitDepth) throw new Error("-delete implies -depth; -prune is ineffective unless -depth is explicitly supplied");
22109
+ if (deletes && prunes && !explicitDepth) throw new PublicDiagnostic("-delete implies -depth; -prune is ineffective unless -depth is explicitly supplied");
22069
22110
  for (const reference of references.keys()) {
22070
22111
  context2.signal.throwIfAborted();
22071
22112
  const path = pathOf(context2, reference);
@@ -22125,7 +22166,7 @@ function createStandardCommandsWithGrep(options3, grep) {
22125
22166
  const execute5 = directExecutor(options3.execute ?? (async (context2) => {
22126
22167
  const command7 = commands.find((definition3) => definition3.name === context2.command);
22127
22168
  if (command7) return command7.execute(context2);
22128
- await diagnostic(context2, new Error("command not found"));
22169
+ await diagnostic(context2, new PublicDiagnostic("command not found"));
22129
22170
  return { exitCode: 127 };
22130
22171
  }));
22131
22172
  commands.push(...basicCommands(), ...filesystemCommands(options3.maxDirectoryEntries), ...streamCommands(options3.maxTeeTargets, options3.maxTailFollowHandles), ...textCommands(), ...grep, ...predicateCommands(), ...executionCommands(execute5, options3.execution), ...findCommands(execute5, options3.maxDirectoryEntries));
@@ -26265,7 +26306,7 @@ async function* range(source2, skip, count2) {
26265
26306
  }
26266
26307
  if (!skip && !count2) return;
26267
26308
  }
26268
- if (skip) throw new Error("cannot skip past end of input");
26309
+ if (skip) throw new PublicDiagnostic("cannot skip past end of input");
26269
26310
  }
26270
26311
  async function* rows(source2, width) {
26271
26312
  const row = new Uint8Array(width);
@@ -26305,7 +26346,7 @@ function numeric2(text3, suffixes = false) {
26305
26346
  }
26306
26347
  function addOffset(offset, length) {
26307
26348
  const result2 = offset + length;
26308
- if (!Number.isSafeInteger(result2)) throw new Error("input address exceeds safe integer range");
26349
+ if (!Number.isSafeInteger(result2)) throw new PublicDiagnostic("input address exceeds safe integer range");
26309
26350
  return result2;
26310
26351
  }
26311
26352
 
@@ -26391,13 +26432,13 @@ async function decode(context2, files, alphabet, ignore, maxInputBytes) {
26391
26432
  }
26392
26433
  }
26393
26434
  if (pending.length) await output(context2, Uint8Array.from(pending));
26394
- if (invalid) throw new Error("invalid input");
26435
+ if (invalid) throw new PublicDiagnostic("invalid input");
26395
26436
  }
26396
26437
  if (quantum.length) {
26397
26438
  if (lastByte !== 61) while (quantum.length < alphabet.quantum) quantum.push(-1);
26398
26439
  const decoded = decodeQuantum(quantum, alphabet);
26399
26440
  if (decoded.bytes.length) await output(context2, Uint8Array.from(decoded.bytes));
26400
- if (!decoded.valid) throw new Error("invalid input");
26441
+ if (!decoded.valid) throw new PublicDiagnostic("invalid input");
26401
26442
  }
26402
26443
  }
26403
26444
  function createBaseCommand(name2, maxInputBytes) {
@@ -26557,9 +26598,9 @@ async function reversePlain(context2, files, maxInputBytes) {
26557
26598
  }
26558
26599
  }
26559
26600
  if (pending.length) await output(context2, Uint8Array.from(pending));
26560
- if (invalid) throw new Error("invalid input: expected hexadecimal digits or ASCII whitespace");
26601
+ if (invalid) throw new PublicDiagnostic("invalid input: expected hexadecimal digits or ASCII whitespace");
26561
26602
  }
26562
- if (high >= 0) throw new Error("invalid input: unmatched hexadecimal digit");
26603
+ if (high >= 0) throw new PublicDiagnostic("invalid input: unmatched hexadecimal digit");
26563
26604
  }
26564
26605
  async function reverseNormal(context2, files, columns, maxInputBytes) {
26565
26606
  let line = "";
@@ -26570,13 +26611,13 @@ async function reverseNormal(context2, files, columns, maxInputBytes) {
26570
26611
  return;
26571
26612
  }
26572
26613
  const match = /^([0-9a-fA-F]{1,14}):[ \t]?(.*)$/u.exec(line.replace(/\r$/u, ""));
26573
- if (!match) throw new Error("invalid input: expected hexadecimal address and colon");
26614
+ if (!match) throw new PublicDiagnostic("invalid input: expected hexadecimal address and colon");
26574
26615
  const address = Number.parseInt(match[1], 16);
26575
- if (!Number.isSafeInteger(address) || address !== offset) throw new Error("invalid input: reverse requires contiguous addresses starting at zero");
26616
+ if (!Number.isSafeInteger(address) || address !== offset) throw new PublicDiagnostic("invalid input: reverse requires contiguous addresses starting at zero");
26576
26617
  const field = match[2].split(/ {2,}|\t/u, 1)[0];
26577
- if (!/^(?:[0-9a-fA-F]{2})+(?: (?:[0-9a-fA-F]{2})+)*$/u.test(field)) throw new Error("invalid input: malformed hexadecimal data field");
26618
+ if (!/^(?:[0-9a-fA-F]{2})+(?: (?:[0-9a-fA-F]{2})+)*$/u.test(field)) throw new PublicDiagnostic("invalid input: malformed hexadecimal data field");
26578
26619
  const digits = field.replaceAll(" ", "");
26579
- if (digits.length > columns * 2) throw new Error("invalid input: data exceeds configured columns");
26620
+ if (digits.length > columns * 2) throw new PublicDiagnostic("invalid input: data exceeds configured columns");
26580
26621
  const bytes3 = new Uint8Array(digits.length / 2);
26581
26622
  for (let index = 0; index < bytes3.length; index++) bytes3[index] = Number.parseInt(digits.slice(index * 2, index * 2 + 2), 16);
26582
26623
  offset = addOffset(offset, bytes3.length);
@@ -26587,7 +26628,7 @@ async function reverseNormal(context2, files, columns, maxInputBytes) {
26587
26628
  for (const byte of chunk) {
26588
26629
  if (byte === 10) await emitLine();
26589
26630
  else {
26590
- if (line.length >= 4096) throw new Error("invalid input: reverse line exceeds 4096 bytes");
26631
+ if (line.length >= 4096) throw new PublicDiagnostic("invalid input: reverse line exceeds 4096 bytes");
26591
26632
  line += String.fromCharCode(byte);
26592
26633
  }
26593
26634
  }
@@ -26887,7 +26928,7 @@ async function verify(context2, manifest2, algorithm, settings17, state) {
26887
26928
  if (entry === "skip") continue;
26888
26929
  if (!entry || manifest2 === "-" && entry.filename === "-") {
26889
26930
  malformed++;
26890
- if (settings17.report === "warn") await diagnostic(context2, `${escaped(manifest2).name}: ${lineNumber}: improperly formatted ${algorithm} checksum line`);
26931
+ if (settings17.report === "warn") await diagnostic(context2, new PublicDiagnostic(`${escaped(manifest2).name}: ${lineNumber}: improperly formatted ${algorithm} checksum line`));
26891
26932
  continue;
26892
26933
  }
26893
26934
  valid = true;
@@ -26908,12 +26949,12 @@ async function verify(context2, manifest2, algorithm, settings17, state) {
26908
26949
  else mismatched++;
26909
26950
  if (settings17.report !== "status" && (!match || settings17.report !== "quiet")) await report(context2, entry.filename, match ? "OK" : "FAILED");
26910
26951
  }
26911
- if (!valid) await diagnostic(context2, `${escaped(manifest2).name}: no properly formatted checksum lines found`);
26952
+ if (!valid) await diagnostic(context2, new PublicDiagnostic(`${escaped(manifest2).name}: no properly formatted checksum lines found`));
26912
26953
  else if (settings17.report !== "status") {
26913
- if (malformed) await diagnostic(context2, `WARNING: ${malformed} improperly formatted checksum line(s)`);
26914
- if (failures) await diagnostic(context2, `WARNING: ${failures} listed file(s) could not be read`);
26915
- if (mismatched) await diagnostic(context2, `WARNING: ${mismatched} computed checksum(s) did NOT match`);
26916
- if (settings17.ignoreMissing && !matched) await diagnostic(context2, `${escaped(manifest2).name}: no file was verified`);
26954
+ if (malformed) await diagnostic(context2, new PublicDiagnostic(`WARNING: ${malformed} improperly formatted checksum line(s)`));
26955
+ if (failures) await diagnostic(context2, new PublicDiagnostic(`WARNING: ${failures} listed file(s) could not be read`));
26956
+ if (mismatched) await diagnostic(context2, new PublicDiagnostic(`WARNING: ${mismatched} computed checksum(s) did NOT match`));
26957
+ if (settings17.ignoreMissing && !matched) await diagnostic(context2, new PublicDiagnostic(`${escaped(manifest2).name}: no file was verified`));
26917
26958
  }
26918
26959
  return valid && matched && !failures && !mismatched && (!settings17.strict || !malformed);
26919
26960
  }
@@ -26975,6 +27016,39 @@ import { createGzip } from "node:zlib";
26975
27016
 
26976
27017
  // packages/safe-bash/src/commands/bytes/compression/gunzip.ts
26977
27018
  init_platform();
27019
+
27020
+ // packages/safe-bash/src/commands/bytes/compression/errors.ts
27021
+ init_platform();
27022
+ var dataErrors = /* @__PURE__ */ new Set([
27023
+ "incorrect header check",
27024
+ "unknown compression method",
27025
+ "invalid window size",
27026
+ "unknown header flags set",
27027
+ "header crc mismatch",
27028
+ "invalid block type",
27029
+ "invalid stored block lengths",
27030
+ "too many length or distance symbols",
27031
+ "invalid code lengths set",
27032
+ "invalid bit length repeat",
27033
+ "invalid code -- missing end-of-block",
27034
+ "invalid literal/lengths set",
27035
+ "invalid distances set",
27036
+ "invalid literal/length code",
27037
+ "invalid distance code",
27038
+ "invalid distance too far back",
27039
+ "incorrect data check",
27040
+ "incorrect length check"
27041
+ ]);
27042
+ function compressionDiagnostic(error) {
27043
+ if (!(error instanceof Error) || error instanceof PublicDiagnostic) return error;
27044
+ const code = "code" in error ? error.code : void 0;
27045
+ if (code === "Z_DATA_ERROR" && dataErrors.has(error.message) || code === "Z_BUF_ERROR" && error.message === "unexpected end of file") {
27046
+ return new PublicDiagnostic(error.message);
27047
+ }
27048
+ return error;
27049
+ }
27050
+
27051
+ // packages/safe-bash/src/commands/bytes/compression/gunzip.ts
26978
27052
  import { createInflateRaw } from "node:zlib";
26979
27053
  var crcTable2 = Uint32Array.from({ length: 256 }, (_, value2) => {
26980
27054
  for (let bit = 0; bit < 8; bit++) value2 = value2 >>> 1 ^ (value2 & 1 ? 3988292384 : 0);
@@ -27015,7 +27089,7 @@ var Input = class {
27015
27089
  }
27016
27090
  async required() {
27017
27091
  const value2 = await this.byte();
27018
- if (value2 === void 0) throw new Error("unexpected end of file");
27092
+ if (value2 === void 0) throw new PublicDiagnostic("unexpected end of file");
27019
27093
  return value2;
27020
27094
  }
27021
27095
  async exact(length) {
@@ -27029,9 +27103,9 @@ var Input = class {
27029
27103
  };
27030
27104
  async function header(input3, magic2) {
27031
27105
  const fixed2 = await input3.exact(8);
27032
- if (fixed2[0] !== 8) throw new Error("unknown compression method");
27106
+ if (fixed2[0] !== 8) throw new PublicDiagnostic("unknown compression method");
27033
27107
  const flags3 = fixed2[1];
27034
- if (flags3 & 224) throw new Error("invalid gzip header flags");
27108
+ if (flags3 & 224) throw new PublicDiagnostic("invalid gzip header flags");
27035
27109
  let crc = updateCrc(updateCrc(4294967295, magic2), fixed2);
27036
27110
  const next = async () => {
27037
27111
  const value2 = await input3.required();
@@ -27049,7 +27123,7 @@ async function header(input3, magic2) {
27049
27123
  }
27050
27124
  if (flags3 & 2) {
27051
27125
  const expected = await input3.required() | await input3.required() << 8;
27052
- if (((crc ^ 4294967295) & 65535) !== expected) throw new Error("header crc mismatch");
27126
+ if (((crc ^ 4294967295) & 65535) !== expected) throw new PublicDiagnostic("header crc mismatch");
27053
27127
  }
27054
27128
  }
27055
27129
  async function* inflate(input3, signal) {
@@ -27068,7 +27142,7 @@ async function* inflate(input3, signal) {
27068
27142
  return;
27069
27143
  }
27070
27144
  const before = codec.bytesWritten;
27071
- await new Promise((resolve, reject) => codec.write(chunk, (error) => error ? reject(error) : resolve()));
27145
+ await new Promise((resolve, reject) => codec.write(chunk, (error) => error ? reject(compressionDiagnostic(error)) : resolve()));
27072
27146
  const consumed = codec.bytesWritten - before;
27073
27147
  if (consumed < chunk.length) {
27074
27148
  input3.restore(chunk.subarray(consumed));
@@ -27077,8 +27151,9 @@ async function* inflate(input3, signal) {
27077
27151
  }
27078
27152
  }
27079
27153
  } catch (error) {
27080
- codec.destroy(error instanceof Error ? error : new Error(String(error)));
27081
- throw error;
27154
+ const failure = error instanceof PublicDiagnostic || error instanceof FsError ? error : new PublicDiagnostic("internal error", { cause: error });
27155
+ codec.destroy(failure);
27156
+ throw failure;
27082
27157
  }
27083
27158
  })();
27084
27159
  void writing.catch(() => {
@@ -27086,6 +27161,9 @@ async function* inflate(input3, signal) {
27086
27161
  try {
27087
27162
  for await (const chunk of readBytes2(codec, signal)) yield chunk;
27088
27163
  await writing;
27164
+ } catch (error) {
27165
+ signal.throwIfAborted();
27166
+ throw compressionDiagnostic(error);
27089
27167
  } finally {
27090
27168
  codec.destroy();
27091
27169
  signal.removeEventListener("abort", abort);
@@ -27100,7 +27178,7 @@ async function* gunzipMembers(source2, signal, force, warn) {
27100
27178
  for (; ; ) {
27101
27179
  const first = await input3.byte();
27102
27180
  if (first === void 0) {
27103
- if (!members && !force) throw new Error("unexpected end of file");
27181
+ if (!members && !force) throw new PublicDiagnostic("unexpected end of file");
27104
27182
  return;
27105
27183
  }
27106
27184
  const second = await input3.byte();
@@ -27123,8 +27201,8 @@ async function* gunzipMembers(source2, signal, force, warn) {
27123
27201
  if (garbage) warn();
27124
27202
  return;
27125
27203
  }
27126
- if (second === void 0) throw new Error("unexpected end of file");
27127
- if (!members) throw new Error("not in gzip format");
27204
+ if (second === void 0) throw new PublicDiagnostic("unexpected end of file");
27205
+ if (!members) throw new PublicDiagnostic("not in gzip format");
27128
27206
  warn();
27129
27207
  return;
27130
27208
  }
@@ -27138,8 +27216,8 @@ async function* gunzipMembers(source2, signal, force, warn) {
27138
27216
  }
27139
27217
  const footer = await input3.exact(8);
27140
27218
  const view = new DataView(footer.buffer, footer.byteOffset, footer.byteLength);
27141
- if ((crc ^ 4294967295) >>> 0 !== view.getUint32(0, true)) throw new Error("incorrect data check (CRC)");
27142
- if (size !== view.getUint32(4, true)) throw new Error("incorrect length check");
27219
+ if ((crc ^ 4294967295) >>> 0 !== view.getUint32(0, true)) throw new PublicDiagnostic("incorrect data check (CRC)");
27220
+ if (size !== view.getUint32(4, true)) throw new PublicDiagnostic("incorrect length check");
27143
27221
  members++;
27144
27222
  }
27145
27223
  } finally {
@@ -27171,8 +27249,10 @@ async function transform(source2, consume, options3, parentSignal, maxOutput = I
27171
27249
  const controller = new AbortController();
27172
27250
  const signal = AbortSignal.any([parentSignal, controller.signal]);
27173
27251
  let failure;
27252
+ let hasFailure = false;
27174
27253
  const fail4 = (error) => {
27175
27254
  if (!controller.signal.aborted) {
27255
+ hasFailure = true;
27176
27256
  failure = error;
27177
27257
  controller.abort(error);
27178
27258
  }
@@ -27221,7 +27301,7 @@ async function transform(source2, consume, options3, parentSignal, maxOutput = I
27221
27301
  }, { signal });
27222
27302
  } catch (error) {
27223
27303
  parentSignal.throwIfAborted();
27224
- throw failure ?? error;
27304
+ throw hasFailure ? failure : error;
27225
27305
  } finally {
27226
27306
  controller.abort();
27227
27307
  readable.destroy();
@@ -27401,7 +27481,10 @@ async function writeFileOperand(context2, plan, options3) {
27401
27481
  }
27402
27482
  await context2.fs.rm(directory2, { recursive: true, signal });
27403
27483
  } catch (error) {
27404
- if (failed) throw new AggregateError([failure, error], "compression failed and staging cleanup failed; input retained");
27484
+ if (failed) {
27485
+ const aggregate = new AggregateError([failure, error], "compression failed and staging cleanup failed; input retained");
27486
+ throw new PublicDiagnostic(aggregate.message, { cause: aggregate });
27487
+ }
27405
27488
  throw error;
27406
27489
  }
27407
27490
  if (failed) throw failure;
@@ -27517,7 +27600,7 @@ No FILE or FILE '-' uses stdin; file output uses private VFS staging.
27517
27600
  }, { ...options3, force: options3.force && (options3.stdout || options3.test || plan.source === "-") }, context2.signal);
27518
27601
  }
27519
27602
  if (warned2) {
27520
- await diagnostic(context2, new Error(`${plan.source}: decompression OK, trailing garbage ignored`));
27603
+ await diagnostic(context2, new PublicDiagnostic(`${plan.source}: decompression OK, trailing garbage ignored`));
27521
27604
  if (exitCode === 0) exitCode = 2;
27522
27605
  }
27523
27606
  } catch (error) {
@@ -27543,7 +27626,7 @@ init_platform();
27543
27626
 
27544
27627
  // packages/safe-bash/src/commands/diff-patch/shared.ts
27545
27628
  init_platform();
27546
- var ToolError = class extends Error {
27629
+ var ToolError = class extends PublicDiagnostic {
27547
27630
  constructor(message3, exitCode = 2) {
27548
27631
  super(message3);
27549
27632
  this.exitCode = exitCode;
@@ -27687,7 +27770,7 @@ function definition(name2, options3, run4) {
27687
27770
  return { exitCode: await run4(context2, new Budget13(context2, options3)) };
27688
27771
  } catch (error) {
27689
27772
  context2.signal.throwIfAborted();
27690
- const message3 = error instanceof Error ? error.message : String(error);
27773
+ const message3 = publicDiagnosticMessage(error, context2.onInternalError);
27691
27774
  await writeDiagnostic(context2.stderr, `${name2}: ${message3.slice(0, 1e3)}${message3.length > 1e3 ? "\u2026" : ""}
27692
27775
  `, context2.signal);
27693
27776
  return { exitCode: error instanceof ToolError ? error.exitCode : 2 };
@@ -28839,7 +28922,7 @@ async function pruneDirectories(parents2, budget) {
28839
28922
  budget.context.signal.throwIfAborted();
28840
28923
  if (isFsError(error, "ENOENT")) continue;
28841
28924
  if (isFsError(error) || error instanceof ToolError) throw error;
28842
- throw new ToolError(`cannot prune directory ${parent}: ${error instanceof Error ? error.message : String(error)}`);
28925
+ throw new ToolError(`cannot prune directory ${parent}: ${publicDiagnosticMessage(error, budget.context.onInternalError)}`);
28843
28926
  }
28844
28927
  }
28845
28928
  }
@@ -29222,7 +29305,7 @@ ${sourcePatch.hunks.length} out of ${sourcePatch.hunks.length} hunks ignored
29222
29305
  } catch (error) {
29223
29306
  context2.signal.throwIfAborted();
29224
29307
  if (committed === 0 && !publishing) throw error;
29225
- throw new ToolError(`commit stopped; ${committed}/${authorized.length} files committed; failing operation may have side effects; path ${activePath}: ${error instanceof Error ? error.message : String(error)}`);
29308
+ throw new ToolError(`commit stopped; ${committed}/${authorized.length} files committed; failing operation may have side effects; path ${activePath}: ${publicDiagnosticMessage(error, budget.context.onInternalError)}`);
29226
29309
  }
29227
29310
  }
29228
29311
  if (options3.atomic && !options3.dryRun) {
@@ -29234,7 +29317,7 @@ ${sourcePatch.hunks.length} out of ${sourcePatch.hunks.length} hunks ignored
29234
29317
  committed++;
29235
29318
  } catch (error) {
29236
29319
  context2.signal.throwIfAborted();
29237
- throw new ToolError(`commit stopped; ${committed}/${prepared.length} files committed; failing operation may have side effects; path ${item.path}: ${error instanceof Error ? error.message : String(error)}`);
29320
+ throw new ToolError(`commit stopped; ${committed}/${prepared.length} files committed; failing operation may have side effects; path ${item.path}: ${publicDiagnosticMessage(error, budget.context.onInternalError)}`);
29238
29321
  }
29239
29322
  for (const parent of item.parents) parents2.add(parent);
29240
29323
  }
@@ -29819,7 +29902,7 @@ function settings2(options3) {
29819
29902
  return Object.freeze(limits);
29820
29903
  }
29821
29904
  function fail2(message3) {
29822
- throw new Error(message3);
29905
+ throw new PublicDiagnostic(message3);
29823
29906
  }
29824
29907
  function vfsPath(cwd, path) {
29825
29908
  return path.startsWith("/") ? path : `${cwd === "/" ? "" : cwd}/${path}`;
@@ -30510,14 +30593,15 @@ async function* compressed(source2, decode3, signal, limits) {
30510
30593
  try {
30511
30594
  for await (const chunk of bounded(source2, limits.maxArchiveBytes, combined, limits.chunkSize)) {
30512
30595
  await wait(combined, () => new Promise((resolve, reject) => {
30513
- transform2.write(chunk, (error) => error ? reject(error) : resolve());
30596
+ transform2.write(chunk, (error) => error ? reject(compressionDiagnostic(error)) : resolve());
30514
30597
  }));
30515
30598
  }
30516
30599
  combined.throwIfAborted();
30517
30600
  transform2.end();
30518
30601
  } catch (error) {
30519
- transform2.destroy(error instanceof Error ? error : new Error(String(error)));
30520
- throw error;
30602
+ const failure = error instanceof PublicDiagnostic || error instanceof FsError ? error : new PublicDiagnostic("internal error", { cause: error });
30603
+ transform2.destroy(failure);
30604
+ throw failure;
30521
30605
  }
30522
30606
  })();
30523
30607
  void pump.catch(() => {
@@ -30525,6 +30609,9 @@ async function* compressed(source2, decode3, signal, limits) {
30525
30609
  try {
30526
30610
  yield* bounded(transform2, limits.maxArchiveBytes, combined, limits.chunkSize);
30527
30611
  await pump;
30612
+ } catch (error) {
30613
+ signal.throwIfAborted();
30614
+ throw compressionDiagnostic(error);
30528
30615
  } finally {
30529
30616
  controller.abort(new Error("archive compression finished"));
30530
30617
  combined.removeEventListener("abort", destroy);
@@ -30903,7 +30990,7 @@ function createTarCommand(options3 = {}) {
30903
30990
  } catch (error) {
30904
30991
  controller.abort(error);
30905
30992
  original.signal.throwIfAborted();
30906
- const message3 = escapeText(display((error instanceof Error ? error.message : String(error)).slice(0, 1024)), "diagnostic");
30993
+ const message3 = escapeText(display(publicDiagnosticMessage(error, original.onInternalError).slice(0, 1024)), "diagnostic");
30907
30994
  await writeBytes(original.stderr, import_buffer.Buffer.from(`tar: ${message3}
30908
30995
  `).subarray(0, limits.maxDiagnosticBytes), original.signal);
30909
30996
  return { exitCode: 2 };
@@ -31051,7 +31138,7 @@ var RecordReader = class {
31051
31138
  }
31052
31139
  async closeOperand(name2) {
31053
31140
  this.budget.context.signal.throwIfAborted();
31054
- if (this.closed) throw new Error(`${name2}: Bad file descriptor`);
31141
+ if (this.closed) throw new PublicDiagnostic(`${name2}: Bad file descriptor`);
31055
31142
  await this.close();
31056
31143
  }
31057
31144
  async close() {
@@ -31125,7 +31212,7 @@ var OrderCheck = class {
31125
31212
  if (this.mode === "check") fail3(message3);
31126
31213
  this.warned.add(file);
31127
31214
  this.failed = true;
31128
- await diagnostic(this.context, new Error(message3));
31215
+ await diagnostic(this.context, new PublicDiagnostic(message3));
31129
31216
  }
31130
31217
  }
31131
31218
  };
@@ -32585,7 +32672,7 @@ function createRevCommand(limits) {
32585
32672
  await session.text("\n");
32586
32673
  }
32587
32674
  if (length !== record4.length) {
32588
- await diagnostic(session.context, new Error(`${name2 === "-" ? "stdin" : name2}: Illegal byte sequence`));
32675
+ await diagnostic(session.context, new PublicDiagnostic(`${name2 === "-" ? "stdin" : name2}: Illegal byte sequence`));
32589
32676
  session.failed = true;
32590
32677
  break;
32591
32678
  }
@@ -32735,26 +32822,26 @@ function settings6(options3) {
32735
32822
  }
32736
32823
  function number3(text3, label, units = false, zero = false) {
32737
32824
  const match = /^[\t\n\v\f\r ]*\+?([0-9]*)([a-zA-Z]*)$/u.exec(text3);
32738
- if (!match || !match[1] && (!units || !match[2] || text3 !== match[2])) throw new Error(`invalid ${label}: '${text3}'`);
32825
+ if (!match || !match[1] && (!units || !match[2] || text3 !== match[2])) throw new PublicDiagnostic(`invalid ${label}: '${text3}'`);
32739
32826
  const suffix2 = match[2];
32740
32827
  let multiplier2 = 1;
32741
32828
  if (suffix2) {
32742
- if (!units) throw new Error(`invalid ${label}: '${text3}'`);
32829
+ if (!units) throw new PublicDiagnostic(`invalid ${label}: '${text3}'`);
32743
32830
  if (suffix2 === "b") multiplier2 = 512;
32744
32831
  else {
32745
32832
  const unit = /^([kKmMGTPEZYRQ])(?:(i?B))?$/u.exec(suffix2);
32746
- if (!unit) throw new Error(`invalid ${label}: '${text3}'`);
32833
+ if (!unit) throw new PublicDiagnostic(`invalid ${label}: '${text3}'`);
32747
32834
  const exponent = "KMGTPEZYRQ".indexOf(unit[1].toUpperCase()) + 1;
32748
32835
  multiplier2 = (unit[2] === "B" ? 1e3 : 1024) ** exponent;
32749
32836
  }
32750
32837
  }
32751
32838
  const value2 = Number(match[1] || "1") * multiplier2;
32752
- if (!Number.isSafeInteger(value2) || value2 < (zero ? 0 : 1)) throw new Error(`invalid ${label}: '${text3}'`);
32839
+ if (!Number.isSafeInteger(value2) || value2 < (zero ? 0 : 1)) throw new PublicDiagnostic(`invalid ${label}: '${text3}'`);
32753
32840
  return value2;
32754
32841
  }
32755
32842
  function parseArguments(args, limits) {
32756
32843
  if (args.reduce((total, argument2) => total + import_buffer.Buffer.byteLength(argument2), 0) > limits.maxArgumentBytes) {
32757
- throw new Error("split argument limit exceeded");
32844
+ throw new PublicDiagnostic("split argument limit exceeded");
32758
32845
  }
32759
32846
  let mode;
32760
32847
  let size = 1e3;
@@ -32768,15 +32855,15 @@ function parseArguments(args, limits) {
32768
32855
  if (option === "d") {
32769
32856
  numeric4 = true;
32770
32857
  if (value2 !== void 0) {
32771
- if (!/^[0-9]*$/u.test(value2)) throw new Error(`invalid start value for numerical suffix: '${value2}'`);
32858
+ if (!/^[0-9]*$/u.test(value2)) throw new PublicDiagnostic(`invalid start value for numerical suffix: '${value2}'`);
32772
32859
  numericStart = value2.replace(/^0+(?=\d)/u, "") || "0";
32773
32860
  }
32774
32861
  } else if (option === "a") suffixLength = number3(value2, "suffix length", false, true);
32775
32862
  else if (option === "additional-suffix") {
32776
- if (value2.includes("/") || value2.includes("\0")) throw new Error("invalid additional suffix: contains directory separator or NUL");
32863
+ if (value2.includes("/") || value2.includes("\0")) throw new PublicDiagnostic("invalid additional suffix: contains directory separator or NUL");
32777
32864
  additionalSuffix = value2;
32778
32865
  } else {
32779
- if (mode) throw new Error("cannot split in more than one way");
32866
+ if (mode) throw new PublicDiagnostic("cannot split in more than one way");
32780
32867
  mode = option === "l" ? "lines" : option === "b" ? "bytes" : "line-bytes";
32781
32868
  size = number3(value2, option === "l" ? "number of lines" : "number of bytes", option !== "l");
32782
32869
  }
@@ -32803,28 +32890,28 @@ function parseArguments(args, limits) {
32803
32890
  const equals = argument2.indexOf("=");
32804
32891
  const name2 = argument2.slice(2, equals < 0 ? void 0 : equals);
32805
32892
  const option = long[name2];
32806
- if (!option) throw new Error(`unrecognized option '${argument2}'`);
32893
+ if (!option) throw new PublicDiagnostic(`unrecognized option '${argument2}'`);
32807
32894
  const value2 = equals < 0 ? option === "d" ? void 0 : args[++index] : argument2.slice(equals + 1);
32808
- if (option !== "d" && value2 === void 0) throw new Error(`option '--${name2}' requires an argument`);
32895
+ if (option !== "d" && value2 === void 0) throw new PublicDiagnostic(`option '--${name2}' requires an argument`);
32809
32896
  apply(option, value2);
32810
32897
  } else {
32811
32898
  for (let offset = 1; offset < argument2.length; offset++) {
32812
32899
  const option = argument2[offset];
32813
- if (!"lbaCd".includes(option)) throw new Error(`invalid option -- '${option}'`);
32900
+ if (!"lbaCd".includes(option)) throw new PublicDiagnostic(`invalid option -- '${option}'`);
32814
32901
  if (option === "d") apply(option);
32815
32902
  else {
32816
32903
  const value2 = argument2.slice(offset + 1) || args[++index];
32817
- if (value2 === void 0) throw new Error(`option requires an argument -- '${option}'`);
32904
+ if (value2 === void 0) throw new PublicDiagnostic(`option requires an argument -- '${option}'`);
32818
32905
  apply(option, value2);
32819
32906
  break;
32820
32907
  }
32821
32908
  }
32822
32909
  }
32823
32910
  }
32824
- if (operands.length > 2) throw new Error(`extra operand '${operands[2]}'`);
32825
- if ((suffixLength || 2) > limits.maxSuffixLength) throw new Error("split suffix length limit exceeded");
32826
- if (numericStart !== void 0 && numericStart.length > (suffixLength || 2)) throw new Error("numerical suffix start value is too large for the suffix length");
32827
- if (mode === "line-bytes" && size > limits.maxBufferBytes) throw new Error("split line-bytes window exceeds buffer limit");
32911
+ if (operands.length > 2) throw new PublicDiagnostic(`extra operand '${operands[2]}'`);
32912
+ if ((suffixLength || 2) > limits.maxSuffixLength) throw new PublicDiagnostic("split suffix length limit exceeded");
32913
+ if (numericStart !== void 0 && numericStart.length > (suffixLength || 2)) throw new PublicDiagnostic("numerical suffix start value is too large for the suffix length");
32914
+ if (mode === "line-bytes" && size > limits.maxBufferBytes) throw new PublicDiagnostic("split line-bytes window exceeds buffer limit");
32828
32915
  return {
32829
32916
  mode: mode ?? "lines",
32830
32917
  size,
@@ -32967,7 +33054,7 @@ var Names = class {
32967
33054
  for (let index = this.digits.length - 1; index >= 0; index--) {
32968
33055
  this.digits[index] = this.digits[index] + 1;
32969
33056
  if (index === 0 && this.args.automatic && this.digits[index] === this.args.alphabet.length - 1) {
32970
- if (this.extension.length + this.digits.length + 2 > this.limits.maxSuffixLength) throw new Error("split suffix length limit exceeded");
33057
+ if (this.extension.length + this.digits.length + 2 > this.limits.maxSuffixLength) throw new PublicDiagnostic("split suffix length limit exceeded");
32971
33058
  this.extension += this.args.alphabet.at(-1);
32972
33059
  this.digits = Array.from({ length: this.digits.length + 1 }, () => 0);
32973
33060
  advanced = true;
@@ -32979,7 +33066,7 @@ var Names = class {
32979
33066
  }
32980
33067
  this.digits[index] = 0;
32981
33068
  }
32982
- if (!advanced) throw new Error("output file suffixes exhausted");
33069
+ if (!advanced) throw new PublicDiagnostic("output file suffixes exhausted");
32983
33070
  }
32984
33071
  this.first = false;
32985
33072
  return this.args.prefix + this.extension + this.digits.map((digit2) => this.args.alphabet[digit2]).join("") + this.args.additionalSuffix;
@@ -33191,7 +33278,7 @@ function createSplitCommand(limits) {
33191
33278
  return { exitCode: 0 };
33192
33279
  } catch (error) {
33193
33280
  context2.signal.throwIfAborted();
33194
- const message3 = error instanceof FsError ? error.message.slice(error.code.length + 2) : error instanceof Error ? error.message : String(error);
33281
+ const message3 = error instanceof FsError ? error.message.slice(error.code.length + 2) : publicDiagnosticMessage(error, context2.onInternalError);
33195
33282
  await writeDiagnostic(context2.stderr, `split: ${message3.slice(0, 4096)}
33196
33283
  `, context2.signal);
33197
33284
  return { exitCode: 1 };
@@ -34062,8 +34149,7 @@ var TreeLimitError = class extends FsError {
34062
34149
  }
34063
34150
  };
34064
34151
  function message2(error, budget) {
34065
- const value2 = error instanceof Error ? error.message : error;
34066
- const text3 = typeof value2 === "string" ? value2 : value2 === null || value2 === void 0 || typeof value2 === "number" || typeof value2 === "boolean" ? String(value2) : "non-string filesystem error";
34152
+ const text3 = publicDiagnosticMessage(error, budget.context.onInternalError);
34067
34153
  budget.text(text3);
34068
34154
  return error instanceof Error ? text3.replace(/^[A-Z][A-Z0-9]+: /u, "") : text3;
34069
34155
  }
@@ -35373,7 +35459,7 @@ function diagnostics(context2, maximum) {
35373
35459
  return async (error) => {
35374
35460
  context2.signal.throwIfAborted();
35375
35461
  if (!remaining) return;
35376
- const message3 = error instanceof Error ? error.message : String(error);
35462
+ const message3 = publicDiagnosticMessage(error, context2.onInternalError);
35377
35463
  const prefix3 = "column: ", marker = "...[diagnostic truncated]\n";
35378
35464
  const candidate = prefix3 + escapeText(message3.slice(0, remaining), "diagnostic") + "\n";
35379
35465
  let bytes3 = import_buffer.Buffer.from(candidate);
@@ -36894,7 +36980,7 @@ function createHtmlToMarkdownCommand(options3 = {}) {
36894
36980
  try {
36895
36981
  context2.signal.throwIfAborted();
36896
36982
  if (operation2?.signal.aborted && error === operation2.signal.reason) throw error;
36897
- const message3 = error instanceof Error ? error.message : String(error);
36983
+ const message3 = error instanceof HtmlUsageError ? error.message : publicDiagnosticMessage(error, context2.onInternalError);
36898
36984
  const text3 = `html-to-markdown: ${escapeText(message3.slice(0, limits.maxDiagnosticBytes), "diagnostic")}
36899
36985
  `;
36900
36986
  let bytes3 = import_buffer.Buffer.from(text3);
@@ -36940,7 +37026,7 @@ init_platform();
36940
37026
 
36941
37027
  // packages/safe-bash/src/commands/du/format.ts
36942
37028
  init_platform();
36943
- var UsageError3 = class extends Error {
37029
+ var UsageError3 = class extends PublicDiagnostic {
36944
37030
  };
36945
37031
  function blockSize2(value2) {
36946
37032
  if (value2 === "human-readable") return { unit: 1n, suffix: "", human: 1024 };
@@ -37260,7 +37346,7 @@ var Budget27 = class {
37260
37346
  }
37261
37347
  async diagnostic(error, path) {
37262
37348
  this.active(this.caller.signal);
37263
- const raw = error instanceof Error ? error.message : typeof error === "string" ? error : "filesystem operation failed";
37349
+ const raw = error instanceof UsageError3 ? error.message : publicDiagnosticMessage(error, this.context.onInternalError);
37264
37350
  const maximum = 4096;
37265
37351
  const short = raw.length > maximum ? raw.slice(0, maximum) + " [diagnostic truncated]" : raw;
37266
37352
  const message3 = short.replace(/^[A-Z][A-Z0-9]+: /u, "");
@@ -37329,7 +37415,7 @@ var Walker3 = class {
37329
37415
  async add(left, right, display2) {
37330
37416
  this.budget.step();
37331
37417
  if (right.bytes > Number.MAX_SAFE_INTEGER - left.bytes) {
37332
- await this.failure(new Error("aggregate exceeds safe integer range; total suppressed"), display2);
37418
+ await this.failure(new PublicDiagnostic("aggregate exceeds safe integer range; total suppressed"), display2);
37333
37419
  return { bytes: left.bytes, complete: false };
37334
37420
  }
37335
37421
  return { bytes: left.bytes + right.bytes, complete: left.complete && right.complete };
@@ -37349,7 +37435,7 @@ var Walker3 = class {
37349
37435
  return void 0;
37350
37436
  }
37351
37437
  if (!Array.isArray(entries2)) {
37352
- await this.failure(new Error("invalid directory listing"), display2);
37438
+ await this.failure(new PublicDiagnostic("invalid directory listing"), display2);
37353
37439
  return void 0;
37354
37440
  }
37355
37441
  this.budget.check(entries2.length, limits.maxDirectoryEntries, "directory entry");
@@ -37357,12 +37443,12 @@ var Walker3 = class {
37357
37443
  for (const entry of entries2) {
37358
37444
  this.budget.step();
37359
37445
  if (!entry || typeof entry.name !== "string") {
37360
- await this.failure(new Error("invalid directory entry"), display2);
37446
+ await this.failure(new PublicDiagnostic("invalid directory entry"), display2);
37361
37447
  return void 0;
37362
37448
  }
37363
37449
  this.budget.text(entry.name);
37364
37450
  if (!entry.name || entry.name === "." || entry.name === ".." || /[\/\0]/u.test(entry.name) || names.has(entry.name)) {
37365
- await this.failure(new Error("invalid or duplicate directory entry name"), display2);
37451
+ await this.failure(new PublicDiagnostic("invalid or duplicate directory entry name"), display2);
37366
37452
  return void 0;
37367
37453
  }
37368
37454
  names.add(entry.name);
@@ -37379,13 +37465,13 @@ var Walker3 = class {
37379
37465
  this.budget.text(path);
37380
37466
  this.budget.text(display2);
37381
37467
  if (display2 === "") {
37382
- await this.failure(new Error("invalid zero-length file name"));
37468
+ await this.failure(new PublicDiagnostic("invalid zero-length file name"));
37383
37469
  return { bytes: 0, complete: false };
37384
37470
  }
37385
37471
  let stat;
37386
37472
  try {
37387
37473
  stat = await this.budget.fs(() => context2.fs.lstat(path, { signal: context2.signal }));
37388
- if (!stat || !["file", "directory", "symlink"].includes(stat.type)) throw new Error("invalid entry type");
37474
+ if (!stat || !["file", "directory", "symlink"].includes(stat.type)) throw new PublicDiagnostic("invalid entry type");
37389
37475
  } catch (error) {
37390
37476
  await this.failure(error, display2);
37391
37477
  return { bytes: 0, complete: false };
@@ -37393,7 +37479,7 @@ var Walker3 = class {
37393
37479
  const bytes3 = this.args.apparent ? stat.type === "directory" ? 0 : stat.size : stat.allocatedBytes;
37394
37480
  let amount;
37395
37481
  if (bytes3 === void 0 || !Number.isSafeInteger(bytes3) || bytes3 < 0) {
37396
- await this.failure(new Error(`${this.args.apparent ? "apparent size" : "allocated bytes"} ${bytes3 === void 0 ? "unknown" : "invalid"}; total suppressed`), display2);
37482
+ await this.failure(new PublicDiagnostic(`${this.args.apparent ? "apparent size" : "allocated bytes"} ${bytes3 === void 0 ? "unknown" : "invalid"}; total suppressed`), display2);
37397
37483
  amount = { bytes: 0, complete: false };
37398
37484
  } else amount = { bytes: bytes3, complete: true };
37399
37485
  if (this.duplicate(stat)) return { bytes: 0, complete: amount.complete };
@@ -37911,7 +37997,8 @@ function createExprCommandWithExecutor(executor, options3 = {}) {
37911
37997
  await budget.yield();
37912
37998
  } catch (error) {
37913
37999
  context2.signal.throwIfAborted();
37914
- const detail = error instanceof ExprError || error instanceof ExprMatchError || error instanceof RegexExecutionError ? error.message : "execution or output failure";
38000
+ const projected = error instanceof ExprError || error instanceof ExprMatchError ? error.message : publicDiagnosticMessage(error, context2.onInternalError);
38001
+ const detail = error instanceof ExprError || error instanceof ExprMatchError || error instanceof RegexExecutionError ? projected : "execution or output failure";
37915
38002
  let message3;
37916
38003
  try {
37917
38004
  budget.check(detail.length + 7, limits.maxOutputBytes, "output bytes");
@@ -39386,7 +39473,7 @@ function commandExecutor(lookup) {
39386
39473
  return async (context2) => {
39387
39474
  const command7 = lookup(context2.command);
39388
39475
  if (command7) return command7.execute(context2);
39389
- await diagnostic(context2, new Error("command not found"));
39476
+ await diagnostic(context2, new PublicDiagnostic("command not found"));
39390
39477
  return { exitCode: 127 };
39391
39478
  };
39392
39479
  }
@@ -39542,6 +39629,7 @@ function portableAgentCommands(options3) {
39542
39629
  }
39543
39630
  export {
39544
39631
  ACCESS_MODES,
39632
+ CommandArgumentIdentityError,
39545
39633
  CommandRegistry,
39546
39634
  EreLedger,
39547
39635
  EreProfileLimitError,