@poe-platform/safe-bash 0.1.802 → 0.1.803

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 (150) hide show
  1. package/README.md +4 -2
  2. package/dist/image-ast/index.browser.js +13 -4
  3. package/dist/image-ast/index.js +13 -4
  4. package/dist/safe-bash/chunks/{chunk-KDNSPLII.js → chunk-2LSAMQER.js} +1 -0
  5. package/dist/safe-bash/chunks/{chunk-NZQXYWA3.js → chunk-5OHX7C2V.js} +0 -1
  6. package/dist/safe-bash/chunks/{chunk-SHEMU2Z7.js → chunk-B7PIL77G.js} +82 -63
  7. package/dist/safe-bash/chunks/{chunk-WDLGKIHD.js → chunk-EEEWOYEG.js} +4 -4
  8. package/dist/safe-bash/chunks/{chunk-GETUOD5D.js → chunk-GDYNCWRV.js} +1 -1
  9. package/dist/safe-bash/chunks/{chunk-RSTHLAF3.js → chunk-JMMEIDPF.js} +1 -1
  10. package/dist/safe-bash/chunks/{chunk-44ALJ4QG.js → chunk-PNBBUWSM.js} +71 -55
  11. package/dist/safe-bash/chunks/{chunk-NQCM3TYR.js → chunk-RYFQ3LZG.js} +73 -44
  12. package/dist/safe-bash/chunks/chunk-VBTDHOWC.js +55 -0
  13. package/dist/safe-bash/command-chunks/{chunk-ORYGZYKW.js → chunk-4FEVBOL5.js} +1 -1
  14. package/dist/safe-bash/command-chunks/{chunk-VXSLJH7G.js → chunk-6JSIFWYT.js} +26 -6
  15. package/dist/safe-bash/command-chunks/chunk-A7MU7762.js +200 -0
  16. package/dist/safe-bash/command-chunks/{chunk-KJIMDLBB.js → chunk-BXCXRYVU.js} +1 -1
  17. package/dist/safe-bash/command-chunks/{chunk-F4TEEZTL.js → chunk-CQHP3I66.js} +1 -1
  18. package/dist/safe-bash/command-chunks/{chunk-PEF7K3UQ.js → chunk-EARHPPPJ.js} +1 -1
  19. package/dist/safe-bash/command-chunks/{chunk-QKFSRZGQ.js → chunk-GFC2NTDG.js} +2 -2
  20. package/dist/safe-bash/command-chunks/chunk-GIRNFXP3.js +466 -0
  21. package/dist/safe-bash/command-chunks/{chunk-FPVUD6TH.js → chunk-HDCNKOIX.js} +9 -7
  22. package/dist/safe-bash/command-chunks/{chunk-MQFIPHIQ.js → chunk-ILX2NOLF.js} +18 -15
  23. package/dist/safe-bash/command-chunks/{chunk-5E4WAO4O.js → chunk-JD5QNRNO.js} +3 -3
  24. package/dist/safe-bash/command-chunks/{chunk-I237SNW5.js → chunk-LFJJQQND.js} +1 -1
  25. package/dist/safe-bash/command-chunks/{chunk-W5DNF4JH.js → chunk-LOICUCHG.js} +1 -1
  26. package/dist/safe-bash/command-chunks/{chunk-7U7EXOXX.js → chunk-NASVPT6F.js} +2 -1
  27. package/dist/safe-bash/command-chunks/{chunk-OQKC5ZU2.js → chunk-NKIELG7Y.js} +22 -1
  28. package/dist/safe-bash/command-chunks/{chunk-WPYIOKE3.js → chunk-PICVQ6B5.js} +2 -2
  29. package/dist/safe-bash/command-chunks/{chunk-YOFC45RK.js → chunk-QVOS4YXL.js} +1 -1
  30. package/dist/safe-bash/command-chunks/{chunk-VGG2DL5Q.js → chunk-TRR4MYWF.js} +4 -0
  31. package/dist/safe-bash/command-chunks/{chunk-2JRBIDAD.js → chunk-V4K2JDYU.js} +2 -2
  32. package/dist/safe-bash/command-chunks/{chunk-6GWJUQAV.js → chunk-WWIBP2ET.js} +38 -111
  33. package/dist/safe-bash/command-chunks/chunk-ZDN7MJE6.js +168 -0
  34. package/dist/safe-bash/commands/bytes/compression/index.js +54 -51
  35. package/dist/safe-bash/commands/chmod/index.browser.js +14 -0
  36. package/dist/safe-bash/commands/chmod/index.d.ts +2 -0
  37. package/dist/safe-bash/commands/chmod/index.js +2 -0
  38. package/dist/safe-bash/commands/metadata/chmod.d.ts +1 -7
  39. package/dist/safe-bash/commands/metadata/chmod.js +1 -204
  40. package/dist/safe-bash/commands/metadata/index.browser.js +1 -5
  41. package/dist/safe-bash/commands/metadata/internal.d.ts +1 -30
  42. package/dist/safe-bash/commands/metadata/internal.js +1 -76
  43. package/dist/safe-bash/commands/metadata/mktemp.d.ts +1 -3
  44. package/dist/safe-bash/commands/metadata/mktemp.js +1 -202
  45. package/dist/safe-bash/commands/metadata/stat.d.ts +1 -7
  46. package/dist/safe-bash/commands/metadata/stat.js +1 -530
  47. package/dist/safe-bash/commands/mktemp/index.browser.js +13 -0
  48. package/dist/safe-bash/commands/mktemp/index.d.ts +2 -0
  49. package/dist/safe-bash/commands/mktemp/index.js +2 -0
  50. package/dist/safe-bash/commands/node/index.browser.js +2 -2
  51. package/dist/safe-bash/commands/portable-random.d.ts +1 -1
  52. package/dist/safe-bash/commands/portable-random.js +1 -12
  53. package/dist/safe-bash/commands/python/index.browser.js +3 -3
  54. package/dist/safe-bash/commands/stat/index.browser.js +13 -0
  55. package/dist/safe-bash/commands/stat/index.d.ts +2 -0
  56. package/dist/safe-bash/commands/stat/index.js +2 -0
  57. package/dist/safe-bash/commands/text.js +46 -10
  58. package/dist/safe-bash/full-core.browser.js +86 -86
  59. package/dist/safe-bash/jobs.browser.js +2 -2
  60. package/dist/safe-bash/opt-in/commands/yq/native-work.js +1 -0
  61. package/dist/safe-bash/optional-host.browser.js +10 -10
  62. package/dist/safe-bash/plugins/index.browser.js +13 -13
  63. package/dist/safe-bash/registry-entry.browser.js +16 -16
  64. package/dist/safe-bash/search.browser.js +14 -14
  65. package/dist/safe-bash/shell/runtime.d.ts +3 -0
  66. package/dist/safe-bash/shell/runtime.js +20 -3
  67. package/dist/safe-bash/shell/types.d.ts +2 -0
  68. package/dist/safe-bash/shell/worker-limits.js +1 -0
  69. package/dist/safe-bash/shell-entry.browser.js +12 -12
  70. package/dist/safe-bash/worker/host.js +1 -1
  71. package/dist/safe-bash-command-bc/index.js +12 -5
  72. package/dist/safe-bash-command-bzip2/index.js +4 -3
  73. package/dist/safe-bash-command-chmod/LICENSE +21 -0
  74. package/dist/safe-bash-command-chmod/command.d.ts +7 -0
  75. package/dist/safe-bash-command-chmod/command.js +11 -0
  76. package/dist/safe-bash-command-chmod/index.d.ts +6 -0
  77. package/dist/safe-bash-command-chmod/index.js +27 -0
  78. package/dist/safe-bash-command-exiftool/index.js +5 -5
  79. package/dist/safe-bash-command-find/find.js +1 -1
  80. package/dist/safe-bash-command-find/index.js +1 -1
  81. package/dist/safe-bash-command-fmt/index.js +9 -2
  82. package/dist/safe-bash-command-gzip/index.js +45 -42
  83. package/dist/safe-bash-command-imagemagick/index.js +3 -1
  84. package/dist/safe-bash-command-jq/index.js +1 -1
  85. package/dist/safe-bash-command-jq/jq.js +1 -1
  86. package/dist/safe-bash-command-less/index.js +12 -3
  87. package/dist/safe-bash-command-mktemp/LICENSE +21 -0
  88. package/dist/safe-bash-command-mktemp/command.d.ts +3 -0
  89. package/dist/safe-bash-command-mktemp/command.js +9 -0
  90. package/dist/safe-bash-command-mktemp/index.d.ts +6 -0
  91. package/dist/safe-bash-command-mktemp/index.js +25 -0
  92. package/dist/safe-bash-command-od/index.js +6 -2
  93. package/dist/safe-bash-command-op/index.js +25 -6
  94. package/dist/safe-bash-command-rg/index.js +1 -1
  95. package/dist/safe-bash-command-rg/rg-command.js +1 -1
  96. package/dist/safe-bash-command-sed/index.js +1 -1
  97. package/dist/safe-bash-command-sed/sed.js +1 -1
  98. package/dist/safe-bash-command-sips/index.js +13 -5
  99. package/dist/safe-bash-command-sponge/index.js +10 -3
  100. package/dist/safe-bash-command-stat/LICENSE +21 -0
  101. package/dist/safe-bash-command-stat/command.d.ts +7 -0
  102. package/dist/safe-bash-command-stat/command.js +9 -0
  103. package/dist/safe-bash-command-stat/index.d.ts +6 -0
  104. package/dist/safe-bash-command-stat/index.js +25 -0
  105. package/dist/safe-bash-command-unrtf/index.js +11 -1
  106. package/dist/safe-bash-command-xxd/index.js +6 -2
  107. package/dist/safe-bash-command-xz/command.d.ts +1 -1
  108. package/dist/safe-bash-command-xz/index.js +3 -2
  109. package/dist/safe-bash-command-yq/index.js +1 -0
  110. package/dist/safe-bash-command-yq/native-work.js +1 -0
  111. package/dist/safe-bash-command-yq/query.js +3 -0
  112. package/dist/safe-bash-compression-engine/bounded-codec.js +3 -3
  113. package/dist/safe-bash-compression-engine/codec-loader.js +2 -2
  114. package/dist/safe-bash-compression-engine/files.js +6 -6
  115. package/dist/safe-bash-compression-engine/index.js +5 -5
  116. package/dist/safe-bash-compression-engine/operand.js +6 -6
  117. package/dist/safe-bash-compression-engine/options.js +1 -1
  118. package/dist/safe-bash-compression-engine/stream.js +5 -5
  119. package/dist/safe-bash-compression-engine/zstd-decode.js +4 -4
  120. package/dist/safe-bash-contracts/escaping.js +2 -2
  121. package/dist/safe-bash-contracts/filesystem-output.js +2 -2
  122. package/dist/safe-bash-contracts/index.js +2 -2
  123. package/dist/safe-bash-contracts/io.d.ts +2 -0
  124. package/dist/safe-bash-contracts/io.js +1 -1
  125. package/dist/safe-bash-contracts/output.js +2 -2
  126. package/dist/safe-bash-io-engine/commands/search/requirements.js +1 -1
  127. package/dist/safe-bash-io-engine/commands/text-programs/shared.js +1 -1
  128. package/dist/safe-bash-mcp/index.browser.js +11 -1
  129. package/dist/safe-bash-mcp/index.js +35 -16
  130. package/dist/safe-bash-metadata-engine/LICENSE +21 -0
  131. package/dist/safe-bash-metadata-engine/index.d.ts +30 -0
  132. package/dist/safe-bash-metadata-engine/index.js +82 -0
  133. package/dist/safe-bash-metadata-engine/random.d.ts +1 -0
  134. package/dist/safe-bash-metadata-engine/random.js +21 -0
  135. package/dist/safe-bash-regex-engine/index.js +1 -1
  136. package/dist/safe-bash-regex-engine/text/regex.js +1 -1
  137. package/dist/safe-bash-search-engine/ergonomic-regex.js +2 -2
  138. package/dist/safe-bash-search-engine/glob.js +2 -2
  139. package/dist/safe-bash-search-engine/grep.js +2 -2
  140. package/dist/safe-bash-search-engine/matcher.js +2 -2
  141. package/dist/safe-bash-search-engine/options.d.ts +2 -0
  142. package/dist/safe-bash-search-engine/options.js +1 -1
  143. package/dist/safe-bash-search-engine/output.js +1 -1
  144. package/dist/safe-bash-search-engine/shared.js +2 -2
  145. package/dist/safe-bash-search-engine/walk.js +3 -3
  146. package/dist/safe-playwright-cloudflare/browser-snapshot-json.js +2 -2
  147. package/dist/safe-playwright-cloudflare/browser-snapshot-references.js +1 -1
  148. package/package.json +31 -5
  149. package/dist/safe-bash/chunks/chunk-VSAJ4OTM.js +0 -962
  150. package/dist/safe-bash/chunks/{chunk-BJA5XNP6.js → chunk-A7XEHALN.js} +3 -3
@@ -52,13 +52,14 @@ function settings(options = {}) {
52
52
  }
53
53
  return Object.freeze(limits);
54
54
  }
55
- async function readSourceText(source, maxBytes, signal) {
55
+ async function readSourceText(source, maxBytes, signal, admit) {
56
56
  const chunks = [];
57
57
  let total = 0;
58
58
  let quantum = 0;
59
59
  let chunksRead = 0;
60
60
  for await (const chunk of readBytes(source, signal)) {
61
61
  total += chunk.byteLength;
62
+ admit(chunk.byteLength);
62
63
  signal.throwIfAborted();
63
64
  quantum += Math.max(1, chunk.byteLength);
64
65
  if (quantum >= 16384 || ++chunksRead >= 128) {
@@ -86,6 +87,11 @@ function createPagerCommand(name, options = {}) {
86
87
  description: `Non-interactive ${name} pager pass-through`,
87
88
  runtimeIdentity: commandRuntimeIdentity,
88
89
  async execute(context) {
90
+ let inputBytes = 0;
91
+ const admit = (bytes) => {
92
+ context.signal.throwIfAborted();
93
+ context.inputBudget?.check(inputBytes += bytes);
94
+ };
89
95
  const maxBytes = Math.min(limits.maxInputBytes, context.limits?.maxInputBytes ?? limits.maxInputBytes);
90
96
  context.signal.throwIfAborted();
91
97
  const args = getCommandArguments(context).args;
@@ -165,6 +171,7 @@ function createPagerCommand(name, options = {}) {
165
171
  await yieldTurn(context.signal);
166
172
  }
167
173
  total += chunk.byteLength;
174
+ admit(chunk.byteLength);
168
175
  if (total > maxBytes) {
169
176
  await writeText(context.stderr, `${name}: input exceeds maximum size of ${maxBytes} bytes
170
177
  `);
@@ -179,7 +186,7 @@ function createPagerCommand(name, options = {}) {
179
186
  const texts = [];
180
187
  let exitCode = 0;
181
188
  if (files.length === 0) {
182
- texts.push(await readSourceText(context.stdin, maxBytes, context.signal));
189
+ texts.push(await readSourceText(context.stdin, maxBytes, context.signal, admit));
183
190
  } else {
184
191
  for (const file of files) {
185
192
  if (file === "-") {
@@ -187,16 +194,18 @@ function createPagerCommand(name, options = {}) {
187
194
  let total = 0;
188
195
  for await (const chunk of readBytes(context.stdin, context.signal)) {
189
196
  total += chunk.byteLength;
197
+ admit(chunk.byteLength);
190
198
  if (total > maxBytes) throw new PublicDiagnostic(`input exceeds maximum size of ${maxBytes} bytes`);
191
199
  await writeBytes(context.stdout, chunk, context.signal);
192
200
  await yieldTurn(context.signal);
193
201
  }
194
- } else texts.push(await readSourceText(context.stdin, maxBytes, context.signal));
202
+ } else texts.push(await readSourceText(context.stdin, maxBytes, context.signal, admit));
195
203
  } else {
196
204
  try {
197
205
  const targetPath = pathPosix.resolve(context.cwd, file);
198
206
  const raw = await context.fs.readFile(targetPath, { signal: context.signal });
199
207
  context.signal.throwIfAborted();
208
+ admit(raw.byteLength);
200
209
  if (raw.byteLength > maxBytes) {
201
210
  await writeText(context.stderr, `${name}: ${file}: input exceeds maximum size
202
211
  `);
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Poe Platform
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ import { type MetadataCommandsOptions } from "../safe-bash-metadata-engine/index.js";
2
+ export declare function evalSyncMktemp(opArgs: readonly string[], env: Readonly<Record<string, string>>, statTypeSync?: (filePath: string) => string | undefined, writeFileSync?: (filePath: string, bytes: Uint8Array) => boolean, mkdirSync?: (filePath: string) => boolean): string | undefined;
3
+ export declare function createMktempCommand(configuration?: MetadataCommandsOptions): import("../safe-bash-contracts/index.js").CommandDefinition;
@@ -0,0 +1,9 @@
1
+ import {
2
+ createMktempCommand,
3
+ evalSyncMktemp
4
+ } from "../safe-bash/command-chunks/chunk-ZDN7MJE6.js";
5
+ import "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
6
+ export {
7
+ createMktempCommand,
8
+ evalSyncMktemp
9
+ };
@@ -0,0 +1,6 @@
1
+ import type { VirtualShellPlugin } from "../safe-bash-contracts/index.js";
2
+ import type { MetadataCommandsOptions } from "../safe-bash-metadata-engine/index.js";
3
+ export * from "./command.js";
4
+ export type { MetadataCommandsOptions as MktempCommandsOptions, MetadataLimits as MktempLimits } from "../safe-bash-metadata-engine/index.js";
5
+ export declare function createMktempCommands(options?: MetadataCommandsOptions): import("../safe-bash-contracts/index.js").CommandDefinition[];
6
+ export declare function mktempCommands(options?: MetadataCommandsOptions): VirtualShellPlugin;
@@ -0,0 +1,25 @@
1
+ import {
2
+ createMktempCommand,
3
+ evalSyncMktemp
4
+ } from "../safe-bash/command-chunks/chunk-ZDN7MJE6.js";
5
+ import {
6
+ init_buffer
7
+ } from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
8
+
9
+ // packages/safe-bash-command-mktemp/src/index.ts
10
+ init_buffer();
11
+ function createMktempCommands(options = {}) {
12
+ return [createMktempCommand(options)];
13
+ }
14
+ function mktempCommands(options = {}) {
15
+ const commands = createMktempCommands(options);
16
+ return { name: "mktemp-commands", setup(host) {
17
+ for (const command of commands) host.commands.register(command, { replace: options.replace ?? false });
18
+ } };
19
+ }
20
+ export {
21
+ createMktempCommand,
22
+ createMktempCommands,
23
+ evalSyncMktemp,
24
+ mktempCommands
25
+ };
@@ -139,10 +139,12 @@ function output(context, text) {
139
139
  return writeBytes(context.stdout, bytes, context.signal);
140
140
  }
141
141
  var ByteInputBudget = class {
142
- constructor(maxInputBytes) {
142
+ constructor(maxInputBytes, inputBudget) {
143
143
  this.maxInputBytes = maxInputBytes;
144
+ this.inputBudget = inputBudget;
144
145
  }
145
146
  maxInputBytes;
147
+ inputBudget;
146
148
  #bytes = 0;
147
149
  #failure;
148
150
  assertOpen(signal) {
@@ -158,13 +160,14 @@ var ByteInputBudget = class {
158
160
  throw this.#failure;
159
161
  }
160
162
  this.#bytes += chunk.byteLength;
163
+ this.inputBudget?.check(this.#bytes);
161
164
  yield chunk;
162
165
  this.assertOpen(signal);
163
166
  }
164
167
  }
165
168
  };
166
169
  async function* sources(context, operands, maxInputBytes, onFileError) {
167
- const budget = new ByteInputBudget(maxInputBytes);
170
+ const budget = new ByteInputBudget(maxInputBytes, context.inputBudget);
168
171
  let usedStdin = false;
169
172
  let emptyChunks = 0;
170
173
  for (const operand of operands.length ? operands : ["-"]) {
@@ -510,6 +513,7 @@ function defineOdCommand(handler) {
510
513
  return await handler(context);
511
514
  } catch (error) {
512
515
  context.signal.throwIfAborted();
516
+ if (error instanceof Error && (error.name === "BudgetExceededError" || error.name === "AbortError")) throw error;
513
517
  await writeDiagnostic(
514
518
  context.stderr,
515
519
  `${context.command}: ${publicDiagnosticMessage(error, context.onInternalError)}
@@ -7,6 +7,7 @@ init_buffer();
7
7
 
8
8
  // packages/safe-bash-command-op/src/cli.ts
9
9
  init_buffer();
10
+ import { isFsError } from "@poe-platform/safe-fs/core";
10
11
  import { InputByteBudget } from "../safe-bash-contracts/io.js";
11
12
 
12
13
  // packages/safe-bash-command-op/src/encoding.ts
@@ -3687,6 +3688,7 @@ function createOpCommand(options = {}) {
3687
3688
  }
3688
3689
  return { exitCode: 0 };
3689
3690
  } catch (error) {
3691
+ if (error instanceof Error && error.name === "BudgetExceededError" || isFsError(error, "EPIPE")) throw error;
3690
3692
  let message = error instanceof Error ? error.message : "operation failed";
3691
3693
  try {
3692
3694
  budget.assertOpen();
@@ -4666,7 +4668,7 @@ function createItemHandlers(backend) {
4666
4668
 
4667
4669
  // packages/safe-bash-command-op/src/index.ts
4668
4670
  import { readBytes } from "../safe-bash-contracts/index.js";
4669
- import { resolvePath } from "@poe-platform/safe-fs/core";
4671
+ import { isFsError as isFsError2, resolvePath } from "@poe-platform/safe-fs/core";
4670
4672
 
4671
4673
  // packages/safe-bash-command-op/src/types.ts
4672
4674
  init_buffer();
@@ -4730,27 +4732,44 @@ function createOpCommand2(options = {}) {
4730
4732
  if (!("fs" in context)) return command.execute(context);
4731
4733
  const host = context;
4732
4734
  const { fs, signal, cwd } = context;
4735
+ let inputBytes = 0;
4736
+ const account = (bytes) => {
4737
+ context.inputBudget?.check(inputBytes += bytes.byteLength);
4738
+ return bytes;
4739
+ };
4733
4740
  const invocation = {
4734
4741
  ...host,
4735
4742
  args: context.args,
4736
4743
  env: { ...context.env },
4737
4744
  signal,
4738
- stdin: readBytes(context.stdin, signal),
4745
+ stdin: (async function* () {
4746
+ for await (const bytes of readBytes(context.stdin, signal)) yield account(bytes);
4747
+ })(),
4739
4748
  stdout: context.stdout,
4740
4749
  stderr: context.stderr,
4741
4750
  ...authentication === void 0 ? {} : { authentication },
4742
4751
  ...pluginScope === void 0 ? {} : { pluginScope },
4743
4752
  ...confirmPluginClear === void 0 ? {} : { confirmPluginClear },
4744
4753
  ...selectPlugin === void 0 ? {} : { selectPlugin },
4745
- readFile: host.readFile ?? (async (path) => {
4754
+ readFile: async (path) => {
4755
+ if (host.readFile) return account(await host.readFile(path));
4746
4756
  signal.throwIfAborted();
4747
4757
  const resolved = resolvePath(cwd, path);
4748
4758
  const capabilities = fs.capabilitiesFor ? await fs.capabilitiesFor(resolved, { signal }) : fs.capabilities;
4749
4759
  if (capabilities.read !== true) throw new Error("op requires VFS read capability");
4750
- const bytes = await fs.readFile(resolved, { signal });
4760
+ let bytes;
4761
+ try {
4762
+ bytes = await fs.readFile(resolved, {
4763
+ signal,
4764
+ ...context.inputBudget ? { maxBytes: Math.max(0, context.inputBudget.maxBytes - inputBytes) } : {}
4765
+ });
4766
+ } catch (error) {
4767
+ if (isFsError2(error, "EFBIG") && context.inputBudget) context.inputBudget.check(context.inputBudget.maxBytes + 1);
4768
+ throw error;
4769
+ }
4751
4770
  signal.throwIfAborted();
4752
- return Uint8Array.from(bytes);
4753
- }),
4771
+ return Uint8Array.from(account(bytes));
4772
+ },
4754
4773
  writeFile: host.writeFile ?? (async (path, bytes, settings = {}) => {
4755
4774
  signal.throwIfAborted();
4756
4775
  const resolved = resolvePath(cwd, path);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createRgCommand
3
- } from "../safe-bash/command-chunks/chunk-OQKC5ZU2.js";
3
+ } from "../safe-bash/command-chunks/chunk-NKIELG7Y.js";
4
4
  import {
5
5
  init_buffer
6
6
  } from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  clearRgFastRunnerPool,
3
3
  createRgCommand
4
- } from "../safe-bash/command-chunks/chunk-OQKC5ZU2.js";
4
+ } from "../safe-bash/command-chunks/chunk-NKIELG7Y.js";
5
5
  import "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
6
6
  export {
7
7
  clearRgFastRunnerPool,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sedCommand
3
- } from "../safe-bash/command-chunks/chunk-7U7EXOXX.js";
3
+ } from "../safe-bash/command-chunks/chunk-NASVPT6F.js";
4
4
  import "../safe-bash/command-chunks/chunk-CQ5YGOGB.js";
5
5
  import {
6
6
  init_buffer
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sedCommand
3
- } from "../safe-bash/command-chunks/chunk-7U7EXOXX.js";
3
+ } from "../safe-bash/command-chunks/chunk-NASVPT6F.js";
4
4
  import "../safe-bash/command-chunks/chunk-CQ5YGOGB.js";
5
5
  import "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
6
6
  export {
@@ -111,6 +111,7 @@ function writeProperties(bytes, format, properties) {
111
111
 
112
112
  // packages/safe-bash-command-sips/src/index.ts
113
113
  import { yieldTurn, drainCooperativeSteps as drainSteps } from "../safe-bash-contracts/yield.js";
114
+ import { FsError } from "../safe-bash-contracts/errors.js";
114
115
  import { InputByteBudget } from "../safe-bash-contracts/io.js";
115
116
  import { writeFileOutput } from "../safe-bash-contracts/filesystem-output-budget.js";
116
117
  import {
@@ -1114,6 +1115,7 @@ async function executeVfsImageTool(context, runner) {
1114
1115
  const carrier = getCommandArguments(context);
1115
1116
  const argv = [...carrier.args];
1116
1117
  const vfsFiles = /* @__PURE__ */ new Map();
1118
+ let totalInputBytes = 0;
1117
1119
  const normalizedArgv = [...argv];
1118
1120
  for (let i = 0; i < normalizedArgv.length; i++) {
1119
1121
  if (++cooperativeWork % 64 === 0) await yieldTurn(context.signal);
@@ -1126,7 +1128,8 @@ async function executeVfsImageTool(context, runner) {
1126
1128
  if (st.type === "directory") {
1127
1129
  normalizedArgv[i + 1] = next + "/";
1128
1130
  }
1129
- } catch {
1131
+ } catch (error) {
1132
+ if (!(error instanceof FsError) || !["ENOENT", "ENOTDIR"].includes(error.code)) throw error;
1130
1133
  }
1131
1134
  }
1132
1135
  continue;
@@ -1134,15 +1137,20 @@ async function executeVfsImageTool(context, runner) {
1134
1137
  if (token.startsWith("-")) continue;
1135
1138
  const bracketMatch = /^(.*)\[(\d+)\]$/.exec(token);
1136
1139
  const fileToken = bracketMatch ? bracketMatch[1] : token;
1140
+ let bytes;
1137
1141
  try {
1138
- const bytes = await context.fs.readFile(resolvePath(context.cwd, fileToken), {
1142
+ bytes = await context.fs.readFile(resolvePath(context.cwd, fileToken), {
1139
1143
  signal: invocation.signal
1140
1144
  });
1141
- vfsFiles.set(fileToken, bytes);
1142
- } catch {
1145
+ } catch (error) {
1146
+ if (!(error instanceof FsError) || !["ENOENT", "ENOTDIR", "EISDIR", "EACCES", "EPERM"].includes(error.code)) throw error;
1147
+ continue;
1143
1148
  }
1149
+ totalInputBytes += bytes.byteLength;
1150
+ context.inputBudget?.check(totalInputBytes);
1151
+ vfsFiles.set(fileToken, bytes);
1144
1152
  }
1145
- context.inputBudget?.check(0);
1153
+ context.inputBudget?.check(totalInputBytes);
1146
1154
  const existingSnap = new Map(vfsFiles);
1147
1155
  const res = await runner(normalizedArgv, vfsFiles, invocation.signal);
1148
1156
  for (const [key, val] of vfsFiles.entries()) {
@@ -51,13 +51,14 @@ function settings(options = {}) {
51
51
  }
52
52
  return Object.freeze(limits);
53
53
  }
54
- async function collectSourceBytes(source, maxBytes, signal) {
54
+ async function collectSourceBytes(source, maxBytes, signal, admit) {
55
55
  const chunks = [];
56
56
  let total = 0;
57
57
  let quantum = 0;
58
58
  let chunksRead = 0;
59
59
  for await (const chunk of readBytes(source, signal)) {
60
60
  total += chunk.byteLength;
61
+ admit(chunk.byteLength);
61
62
  signal.throwIfAborted();
62
63
  quantum += Math.max(1, chunk.byteLength);
63
64
  if (quantum >= 16384 || ++chunksRead >= 128) {
@@ -89,6 +90,11 @@ function createSpongeCommand(options = {}) {
89
90
  description: "Soak up all standard input before writing to a file",
90
91
  runtimeIdentity: commandRuntimeIdentity,
91
92
  async execute(context) {
93
+ let inputBytes = 0;
94
+ const admit = (bytes) => {
95
+ context.signal.throwIfAborted();
96
+ context.inputBudget?.check(inputBytes += bytes);
97
+ };
92
98
  context.signal.throwIfAborted();
93
99
  const args = getCommandArguments(context).args;
94
100
  let append = false;
@@ -131,7 +137,7 @@ function createSpongeCommand(options = {}) {
131
137
  }
132
138
  try {
133
139
  const maxBytes = Math.min(limits.maxBufferedBytes, context.limits?.maxInputBytes ?? limits.maxBufferedBytes);
134
- const buffered = await collectSourceBytes(context.stdin, maxBytes, context.signal);
140
+ const buffered = await collectSourceBytes(context.stdin, maxBytes, context.signal, admit);
135
141
  if (files.length === 0 || files[0] === "-") {
136
142
  await writeBytes(context.stdout, buffered, context.signal);
137
143
  return { exitCode: 0 };
@@ -140,7 +146,8 @@ function createSpongeCommand(options = {}) {
140
146
  if (append) {
141
147
  let existing = new Uint8Array(0);
142
148
  try {
143
- existing = await context.fs.readFile(targetPath);
149
+ existing = await context.fs.readFile(targetPath, { signal: context.signal });
150
+ admit(existing.byteLength);
144
151
  } catch (error) {
145
152
  context.signal.throwIfAborted();
146
153
  if (!(error instanceof FsError) || error.code !== "ENOENT") throw error;
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Poe Platform
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,7 @@
1
+ import { type FileStat } from "../safe-bash-contracts/index.js";
2
+ import { type MetadataCommandsOptions } from "../safe-bash-metadata-engine/index.js";
3
+ export declare function createStatCommand(configuration?: MetadataCommandsOptions): import("../safe-bash-contracts/index.js").CommandDefinition;
4
+ export interface SyncStatInfo extends FileStat {
5
+ readonly target?: string;
6
+ }
7
+ export declare function evalSyncStat(args: readonly string[], cwd: string, quotingStyle: string | undefined, inspectStat: (absPath: string, follow: boolean) => SyncStatInfo | undefined): string | undefined;
@@ -0,0 +1,9 @@
1
+ import {
2
+ createStatCommand,
3
+ evalSyncStat
4
+ } from "../safe-bash/command-chunks/chunk-GIRNFXP3.js";
5
+ import "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
6
+ export {
7
+ createStatCommand,
8
+ evalSyncStat
9
+ };
@@ -0,0 +1,6 @@
1
+ import type { VirtualShellPlugin } from "../safe-bash-contracts/index.js";
2
+ import type { MetadataCommandsOptions } from "../safe-bash-metadata-engine/index.js";
3
+ export * from "./command.js";
4
+ export type { MetadataCommandsOptions as StatCommandsOptions, MetadataLimits as StatLimits } from "../safe-bash-metadata-engine/index.js";
5
+ export declare function createStatCommands(options?: MetadataCommandsOptions): import("../safe-bash-contracts/index.js").CommandDefinition[];
6
+ export declare function statCommands(options?: MetadataCommandsOptions): VirtualShellPlugin;
@@ -0,0 +1,25 @@
1
+ import {
2
+ createStatCommand,
3
+ evalSyncStat
4
+ } from "../safe-bash/command-chunks/chunk-GIRNFXP3.js";
5
+ import {
6
+ init_buffer
7
+ } from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
8
+
9
+ // packages/safe-bash-command-stat/src/index.ts
10
+ init_buffer();
11
+ function createStatCommands(options = {}) {
12
+ return [createStatCommand(options)];
13
+ }
14
+ function statCommands(options = {}) {
15
+ const commands = createStatCommands(options);
16
+ return { name: "stat-commands", setup(host) {
17
+ for (const command of commands) host.commands.register(command, { replace: options.replace ?? false });
18
+ } };
19
+ }
20
+ export {
21
+ createStatCommand,
22
+ createStatCommands,
23
+ evalSyncStat,
24
+ statCommands
25
+ };
@@ -2136,9 +2136,17 @@ async function executeUnrtf(context, configuration = {}, cli = false) {
2136
2136
  new Budget({ limits, signal, ...profile === void 0 ? {} : { profile } });
2137
2137
  if (format !== "text" && format !== "html" && !(profile === "gnu-0.21.10" && format === "latex") || noremap && profile !== "gnu-0.21.10") throw new UnrtfError("E_PROFILE", "Option requires the GNU personality profile", 0);
2138
2138
  if (file?.includes("\0")) throw new UnrtfError("E_PARSE", "NUL is unavailable in VFS paths", 0);
2139
+ let inputBytes = 0;
2140
+ const admitInput = (bytes) => {
2141
+ signal.throwIfAborted();
2142
+ context.inputBudget?.check(inputBytes += bytes.byteLength);
2143
+ };
2139
2144
  async function* source() {
2140
2145
  if (file === void 0) {
2141
- yield* readBytes(context.stdin, signal);
2146
+ for await (const bytes of readBytes(context.stdin, signal)) {
2147
+ admitInput(bytes);
2148
+ yield bytes;
2149
+ }
2142
2150
  return;
2143
2151
  }
2144
2152
  const path = file.startsWith("/") ? file : context.cwd + "/" + file;
@@ -2147,12 +2155,14 @@ async function executeUnrtf(context, configuration = {}, cli = false) {
2147
2155
  try {
2148
2156
  if (context.fs.readStream) {
2149
2157
  for await (const bytes of readBytes(context.fs.readStream(candidate, { signal }), signal)) {
2158
+ admitInput(bytes);
2150
2159
  yielded = true;
2151
2160
  yield bytes;
2152
2161
  }
2153
2162
  } else {
2154
2163
  const maxBytes = Math.min(limits.inputBytes, limits.retainedBytes);
2155
2164
  const bytes = await context.fs.readFile(candidate, { signal, ...Number.isFinite(maxBytes) ? { maxBytes } : {} });
2165
+ admitInput(bytes);
2156
2166
  budget.charge("retainedBytes", bytes.length, 0);
2157
2167
  try {
2158
2168
  yield bytes;
@@ -146,10 +146,12 @@ function output(context, text) {
146
146
  return writeBytes(context.stdout, bytes, context.signal);
147
147
  }
148
148
  var ByteInputBudget = class {
149
- constructor(maxInputBytes) {
149
+ constructor(maxInputBytes, inputBudget) {
150
150
  this.maxInputBytes = maxInputBytes;
151
+ this.inputBudget = inputBudget;
151
152
  }
152
153
  maxInputBytes;
154
+ inputBudget;
153
155
  #bytes = 0;
154
156
  #failure;
155
157
  assertOpen(signal) {
@@ -165,13 +167,14 @@ var ByteInputBudget = class {
165
167
  throw this.#failure;
166
168
  }
167
169
  this.#bytes += chunk.byteLength;
170
+ this.inputBudget?.check(this.#bytes);
168
171
  yield chunk;
169
172
  this.assertOpen(signal);
170
173
  }
171
174
  }
172
175
  };
173
176
  async function* sources(context, operands, maxInputBytes) {
174
- const budget = new ByteInputBudget(maxInputBytes);
177
+ const budget = new ByteInputBudget(maxInputBytes, context.inputBudget);
175
178
  let usedStdin = false;
176
179
  let emptyChunks = 0;
177
180
  for (const operand of operands.length ? operands : ["-"]) {
@@ -420,6 +423,7 @@ function defineCommand(name, handler) {
420
423
  return await handler(context);
421
424
  } catch (error) {
422
425
  context.signal.throwIfAborted();
426
+ if (error instanceof Error && (error.name === "BudgetExceededError" || error.name === "AbortError")) throw error;
423
427
  await writeDiagnostic(
424
428
  context.stderr,
425
429
  `${context.command}: ${publicDiagnosticMessage(error, context.onInternalError)}
@@ -1,4 +1,4 @@
1
- import type { CommandDefinition } from "../safe-bash-contracts/index.js";
1
+ import { type CommandDefinition } from "../safe-bash-contracts/index.js";
2
2
  import { type CompressionCommandOptions } from "../safe-bash-compression-engine/stream.js";
3
3
  import type { VirtualShellPlugin } from "../safe-bash-contracts/plugin.js";
4
4
  export interface XzLimits {
@@ -19,6 +19,7 @@ init_buffer();
19
19
  // packages/safe-bash-command-xz/src/command.ts
20
20
  init_buffer();
21
21
  import { PublicDiagnostic } from "../safe-bash-contracts/diagnostics.js";
22
+ import { withInputByteBudget } from "../safe-bash-contracts/index.js";
22
23
  import { codeOf, diagnostic, output } from "../safe-bash-compression-engine/internal.js";
23
24
  import { UsageError } from "../safe-bash-contracts/diagnostics.js";
24
25
  import { runOperand } from "../safe-bash-compression-engine/operand.js";
@@ -29,7 +30,7 @@ function createXzCommand(config = {}, name = "xz") {
29
30
  if (maxDecodedBytes !== void 0 && maxDecodedBytes !== Infinity && (!Number.isSafeInteger(maxDecodedBytes) || maxDecodedBytes < 0)) {
30
31
  throw new RangeError("maxDecodedBytes must be a nonnegative safe integer or Infinity");
31
32
  }
32
- return { name, async execute(context) {
33
+ return { name, execute: withInputByteBudget(async (context) => {
33
34
  context.signal.throwIfAborted();
34
35
  try {
35
36
  const options = parseOptions(name, context.args);
@@ -114,7 +115,7 @@ file ${value.streams} ${value.blocks} ${value.compressed} ${value.uncompressed}
114
115
  await diagnostic(context, error);
115
116
  return { exitCode: error instanceof UsageError ? 2 : 1 };
116
117
  }
117
- } };
118
+ }) };
118
119
  }
119
120
  function createUnxzCommand(options = {}) {
120
121
  return createXzCommand(options, "unxz");
@@ -123,6 +123,7 @@ var NativeWork = class {
123
123
  this.assertOpen();
124
124
  if (bytes > this.limits.maxInputBytes - this.#input) throw new MikeError("yq limit exceeded: maxInputBytes");
125
125
  this.#input += bytes;
126
+ this.context.inputBudget?.check(this.#input);
126
127
  }
127
128
  node(count = 1) {
128
129
  this.assertOpen();
@@ -84,6 +84,7 @@ export class NativeWork {
84
84
  if (bytes > this.limits.maxInputBytes - this.#input)
85
85
  throw new MikeError("yq limit exceeded: maxInputBytes");
86
86
  this.#input += bytes;
87
+ this.context.inputBudget?.check(this.#input);
87
88
  }
88
89
  node(count = 1) {
89
90
  this.assertOpen();
@@ -161,6 +161,7 @@ var SinkFailure = class {
161
161
  reason;
162
162
  };
163
163
  var InvocationOwner = class {
164
+ inputBytes = 0;
164
165
  #accepting = true;
165
166
  #callbacks = [];
166
167
  #closePromise;
@@ -397,6 +398,7 @@ async function collectSource(context, owner, session, sourceName, source, vfs, i
397
398
  }
398
399
  owner.assertOpen(context.signal);
399
400
  if (chunk.byteLength === 0) continue;
401
+ context.inputBudget?.check(owner.inputBytes += chunk.byteLength);
400
402
  session.ownedWork.admitInputBytes(chunk.byteLength);
401
403
  if (chunk.byteLength > yqCaps.maxInputBytes - size) throw fromJqLimit(new JqLimitError("maxInputBytes"));
402
404
  if (inputFormat === "toml" && chunk.byteLength > yqCaps.maxDocumentBytes - size) throw new YqError("limit", "LIMIT_MAX_DOCUMENT_BYTES", 5);
@@ -451,6 +453,7 @@ async function sourceFrames(context, owner, session, sourceName, inputFormat) {
451
453
  throw failure;
452
454
  }
453
455
  owner.assertOpen(context.signal);
456
+ context.inputBudget?.check(owner.inputBytes += bytes.byteLength);
454
457
  session.ownedWork.admitInputBytes(bytes.byteLength);
455
458
  if (inputFormat === "toml") {
456
459
  if (bytes.byteLength > yqCaps.maxDocumentBytes) throw new YqError("limit", "LIMIT_MAX_DOCUMENT_BYTES", 5);
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  boundedCodec
3
- } from "../safe-bash/command-chunks/chunk-W5DNF4JH.js";
4
- import "../safe-bash/command-chunks/chunk-KJIMDLBB.js";
5
- import "../safe-bash/command-chunks/chunk-5E4WAO4O.js";
3
+ } from "../safe-bash/command-chunks/chunk-LOICUCHG.js";
4
+ import "../safe-bash/command-chunks/chunk-BXCXRYVU.js";
5
+ import "../safe-bash/command-chunks/chunk-JD5QNRNO.js";
6
6
  import "../safe-bash/command-chunks/chunk-QE3VAUMI.js";
7
7
  import "../safe-bash/command-chunks/chunk-2UQSP2CE.js";
8
8
  import "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createCodec
3
- } from "../safe-bash/command-chunks/chunk-KJIMDLBB.js";
4
- import "../safe-bash/command-chunks/chunk-5E4WAO4O.js";
3
+ } from "../safe-bash/command-chunks/chunk-BXCXRYVU.js";
4
+ import "../safe-bash/command-chunks/chunk-JD5QNRNO.js";
5
5
  import "../safe-bash/command-chunks/chunk-QE3VAUMI.js";
6
6
  import "../safe-bash/command-chunks/chunk-2UQSP2CE.js";
7
7
  import "../safe-bash/command-chunks/chunk-HX3SHTCE.js";