@poe-platform/safe-bash 0.1.501 → 0.1.503

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 (112) hide show
  1. package/dist/safe-bash/commands/apply-patch/apply.d.ts.map +1 -1
  2. package/dist/safe-bash/commands/apply-patch/apply.js +5 -2
  3. package/dist/safe-bash/commands/apply-patch/apply.js.map +1 -1
  4. package/dist/safe-bash/commands/archive/extract.d.ts.map +1 -1
  5. package/dist/safe-bash/commands/archive/extract.js +5 -2
  6. package/dist/safe-bash/commands/archive/extract.js.map +1 -1
  7. package/dist/safe-bash/commands/archive/internal.d.ts.map +1 -1
  8. package/dist/safe-bash/commands/archive/internal.js +6 -2
  9. package/dist/safe-bash/commands/archive/internal.js.map +1 -1
  10. package/dist/safe-bash/commands/bytes/compression/files.d.ts.map +1 -1
  11. package/dist/safe-bash/commands/bytes/compression/files.js +10 -6
  12. package/dist/safe-bash/commands/bytes/compression/files.js.map +1 -1
  13. package/dist/safe-bash/commands/diff-patch/diff.d.ts.map +1 -1
  14. package/dist/safe-bash/commands/diff-patch/diff.js +4 -3
  15. package/dist/safe-bash/commands/diff-patch/diff.js.map +1 -1
  16. package/dist/safe-bash/commands/diff-patch/shared.d.ts.map +1 -1
  17. package/dist/safe-bash/commands/diff-patch/shared.js +5 -3
  18. package/dist/safe-bash/commands/diff-patch/shared.js.map +1 -1
  19. package/dist/safe-bash/commands/du/du.d.ts.map +1 -1
  20. package/dist/safe-bash/commands/du/du.js +6 -6
  21. package/dist/safe-bash/commands/du/du.js.map +1 -1
  22. package/dist/safe-bash/commands/file/index.d.ts.map +1 -1
  23. package/dist/safe-bash/commands/file/index.js +9 -3
  24. package/dist/safe-bash/commands/file/index.js.map +1 -1
  25. package/dist/safe-bash/commands/filesystem-requirements.d.ts.map +1 -1
  26. package/dist/safe-bash/commands/filesystem-requirements.js +1 -0
  27. package/dist/safe-bash/commands/filesystem-requirements.js.map +1 -1
  28. package/dist/safe-bash/commands/filesystem.d.ts.map +1 -1
  29. package/dist/safe-bash/commands/filesystem.js +54 -10
  30. package/dist/safe-bash/commands/filesystem.js.map +1 -1
  31. package/dist/safe-bash/commands/find.js +1 -1
  32. package/dist/safe-bash/commands/find.js.map +1 -1
  33. package/dist/safe-bash/commands/html-to-markdown/input.d.ts.map +1 -1
  34. package/dist/safe-bash/commands/html-to-markdown/input.js +12 -18
  35. package/dist/safe-bash/commands/html-to-markdown/input.js.map +1 -1
  36. package/dist/safe-bash/commands/internal.d.ts +1 -1
  37. package/dist/safe-bash/commands/internal.d.ts.map +1 -1
  38. package/dist/safe-bash/commands/internal.js +3 -2
  39. package/dist/safe-bash/commands/internal.js.map +1 -1
  40. package/dist/safe-bash/commands/metadata/internal.d.ts +2 -2
  41. package/dist/safe-bash/commands/metadata/internal.d.ts.map +1 -1
  42. package/dist/safe-bash/commands/metadata/internal.js +1 -1
  43. package/dist/safe-bash/commands/metadata/internal.js.map +1 -1
  44. package/dist/safe-bash/commands/metadata/mktemp.d.ts.map +1 -1
  45. package/dist/safe-bash/commands/metadata/mktemp.js +5 -2
  46. package/dist/safe-bash/commands/metadata/mktemp.js.map +1 -1
  47. package/dist/safe-bash/commands/metadata/stat.js +1 -1
  48. package/dist/safe-bash/commands/metadata/stat.js.map +1 -1
  49. package/dist/safe-bash/commands/move.d.ts.map +1 -1
  50. package/dist/safe-bash/commands/move.js +3 -2
  51. package/dist/safe-bash/commands/move.js.map +1 -1
  52. package/dist/safe-bash/commands/network/body.d.ts.map +1 -1
  53. package/dist/safe-bash/commands/network/body.js +3 -1
  54. package/dist/safe-bash/commands/network/body.js.map +1 -1
  55. package/dist/safe-bash/commands/predicates.d.ts.map +1 -1
  56. package/dist/safe-bash/commands/predicates.js +8 -2
  57. package/dist/safe-bash/commands/predicates.js.map +1 -1
  58. package/dist/safe-bash/commands/safejs/index.d.ts.map +1 -1
  59. package/dist/safe-bash/commands/safejs/index.js +2 -1
  60. package/dist/safe-bash/commands/safejs/index.js.map +1 -1
  61. package/dist/safe-bash/commands/split/io.d.ts.map +1 -1
  62. package/dist/safe-bash/commands/split/io.js +2 -1
  63. package/dist/safe-bash/commands/split/io.js.map +1 -1
  64. package/dist/safe-bash/commands/split/split.d.ts.map +1 -1
  65. package/dist/safe-bash/commands/split/split.js +2 -1
  66. package/dist/safe-bash/commands/split/split.js.map +1 -1
  67. package/dist/safe-bash/commands/stream-format/shared.d.ts.map +1 -1
  68. package/dist/safe-bash/commands/stream-format/shared.js +7 -4
  69. package/dist/safe-bash/commands/stream-format/shared.js.map +1 -1
  70. package/dist/safe-bash/commands/stream-inspection/shared.d.ts.map +1 -1
  71. package/dist/safe-bash/commands/stream-inspection/shared.js +7 -4
  72. package/dist/safe-bash/commands/stream-inspection/shared.js.map +1 -1
  73. package/dist/safe-bash/commands/streams.d.ts.map +1 -1
  74. package/dist/safe-bash/commands/streams.js +4 -2
  75. package/dist/safe-bash/commands/streams.js.map +1 -1
  76. package/dist/safe-bash/commands/structured/jq.d.ts.map +1 -1
  77. package/dist/safe-bash/commands/structured/jq.js +15 -5
  78. package/dist/safe-bash/commands/structured/jq.js.map +1 -1
  79. package/dist/safe-bash/commands/table-text/internal.d.ts.map +1 -1
  80. package/dist/safe-bash/commands/table-text/internal.js +5 -4
  81. package/dist/safe-bash/commands/table-text/internal.js.map +1 -1
  82. package/dist/safe-bash/commands/text-programs/awk-runtime.d.ts.map +1 -1
  83. package/dist/safe-bash/commands/text-programs/awk-runtime.js +10 -4
  84. package/dist/safe-bash/commands/text-programs/awk-runtime.js.map +1 -1
  85. package/dist/safe-bash/commands/text.d.ts.map +1 -1
  86. package/dist/safe-bash/commands/text.js +3 -2
  87. package/dist/safe-bash/commands/text.js.map +1 -1
  88. package/dist/safe-bash/commands/time-env/date.d.ts.map +1 -1
  89. package/dist/safe-bash/commands/time-env/date.js +3 -2
  90. package/dist/safe-bash/commands/time-env/date.js.map +1 -1
  91. package/dist/safe-bash/commands/tree/tree.d.ts.map +1 -1
  92. package/dist/safe-bash/commands/tree/tree.js +2 -1
  93. package/dist/safe-bash/commands/tree/tree.js.map +1 -1
  94. package/dist/safe-bash/contracts/filesystem.d.ts +1 -1
  95. package/dist/safe-bash/contracts/filesystem.d.ts.map +1 -1
  96. package/dist/safe-bash/core.browser.js +259 -119
  97. package/dist/safe-bash/core.browser.js.map +4 -4
  98. package/dist/safe-bash/shell/conditional.d.ts.map +1 -1
  99. package/dist/safe-bash/shell/conditional.js +10 -6
  100. package/dist/safe-bash/shell/conditional.js.map +1 -1
  101. package/dist/safe-bash/shell/input.d.ts +1 -1
  102. package/dist/safe-bash/shell/input.d.ts.map +1 -1
  103. package/dist/safe-bash/shell/input.js +7 -3
  104. package/dist/safe-bash/shell/input.js.map +1 -1
  105. package/dist/safe-bash/shell/runtime.d.ts +2 -1
  106. package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
  107. package/dist/safe-bash/shell/runtime.js +37 -28
  108. package/dist/safe-bash/shell/runtime.js.map +1 -1
  109. package/dist/safe-bash/shell/shell.d.ts.map +1 -1
  110. package/dist/safe-bash/shell/shell.js +3 -1
  111. package/dist/safe-bash/shell/shell.js.map +1 -1
  112. package/package.json +2 -2
@@ -4962,7 +4962,8 @@ async function* input(context2, name2 = "-") {
4962
4962
  } else {
4963
4963
  await assertInputRequirements(context2, [name2]);
4964
4964
  const path = pathOf(context2, name2);
4965
- if (context2.fs.readStream && context2.fs.capabilities.streamingRead !== false) {
4965
+ const capabilities = await context2.fs.capabilitiesFor?.(path, { signal: context2.signal }) ?? context2.fs.capabilities;
4966
+ if (context2.fs.readStream && capabilities.streamingRead !== false) {
4966
4967
  let emitted = false;
4967
4968
  let reading = true;
4968
4969
  try {
@@ -4978,7 +4979,7 @@ async function* input(context2, name2 = "-") {
4978
4979
  if (!reading || emitted || !(error instanceof FsError) || error.code !== "ENOTSUP") throw error;
4979
4980
  }
4980
4981
  }
4981
- if (context2.fs.capabilities.read === false) throw new FsError("ENOTSUP", { syscall: "readFile", path });
4982
+ if (capabilities.read === false) throw new FsError("ENOTSUP", { syscall: "readFile", path });
4982
4983
  yield* readBytes2({
4983
4984
  async *[Symbol.asyncIterator]() {
4984
4985
  const bytes3 = await context2.fs.readFile(path, { signal: context2.signal, maxBytes: bufferLimit });
@@ -5381,6 +5382,7 @@ var filesystemCommandRequirements = {
5381
5382
  ],
5382
5383
  mv: [
5383
5384
  { id: "rename", description: "Rename files or directories", capabilities: ["stat", "rename"], mutates: true },
5385
+ { id: "no-replace", description: "Atomically preserve an existing destination (-n)", capabilities: ["stat", "rename", "atomicRenameNoReplace"], mutates: true },
5384
5386
  { id: "cross-source", description: "Remove file sources after an existing cross-device transfer", capabilities: ["stat", "remove"], mutates: true },
5385
5387
  { id: "cross-directory-source", description: "Traverse and remove cross-device source directories", capabilities: ["stat", "readdir", "removeDirectory"], mutates: true },
5386
5388
  { id: "cross-link-source", description: "Inspect and remove cross-device source links", capabilities: ["stat", "readlink", "remove"], mutates: true },
@@ -5559,8 +5561,9 @@ async function moveAcrossDevices(context2, source2, target, noClobber, budget) {
5559
5561
  for (const entry of [...plan].reverse()) {
5560
5562
  context2.signal.throwIfAborted();
5561
5563
  if (entry.stat.type !== "symlink") {
5562
- if (context2.fs.capabilities.permissions === true && context2.fs.chmod) await context2.fs.chmod(entry.target, entry.stat.mode & 4095, { signal: context2.signal });
5563
- if (context2.fs.capabilities.timestamps === true && context2.fs.utimes) {
5564
+ const capabilities = await context2.fs.capabilitiesFor?.(entry.target, { signal: context2.signal }) ?? context2.fs.capabilities;
5565
+ if (capabilities.permissions === true && context2.fs.chmod) await context2.fs.chmod(entry.target, entry.stat.mode & 4095, { signal: context2.signal });
5566
+ if (capabilities.timestamps === true && context2.fs.utimes) {
5564
5567
  try {
5565
5568
  await context2.fs.utimes(entry.target, entry.stat.atimeMs, entry.stat.mtimeMs, { signal: context2.signal });
5566
5569
  } catch (error) {
@@ -5627,6 +5630,23 @@ async function maybeStat(context2, path, follow = true) {
5627
5630
  throw error;
5628
5631
  }
5629
5632
  }
5633
+ async function admitNoReplaceRename(context2, target) {
5634
+ let candidate = target;
5635
+ while (true) {
5636
+ try {
5637
+ const capabilities = await context2.fs.capabilitiesFor?.(candidate, { signal: context2.signal }) ?? context2.fs.capabilities;
5638
+ context2.signal.throwIfAborted();
5639
+ if (capabilities.atomicRenameNoReplace !== true) {
5640
+ throw new FsError("ENOTSUP", { syscall: "mv", path: target, message: "atomic no-replace rename is unavailable" });
5641
+ }
5642
+ return;
5643
+ } catch (error) {
5644
+ context2.signal.throwIfAborted();
5645
+ if (codeOf(error) !== "ENOENT" || candidate === "/") throw error;
5646
+ candidate = dirname(candidate);
5647
+ }
5648
+ }
5649
+ }
5630
5650
  async function canonicalMissing(context2, path, mode = "copy") {
5631
5651
  if (mode !== "copy") {
5632
5652
  context2.signal.throwIfAborted();
@@ -5668,6 +5688,8 @@ function needCapability(context2, capability) {
5668
5688
  if (!context2.fs[capability]) throw new FsError("ENOTSUP", { syscall: capability });
5669
5689
  }
5670
5690
  async function admitEmptyDirectory(context2, path, readDirectory) {
5691
+ const stat = await maybeStat(context2, path, false);
5692
+ if (stat && stat.type !== "directory") throw new FsError("ENOTDIR", { syscall: "rmdir", path });
5671
5693
  try {
5672
5694
  await admitFilesystemModes(context2, "rmdir", ["directory"], [path]);
5673
5695
  } catch (error) {
@@ -5746,14 +5768,15 @@ async function copy(context2, source2, target, flags3, readDirectory, top = true
5746
5768
  }
5747
5769
  if (!preflight) await context2.fs.symlink(linkTarget, target, { signal: context2.signal });
5748
5770
  } else {
5749
- await admitFilesystemModes(context2, "cp", ["file", ...flags3.has("f") && targetStat ? ["replace", "exclusive"] : []], [target]);
5771
+ const replace = flags3.has("f") && targetStat !== void 0 && targetStat.type !== "character";
5772
+ await admitFilesystemModes(context2, "cp", ["file", ...replace ? ["replace", "exclusive"] : []], [target]);
5750
5773
  if (targetStat?.type === "directory") throw new FsError("EISDIR", { path: target });
5751
5774
  if (preflight) return;
5752
5775
  try {
5753
5776
  await context2.fs.copyFile(source2, target, { signal: context2.signal });
5754
5777
  } catch (error) {
5755
5778
  context2.signal.throwIfAborted();
5756
- if (!flags3.has("f") || !targetStat || codeOf(error) !== "EACCES") throw error;
5779
+ if (!replace || codeOf(error) !== "EACCES") throw error;
5757
5780
  const existing2 = await maybeStat(context2, target, false);
5758
5781
  if (existing2) {
5759
5782
  const sourceEntry = await context2.fs.lstat(source2, { signal: context2.signal });
@@ -5772,7 +5795,7 @@ async function copy(context2, source2, target, flags3, readDirectory, top = true
5772
5795
  `);
5773
5796
  }
5774
5797
  function modeText(stat) {
5775
- let text3 = stat.type === "directory" ? "d" : stat.type === "symlink" ? "l" : "-";
5798
+ let text3 = stat.type === "directory" ? "d" : stat.type === "symlink" ? "l" : stat.type === "character" ? "c" : "-";
5776
5799
  for (const shift of [6, 3, 0]) {
5777
5800
  const mode = stat.mode >> shift;
5778
5801
  text3 += (mode & 4 ? "r" : "-") + (mode & 2 ? "w" : "-") + (mode & 1 ? "x" : "-");
@@ -5790,17 +5813,23 @@ function filesystemCommands(maxDirectoryEntries) {
5790
5813
  requireOperands(parsed.operands);
5791
5814
  const mode = value(parsed, "m");
5792
5815
  if (mode !== void 0 && !/^[0-7]{1,4}$/u.test(mode)) throw new UsageError(`invalid mode '${mode}' (octal required)`);
5793
- await preflightOperands(context2, parsed.operands, (operand) => admitFilesystemModes(
5794
- context2,
5795
- "mkdir",
5796
- [parsed.flags.has("p") ? "parents" : "directory"],
5797
- [pathOf(context2, operand)]
5798
- ));
5799
- return eachOperand(context2, parsed.operands, async (operand) => {
5800
- await context2.fs.mkdir(pathOf(context2, operand), { recursive: parsed.flags.has("p"), ...mode === void 0 ? {} : { mode: parseInt(mode, 8) }, signal: context2.signal });
5801
- if (parsed.flags.has("v")) await output(context2, `mkdir: created directory '${escapeText(operand, "display")}'
5816
+ const createDirectory = async (operand, preflight) => {
5817
+ const path = pathOf(context2, operand);
5818
+ const recursive = parsed.flags.has("p");
5819
+ const stat = await maybeStat(context2, path, recursive);
5820
+ if (stat) {
5821
+ if (recursive && stat.type === "directory") return;
5822
+ throw new FsError("EEXIST", { syscall: "mkdir", path });
5823
+ }
5824
+ await admitFilesystemModes(context2, "mkdir", [recursive ? "parents" : "directory"], [path]);
5825
+ if (!preflight) {
5826
+ await context2.fs.mkdir(path, { recursive, ...mode === void 0 ? {} : { mode: parseInt(mode, 8) }, signal: context2.signal });
5827
+ if (parsed.flags.has("v")) await output(context2, `mkdir: created directory '${escapeText(operand, "display")}'
5802
5828
  `);
5803
- });
5829
+ }
5830
+ };
5831
+ await preflightOperands(context2, parsed.operands, (operand) => createDirectory(operand, true));
5832
+ return eachOperand(context2, parsed.operands, (operand) => createDirectory(operand, false));
5804
5833
  }),
5805
5834
  define("touch", async (context2) => {
5806
5835
  const parsed = options2(context2.args, "camr:", { "no-create": "c", reference: "r" });
@@ -5868,15 +5897,21 @@ function filesystemCommands(maxDirectoryEntries) {
5868
5897
  const target = destination2.directory ? joinPath(destination2.target, basename(source2)) : destination2.target;
5869
5898
  if (parsed.flags.has("n") && await maybeStat(context2, target, false)) return;
5870
5899
  await admitFilesystemModes(context2, "mv", ["rename"], [source2, target]);
5900
+ if (parsed.flags.has("n")) await admitNoReplaceRename(context2, target);
5871
5901
  });
5872
5902
  return eachOperand(context2, destination2.sources, async (operand) => {
5873
5903
  const source2 = pathOf(context2, operand);
5874
5904
  const target = destination2.directory ? joinPath(destination2.target, basename(source2)) : destination2.target;
5875
5905
  if (parsed.flags.has("n") && await maybeStat(context2, target, false)) return;
5906
+ if (parsed.flags.has("n")) await admitNoReplaceRename(context2, target);
5876
5907
  try {
5877
- await context2.fs.rename(source2, target, { signal: context2.signal });
5908
+ await context2.fs.rename(source2, target, { signal: context2.signal, ...parsed.flags.has("n") ? { noReplace: true } : {} });
5878
5909
  } catch (error) {
5879
5910
  context2.signal.throwIfAborted();
5911
+ if (parsed.flags.has("n")) {
5912
+ if (codeOf(error) === "EEXIST") return;
5913
+ throw error;
5914
+ }
5880
5915
  if (codeOf(error) !== "EXDEV") throw error;
5881
5916
  if (!await moveAcrossDevices(context2, source2, target, parsed.flags.has("n"), budget)) {
5882
5917
  if (!parsed.flags.has("n")) throw new FsError("EINVAL", { path: source2, dest: target, message: "source and destination are the same file" });
@@ -7170,8 +7205,15 @@ function streamCommands(maxTeeTargets = 64, maxTailFollowHandles = 64) {
7170
7205
  try {
7171
7206
  for (const operand of parsed.operands) {
7172
7207
  try {
7173
- assertCommandRequirements(context2, teeRequirements, [parsed.flags.has("a") ? "append" : "overwrite"]);
7174
- targets.add(await openFileOutput(context2, pathOf(context2, operand), parsed.flags.has("a") ? "a" : "w"));
7208
+ const path = pathOf(context2, operand);
7209
+ const capabilities = await context2.fs.capabilitiesFor?.(path, { signal: context2.signal }) ?? context2.fs.capabilities;
7210
+ assertCommandRequirements(
7211
+ context2,
7212
+ teeRequirements,
7213
+ [parsed.flags.has("a") ? "append" : "overwrite"],
7214
+ context2.fs.capabilities.readOnly === true ? { ...capabilities, readOnly: true } : capabilities
7215
+ );
7216
+ targets.add(await openFileOutput(context2, path, parsed.flags.has("a") ? "a" : "w"));
7175
7217
  } catch (error) {
7176
7218
  context2.signal.throwIfAborted();
7177
7219
  await diagnostic(context2, error);
@@ -7526,9 +7568,10 @@ async function emitRecords(context2, records4, destination2) {
7526
7568
  return;
7527
7569
  }
7528
7570
  await admitTextOutput(context2, destination2);
7529
- if (context2.fs.writeStream && context2.fs.capabilities.streamingWrite !== false) await context2.fs.writeStream(pathOf(context2, destination2), records4, { signal: context2.signal });
7571
+ const capabilities = await context2.fs.capabilitiesFor?.(pathOf(context2, destination2), { signal: context2.signal }) ?? context2.fs.capabilities;
7572
+ if (context2.fs.writeStream && capabilities.streamingWrite !== false) await context2.fs.writeStream(pathOf(context2, destination2), records4, { signal: context2.signal });
7530
7573
  else {
7531
- if (context2.fs.capabilities.write === false) throw new FsError("ENOTSUP", { syscall: "writeFile", path: pathOf(context2, destination2) });
7574
+ if (capabilities.write === false) throw new FsError("ENOTSUP", { syscall: "writeFile", path: pathOf(context2, destination2) });
7532
7575
  let size = 0;
7533
7576
  const chunks = [];
7534
7577
  for await (const bytes3 of records4) {
@@ -7901,7 +7944,7 @@ function predicateCommands() {
7901
7944
  if (!args.length) return { exitCode: 1 };
7902
7945
  if (args.length === 1) return { exitCode: args[0] ? 0 : 1 };
7903
7946
  if (args.length === 2 && args[0] === "!") return { exitCode: args[1] ? 1 : 0 };
7904
- const unary2 = /* @__PURE__ */ new Set(["-n", "-z", "-e", "-a", "-f", "-d", "-L", "-h", "-s", "-r", "-w", "-x"]);
7947
+ const unary2 = /* @__PURE__ */ new Set(["-n", "-z", "-e", "-a", "-f", "-c", "-d", "-L", "-h", "-s", "-r", "-w", "-x"]);
7905
7948
  const binary3 = /* @__PURE__ */ new Set(["=", "==", "!=", "<", ">", "-eq", "-ne", "-lt", "-le", "-gt", "-ge", "-nt", "-ot", "-ef"]);
7906
7949
  let offset = 0;
7907
7950
  const number4 = (text3) => {
@@ -7936,7 +7979,9 @@ function predicateCommands() {
7936
7979
  const rightStat = await metadata(context2, right);
7937
7980
  if (operator === "-nt") return leftStat !== void 0 && (!rightStat || leftStat.mtimeMs > rightStat.mtimeMs);
7938
7981
  if (operator === "-ot") return rightStat !== void 0 && (!leftStat || leftStat.mtimeMs < rightStat.mtimeMs);
7939
- return leftStat?.ino !== void 0 && rightStat?.ino !== void 0 && leftStat.ino === rightStat.ino && leftStat.dev === rightStat.dev;
7982
+ const identity2 = compareCopyIdentity(leftStat, rightStat);
7983
+ if (identity2 !== "unknown") return identity2 === "same";
7984
+ return leftStat?.ino !== void 0 && rightStat?.ino !== void 0 && leftStat.type === rightStat.type && leftStat.ino === rightStat.ino && leftStat.dev === rightStat.dev;
7940
7985
  }
7941
7986
  const leftNumber = number4(token);
7942
7987
  const rightNumber = number4(right);
@@ -7974,6 +8019,7 @@ function predicateCommands() {
7974
8019
  const stat = await metadata(context2, operand, token === "-L" || token === "-h");
7975
8020
  if (!stat) return false;
7976
8021
  if (token === "-f") return stat.type === "file";
8022
+ if (token === "-c") return stat.type === "character";
7977
8023
  if (token === "-d") return stat.type === "directory";
7978
8024
  if (token === "-L" || token === "-h") return stat.type === "symlink";
7979
8025
  if (token === "-s") return stat.size > 0;
@@ -8924,7 +8970,7 @@ function findCommands(execute5, maxDirectoryEntries) {
8924
8970
  };
8925
8971
  }
8926
8972
  if (token === "-type") {
8927
- const types = { f: "file", d: "directory", l: "symlink" };
8973
+ const types = { f: "file", d: "directory", l: "symlink", c: "character" };
8928
8974
  if (!types[operand]) throw new UsageError(`unsupported file type '${operand}'`);
8929
8975
  return async (entry) => entry.stat.type === types[operand];
8930
8976
  }
@@ -11711,8 +11757,14 @@ var AwkRuntime = class {
11711
11757
  const useStdin = file === "-";
11712
11758
  const source2 = (async function* () {
11713
11759
  if (useStdin) yield* context2.stdin;
11714
- else if (context2.fs.readStream) yield* context2.fs.readStream(name2, { signal: context2.signal });
11715
- else yield await context2.fs.readFile(name2, { signal: context2.signal, maxBytes: budget.maxBufferBytes });
11760
+ else {
11761
+ budget.step();
11762
+ await budget.checkpoint();
11763
+ const capabilities = await context2.fs.capabilitiesFor?.(name2, { signal: context2.signal }) ?? context2.fs.capabilities;
11764
+ context2.signal.throwIfAborted();
11765
+ if (context2.fs.readStream && capabilities.streamingRead !== false) yield* context2.fs.readStream(name2, { signal: context2.signal });
11766
+ else yield await context2.fs.readFile(name2, { signal: context2.signal, maxBytes: budget.maxBufferBytes });
11767
+ }
11716
11768
  })();
11717
11769
  try {
11718
11770
  reader = new Reader(source2, budget, this.retention);
@@ -14338,10 +14390,12 @@ function argumentsFor(args, budget) {
14338
14390
  return options3;
14339
14391
  }
14340
14392
  async function readProgram2(context2, path, limits) {
14341
- const absolute = resolvePath(context2.cwd, path);
14393
+ const absolute = pathOf(context2, path);
14342
14394
  const chunks = [];
14343
14395
  let size = 0;
14344
- if (context2.fs.readStream) {
14396
+ const capabilities = context2.fs.capabilitiesFor ? await interruptible(() => context2.fs.capabilitiesFor(absolute, { signal: context2.signal }), context2.signal) : context2.fs.capabilities;
14397
+ context2.signal.throwIfAborted();
14398
+ if (context2.fs.readStream && capabilities.streamingRead !== false) {
14345
14399
  for await (const chunk of readBytes2(context2.fs.readStream(absolute, { signal: context2.signal }), context2.signal)) {
14346
14400
  size += chunk.byteLength;
14347
14401
  if (size > limits.maxSourceBytes) throw new JqLimitError("maxSourceBytes");
@@ -14368,9 +14422,12 @@ async function* inputSources(context2, options3, budget) {
14368
14422
  usedStdin = true;
14369
14423
  source2 = context2.stdin;
14370
14424
  } else {
14371
- const absolute = resolvePath(context2.cwd, file);
14425
+ const absolute = pathOf(context2, file);
14372
14426
  const remaining = budget.limits.maxInputBytes - budget.inputBytes;
14373
- if (context2.fs.readStream) source2 = context2.fs.readStream(absolute, { signal: context2.signal });
14427
+ await budget.tick();
14428
+ const capabilities = context2.fs.capabilitiesFor ? await interruptible(() => context2.fs.capabilitiesFor(absolute, { signal: context2.signal }), context2.signal) : context2.fs.capabilities;
14429
+ context2.signal.throwIfAborted();
14430
+ if (context2.fs.readStream && capabilities.streamingRead !== false) source2 = context2.fs.readStream(absolute, { signal: context2.signal });
14374
14431
  else source2 = toByteSource(await interruptible(() => context2.fs.readFile(absolute, { signal: context2.signal, maxBytes: remaining }), context2.signal));
14375
14432
  }
14376
14433
  budget.inputLocation = { name: file === "-" ? "<stdin>" : file, line: 0, complete: false };
@@ -21010,10 +21067,11 @@ async function planOperands(context2, options3) {
21010
21067
  continue;
21011
21068
  }
21012
21069
  if (!name2) throw new FsError("ENOENT", { path: name2 });
21013
- if (!context2.fs.readStream || context2.fs.capabilities.streamingRead === false) {
21070
+ const source2 = pathOf(context2, name2);
21071
+ const sourceCapabilities = await context2.fs.capabilitiesFor?.(source2, { signal: context2.signal }) ?? context2.fs.capabilities;
21072
+ if (!context2.fs.readStream || sourceCapabilities.streamingRead === false) {
21014
21073
  throw new FsError("ENOTSUP", { message: "named input requires VFS streaming reads; no readFile fallback" });
21015
21074
  }
21016
- const source2 = pathOf(context2, name2);
21017
21075
  const sourceStat = await context2.fs.lstat(source2, { signal: context2.signal });
21018
21076
  if (sourceStat.type !== "file") throw new FsError("EINVAL", { path: source2, message: "input must be a regular, non-symlink file" });
21019
21077
  const realSource = await context2.fs.realpath(source2, { signal: context2.signal });
@@ -21024,20 +21082,22 @@ async function planOperands(context2, options3) {
21024
21082
  if (context2.fs.capabilities.readOnly === true) {
21025
21083
  throw new FsError("EROFS", { syscall: context2.command, path: realSource });
21026
21084
  }
21027
- if (!context2.fs.writeStream || context2.fs.capabilities.streamingWrite === false) {
21028
- throw new FsError("ENOTSUP", { message: "file output requires VFS streaming writes (use -c for stdout)" });
21029
- }
21030
21085
  if (!options3.keep && !options3.force && (sourceStat.nlink ?? 1) > 1) {
21031
21086
  throw new FsError("EINVAL", { path: source2, message: "input has multiple links (use -k or -f)" });
21032
21087
  }
21033
21088
  const destination2 = outputPath(realSource, options3);
21089
+ const capabilities = await context2.fs.capabilitiesFor?.(destination2, { signal: context2.signal }) ?? context2.fs.capabilities;
21090
+ if (capabilities.readOnly === true) throw new FsError("EROFS", { syscall: context2.command, path: destination2 });
21091
+ if (!context2.fs.writeStream || capabilities.streamingWrite === false) {
21092
+ throw new FsError("ENOTSUP", { message: "file output requires VFS streaming writes (use -c for stdout)" });
21093
+ }
21034
21094
  const destinationStat = await existing(context2, destination2);
21035
21095
  if (destinationStat) {
21036
21096
  if (destinationStat.type !== "file" || sameIdentity(sourceStat, destinationStat) || realSource === await context2.fs.realpath(destination2, { signal: context2.signal })) {
21037
21097
  throw new FsError("EINVAL", { path: destination2, message: "destination is not a distinct regular file" });
21038
21098
  }
21039
21099
  if (!options3.force) throw new FsError("EEXIST", { path: destination2 });
21040
- if (context2.fs.capabilities.atomicRename !== true) {
21100
+ if (capabilities.atomicRename !== true) {
21041
21101
  throw new FsError("ENOTSUP", { path: destination2, message: "forced replacement requires VFS atomicRename" });
21042
21102
  }
21043
21103
  }
@@ -21370,7 +21430,8 @@ var Budget11 = class {
21370
21430
  async read(path) {
21371
21431
  this.context.signal.throwIfAborted();
21372
21432
  const remaining = this.limits.maxInputBytes - this.inputBytes;
21373
- const bytes3 = path === "-" ? await collectBytes2(this.chunks(this.context.stdin), { signal: this.context.signal, maxBytes: remaining }) : this.context.fs.readStream ? await collectBytes2(this.chunks(this.context.fs.readStream(path, { signal: this.context.signal })), { signal: this.context.signal, maxBytes: remaining }) : await host(this.context, () => this.context.fs.readFile(path, { signal: this.context.signal, maxBytes: remaining }));
21433
+ const capabilities = path === "-" ? void 0 : await host(this.context, async () => await this.context.fs.capabilitiesFor?.(path, { signal: this.context.signal }) ?? this.context.fs.capabilities);
21434
+ const bytes3 = path === "-" ? await collectBytes2(this.chunks(this.context.stdin), { signal: this.context.signal, maxBytes: remaining }) : this.context.fs.readStream && capabilities?.streamingRead !== false ? await collectBytes2(this.chunks(this.context.fs.readStream(path, { signal: this.context.signal })), { signal: this.context.signal, maxBytes: remaining }) : await host(this.context, () => this.context.fs.readFile(path, { signal: this.context.signal, maxBytes: remaining }));
21374
21435
  this.inputBytes += bytes3.byteLength;
21375
21436
  if (this.inputBytes > this.limits.maxInputBytes) throw new ToolError("input byte limit exceeded");
21376
21437
  return this.text(bytes3);
@@ -21405,7 +21466,7 @@ async function host(context2, operation2) {
21405
21466
  async function inspect(budget, path) {
21406
21467
  const context2 = budget.context;
21407
21468
  if (path.length > 4096) throw new ToolError("path length limit exceeded");
21408
- const absolute = resolvePath(context2.cwd, path);
21469
+ const absolute = pathOf(context2, path);
21409
21470
  const parts2 = absolute.split("/").filter(Boolean);
21410
21471
  if (absolute.length > 4096 || parts2.length > 256) throw new ToolError("path length/depth limit exceeded");
21411
21472
  let current = "";
@@ -21794,7 +21855,7 @@ async function run(context2, budget) {
21794
21855
  const names = /* @__PURE__ */ new Set();
21795
21856
  for (const path of [leftStat ? left : void 0, rightStat ? right : void 0]) {
21796
21857
  if (path === void 0) continue;
21797
- const entries3 = await host(context2, () => context2.fs.readdir(resolvePath(context2.cwd, path), { signal: context2.signal }));
21858
+ const entries3 = await host(context2, () => context2.fs.readdir(pathOf(context2, path), { signal: context2.signal }));
21798
21859
  for (const entry of entries3) {
21799
21860
  budget.step();
21800
21861
  if (!entry.name || entry.name === "." || entry.name === ".." || /[\/\\\0\r\n\t]/u.test(entry.name)) throw new ToolError("unsafe directory entry name");
@@ -21808,7 +21869,7 @@ async function run(context2, budget) {
21808
21869
  const read = async (path, exists) => {
21809
21870
  if (!exists) return "";
21810
21871
  if (path === "-") return stdin ??= await budget.read("-");
21811
- return budget.read(resolvePath(context2.cwd, path));
21872
+ return budget.read(pathOf(context2, path));
21812
21873
  };
21813
21874
  const oldText = await read(left, !!leftStat);
21814
21875
  const newText = await read(right, !!rightStat);
@@ -23070,7 +23131,7 @@ function metadataCommand(name2, handler) {
23070
23131
  } };
23071
23132
  }
23072
23133
  function permissionString(mode, type2) {
23073
- let text3 = type2 === "directory" ? "d" : type2 === "symlink" ? "l" : "-";
23134
+ let text3 = type2 === "directory" ? "d" : type2 === "symlink" ? "l" : type2 === "character" ? "c" : "-";
23074
23135
  for (const [read, write2, execute5, special2, lower, upper] of [
23075
23136
  [256, 128, 64, 2048, "s", "S"],
23076
23137
  [32, 16, 8, 1024, "s", "S"],
@@ -23390,7 +23451,7 @@ async function render(context2, path, name2, stat, format2, escapes, limit) {
23390
23451
  }
23391
23452
  } else if (code === "%") text3 = "%";
23392
23453
  else if (code === "A") text3 = permissionString(stat.mode, stat.type);
23393
- else if (code === "F") text3 = stat.type === "directory" ? "directory" : stat.type === "symlink" ? "symbolic link" : stat.size === 0 ? "regular empty file" : "regular file";
23454
+ else if (code === "F") text3 = stat.type === "directory" ? "directory" : stat.type === "symlink" ? "symbolic link" : stat.type === "character" ? "character special file" : stat.size === 0 ? "regular empty file" : "regular file";
23394
23455
  else if (["x", "y", "z", "w"].includes(code)) {
23395
23456
  const value2 = times[code.toUpperCase()];
23396
23457
  text3 = code === "w" && value2 === void 0 ? "-" : timestamp2(available(value2, code));
@@ -23515,7 +23576,6 @@ function createMktempCommand(configuration = {}) {
23515
23576
  try {
23516
23577
  if (!parsed.dryRun) {
23517
23578
  if (context2.fs.capabilities.readOnly) throw new FsError("EROFS", { syscall: "mktemp" });
23518
- if (context2.fs.capabilities.permissions !== true) throw new FsError("ENOTSUP", { syscall: "mktemp", message: "private temporary creation requires declared permission support" });
23519
23579
  }
23520
23580
  for (let attempt = 0; attempt < configured.limits.maxAttempts; attempt++) {
23521
23581
  await budget.step();
@@ -23534,6 +23594,9 @@ function createMktempCommand(configuration = {}) {
23534
23594
  if (codeOf(error) !== "ENOENT") throw error;
23535
23595
  }
23536
23596
  } else {
23597
+ const capabilities = await context2.fs.capabilitiesFor?.(path, { signal: context2.signal }) ?? context2.fs.capabilities;
23598
+ if (capabilities.readOnly === true) throw new FsError("EROFS", { syscall: "mktemp" });
23599
+ if (capabilities.permissions !== true) throw new FsError("ENOTSUP", { syscall: "mktemp", message: "private temporary creation requires declared permission support" });
23537
23600
  try {
23538
23601
  const mode = (parsed.directory ? 448 : 384) & ~configured.umask;
23539
23602
  if (parsed.directory) await context2.fs.mkdir(path, { mode, recursive: false, signal: context2.signal });
@@ -23714,7 +23777,9 @@ async function* bounded(source2, maximum, signal, chunkSize2) {
23714
23777
  }
23715
23778
  async function* fileSource(context2, path, limits) {
23716
23779
  context2.signal.throwIfAborted();
23717
- if (context2.fs.readStream) {
23780
+ const capabilities = await operation(context2, () => context2.fs.capabilitiesFor?.(path, { signal: context2.signal }) ?? context2.fs.capabilities);
23781
+ context2.signal.throwIfAborted();
23782
+ if (context2.fs.readStream && capabilities.streamingRead !== false) {
23718
23783
  yield* readBytes2(context2.fs.readStream(path, { signal: context2.signal, chunkSize: limits.chunkSize }), context2.signal);
23719
23784
  } else {
23720
23785
  const stat = await operation(context2, () => context2.fs.stat(path, { signal: context2.signal }));
@@ -23726,7 +23791,9 @@ async function* fileSource(context2, path, limits) {
23726
23791
  }
23727
23792
  async function publish2(context2, path, source2, mode = 384) {
23728
23793
  const options3 = { signal: context2.signal, flag: "wx", mode };
23729
- if (context2.fs.writeStream) {
23794
+ const capabilities = await operation(context2, () => context2.fs.capabilitiesFor?.(path, { signal: context2.signal }) ?? context2.fs.capabilities);
23795
+ context2.signal.throwIfAborted();
23796
+ if (context2.fs.writeStream && capabilities.streamingWrite !== false) {
23730
23797
  let finished = false;
23731
23798
  const observed = (async function* () {
23732
23799
  yield* readBytes2(source2, context2.signal);
@@ -24492,7 +24559,7 @@ async function readArchive(context2, source2, options3, budget) {
24492
24559
  archivePath = await operation(context2, () => context2.fs.realpath(vfsPath(context2.cwd, options3.archive), { signal: context2.signal }));
24493
24560
  archiveStat = await operation(context2, () => context2.fs.stat(archivePath, { signal: context2.signal }));
24494
24561
  }
24495
- if (options3.mode === "x") await checkRoot(context2, resolvePath(options3.cwd));
24562
+ if (options3.mode === "x") await checkRoot(context2, options3.cwd);
24496
24563
  try {
24497
24564
  while (true) {
24498
24565
  const block = await reader.exact(512);
@@ -24553,7 +24620,10 @@ async function readArchive(context2, source2, options3, budget) {
24553
24620
  const operand = options3.operands[index];
24554
24621
  const wanted = operand.name.replace(/^\/+/u, "").replace(/\/+$/u, "");
24555
24622
  if (name2.replace(/\/+$/u, "") === wanted || name2.startsWith(`${wanted}/`)) {
24556
- if (!selected) root = resolvePath(operand.cwd);
24623
+ if (!selected) {
24624
+ if (options3.mode === "x") await checkRoot(context2, operand.cwd);
24625
+ root = resolvePath(operand.cwd);
24626
+ }
24557
24627
  selected = true;
24558
24628
  matched.add(index);
24559
24629
  }
@@ -24864,10 +24934,11 @@ var Inputs = class {
24864
24934
  let source2;
24865
24935
  if (name2 === "-") source2 = this.context.stdin;
24866
24936
  else {
24867
- const path = resolvePath(this.context.cwd, name2);
24937
+ const path = pathOf(this.context, name2);
24868
24938
  const stat = await this.context.fs.stat(path, { signal: this.signal });
24869
24939
  if (stat.type === "directory") throw new FsError("EISDIR", { path });
24870
- if (this.context.fs.readStream) source2 = this.context.fs.readStream(path, { signal: this.signal });
24940
+ const capabilities = await this.context.fs.capabilitiesFor?.(path, { signal: this.signal }) ?? this.context.fs.capabilities;
24941
+ if (this.context.fs.readStream && capabilities.streamingRead !== false) source2 = this.context.fs.readStream(path, { signal: this.signal });
24871
24942
  else {
24872
24943
  const { context: context2, signal, budget } = this;
24873
24944
  source2 = (async function* () {
@@ -25430,11 +25501,14 @@ var Session = class {
25430
25501
  } };
25431
25502
  } else {
25432
25503
  if (!name2) throw new FsError("ENOENT", { path: name2 });
25433
- const path = resolvePath(session.context.cwd, name2);
25504
+ const path = pathOf(session.context, name2);
25434
25505
  const stat = await session.context.fs.stat(path, { signal });
25435
25506
  signal.throwIfAborted();
25436
25507
  if (stat.type === "directory") throw new FsError("EISDIR", { path });
25437
- if (session.context.fs.readStream) yield* session.context.fs.readStream(path, { signal });
25508
+ await session.step();
25509
+ const capabilities = await session.context.fs.capabilitiesFor?.(path, { signal }) ?? session.context.fs.capabilities;
25510
+ signal.throwIfAborted();
25511
+ if (session.context.fs.readStream && capabilities.streamingRead !== false) yield* session.context.fs.readStream(path, { signal });
25438
25512
  else yield await session.context.fs.readFile(path, { signal, maxBytes: Math.min(session.limits.maxChunkBytes, session.limits.maxInputBytes - session.inputBytes) });
25439
25513
  }
25440
25514
  })();
@@ -25937,11 +26011,14 @@ var Session2 = class {
25937
26011
  } };
25938
26012
  } else {
25939
26013
  if (!name2) throw new FsError("ENOENT", { path: name2 });
25940
- const path = resolvePath(session.context.cwd, name2);
26014
+ const path = pathOf(session.context, name2);
25941
26015
  const stat = await session.context.fs.stat(path, { signal });
25942
26016
  signal.throwIfAborted();
25943
26017
  if (stat.type === "directory") throw new FsError("EISDIR", { path });
25944
- if (session.context.fs.readStream) yield* session.context.fs.readStream(path, { signal });
26018
+ await session.step();
26019
+ const capabilities = await session.context.fs.capabilitiesFor?.(path, { signal }) ?? session.context.fs.capabilities;
26020
+ signal.throwIfAborted();
26021
+ if (session.context.fs.readStream && capabilities.streamingRead !== false) yield* session.context.fs.readStream(path, { signal });
25945
26022
  else yield await session.context.fs.readFile(path, { signal, maxBytes: Math.min(session.limits.maxChunkBytes, session.limits.maxInputBytes - session.inputBytes) });
25946
26023
  }
25947
26024
  })();
@@ -26710,7 +26787,8 @@ var Cursor = class {
26710
26787
  if (input3 === "-") yield* readBytes2(context2.stdin, signal);
26711
26788
  else {
26712
26789
  const path = pathOf(context2, input3);
26713
- if (context2.fs.readStream && context2.fs.capabilities.streamingRead !== false) {
26790
+ const capabilities = await interruptible2(() => Promise.resolve(context2.fs.capabilitiesFor?.(path, { signal }) ?? context2.fs.capabilities), signal);
26791
+ if (context2.fs.readStream && capabilities.streamingRead !== false) {
26714
26792
  yield* readBytes2(context2.fs.readStream(path, { signal, chunkSize: limits.maxChunkBytes }), signal);
26715
26793
  } else {
26716
26794
  const maxBytes = Math.min(limits.maxInputBytes, limits.maxBufferBytes);
@@ -26977,7 +27055,8 @@ async function run3(context2, limits) {
26977
27055
  yield chunk;
26978
27056
  }
26979
27057
  })();
26980
- if (context2.fs.writeStream && context2.fs.capabilities.streamingWrite !== false) {
27058
+ const capabilities = await interruptible2(() => Promise.resolve(context2.fs.capabilitiesFor?.(destination2.path, { signal }) ?? context2.fs.capabilities), signal);
27059
+ if (context2.fs.writeStream && capabilities.streamingWrite !== false) {
26981
27060
  await interruptible2(() => context2.fs.writeStream(destination2.path, source2, { signal, flag: destination2.flag }), signal);
26982
27061
  } else {
26983
27062
  const bytes3 = await collectBytes2(source2, { signal, maxBytes: limits.maxBufferBytes });
@@ -27706,7 +27785,7 @@ function createDateCommand(configuration) {
27706
27785
  if (parsed.reference !== void 0) {
27707
27786
  try {
27708
27787
  if (!parsed.reference) throw new FsError("ENOENT", { path: parsed.reference });
27709
- const stat = await context2.fs.stat(resolvePath(context2.cwd, parsed.reference), { signal: context2.signal });
27788
+ const stat = await context2.fs.stat(pathOf(context2, parsed.reference), { signal: context2.signal });
27710
27789
  context2.signal.throwIfAborted();
27711
27790
  instant = millisecondsInstant(stat.mtimeMs);
27712
27791
  } catch (error) {
@@ -28419,7 +28498,7 @@ var Walker2 = class {
28419
28498
  this.budget.text(operand);
28420
28499
  this.budget.entry();
28421
28500
  if (this.args.json && index) await this.write(`,${this.newline()}`);
28422
- const entry = await this.inspect(resolvePath(this.budget.context.cwd, operand), operand, operand);
28501
+ const entry = await this.inspect(pathOf(this.budget.context, operand), operand, operand);
28423
28502
  await this.visit(entry, [], "", true, 0);
28424
28503
  }
28425
28504
  if (this.args.report) {
@@ -28849,10 +28928,11 @@ async function inspect2(context2, name2, follow, describe2, budget, stdinUsed) {
28849
28928
  return result3;
28850
28929
  }
28851
28930
  if (!name2 || name2.includes("\0")) throw new FsError(name2 ? "EINVAL" : "ENOENT", { path: name2 });
28852
- const path = resolvePath(context2.cwd, name2);
28931
+ const path = pathOf(context2, name2);
28853
28932
  const fs = context2.fs;
28854
28933
  const stat = await budget.host(() => follow ? fs.stat(path, { signal: budget.signal }) : fs.lstat(path, { signal: budget.signal }));
28855
28934
  if (stat.type === "directory") return { description: "directory", mime: "inode/directory", encoding: "binary" };
28935
+ if (stat.type === "character") return { description: "character special", mime: "inode/chardevice", encoding: "binary" };
28856
28936
  if (stat.type === "symlink") {
28857
28937
  if (follow) throw new FsError("ENOTSUP", { path, message: "followed stat returned a symbolic link" });
28858
28938
  const target = fs.readlink ? await budget.host(() => fs.readlink(path, { signal: budget.signal })) : void 0;
@@ -28861,7 +28941,8 @@ async function inspect2(context2, name2, follow, describe2, budget, stdinUsed) {
28861
28941
  }
28862
28942
  if (stat.type !== "file") throw new FsError("ENOTSUP", { path, message: "unsupported filesystem entry type" });
28863
28943
  let sample;
28864
- if (fs.readStream) {
28944
+ const capabilities = fs.capabilitiesFor ? await budget.host(() => fs.capabilitiesFor(path, { signal: budget.signal })) : fs.capabilities;
28945
+ if (fs.readStream && capabilities.streamingRead !== false) {
28865
28946
  const controller = new AbortController();
28866
28947
  const signal = AbortSignal.any([budget.signal, controller.signal]);
28867
28948
  try {
@@ -30226,25 +30307,17 @@ var Inputs2 = class {
30226
30307
  if (name2 === "-") source2 = this.context.stdin;
30227
30308
  else {
30228
30309
  const context2 = this.context, budget = this.budget, path = pathOf(context2, name2);
30229
- if (context2.fs.readStream) source2 = context2.fs.readStream(path, { signal: context2.signal, chunkSize: 16384 });
30230
- else {
30231
- let consumed = false;
30232
- source2 = { [Symbol.asyncIterator]() {
30233
- return {
30234
- async next() {
30235
- if (consumed) return { done: true, value: void 0 };
30236
- consumed = true;
30237
- const value2 = await context2.fs.readFile(path, { signal: context2.signal, maxBytes: budget.limits.maxInputBytes - budget.input });
30238
- context2.signal.throwIfAborted();
30239
- return { done: false, value: value2 };
30240
- },
30241
- async return() {
30242
- consumed = true;
30243
- return { done: true, value: void 0 };
30244
- }
30245
- };
30246
- } };
30247
- }
30310
+ source2 = (async function* () {
30311
+ const capabilities = await context2.fs.capabilitiesFor?.(path, { signal: context2.signal }) ?? context2.fs.capabilities;
30312
+ context2.signal.throwIfAborted();
30313
+ if (context2.fs.readStream && capabilities.streamingRead !== false) {
30314
+ yield* readBytes2(context2.fs.readStream(path, { signal: context2.signal, chunkSize: 16384 }), context2.signal);
30315
+ } else {
30316
+ const value2 = await context2.fs.readFile(path, { signal: context2.signal, maxBytes: budget.limits.maxInputBytes - budget.input });
30317
+ context2.signal.throwIfAborted();
30318
+ yield value2;
30319
+ }
30320
+ })();
30248
30321
  }
30249
30322
  const cursor = new Cursor2(source2, this.context.signal);
30250
30323
  this.cursors.push(cursor);
@@ -31249,7 +31322,7 @@ var Walker3 = class {
31249
31322
  let stat;
31250
31323
  try {
31251
31324
  stat = await this.budget.fs(() => context2.fs.lstat(path, { signal: context2.signal }));
31252
- if (!stat || !["file", "directory", "symlink"].includes(stat.type)) throw new PublicDiagnostic("invalid entry type");
31325
+ if (!stat || !["file", "directory", "symlink", "character"].includes(stat.type)) throw new PublicDiagnostic("invalid entry type");
31253
31326
  } catch (error) {
31254
31327
  await this.failure(error, display2);
31255
31328
  return { bytes: 0, complete: false };
@@ -31281,10 +31354,9 @@ var Walker3 = class {
31281
31354
  const { context: context2 } = this.budget;
31282
31355
  this.budget.text(context2.cwd);
31283
31356
  const paths = this.args.operands.map((operand) => {
31284
- const path = resolvePath(context2.cwd, operand);
31285
- const resolved = operand.endsWith("/") && path !== "/" ? path + "/" : path;
31286
- this.budget.text(resolved);
31287
- return resolved;
31357
+ const path = pathOf(context2, operand === "" ? "." : operand);
31358
+ this.budget.text(path);
31359
+ return path;
31288
31360
  });
31289
31361
  for (let index = 0; index < paths.length; index++) {
31290
31362
  const amount = await this.walk(paths[index], this.args.operands[index], 0);
@@ -33095,7 +33167,10 @@ var Invocation2 = class {
33095
33167
  try {
33096
33168
  await this.work.fs(target, () => this.context.fs.access(target, 2, { signal: this.context.signal }));
33097
33169
  } catch (error) {
33098
- if (error instanceof FileFailure2 && (error.error.code === "ENOTSUP" || error.error.code === "EOPNOTSUPP") && this.context.fs.capabilities.permissions !== true) return;
33170
+ if (error instanceof FileFailure2 && (error.error.code === "ENOTSUP" || error.error.code === "EOPNOTSUPP")) {
33171
+ const capabilities = await this.work.fs(target, async () => await this.context.fs.capabilitiesFor?.(target, { signal: this.context.signal }) ?? this.context.fs.capabilities);
33172
+ if (capabilities.permissions !== true) return;
33173
+ }
33099
33174
  throw error;
33100
33175
  }
33101
33176
  }
@@ -33382,6 +33457,7 @@ init_platform();
33382
33457
 
33383
33458
  // packages/safe-bash/src/shell/shell.ts
33384
33459
  init_platform();
33460
+ import { createDeviceFileSystem } from "@poe-platform/safe-fs/core";
33385
33461
 
33386
33462
  // packages/safe-bash/src/shell/env-warning.ts
33387
33463
  init_platform();
@@ -33976,20 +34052,22 @@ async function unary(operator, value2, context2) {
33976
34052
  return context2.present(value2);
33977
34053
  }
33978
34054
  if (operator === "-o") return context2.option(value2);
33979
- if (!["-e", "-a", "-f", "-d", "-s", "-L", "-h", "-r", "-w", "-x"].includes(operator)) unsupported3(operator);
34055
+ if (!["-e", "-a", "-f", "-c", "-d", "-s", "-L", "-h", "-r", "-w", "-x"].includes(operator)) unsupported3(operator);
33980
34056
  if (value2 === "") return false;
33981
34057
  if (/^\/dev\/(?:fd(?:\/|$)|stdin$|stdout$|stderr$)/u.test(value2)) unsupported3("descriptor predicate");
33982
34058
  const access = ["-r", "-w", "-x"].includes(operator);
33983
- if (access && context2.fs.capabilities.permissions !== true) unsupported3("unobservable access permission");
33984
34059
  try {
33985
34060
  if (access) {
33986
- await context2.fs.access(resolvePath(context2.cwd, value2), operator === "-r" ? 4 : operator === "-w" ? 2 : 1, { signal: context2.signal });
34061
+ const capabilities = await context2.fs.capabilitiesFor?.(pathOf(context2, value2), { signal: context2.signal }) ?? context2.fs.capabilities;
34062
+ if (capabilities.permissions !== true) unsupported3("unobservable access permission");
34063
+ await context2.fs.access(pathOf(context2, value2), operator === "-r" ? 4 : operator === "-w" ? 2 : 1, { signal: context2.signal });
33987
34064
  context2.signal.throwIfAborted();
33988
34065
  return true;
33989
34066
  }
33990
- const metadata3 = await (operator === "-L" || operator === "-h" ? context2.fs.lstat(resolvePath(context2.cwd, value2), { signal: context2.signal }) : context2.fs.stat(resolvePath(context2.cwd, value2), { signal: context2.signal }));
34067
+ const metadata3 = await (operator === "-L" || operator === "-h" ? context2.fs.lstat(pathOf(context2, value2), { signal: context2.signal }) : context2.fs.stat(pathOf(context2, value2), { signal: context2.signal }));
33991
34068
  context2.signal.throwIfAborted();
33992
34069
  if (operator === "-f") return metadata3.type === "file";
34070
+ if (operator === "-c") return metadata3.type === "character";
33993
34071
  if (operator === "-d") return metadata3.type === "directory";
33994
34072
  if (operator === "-s") return metadata3.size > 0;
33995
34073
  if (operator === "-L" || operator === "-h") return metadata3.type === "symlink";
@@ -38474,19 +38552,20 @@ var CdLookup = class {
38474
38552
  const rawBytes = absolute ? targetBytes : component.startsWith("/") ? componentBytes + 1 + targetBytes : cwdBytes + 1 + (component ? componentBytes + 1 : 0) + targetBytes;
38475
38553
  if (rawBytes > 65536) throw new PublicDiagnostic("cd: path exceeds 65536 UTF-8 bytes");
38476
38554
  await this.charge(2 * rawBytes);
38477
- const raw = absolute ? target : component.startsWith("/") ? `${component}/${target}` : component ? `${cwd}/${component}/${target}` : `${cwd}/${target}`;
38555
+ const raw = absolute ? target : pathOf({ cwd }, component ? `${component}/${target}` : target);
38478
38556
  const path = resolvePath(cwd, raw);
38557
+ const operand = pathOf({ cwd }, raw);
38479
38558
  await this.scan(path);
38480
38559
  this.signal.throwIfAborted();
38481
38560
  if (++this.probes > 4097) throw new PublicDiagnostic("cd: probe limit exceeded");
38482
38561
  await this.charge(1);
38483
38562
  this.signal.throwIfAborted();
38484
- const stat = await fs.stat(path, { signal: this.signal });
38563
+ const stat = await fs.stat(operand, { signal: this.signal });
38485
38564
  this.signal.throwIfAborted();
38486
38565
  if (stat.type !== "directory") throw new FsError("ENOTDIR", { path });
38487
38566
  await this.charge(1);
38488
38567
  this.signal.throwIfAborted();
38489
- await fs.access(path, ACCESS_MODES.X_OK, { signal: this.signal });
38568
+ await fs.access(operand, ACCESS_MODES.X_OK, { signal: this.signal });
38490
38569
  this.signal.throwIfAborted();
38491
38570
  return path;
38492
38571
  };
@@ -38841,7 +38920,7 @@ var InvocationCancellationOwner = class {
38841
38920
  }
38842
38921
  };
38843
38922
  var Runtime = class _Runtime {
38844
- constructor(fs, commands, middleware, budget, signal = budget.signal, fileWrites = /* @__PURE__ */ new Map(), outputFiles = /* @__PURE__ */ new Map(), commandSignal = signal, cancellation, cancellationState, cancellationOwner, cancellationDepth, cancellationMaxDepth, outcomeFrame = void 0) {
38923
+ constructor(fs, commands, middleware, budget, signal = budget.signal, fileWrites = /* @__PURE__ */ new Map(), outputFiles = /* @__PURE__ */ new Map(), commandSignal = signal, cancellation, cancellationState, cancellationOwner, cancellationDepth, cancellationMaxDepth, outcomeFrame = void 0, inputProfile = fs) {
38845
38924
  this.fs = fs;
38846
38925
  this.commands = commands;
38847
38926
  this.middleware = middleware;
@@ -38856,6 +38935,7 @@ var Runtime = class _Runtime {
38856
38935
  this.cancellationDepth = cancellationDepth;
38857
38936
  this.cancellationMaxDepth = cancellationMaxDepth;
38858
38937
  this.outcomeFrame = outcomeFrame;
38938
+ this.inputProfile = inputProfile;
38859
38939
  this.fs = scopeFileSystem(fs, () => budget.fileSystemOperation(), signal);
38860
38940
  const checkpoint = () => budget.cpuCheckpoint();
38861
38941
  registerYieldCheckpoint(signal, checkpoint);
@@ -38875,6 +38955,7 @@ var Runtime = class _Runtime {
38875
38955
  cancellationDepth;
38876
38956
  cancellationMaxDepth;
38877
38957
  outcomeFrame;
38958
+ inputProfile;
38878
38959
  async ereDiagnostic(io, detail) {
38879
38960
  try {
38880
38961
  await this.diagnostic(io, detail);
@@ -39073,7 +39154,8 @@ var Runtime = class _Runtime {
39073
39154
  owner ?? this.cancellationOwner,
39074
39155
  prepared.owned ? childDepth : this.cancellationDepth,
39075
39156
  this.cancellationMaxDepth,
39076
- frame
39157
+ frame,
39158
+ this.inputProfile
39077
39159
  );
39078
39160
  let captured;
39079
39161
  const executeChild = () => execute5(runtime, scope);
@@ -39616,7 +39698,8 @@ var Runtime = class _Runtime {
39616
39698
  owner,
39617
39699
  childDepth,
39618
39700
  this.cancellationMaxDepth,
39619
- frame
39701
+ frame,
39702
+ this.inputProfile
39620
39703
  );
39621
39704
  const input3 = new ShellInput(incoming?.readable ?? io.stdin, this.budget, signal);
39622
39705
  const pipeOutput = outgoing && { [outputFailure]: outgoing.abort, ownedOutput: outgoing.writable.ownedOutput, write: async (chunk) => {
@@ -40115,13 +40198,13 @@ var Runtime = class _Runtime {
40115
40198
  }
40116
40199
  }
40117
40200
  } else {
40118
- const path = resolvePath(state.cwd, target);
40201
+ const path = pathOf(state, target);
40119
40202
  const options3 = { signal: this.signal };
40120
40203
  if (redirect.operator === "<") {
40121
40204
  await interruptible3(this.fs.access(path, 4, options3), this.signal);
40122
40205
  const stat = await interruptible3(this.fs.stat(path, options3), this.signal);
40123
40206
  if (stat.type === "directory" && !fileShortcut) throw new PublicDiagnostic(`${target}: Is a directory`);
40124
- const source2 = stat.type === "directory" ? toByteSource("") : await fileInput(this.fs, path, this.budget.limits.maxInputBytes, this.signal);
40207
+ const source2 = stat.type === "directory" ? toByteSource("") : await fileInput(this.fs, path, this.budget.limits.maxInputBytes, this.signal, this.inputProfile);
40125
40208
  const input3 = new ShellInput(source2, this.budget, this.signal);
40126
40209
  inputs2.add(input3);
40127
40210
  descriptors.set(redirect.descriptor, { input: input3, stdinIsDefault: false });
@@ -40129,24 +40212,25 @@ var Runtime = class _Runtime {
40129
40212
  const append = redirect.operator === ">>";
40130
40213
  const capabilities = await this.fs.capabilitiesFor?.(path, options3) ?? this.fs.capabilities;
40131
40214
  const random = capabilities.randomAccessWrite === true;
40215
+ const key = resolvePath(state.cwd, path);
40132
40216
  let file;
40133
- await this.fileOperation(path, async () => {
40134
- file = this.outputFiles.get(path) ?? { data: void 0, references: 0 };
40217
+ await this.fileOperation(key, async () => {
40218
+ file = this.outputFiles.get(key) ?? { data: void 0, references: 0 };
40135
40219
  if (!random && file.references) throw new FsError("ENOTSUP", { path, message: "Conflicting sequential output descriptors" });
40136
40220
  file.references++;
40137
- this.outputFiles.set(path, file);
40221
+ this.outputFiles.set(key, file);
40138
40222
  });
40139
40223
  let closed = false;
40140
40224
  let offset = 0;
40141
40225
  const incremental = async () => {
40142
- await this.fileOperation(path, async () => {
40226
+ await this.fileOperation(key, async () => {
40143
40227
  if (append) await this.fs.appendFile(path, new Uint8Array(), options3);
40144
40228
  else await this.fs.writeFile(path, new Uint8Array(), { ...options3, flag: "w" });
40145
40229
  if (!append) file.data = new Uint8Array();
40146
40230
  });
40147
40231
  return { write: (chunk) => {
40148
40232
  const copy2 = new Uint8Array(chunk);
40149
- return this.fileOperation(path, async () => {
40233
+ return this.fileOperation(key, async () => {
40150
40234
  if (closed) throw new Error("Output descriptor is closed");
40151
40235
  const current = file.data;
40152
40236
  let atEOF = false;
@@ -40178,7 +40262,7 @@ var Runtime = class _Runtime {
40178
40262
  if (closed) return;
40179
40263
  closed = true;
40180
40264
  resumePathCache();
40181
- if (--file.references === 0 && this.outputFiles.get(path) === file) this.outputFiles.delete(path);
40265
+ if (--file.references === 0 && this.outputFiles.get(key) === file) this.outputFiles.delete(key);
40182
40266
  };
40183
40267
  let target2;
40184
40268
  let outputScope;
@@ -40422,7 +40506,8 @@ var Runtime = class _Runtime {
40422
40506
  this.cancellationOwner,
40423
40507
  this.cancellationDepth,
40424
40508
  this.cancellationMaxDepth,
40425
- this.outcomeFrame
40509
+ this.outcomeFrame,
40510
+ this.inputProfile
40426
40511
  );
40427
40512
  try {
40428
40513
  return await runtime.dispatchScoped(name2, values, state, { ...io, [invocationScope]: scope }, assignments2, bypassFunctions);
@@ -40818,11 +40903,12 @@ ${functionDisplay(name2, state.functions.get(name2))}`;
40818
40903
  let denied;
40819
40904
  const matches3 = [];
40820
40905
  for (const target of pathTargets(name2, state.variables.PATH, this.budget.limits, this.signal, (limit) => this.budget.fail(limit))) {
40821
- const resolved = resolvePath(state.cwd, target);
40906
+ const resolved = pathOf(state, target);
40822
40907
  try {
40823
40908
  const options3 = { signal: this.signal };
40824
40909
  if (!await interruptible3(this.budget.pathLookup.isFile(this.fs, resolved, this.signal), this.signal)) continue;
40825
- if (this.fs.capabilities.permissions !== true) throw new CommandFailure2(`${target}: execution permissions are not supported by this filesystem`, 126);
40910
+ const capabilities = this.fs.capabilitiesFor ? await interruptible3(this.fs.capabilitiesFor(resolved, options3), this.signal) : this.fs.capabilities;
40911
+ if (capabilities.permissions !== true) throw new CommandFailure2(`${target}: execution permissions are not supported by this filesystem`, 126);
40826
40912
  await interruptible3(this.fs.access(resolved, ACCESS_MODES.X_OK, options3), this.signal);
40827
40913
  matches3.push(target);
40828
40914
  if (!all) return matches3;
@@ -41037,7 +41123,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
41037
41123
  this.cancellationOwner,
41038
41124
  this.cancellationDepth,
41039
41125
  this.cancellationMaxDepth,
41040
- this.outcomeFrame
41126
+ this.outcomeFrame,
41127
+ this.inputProfile
41041
41128
  );
41042
41129
  let input3;
41043
41130
  try {
@@ -41214,7 +41301,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
41214
41301
  async scriptFile(context2, state, io, target, args, direct, errexit = false, loadedSource, braceexpand = true) {
41215
41302
  if (target === "") throw new CommandFailure2(`${context2.command}: : No such file or directory`, 127);
41216
41303
  if (state.depth >= this.budget.limits.maxSubstitutionDepth) this.budget.fail("maxSubstitutionDepth");
41217
- const path = resolvePath(state.cwd, target);
41304
+ const path = pathOf(state, target);
41218
41305
  let source2;
41219
41306
  let environmentInterpreter = null;
41220
41307
  let interpreterProfile;
@@ -41224,7 +41311,10 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
41224
41311
  const options3 = { signal: this.signal };
41225
41312
  const stat = await interruptible3(this.fs.stat(path, options3), this.signal);
41226
41313
  if (stat.type !== "file") throw new CommandFailure2(`${target}: ${stat.type === "directory" ? "Is a directory" : "not a regular file"}`, 126);
41227
- if (direct && this.fs.capabilities.permissions !== true) throw new CommandFailure2(`${target}: execution permissions are not supported by this filesystem`, 126);
41314
+ if (direct) {
41315
+ const capabilities = this.fs.capabilitiesFor ? await interruptible3(this.fs.capabilitiesFor(path, options3), this.signal) : this.fs.capabilities;
41316
+ if (capabilities.permissions !== true) throw new CommandFailure2(`${target}: execution permissions are not supported by this filesystem`, 126);
41317
+ }
41228
41318
  await interruptible3(this.fs.access(path, ACCESS_MODES.R_OK | (direct ? ACCESS_MODES.X_OK : 0), options3), this.signal);
41229
41319
  const maxBytes = this.budget.limits.maxSourceBytes - this.budget.sourceBytes;
41230
41320
  if (stat.size > maxBytes) this.budget.fail("maxSourceBytes");
@@ -41362,7 +41452,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
41362
41452
  if (filename && !filename.includes("/") && state.variables.PATH) {
41363
41453
  let found = false;
41364
41454
  for (const candidate of pathTargets(filename, state.variables.PATH, this.budget.limits, this.signal, (limit) => this.budget.fail(limit))) {
41365
- const path2 = resolvePath(state.cwd, candidate);
41455
+ const path2 = pathOf(state, candidate);
41366
41456
  try {
41367
41457
  if (!await interruptible3(this.budget.pathLookup.isFile(this.fs, path2, this.signal), this.signal)) continue;
41368
41458
  await interruptible3(this.fs.access(path2, ACCESS_MODES.R_OK, options3), this.signal);
@@ -41377,7 +41467,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
41377
41467
  if (!found && state.profile === "sh") throw new CommandFailure2(`${context2.command}: ${filename}: file not found`, 1);
41378
41468
  }
41379
41469
  if (!filename) throw new CommandFailure2(": No such file or directory", 1);
41380
- const path = resolvePath(state.cwd, target);
41470
+ const path = pathOf(state, target);
41381
41471
  const stat = await interruptible3(this.fs.stat(path, options3), this.signal);
41382
41472
  if (stat.type === "directory") throw new CommandFailure2(`${context2.command}: ${target}: is a directory`, 1);
41383
41473
  if (stat.type !== "file") throw new CommandFailure2(`${target}: not a regular file`, 1);
@@ -43257,7 +43347,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
43257
43347
  for (const candidate of candidates) {
43258
43348
  let entries3;
43259
43349
  try {
43260
- const pending = this.fs.readdir(resolvePath(state.cwd, candidate || "."), { signal: this.signal });
43350
+ const pending = this.fs.readdir(pathOf(state, candidate || "."), { signal: this.signal });
43261
43351
  entries3 = arrayStore(state) ? await interruptible3(pending, this.signal) : await pending;
43262
43352
  } catch (error) {
43263
43353
  if (["ENOENT", "ENOTDIR", "EACCES"].includes(errorCode(error) ?? "")) continue;
@@ -43278,7 +43368,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
43278
43368
  const found = [];
43279
43369
  for (const candidate of candidates) {
43280
43370
  try {
43281
- const pending = this.fs.stat(resolvePath(state.cwd, candidate), { signal: this.signal });
43371
+ const pending = this.fs.stat(pathOf(state, candidate), { signal: this.signal });
43282
43372
  const stat = arrayStore(state) ? await interruptible3(pending, this.signal) : await pending;
43283
43373
  if (!value2.endsWith("/") || stat.type === "directory") found.push(candidate + (value2.endsWith("/") ? "/" : ""));
43284
43374
  } catch (error) {
@@ -43290,7 +43380,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
43290
43380
  };
43291
43381
 
43292
43382
  // packages/safe-bash/src/shell/input.ts
43293
- async function fileInput(fs, path, maxBytes, signal) {
43383
+ async function fileInput(fs, path, maxBytes, signal, inputProfile = fs) {
43294
43384
  signal.throwIfAborted();
43295
43385
  async function bufferedInput() {
43296
43386
  signal.throwIfAborted();
@@ -43300,7 +43390,13 @@ async function fileInput(fs, path, maxBytes, signal) {
43300
43390
  return toByteSource(bytes3);
43301
43391
  }
43302
43392
  const readStream = fs.readStream;
43303
- if (!readStream || fs.capabilities.streamingRead === false) return bufferedInput();
43393
+ const capabilities = await interruptible3(Promise.resolve(fs.capabilitiesFor?.(path, { signal }) ?? fs.capabilities), signal);
43394
+ if (!readStream || capabilities.streamingRead === false) {
43395
+ if (!inputProfile.readStream || inputProfile.capabilities.streamingRead === false) return bufferedInput();
43396
+ return { async *[Symbol.asyncIterator]() {
43397
+ yield* await bufferedInput();
43398
+ } };
43399
+ }
43304
43400
  let iterator;
43305
43401
  try {
43306
43402
  iterator = readStream.call(fs, path, { signal })[Symbol.asyncIterator]();
@@ -43894,8 +43990,9 @@ var Shell = class {
43894
43990
  profile: "bash"
43895
43991
  };
43896
43992
  const admission = Runtime.rootCancellationAdmission(budget);
43993
+ const filesystem = options3.fs ?? this.#options.fs;
43897
43994
  const runtime = new Runtime(
43898
- options3.fs ?? this.#options.fs,
43995
+ createDeviceFileSystem(filesystem),
43899
43996
  this.commands,
43900
43997
  [...this.#middleware],
43901
43998
  budget,
@@ -43907,7 +44004,9 @@ var Shell = class {
43907
44004
  cancellationState,
43908
44005
  owner,
43909
44006
  0,
43910
- admission.maxDepth
44007
+ admission.maxDepth,
44008
+ void 0,
44009
+ filesystem
43911
44010
  );
43912
44011
  exitCode = 0;
43913
44012
  while (true) {
@@ -44109,7 +44208,7 @@ init_platform();
44109
44208
  // packages/safe-js/dist/browser/safe-fs.js
44110
44209
  init_platform();
44111
44210
 
44112
- // packages/safe-js/dist/browser/chunks/chunk-I3HSJDAA.js
44211
+ // packages/safe-js/dist/browser/chunks/chunk-QK4IEGRO.js
44113
44212
  init_platform();
44114
44213
  var platform = Object.freeze({
44115
44214
  errno(_code) {
@@ -44767,6 +44866,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
44767
44866
  removeDirectory: true,
44768
44867
  recursiveRemove: true,
44769
44868
  rename: true,
44869
+ atomicRenameNoReplace: true,
44770
44870
  copy: true,
44771
44871
  exclusiveCopy: true,
44772
44872
  readlink: true,
@@ -45191,6 +45291,7 @@ var MemoryFileSystem = class _MemoryFileSystem {
45191
45291
  if (this.terminalDot(source2) || this.terminalDot(destination2)) this.fail("EINVAL", "rename", source2, destination2);
45192
45292
  if (node === this.root || target.node === this.root) this.fail("EBUSY", "rename", source2, destination2);
45193
45293
  if (destination2.endsWith("/") && node.type !== "directory") this.fail("ENOTDIR", "rename", source2, destination2);
45294
+ if (options3.noReplace && target.node) this.fail("EEXIST", "rename", source2, destination2);
45194
45295
  if (target.node === node) return;
45195
45296
  if (node.type === "directory" && target.path.startsWith(`${origin.path}/`)) this.fail("EINVAL", "rename", source2, destination2);
45196
45297
  this.permission(origin.parent, 3, "rename", source2);
@@ -45477,6 +45578,39 @@ function stockDescriptorWrite(filesystem) {
45477
45578
  }
45478
45579
  return true;
45479
45580
  }
45581
+ var deviceCapabilities = Object.freeze({
45582
+ readOnly: false,
45583
+ read: true,
45584
+ stat: true,
45585
+ realpath: true,
45586
+ access: true,
45587
+ readdir: false,
45588
+ write: true,
45589
+ append: true,
45590
+ exclusiveCreate: true,
45591
+ streamingRead: true,
45592
+ retainedRead: true,
45593
+ streamingWrite: true,
45594
+ streamingAppend: true,
45595
+ copy: true,
45596
+ exclusiveCopy: true,
45597
+ remove: false,
45598
+ removeDirectory: false,
45599
+ recursiveRemove: false,
45600
+ rename: false,
45601
+ mkdir: false,
45602
+ recursiveMkdir: false,
45603
+ symlinks: false,
45604
+ hardlinks: false,
45605
+ readlink: false,
45606
+ permissions: false,
45607
+ timestamps: false,
45608
+ truncate: false,
45609
+ randomAccessWrite: false,
45610
+ atomicRename: false,
45611
+ atomicRenameNoReplace: false,
45612
+ descriptorWriteStream: true
45613
+ });
45480
45614
  var syntheticStat = Object.freeze({
45481
45615
  type: "directory",
45482
45616
  size: 0,
@@ -45849,6 +45983,7 @@ var WebDavFileSystem = class {
45849
45983
  remove: true,
45850
45984
  recursiveRemove: true,
45851
45985
  rename: true,
45986
+ atomicRenameNoReplace: false,
45852
45987
  copy: true,
45853
45988
  exclusiveCopy: true,
45854
45989
  readlink: false,
@@ -46787,6 +46922,10 @@ var WebDavFileSystem = class {
46787
46922
  }
46788
46923
  }
46789
46924
  async rename(source2, destination2, options3 = {}) {
46925
+ if (options3.noReplace) {
46926
+ options3.signal?.throwIfAborted();
46927
+ fail32("ENOTSUP", "rename", source2, "atomic no-replace rename is unsupported");
46928
+ }
46790
46929
  await this.transfer("MOVE", source2, destination2, options3);
46791
46930
  }
46792
46931
  async copyFile(source2, destination2, options3 = {}) {
@@ -47351,7 +47490,8 @@ function createSafeJsCommands(options3 = {}, dialect = {
47351
47490
  let filename = parsed.file;
47352
47491
  if (source2 === void 0) {
47353
47492
  if (!fromStdin) filename = pathOf(context2, parsed.file);
47354
- const bytes3 = fromStdin ? context2.stdin : context2.fs.readStream && context2.fs.capabilities.streamingRead !== false ? context2.fs.readStream(filename, { signal, chunkSize: 65536 }) : toByteSource(await withSignal(signal, () => context2.fs.readFile(filename, { signal, maxBytes: limits.maxSourceBytes })));
47493
+ const capabilities = fromStdin ? void 0 : await withSignal(signal, async () => await context2.fs.capabilitiesFor?.(filename, { signal }) ?? context2.fs.capabilities);
47494
+ const bytes3 = fromStdin ? context2.stdin : context2.fs.readStream && capabilities?.streamingRead !== false ? context2.fs.readStream(filename, { signal, chunkSize: 65536 }) : toByteSource(await withSignal(signal, () => context2.fs.readFile(filename, { signal, maxBytes: limits.maxSourceBytes })));
47355
47495
  const reader = new GuestInput(bytes3, limits.maxSourceBytes, signal, fail4, "maxSourceBytes");
47356
47496
  try {
47357
47497
  source2 = await reader.readText();