@dexto/tools-filesystem 1.6.25 → 1.6.26
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 +6 -4
- package/dist/directory-approval.d.ts.map +1 -1
- package/dist/directory-approval.integration.test.cjs +235 -6
- package/dist/directory-approval.integration.test.js +236 -6
- package/dist/directory-approval.js +6 -4
- package/dist/filesystem-service.cjs +6 -2
- package/dist/filesystem-service.d.ts.map +1 -1
- package/dist/filesystem-service.js +6 -2
- package/dist/glob-files-tool.cjs +3 -13
- package/dist/glob-files-tool.d.ts.map +1 -1
- package/dist/glob-files-tool.js +3 -3
- package/dist/glob-files-tool.test.cjs +115 -0
- package/dist/glob-files-tool.test.d.ts +2 -0
- package/dist/glob-files-tool.test.d.ts.map +1 -0
- package/dist/glob-files-tool.test.js +92 -0
- package/dist/grep-content-tool.cjs +3 -13
- package/dist/grep-content-tool.d.ts.map +1 -1
- package/dist/grep-content-tool.js +3 -3
- package/dist/grep-content-tool.test.cjs +115 -0
- package/dist/grep-content-tool.test.d.ts +2 -0
- package/dist/grep-content-tool.test.d.ts.map +1 -0
- package/dist/grep-content-tool.test.js +92 -0
- package/dist/path-utils.cjs +55 -0
- package/dist/path-utils.d.ts +11 -0
- package/dist/path-utils.d.ts.map +1 -0
- package/dist/path-utils.js +20 -0
- package/dist/path-utils.test.cjs +52 -0
- package/dist/path-utils.test.d.ts +2 -0
- package/dist/path-utils.test.d.ts.map +1 -0
- package/dist/path-utils.test.js +29 -0
- package/dist/path-validator.cjs +23 -9
- package/dist/path-validator.d.ts.map +1 -1
- package/dist/path-validator.js +23 -9
- package/dist/path-validator.test.cjs +41 -0
- package/dist/path-validator.test.js +19 -0
- package/dist/tool-factory-config.d.ts +2 -2
- package/dist/tool-factory.cjs +29 -50
- package/dist/tool-factory.d.ts.map +1 -1
- package/dist/tool-factory.js +29 -50
- package/dist/write-file-tool.test.cjs +33 -0
- package/dist/write-file-tool.test.js +33 -0
- package/package.json +3 -3
package/dist/tool-factory.js
CHANGED
|
@@ -28,64 +28,43 @@ const fileSystemToolsFactory = {
|
|
|
28
28
|
backupPath: config.backupPath,
|
|
29
29
|
backupRetentionDays: config.backupRetentionDays
|
|
30
30
|
};
|
|
31
|
-
let fileSystemService;
|
|
32
31
|
const resolveWorkingDirectory = (context) => context.workspace?.path ?? fileSystemConfig.workingDirectory ?? process.cwd();
|
|
33
|
-
const
|
|
34
|
-
const workingDirectory = resolveWorkingDirectory(context);
|
|
35
|
-
service.setWorkingDirectory(workingDirectory);
|
|
36
|
-
};
|
|
37
|
-
const resolveInjectedService = (context) => {
|
|
38
|
-
const candidate = context.services?.filesystemService;
|
|
39
|
-
if (!candidate) return null;
|
|
40
|
-
if (candidate instanceof FileSystemService) return candidate;
|
|
41
|
-
const hasMethods = typeof candidate.readFile === "function" && typeof candidate.writeFile === "function" && typeof candidate.setWorkingDirectory === "function" && typeof candidate.setDirectoryApprovalChecker === "function";
|
|
42
|
-
return hasMethods ? candidate : null;
|
|
43
|
-
};
|
|
44
|
-
const getFileSystemService = async (context) => {
|
|
45
|
-
const injectedService = resolveInjectedService(context);
|
|
46
|
-
if (injectedService) {
|
|
47
|
-
const approvalManager2 = context.services?.approval;
|
|
48
|
-
if (!approvalManager2) {
|
|
49
|
-
throw ToolError.configInvalid(
|
|
50
|
-
"filesystem-tools requires ToolExecutionContext.services.approval"
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
injectedService.setDirectoryApprovalChecker(
|
|
54
|
-
(filePath) => approvalManager2.isDirectoryApproved(filePath)
|
|
55
|
-
);
|
|
56
|
-
applyWorkspace(context, injectedService);
|
|
57
|
-
return injectedService;
|
|
58
|
-
}
|
|
59
|
-
if (fileSystemService) {
|
|
60
|
-
const approvalManager2 = context.services?.approval;
|
|
61
|
-
if (!approvalManager2) {
|
|
62
|
-
throw ToolError.configInvalid(
|
|
63
|
-
"filesystem-tools requires ToolExecutionContext.services.approval"
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
fileSystemService.setDirectoryApprovalChecker(
|
|
67
|
-
(filePath) => approvalManager2.isDirectoryApproved(filePath)
|
|
68
|
-
);
|
|
69
|
-
applyWorkspace(context, fileSystemService);
|
|
70
|
-
return fileSystemService;
|
|
71
|
-
}
|
|
72
|
-
const logger = context.logger;
|
|
73
|
-
fileSystemService = new FileSystemService(fileSystemConfig, logger);
|
|
32
|
+
const createScopedFileSystemService = (context, baseConfig) => {
|
|
74
33
|
const approvalManager = context.services?.approval;
|
|
75
34
|
if (!approvalManager) {
|
|
76
35
|
throw ToolError.configInvalid(
|
|
77
36
|
"filesystem-tools requires ToolExecutionContext.services.approval"
|
|
78
37
|
);
|
|
79
38
|
}
|
|
80
|
-
|
|
81
|
-
|
|
39
|
+
const service = new FileSystemService(
|
|
40
|
+
{
|
|
41
|
+
...baseConfig,
|
|
42
|
+
workingDirectory: resolveWorkingDirectory(context)
|
|
43
|
+
},
|
|
44
|
+
context.logger
|
|
45
|
+
);
|
|
46
|
+
service.setDirectoryApprovalChecker(
|
|
47
|
+
(filePath) => approvalManager.isDirectoryApproved(filePath, context.sessionId)
|
|
48
|
+
);
|
|
49
|
+
return service;
|
|
50
|
+
};
|
|
51
|
+
const resolveInjectedServiceConfig = (context) => {
|
|
52
|
+
const candidate = context.services?.filesystemService;
|
|
53
|
+
if (!candidate) return null;
|
|
54
|
+
if (candidate instanceof FileSystemService) return candidate.getConfig();
|
|
55
|
+
const getConfig = candidate.getConfig;
|
|
56
|
+
if (typeof getConfig === "function") {
|
|
57
|
+
return getConfig.call(candidate);
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
};
|
|
61
|
+
const getFileSystemService = async (context) => {
|
|
62
|
+
const scopedFileSystemService = createScopedFileSystemService(
|
|
63
|
+
context,
|
|
64
|
+
resolveInjectedServiceConfig(context) ?? fileSystemConfig
|
|
82
65
|
);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
86
|
-
logger.error(`Failed to initialize FileSystemService: ${message}`);
|
|
87
|
-
});
|
|
88
|
-
return fileSystemService;
|
|
66
|
+
await scopedFileSystemService.initialize();
|
|
67
|
+
return scopedFileSystemService;
|
|
89
68
|
};
|
|
90
69
|
const toolCreators = {
|
|
91
70
|
read_file: () => createReadFileTool(getFileSystemService),
|
|
@@ -193,6 +193,39 @@ function createToolContext(logger, overrides = {}) {
|
|
|
193
193
|
});
|
|
194
194
|
});
|
|
195
195
|
(0, import_vitest.describe)("File Modification Detection - New Files", () => {
|
|
196
|
+
(0, import_vitest.it)("should expand home-directory shorthand when creating a file", async () => {
|
|
197
|
+
const homeTempDir = await fs.mkdtemp(
|
|
198
|
+
path.join(os.homedir(), ".dexto-write-home-test-")
|
|
199
|
+
);
|
|
200
|
+
const homeRelativeDir = `~/${path.basename(homeTempDir)}`;
|
|
201
|
+
const fileSystemServiceForHome = new import_filesystem_service.FileSystemService(
|
|
202
|
+
{
|
|
203
|
+
allowedPaths: [homeTempDir],
|
|
204
|
+
blockedPaths: [],
|
|
205
|
+
blockedExtensions: [],
|
|
206
|
+
maxFileSize: 10 * 1024 * 1024,
|
|
207
|
+
workingDirectory: tempDir,
|
|
208
|
+
enableBackups: false,
|
|
209
|
+
backupRetentionDays: 7
|
|
210
|
+
},
|
|
211
|
+
mockLogger
|
|
212
|
+
);
|
|
213
|
+
await fileSystemServiceForHome.initialize();
|
|
214
|
+
const tool = (0, import_write_file_tool.createWriteFileTool)(async () => fileSystemServiceForHome);
|
|
215
|
+
try {
|
|
216
|
+
const parsedInput = tool.inputSchema.parse({
|
|
217
|
+
file_path: `${homeRelativeDir}/nested/new-file.txt`,
|
|
218
|
+
content: "brand new content",
|
|
219
|
+
create_dirs: true
|
|
220
|
+
});
|
|
221
|
+
const result = await tool.execute(parsedInput, createToolContext(mockLogger));
|
|
222
|
+
(0, import_vitest.expect)(result.success).toBe(true);
|
|
223
|
+
(0, import_vitest.expect)(result.path).toBe(path.join(homeTempDir, "nested", "new-file.txt"));
|
|
224
|
+
(0, import_vitest.expect)(await fs.readFile(result.path, "utf-8")).toBe("brand new content");
|
|
225
|
+
} finally {
|
|
226
|
+
await fs.rm(homeTempDir, { recursive: true, force: true });
|
|
227
|
+
}
|
|
228
|
+
});
|
|
196
229
|
(0, import_vitest.it)("should succeed when creating new file that still does not exist", async () => {
|
|
197
230
|
const tool = (0, import_write_file_tool.createWriteFileTool)(async () => fileSystemService);
|
|
198
231
|
const testFile = path.join(tempDir, "new-file.txt");
|
|
@@ -170,6 +170,39 @@ describe("write_file tool", () => {
|
|
|
170
170
|
});
|
|
171
171
|
});
|
|
172
172
|
describe("File Modification Detection - New Files", () => {
|
|
173
|
+
it("should expand home-directory shorthand when creating a file", async () => {
|
|
174
|
+
const homeTempDir = await fs.mkdtemp(
|
|
175
|
+
path.join(os.homedir(), ".dexto-write-home-test-")
|
|
176
|
+
);
|
|
177
|
+
const homeRelativeDir = `~/${path.basename(homeTempDir)}`;
|
|
178
|
+
const fileSystemServiceForHome = new FileSystemService(
|
|
179
|
+
{
|
|
180
|
+
allowedPaths: [homeTempDir],
|
|
181
|
+
blockedPaths: [],
|
|
182
|
+
blockedExtensions: [],
|
|
183
|
+
maxFileSize: 10 * 1024 * 1024,
|
|
184
|
+
workingDirectory: tempDir,
|
|
185
|
+
enableBackups: false,
|
|
186
|
+
backupRetentionDays: 7
|
|
187
|
+
},
|
|
188
|
+
mockLogger
|
|
189
|
+
);
|
|
190
|
+
await fileSystemServiceForHome.initialize();
|
|
191
|
+
const tool = createWriteFileTool(async () => fileSystemServiceForHome);
|
|
192
|
+
try {
|
|
193
|
+
const parsedInput = tool.inputSchema.parse({
|
|
194
|
+
file_path: `${homeRelativeDir}/nested/new-file.txt`,
|
|
195
|
+
content: "brand new content",
|
|
196
|
+
create_dirs: true
|
|
197
|
+
});
|
|
198
|
+
const result = await tool.execute(parsedInput, createToolContext(mockLogger));
|
|
199
|
+
expect(result.success).toBe(true);
|
|
200
|
+
expect(result.path).toBe(path.join(homeTempDir, "nested", "new-file.txt"));
|
|
201
|
+
expect(await fs.readFile(result.path, "utf-8")).toBe("brand new content");
|
|
202
|
+
} finally {
|
|
203
|
+
await fs.rm(homeTempDir, { recursive: true, force: true });
|
|
204
|
+
}
|
|
205
|
+
});
|
|
173
206
|
it("should succeed when creating new file that still does not exist", async () => {
|
|
174
207
|
const tool = createWriteFileTool(async () => fileSystemService);
|
|
175
208
|
const testFile = path.join(tempDir, "new-file.txt");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dexto/tools-filesystem",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.26",
|
|
4
4
|
"description": "FileSystem tools factory for Dexto agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"glob": "^12.0.0",
|
|
23
23
|
"safe-regex": "^2.1.1",
|
|
24
24
|
"zod": "^3.25.0",
|
|
25
|
-
"@dexto/agent-config": "1.6.
|
|
26
|
-
"@dexto/core": "1.6.
|
|
25
|
+
"@dexto/agent-config": "1.6.26",
|
|
26
|
+
"@dexto/core": "1.6.26"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/diff": "^5.2.3",
|