@dexto/tools-filesystem 1.5.8 → 1.6.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/directory-approval.cjs +98 -0
- package/dist/directory-approval.d.ts +24 -0
- package/dist/directory-approval.d.ts.map +1 -0
- package/dist/directory-approval.integration.test.cjs +175 -390
- package/dist/directory-approval.integration.test.d.ts +14 -2
- package/dist/directory-approval.integration.test.d.ts.map +1 -0
- package/dist/directory-approval.integration.test.js +178 -390
- package/dist/directory-approval.js +63 -0
- package/dist/edit-file-tool.cjs +109 -120
- package/dist/edit-file-tool.d.ts +22 -9
- package/dist/edit-file-tool.d.ts.map +1 -0
- package/dist/edit-file-tool.js +116 -110
- package/dist/edit-file-tool.test.cjs +109 -29
- package/dist/edit-file-tool.test.d.ts +7 -2
- package/dist/edit-file-tool.test.d.ts.map +1 -0
- package/dist/edit-file-tool.test.js +109 -29
- package/dist/error-codes.cjs +4 -0
- package/dist/error-codes.d.ts +6 -3
- package/dist/error-codes.d.ts.map +1 -0
- package/dist/error-codes.js +4 -0
- package/dist/errors.cjs +48 -0
- package/dist/errors.d.ts +20 -7
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +48 -0
- package/dist/file-tool-types.d.ts +8 -40
- package/dist/file-tool-types.d.ts.map +1 -0
- package/dist/filesystem-service.cjs +325 -10
- package/dist/filesystem-service.d.ts +41 -12
- package/dist/filesystem-service.d.ts.map +1 -0
- package/dist/filesystem-service.js +326 -11
- package/dist/filesystem-service.test.cjs +10 -2
- package/dist/filesystem-service.test.d.ts +7 -2
- package/dist/filesystem-service.test.d.ts.map +1 -0
- package/dist/filesystem-service.test.js +10 -2
- package/dist/glob-files-tool.cjs +32 -46
- package/dist/glob-files-tool.d.ts +19 -9
- package/dist/glob-files-tool.d.ts.map +1 -0
- package/dist/glob-files-tool.js +33 -47
- package/dist/grep-content-tool.cjs +40 -45
- package/dist/grep-content-tool.d.ts +28 -9
- package/dist/grep-content-tool.d.ts.map +1 -0
- package/dist/grep-content-tool.js +41 -46
- package/dist/index.cjs +6 -3
- package/dist/index.d.cts +852 -14
- package/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -2
- package/dist/path-validator.cjs +28 -2
- package/dist/path-validator.d.ts +20 -9
- package/dist/path-validator.d.ts.map +1 -0
- package/dist/path-validator.js +28 -2
- package/dist/path-validator.test.d.ts +7 -2
- package/dist/path-validator.test.d.ts.map +1 -0
- package/dist/read-file-tool.cjs +26 -59
- package/dist/read-file-tool.d.ts +19 -9
- package/dist/read-file-tool.d.ts.map +1 -0
- package/dist/read-file-tool.js +27 -50
- package/dist/tool-factory-config.cjs +61 -0
- package/dist/{tool-provider.d.ts → tool-factory-config.d.ts} +13 -30
- package/dist/tool-factory-config.d.ts.map +1 -0
- package/dist/tool-factory-config.js +36 -0
- package/dist/tool-factory.cjs +123 -0
- package/dist/tool-factory.d.ts +4 -0
- package/dist/tool-factory.d.ts.map +1 -0
- package/dist/tool-factory.js +102 -0
- package/dist/types.d.ts +82 -18
- package/dist/types.d.ts.map +1 -0
- package/dist/write-file-tool.cjs +93 -99
- package/dist/write-file-tool.d.ts +22 -9
- package/dist/write-file-tool.d.ts.map +1 -0
- package/dist/write-file-tool.js +97 -91
- package/dist/write-file-tool.test.cjs +139 -33
- package/dist/write-file-tool.test.d.ts +7 -2
- package/dist/write-file-tool.test.d.ts.map +1 -0
- package/dist/write-file-tool.test.js +139 -33
- package/package.json +5 -4
- package/dist/directory-approval.integration.test.d.cts +0 -2
- package/dist/edit-file-tool.d.cts +0 -17
- package/dist/edit-file-tool.test.d.cts +0 -2
- package/dist/error-codes.d.cts +0 -32
- package/dist/errors.d.cts +0 -112
- package/dist/file-tool-types.d.cts +0 -46
- package/dist/filesystem-service.d.cts +0 -112
- package/dist/filesystem-service.test.d.cts +0 -2
- package/dist/glob-files-tool.d.cts +0 -17
- package/dist/grep-content-tool.d.cts +0 -17
- package/dist/path-validator.d.cts +0 -97
- package/dist/path-validator.test.d.cts +0 -2
- package/dist/read-file-tool.d.cts +0 -17
- package/dist/tool-provider.cjs +0 -123
- package/dist/tool-provider.d.cts +0 -77
- package/dist/tool-provider.js +0 -99
- package/dist/types.d.cts +0 -178
- package/dist/write-file-tool.d.cts +0 -17
- package/dist/write-file-tool.test.d.cts +0 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @dexto/tools-filesystem
|
|
3
|
+
*
|
|
4
|
+
* FileSystem tools factory for Dexto agents.
|
|
5
|
+
* Provides file operation tools: read, write, edit, glob, grep.
|
|
6
|
+
*/
|
|
7
|
+
export { fileSystemToolsFactory } from './tool-factory.js';
|
|
8
|
+
export type { FileSystemServiceGetter } from './file-tool-types.js';
|
|
9
|
+
export { FileSystemToolsConfigSchema, type FileSystemToolsConfig } from './tool-factory-config.js';
|
|
3
10
|
export { FileSystemService } from './filesystem-service.js';
|
|
4
11
|
export { PathValidator } from './path-validator.js';
|
|
5
12
|
export { FileSystemError } from './errors.js';
|
|
6
13
|
export { FileSystemErrorCode } from './error-codes.js';
|
|
7
|
-
export {
|
|
14
|
+
export type { FileSystemConfig, FileContent, ReadFileOptions, GlobOptions, GlobResult, GrepOptions, SearchResult, SearchMatch, WriteFileOptions, WriteResult, EditFileOptions, EditResult, EditOperation, FileMetadata, DirectoryEntry, ListDirectoryOptions, ListDirectoryResult, CreateDirectoryOptions, CreateDirectoryResult, DeletePathOptions, DeletePathResult, RenamePathResult, PathValidation, BufferEncoding, } from './types.js';
|
|
8
15
|
export { createReadFileTool } from './read-file-tool.js';
|
|
9
16
|
export { createWriteFileTool } from './write-file-tool.js';
|
|
10
17
|
export { createEditFileTool } from './edit-file-tool.js';
|
|
11
18
|
export { createGlobFilesTool } from './glob-files-tool.js';
|
|
12
19
|
export { createGrepContentTool } from './grep-content-tool.js';
|
|
13
|
-
|
|
14
|
-
import '@dexto/core';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,2BAA2B,EAAE,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAGnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAGvD,YAAY,EACR,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,WAAW,EACX,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,UAAU,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,cAAc,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fileSystemToolsFactory } from "./tool-factory.js";
|
|
2
|
+
import { FileSystemToolsConfigSchema } from "./tool-factory-config.js";
|
|
2
3
|
import { FileSystemService } from "./filesystem-service.js";
|
|
3
4
|
import { PathValidator } from "./path-validator.js";
|
|
4
5
|
import { FileSystemError } from "./errors.js";
|
|
@@ -12,11 +13,12 @@ export {
|
|
|
12
13
|
FileSystemError,
|
|
13
14
|
FileSystemErrorCode,
|
|
14
15
|
FileSystemService,
|
|
16
|
+
FileSystemToolsConfigSchema,
|
|
15
17
|
PathValidator,
|
|
16
18
|
createEditFileTool,
|
|
17
19
|
createGlobFilesTool,
|
|
18
20
|
createGrepContentTool,
|
|
19
21
|
createReadFileTool,
|
|
20
22
|
createWriteFileTool,
|
|
21
|
-
|
|
23
|
+
fileSystemToolsFactory
|
|
22
24
|
};
|
package/dist/path-validator.cjs
CHANGED
|
@@ -68,6 +68,24 @@ class PathValidator {
|
|
|
68
68
|
* Validate a file path for security and policy compliance
|
|
69
69
|
*/
|
|
70
70
|
async validatePath(filePath) {
|
|
71
|
+
return this.validatePathInternal(filePath, { skipAllowedCheck: false });
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Validate a file path for preview purposes.
|
|
75
|
+
*
|
|
76
|
+
* This is identical to {@link validatePath} except it does NOT enforce config-allowed roots.
|
|
77
|
+
* It still enforces:
|
|
78
|
+
* - traversal protection
|
|
79
|
+
* - blocked paths (absolute blocked paths only; relative blocked paths are resolved against
|
|
80
|
+
* config-allowed roots and may not match paths outside those roots)
|
|
81
|
+
* - blocked extensions
|
|
82
|
+
*
|
|
83
|
+
* Used for generating UI-only previews (e.g., diffs) before the user approves directory access.
|
|
84
|
+
*/
|
|
85
|
+
async validatePathForPreview(filePath) {
|
|
86
|
+
return this.validatePathInternal(filePath, { skipAllowedCheck: true });
|
|
87
|
+
}
|
|
88
|
+
async validatePathInternal(filePath, options) {
|
|
71
89
|
if (!filePath || filePath.trim() === "") {
|
|
72
90
|
return {
|
|
73
91
|
isValid: false,
|
|
@@ -75,9 +93,11 @@ class PathValidator {
|
|
|
75
93
|
};
|
|
76
94
|
}
|
|
77
95
|
const workingDir = this.config.workingDirectory || process.cwd();
|
|
96
|
+
let resolvedPath;
|
|
78
97
|
let normalizedPath;
|
|
79
98
|
try {
|
|
80
|
-
|
|
99
|
+
resolvedPath = path.isAbsolute(filePath) ? path.resolve(filePath) : path.resolve(workingDir, filePath);
|
|
100
|
+
normalizedPath = resolvedPath;
|
|
81
101
|
try {
|
|
82
102
|
normalizedPath = await fs.realpath(normalizedPath);
|
|
83
103
|
} catch {
|
|
@@ -94,7 +114,13 @@ class PathValidator {
|
|
|
94
114
|
error: "Path traversal detected"
|
|
95
115
|
};
|
|
96
116
|
}
|
|
97
|
-
if (!this.
|
|
117
|
+
if (options.skipAllowedCheck && this.isInConfigAllowedPaths(resolvedPath) && !this.isInConfigAllowedPaths(normalizedPath)) {
|
|
118
|
+
return {
|
|
119
|
+
isValid: false,
|
|
120
|
+
error: "Symlink target escapes allowed paths"
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
if (!options.skipAllowedCheck && !this.isPathAllowed(normalizedPath)) {
|
|
98
124
|
return {
|
|
99
125
|
isValid: false,
|
|
100
126
|
error: `Path is not within allowed paths. Allowed: ${this.normalizedAllowedPaths.join(", ")}`
|
package/dist/path-validator.d.ts
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import { FileSystemConfig, PathValidation } from './types.js';
|
|
2
|
-
import { IDextoLogger } from '@dexto/core';
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
2
|
* Path Validator
|
|
6
3
|
*
|
|
7
4
|
* Security-focused path validation for file system operations
|
|
8
5
|
*/
|
|
9
|
-
|
|
6
|
+
import { FileSystemConfig, PathValidation } from './types.js';
|
|
7
|
+
import type { Logger } from '@dexto/core';
|
|
10
8
|
/**
|
|
11
9
|
* Callback type for checking if a path is in an approved directory.
|
|
12
10
|
* Used to consult ApprovalManager without creating a direct dependency.
|
|
13
11
|
*/
|
|
14
|
-
type DirectoryApprovalChecker = (filePath: string) => boolean;
|
|
12
|
+
export type DirectoryApprovalChecker = (filePath: string) => boolean;
|
|
15
13
|
/**
|
|
16
14
|
* PathValidator - Validates file paths for security and policy compliance
|
|
17
15
|
*
|
|
@@ -25,14 +23,14 @@ type DirectoryApprovalChecker = (filePath: string) => boolean;
|
|
|
25
23
|
* PathValidator can optionally consult an external approval checker (e.g., ApprovalManager)
|
|
26
24
|
* to determine if paths outside the config's allowed paths are accessible.
|
|
27
25
|
*/
|
|
28
|
-
declare class PathValidator {
|
|
26
|
+
export declare class PathValidator {
|
|
29
27
|
private config;
|
|
30
28
|
private normalizedAllowedPaths;
|
|
31
29
|
private normalizedBlockedPaths;
|
|
32
30
|
private normalizedBlockedExtensions;
|
|
33
31
|
private logger;
|
|
34
32
|
private directoryApprovalChecker;
|
|
35
|
-
constructor(config: FileSystemConfig, logger:
|
|
33
|
+
constructor(config: FileSystemConfig, logger: Logger);
|
|
36
34
|
/**
|
|
37
35
|
* Set a callback to check if a path is in an approved directory.
|
|
38
36
|
* This allows PathValidator to consult ApprovalManager without a direct dependency.
|
|
@@ -44,6 +42,20 @@ declare class PathValidator {
|
|
|
44
42
|
* Validate a file path for security and policy compliance
|
|
45
43
|
*/
|
|
46
44
|
validatePath(filePath: string): Promise<PathValidation>;
|
|
45
|
+
/**
|
|
46
|
+
* Validate a file path for preview purposes.
|
|
47
|
+
*
|
|
48
|
+
* This is identical to {@link validatePath} except it does NOT enforce config-allowed roots.
|
|
49
|
+
* It still enforces:
|
|
50
|
+
* - traversal protection
|
|
51
|
+
* - blocked paths (absolute blocked paths only; relative blocked paths are resolved against
|
|
52
|
+
* config-allowed roots and may not match paths outside those roots)
|
|
53
|
+
* - blocked extensions
|
|
54
|
+
*
|
|
55
|
+
* Used for generating UI-only previews (e.g., diffs) before the user approves directory access.
|
|
56
|
+
*/
|
|
57
|
+
validatePathForPreview(filePath: string): Promise<PathValidation>;
|
|
58
|
+
private validatePathInternal;
|
|
47
59
|
/**
|
|
48
60
|
* Check if path contains traversal attempts
|
|
49
61
|
*/
|
|
@@ -93,5 +105,4 @@ declare class PathValidator {
|
|
|
93
105
|
*/
|
|
94
106
|
getBlockedPaths(): string[];
|
|
95
107
|
}
|
|
96
|
-
|
|
97
|
-
export { type DirectoryApprovalChecker, PathValidator };
|
|
108
|
+
//# sourceMappingURL=path-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-validator.d.ts","sourceRoot":"","sources":["../src/path-validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;AAErE;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,sBAAsB,CAAW;IACzC,OAAO,CAAC,sBAAsB,CAAW;IACzC,OAAO,CAAC,2BAA2B,CAAW;IAC9C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,wBAAwB,CAAuC;gBAE3D,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM;IAsBpD;;;;;OAKG;IACH,2BAA2B,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI;IAKpE;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAI7D;;;;;;;;;;;OAWG;IACG,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;YAIzD,oBAAoB;IAyFlC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAIrB;;OAEG;IACH,OAAO,CAAC,aAAa;IAyBrB;;;OAGG;IACH,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO;IAInD;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAyBzB;;;;;;;;;OASG;IACG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA8B7D;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAY9B;;OAEG;IACH,eAAe,IAAI,MAAM,EAAE;IAI3B;;OAEG;IACH,eAAe,IAAI,MAAM,EAAE;CAG9B"}
|
package/dist/path-validator.js
CHANGED
|
@@ -35,6 +35,24 @@ class PathValidator {
|
|
|
35
35
|
* Validate a file path for security and policy compliance
|
|
36
36
|
*/
|
|
37
37
|
async validatePath(filePath) {
|
|
38
|
+
return this.validatePathInternal(filePath, { skipAllowedCheck: false });
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validate a file path for preview purposes.
|
|
42
|
+
*
|
|
43
|
+
* This is identical to {@link validatePath} except it does NOT enforce config-allowed roots.
|
|
44
|
+
* It still enforces:
|
|
45
|
+
* - traversal protection
|
|
46
|
+
* - blocked paths (absolute blocked paths only; relative blocked paths are resolved against
|
|
47
|
+
* config-allowed roots and may not match paths outside those roots)
|
|
48
|
+
* - blocked extensions
|
|
49
|
+
*
|
|
50
|
+
* Used for generating UI-only previews (e.g., diffs) before the user approves directory access.
|
|
51
|
+
*/
|
|
52
|
+
async validatePathForPreview(filePath) {
|
|
53
|
+
return this.validatePathInternal(filePath, { skipAllowedCheck: true });
|
|
54
|
+
}
|
|
55
|
+
async validatePathInternal(filePath, options) {
|
|
38
56
|
if (!filePath || filePath.trim() === "") {
|
|
39
57
|
return {
|
|
40
58
|
isValid: false,
|
|
@@ -42,9 +60,11 @@ class PathValidator {
|
|
|
42
60
|
};
|
|
43
61
|
}
|
|
44
62
|
const workingDir = this.config.workingDirectory || process.cwd();
|
|
63
|
+
let resolvedPath;
|
|
45
64
|
let normalizedPath;
|
|
46
65
|
try {
|
|
47
|
-
|
|
66
|
+
resolvedPath = path.isAbsolute(filePath) ? path.resolve(filePath) : path.resolve(workingDir, filePath);
|
|
67
|
+
normalizedPath = resolvedPath;
|
|
48
68
|
try {
|
|
49
69
|
normalizedPath = await fs.realpath(normalizedPath);
|
|
50
70
|
} catch {
|
|
@@ -61,7 +81,13 @@ class PathValidator {
|
|
|
61
81
|
error: "Path traversal detected"
|
|
62
82
|
};
|
|
63
83
|
}
|
|
64
|
-
if (!this.
|
|
84
|
+
if (options.skipAllowedCheck && this.isInConfigAllowedPaths(resolvedPath) && !this.isInConfigAllowedPaths(normalizedPath)) {
|
|
85
|
+
return {
|
|
86
|
+
isValid: false,
|
|
87
|
+
error: "Symlink target escapes allowed paths"
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (!options.skipAllowedCheck && !this.isPathAllowed(normalizedPath)) {
|
|
65
91
|
return {
|
|
66
92
|
isValid: false,
|
|
67
93
|
error: `Path is not within allowed paths. Allowed: ${this.normalizedAllowedPaths.join(", ")}`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-validator.test.d.ts","sourceRoot":"","sources":["../src/path-validator.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
package/dist/read-file-tool.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,84 +15,53 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
var read_file_tool_exports = {};
|
|
30
20
|
__export(read_file_tool_exports, {
|
|
31
21
|
createReadFileTool: () => createReadFileTool
|
|
32
22
|
});
|
|
33
23
|
module.exports = __toCommonJS(read_file_tool_exports);
|
|
34
|
-
var path = __toESM(require("node:path"), 1);
|
|
35
24
|
var import_zod = require("zod");
|
|
36
25
|
var import_core = require("@dexto/core");
|
|
26
|
+
var import_directory_approval = require("./directory-approval.js");
|
|
37
27
|
const ReadFileInputSchema = import_zod.z.object({
|
|
38
|
-
file_path: import_zod.z.string().describe("Absolute path to the file to read"),
|
|
28
|
+
file_path: import_zod.z.string().min(1).describe("Absolute path to the file to read"),
|
|
39
29
|
limit: import_zod.z.number().int().positive().optional().describe("Maximum number of lines to read (optional)"),
|
|
40
30
|
offset: import_zod.z.number().int().min(1).optional().describe("Starting line number (1-based, optional)")
|
|
41
31
|
}).strict();
|
|
42
|
-
function createReadFileTool(
|
|
43
|
-
|
|
44
|
-
let pendingApprovalParentDir;
|
|
45
|
-
return {
|
|
32
|
+
function createReadFileTool(getFileSystemService) {
|
|
33
|
+
return (0, import_core.defineTool)({
|
|
46
34
|
id: "read_file",
|
|
35
|
+
aliases: ["read"],
|
|
47
36
|
description: "Read the contents of a file with optional pagination. Returns file content, line count, encoding, and whether the output was truncated. Use limit and offset parameters for large files to read specific sections. This tool is for reading files within allowed paths only.",
|
|
48
37
|
inputSchema: ReadFileInputSchema,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const { file_path } = args;
|
|
55
|
-
if (!file_path) return null;
|
|
56
|
-
const isAllowed = await fileSystemService.isPathWithinConfigAllowed(file_path);
|
|
57
|
-
if (isAllowed) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
if (directoryApproval?.isSessionApproved(file_path)) {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
const absolutePath = path.resolve(file_path);
|
|
64
|
-
const parentDir = path.dirname(absolutePath);
|
|
65
|
-
pendingApprovalParentDir = parentDir;
|
|
66
|
-
return {
|
|
67
|
-
type: import_core.ApprovalType.DIRECTORY_ACCESS,
|
|
68
|
-
metadata: {
|
|
69
|
-
path: absolutePath,
|
|
70
|
-
parentDir,
|
|
71
|
-
operation: "read",
|
|
72
|
-
toolName: "read_file"
|
|
73
|
-
}
|
|
74
|
-
};
|
|
38
|
+
presentation: {
|
|
39
|
+
describeHeader: (input) => (0, import_core.createLocalToolCallHeader)({
|
|
40
|
+
title: "Read",
|
|
41
|
+
argsText: (0, import_core.truncateForHeader)(input.file_path, 140)
|
|
42
|
+
})
|
|
75
43
|
},
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
rememberDirectory ? "session" : "once"
|
|
86
|
-
);
|
|
87
|
-
pendingApprovalParentDir = void 0;
|
|
88
|
-
},
|
|
89
|
-
execute: async (input, _context) => {
|
|
44
|
+
...(0, import_directory_approval.createDirectoryAccessApprovalHandlers)({
|
|
45
|
+
toolName: "read_file",
|
|
46
|
+
operation: "read",
|
|
47
|
+
inputSchema: ReadFileInputSchema,
|
|
48
|
+
getFileSystemService,
|
|
49
|
+
resolvePaths: (input, fileSystemService) => (0, import_directory_approval.resolveFilePath)(fileSystemService.getWorkingDirectory(), input.file_path)
|
|
50
|
+
}),
|
|
51
|
+
async execute(input, context) {
|
|
52
|
+
const resolvedFileSystemService = await getFileSystemService(context);
|
|
90
53
|
const { file_path, limit, offset } = input;
|
|
91
|
-
const
|
|
54
|
+
const { path: resolvedPath } = (0, import_directory_approval.resolveFilePath)(
|
|
55
|
+
resolvedFileSystemService.getWorkingDirectory(),
|
|
56
|
+
file_path
|
|
57
|
+
);
|
|
58
|
+
const result = await resolvedFileSystemService.readFile(resolvedPath, {
|
|
92
59
|
limit,
|
|
93
60
|
offset
|
|
94
61
|
});
|
|
95
62
|
const _display = {
|
|
96
63
|
type: "file",
|
|
97
|
-
path:
|
|
64
|
+
path: resolvedPath,
|
|
98
65
|
operation: "read",
|
|
99
66
|
size: result.size,
|
|
100
67
|
lineCount: result.lines
|
|
@@ -109,7 +76,7 @@ function createReadFileTool(options) {
|
|
|
109
76
|
_display
|
|
110
77
|
};
|
|
111
78
|
}
|
|
112
|
-
};
|
|
79
|
+
});
|
|
113
80
|
}
|
|
114
81
|
// Annotate the CommonJS export names for ESM import in node:
|
|
115
82
|
0 && (module.exports = {
|
package/dist/read-file-tool.d.ts
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
|
-
import { InternalTool } from '@dexto/core';
|
|
2
|
-
import { FileToolOptions } from './file-tool-types.js';
|
|
3
|
-
import './filesystem-service.js';
|
|
4
|
-
import './types.js';
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* Read File Tool
|
|
8
3
|
*
|
|
9
4
|
* Internal tool for reading file contents with size limits and pagination
|
|
10
5
|
*/
|
|
11
|
-
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import type { Tool } from '@dexto/core';
|
|
8
|
+
import type { FileSystemServiceGetter } from './file-tool-types.js';
|
|
9
|
+
declare const ReadFileInputSchema: z.ZodObject<{
|
|
10
|
+
file_path: z.ZodString;
|
|
11
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
}, "strict", z.ZodTypeAny, {
|
|
14
|
+
file_path: string;
|
|
15
|
+
limit?: number | undefined;
|
|
16
|
+
offset?: number | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
file_path: string;
|
|
19
|
+
limit?: number | undefined;
|
|
20
|
+
offset?: number | undefined;
|
|
21
|
+
}>;
|
|
12
22
|
/**
|
|
13
23
|
* Create the read_file internal tool with directory approval support
|
|
14
24
|
*/
|
|
15
|
-
declare function createReadFileTool(
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
export declare function createReadFileTool(getFileSystemService: FileSystemServiceGetter): Tool<typeof ReadFileInputSchema>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=read-file-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-file-tool.d.ts","sourceRoot":"","sources":["../src/read-file-tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAmB,IAAI,EAAwB,MAAM,aAAa,CAAC;AAC/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAGpE,QAAA,MAAM,mBAAmB;;;;;;;;;;;;EAgBZ,CAAC;AAEd;;GAEG;AACH,wBAAgB,kBAAkB,CAC9B,oBAAoB,EAAE,uBAAuB,GAC9C,IAAI,CAAC,OAAO,mBAAmB,CAAC,CA6DlC"}
|
package/dist/read-file-tool.js
CHANGED
|
@@ -1,67 +1,44 @@
|
|
|
1
|
-
import * as path from "node:path";
|
|
2
1
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
2
|
+
import { createLocalToolCallHeader, defineTool, truncateForHeader } from "@dexto/core";
|
|
3
|
+
import { createDirectoryAccessApprovalHandlers, resolveFilePath } from "./directory-approval.js";
|
|
4
4
|
const ReadFileInputSchema = z.object({
|
|
5
|
-
file_path: z.string().describe("Absolute path to the file to read"),
|
|
5
|
+
file_path: z.string().min(1).describe("Absolute path to the file to read"),
|
|
6
6
|
limit: z.number().int().positive().optional().describe("Maximum number of lines to read (optional)"),
|
|
7
7
|
offset: z.number().int().min(1).optional().describe("Starting line number (1-based, optional)")
|
|
8
8
|
}).strict();
|
|
9
|
-
function createReadFileTool(
|
|
10
|
-
|
|
11
|
-
let pendingApprovalParentDir;
|
|
12
|
-
return {
|
|
9
|
+
function createReadFileTool(getFileSystemService) {
|
|
10
|
+
return defineTool({
|
|
13
11
|
id: "read_file",
|
|
12
|
+
aliases: ["read"],
|
|
14
13
|
description: "Read the contents of a file with optional pagination. Returns file content, line count, encoding, and whether the output was truncated. Use limit and offset parameters for large files to read specific sections. This tool is for reading files within allowed paths only.",
|
|
15
14
|
inputSchema: ReadFileInputSchema,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const { file_path } = args;
|
|
22
|
-
if (!file_path) return null;
|
|
23
|
-
const isAllowed = await fileSystemService.isPathWithinConfigAllowed(file_path);
|
|
24
|
-
if (isAllowed) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
if (directoryApproval?.isSessionApproved(file_path)) {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
const absolutePath = path.resolve(file_path);
|
|
31
|
-
const parentDir = path.dirname(absolutePath);
|
|
32
|
-
pendingApprovalParentDir = parentDir;
|
|
33
|
-
return {
|
|
34
|
-
type: ApprovalType.DIRECTORY_ACCESS,
|
|
35
|
-
metadata: {
|
|
36
|
-
path: absolutePath,
|
|
37
|
-
parentDir,
|
|
38
|
-
operation: "read",
|
|
39
|
-
toolName: "read_file"
|
|
40
|
-
}
|
|
41
|
-
};
|
|
15
|
+
presentation: {
|
|
16
|
+
describeHeader: (input) => createLocalToolCallHeader({
|
|
17
|
+
title: "Read",
|
|
18
|
+
argsText: truncateForHeader(input.file_path, 140)
|
|
19
|
+
})
|
|
42
20
|
},
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
rememberDirectory ? "session" : "once"
|
|
53
|
-
);
|
|
54
|
-
pendingApprovalParentDir = void 0;
|
|
55
|
-
},
|
|
56
|
-
execute: async (input, _context) => {
|
|
21
|
+
...createDirectoryAccessApprovalHandlers({
|
|
22
|
+
toolName: "read_file",
|
|
23
|
+
operation: "read",
|
|
24
|
+
inputSchema: ReadFileInputSchema,
|
|
25
|
+
getFileSystemService,
|
|
26
|
+
resolvePaths: (input, fileSystemService) => resolveFilePath(fileSystemService.getWorkingDirectory(), input.file_path)
|
|
27
|
+
}),
|
|
28
|
+
async execute(input, context) {
|
|
29
|
+
const resolvedFileSystemService = await getFileSystemService(context);
|
|
57
30
|
const { file_path, limit, offset } = input;
|
|
58
|
-
const
|
|
31
|
+
const { path: resolvedPath } = resolveFilePath(
|
|
32
|
+
resolvedFileSystemService.getWorkingDirectory(),
|
|
33
|
+
file_path
|
|
34
|
+
);
|
|
35
|
+
const result = await resolvedFileSystemService.readFile(resolvedPath, {
|
|
59
36
|
limit,
|
|
60
37
|
offset
|
|
61
38
|
});
|
|
62
39
|
const _display = {
|
|
63
40
|
type: "file",
|
|
64
|
-
path:
|
|
41
|
+
path: resolvedPath,
|
|
65
42
|
operation: "read",
|
|
66
43
|
size: result.size,
|
|
67
44
|
lineCount: result.lines
|
|
@@ -76,7 +53,7 @@ function createReadFileTool(options) {
|
|
|
76
53
|
_display
|
|
77
54
|
};
|
|
78
55
|
}
|
|
79
|
-
};
|
|
56
|
+
});
|
|
80
57
|
}
|
|
81
58
|
export {
|
|
82
59
|
createReadFileTool
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var tool_factory_config_exports = {};
|
|
20
|
+
__export(tool_factory_config_exports, {
|
|
21
|
+
FILESYSTEM_TOOL_NAMES: () => FILESYSTEM_TOOL_NAMES,
|
|
22
|
+
FileSystemToolsConfigSchema: () => FileSystemToolsConfigSchema
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(tool_factory_config_exports);
|
|
25
|
+
var import_zod = require("zod");
|
|
26
|
+
const DEFAULT_ALLOWED_PATHS = ["."];
|
|
27
|
+
const DEFAULT_BLOCKED_PATHS = [".git", "node_modules/.bin", ".env"];
|
|
28
|
+
const DEFAULT_BLOCKED_EXTENSIONS = [".exe", ".dll", ".so"];
|
|
29
|
+
const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
30
|
+
const DEFAULT_ENABLE_BACKUPS = false;
|
|
31
|
+
const DEFAULT_BACKUP_RETENTION_DAYS = 7;
|
|
32
|
+
const FILESYSTEM_TOOL_NAMES = [
|
|
33
|
+
"read_file",
|
|
34
|
+
"write_file",
|
|
35
|
+
"edit_file",
|
|
36
|
+
"glob_files",
|
|
37
|
+
"grep_content"
|
|
38
|
+
];
|
|
39
|
+
const FileSystemToolsConfigSchema = import_zod.z.object({
|
|
40
|
+
type: import_zod.z.literal("filesystem-tools"),
|
|
41
|
+
allowedPaths: import_zod.z.array(import_zod.z.string()).default(DEFAULT_ALLOWED_PATHS).describe("List of allowed base paths for file operations"),
|
|
42
|
+
blockedPaths: import_zod.z.array(import_zod.z.string()).default(DEFAULT_BLOCKED_PATHS).describe("List of blocked paths to exclude from operations"),
|
|
43
|
+
blockedExtensions: import_zod.z.array(import_zod.z.string()).default(DEFAULT_BLOCKED_EXTENSIONS).describe("List of blocked file extensions"),
|
|
44
|
+
maxFileSize: import_zod.z.number().int().positive().default(DEFAULT_MAX_FILE_SIZE).describe(
|
|
45
|
+
`Maximum file size in bytes (default: ${DEFAULT_MAX_FILE_SIZE / 1024 / 1024}MB)`
|
|
46
|
+
),
|
|
47
|
+
workingDirectory: import_zod.z.string().optional().describe("Working directory for file operations (defaults to process.cwd())"),
|
|
48
|
+
enableBackups: import_zod.z.boolean().default(DEFAULT_ENABLE_BACKUPS).describe("Enable automatic backups of modified files"),
|
|
49
|
+
backupPath: import_zod.z.string().optional().describe("Absolute path for storing file backups (if enableBackups is true)"),
|
|
50
|
+
backupRetentionDays: import_zod.z.number().int().positive().default(DEFAULT_BACKUP_RETENTION_DAYS).describe(
|
|
51
|
+
`Number of days to retain backup files (default: ${DEFAULT_BACKUP_RETENTION_DAYS})`
|
|
52
|
+
),
|
|
53
|
+
enabledTools: import_zod.z.array(import_zod.z.enum(FILESYSTEM_TOOL_NAMES)).optional().describe(
|
|
54
|
+
`Subset of tools to enable. If not specified, all tools are enabled. Available: ${FILESYSTEM_TOOL_NAMES.join(", ")}`
|
|
55
|
+
)
|
|
56
|
+
}).strict();
|
|
57
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
58
|
+
0 && (module.exports = {
|
|
59
|
+
FILESYSTEM_TOOL_NAMES,
|
|
60
|
+
FileSystemToolsConfigSchema
|
|
61
|
+
});
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { CustomToolProvider } from '@dexto/core';
|
|
3
|
-
export { FileToolOptions } from './file-tool-types.js';
|
|
4
|
-
import './filesystem-service.js';
|
|
5
|
-
import './types.js';
|
|
6
|
-
|
|
7
1
|
/**
|
|
8
|
-
* FileSystem Tools
|
|
2
|
+
* FileSystem Tools Factory
|
|
9
3
|
*
|
|
10
4
|
* Provides file operation tools by wrapping FileSystemService.
|
|
11
|
-
* When registered, the
|
|
5
|
+
* When registered, the factory initializes FileSystemService and creates tools
|
|
12
6
|
* for file operations (read, write, edit, glob, grep).
|
|
13
7
|
*/
|
|
14
|
-
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
/**
|
|
10
|
+
* Available filesystem tool names for enabledTools configuration.
|
|
11
|
+
*/
|
|
12
|
+
export declare const FILESYSTEM_TOOL_NAMES: readonly ["read_file", "write_file", "edit_file", "glob_files", "grep_content"];
|
|
15
13
|
/**
|
|
16
|
-
* Configuration schema for FileSystem tools
|
|
14
|
+
* Configuration schema for FileSystem tools factory.
|
|
17
15
|
*
|
|
18
16
|
* This is the SINGLE SOURCE OF TRUTH for all configuration:
|
|
19
17
|
* - Validation rules
|
|
@@ -24,7 +22,7 @@ import './types.js';
|
|
|
24
22
|
* Services receive fully-validated config from this schema and use it as-is,
|
|
25
23
|
* with no additional defaults or fallbacks needed.
|
|
26
24
|
*/
|
|
27
|
-
declare const FileSystemToolsConfigSchema: z.ZodObject<{
|
|
25
|
+
export declare const FileSystemToolsConfigSchema: z.ZodObject<{
|
|
28
26
|
type: z.ZodLiteral<"filesystem-tools">;
|
|
29
27
|
allowedPaths: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
30
28
|
blockedPaths: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -45,7 +43,7 @@ declare const FileSystemToolsConfigSchema: z.ZodObject<{
|
|
|
45
43
|
type: "filesystem-tools";
|
|
46
44
|
backupPath?: string | undefined;
|
|
47
45
|
workingDirectory?: string | undefined;
|
|
48
|
-
enabledTools?: ("
|
|
46
|
+
enabledTools?: ("read_file" | "write_file" | "edit_file" | "glob_files" | "grep_content")[] | undefined;
|
|
49
47
|
}, {
|
|
50
48
|
type: "filesystem-tools";
|
|
51
49
|
allowedPaths?: string[] | undefined;
|
|
@@ -56,22 +54,7 @@ declare const FileSystemToolsConfigSchema: z.ZodObject<{
|
|
|
56
54
|
enableBackups?: boolean | undefined;
|
|
57
55
|
backupRetentionDays?: number | undefined;
|
|
58
56
|
workingDirectory?: string | undefined;
|
|
59
|
-
enabledTools?: ("
|
|
57
|
+
enabledTools?: ("read_file" | "write_file" | "edit_file" | "glob_files" | "grep_content")[] | undefined;
|
|
60
58
|
}>;
|
|
61
|
-
type FileSystemToolsConfig = z.output<typeof FileSystemToolsConfigSchema>;
|
|
62
|
-
|
|
63
|
-
* FileSystem tools provider.
|
|
64
|
-
*
|
|
65
|
-
* Wraps FileSystemService and provides file operation tools:
|
|
66
|
-
* - read_file: Read file contents with pagination
|
|
67
|
-
* - write_file: Write or overwrite file contents
|
|
68
|
-
* - edit_file: Edit files using search/replace operations
|
|
69
|
-
* - glob_files: Find files matching glob patterns
|
|
70
|
-
* - grep_content: Search file contents using regex
|
|
71
|
-
*
|
|
72
|
-
* When registered via customToolRegistry, FileSystemService is automatically
|
|
73
|
-
* initialized and file operation tools become available to the agent.
|
|
74
|
-
*/
|
|
75
|
-
declare const fileSystemToolsProvider: CustomToolProvider<'filesystem-tools', FileSystemToolsConfig>;
|
|
76
|
-
|
|
77
|
-
export { fileSystemToolsProvider };
|
|
59
|
+
export type FileSystemToolsConfig = z.output<typeof FileSystemToolsConfigSchema>;
|
|
60
|
+
//# sourceMappingURL=tool-factory-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-factory-config.d.ts","sourceRoot":"","sources":["../src/tool-factory-config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB;;GAEG;AACH,eAAO,MAAM,qBAAqB,iFAMxB,CAAC;AAEX;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkD3B,CAAC;AAEd,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
|