@lousy-agents/agent-shell 5.15.4 → 5.15.6

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 +270 -51
  2. package/package.json +3 -3
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
- 341(__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
5
+ 818(__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");
@@ -222,6 +222,7 @@ function hasNonEmptyString(value) {
222
222
 
223
223
 
224
224
 
225
+
225
226
  const NOT_FOUND_CODES = new Set(["ENOENT", "ENOTDIR"]);
226
227
  const SYMLINK_OPEN_CODES = new Set(["ELOOP", "EINVAL", "ENOTSUP"]);
227
228
  const POSIX_SEPARATOR_CHAR_CODE = 0x2f;
@@ -421,6 +422,29 @@ function directory_guard_createNearestExistingSyncDirectoryGuard(rootReal, targe
421
422
  return directory_guard_createSyncDirectoryGuard(root);
422
423
  }
423
424
 
425
+ ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/fsync.js
426
+
427
+
428
+ async function syncDirectoryBestEffort(dirPath) {
429
+ if (process.platform === "win32") {
430
+ return;
431
+ }
432
+ let handle;
433
+ try {
434
+ const flags = external_node_fs_namespaceObject.constants.O_RDONLY |
435
+ ("O_DIRECTORY" in external_node_fs_namespaceObject.constants ? external_node_fs_namespaceObject.constants.O_DIRECTORY : 0) |
436
+ ("O_NOFOLLOW" in external_node_fs_namespaceObject.constants ? external_node_fs_namespaceObject.constants.O_NOFOLLOW : 0);
437
+ handle = await promises_namespaceObject.open(dirPath, flags);
438
+ await handle.sync();
439
+ }
440
+ catch {
441
+ // Some filesystems reject directory handles; keep the write usable there.
442
+ }
443
+ finally {
444
+ await handle?.close().catch(() => undefined);
445
+ }
446
+ }
447
+
424
448
  ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js
425
449
 
426
450
 
@@ -1517,6 +1541,7 @@ async function runPinnedPathHelper(params) {
1517
1541
 
1518
1542
 
1519
1543
 
1544
+
1520
1545
  function byteLength(input, encoding) {
1521
1546
  return typeof input === "string"
1522
1547
  ? Buffer.byteLength(input, encoding ?? "utf8")
@@ -1709,11 +1734,13 @@ async function runPinnedWriteFallback(params) {
1709
1734
  throw new errors_FsSafeError("path-mismatch", "fallback temp path changed during write");
1710
1735
  }
1711
1736
  const expectedTempStat = tempStat;
1737
+ await handle.sync();
1712
1738
  await handle.close().catch(() => undefined);
1713
1739
  handle = undefined;
1714
1740
  await withAsyncDirectoryGuards([parentGuard], async () => {
1715
1741
  await promises_namespaceObject.rename(tempPath, targetPath);
1716
1742
  renamed = true;
1743
+ await syncDirectoryBestEffort(parentPath);
1717
1744
  targetStat = await promises_namespaceObject.lstat(targetPath);
1718
1745
  if (targetStat.isSymbolicLink() || !file_identity_sameFileIdentity(targetStat, expectedTempStat)) {
1719
1746
  throw new errors_FsSafeError("path-mismatch", "fallback target changed during write");
@@ -2387,6 +2414,197 @@ function path_policy_shortPath(value) {
2387
2414
  return value;
2388
2415
  }
2389
2416
 
2417
+ ;// CONCATENATED MODULE: external "node:url"
2418
+ const external_node_url_namespaceObject = __rspack_createRequire_require("node:url");
2419
+ ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/local-file-access.js
2420
+
2421
+
2422
+
2423
+ const ENCODED_FILE_URL_SEPARATOR_RE = /%(?:2f|5c)/i;
2424
+ function isLocalFileUrlHost(hostname) {
2425
+ const normalized = normalizeLowercaseStringOrEmpty(hostname);
2426
+ return normalized === "" || normalized === "localhost";
2427
+ }
2428
+ function hasEncodedFileUrlSeparator(pathname) {
2429
+ return ENCODED_FILE_URL_SEPARATOR_RE.test(pathname);
2430
+ }
2431
+ function isWindowsNetworkPath(filePath, platform = process.platform) {
2432
+ if (platform !== "win32") {
2433
+ return false;
2434
+ }
2435
+ const normalized = filePath.replace(/\//g, "\\");
2436
+ return normalized.startsWith("\\\\?\\UNC\\") || normalized.startsWith("\\\\");
2437
+ }
2438
+ function isWindowsDriveLetterPath(filePath, platform = process.platform) {
2439
+ return platform === "win32" && /^[A-Za-z]:[\\/]/.test(filePath);
2440
+ }
2441
+ function assertNoWindowsNetworkPath(filePath, label = "Path") {
2442
+ if (isWindowsNetworkPath(filePath)) {
2443
+ throw new Error(`${label} cannot use Windows network paths: ${filePath}`);
2444
+ }
2445
+ }
2446
+ function safeFileURLToPath(fileUrl) {
2447
+ let parsed;
2448
+ try {
2449
+ parsed = new external_node_url_namespaceObject.URL(fileUrl);
2450
+ }
2451
+ catch {
2452
+ throw new Error(`Invalid file:// URL: ${fileUrl}`);
2453
+ }
2454
+ if (parsed.protocol !== "file:") {
2455
+ throw new Error(`Invalid file:// URL: ${fileUrl}`);
2456
+ }
2457
+ if (!isLocalFileUrlHost(parsed.hostname)) {
2458
+ throw new Error(`file:// URLs with remote hosts are not allowed: ${fileUrl}`);
2459
+ }
2460
+ if (hasEncodedFileUrlSeparator(parsed.pathname)) {
2461
+ throw new Error(`file:// URLs cannot encode path separators: ${fileUrl}`);
2462
+ }
2463
+ const filePath = (0,external_node_url_namespaceObject.fileURLToPath)(parsed);
2464
+ assertNoWindowsNetworkPath(filePath, "Local file URL");
2465
+ return filePath;
2466
+ }
2467
+ function trySafeFileURLToPath(fileUrl) {
2468
+ try {
2469
+ return safeFileURLToPath(fileUrl);
2470
+ }
2471
+ catch {
2472
+ return undefined;
2473
+ }
2474
+ }
2475
+ function basenameFromMediaSource(source) {
2476
+ if (!source) {
2477
+ return undefined;
2478
+ }
2479
+ if (source.startsWith("file://")) {
2480
+ const filePath = trySafeFileURLToPath(source);
2481
+ return filePath ? path.basename(filePath) || undefined : undefined;
2482
+ }
2483
+ if (/^https?:\/\//i.test(source)) {
2484
+ try {
2485
+ return path.basename(new URL(source).pathname) || undefined;
2486
+ }
2487
+ catch {
2488
+ return undefined;
2489
+ }
2490
+ }
2491
+ return path.basename(source) || undefined;
2492
+ }
2493
+
2494
+ ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/device-path.js
2495
+
2496
+
2497
+
2498
+ const POSIX_BLOCKED_DEVICE_PATHS = new Set([
2499
+ "/dev/zero",
2500
+ "/dev/random",
2501
+ "/dev/urandom",
2502
+ "/dev/full",
2503
+ "/dev/stdin",
2504
+ "/dev/stdout",
2505
+ "/dev/stderr",
2506
+ "/dev/tty",
2507
+ "/dev/console",
2508
+ ]);
2509
+ const WINDOWS_RESERVED_DEVICE_NAMES = new Set([
2510
+ "CON",
2511
+ "PRN",
2512
+ "AUX",
2513
+ "NUL",
2514
+ "CLOCK$",
2515
+ "CONIN$",
2516
+ "CONOUT$",
2517
+ "COM1",
2518
+ "COM2",
2519
+ "COM3",
2520
+ "COM4",
2521
+ "COM5",
2522
+ "COM6",
2523
+ "COM7",
2524
+ "COM8",
2525
+ "COM9",
2526
+ "COM¹",
2527
+ "COM²",
2528
+ "COM³",
2529
+ "LPT1",
2530
+ "LPT2",
2531
+ "LPT3",
2532
+ "LPT4",
2533
+ "LPT5",
2534
+ "LPT6",
2535
+ "LPT7",
2536
+ "LPT8",
2537
+ "LPT9",
2538
+ "LPT¹",
2539
+ "LPT²",
2540
+ "LPT³",
2541
+ ]);
2542
+ function candidateReadPaths(filePath) {
2543
+ if (!filePath.startsWith("file://")) {
2544
+ return [filePath];
2545
+ }
2546
+ const parsed = trySafeFileURLToPath(filePath);
2547
+ return parsed === undefined ? [filePath] : [filePath, parsed];
2548
+ }
2549
+ function normalizePosixPath(filePath, cwd) {
2550
+ if (external_node_path_namespaceObject.posix.isAbsolute(filePath)) {
2551
+ return external_node_path_namespaceObject.posix.normalize(filePath);
2552
+ }
2553
+ const base = cwd && external_node_path_namespaceObject.posix.isAbsolute(cwd) ? cwd : process.cwd();
2554
+ return external_node_path_namespaceObject.posix.resolve(base, filePath);
2555
+ }
2556
+ function matchPosixDeviceReadPath(filePath, cwd) {
2557
+ const normalized = normalizePosixPath(filePath, cwd);
2558
+ if (POSIX_BLOCKED_DEVICE_PATHS.has(normalized)) {
2559
+ return { path: normalized, reason: "posix-device" };
2560
+ }
2561
+ if (normalized === "/dev/fd" || normalized.startsWith("/dev/fd/")) {
2562
+ return { path: normalized, reason: "posix-fd" };
2563
+ }
2564
+ if (/^\/proc\/(?:self|thread-self|\d+)\/fd(?:\/|$)/.test(normalized)) {
2565
+ return { path: normalized, reason: "posix-fd" };
2566
+ }
2567
+ return undefined;
2568
+ }
2569
+ function normalizeWindowsDeviceBaseName(filePath) {
2570
+ const normalized = filePath.replace(/\//g, "\\").replace(/[\\]+$/g, "");
2571
+ const lastSegment = normalized.split("\\").filter(Boolean).at(-1) ?? normalized;
2572
+ const withoutStream = lastSegment.split(":")[0] ?? lastSegment;
2573
+ const withoutTrailingIgnoredChars = withoutStream.replace(/[ .]+$/g, "");
2574
+ return (withoutTrailingIgnoredChars.split(".")[0] ?? withoutTrailingIgnoredChars).toUpperCase();
2575
+ }
2576
+ function matchWindowsDeviceReadPath(filePath) {
2577
+ const normalized = filePath.replace(/\//g, "\\");
2578
+ if (/^\\\\\.\\/.test(normalized) || /^\\\\\?\\GLOBALROOT\\Device\\/i.test(normalized)) {
2579
+ return { path: normalized, reason: "windows-device" };
2580
+ }
2581
+ const baseName = normalizeWindowsDeviceBaseName(filePath);
2582
+ if (WINDOWS_RESERVED_DEVICE_NAMES.has(baseName)) {
2583
+ return { path: normalized, reason: "windows-device" };
2584
+ }
2585
+ return undefined;
2586
+ }
2587
+ function matchUnsafeDeviceReadPath(filePath, options = {}) {
2588
+ const platform = options.platform ?? process.platform;
2589
+ for (const candidate of candidateReadPaths(filePath)) {
2590
+ const match = platform === "win32"
2591
+ ? matchWindowsDeviceReadPath(candidate)
2592
+ : matchPosixDeviceReadPath(candidate, options.cwd);
2593
+ if (match) {
2594
+ return match;
2595
+ }
2596
+ }
2597
+ return undefined;
2598
+ }
2599
+ function isUnsafeDeviceReadPath(filePath, options) {
2600
+ return matchUnsafeDeviceReadPath(filePath, options) !== undefined;
2601
+ }
2602
+ function assertNoUnsafeDeviceReadPath(filePath, options) {
2603
+ if (matchUnsafeDeviceReadPath(filePath, options)) {
2604
+ throw new errors_FsSafeError("device-path", `file reads from unsafe device paths are not allowed: ${filePath}`);
2605
+ }
2606
+ }
2607
+
2390
2608
  ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/read-opened-file.js
2391
2609
 
2392
2610
  async function read_opened_file_readOpenedFileSafely(params) {
@@ -2738,6 +2956,7 @@ async function serializePathWrite(key, run) {
2738
2956
 
2739
2957
 
2740
2958
 
2959
+
2741
2960
 
2742
2961
 
2743
2962
  function logWarn(message) {
@@ -2763,20 +2982,16 @@ const OPEN_APPEND_CREATE_FLAGS = external_node_fs_namespaceObject.constants.O_RD
2763
2982
  external_node_fs_namespaceObject.constants.O_EXCL |
2764
2983
  (SUPPORTS_NOFOLLOW ? external_node_fs_namespaceObject.constants.O_NOFOLLOW : 0);
2765
2984
  const DEFAULT_ROOT_MAX_BYTES = 16 * 1024 * 1024;
2766
- function closeHandleForDispose(handle) {
2767
- return handle.close().catch(() => undefined);
2768
- }
2769
2985
  function openResult(params) {
2770
2986
  return {
2771
2987
  handle: params.handle,
2772
2988
  realPath: params.realPath,
2773
2989
  stat: params.stat,
2774
- [Symbol.asyncDispose]: async () => {
2775
- await closeHandleForDispose(params.handle);
2776
- },
2990
+ [Symbol.asyncDispose]: () => params.handle.close().catch(() => undefined),
2777
2991
  };
2778
2992
  }
2779
2993
  async function openVerifiedLocalFile(filePath, options) {
2994
+ assertNoUnsafeDeviceReadPath(filePath);
2780
2995
  const fsSafeTestHooks = getFsSafeTestHooks();
2781
2996
  // Reject directories before opening so we never surface EISDIR to callers (e.g. tool
2782
2997
  // results that get sent to messaging channels). See openclaw/openclaw#31186.
@@ -3301,9 +3516,7 @@ async function openWritableFileInRoot(root, params) {
3301
3516
  createdForWrite,
3302
3517
  realPath,
3303
3518
  stat,
3304
- [Symbol.asyncDispose]: async () => {
3305
- await closeHandleForDispose(handle);
3306
- },
3519
+ [Symbol.asyncDispose]: () => handle.close().catch(() => undefined),
3307
3520
  };
3308
3521
  }
3309
3522
  catch (err) {
@@ -3340,10 +3553,15 @@ async function appendFileInRoot(root, params) {
3340
3553
  }
3341
3554
  if (typeof params.data === "string") {
3342
3555
  await target.handle.appendFile(`${prefix}${params.data}`, params.encoding ?? "utf8");
3343
- return;
3344
3556
  }
3345
- const payload = prefix.length > 0 ? Buffer.concat([Buffer.from(prefix, "utf8"), params.data]) : params.data;
3346
- await target.handle.appendFile(payload);
3557
+ else {
3558
+ const payload = prefix.length > 0 ? Buffer.concat([Buffer.from(prefix, "utf8"), params.data]) : params.data;
3559
+ await target.handle.appendFile(payload);
3560
+ }
3561
+ await target.handle.sync();
3562
+ if (target.createdForWrite) {
3563
+ await syncDirectoryBestEffort(external_node_path_namespaceObject.dirname(target.realPath));
3564
+ }
3347
3565
  }
3348
3566
  finally {
3349
3567
  await target.handle.close().catch(() => { });
@@ -3400,42 +3618,45 @@ async function writeFileInRoot(root, params) {
3400
3618
  }
3401
3619
  const pinned = await resolvePinnedWriteTargetInRoot(root, params.relativePath, params.mode, params.denyMutations);
3402
3620
  await serializePathWrite(pinned.targetPath, async () => {
3403
- let identity;
3404
- try {
3405
- identity = await runPinnedWriteHelper({
3406
- rootPath: pinned.rootReal,
3407
- relativeParentPath: pinned.relativeParentPath,
3408
- basename: pinned.basename,
3409
- mkdir: params.mkdir !== false,
3410
- mode: params.mode ?? pinned.mode,
3411
- overwrite: params.overwrite,
3412
- input: {
3413
- kind: "buffer",
3414
- data: params.data,
3415
- encoding: params.encoding,
3416
- },
3417
- });
3418
- }
3419
- catch (error) {
3420
- if (params.overwrite === false && isAlreadyExistsError(error)) {
3421
- throw new errors_FsSafeError("already-exists", "file already exists", {
3422
- cause: error instanceof Error ? error : undefined,
3423
- });
3424
- }
3425
- throw normalizePinnedWriteError(error);
3426
- }
3427
- try {
3428
- await verifyAtomicWriteResult({
3429
- root,
3430
- targetPath: pinned.targetPath,
3431
- expectedIdentity: identity,
3621
+ await commitPinnedWriteInRoot(root, pinned, params);
3622
+ });
3623
+ }
3624
+ async function commitPinnedWriteInRoot(root, pinned, params) {
3625
+ let identity;
3626
+ try {
3627
+ identity = await runPinnedWriteHelper({
3628
+ rootPath: pinned.rootReal,
3629
+ relativeParentPath: pinned.relativeParentPath,
3630
+ basename: pinned.basename,
3631
+ mkdir: params.mkdir !== false,
3632
+ mode: params.mode ?? pinned.mode,
3633
+ overwrite: params.overwrite,
3634
+ input: {
3635
+ kind: "buffer",
3636
+ data: params.data,
3637
+ encoding: params.encoding,
3638
+ },
3639
+ });
3640
+ }
3641
+ catch (error) {
3642
+ if (params.overwrite === false && isAlreadyExistsError(error)) {
3643
+ throw new errors_FsSafeError("already-exists", "file already exists", {
3644
+ cause: error instanceof Error ? error : undefined,
3432
3645
  });
3433
3646
  }
3434
- catch (err) {
3435
- emitWriteBoundaryWarning(`post-write verification failed: ${String(err)}`);
3436
- throw err;
3437
- }
3438
- });
3647
+ throw normalizePinnedWriteError(error);
3648
+ }
3649
+ try {
3650
+ await verifyAtomicWriteResult({
3651
+ root,
3652
+ targetPath: pinned.targetPath,
3653
+ expectedIdentity: identity,
3654
+ });
3655
+ }
3656
+ catch (err) {
3657
+ emitWriteBoundaryWarning(`post-write verification failed: ${String(err)}`);
3658
+ throw err;
3659
+ }
3439
3660
  }
3440
3661
  async function copyFileInRoot(root, params) {
3441
3662
  assertValidRootRelativePath(params.relativePath);
@@ -4591,7 +4812,7 @@ const regexes_base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0
4591
4812
  const regexes_base64url = /^[A-Za-z0-9_-]*$/;
4592
4813
  // based on https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address
4593
4814
  // export const hostname: RegExp = /^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+$/;
4594
- const hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
4815
+ const regexes_hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
4595
4816
  const domain = /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
4596
4817
  const httpProtocol = /^https?$/;
4597
4818
  // https://blog.stevenlevithan.com/archives/validate-phone-number#r4-3 (regex sans spaces)
@@ -12775,8 +12996,6 @@ function hasProtoKey(value) {
12775
12996
 
12776
12997
  ;// CONCATENATED MODULE: external "node:module"
12777
12998
  const external_node_module_namespaceObject = __rspack_createRequire_require("node:module");
12778
- ;// CONCATENATED MODULE: external "node:url"
12779
- const external_node_url_namespaceObject = __rspack_createRequire_require("node:url");
12780
12999
  ;// CONCATENATED MODULE: ./src/gateways/resolve-sdk.ts
12781
13000
 
12782
13001
 
@@ -15052,4 +15271,4 @@ if (installedChunkData !== 0) { // 0 means "already installed".'
15052
15271
  // module factories are used so entry inlining is disabled
15053
15272
  // startup
15054
15273
  // Load entry module and return exports
15055
- var __webpack_exports__ = __webpack_require__(341);
15274
+ var __webpack_exports__ = __webpack_require__(818);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lousy-agents/agent-shell",
3
- "version": "5.15.4",
3
+ "version": "5.15.6",
4
4
  "description": "A flight recorder for npm script execution",
5
5
  "type": "module",
6
6
  "repository": {
@@ -36,11 +36,11 @@
36
36
  "build": "rspack build --config rspack.config.ts && chmod +x dist/index.js"
37
37
  },
38
38
  "dependencies": {
39
- "@openclaw/fs-safe": "0.3.0",
39
+ "@openclaw/fs-safe": "0.4.0",
40
40
  "zod": "4.4.3"
41
41
  },
42
42
  "peerDependencies": {
43
- "@github/copilot-sdk": "1.0.1"
43
+ "@github/copilot-sdk": "1.0.3"
44
44
  },
45
45
  "peerDependenciesMeta": {
46
46
  "@github/copilot-sdk": {