@lousy-agents/mcp 5.22.6 → 5.22.8

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/mcp-server.js +54 -22
  2. package/package.json +1 -1
@@ -37580,12 +37580,23 @@ function parseMode(value) {
37580
37580
  function configureFsSafeNative(config) {
37581
37581
  overrideConfig = { ...overrideConfig, ...config };
37582
37582
  }
37583
+ function rejectLegacyMode() {
37584
+ for (const source of ["FS_SAFE_PYTHON_MODE", "OPENCLAW_FS_SAFE_PYTHON_MODE"]) {
37585
+ if (process.env[source] === undefined)
37586
+ continue;
37587
+ const mode = parseMode(process.env[source]) ?? "auto";
37588
+ throw new Error(`${source} has been removed. Set FS_SAFE_NATIVE_MODE=${mode} or ` +
37589
+ `configureFsSafeNative({ mode: "${mode}" }) before using fs-safe, then remove ${source}. ` +
37590
+ "Legacy mode settings no longer select native policy.");
37591
+ }
37592
+ return "auto";
37593
+ }
37583
37594
  function getFsSafeNativeConfig() {
37584
37595
  return {
37585
37596
  mode: overrideConfig.mode ??
37586
37597
  parseMode(process.env.FS_SAFE_NATIVE_MODE) ??
37587
37598
  parseMode(process.env.OPENCLAW_FS_SAFE_NATIVE_MODE) ??
37588
- "auto",
37599
+ rejectLegacyMode(),
37589
37600
  };
37590
37601
  }
37591
37602
  /** Internal provenance; keep the public configuration shape unchanged. */
@@ -37597,13 +37608,13 @@ function getNativeModeSetting() {
37597
37608
  if (mode !== undefined)
37598
37609
  return { mode, source };
37599
37610
  }
37600
- return { mode: "auto", source: "default" };
37611
+ return { mode: rejectLegacyMode(), source: "default" };
37601
37612
  }
37602
37613
  function isFsSafeNativeRequired() {
37603
37614
  return (overrideConfig.mode ??
37604
37615
  parseMode(process.env.FS_SAFE_NATIVE_MODE) ??
37605
37616
  parseMode(process.env.OPENCLAW_FS_SAFE_NATIVE_MODE) ??
37606
- "auto") === "require";
37617
+ rejectLegacyMode()) === "require";
37607
37618
  }
37608
37619
  function __resetFsSafeNativeConfigForTest() {
37609
37620
  overrideConfig = {};
@@ -42445,14 +42456,15 @@ function pathExistsSync(targetPath) {
42445
42456
  function resolvePathViaExistingAncestorSync(targetPath) {
42446
42457
  return resolveExistingAncestor(targetPath, "ordinary");
42447
42458
  }
42448
- function resolveExistingAncestor(targetPath, mode) {
42449
- const exists = mode === "native" ? root_path_existing_pathExists : pathExistsSync;
42450
- const canonicalize = mode === "native" ? realpath_realpathSync.native : realpath_realpathSync;
42459
+ function resolveExistingAncestor(targetPath, mode, preserveRawSegments = false, remainingHops = 64) {
42460
+ const exists = mode === "native" || preserveRawSegments ? root_path_existing_pathExists : pathExistsSync;
42461
+ const canonicalize = realpath_realpathSync.native;
42451
42462
  windows_path_alias_assertNoWindowsPathAlias(targetPath);
42452
42463
  const normalized = windows_path_alias_resolvePathPreservingWindowsRoot(targetPath);
42453
42464
  windows_path_alias_assertNoWindowsPathAlias(normalized);
42454
- let cursor = normalized;
42455
- const filesystemRoot = external_node_path_.parse(normalized).root;
42465
+ const candidate = preserveRawSegments ? absolutePathWithRawSegments(targetPath) : normalized;
42466
+ let cursor = candidate;
42467
+ const filesystemRoot = external_node_path_.parse(candidate).root;
42456
42468
  while (cursor !== filesystemRoot &&
42457
42469
  !exists(cursor)) {
42458
42470
  cursor = external_node_path_.dirname(cursor);
@@ -42464,22 +42476,30 @@ function resolveExistingAncestor(targetPath, mode) {
42464
42476
  try {
42465
42477
  rawResolvedAncestor = canonicalize(windows_path_alias_pathForWindowsFilesystem(cursor));
42466
42478
  }
42467
- catch {
42468
- return normalized;
42479
+ catch (error) {
42480
+ if (!preserveRawSegments)
42481
+ return normalized;
42482
+ if (!path_isNotFoundPathError(error))
42483
+ throw error;
42484
+ rawResolvedAncestor = resolveSymlinkHopPath(cursor, mode, false, remainingHops);
42469
42485
  }
42470
42486
  windows_path_alias_assertNoWindowsPathAlias(rawResolvedAncestor);
42471
42487
  const resolvedAncestor = windows_path_alias_resolvePathPreservingWindowsRoot(rawResolvedAncestor);
42472
42488
  windows_path_alias_assertNoWindowsPathAlias(resolvedAncestor);
42473
42489
  // Keep a leading suffix separator relative to the canonical ancestor.
42474
- const resolved = cursor === normalized
42490
+ const suffix = candidate.slice(cursor.length);
42491
+ if (preserveRawSegments && suffix.split(external_node_path_.sep).includes("..")) {
42492
+ throw new errors_FsSafeError("symlink", "symlink target has an unresolved parent component");
42493
+ }
42494
+ const resolved = cursor === candidate
42475
42495
  ? resolvedAncestor
42476
- : external_node_path_.resolve(resolvedAncestor, `.${external_node_path_.sep}${normalized.slice(cursor.length)}`);
42496
+ : external_node_path_.resolve(resolvedAncestor, `.${external_node_path_.sep}${suffix}`);
42477
42497
  windows_path_alias_assertNoWindowsPathAlias(resolved);
42478
42498
  return resolved;
42479
42499
  }
42480
- function resolveSymlinkHopPath(symlinkPath, mode, rejectUnresolved) {
42500
+ function resolveSymlinkHopPath(symlinkPath, mode, rejectUnresolved, remainingHops = 64) {
42481
42501
  try {
42482
- const canonicalize = mode === "native" ? realpath_realpathSync.native : realpath_realpathSync;
42502
+ const canonicalize = realpath_realpathSync.native;
42483
42503
  const rawRealPath = canonicalize(symlinkPath);
42484
42504
  windows_path_alias_assertNoWindowsPathAlias(rawRealPath, "filesystem", "resolved symlink path uses a Windows filesystem namespace alias");
42485
42505
  const realPath = windows_path_alias_resolvePathPreservingWindowsRoot(rawRealPath);
@@ -42492,11 +42512,16 @@ function resolveSymlinkHopPath(symlinkPath, mode, rejectUnresolved) {
42492
42512
  }
42493
42513
  if (!path_isNotFoundPathError(error))
42494
42514
  throw error;
42515
+ if (remainingHops <= 0)
42516
+ throw new errors_FsSafeError("symlink", "too many unresolved symlink hops");
42495
42517
  const linkTarget = external_node_fs_.readlinkSync(symlinkPath);
42496
42518
  windows_path_alias_assertNoWindowsPathAlias(linkTarget, "filesystem", "symlink target uses a Windows filesystem namespace alias");
42497
42519
  const linkDir = windows_path_alias_resolvePathPreservingWindowsRoot(external_node_path_.dirname(symlinkPath));
42498
- const targetPath = windows_path_alias_resolvePathFromBasePreservingWindowsRoot(linkDir, linkTarget);
42499
- const resolved = resolveExistingAncestor(targetPath, mode);
42520
+ // Keep parent segments until the kernel has resolved the existing prefix.
42521
+ const targetPath = external_node_path_.isAbsolute(linkTarget) ? linkTarget
42522
+ : external_node_path_.parse(linkTarget).root ? windows_path_alias_resolvePathFromBasePreservingWindowsRoot(linkDir, linkTarget)
42523
+ : `${linkDir}${external_node_path_.sep}${linkTarget}`;
42524
+ const resolved = resolveExistingAncestor(targetPath, mode, true, remainingHops - 1);
42500
42525
  windows_path_alias_assertNoWindowsPathAlias(resolved, "filesystem", "resolved symlink path uses a Windows filesystem namespace alias");
42501
42526
  return resolved;
42502
42527
  }
@@ -46485,8 +46510,8 @@ function assertResolvedLinkDirectory(pathname, isLast) {
46485
46510
  const stat = external_node_fs_.statSync(windows_path_alias_pathForWindowsFilesystem(pathname));
46486
46511
  assertDirectoryBeforeMoreSegments(stat, pathname, isLast);
46487
46512
  }
46488
- // Both public APIs use synchronous metadata; only canonicalization and ancestor
46489
- // existence differ. Promise wrappers preserve the asynchronous rejection API.
46513
+ // Both public APIs use kernel canonicalization and synchronous metadata; only
46514
+ // ancestor existence differs. Promise wrappers preserve asynchronous rejection.
46490
46515
  function traverseRootPath(params, { mode = "native", observation: observationOutput, observeRoot, removalReceipts }) {
46491
46516
  const input = captureValidRootPathInputs(params);
46492
46517
  const rawAbsolutePath = absolutePathWithRawSegments(input.absolutePath);
@@ -54476,7 +54501,7 @@ function directoryChangedError(error) {
54476
54501
  return error;
54477
54502
  return new errors_FsSafeError("path-mismatch", "directory changed during operation", errorCauseOptions(error));
54478
54503
  }
54479
- async function assertRootDirectoryObservationGuard(root, guard) {
54504
+ async function assertRootDirectoryObservationGuard(root, guard, backend) {
54480
54505
  if (isNativeDirectoryObservationGuard(guard)) {
54481
54506
  throw new errors_FsSafeError("path-mismatch", "native directory observation cannot be revalidated");
54482
54507
  }
@@ -54485,7 +54510,9 @@ async function assertRootDirectoryObservationGuard(root, guard) {
54485
54510
  identity.dev === root.rootIdentity.dev && identity.ino === root.rootIdentity.ino;
54486
54511
  if (guardPinsRoot) {
54487
54512
  try {
54488
- if ("identity" in guard)
54513
+ if (backend && "identity" in guard)
54514
+ assertReceiptDirectoryGuardSync(root, guard, backend);
54515
+ else if ("identity" in guard)
54489
54516
  assertDirectoryObservationGuardSync(guard);
54490
54517
  else
54491
54518
  await assertAsyncDirectoryGuard(guard);
@@ -54508,7 +54535,9 @@ async function assertRootDirectoryObservationGuard(root, guard) {
54508
54535
  await assertRootIdentityCurrent(root);
54509
54536
  }
54510
54537
  try {
54511
- if ("identity" in guard)
54538
+ if (backend && "identity" in guard)
54539
+ assertReceiptDirectoryGuardSync(root, guard, backend);
54540
+ else if ("identity" in guard)
54512
54541
  assertDirectoryObservationGuardSync(guard);
54513
54542
  else
54514
54543
  await assertAsyncDirectoryGuard(guard);
@@ -54662,12 +54691,15 @@ async function openRootDirectoryListing(root, directory, options, receipt) {
54662
54691
  identity: { dev: admitted.stat.dev, ino: admitted.stat.ino },
54663
54692
  }, admitted.dir, admitted.realPath);
54664
54693
  }
54694
+ // Windows watch listings keep every fence while sharing one handle for its
54695
+ // identity/path queries. POSIX pathname checks are cheaper than this helper.
54696
+ const backend = getNativeDirectoryObservationBackend(options.exactIdentity === true && process.platform === "win32");
54665
54697
  const assertCurrent = async () => {
54666
54698
  options.signal?.throwIfAborted();
54667
54699
  if (receipt)
54668
54700
  assertRootPathObservationReceiptCurrent(root, receipt);
54669
54701
  else
54670
- await assertRootDirectoryObservationGuard(root, guard);
54702
+ await assertRootDirectoryObservationGuard(root, guard, backend);
54671
54703
  options.signal?.throwIfAborted();
54672
54704
  };
54673
54705
  const paths = { directory: guard.realPath, names: new Map() };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lousy-agents/mcp",
3
- "version": "5.22.6",
3
+ "version": "5.22.8",
4
4
  "description": "MCP server for lousy-agents - provides AI coding assistant tools via the Model Context Protocol",
5
5
  "type": "module",
6
6
  "repository": {