@lousy-agents/agent-shell 5.14.10 → 5.15.1
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.
- package/dist/index.js +279 -123
- 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
|
-
|
|
5
|
+
341(__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");
|
|
@@ -546,6 +546,191 @@ function guardedRmSync(params) {
|
|
|
546
546
|
}), { verifyAfter: params.verifyAfter });
|
|
547
547
|
}
|
|
548
548
|
|
|
549
|
+
;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/deny-mutations.js
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
async function pathExists(filePath) {
|
|
555
|
+
try {
|
|
556
|
+
await promises_namespaceObject.lstat(filePath);
|
|
557
|
+
return true;
|
|
558
|
+
}
|
|
559
|
+
catch (err) {
|
|
560
|
+
if (!path_isNotFoundPathError(err)) {
|
|
561
|
+
throw err;
|
|
562
|
+
}
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
async function resolvePathViaExistingAncestor(targetPath) {
|
|
567
|
+
const normalized = external_node_path_namespaceObject.resolve(targetPath);
|
|
568
|
+
let cursor = normalized;
|
|
569
|
+
const missingSuffix = [];
|
|
570
|
+
while (external_node_path_namespaceObject.dirname(cursor) !== cursor && !(await pathExists(cursor))) {
|
|
571
|
+
missingSuffix.unshift(external_node_path_namespaceObject.basename(cursor));
|
|
572
|
+
cursor = external_node_path_namespaceObject.dirname(cursor);
|
|
573
|
+
}
|
|
574
|
+
if (!(await pathExists(cursor))) {
|
|
575
|
+
return normalized;
|
|
576
|
+
}
|
|
577
|
+
try {
|
|
578
|
+
const resolvedAncestor = external_node_path_namespaceObject.resolve(await promises_namespaceObject.realpath(cursor));
|
|
579
|
+
return missingSuffix.length === 0
|
|
580
|
+
? resolvedAncestor
|
|
581
|
+
: external_node_path_namespaceObject.resolve(resolvedAncestor, ...missingSuffix);
|
|
582
|
+
}
|
|
583
|
+
catch {
|
|
584
|
+
return normalized;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
async function comparablePaths(rawPath) {
|
|
588
|
+
path_assertNoNulPathInput(rawPath, "path contains a NUL byte");
|
|
589
|
+
const resolved = external_node_path_namespaceObject.resolve(rawPath);
|
|
590
|
+
return new Set([resolved, await resolvePathViaExistingAncestor(resolved)]);
|
|
591
|
+
}
|
|
592
|
+
function isSamePath(left, right) {
|
|
593
|
+
return path_isPathInside(left, right) && path_isPathInside(right, left);
|
|
594
|
+
}
|
|
595
|
+
function hasPolicyEntries(policy) {
|
|
596
|
+
return Boolean(policy?.paths?.length || policy?.prefixes?.length);
|
|
597
|
+
}
|
|
598
|
+
function policyPathEntries(entries) {
|
|
599
|
+
const paths = [];
|
|
600
|
+
for (const entry of entries ?? []) {
|
|
601
|
+
if (entry.length === 0) {
|
|
602
|
+
throw new errors_FsSafeError("invalid-path", "deny mutation paths must be non-empty");
|
|
603
|
+
}
|
|
604
|
+
path_assertNoNulPathInput(entry, "deny mutation path contains a NUL byte");
|
|
605
|
+
if (!external_node_path_namespaceObject.isAbsolute(entry)) {
|
|
606
|
+
throw new errors_FsSafeError("invalid-path", "deny mutation paths must be absolute");
|
|
607
|
+
}
|
|
608
|
+
paths.push(entry);
|
|
609
|
+
}
|
|
610
|
+
return paths;
|
|
611
|
+
}
|
|
612
|
+
async function assertMutationNotDenied(filePath, policy, options = {}) {
|
|
613
|
+
if (!hasPolicyEntries(policy)) {
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
const targetPaths = await comparablePaths(filePath);
|
|
617
|
+
for (const deniedPath of policyPathEntries(policy.paths)) {
|
|
618
|
+
const deniedPaths = await comparablePaths(deniedPath);
|
|
619
|
+
for (const target of targetPaths) {
|
|
620
|
+
for (const denied of deniedPaths) {
|
|
621
|
+
if (isSamePath(denied, target) ||
|
|
622
|
+
(options.protectAncestors === true && path_isPathInside(target, denied))) {
|
|
623
|
+
throw new errors_FsSafeError("denied-path", "path is denied by denyMutations policy");
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
for (const deniedPrefix of policyPathEntries(policy.prefixes)) {
|
|
629
|
+
const deniedPaths = await comparablePaths(deniedPrefix);
|
|
630
|
+
for (const target of targetPaths) {
|
|
631
|
+
for (const denied of deniedPaths) {
|
|
632
|
+
if (path_isPathInside(denied, target) ||
|
|
633
|
+
(options.protectAncestors === true && path_isPathInside(target, denied))) {
|
|
634
|
+
throw new errors_FsSafeError("denied-path", "path is denied by denyMutations policy");
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
function mergeDenyMutationPolicies(defaultPolicy, callPolicy) {
|
|
641
|
+
if (!defaultPolicy) {
|
|
642
|
+
return callPolicy;
|
|
643
|
+
}
|
|
644
|
+
if (!callPolicy) {
|
|
645
|
+
return defaultPolicy;
|
|
646
|
+
}
|
|
647
|
+
return {
|
|
648
|
+
paths: [...(defaultPolicy.paths ?? []), ...(callPolicy.paths ?? [])],
|
|
649
|
+
prefixes: [...(defaultPolicy.prefixes ?? []), ...(callPolicy.prefixes ?? [])],
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/opened-realpath.js
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
async function resolveOpenedFileRealPathForHandle(handle, ioPath) {
|
|
660
|
+
const handleStat = await handle.stat();
|
|
661
|
+
const fdCandidates = process.platform === "linux"
|
|
662
|
+
? [`/proc/self/fd/${handle.fd}`, `/dev/fd/${handle.fd}`]
|
|
663
|
+
: process.platform === "win32"
|
|
664
|
+
? []
|
|
665
|
+
: [`/dev/fd/${handle.fd}`];
|
|
666
|
+
for (const fdPath of fdCandidates) {
|
|
667
|
+
try {
|
|
668
|
+
const fdRealPath = await promises_namespaceObject.realpath(fdPath);
|
|
669
|
+
const fdRealStat = await promises_namespaceObject.stat(fdRealPath);
|
|
670
|
+
if (file_identity_sameFileIdentity(handleStat, fdRealStat)) {
|
|
671
|
+
return fdRealPath;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
catch {
|
|
675
|
+
// try next fd path
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
try {
|
|
679
|
+
const ioRealPath = await promises_namespaceObject.realpath(ioPath);
|
|
680
|
+
const ioRealStat = await promises_namespaceObject.stat(ioRealPath);
|
|
681
|
+
if (file_identity_sameFileIdentity(handleStat, ioRealStat)) {
|
|
682
|
+
return ioRealPath;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
catch (err) {
|
|
686
|
+
if (!path_isNotFoundPathError(err)) {
|
|
687
|
+
throw err;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
const parentResolved = await resolveOpenedFileRealPathFromParent(handleStat, ioPath);
|
|
691
|
+
if (parentResolved) {
|
|
692
|
+
return parentResolved;
|
|
693
|
+
}
|
|
694
|
+
throw new errors_FsSafeError("path-mismatch", "unable to resolve opened file path");
|
|
695
|
+
}
|
|
696
|
+
async function resolveOpenedFileRealPathFromParent(handleStat, ioPath) {
|
|
697
|
+
let parentReal;
|
|
698
|
+
try {
|
|
699
|
+
parentReal = await promises_namespaceObject.realpath(external_node_path_namespaceObject.dirname(ioPath));
|
|
700
|
+
}
|
|
701
|
+
catch (err) {
|
|
702
|
+
if (path_isNotFoundPathError(err)) {
|
|
703
|
+
return null;
|
|
704
|
+
}
|
|
705
|
+
throw err;
|
|
706
|
+
}
|
|
707
|
+
let entries;
|
|
708
|
+
try {
|
|
709
|
+
entries = await promises_namespaceObject.readdir(parentReal);
|
|
710
|
+
}
|
|
711
|
+
catch (err) {
|
|
712
|
+
if (path_isNotFoundPathError(err)) {
|
|
713
|
+
return null;
|
|
714
|
+
}
|
|
715
|
+
throw err;
|
|
716
|
+
}
|
|
717
|
+
for (const entry of entries.toSorted()) {
|
|
718
|
+
const candidatePath = external_node_path_namespaceObject.join(parentReal, entry);
|
|
719
|
+
try {
|
|
720
|
+
const candidateStat = await promises_namespaceObject.lstat(candidatePath);
|
|
721
|
+
if (candidateStat.isFile() && file_identity_sameFileIdentity(handleStat, candidateStat)) {
|
|
722
|
+
return await promises_namespaceObject.realpath(candidatePath);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
catch (err) {
|
|
726
|
+
if (!path_isNotFoundPathError(err)) {
|
|
727
|
+
throw err;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
733
|
+
|
|
549
734
|
;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/pinned-python-config.js
|
|
550
735
|
let overrideConfig = {};
|
|
551
736
|
function parseMode(value) {
|
|
@@ -1390,7 +1575,7 @@ async function runPinnedWriteHelper(params) {
|
|
|
1390
1575
|
relativeParentPath: params.relativeParentPath,
|
|
1391
1576
|
});
|
|
1392
1577
|
if (getFsSafePythonConfig().mode === "off") {
|
|
1393
|
-
return await
|
|
1578
|
+
return await runPinnedWriteFallback(params);
|
|
1394
1579
|
}
|
|
1395
1580
|
if (params.input.kind === "stream") {
|
|
1396
1581
|
try {
|
|
@@ -1398,7 +1583,7 @@ async function runPinnedWriteHelper(params) {
|
|
|
1398
1583
|
}
|
|
1399
1584
|
catch (error) {
|
|
1400
1585
|
if (canFallbackFromPythonError(error)) {
|
|
1401
|
-
return await
|
|
1586
|
+
return await runPinnedWriteFallback(params);
|
|
1402
1587
|
}
|
|
1403
1588
|
throw error;
|
|
1404
1589
|
}
|
|
@@ -1422,7 +1607,7 @@ async function runPinnedWriteHelper(params) {
|
|
|
1422
1607
|
}
|
|
1423
1608
|
catch (error) {
|
|
1424
1609
|
if (canFallbackFromPythonError(error)) {
|
|
1425
|
-
return await
|
|
1610
|
+
return await runPinnedWriteFallback(params);
|
|
1426
1611
|
}
|
|
1427
1612
|
throw error;
|
|
1428
1613
|
}
|
|
@@ -1449,12 +1634,6 @@ async function runPinnedCopyHelper(params) {
|
|
|
1449
1634
|
},
|
|
1450
1635
|
});
|
|
1451
1636
|
}
|
|
1452
|
-
async function runPinnedWriteFallbackOrThrow(params, cause) {
|
|
1453
|
-
if (process.platform !== "win32") {
|
|
1454
|
-
throw new errors_FsSafeError("helper-unavailable", "Python helper is required for pinned writes on this platform", { cause });
|
|
1455
|
-
}
|
|
1456
|
-
return await runPinnedWriteFallback(params);
|
|
1457
|
-
}
|
|
1458
1637
|
async function runPinnedWriteFallback(params) {
|
|
1459
1638
|
const parentPath = params.relativeParentPath
|
|
1460
1639
|
? external_node_path_namespaceObject.join(params.rootPath, ...params.relativeParentPath.split("/"))
|
|
@@ -1577,7 +1756,7 @@ async function resolveRootPath(params) {
|
|
|
1577
1756
|
const absolutePath = external_node_path_namespaceObject.resolve(params.absolutePath);
|
|
1578
1757
|
const rootCanonicalPath = params.rootCanonicalPath
|
|
1579
1758
|
? external_node_path_namespaceObject.resolve(params.rootCanonicalPath)
|
|
1580
|
-
: await
|
|
1759
|
+
: await root_path_resolvePathViaExistingAncestor(rootPath);
|
|
1581
1760
|
const context = createBoundaryResolutionContext({
|
|
1582
1761
|
resolveParams: params,
|
|
1583
1762
|
rootPath,
|
|
@@ -1946,7 +2125,7 @@ async function resolveOutsideLexicalCanonicalPathAsync(params) {
|
|
|
1946
2125
|
if (path_isPathInside(params.rootPath, params.absolutePath)) {
|
|
1947
2126
|
return undefined;
|
|
1948
2127
|
}
|
|
1949
|
-
return await
|
|
2128
|
+
return await root_path_resolvePathViaExistingAncestor(params.absolutePath);
|
|
1950
2129
|
}
|
|
1951
2130
|
function resolveOutsideLexicalCanonicalPathSync(params) {
|
|
1952
2131
|
if (isPathInside(params.rootPath, params.absolutePath)) {
|
|
@@ -1993,11 +2172,11 @@ function buildResolvedRootPath(params) {
|
|
|
1993
2172
|
kind: params.kind.kind,
|
|
1994
2173
|
};
|
|
1995
2174
|
}
|
|
1996
|
-
async function
|
|
2175
|
+
async function root_path_resolvePathViaExistingAncestor(targetPath) {
|
|
1997
2176
|
const normalized = external_node_path_namespaceObject.resolve(targetPath);
|
|
1998
2177
|
let cursor = normalized;
|
|
1999
2178
|
const missingSuffix = [];
|
|
2000
|
-
while (!isFilesystemRoot(cursor) && !(await
|
|
2179
|
+
while (!isFilesystemRoot(cursor) && !(await root_path_pathExists(cursor))) {
|
|
2001
2180
|
missingSuffix.unshift(external_node_path_namespaceObject.basename(cursor));
|
|
2002
2181
|
const parent = external_node_path_namespaceObject.dirname(cursor);
|
|
2003
2182
|
if (parent === cursor) {
|
|
@@ -2005,7 +2184,7 @@ async function resolvePathViaExistingAncestor(targetPath) {
|
|
|
2005
2184
|
}
|
|
2006
2185
|
cursor = parent;
|
|
2007
2186
|
}
|
|
2008
|
-
if (!(await
|
|
2187
|
+
if (!(await root_path_pathExists(cursor))) {
|
|
2009
2188
|
return normalized;
|
|
2010
2189
|
}
|
|
2011
2190
|
try {
|
|
@@ -2117,7 +2296,7 @@ function shortPath(value) {
|
|
|
2117
2296
|
function isFilesystemRoot(candidate) {
|
|
2118
2297
|
return external_node_path_namespaceObject.parse(candidate).root === candidate;
|
|
2119
2298
|
}
|
|
2120
|
-
async function
|
|
2299
|
+
async function root_path_pathExists(targetPath) {
|
|
2121
2300
|
try {
|
|
2122
2301
|
await promises_namespaceObject.lstat(targetPath);
|
|
2123
2302
|
return true;
|
|
@@ -2139,7 +2318,7 @@ async function resolveSymlinkHopPath(symlinkPath) {
|
|
|
2139
2318
|
}
|
|
2140
2319
|
const linkTarget = await promises_namespaceObject.readlink(symlinkPath);
|
|
2141
2320
|
const linkAbsolute = external_node_path_namespaceObject.resolve(external_node_path_namespaceObject.dirname(symlinkPath), linkTarget);
|
|
2142
|
-
return
|
|
2321
|
+
return root_path_resolvePathViaExistingAncestor(linkAbsolute);
|
|
2143
2322
|
}
|
|
2144
2323
|
}
|
|
2145
2324
|
function resolveSymlinkHopPathSync(symlinkPath) {
|
|
@@ -2208,6 +2387,23 @@ function path_policy_shortPath(value) {
|
|
|
2208
2387
|
return value;
|
|
2209
2388
|
}
|
|
2210
2389
|
|
|
2390
|
+
;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/read-opened-file.js
|
|
2391
|
+
|
|
2392
|
+
async function read_opened_file_readOpenedFileSafely(params) {
|
|
2393
|
+
if (params.maxBytes !== undefined && params.opened.stat.size > params.maxBytes) {
|
|
2394
|
+
throw new errors_FsSafeError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${params.opened.stat.size})`);
|
|
2395
|
+
}
|
|
2396
|
+
const buffer = await params.opened.handle.readFile();
|
|
2397
|
+
if (params.maxBytes !== undefined && buffer.byteLength > params.maxBytes) {
|
|
2398
|
+
throw new errors_FsSafeError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${buffer.byteLength})`);
|
|
2399
|
+
}
|
|
2400
|
+
return {
|
|
2401
|
+
buffer,
|
|
2402
|
+
realPath: params.opened.realPath,
|
|
2403
|
+
stat: params.opened.stat,
|
|
2404
|
+
};
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2211
2407
|
;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/path-stat.js
|
|
2212
2408
|
function pathStatFromStats(stat) {
|
|
2213
2409
|
return {
|
|
@@ -2535,6 +2731,10 @@ async function serializePathWrite(key, run) {
|
|
|
2535
2731
|
|
|
2536
2732
|
|
|
2537
2733
|
|
|
2734
|
+
|
|
2735
|
+
|
|
2736
|
+
|
|
2737
|
+
|
|
2538
2738
|
|
|
2539
2739
|
|
|
2540
2740
|
|
|
@@ -2733,6 +2933,7 @@ class RootHandle {
|
|
|
2733
2933
|
mkdir: this.defaults.mkdir,
|
|
2734
2934
|
mode: this.defaults.mode,
|
|
2735
2935
|
...options,
|
|
2936
|
+
denyMutations: mergeDenyMutationPolicies(this.defaults.denyMutations, options.denyMutations),
|
|
2736
2937
|
append: writeMode === "append",
|
|
2737
2938
|
truncateExisting: writeMode === "replace",
|
|
2738
2939
|
});
|
|
@@ -2744,18 +2945,29 @@ class RootHandle {
|
|
|
2744
2945
|
mkdir: this.defaults.mkdir,
|
|
2745
2946
|
mode: this.defaults.mode,
|
|
2746
2947
|
...options,
|
|
2948
|
+
denyMutations: mergeDenyMutationPolicies(this.defaults.denyMutations, options.denyMutations),
|
|
2747
2949
|
});
|
|
2748
2950
|
}
|
|
2749
|
-
async remove(relativePath) {
|
|
2951
|
+
async remove(relativePath, options = {}) {
|
|
2750
2952
|
assertValidRootRelativePath(relativePath);
|
|
2751
|
-
await removePathInRoot(this.context,
|
|
2953
|
+
await removePathInRoot(this.context, {
|
|
2954
|
+
relativePath,
|
|
2955
|
+
denyMutations: mergeDenyMutationPolicies(this.defaults.denyMutations, options.denyMutations),
|
|
2956
|
+
});
|
|
2752
2957
|
}
|
|
2753
|
-
async mkdir(relativePath) {
|
|
2958
|
+
async mkdir(relativePath, options = {}) {
|
|
2754
2959
|
assertValidRootRelativePath(relativePath);
|
|
2755
|
-
await mkdirPathInRoot(this.context, {
|
|
2960
|
+
await mkdirPathInRoot(this.context, {
|
|
2961
|
+
relativePath,
|
|
2962
|
+
denyMutations: mergeDenyMutationPolicies(this.defaults.denyMutations, options.denyMutations),
|
|
2963
|
+
});
|
|
2756
2964
|
}
|
|
2757
|
-
async ensureRoot() {
|
|
2758
|
-
await mkdirPathInRoot(this.context, {
|
|
2965
|
+
async ensureRoot(options = {}) {
|
|
2966
|
+
await mkdirPathInRoot(this.context, {
|
|
2967
|
+
relativePath: "",
|
|
2968
|
+
allowRoot: true,
|
|
2969
|
+
denyMutations: mergeDenyMutationPolicies(this.defaults.denyMutations, options.denyMutations),
|
|
2970
|
+
});
|
|
2759
2971
|
}
|
|
2760
2972
|
async write(relativePath, data, options = {}) {
|
|
2761
2973
|
await writeFileInRoot(this.context, {
|
|
@@ -2764,6 +2976,7 @@ class RootHandle {
|
|
|
2764
2976
|
mkdir: this.defaults.mkdir,
|
|
2765
2977
|
mode: this.defaults.mode,
|
|
2766
2978
|
...options,
|
|
2979
|
+
denyMutations: mergeDenyMutationPolicies(this.defaults.denyMutations, options.denyMutations),
|
|
2767
2980
|
});
|
|
2768
2981
|
}
|
|
2769
2982
|
async create(relativePath, data, options = {}) {
|
|
@@ -2773,6 +2986,7 @@ class RootHandle {
|
|
|
2773
2986
|
mkdir: this.defaults.mkdir,
|
|
2774
2987
|
mode: this.defaults.mode,
|
|
2775
2988
|
...options,
|
|
2989
|
+
denyMutations: mergeDenyMutationPolicies(this.defaults.denyMutations, options.denyMutations),
|
|
2776
2990
|
overwrite: false,
|
|
2777
2991
|
});
|
|
2778
2992
|
}
|
|
@@ -2795,6 +3009,7 @@ class RootHandle {
|
|
|
2795
3009
|
mkdir: this.defaults.mkdir,
|
|
2796
3010
|
mode: this.defaults.mode,
|
|
2797
3011
|
...options,
|
|
3012
|
+
denyMutations: mergeDenyMutationPolicies(this.defaults.denyMutations, options.denyMutations),
|
|
2798
3013
|
});
|
|
2799
3014
|
}
|
|
2800
3015
|
async exists(relativePath) {
|
|
@@ -2838,6 +3053,12 @@ class RootHandle {
|
|
|
2838
3053
|
async move(fromRelative, toRelative, options = {}) {
|
|
2839
3054
|
assertValidRootRelativePath(fromRelative);
|
|
2840
3055
|
assertValidRootRelativePath(toRelative);
|
|
3056
|
+
const denyMutations = mergeDenyMutationPolicies(this.defaults.denyMutations, options.denyMutations);
|
|
3057
|
+
await assertMoveMutationAllowed(this.context, {
|
|
3058
|
+
fromRelative,
|
|
3059
|
+
toRelative,
|
|
3060
|
+
denyMutations,
|
|
3061
|
+
});
|
|
2841
3062
|
try {
|
|
2842
3063
|
await runPinnedHelper("rename", this.rootReal, {
|
|
2843
3064
|
from: fromRelative,
|
|
@@ -2849,6 +3070,7 @@ class RootHandle {
|
|
|
2849
3070
|
if (canFallbackFromPythonError(error)) {
|
|
2850
3071
|
await movePathFallback(this.context, {
|
|
2851
3072
|
fromRelative,
|
|
3073
|
+
denyMutations,
|
|
2852
3074
|
overwrite: options.overwrite ?? false,
|
|
2853
3075
|
toRelative,
|
|
2854
3076
|
});
|
|
@@ -2897,7 +3119,7 @@ async function openFileInRoot(root, params) {
|
|
|
2897
3119
|
async function readFileInRoot(root, params) {
|
|
2898
3120
|
const opened = await openFileInRoot(root, params);
|
|
2899
3121
|
try {
|
|
2900
|
-
return await
|
|
3122
|
+
return await read_opened_file_readOpenedFileSafely({ opened, maxBytes: params.maxBytes });
|
|
2901
3123
|
}
|
|
2902
3124
|
finally {
|
|
2903
3125
|
await opened.handle.close().catch(() => { });
|
|
@@ -2930,20 +3152,6 @@ async function openLocalFileSafely(params) {
|
|
|
2930
3152
|
assertNoNulPathInput(params.filePath, "file path contains a NUL byte");
|
|
2931
3153
|
return await openVerifiedLocalFile(params.filePath);
|
|
2932
3154
|
}
|
|
2933
|
-
async function readOpenedFileSafely(params) {
|
|
2934
|
-
if (params.maxBytes !== undefined && params.opened.stat.size > params.maxBytes) {
|
|
2935
|
-
throw new errors_FsSafeError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${params.opened.stat.size})`);
|
|
2936
|
-
}
|
|
2937
|
-
const buffer = await params.opened.handle.readFile();
|
|
2938
|
-
if (params.maxBytes !== undefined && buffer.byteLength > params.maxBytes) {
|
|
2939
|
-
throw new errors_FsSafeError("too-large", `file exceeds limit of ${params.maxBytes} bytes (got ${buffer.byteLength})`);
|
|
2940
|
-
}
|
|
2941
|
-
return {
|
|
2942
|
-
buffer,
|
|
2943
|
-
realPath: params.opened.realPath,
|
|
2944
|
-
stat: params.opened.stat,
|
|
2945
|
-
};
|
|
2946
|
-
}
|
|
2947
3155
|
function emitWriteBoundaryWarning(reason) {
|
|
2948
3156
|
logWarn(`security: fs-safe write boundary warning (${reason})`);
|
|
2949
3157
|
}
|
|
@@ -2984,82 +3192,9 @@ async function verifyAtomicWriteResult(params) {
|
|
|
2984
3192
|
await opened.handle.close().catch(() => { });
|
|
2985
3193
|
}
|
|
2986
3194
|
}
|
|
2987
|
-
async function resolveOpenedFileRealPathForHandle(handle, ioPath) {
|
|
2988
|
-
const handleStat = await handle.stat();
|
|
2989
|
-
const fdCandidates = process.platform === "linux"
|
|
2990
|
-
? [`/proc/self/fd/${handle.fd}`, `/dev/fd/${handle.fd}`]
|
|
2991
|
-
: process.platform === "win32"
|
|
2992
|
-
? []
|
|
2993
|
-
: [`/dev/fd/${handle.fd}`];
|
|
2994
|
-
for (const fdPath of fdCandidates) {
|
|
2995
|
-
try {
|
|
2996
|
-
const fdRealPath = await promises_namespaceObject.realpath(fdPath);
|
|
2997
|
-
const fdRealStat = await promises_namespaceObject.stat(fdRealPath);
|
|
2998
|
-
if (file_identity_sameFileIdentity(handleStat, fdRealStat)) {
|
|
2999
|
-
return fdRealPath;
|
|
3000
|
-
}
|
|
3001
|
-
}
|
|
3002
|
-
catch {
|
|
3003
|
-
// try next fd path
|
|
3004
|
-
}
|
|
3005
|
-
}
|
|
3006
|
-
try {
|
|
3007
|
-
const ioRealPath = await promises_namespaceObject.realpath(ioPath);
|
|
3008
|
-
const ioRealStat = await promises_namespaceObject.stat(ioRealPath);
|
|
3009
|
-
if (file_identity_sameFileIdentity(handleStat, ioRealStat)) {
|
|
3010
|
-
return ioRealPath;
|
|
3011
|
-
}
|
|
3012
|
-
}
|
|
3013
|
-
catch (err) {
|
|
3014
|
-
if (!path_isNotFoundPathError(err)) {
|
|
3015
|
-
throw err;
|
|
3016
|
-
}
|
|
3017
|
-
}
|
|
3018
|
-
const parentResolved = await resolveOpenedFileRealPathFromParent(handleStat, ioPath);
|
|
3019
|
-
if (parentResolved) {
|
|
3020
|
-
return parentResolved;
|
|
3021
|
-
}
|
|
3022
|
-
throw new errors_FsSafeError("path-mismatch", "unable to resolve opened file path");
|
|
3023
|
-
}
|
|
3024
|
-
async function resolveOpenedFileRealPathFromParent(handleStat, ioPath) {
|
|
3025
|
-
let parentReal;
|
|
3026
|
-
try {
|
|
3027
|
-
parentReal = await promises_namespaceObject.realpath(external_node_path_namespaceObject.dirname(ioPath));
|
|
3028
|
-
}
|
|
3029
|
-
catch (err) {
|
|
3030
|
-
if (path_isNotFoundPathError(err)) {
|
|
3031
|
-
return null;
|
|
3032
|
-
}
|
|
3033
|
-
throw err;
|
|
3034
|
-
}
|
|
3035
|
-
let entries;
|
|
3036
|
-
try {
|
|
3037
|
-
entries = await promises_namespaceObject.readdir(parentReal);
|
|
3038
|
-
}
|
|
3039
|
-
catch (err) {
|
|
3040
|
-
if (path_isNotFoundPathError(err)) {
|
|
3041
|
-
return null;
|
|
3042
|
-
}
|
|
3043
|
-
throw err;
|
|
3044
|
-
}
|
|
3045
|
-
for (const entry of entries.toSorted()) {
|
|
3046
|
-
const candidatePath = external_node_path_namespaceObject.join(parentReal, entry);
|
|
3047
|
-
try {
|
|
3048
|
-
const candidateStat = await promises_namespaceObject.lstat(candidatePath);
|
|
3049
|
-
if (candidateStat.isFile() && file_identity_sameFileIdentity(handleStat, candidateStat)) {
|
|
3050
|
-
return await promises_namespaceObject.realpath(candidatePath);
|
|
3051
|
-
}
|
|
3052
|
-
}
|
|
3053
|
-
catch (err) {
|
|
3054
|
-
if (!path_isNotFoundPathError(err)) {
|
|
3055
|
-
throw err;
|
|
3056
|
-
}
|
|
3057
|
-
}
|
|
3058
|
-
}
|
|
3059
|
-
return null;
|
|
3060
|
-
}
|
|
3061
3195
|
async function openWritableFileInRoot(root, params) {
|
|
3062
3196
|
const { rootReal, rootWithSep, resolved } = await resolvePathInRoot(root, params.relativePath);
|
|
3197
|
+
await assertMutationNotDenied(resolved, params.denyMutations);
|
|
3063
3198
|
try {
|
|
3064
3199
|
await assertNoPathAliasEscape({
|
|
3065
3200
|
absolutePath: resolved,
|
|
@@ -3186,6 +3321,7 @@ async function appendFileInRoot(root, params) {
|
|
|
3186
3321
|
relativePath: params.relativePath,
|
|
3187
3322
|
mkdir: params.mkdir,
|
|
3188
3323
|
mode: params.mode,
|
|
3324
|
+
denyMutations: params.denyMutations,
|
|
3189
3325
|
truncateExisting: false,
|
|
3190
3326
|
append: true,
|
|
3191
3327
|
});
|
|
@@ -3213,8 +3349,8 @@ async function appendFileInRoot(root, params) {
|
|
|
3213
3349
|
await target.handle.close().catch(() => { });
|
|
3214
3350
|
}
|
|
3215
3351
|
}
|
|
3216
|
-
async function removePathInRoot(root,
|
|
3217
|
-
const resolved = await resolvePinnedRemovePathInRoot(root, relativePath);
|
|
3352
|
+
async function removePathInRoot(root, params) {
|
|
3353
|
+
const resolved = await resolvePinnedRemovePathInRoot(root, params.relativePath, params.denyMutations);
|
|
3218
3354
|
if (process.platform === "win32") {
|
|
3219
3355
|
await removePathFallback(resolved);
|
|
3220
3356
|
return;
|
|
@@ -3262,7 +3398,7 @@ async function writeFileInRoot(root, params) {
|
|
|
3262
3398
|
});
|
|
3263
3399
|
return;
|
|
3264
3400
|
}
|
|
3265
|
-
const pinned = await resolvePinnedWriteTargetInRoot(root, params.relativePath, params.mode);
|
|
3401
|
+
const pinned = await resolvePinnedWriteTargetInRoot(root, params.relativePath, params.mode, params.denyMutations);
|
|
3266
3402
|
await serializePathWrite(pinned.targetPath, async () => {
|
|
3267
3403
|
let identity;
|
|
3268
3404
|
try {
|
|
@@ -3318,7 +3454,7 @@ async function copyFileInRoot(root, params) {
|
|
|
3318
3454
|
});
|
|
3319
3455
|
return;
|
|
3320
3456
|
}
|
|
3321
|
-
const pinned = await resolvePinnedWriteTargetInRoot(root, params.relativePath, params.mode);
|
|
3457
|
+
const pinned = await resolvePinnedWriteTargetInRoot(root, params.relativePath, params.mode, params.denyMutations);
|
|
3322
3458
|
await serializePathWrite(pinned.targetPath, async () => {
|
|
3323
3459
|
let identity;
|
|
3324
3460
|
try {
|
|
@@ -3362,8 +3498,9 @@ async function copyFileInRoot(root, params) {
|
|
|
3362
3498
|
await source.handle.close().catch(() => { });
|
|
3363
3499
|
}
|
|
3364
3500
|
}
|
|
3365
|
-
async function resolvePinnedWriteTargetInRoot(root, relativePath, requestedMode) {
|
|
3501
|
+
async function resolvePinnedWriteTargetInRoot(root, relativePath, requestedMode, denyMutations) {
|
|
3366
3502
|
const { rootReal, rootWithSep, resolved } = await resolvePathInRoot(root, relativePath);
|
|
3503
|
+
await assertMutationNotDenied(resolved, denyMutations);
|
|
3367
3504
|
try {
|
|
3368
3505
|
await assertNoPathAliasEscape({
|
|
3369
3506
|
absolutePath: resolved,
|
|
@@ -3420,12 +3557,16 @@ async function resolvePinnedWriteTargetInRoot(root, relativePath, requestedMode)
|
|
|
3420
3557
|
async function resolvePinnedPathInRoot(root, params) {
|
|
3421
3558
|
return await resolvePinnedOperationPathInRoot(root, {
|
|
3422
3559
|
allowRoot: params.allowRoot,
|
|
3560
|
+
denyMutations: params.denyMutations,
|
|
3561
|
+
protectDenyMutationAncestors: false,
|
|
3423
3562
|
relativePath: params.relativePath,
|
|
3424
3563
|
policy: PATH_ALIAS_POLICIES.strict,
|
|
3425
3564
|
});
|
|
3426
3565
|
}
|
|
3427
|
-
async function resolvePinnedRemovePathInRoot(root, relativePath) {
|
|
3566
|
+
async function resolvePinnedRemovePathInRoot(root, relativePath, denyMutations) {
|
|
3428
3567
|
return await resolvePinnedOperationPathInRoot(root, {
|
|
3568
|
+
denyMutations,
|
|
3569
|
+
protectDenyMutationAncestors: true,
|
|
3429
3570
|
relativePath,
|
|
3430
3571
|
policy: PATH_ALIAS_POLICIES.unlinkTarget,
|
|
3431
3572
|
});
|
|
@@ -3437,6 +3578,7 @@ async function resolvePinnedOperationPathInRoot(root, params) {
|
|
|
3437
3578
|
});
|
|
3438
3579
|
const relativeResolved = external_node_path_namespaceObject.relative(resolved.rootReal, resolved.canonicalPath);
|
|
3439
3580
|
if ((relativeResolved === "" || relativeResolved === ".") && params.allowRoot === true) {
|
|
3581
|
+
await assertMutationNotDenied(resolved.canonicalPath, params.denyMutations);
|
|
3440
3582
|
return { rootReal: resolved.rootReal, resolved: resolved.canonicalPath, relativePosix: "" };
|
|
3441
3583
|
}
|
|
3442
3584
|
const firstSegment = relativeResolved.split(external_node_path_namespaceObject.sep)[0];
|
|
@@ -3450,6 +3592,9 @@ async function resolvePinnedOperationPathInRoot(root, params) {
|
|
|
3450
3592
|
if (!path_isPathInside(resolved.rootWithSep, resolved.canonicalPath)) {
|
|
3451
3593
|
throw new errors_FsSafeError("outside-workspace", "file is outside workspace root");
|
|
3452
3594
|
}
|
|
3595
|
+
await assertMutationNotDenied(resolved.canonicalPath, params.denyMutations, {
|
|
3596
|
+
protectAncestors: params.protectDenyMutationAncestors,
|
|
3597
|
+
});
|
|
3453
3598
|
return { rootReal: resolved.rootReal, resolved: resolved.canonicalPath, relativePosix };
|
|
3454
3599
|
}
|
|
3455
3600
|
async function resolvePinnedRootPathInRoot(root, params) {
|
|
@@ -3527,13 +3672,21 @@ async function listPathFallback(root, relativePath, withFileTypes) {
|
|
|
3527
3672
|
throw error;
|
|
3528
3673
|
}
|
|
3529
3674
|
}
|
|
3675
|
+
async function assertMoveMutationAllowed(root, params) {
|
|
3676
|
+
const source = await resolvePathInRoot(root, params.fromRelative);
|
|
3677
|
+
await assertMutationNotDenied(source.resolved, params.denyMutations, { protectAncestors: true });
|
|
3678
|
+
const target = await resolvePathInRoot(root, params.toRelative);
|
|
3679
|
+
await assertMutationNotDenied(target.resolved, params.denyMutations, { protectAncestors: true });
|
|
3680
|
+
}
|
|
3530
3681
|
async function movePathFallback(root, params) {
|
|
3531
3682
|
const source = await resolvePathInRoot(root, params.fromRelative);
|
|
3683
|
+
await assertMutationNotDenied(source.resolved, params.denyMutations, { protectAncestors: true });
|
|
3532
3684
|
await resolvePinnedRootPathInRoot(root, {
|
|
3533
3685
|
relativePath: params.fromRelative,
|
|
3534
3686
|
policy: PATH_ALIAS_POLICIES.strict,
|
|
3535
3687
|
});
|
|
3536
3688
|
const target = await resolvePathInRoot(root, params.toRelative);
|
|
3689
|
+
await assertMutationNotDenied(target.resolved, params.denyMutations, { protectAncestors: true });
|
|
3537
3690
|
await resolvePinnedRootPathInRoot(root, {
|
|
3538
3691
|
relativePath: params.toRelative,
|
|
3539
3692
|
policy: PATH_ALIAS_POLICIES.unlinkTarget,
|
|
@@ -3617,6 +3770,7 @@ async function writeFileFallback(root, params) {
|
|
|
3617
3770
|
relativePath: params.relativePath,
|
|
3618
3771
|
mkdir: params.mkdir,
|
|
3619
3772
|
mode: params.mode,
|
|
3773
|
+
denyMutations: params.denyMutations,
|
|
3620
3774
|
truncateExisting: false,
|
|
3621
3775
|
});
|
|
3622
3776
|
const destinationPath = target.realPath;
|
|
@@ -3662,6 +3816,7 @@ async function writeFileFallback(root, params) {
|
|
|
3662
3816
|
}
|
|
3663
3817
|
async function writeMissingFileFallback(root, params) {
|
|
3664
3818
|
const { rootReal, resolved } = await resolvePathInRoot(root, params.relativePath);
|
|
3819
|
+
await assertMutationNotDenied(resolved, params.denyMutations);
|
|
3665
3820
|
try {
|
|
3666
3821
|
await assertNoPathAliasEscape({
|
|
3667
3822
|
absolutePath: resolved,
|
|
@@ -3735,6 +3890,7 @@ async function copyFileFallback(root, params, source) {
|
|
|
3735
3890
|
relativePath: params.relativePath,
|
|
3736
3891
|
mkdir: params.mkdir,
|
|
3737
3892
|
mode: params.mode,
|
|
3893
|
+
denyMutations: params.denyMutations,
|
|
3738
3894
|
truncateExisting: false,
|
|
3739
3895
|
});
|
|
3740
3896
|
const destinationPath = target.realPath;
|
|
@@ -12366,7 +12522,7 @@ async function emitScriptEndEvent(options, deps) {
|
|
|
12366
12522
|
const capturedEnv = captureEnv(options.env);
|
|
12367
12523
|
const tags = captureTags(options.env);
|
|
12368
12524
|
const event = {
|
|
12369
|
-
v: SCHEMA_VERSION,
|
|
12525
|
+
v: (/* inlined export .SCHEMA_VERSION */1),
|
|
12370
12526
|
session_id: sessionId,
|
|
12371
12527
|
event: "script_end",
|
|
12372
12528
|
command: options.command,
|
|
@@ -12395,7 +12551,7 @@ async function emitShimErrorEvent(options, deps) {
|
|
|
12395
12551
|
const capturedEnv = captureEnv(options.env);
|
|
12396
12552
|
const tags = captureTags(options.env);
|
|
12397
12553
|
const event = {
|
|
12398
|
-
v: SCHEMA_VERSION,
|
|
12554
|
+
v: (/* inlined export .SCHEMA_VERSION */1),
|
|
12399
12555
|
session_id: sessionId,
|
|
12400
12556
|
event: "shim_error",
|
|
12401
12557
|
command: options.command,
|
|
@@ -12416,7 +12572,7 @@ async function emitPolicyDecisionEvent(options, deps) {
|
|
|
12416
12572
|
const capturedEnv = captureEnv(options.env);
|
|
12417
12573
|
const tags = captureTags(options.env);
|
|
12418
12574
|
const event = {
|
|
12419
|
-
v: SCHEMA_VERSION,
|
|
12575
|
+
v: (/* inlined export .SCHEMA_VERSION */1),
|
|
12420
12576
|
session_id: sessionId,
|
|
12421
12577
|
event: "policy_decision",
|
|
12422
12578
|
command: options.command,
|
|
@@ -12439,7 +12595,7 @@ async function emitToolUseEvent(options, deps) {
|
|
|
12439
12595
|
const capturedEnv = captureEnv(options.env);
|
|
12440
12596
|
const tags = captureTags(options.env);
|
|
12441
12597
|
const event = {
|
|
12442
|
-
v: SCHEMA_VERSION,
|
|
12598
|
+
v: (/* inlined export .SCHEMA_VERSION */1),
|
|
12443
12599
|
session_id: sessionId,
|
|
12444
12600
|
event: "tool_use",
|
|
12445
12601
|
tool_name: options.tool_name,
|
|
@@ -14896,4 +15052,4 @@ if (installedChunkData !== 0) { // 0 means "already installed".'
|
|
|
14896
15052
|
// module factories are used so entry inlining is disabled
|
|
14897
15053
|
// startup
|
|
14898
15054
|
// Load entry module and return exports
|
|
14899
|
-
var __webpack_exports__ = __webpack_require__(
|
|
15055
|
+
var __webpack_exports__ = __webpack_require__(341);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lousy-agents/agent-shell",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.15.1",
|
|
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.
|
|
39
|
+
"@openclaw/fs-safe": "0.3.0",
|
|
40
40
|
"zod": "4.4.3"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@github/copilot-sdk": "0.
|
|
43
|
+
"@github/copilot-sdk": "1.0.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependenciesMeta": {
|
|
46
46
|
"@github/copilot-sdk": {
|