@poe-platform/safe-bash 0.1.546 → 0.1.548

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 (141) hide show
  1. package/README.md +1 -1
  2. package/dist/safe-bash/chunks/{chunk-UO33SQJU.js → chunk-2PQ3XOCQ.js} +239 -2
  3. package/dist/safe-bash/chunks/chunk-2PQ3XOCQ.js.map +7 -0
  4. package/dist/safe-bash/chunks/{chunk-WISNTI7E.js → chunk-3Y5PKSHX.js} +7 -11
  5. package/dist/safe-bash/chunks/{chunk-WISNTI7E.js.map → chunk-3Y5PKSHX.js.map} +1 -1
  6. package/dist/safe-bash/chunks/{chunk-VY5N6O6I.js → chunk-BXVGCJXW.js} +108 -21
  7. package/dist/safe-bash/chunks/chunk-BXVGCJXW.js.map +7 -0
  8. package/dist/safe-bash/chunks/chunk-C7QNJ3D4.js +13 -0
  9. package/dist/safe-bash/chunks/chunk-C7QNJ3D4.js.map +7 -0
  10. package/dist/safe-bash/chunks/{chunk-AWP6Z3RR.js → chunk-E3NZKSTA.js} +8 -12
  11. package/dist/safe-bash/chunks/{chunk-AWP6Z3RR.js.map → chunk-E3NZKSTA.js.map} +1 -1
  12. package/dist/safe-bash/chunks/{chunk-WXUZXY35.js → chunk-FMTBJ7SG.js} +3 -3
  13. package/dist/safe-bash/chunks/{chunk-QX2X5EC5.js → chunk-H6E6F5KJ.js} +7 -11
  14. package/dist/safe-bash/chunks/{chunk-QX2X5EC5.js.map → chunk-H6E6F5KJ.js.map} +1 -1
  15. package/dist/safe-bash/chunks/{chunk-IDJQT32M.js → chunk-HQCBEAFK.js} +7 -11
  16. package/dist/safe-bash/chunks/{chunk-IDJQT32M.js.map → chunk-HQCBEAFK.js.map} +1 -1
  17. package/dist/safe-bash/chunks/{chunk-4V3NGZAG.js → chunk-IYFB6VED.js} +6 -10
  18. package/dist/safe-bash/chunks/{chunk-4V3NGZAG.js.map → chunk-IYFB6VED.js.map} +1 -1
  19. package/dist/safe-bash/chunks/chunk-KJYVSFGF.js +284 -0
  20. package/dist/safe-bash/chunks/chunk-KJYVSFGF.js.map +7 -0
  21. package/dist/safe-bash/chunks/{chunk-O7BRWSKX.js → chunk-LHKAA57T.js} +60 -17
  22. package/dist/safe-bash/chunks/chunk-LHKAA57T.js.map +7 -0
  23. package/dist/safe-bash/chunks/chunk-LR32SJ3D.js +915 -0
  24. package/dist/safe-bash/chunks/chunk-LR32SJ3D.js.map +7 -0
  25. package/dist/safe-bash/chunks/{chunk-EUNOVYVT.js → chunk-OECKXHVJ.js} +2 -2
  26. package/dist/safe-bash/chunks/{chunk-DKT746UJ.js → chunk-PE5NZIA2.js} +5 -9
  27. package/dist/safe-bash/chunks/{chunk-DKT746UJ.js.map → chunk-PE5NZIA2.js.map} +1 -1
  28. package/dist/safe-bash/chunks/{chunk-X7C3PN2T.js → chunk-PMBBUNNN.js} +168 -114
  29. package/dist/safe-bash/chunks/{chunk-X7C3PN2T.js.map → chunk-PMBBUNNN.js.map} +3 -3
  30. package/dist/safe-bash/chunks/{chunk-YFFFBLBC.js → chunk-TJVKGNKA.js} +6 -10
  31. package/dist/safe-bash/chunks/{chunk-YFFFBLBC.js.map → chunk-TJVKGNKA.js.map} +1 -1
  32. package/dist/safe-bash/chunks/{chunk-FIY2BMTU.js → chunk-W3TLNFDB.js} +8 -12
  33. package/dist/safe-bash/chunks/{chunk-FIY2BMTU.js.map → chunk-W3TLNFDB.js.map} +1 -1
  34. package/dist/safe-bash/chunks/{chunk-PPFWG34Y.js → chunk-XBLVOMEJ.js} +2 -2
  35. package/dist/safe-bash/chunks/{chunk-WJWYJDQE.js → chunk-XYVCXUGM.js} +7 -11
  36. package/dist/safe-bash/chunks/{chunk-WJWYJDQE.js.map → chunk-XYVCXUGM.js.map} +1 -1
  37. package/dist/safe-bash/commands/archive/unzip/safety.d.ts +3 -2
  38. package/dist/safe-bash/commands/archive/unzip/safety.d.ts.map +1 -1
  39. package/dist/safe-bash/commands/archive/unzip/safety.js +57 -62
  40. package/dist/safe-bash/commands/archive/unzip/safety.js.map +1 -1
  41. package/dist/safe-bash/commands/archive/unzip.d.ts.map +1 -1
  42. package/dist/safe-bash/commands/archive/unzip.js +12 -9
  43. package/dist/safe-bash/commands/archive/unzip.js.map +1 -1
  44. package/dist/safe-bash/commands/archive/zip/safety.d.ts +1 -0
  45. package/dist/safe-bash/commands/archive/zip/safety.d.ts.map +1 -1
  46. package/dist/safe-bash/commands/archive/zip/safety.js +19 -87
  47. package/dist/safe-bash/commands/archive/zip/safety.js.map +1 -1
  48. package/dist/safe-bash/commands/archive/zip.d.ts.map +1 -1
  49. package/dist/safe-bash/commands/archive/zip.js +2 -1
  50. package/dist/safe-bash/commands/archive/zip.js.map +1 -1
  51. package/dist/safe-bash/commands/csplit/command.d.ts.map +1 -1
  52. package/dist/safe-bash/commands/csplit/command.js +3 -1
  53. package/dist/safe-bash/commands/csplit/command.js.map +1 -1
  54. package/dist/safe-bash/commands/csplit/index.browser.js +4 -6
  55. package/dist/safe-bash/commands/csplit/internal.d.ts +2 -0
  56. package/dist/safe-bash/commands/csplit/internal.d.ts.map +1 -1
  57. package/dist/safe-bash/commands/csplit/internal.js +12 -0
  58. package/dist/safe-bash/commands/csplit/internal.js.map +1 -1
  59. package/dist/safe-bash/commands/csplit/io.d.ts +4 -2
  60. package/dist/safe-bash/commands/csplit/io.d.ts.map +1 -1
  61. package/dist/safe-bash/commands/csplit/io.js +98 -58
  62. package/dist/safe-bash/commands/csplit/io.js.map +1 -1
  63. package/dist/safe-bash/commands/factor/index.browser.js +3 -5
  64. package/dist/safe-bash/commands/getopt/index.browser.js +3 -5
  65. package/dist/safe-bash/commands/hexdump/index.browser.js +3 -5
  66. package/dist/safe-bash/commands/iconv/index.browser.js +3 -5
  67. package/dist/safe-bash/commands/line-endings/index.browser.js +4 -6
  68. package/dist/safe-bash/commands/llm/command.d.ts +3 -2
  69. package/dist/safe-bash/commands/llm/command.d.ts.map +1 -1
  70. package/dist/safe-bash/commands/llm/command.js +260 -181
  71. package/dist/safe-bash/commands/llm/command.js.map +1 -1
  72. package/dist/safe-bash/commands/llm/elevenlabs-stream.d.ts +3 -0
  73. package/dist/safe-bash/commands/llm/elevenlabs-stream.d.ts.map +1 -0
  74. package/dist/safe-bash/commands/llm/elevenlabs-stream.js +118 -0
  75. package/dist/safe-bash/commands/llm/elevenlabs-stream.js.map +1 -0
  76. package/dist/safe-bash/commands/llm/elevenlabs.d.ts +16 -0
  77. package/dist/safe-bash/commands/llm/elevenlabs.d.ts.map +1 -0
  78. package/dist/safe-bash/commands/llm/elevenlabs.js +120 -0
  79. package/dist/safe-bash/commands/llm/elevenlabs.js.map +1 -0
  80. package/dist/safe-bash/commands/llm/index.browser.js +10 -4
  81. package/dist/safe-bash/commands/llm/index.d.ts +5 -5
  82. package/dist/safe-bash/commands/llm/index.d.ts.map +1 -1
  83. package/dist/safe-bash/commands/llm/index.js +3 -11
  84. package/dist/safe-bash/commands/llm/index.js.map +1 -1
  85. package/dist/safe-bash/commands/llm/mime.d.ts +2 -1
  86. package/dist/safe-bash/commands/llm/mime.d.ts.map +1 -1
  87. package/dist/safe-bash/commands/llm/mime.js +125 -21
  88. package/dist/safe-bash/commands/llm/mime.js.map +1 -1
  89. package/dist/safe-bash/commands/llm/openai-http.d.ts +9 -0
  90. package/dist/safe-bash/commands/llm/openai-http.d.ts.map +1 -0
  91. package/dist/safe-bash/commands/llm/openai-http.js +144 -0
  92. package/dist/safe-bash/commands/llm/openai-http.js.map +1 -0
  93. package/dist/safe-bash/commands/llm/openai-sse.d.ts +3 -0
  94. package/dist/safe-bash/commands/llm/openai-sse.d.ts.map +1 -0
  95. package/dist/safe-bash/commands/llm/openai-sse.js +67 -0
  96. package/dist/safe-bash/commands/llm/openai-sse.js.map +1 -0
  97. package/dist/safe-bash/commands/llm/openai.d.ts +15 -0
  98. package/dist/safe-bash/commands/llm/openai.d.ts.map +1 -0
  99. package/dist/safe-bash/commands/llm/openai.js +203 -0
  100. package/dist/safe-bash/commands/llm/openai.js.map +1 -0
  101. package/dist/safe-bash/commands/llm/providers/elevenlabs.d.ts +1 -15
  102. package/dist/safe-bash/commands/llm/providers/elevenlabs.d.ts.map +1 -1
  103. package/dist/safe-bash/commands/llm/providers/elevenlabs.js +1 -50
  104. package/dist/safe-bash/commands/llm/providers/elevenlabs.js.map +1 -1
  105. package/dist/safe-bash/commands/llm/providers/index.browser.js +2 -4
  106. package/dist/safe-bash/commands/llm/providers/openai.d.ts +1 -14
  107. package/dist/safe-bash/commands/llm/providers/openai.d.ts.map +1 -1
  108. package/dist/safe-bash/commands/llm/providers/openai.js +1 -77
  109. package/dist/safe-bash/commands/llm/providers/openai.js.map +1 -1
  110. package/dist/safe-bash/commands/llm/providers/shared.d.ts +4 -14
  111. package/dist/safe-bash/commands/llm/providers/shared.d.ts.map +1 -1
  112. package/dist/safe-bash/commands/llm/providers/shared.js +3 -156
  113. package/dist/safe-bash/commands/llm/providers/shared.js.map +1 -1
  114. package/dist/safe-bash/commands/network/index.browser.js +8 -13
  115. package/dist/safe-bash/commands/pr/index.browser.js +3 -5
  116. package/dist/safe-bash/commands/tsort/index.browser.js +3 -5
  117. package/dist/safe-bash/commands/xml/index.browser.js +4 -7
  118. package/dist/safe-bash/commands/yq/index.browser.js +5 -8
  119. package/dist/safe-bash/contracts/filesystem.d.ts +1 -1
  120. package/dist/safe-bash/contracts/filesystem.d.ts.map +1 -1
  121. package/dist/safe-bash/core.browser.js +278 -171
  122. package/dist/safe-bash/core.browser.js.map +3 -3
  123. package/package.json +2 -2
  124. package/dist/safe-bash/chunks/chunk-BZUQJTOZ.js +0 -322
  125. package/dist/safe-bash/chunks/chunk-BZUQJTOZ.js.map +0 -7
  126. package/dist/safe-bash/chunks/chunk-EUTSYRNM.js +0 -111
  127. package/dist/safe-bash/chunks/chunk-EUTSYRNM.js.map +0 -7
  128. package/dist/safe-bash/chunks/chunk-F5AOPLRZ.js +0 -355
  129. package/dist/safe-bash/chunks/chunk-F5AOPLRZ.js.map +0 -7
  130. package/dist/safe-bash/chunks/chunk-FDGESHPB.js +0 -224
  131. package/dist/safe-bash/chunks/chunk-FDGESHPB.js.map +0 -7
  132. package/dist/safe-bash/chunks/chunk-KYU6MXVK.js +0 -58
  133. package/dist/safe-bash/chunks/chunk-KYU6MXVK.js.map +0 -7
  134. package/dist/safe-bash/chunks/chunk-O7BRWSKX.js.map +0 -7
  135. package/dist/safe-bash/chunks/chunk-TTTOMUAY.js +0 -33
  136. package/dist/safe-bash/chunks/chunk-TTTOMUAY.js.map +0 -7
  137. package/dist/safe-bash/chunks/chunk-UO33SQJU.js.map +0 -7
  138. package/dist/safe-bash/chunks/chunk-VY5N6O6I.js.map +0 -7
  139. /package/dist/safe-bash/chunks/{chunk-WXUZXY35.js.map → chunk-FMTBJ7SG.js.map} +0 -0
  140. /package/dist/safe-bash/chunks/{chunk-EUNOVYVT.js.map → chunk-OECKXHVJ.js.map} +0 -0
  141. /package/dist/safe-bash/chunks/{chunk-PPFWG34Y.js.map → chunk-XBLVOMEJ.js.map} +0 -0
@@ -1,24 +1,20 @@
1
1
  import {
2
2
  writeFileOutput
3
- } from "./chunk-WXUZXY35.js";
4
- import {
5
- PublicDiagnostic,
6
- publicDiagnosticMessage
7
- } from "./chunk-TTTOMUAY.js";
3
+ } from "./chunk-FMTBJ7SG.js";
8
4
  import {
9
5
  dirname,
10
6
  resolvePath
11
7
  } from "./chunk-DPJWEGIX.js";
12
8
  import {
9
+ FsError,
10
+ PublicDiagnostic,
13
11
  getCommandArguments,
12
+ publicDiagnosticMessage,
14
13
  shellValueByteLength,
15
- shellValueBytes
16
- } from "./chunk-UO33SQJU.js";
17
- import {
18
- FsError,
14
+ shellValueBytes,
19
15
  writeBytes,
20
16
  yieldTurn
21
- } from "./chunk-FDGESHPB.js";
17
+ } from "./chunk-2PQ3XOCQ.js";
22
18
  import {
23
19
  init_platform
24
20
  } from "./chunk-2KL6W6NB.js";
@@ -11291,10 +11287,18 @@ var Budget = class {
11291
11287
  }
11292
11288
  context;
11293
11289
  limits;
11290
+ buffers = /* @__PURE__ */ new Map();
11294
11291
  work = 0;
11295
11292
  checkpoint = 0;
11296
11293
  diagnostics = 0;
11297
11294
  output = 0;
11295
+ reserveBuffered(owner, bytes2) {
11296
+ let total = bytes2;
11297
+ for (const [key, value] of this.buffers) if (key !== owner) total += value;
11298
+ this.check(total, this.limits.maxBufferedBytes, "buffered bytes");
11299
+ if (bytes2) this.buffers.set(owner, bytes2);
11300
+ else this.buffers.delete(owner);
11301
+ }
11298
11302
  quote(value) {
11299
11303
  const locale = this.context.env.LC_ALL || this.context.env.LC_CTYPE || this.context.env.LANG || "C";
11300
11304
  this.charge(value.length);
@@ -11378,6 +11382,9 @@ function fsDetail(error) {
11378
11382
  // packages/safe-bash/src/commands/csplit/io.ts
11379
11383
  init_platform();
11380
11384
  import { retainFileSystemCleanup } from "@poe-platform/safe-fs/core";
11385
+ var retainedLineUnits = 128;
11386
+ var retainedOutputUnits = 256;
11387
+ var outputBufferBytes = 65536;
11381
11388
  function sameIdentity(first, second) {
11382
11389
  return (typeof first.identityScope === "object" && first.identityScope !== null || typeof first.identityScope === "symbol") && first.identityScope === second.identityScope && Number.isSafeInteger(first.dev) && Number.isSafeInteger(first.ino) && first.dev >= 0 && first.ino >= 0 && first.dev === second.dev && first.ino === second.ino;
11383
11390
  }
@@ -11388,11 +11395,19 @@ var Lifecycle = class {
11388
11395
  }
11389
11396
  budget;
11390
11397
  pending = /* @__PURE__ */ new Set();
11391
- cleanups = [];
11398
+ cleanups = /* @__PURE__ */ new Set();
11392
11399
  closing;
11393
11400
  cleanup(action) {
11394
11401
  this.assertOpen();
11395
- this.cleanups.push(action);
11402
+ const owned = async () => {
11403
+ try {
11404
+ await action();
11405
+ } finally {
11406
+ this.cleanups.delete(owned);
11407
+ }
11408
+ };
11409
+ this.cleanups.add(owned);
11410
+ return owned;
11396
11411
  }
11397
11412
  assertOpen() {
11398
11413
  this.budget.context.signal.throwIfAborted();
@@ -11434,10 +11449,18 @@ var Lines = class {
11434
11449
  constructor(lifecycle) {
11435
11450
  this.lifecycle = lifecycle;
11436
11451
  lifecycle.cleanup(async () => {
11437
- if (!this.ended) await this.iterator?.return?.();
11452
+ try {
11453
+ if (!this.ended) await this.iterator?.return?.();
11454
+ } finally {
11455
+ this.lines.length = 0;
11456
+ this.partial = [];
11457
+ lifecycle.budget.reserveBuffered(this, 0);
11458
+ lifecycle.budget.reserveBuffered(this.fallbackAllocation, 0);
11459
+ }
11438
11460
  });
11439
11461
  }
11440
11462
  lifecycle;
11463
+ fallbackAllocation = {};
11441
11464
  lines = [];
11442
11465
  partial = [];
11443
11466
  partialBytes = 0;
@@ -11447,6 +11470,9 @@ var Lines = class {
11447
11470
  ended = false;
11448
11471
  path;
11449
11472
  identity;
11473
+ reserve(extraLines = 0, extraParts = 0) {
11474
+ this.lifecycle.budget.reserveBuffered(this, this.total * 2 + (this.lines.length + extraLines + this.partial.length + extraParts) * retainedLineUnits);
11475
+ }
11450
11476
  async open(name) {
11451
11477
  if (name === "-") {
11452
11478
  this.identity = this.lifecycle.budget.context.stdinInput?.stat;
@@ -11469,7 +11495,11 @@ var Lines = class {
11469
11495
  const capabilities = await this.lifecycle.operation(async () => await fs.capabilitiesFor?.(this.path, { signal }) ?? fs.capabilities);
11470
11496
  if (fs.readStream && capabilities.streamingRead !== false) return fs.readStream(this.path, { signal, chunkSize: 65536 });
11471
11497
  if (this.identity.size > Math.min(limits.maxInputBytes, limits.maxBufferedBytes / 2)) throw new CsplitError("buffered input bytes limit exceeded");
11472
- const value = await this.lifecycle.operation(() => fs.readFile(this.path, { signal, maxBytes: limits.maxInputBytes }));
11498
+ const admittedBytes = this.identity.size;
11499
+ this.lifecycle.budget.reserveBuffered(this.fallbackAllocation, admittedBytes);
11500
+ this.lifecycle.budget.reserveBuffered(this, admittedBytes * 2);
11501
+ const value = await this.lifecycle.operation(() => fs.readFile(this.path, { signal, maxBytes: admittedBytes }));
11502
+ this.lifecycle.budget.check(value.length, admittedBytes, "input bytes");
11473
11503
  return { async *[Symbol.asyncIterator]() {
11474
11504
  yield value;
11475
11505
  } };
@@ -11477,6 +11507,7 @@ var Lines = class {
11477
11507
  appendLine() {
11478
11508
  const { budget } = this.lifecycle;
11479
11509
  budget.check(this.lines.length + 1, budget.limits.maxLines, "line count");
11510
+ this.reserve(1);
11480
11511
  const line = new Uint8Array(this.partialBytes);
11481
11512
  let offset = 0;
11482
11513
  for (const part of this.partial) {
@@ -11486,6 +11517,7 @@ var Lines = class {
11486
11517
  this.lines.push(line);
11487
11518
  this.partial = [];
11488
11519
  this.partialBytes = 0;
11520
+ this.reserve();
11489
11521
  }
11490
11522
  async get(number) {
11491
11523
  const { budget } = this.lifecycle;
@@ -11504,7 +11536,7 @@ var Lines = class {
11504
11536
  if (!(chunk instanceof Uint8Array)) throw new CsplitError("input produced a non-byte chunk");
11505
11537
  this.total += chunk.length;
11506
11538
  budget.check(this.total, budget.limits.maxInputBytes, "input bytes");
11507
- budget.check(this.total * 2, budget.limits.maxBufferedBytes, "buffered bytes");
11539
+ this.reserve();
11508
11540
  if (!chunk.length) budget.check(++this.emptyChunks, budget.limits.maxEmptyChunks, "empty input chunks");
11509
11541
  budget.charge(chunk.length);
11510
11542
  const owned = Uint8Array.from(chunk);
@@ -11513,6 +11545,7 @@ var Lines = class {
11513
11545
  if (owned[offset] === 10) {
11514
11546
  this.partialBytes += offset + 1 - start;
11515
11547
  budget.check(this.partialBytes, budget.limits.maxLineBytes, "line bytes");
11548
+ this.reserve(0, 1);
11516
11549
  this.partial.push(owned.subarray(start, offset + 1));
11517
11550
  this.appendLine();
11518
11551
  start = offset + 1;
@@ -11525,6 +11558,7 @@ var Lines = class {
11525
11558
  if (start < owned.length) {
11526
11559
  this.partialBytes += owned.length - start;
11527
11560
  budget.check(this.partialBytes, budget.limits.maxLineBytes, "line bytes");
11561
+ this.reserve(0, 1);
11528
11562
  this.partial.push(owned.subarray(start));
11529
11563
  }
11530
11564
  await budget.checkpointWork();
@@ -11557,18 +11591,12 @@ var Outputs = class {
11557
11591
  let current = "/";
11558
11592
  for (const component of ["", ...components]) {
11559
11593
  if (component) current = resolvePath(current, component);
11560
- const identity = await this.lifecycle.operation(() => context.fs.lstat(current, { signal: context.signal }));
11594
+ const identity = Object.freeze({ ...await this.lifecycle.operation(() => context.fs.lstat(current, { signal: context.signal })) });
11561
11595
  if (identity.type !== "directory" || !sameIdentity(identity, identity)) throw new CsplitError("unsafe output directory identity");
11562
11596
  parents.push({ path: current, identity });
11563
11597
  }
11564
11598
  return parents;
11565
11599
  }
11566
- async checked(output) {
11567
- await this.checkedParents(output.parents);
11568
- const { context } = this.lifecycle.budget;
11569
- const current = await this.lifecycle.operation(() => context.fs.lstat(output.path, { signal: context.signal }));
11570
- if (!output.identity || current.type !== "file" || !sameIdentity(current, output.identity)) throw new CsplitError("output changed before mutation");
11571
- }
11572
11600
  async checkedParents(parents) {
11573
11601
  const { context } = this.lifecycle.budget;
11574
11602
  for (const parent of parents) {
@@ -11585,53 +11613,48 @@ var Outputs = class {
11585
11613
  budget.check(name.length, limits.maxPathBytes, "output filename bytes");
11586
11614
  const path = resolvePath(context.cwd, pathText(name));
11587
11615
  try {
11616
+ const capabilities = await this.lifecycle.operation(async () => await context.fs.capabilitiesFor?.(path, { signal: context.signal, create: true }) ?? context.fs.capabilities);
11617
+ if (capabilities.atomicFileMutation !== true || !context.fs.writeFileConditional || !context.fs.removeFileConditional) throw new CsplitError("atomic output mutations are not supported");
11588
11618
  const parents = await this.parents(path);
11589
11619
  let existing;
11590
11620
  try {
11591
- existing = await this.lifecycle.operation(() => context.fs.lstat(path, { signal: context.signal }));
11621
+ existing = Object.freeze({ ...await this.lifecycle.operation(() => context.fs.lstat(path, { signal: context.signal })) });
11592
11622
  } catch (error) {
11593
11623
  context.signal.throwIfAborted();
11594
11624
  if (!missing(error)) throw error;
11595
11625
  }
11596
11626
  if (existing && (existing.type !== "file" || !sameIdentity(existing, existing))) throw new CsplitError(`unsafe output file ${budget.quote(name)}`);
11597
11627
  this.input.assertOutput(path, existing);
11598
- const output = { path, name, parents, created: false, removed: false, elided: false, failed: false, size: 0, cleanup: async () => {
11628
+ const metadataBytes = retainedOutputUnits + path.length * 2;
11629
+ const output = { path, parent: parents.at(-1).identity, metadataBytes, created: false, removed: false, elided: false, failed: false, size: 0, buffered: 0, cleanup: async () => {
11599
11630
  } };
11600
- output.cleanup = retainFileSystemCleanup(context.fs, async (view) => {
11631
+ budget.reserveBuffered(output, metadataBytes);
11632
+ output.cleanup = this.lifecycle.cleanup(retainFileSystemCleanup(context.fs, async (view) => {
11633
+ delete output.buffer;
11634
+ output.buffered = 0;
11635
+ budget.reserveBuffered(output, 0);
11601
11636
  if (!output.created || !output.identity || !output.elided && (this.succeeded || this.options.keep || this.preserve)) return;
11602
11637
  try {
11603
- for (const parent of parents) {
11604
- const current2 = await view.lstat(parent.path);
11605
- if (current2.type !== "directory" || !sameIdentity(current2, parent.identity)) return;
11606
- }
11607
- const current = await view.lstat(path);
11608
- if (current.type === "file" && sameIdentity(current, output.identity)) {
11609
- await view.rm(path);
11610
- output.removed = true;
11611
- }
11638
+ if (!view.removeFileConditional) throw new FsError("ENOTSUP");
11639
+ await view.removeFileConditional(path, { expected: output.identity, parent: output.parent });
11640
+ output.removed = true;
11612
11641
  } catch (error) {
11613
- if (!missing(error)) throw error;
11642
+ if (!missing(error) && !(error instanceof FsError && error.code === "EAGAIN")) throw error;
11614
11643
  }
11615
- }, { maxOperations: limits.maxPathDepth + 3 });
11616
- this.lifecycle.cleanup(output.cleanup);
11617
- await this.checkedParents(parents);
11618
- let admitted;
11644
+ }, { maxOperations: 1 }));
11619
11645
  try {
11620
- admitted = await this.lifecycle.operation(() => context.fs.lstat(path, { signal: context.signal }));
11621
- } catch (error) {
11622
- context.signal.throwIfAborted();
11623
- if (!missing(error)) throw error;
11646
+ await this.checkedParents(parents);
11647
+ await this.lifecycle.operation(async () => {
11648
+ output.identity = Object.freeze({ ...await context.fs.writeFileConditional(path, new Uint8Array(), {
11649
+ signal: context.signal,
11650
+ expected: existing ?? null,
11651
+ parent: output.parent
11652
+ }) });
11653
+ output.created = true;
11654
+ });
11655
+ } finally {
11656
+ parents.length = 0;
11624
11657
  }
11625
- if (admitted ? !existing || admitted.type !== "file" || !sameIdentity(admitted, existing) : existing !== void 0) throw new CsplitError("output changed before creation");
11626
- await this.checkedParents(parents);
11627
- await this.lifecycle.operation(async () => {
11628
- await context.fs.writeFile(path, new Uint8Array(), { signal: context.signal, flag: existing ? "w" : "wx" });
11629
- output.created = true;
11630
- if (existing) output.identity = existing;
11631
- const identity = await context.fs.lstat(path, { signal: context.signal });
11632
- if (identity.type !== "file" || !sameIdentity(identity, identity) || existing && !sameIdentity(existing, identity)) throw new CsplitError("output creation identity unavailable");
11633
- output.identity = identity;
11634
- });
11635
11658
  this.index++;
11636
11659
  this.current = output;
11637
11660
  } catch (error) {
@@ -11639,18 +11662,42 @@ var Outputs = class {
11639
11662
  throw error;
11640
11663
  }
11641
11664
  }
11665
+ async flush(output) {
11666
+ if (!output.buffered) return;
11667
+ const { context } = this.lifecycle.budget;
11668
+ try {
11669
+ await this.lifecycle.operation(() => writeFileOutput(context, output.buffer.subarray(0, output.buffered), async (chunk) => {
11670
+ output.identity = Object.freeze({ ...await context.fs.writeFileConditional(output.path, chunk, {
11671
+ signal: context.signal,
11672
+ expected: output.identity,
11673
+ parent: output.parent,
11674
+ append: true
11675
+ }) });
11676
+ output.buffered = 0;
11677
+ }));
11678
+ } catch (error) {
11679
+ output.failed = true;
11680
+ throw error;
11681
+ }
11682
+ }
11642
11683
  async write(value) {
11643
11684
  const output = this.current;
11644
11685
  if (!output) throw new CsplitError("output is not open");
11645
11686
  const { budget } = this.lifecycle;
11646
11687
  budget.fileBytes(value.length);
11647
- try {
11648
- await this.checked(output);
11649
- await this.lifecycle.operation(() => writeFileOutput(budget.context, value, (chunk) => budget.context.fs.appendFile(output.path, chunk, { signal: budget.context.signal })));
11650
- output.size += value.length;
11651
- } catch (error) {
11652
- output.failed = true;
11653
- throw error;
11688
+ if (!output.buffer) {
11689
+ const capacity = Math.min(outputBufferBytes, budget.limits.maxBufferedBytes);
11690
+ budget.reserveBuffered(output, output.metadataBytes + capacity);
11691
+ output.buffer = new Uint8Array(capacity);
11692
+ }
11693
+ for (let offset = 0; offset < value.length; ) {
11694
+ this.lifecycle.assertOpen();
11695
+ const count = Math.min(value.length - offset, output.buffer.length - output.buffered);
11696
+ output.buffer.set(value.subarray(offset, offset + count), output.buffered);
11697
+ output.buffered += count;
11698
+ output.size += count;
11699
+ offset += count;
11700
+ if (output.buffered === output.buffer.length) await this.flush(output);
11654
11701
  }
11655
11702
  }
11656
11703
  async finish() {
@@ -11658,8 +11705,10 @@ var Outputs = class {
11658
11705
  if (!output) return;
11659
11706
  this.current = void 0;
11660
11707
  if (output.failed) return;
11708
+ await this.flush(output);
11709
+ delete output.buffer;
11710
+ this.lifecycle.budget.reserveBuffered(output, output.metadataBytes);
11661
11711
  if (!output.size && this.options.elide) {
11662
- await this.checked(output);
11663
11712
  output.elided = true;
11664
11713
  await output.cleanup();
11665
11714
  if (!output.removed) throw new CsplitError("output changed before empty-file removal");
@@ -12002,62 +12051,67 @@ var Splitter = class {
12002
12051
  // packages/safe-bash/src/commands/csplit/command.ts
12003
12052
  function createCsplitCommandWithExecutor(executor, options2 = {}) {
12004
12053
  const limits = settings(options2);
12005
- return { name: "csplit", description: "Split files at bounded line and BRE boundaries", async execute(context) {
12006
- return withRegexSession(context, executor, async (session) => {
12007
- const budget = new Budget(context, limits);
12008
- const lifecycle = new Lifecycle(budget);
12009
- let output;
12010
- let failure;
12011
- let primary;
12012
- let exitCode = 0;
12013
- try {
12014
- const parsed = parseOptions(budget.arguments(), budget);
12015
- if (parsed.information) {
12016
- await budget.print(parsed.information === "version" ? "csplit (virtual-bash)\n" : "Usage: csplit [OPTION]... FILE PATTERN...\nOptions: -f PREFIX, -b SUFFIX, -k, -z, -n DIGITS, -s, --suppress-matched\nPatterns: INTEGER, /REGEXP/[OFFSET], %REGEXP%[OFFSET], {INTEGER}, {*}\n");
12017
- } else {
12018
- const format = suffixFormatter(parsed, budget);
12019
- const input = new Lines(lifecycle);
12020
- try {
12021
- await input.open(parsed.operands[0]);
12022
- } catch (error) {
12023
- if (error instanceof FsError) throw new CsplitError(`cannot open ${budget.quote(parsed.operands[0])} for reading: ${fsDetail(error)}`);
12024
- throw error;
12054
+ return {
12055
+ name: "csplit",
12056
+ description: "Split files at bounded line and BRE boundaries",
12057
+ filesystemRequirements: [{ id: "split", description: "Atomically mutate owned VFS outputs", capabilities: ["atomicFileMutation"], mutates: true }],
12058
+ async execute(context) {
12059
+ return withRegexSession(context, executor, async (session) => {
12060
+ const budget = new Budget(context, limits);
12061
+ const lifecycle = new Lifecycle(budget);
12062
+ let output;
12063
+ let failure;
12064
+ let primary;
12065
+ let exitCode = 0;
12066
+ try {
12067
+ const parsed = parseOptions(budget.arguments(), budget);
12068
+ if (parsed.information) {
12069
+ await budget.print(parsed.information === "version" ? "csplit (virtual-bash)\n" : "Usage: csplit [OPTION]... FILE PATTERN...\nOptions: -f PREFIX, -b SUFFIX, -k, -z, -n DIGITS, -s, --suppress-matched\nPatterns: INTEGER, /REGEXP/[OFFSET], %REGEXP%[OFFSET], {INTEGER}, {*}\n");
12070
+ } else {
12071
+ const format = suffixFormatter(parsed, budget);
12072
+ const input = new Lines(lifecycle);
12073
+ try {
12074
+ await input.open(parsed.operands[0]);
12075
+ } catch (error) {
12076
+ if (error instanceof FsError) throw new CsplitError(`cannot open ${budget.quote(parsed.operands[0])} for reading: ${fsDetail(error)}`);
12077
+ throw error;
12078
+ }
12079
+ const matcher = new Matcher(session, budget);
12080
+ const patterns = await preparePatterns(parsed.operands.slice(1), matcher);
12081
+ output = new Outputs(lifecycle, parsed, format, input);
12082
+ await new Splitter(input, output, matcher).run(patterns);
12083
+ output.succeeded = true;
12025
12084
  }
12026
- const matcher = new Matcher(session, budget);
12027
- const patterns = await preparePatterns(parsed.operands.slice(1), matcher);
12028
- output = new Outputs(lifecycle, parsed, format, input);
12029
- await new Splitter(input, output, matcher).run(patterns);
12030
- output.succeeded = true;
12031
- }
12032
- } catch (error) {
12033
- primary = { reason: error };
12034
- failure = { reason: error };
12035
- if (output && error instanceof CsplitError && error.preserve) output.preserve = true;
12036
- if (!context.signal.aborted) {
12037
- exitCode = 1;
12038
- try {
12039
- const message = error instanceof ExprMatchError ? error.message : error instanceof FsError ? fsDetail(error) : publicDiagnosticMessage(error, context.onInternalError);
12040
- await budget.print(`csplit: ${message}
12085
+ } catch (error) {
12086
+ primary = { reason: error };
12087
+ failure = { reason: error };
12088
+ if (output && error instanceof CsplitError && error.preserve) output.preserve = true;
12089
+ if (!context.signal.aborted) {
12090
+ exitCode = 1;
12091
+ try {
12092
+ const message = error instanceof ExprMatchError ? error.message : error instanceof FsError ? fsDetail(error) : publicDiagnosticMessage(error, context.onInternalError);
12093
+ await budget.print(`csplit: ${message}
12041
12094
  `, true);
12042
- if (error instanceof CsplitError && error.usage) await budget.print("Try 'csplit --help' for more information.\n", true);
12043
- if (!(error instanceof CsplitError && error.preserve)) await output?.finish();
12044
- failure = void 0;
12045
- } catch (reporting) {
12046
- failure = { reason: new AggregateError([error, reporting], "csplit failure reporting failed") };
12095
+ if (error instanceof CsplitError && error.usage) await budget.print("Try 'csplit --help' for more information.\n", true);
12096
+ if (!(error instanceof CsplitError && error.preserve)) await output?.finish();
12097
+ failure = void 0;
12098
+ } catch (reporting) {
12099
+ failure = { reason: new AggregateError([error, reporting], "csplit failure reporting failed") };
12100
+ }
12047
12101
  }
12048
12102
  }
12049
- }
12050
- try {
12051
- await lifecycle.close();
12052
- } catch (cleanup) {
12053
- const previous = failure ?? primary;
12054
- failure = { reason: previous ? new AggregateError([previous.reason, cleanup], "csplit execution and cleanup failed") : cleanup };
12055
- }
12056
- context.signal.throwIfAborted();
12057
- if (failure) throw failure.reason;
12058
- return { exitCode };
12059
- });
12060
- } };
12103
+ try {
12104
+ await lifecycle.close();
12105
+ } catch (cleanup) {
12106
+ const previous = failure ?? primary;
12107
+ failure = { reason: previous ? new AggregateError([previous.reason, cleanup], "csplit execution and cleanup failed") : cleanup };
12108
+ }
12109
+ context.signal.throwIfAborted();
12110
+ if (failure) throw failure.reason;
12111
+ return { exitCode };
12112
+ });
12113
+ }
12114
+ };
12061
12115
  }
12062
12116
 
12063
12117
  // packages/safe-bash/src/commands/csplit/index.ts
@@ -12100,4 +12154,4 @@ export {
12100
12154
  createCsplitCommands,
12101
12155
  csplitCommands
12102
12156
  };
12103
- //# sourceMappingURL=chunk-X7C3PN2T.js.map
12157
+ //# sourceMappingURL=chunk-PMBBUNNN.js.map