@lousy-agents/agent-shell 5.17.10 → 5.17.12

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 (2) hide show
  1. package/dist/index.js +300 -14
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { createRequire as __rspack_createRequire } from "node:module";
3
3
  const __rspack_createRequire_require = __rspack_createRequire(import.meta.url);
4
4
  var __webpack_modules__ = ({
5
- 953(__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
5
+ 834(__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
6
6
 
7
7
  ;// CONCATENATED MODULE: external "node:child_process"
8
8
  const external_node_child_process_namespaceObject = __rspack_createRequire_require("node:child_process");
@@ -430,26 +430,304 @@ function directory_guard_createNearestExistingSyncDirectoryGuard(rootReal, targe
430
430
  return directory_guard_createSyncDirectoryGuard(root);
431
431
  }
432
432
 
433
- ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/fsync.js
433
+ ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/directory-durability.js
434
434
 
435
435
 
436
- async function syncDirectoryBestEffort(dirPath) {
436
+
437
+
438
+
439
+
440
+ function directoryOpenFlags() {
437
441
  if (process.platform === "win32") {
438
- return;
442
+ return "r";
439
443
  }
440
- let handle;
444
+ return (external_node_fs_namespaceObject.constants.O_RDONLY |
445
+ external_node_fs_namespaceObject.constants.O_DIRECTORY |
446
+ external_node_fs_namespaceObject.constants.O_NOFOLLOW |
447
+ external_node_fs_namespaceObject.constants.O_NONBLOCK);
448
+ }
449
+ function isWindowsDirectorySyncUnsupported(error) {
450
+ if (process.platform !== "win32") {
451
+ return false;
452
+ }
453
+ const code = error.code;
454
+ return (code === "EACCES" ||
455
+ code === "EINVAL" ||
456
+ code === "EISDIR" ||
457
+ code === "ENOSYS" ||
458
+ code === "ENOTSUP" ||
459
+ code === "EPERM");
460
+ }
461
+ function isWindowsDirectoryOpenUnsupported(error) {
462
+ if (process.platform !== "win32") {
463
+ return false;
464
+ }
465
+ const code = error.code;
466
+ return code === "EINVAL" || code === "EISDIR" || code === "ENOSYS" || code === "ENOTSUP";
467
+ }
468
+ function unsupportedOutcome(error) {
469
+ const code = error.code;
470
+ return code ? { status: "unsupported", code } : { status: "unsupported" };
471
+ }
472
+ function assertDirectory(identity, pathname, label) {
473
+ if (identity.isSymbolicLink() || !identity.isDirectory()) {
474
+ throw new errors_FsSafeError("not-file", `${label} must be a real directory: ${pathname}`);
475
+ }
476
+ }
477
+ async function createDirectoryReceipt(directoryPath, label) {
478
+ const resolvedPath = external_node_path_namespaceObject.resolve(directoryPath);
479
+ const identity = await promises_namespaceObject.lstat(resolvedPath);
480
+ assertDirectory(identity, resolvedPath, label);
481
+ return {
482
+ path: resolvedPath,
483
+ realPath: await promises_namespaceObject.realpath(resolvedPath),
484
+ identity,
485
+ };
486
+ }
487
+ function createDirectoryReceiptSync(directoryPath, label) {
488
+ const resolvedPath = path.resolve(directoryPath);
489
+ const identity = fsSync.lstatSync(resolvedPath);
490
+ assertDirectory(identity, resolvedPath, label);
491
+ return {
492
+ path: resolvedPath,
493
+ realPath: fsSync.realpathSync(resolvedPath),
494
+ identity,
495
+ };
496
+ }
497
+ async function assertDirectoryReceiptCurrent(receipt, label) {
498
+ const currentIdentity = await promises_namespaceObject.lstat(receipt.path);
499
+ assertDirectory(currentIdentity, receipt.path, label);
500
+ if (!file_identity_sameFileIdentity(receipt.identity, currentIdentity) ||
501
+ (await promises_namespaceObject.realpath(receipt.path)) !== receipt.realPath) {
502
+ throw new errors_FsSafeError("path-mismatch", `${label} changed during durable directory operation: ${receipt.path}`);
503
+ }
504
+ }
505
+ function assertDirectoryReceiptCurrentSync(receipt, label) {
506
+ const currentIdentity = fsSync.lstatSync(receipt.path);
507
+ assertDirectory(currentIdentity, receipt.path, label);
508
+ if (!sameFileIdentity(receipt.identity, currentIdentity) ||
509
+ fsSync.realpathSync(receipt.path) !== receipt.realPath) {
510
+ throw new FsSafeError("path-mismatch", `${label} changed during durable directory operation: ${receipt.path}`);
511
+ }
512
+ }
513
+ async function assertOpenDirectoryCurrent(handle, receipt, label) {
514
+ const openedIdentity = await handle.stat();
515
+ assertDirectory(openedIdentity, receipt.path, label);
516
+ if (!file_identity_sameFileIdentity(receipt.identity, openedIdentity)) {
517
+ throw new errors_FsSafeError("path-mismatch", `${label} handle changed during directory sync: ${receipt.path}`);
518
+ }
519
+ await assertDirectoryReceiptCurrent(receipt, label);
520
+ }
521
+ class PinnedDirectoryImpl {
522
+ receipt;
523
+ #handle;
524
+ #label;
525
+ #closed = false;
526
+ constructor(handle, receipt, label) {
527
+ this.#handle = handle;
528
+ this.receipt = receipt;
529
+ this.#label = label;
530
+ }
531
+ async assertCurrent() {
532
+ if (this.#closed) {
533
+ throw new errors_FsSafeError("helper-failed", `${this.#label} pin is already closed`);
534
+ }
535
+ await assertOpenDirectoryCurrent(this.#handle, this.receipt, this.#label);
536
+ }
537
+ async sync() {
538
+ await this.assertCurrent();
539
+ try {
540
+ await this.#handle.sync();
541
+ }
542
+ catch (error) {
543
+ if (!isWindowsDirectorySyncUnsupported(error)) {
544
+ throw error;
545
+ }
546
+ await this.assertCurrent();
547
+ return unsupportedOutcome(error);
548
+ }
549
+ await this.assertCurrent();
550
+ return { status: "synced" };
551
+ }
552
+ async close() {
553
+ if (this.#closed) {
554
+ return;
555
+ }
556
+ this.#closed = true;
557
+ await this.#handle.close();
558
+ }
559
+ }
560
+ async function pinDirectory(directory, options = {}) {
561
+ const label = options.label ?? "directory";
562
+ const receipt = typeof directory === "string" ? await createDirectoryReceipt(directory, label) : directory;
563
+ await assertDirectoryReceiptCurrent(receipt, label);
564
+ const handle = await promises_namespaceObject.open(receipt.path, directoryOpenFlags());
441
565
  try {
442
- const flags = external_node_fs_namespaceObject.constants.O_RDONLY |
443
- ("O_DIRECTORY" in external_node_fs_namespaceObject.constants ? external_node_fs_namespaceObject.constants.O_DIRECTORY : 0) |
444
- ("O_NOFOLLOW" in external_node_fs_namespaceObject.constants ? external_node_fs_namespaceObject.constants.O_NOFOLLOW : 0);
445
- handle = await promises_namespaceObject.open(dirPath, flags);
446
- await handle.sync();
566
+ await assertOpenDirectoryCurrent(handle, receipt, label);
567
+ return new PinnedDirectoryImpl(handle, receipt, label);
568
+ }
569
+ catch (error) {
570
+ await handle.close().catch(() => undefined);
571
+ throw error;
572
+ }
573
+ }
574
+ async function syncDirectory(directory, options = {}) {
575
+ const label = options.label ?? "directory";
576
+ const receipt = typeof directory === "string" ? await createDirectoryReceipt(directory, label) : directory;
577
+ let pinned;
578
+ try {
579
+ pinned = await pinDirectory(receipt, { label });
580
+ }
581
+ catch (error) {
582
+ if (!isWindowsDirectoryOpenUnsupported(error)) {
583
+ throw error;
584
+ }
585
+ await assertDirectoryReceiptCurrent(receipt, label);
586
+ return unsupportedOutcome(error);
587
+ }
588
+ try {
589
+ return await pinned.sync();
590
+ }
591
+ finally {
592
+ await pinned.close();
593
+ }
594
+ }
595
+ function syncDirectorySync(directory, options = {}) {
596
+ const label = options.label ?? "directory";
597
+ const receipt = typeof directory === "string" ? createDirectoryReceiptSync(directory, label) : directory;
598
+ assertDirectoryReceiptCurrentSync(receipt, label);
599
+ let descriptor;
600
+ try {
601
+ descriptor = fsSync.openSync(receipt.path, directoryOpenFlags());
602
+ }
603
+ catch (error) {
604
+ if (!isWindowsDirectoryOpenUnsupported(error)) {
605
+ throw error;
606
+ }
607
+ assertDirectoryReceiptCurrentSync(receipt, label);
608
+ return unsupportedOutcome(error);
609
+ }
610
+ try {
611
+ const openedIdentity = fsSync.fstatSync(descriptor);
612
+ assertDirectory(openedIdentity, receipt.path, label);
613
+ if (!sameFileIdentity(receipt.identity, openedIdentity)) {
614
+ throw new FsSafeError("path-mismatch", `${label} handle changed during directory sync: ${receipt.path}`);
615
+ }
616
+ assertDirectoryReceiptCurrentSync(receipt, label);
617
+ try {
618
+ fsSync.fsyncSync(descriptor);
619
+ }
620
+ catch (error) {
621
+ if (!isWindowsDirectorySyncUnsupported(error)) {
622
+ throw error;
623
+ }
624
+ assertDirectoryReceiptCurrentSync(receipt, label);
625
+ return unsupportedOutcome(error);
626
+ }
627
+ assertDirectoryReceiptCurrentSync(receipt, label);
628
+ return { status: "synced" };
629
+ }
630
+ finally {
631
+ fsSync.closeSync(descriptor);
632
+ }
633
+ }
634
+ async function syncDirectoryBestEffort(directoryPath) {
635
+ await syncDirectory(directoryPath).catch(() => undefined);
636
+ }
637
+ function syncDirectoryBestEffortSync(directoryPath) {
638
+ try {
639
+ syncDirectorySync(directoryPath);
447
640
  }
448
641
  catch {
449
- // Some filesystems reject directory handles; keep the write usable there.
642
+ // Compatibility helper for operations whose primary write may remain usable.
643
+ }
644
+ }
645
+ async function findExistingAncestorReceipt(targetPath, label) {
646
+ let currentPath = path.resolve(targetPath);
647
+ while (true) {
648
+ try {
649
+ return await createDirectoryReceipt(currentPath, label);
650
+ }
651
+ catch (error) {
652
+ if (error.code !== "ENOENT") {
653
+ throw error;
654
+ }
655
+ }
656
+ const parentPath = path.dirname(currentPath);
657
+ if (parentPath === currentPath) {
658
+ throw new FsSafeError("not-found", `${label} has no existing directory ancestor`);
659
+ }
660
+ currentPath = parentPath;
661
+ }
662
+ }
663
+ async function ensureDurableDirectory(options) {
664
+ const directoryPath = path.resolve(options.directoryPath);
665
+ const label = options.label ?? "directory";
666
+ const ancestorReceipt = await findExistingAncestorReceipt(directoryPath, label);
667
+ const targetExists = ancestorReceipt.path === directoryPath;
668
+ if (options.expectedExistingIdentity &&
669
+ (!targetExists || !sameFileIdentity(options.expectedExistingIdentity, ancestorReceipt.identity))) {
670
+ throw new FsSafeError("path-mismatch", `${label} changed before durable directory pinning: ${directoryPath}`);
671
+ }
672
+ const ancestor = await pinDirectory(ancestorReceipt, { label });
673
+ const pinnedDirectories = [ancestor];
674
+ try {
675
+ await ancestor.assertCurrent();
676
+ if (!targetExists) {
677
+ if (options.create) {
678
+ await options.create(directoryPath);
679
+ }
680
+ else {
681
+ const created = await ensureAbsoluteDirectory(directoryPath, {
682
+ mode: options.mode,
683
+ scopeLabel: label,
684
+ });
685
+ if (!created.ok) {
686
+ throw created.error;
687
+ }
688
+ }
689
+ }
690
+ await ancestor.assertCurrent();
691
+ let currentPath = ancestor.receipt.path;
692
+ for (const segment of path
693
+ .relative(ancestor.receipt.path, directoryPath)
694
+ .split(path.sep)
695
+ .filter(Boolean)) {
696
+ currentPath = path.join(currentPath, segment);
697
+ pinnedDirectories.push(await pinDirectory(currentPath, { label }));
698
+ }
699
+ let parentSync = { status: "not-needed" };
700
+ for (let index = pinnedDirectories.length - 1; index > 0; index -= 1) {
701
+ const parent = pinnedDirectories[index - 1];
702
+ const child = pinnedDirectories[index];
703
+ if (!parent || !child) {
704
+ throw new FsSafeError("helper-failed", `${label} directory pin chain is incomplete`);
705
+ }
706
+ await child.assertCurrent();
707
+ try {
708
+ const outcome = await parent.sync();
709
+ if (outcome.status === "unsupported") {
710
+ parentSync = outcome;
711
+ }
712
+ else if (parentSync.status === "not-needed") {
713
+ parentSync = outcome;
714
+ }
715
+ }
716
+ catch (error) {
717
+ throw new FsSafeError("helper-failed", `${label} could not sync created directory edge ${child.receipt.path} through ${parent.receipt.path}`, { cause: error });
718
+ }
719
+ await child.assertCurrent();
720
+ }
721
+ const finalReceipt = pinnedDirectories.at(-1)?.receipt;
722
+ if (!finalReceipt) {
723
+ throw new FsSafeError("helper-failed", `${label} directory receipt is missing`);
724
+ }
725
+ await ancestor.assertCurrent();
726
+ await assertDirectoryReceiptCurrent(finalReceipt, label);
727
+ return { ...finalReceipt, parentSync };
450
728
  }
451
729
  finally {
452
- await handle?.close().catch(() => undefined);
730
+ await Promise.all(pinnedDirectories.toReversed().map(async (directory) => directory.close()));
453
731
  }
454
732
  }
455
733
 
@@ -3050,7 +3328,15 @@ function isWindowsNetworkPath(filePath, platform = process.platform) {
3050
3328
  return false;
3051
3329
  }
3052
3330
  const normalized = filePath.replace(/\//g, "\\");
3053
- return normalized.startsWith("\\\\?\\UNC\\") || normalized.startsWith("\\\\");
3331
+ const extendedDrive = normalized.length >= 7 &&
3332
+ normalized.startsWith("\\\\?\\") &&
3333
+ /^[a-z]$/i.test(normalized[4] ?? "") &&
3334
+ normalized[5] === ":" &&
3335
+ normalized[6] === "\\";
3336
+ if (extendedDrive) {
3337
+ return false;
3338
+ }
3339
+ return normalized.startsWith("\\\\");
3054
3340
  }
3055
3341
  function isWindowsDriveLetterPath(filePath, platform = process.platform) {
3056
3342
  return platform === "win32" && /^[A-Za-z]:[\\/]/.test(filePath);
@@ -15966,4 +16252,4 @@ if (installedChunkData !== 0) { // 0 means "already installed".'
15966
16252
  // module factories are used so entry inlining is disabled
15967
16253
  // startup
15968
16254
  // Load entry module and return exports
15969
- var __webpack_exports__ = __webpack_require__(953);
16255
+ var __webpack_exports__ = __webpack_require__(834);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lousy-agents/agent-shell",
3
- "version": "5.17.10",
3
+ "version": "5.17.12",
4
4
  "description": "A flight recorder for npm script execution",
5
5
  "type": "module",
6
6
  "repository": {
@@ -36,7 +36,7 @@
36
36
  "build": "rspack build --config rspack.config.ts && chmod +x dist/index.js"
37
37
  },
38
38
  "dependencies": {
39
- "@openclaw/fs-safe": "0.4.5",
39
+ "@openclaw/fs-safe": "0.4.7",
40
40
  "zod": "4.4.3"
41
41
  },
42
42
  "peerDependencies": {