@dexto/tools-filesystem 1.5.3 → 1.5.5

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/errors.cjs CHANGED
@@ -23,6 +23,7 @@ __export(errors_exports, {
23
23
  module.exports = __toCommonJS(errors_exports);
24
24
  var import_core = require("@dexto/core");
25
25
  var import_error_codes = require("./error-codes.js");
26
+ const FILESYSTEM_SCOPE = "filesystem";
26
27
  class FileSystemError {
27
28
  constructor() {
28
29
  }
@@ -32,7 +33,7 @@ class FileSystemError {
32
33
  static fileNotFound(path) {
33
34
  return new import_core.DextoRuntimeError(
34
35
  import_error_codes.FileSystemErrorCode.FILE_NOT_FOUND,
35
- import_core.ErrorScope.FILESYSTEM,
36
+ FILESYSTEM_SCOPE,
36
37
  import_core.ErrorType.NOT_FOUND,
37
38
  `File not found: ${path}`,
38
39
  { path }
@@ -44,7 +45,7 @@ class FileSystemError {
44
45
  static directoryNotFound(path) {
45
46
  return new import_core.DextoRuntimeError(
46
47
  import_error_codes.FileSystemErrorCode.DIRECTORY_NOT_FOUND,
47
- import_core.ErrorScope.FILESYSTEM,
48
+ FILESYSTEM_SCOPE,
48
49
  import_core.ErrorType.NOT_FOUND,
49
50
  `Directory not found: ${path}`,
50
51
  { path }
@@ -56,7 +57,7 @@ class FileSystemError {
56
57
  static permissionDenied(path, operation) {
57
58
  return new import_core.DextoRuntimeError(
58
59
  import_error_codes.FileSystemErrorCode.PERMISSION_DENIED,
59
- import_core.ErrorScope.FILESYSTEM,
60
+ FILESYSTEM_SCOPE,
60
61
  import_core.ErrorType.FORBIDDEN,
61
62
  `Permission denied: cannot ${operation} ${path}`,
62
63
  { path, operation }
@@ -68,7 +69,7 @@ class FileSystemError {
68
69
  static pathNotAllowed(path, allowedPaths) {
69
70
  return new import_core.DextoRuntimeError(
70
71
  import_error_codes.FileSystemErrorCode.PATH_NOT_ALLOWED,
71
- import_core.ErrorScope.FILESYSTEM,
72
+ FILESYSTEM_SCOPE,
72
73
  import_core.ErrorType.USER,
73
74
  `Path not allowed: ${path}. Must be within allowed paths: ${allowedPaths.join(", ")}`,
74
75
  { path, allowedPaths },
@@ -81,7 +82,7 @@ class FileSystemError {
81
82
  static pathBlocked(path, reason) {
82
83
  return new import_core.DextoRuntimeError(
83
84
  import_error_codes.FileSystemErrorCode.PATH_BLOCKED,
84
- import_core.ErrorScope.FILESYSTEM,
85
+ FILESYSTEM_SCOPE,
85
86
  import_core.ErrorType.FORBIDDEN,
86
87
  `Path is blocked: ${path}. Reason: ${reason}`,
87
88
  { path, reason }
@@ -93,7 +94,7 @@ class FileSystemError {
93
94
  static invalidPath(path, reason) {
94
95
  return new import_core.DextoRuntimeError(
95
96
  import_error_codes.FileSystemErrorCode.INVALID_PATH,
96
- import_core.ErrorScope.FILESYSTEM,
97
+ FILESYSTEM_SCOPE,
97
98
  import_core.ErrorType.USER,
98
99
  `Invalid path: ${path}. ${reason}`,
99
100
  { path, reason }
@@ -105,7 +106,7 @@ class FileSystemError {
105
106
  static pathTraversal(path) {
106
107
  return new import_core.DextoRuntimeError(
107
108
  import_error_codes.FileSystemErrorCode.PATH_TRAVERSAL_DETECTED,
108
- import_core.ErrorScope.FILESYSTEM,
109
+ FILESYSTEM_SCOPE,
109
110
  import_core.ErrorType.FORBIDDEN,
110
111
  `Path traversal detected in: ${path}`,
111
112
  { path }
@@ -117,7 +118,7 @@ class FileSystemError {
117
118
  static invalidExtension(path, blockedExtensions) {
118
119
  return new import_core.DextoRuntimeError(
119
120
  import_error_codes.FileSystemErrorCode.INVALID_FILE_EXTENSION,
120
- import_core.ErrorScope.FILESYSTEM,
121
+ FILESYSTEM_SCOPE,
121
122
  import_core.ErrorType.USER,
122
123
  `Invalid file extension: ${path}. Blocked extensions: ${blockedExtensions.join(", ")}`,
123
124
  { path, blockedExtensions }
@@ -129,7 +130,7 @@ class FileSystemError {
129
130
  static fileTooLarge(path, size, maxSize) {
130
131
  return new import_core.DextoRuntimeError(
131
132
  import_error_codes.FileSystemErrorCode.FILE_TOO_LARGE,
132
- import_core.ErrorScope.FILESYSTEM,
133
+ FILESYSTEM_SCOPE,
133
134
  import_core.ErrorType.USER,
134
135
  `File too large: ${path} (${size} bytes). Maximum allowed: ${maxSize} bytes`,
135
136
  { path, size, maxSize }
@@ -141,7 +142,7 @@ class FileSystemError {
141
142
  static tooManyResults(operation, count, maxResults) {
142
143
  return new import_core.DextoRuntimeError(
143
144
  import_error_codes.FileSystemErrorCode.TOO_MANY_RESULTS,
144
- import_core.ErrorScope.FILESYSTEM,
145
+ FILESYSTEM_SCOPE,
145
146
  import_core.ErrorType.USER,
146
147
  `Too many results from ${operation}: ${count}. Maximum allowed: ${maxResults}`,
147
148
  { operation, count, maxResults },
@@ -154,7 +155,7 @@ class FileSystemError {
154
155
  static readFailed(path, cause) {
155
156
  return new import_core.DextoRuntimeError(
156
157
  import_error_codes.FileSystemErrorCode.READ_FAILED,
157
- import_core.ErrorScope.FILESYSTEM,
158
+ FILESYSTEM_SCOPE,
158
159
  import_core.ErrorType.SYSTEM,
159
160
  `Failed to read file: ${path}. ${cause}`,
160
161
  { path, cause }
@@ -166,7 +167,7 @@ class FileSystemError {
166
167
  static writeFailed(path, cause) {
167
168
  return new import_core.DextoRuntimeError(
168
169
  import_error_codes.FileSystemErrorCode.WRITE_FAILED,
169
- import_core.ErrorScope.FILESYSTEM,
170
+ FILESYSTEM_SCOPE,
170
171
  import_core.ErrorType.SYSTEM,
171
172
  `Failed to write file: ${path}. ${cause}`,
172
173
  { path, cause }
@@ -178,7 +179,7 @@ class FileSystemError {
178
179
  static backupFailed(path, cause) {
179
180
  return new import_core.DextoRuntimeError(
180
181
  import_error_codes.FileSystemErrorCode.BACKUP_FAILED,
181
- import_core.ErrorScope.FILESYSTEM,
182
+ FILESYSTEM_SCOPE,
182
183
  import_core.ErrorType.SYSTEM,
183
184
  `Failed to create backup for: ${path}. ${cause}`,
184
185
  { path, cause }
@@ -190,7 +191,7 @@ class FileSystemError {
190
191
  static editFailed(path, cause) {
191
192
  return new import_core.DextoRuntimeError(
192
193
  import_error_codes.FileSystemErrorCode.EDIT_FAILED,
193
- import_core.ErrorScope.FILESYSTEM,
194
+ FILESYSTEM_SCOPE,
194
195
  import_core.ErrorType.SYSTEM,
195
196
  `Failed to edit file: ${path}. ${cause}`,
196
197
  { path, cause }
@@ -202,7 +203,7 @@ class FileSystemError {
202
203
  static stringNotUnique(path, searchString, occurrences) {
203
204
  return new import_core.DextoRuntimeError(
204
205
  import_error_codes.FileSystemErrorCode.STRING_NOT_UNIQUE,
205
- import_core.ErrorScope.FILESYSTEM,
206
+ FILESYSTEM_SCOPE,
206
207
  import_core.ErrorType.USER,
207
208
  `String is not unique in ${path}: "${searchString}" found ${occurrences} times. Use replaceAll=true or provide a more specific string.`,
208
209
  { path, searchString, occurrences },
@@ -215,7 +216,7 @@ class FileSystemError {
215
216
  static stringNotFound(path, searchString) {
216
217
  return new import_core.DextoRuntimeError(
217
218
  import_error_codes.FileSystemErrorCode.STRING_NOT_FOUND,
218
- import_core.ErrorScope.FILESYSTEM,
219
+ FILESYSTEM_SCOPE,
219
220
  import_core.ErrorType.USER,
220
221
  `String not found in ${path}: "${searchString}"`,
221
222
  { path, searchString }
@@ -227,7 +228,7 @@ class FileSystemError {
227
228
  static globFailed(pattern, cause) {
228
229
  return new import_core.DextoRuntimeError(
229
230
  import_error_codes.FileSystemErrorCode.GLOB_FAILED,
230
- import_core.ErrorScope.FILESYSTEM,
231
+ FILESYSTEM_SCOPE,
231
232
  import_core.ErrorType.SYSTEM,
232
233
  `Glob operation failed for pattern: ${pattern}. ${cause}`,
233
234
  { pattern, cause }
@@ -239,7 +240,7 @@ class FileSystemError {
239
240
  static searchFailed(pattern, cause) {
240
241
  return new import_core.DextoRuntimeError(
241
242
  import_error_codes.FileSystemErrorCode.SEARCH_FAILED,
242
- import_core.ErrorScope.FILESYSTEM,
243
+ FILESYSTEM_SCOPE,
243
244
  import_core.ErrorType.SYSTEM,
244
245
  `Search operation failed for pattern: ${pattern}. ${cause}`,
245
246
  { pattern, cause }
@@ -251,7 +252,7 @@ class FileSystemError {
251
252
  static invalidPattern(pattern, cause) {
252
253
  return new import_core.DextoRuntimeError(
253
254
  import_error_codes.FileSystemErrorCode.INVALID_PATTERN,
254
- import_core.ErrorScope.FILESYSTEM,
255
+ FILESYSTEM_SCOPE,
255
256
  import_core.ErrorType.USER,
256
257
  `Invalid pattern: ${pattern}. ${cause}`,
257
258
  { pattern, cause }
@@ -263,7 +264,7 @@ class FileSystemError {
263
264
  static regexTimeout(pattern) {
264
265
  return new import_core.DextoRuntimeError(
265
266
  import_error_codes.FileSystemErrorCode.REGEX_TIMEOUT,
266
- import_core.ErrorScope.FILESYSTEM,
267
+ FILESYSTEM_SCOPE,
267
268
  import_core.ErrorType.TIMEOUT,
268
269
  `Regex operation timed out for pattern: ${pattern}`,
269
270
  { pattern },
@@ -276,7 +277,7 @@ class FileSystemError {
276
277
  static invalidConfig(reason) {
277
278
  return new import_core.DextoRuntimeError(
278
279
  import_error_codes.FileSystemErrorCode.INVALID_CONFIG,
279
- import_core.ErrorScope.FILESYSTEM,
280
+ FILESYSTEM_SCOPE,
280
281
  import_core.ErrorType.USER,
281
282
  `Invalid FileSystem configuration: ${reason}`,
282
283
  { reason }
@@ -288,7 +289,7 @@ class FileSystemError {
288
289
  static notInitialized() {
289
290
  return new import_core.DextoRuntimeError(
290
291
  import_error_codes.FileSystemErrorCode.SERVICE_NOT_INITIALIZED,
291
- import_core.ErrorScope.FILESYSTEM,
292
+ FILESYSTEM_SCOPE,
292
293
  import_core.ErrorType.SYSTEM,
293
294
  "FileSystemService has not been initialized",
294
295
  {},
package/dist/errors.js CHANGED
@@ -1,4 +1,5 @@
1
- import { DextoRuntimeError, ErrorScope, ErrorType } from "@dexto/core";
1
+ import { DextoRuntimeError, ErrorType } from "@dexto/core";
2
+ const FILESYSTEM_SCOPE = "filesystem";
2
3
  import { FileSystemErrorCode } from "./error-codes.js";
3
4
  class FileSystemError {
4
5
  constructor() {
@@ -9,7 +10,7 @@ class FileSystemError {
9
10
  static fileNotFound(path) {
10
11
  return new DextoRuntimeError(
11
12
  FileSystemErrorCode.FILE_NOT_FOUND,
12
- ErrorScope.FILESYSTEM,
13
+ FILESYSTEM_SCOPE,
13
14
  ErrorType.NOT_FOUND,
14
15
  `File not found: ${path}`,
15
16
  { path }
@@ -21,7 +22,7 @@ class FileSystemError {
21
22
  static directoryNotFound(path) {
22
23
  return new DextoRuntimeError(
23
24
  FileSystemErrorCode.DIRECTORY_NOT_FOUND,
24
- ErrorScope.FILESYSTEM,
25
+ FILESYSTEM_SCOPE,
25
26
  ErrorType.NOT_FOUND,
26
27
  `Directory not found: ${path}`,
27
28
  { path }
@@ -33,7 +34,7 @@ class FileSystemError {
33
34
  static permissionDenied(path, operation) {
34
35
  return new DextoRuntimeError(
35
36
  FileSystemErrorCode.PERMISSION_DENIED,
36
- ErrorScope.FILESYSTEM,
37
+ FILESYSTEM_SCOPE,
37
38
  ErrorType.FORBIDDEN,
38
39
  `Permission denied: cannot ${operation} ${path}`,
39
40
  { path, operation }
@@ -45,7 +46,7 @@ class FileSystemError {
45
46
  static pathNotAllowed(path, allowedPaths) {
46
47
  return new DextoRuntimeError(
47
48
  FileSystemErrorCode.PATH_NOT_ALLOWED,
48
- ErrorScope.FILESYSTEM,
49
+ FILESYSTEM_SCOPE,
49
50
  ErrorType.USER,
50
51
  `Path not allowed: ${path}. Must be within allowed paths: ${allowedPaths.join(", ")}`,
51
52
  { path, allowedPaths },
@@ -58,7 +59,7 @@ class FileSystemError {
58
59
  static pathBlocked(path, reason) {
59
60
  return new DextoRuntimeError(
60
61
  FileSystemErrorCode.PATH_BLOCKED,
61
- ErrorScope.FILESYSTEM,
62
+ FILESYSTEM_SCOPE,
62
63
  ErrorType.FORBIDDEN,
63
64
  `Path is blocked: ${path}. Reason: ${reason}`,
64
65
  { path, reason }
@@ -70,7 +71,7 @@ class FileSystemError {
70
71
  static invalidPath(path, reason) {
71
72
  return new DextoRuntimeError(
72
73
  FileSystemErrorCode.INVALID_PATH,
73
- ErrorScope.FILESYSTEM,
74
+ FILESYSTEM_SCOPE,
74
75
  ErrorType.USER,
75
76
  `Invalid path: ${path}. ${reason}`,
76
77
  { path, reason }
@@ -82,7 +83,7 @@ class FileSystemError {
82
83
  static pathTraversal(path) {
83
84
  return new DextoRuntimeError(
84
85
  FileSystemErrorCode.PATH_TRAVERSAL_DETECTED,
85
- ErrorScope.FILESYSTEM,
86
+ FILESYSTEM_SCOPE,
86
87
  ErrorType.FORBIDDEN,
87
88
  `Path traversal detected in: ${path}`,
88
89
  { path }
@@ -94,7 +95,7 @@ class FileSystemError {
94
95
  static invalidExtension(path, blockedExtensions) {
95
96
  return new DextoRuntimeError(
96
97
  FileSystemErrorCode.INVALID_FILE_EXTENSION,
97
- ErrorScope.FILESYSTEM,
98
+ FILESYSTEM_SCOPE,
98
99
  ErrorType.USER,
99
100
  `Invalid file extension: ${path}. Blocked extensions: ${blockedExtensions.join(", ")}`,
100
101
  { path, blockedExtensions }
@@ -106,7 +107,7 @@ class FileSystemError {
106
107
  static fileTooLarge(path, size, maxSize) {
107
108
  return new DextoRuntimeError(
108
109
  FileSystemErrorCode.FILE_TOO_LARGE,
109
- ErrorScope.FILESYSTEM,
110
+ FILESYSTEM_SCOPE,
110
111
  ErrorType.USER,
111
112
  `File too large: ${path} (${size} bytes). Maximum allowed: ${maxSize} bytes`,
112
113
  { path, size, maxSize }
@@ -118,7 +119,7 @@ class FileSystemError {
118
119
  static tooManyResults(operation, count, maxResults) {
119
120
  return new DextoRuntimeError(
120
121
  FileSystemErrorCode.TOO_MANY_RESULTS,
121
- ErrorScope.FILESYSTEM,
122
+ FILESYSTEM_SCOPE,
122
123
  ErrorType.USER,
123
124
  `Too many results from ${operation}: ${count}. Maximum allowed: ${maxResults}`,
124
125
  { operation, count, maxResults },
@@ -131,7 +132,7 @@ class FileSystemError {
131
132
  static readFailed(path, cause) {
132
133
  return new DextoRuntimeError(
133
134
  FileSystemErrorCode.READ_FAILED,
134
- ErrorScope.FILESYSTEM,
135
+ FILESYSTEM_SCOPE,
135
136
  ErrorType.SYSTEM,
136
137
  `Failed to read file: ${path}. ${cause}`,
137
138
  { path, cause }
@@ -143,7 +144,7 @@ class FileSystemError {
143
144
  static writeFailed(path, cause) {
144
145
  return new DextoRuntimeError(
145
146
  FileSystemErrorCode.WRITE_FAILED,
146
- ErrorScope.FILESYSTEM,
147
+ FILESYSTEM_SCOPE,
147
148
  ErrorType.SYSTEM,
148
149
  `Failed to write file: ${path}. ${cause}`,
149
150
  { path, cause }
@@ -155,7 +156,7 @@ class FileSystemError {
155
156
  static backupFailed(path, cause) {
156
157
  return new DextoRuntimeError(
157
158
  FileSystemErrorCode.BACKUP_FAILED,
158
- ErrorScope.FILESYSTEM,
159
+ FILESYSTEM_SCOPE,
159
160
  ErrorType.SYSTEM,
160
161
  `Failed to create backup for: ${path}. ${cause}`,
161
162
  { path, cause }
@@ -167,7 +168,7 @@ class FileSystemError {
167
168
  static editFailed(path, cause) {
168
169
  return new DextoRuntimeError(
169
170
  FileSystemErrorCode.EDIT_FAILED,
170
- ErrorScope.FILESYSTEM,
171
+ FILESYSTEM_SCOPE,
171
172
  ErrorType.SYSTEM,
172
173
  `Failed to edit file: ${path}. ${cause}`,
173
174
  { path, cause }
@@ -179,7 +180,7 @@ class FileSystemError {
179
180
  static stringNotUnique(path, searchString, occurrences) {
180
181
  return new DextoRuntimeError(
181
182
  FileSystemErrorCode.STRING_NOT_UNIQUE,
182
- ErrorScope.FILESYSTEM,
183
+ FILESYSTEM_SCOPE,
183
184
  ErrorType.USER,
184
185
  `String is not unique in ${path}: "${searchString}" found ${occurrences} times. Use replaceAll=true or provide a more specific string.`,
185
186
  { path, searchString, occurrences },
@@ -192,7 +193,7 @@ class FileSystemError {
192
193
  static stringNotFound(path, searchString) {
193
194
  return new DextoRuntimeError(
194
195
  FileSystemErrorCode.STRING_NOT_FOUND,
195
- ErrorScope.FILESYSTEM,
196
+ FILESYSTEM_SCOPE,
196
197
  ErrorType.USER,
197
198
  `String not found in ${path}: "${searchString}"`,
198
199
  { path, searchString }
@@ -204,7 +205,7 @@ class FileSystemError {
204
205
  static globFailed(pattern, cause) {
205
206
  return new DextoRuntimeError(
206
207
  FileSystemErrorCode.GLOB_FAILED,
207
- ErrorScope.FILESYSTEM,
208
+ FILESYSTEM_SCOPE,
208
209
  ErrorType.SYSTEM,
209
210
  `Glob operation failed for pattern: ${pattern}. ${cause}`,
210
211
  { pattern, cause }
@@ -216,7 +217,7 @@ class FileSystemError {
216
217
  static searchFailed(pattern, cause) {
217
218
  return new DextoRuntimeError(
218
219
  FileSystemErrorCode.SEARCH_FAILED,
219
- ErrorScope.FILESYSTEM,
220
+ FILESYSTEM_SCOPE,
220
221
  ErrorType.SYSTEM,
221
222
  `Search operation failed for pattern: ${pattern}. ${cause}`,
222
223
  { pattern, cause }
@@ -228,7 +229,7 @@ class FileSystemError {
228
229
  static invalidPattern(pattern, cause) {
229
230
  return new DextoRuntimeError(
230
231
  FileSystemErrorCode.INVALID_PATTERN,
231
- ErrorScope.FILESYSTEM,
232
+ FILESYSTEM_SCOPE,
232
233
  ErrorType.USER,
233
234
  `Invalid pattern: ${pattern}. ${cause}`,
234
235
  { pattern, cause }
@@ -240,7 +241,7 @@ class FileSystemError {
240
241
  static regexTimeout(pattern) {
241
242
  return new DextoRuntimeError(
242
243
  FileSystemErrorCode.REGEX_TIMEOUT,
243
- ErrorScope.FILESYSTEM,
244
+ FILESYSTEM_SCOPE,
244
245
  ErrorType.TIMEOUT,
245
246
  `Regex operation timed out for pattern: ${pattern}`,
246
247
  { pattern },
@@ -253,7 +254,7 @@ class FileSystemError {
253
254
  static invalidConfig(reason) {
254
255
  return new DextoRuntimeError(
255
256
  FileSystemErrorCode.INVALID_CONFIG,
256
- ErrorScope.FILESYSTEM,
257
+ FILESYSTEM_SCOPE,
257
258
  ErrorType.USER,
258
259
  `Invalid FileSystem configuration: ${reason}`,
259
260
  { reason }
@@ -265,7 +266,7 @@ class FileSystemError {
265
266
  static notInitialized() {
266
267
  return new DextoRuntimeError(
267
268
  FileSystemErrorCode.SERVICE_NOT_INITIALIZED,
268
- ErrorScope.FILESYSTEM,
269
+ FILESYSTEM_SCOPE,
269
270
  ErrorType.SYSTEM,
270
271
  "FileSystemService has not been initialized",
271
272
  {},
@@ -66,6 +66,13 @@ class FileSystemService {
66
66
  getBackupDir() {
67
67
  return this.config.backupPath || (0, import_core.getDextoPath)("backups");
68
68
  }
69
+ /**
70
+ * Get the effective working directory for file operations.
71
+ * Falls back to process.cwd() if not configured.
72
+ */
73
+ getWorkingDirectory() {
74
+ return this.config.workingDirectory || process.cwd();
75
+ }
69
76
  /**
70
77
  * Initialize the service.
71
78
  * Safe to call multiple times - subsequent calls return the same promise.
@@ -36,6 +36,11 @@ declare class FileSystemService {
36
36
  * TODO: Migrate to explicit configuration via CLI enrichment layer (per-agent paths)
37
37
  */
38
38
  private getBackupDir;
39
+ /**
40
+ * Get the effective working directory for file operations.
41
+ * Falls back to process.cwd() if not configured.
42
+ */
43
+ getWorkingDirectory(): string;
39
44
  /**
40
45
  * Initialize the service.
41
46
  * Safe to call multiple times - subsequent calls return the same promise.
@@ -36,6 +36,11 @@ declare class FileSystemService {
36
36
  * TODO: Migrate to explicit configuration via CLI enrichment layer (per-agent paths)
37
37
  */
38
38
  private getBackupDir;
39
+ /**
40
+ * Get the effective working directory for file operations.
41
+ * Falls back to process.cwd() if not configured.
42
+ */
43
+ getWorkingDirectory(): string;
39
44
  /**
40
45
  * Initialize the service.
41
46
  * Safe to call multiple times - subsequent calls return the same promise.
@@ -33,6 +33,13 @@ class FileSystemService {
33
33
  getBackupDir() {
34
34
  return this.config.backupPath || getDextoPath("backups");
35
35
  }
36
+ /**
37
+ * Get the effective working directory for file operations.
38
+ * Falls back to process.cwd() if not configured.
39
+ */
40
+ getWorkingDirectory() {
41
+ return this.config.workingDirectory || process.cwd();
42
+ }
36
43
  /**
37
44
  * Initialize the service.
38
45
  * Safe to call multiple times - subsequent calls return the same promise.
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,27 +17,78 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
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
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
  var glob_files_tool_exports = {};
20
30
  __export(glob_files_tool_exports, {
21
31
  createGlobFilesTool: () => createGlobFilesTool
22
32
  });
23
33
  module.exports = __toCommonJS(glob_files_tool_exports);
34
+ var path = __toESM(require("node:path"), 1);
24
35
  var import_zod = require("zod");
36
+ var import_core = require("@dexto/core");
25
37
  const GlobFilesInputSchema = import_zod.z.object({
26
38
  pattern: import_zod.z.string().describe('Glob pattern to match files (e.g., "**/*.ts", "src/**/*.js")'),
27
39
  path: import_zod.z.string().optional().describe("Base directory to search from (defaults to working directory)"),
28
40
  max_results: import_zod.z.number().int().positive().optional().default(1e3).describe("Maximum number of results to return (default: 1000)")
29
41
  }).strict();
30
- function createGlobFilesTool(fileSystemService) {
42
+ function createGlobFilesTool(options) {
43
+ const { fileSystemService, directoryApproval } = options;
44
+ let pendingApprovalSearchDir;
31
45
  return {
32
46
  id: "glob_files",
33
47
  description: "Find files matching a glob pattern. Supports standard glob syntax like **/*.js for recursive matches, *.ts for files in current directory, and src/**/*.tsx for nested paths. Returns array of file paths with metadata (size, modified date). Results are limited to allowed paths only.",
34
48
  inputSchema: GlobFilesInputSchema,
49
+ /**
50
+ * Check if this glob operation needs directory access approval.
51
+ * Returns custom approval request if the search directory is outside allowed paths.
52
+ */
53
+ getApprovalOverride: async (args) => {
54
+ const { path: searchPath } = args;
55
+ const baseDir = fileSystemService.getWorkingDirectory();
56
+ const searchDir = path.resolve(baseDir, searchPath || ".");
57
+ const isAllowed = await fileSystemService.isPathWithinConfigAllowed(searchDir);
58
+ if (isAllowed) {
59
+ return null;
60
+ }
61
+ if (directoryApproval?.isSessionApproved(searchDir)) {
62
+ return null;
63
+ }
64
+ pendingApprovalSearchDir = searchDir;
65
+ return {
66
+ type: import_core.ApprovalType.DIRECTORY_ACCESS,
67
+ metadata: {
68
+ path: searchDir,
69
+ parentDir: searchDir,
70
+ operation: "search",
71
+ toolName: "glob_files"
72
+ }
73
+ };
74
+ },
75
+ /**
76
+ * Handle approved directory access - remember the directory for session
77
+ */
78
+ onApprovalGranted: (response) => {
79
+ if (!directoryApproval || !pendingApprovalSearchDir) return;
80
+ const data = response.data;
81
+ const rememberDirectory = data?.rememberDirectory ?? false;
82
+ directoryApproval.addApproved(
83
+ pendingApprovalSearchDir,
84
+ rememberDirectory ? "session" : "once"
85
+ );
86
+ pendingApprovalSearchDir = void 0;
87
+ },
35
88
  execute: async (input, _context) => {
36
- const { pattern, path, max_results } = input;
89
+ const { pattern, path: path2, max_results } = input;
37
90
  const result = await fileSystemService.globFiles(pattern, {
38
- cwd: path,
91
+ cwd: path2,
39
92
  maxResults: max_results,
40
93
  includeMetadata: true
41
94
  });
@@ -1,5 +1,6 @@
1
1
  import { InternalTool } from '@dexto/core';
2
- import { FileSystemService } from './filesystem-service.cjs';
2
+ import { FileToolOptions } from './file-tool-types.cjs';
3
+ import './filesystem-service.cjs';
3
4
  import './types.cjs';
4
5
 
5
6
  /**
@@ -9,8 +10,8 @@ import './types.cjs';
9
10
  */
10
11
 
11
12
  /**
12
- * Create the glob_files internal tool
13
+ * Create the glob_files internal tool with directory approval support
13
14
  */
14
- declare function createGlobFilesTool(fileSystemService: FileSystemService): InternalTool;
15
+ declare function createGlobFilesTool(options: FileToolOptions): InternalTool;
15
16
 
16
17
  export { createGlobFilesTool };
@@ -1,5 +1,6 @@
1
1
  import { InternalTool } from '@dexto/core';
2
- import { FileSystemService } from './filesystem-service.js';
2
+ import { FileToolOptions } from './file-tool-types.js';
3
+ import './filesystem-service.js';
3
4
  import './types.js';
4
5
 
5
6
  /**
@@ -9,8 +10,8 @@ import './types.js';
9
10
  */
10
11
 
11
12
  /**
12
- * Create the glob_files internal tool
13
+ * Create the glob_files internal tool with directory approval support
13
14
  */
14
- declare function createGlobFilesTool(fileSystemService: FileSystemService): InternalTool;
15
+ declare function createGlobFilesTool(options: FileToolOptions): InternalTool;
15
16
 
16
17
  export { createGlobFilesTool };
@@ -1,18 +1,61 @@
1
+ import * as path from "node:path";
1
2
  import { z } from "zod";
3
+ import { ApprovalType } from "@dexto/core";
2
4
  const GlobFilesInputSchema = z.object({
3
5
  pattern: z.string().describe('Glob pattern to match files (e.g., "**/*.ts", "src/**/*.js")'),
4
6
  path: z.string().optional().describe("Base directory to search from (defaults to working directory)"),
5
7
  max_results: z.number().int().positive().optional().default(1e3).describe("Maximum number of results to return (default: 1000)")
6
8
  }).strict();
7
- function createGlobFilesTool(fileSystemService) {
9
+ function createGlobFilesTool(options) {
10
+ const { fileSystemService, directoryApproval } = options;
11
+ let pendingApprovalSearchDir;
8
12
  return {
9
13
  id: "glob_files",
10
14
  description: "Find files matching a glob pattern. Supports standard glob syntax like **/*.js for recursive matches, *.ts for files in current directory, and src/**/*.tsx for nested paths. Returns array of file paths with metadata (size, modified date). Results are limited to allowed paths only.",
11
15
  inputSchema: GlobFilesInputSchema,
16
+ /**
17
+ * Check if this glob operation needs directory access approval.
18
+ * Returns custom approval request if the search directory is outside allowed paths.
19
+ */
20
+ getApprovalOverride: async (args) => {
21
+ const { path: searchPath } = args;
22
+ const baseDir = fileSystemService.getWorkingDirectory();
23
+ const searchDir = path.resolve(baseDir, searchPath || ".");
24
+ const isAllowed = await fileSystemService.isPathWithinConfigAllowed(searchDir);
25
+ if (isAllowed) {
26
+ return null;
27
+ }
28
+ if (directoryApproval?.isSessionApproved(searchDir)) {
29
+ return null;
30
+ }
31
+ pendingApprovalSearchDir = searchDir;
32
+ return {
33
+ type: ApprovalType.DIRECTORY_ACCESS,
34
+ metadata: {
35
+ path: searchDir,
36
+ parentDir: searchDir,
37
+ operation: "search",
38
+ toolName: "glob_files"
39
+ }
40
+ };
41
+ },
42
+ /**
43
+ * Handle approved directory access - remember the directory for session
44
+ */
45
+ onApprovalGranted: (response) => {
46
+ if (!directoryApproval || !pendingApprovalSearchDir) return;
47
+ const data = response.data;
48
+ const rememberDirectory = data?.rememberDirectory ?? false;
49
+ directoryApproval.addApproved(
50
+ pendingApprovalSearchDir,
51
+ rememberDirectory ? "session" : "once"
52
+ );
53
+ pendingApprovalSearchDir = void 0;
54
+ },
12
55
  execute: async (input, _context) => {
13
- const { pattern, path, max_results } = input;
56
+ const { pattern, path: path2, max_results } = input;
14
57
  const result = await fileSystemService.globFiles(pattern, {
15
- cwd: path,
58
+ cwd: path2,
16
59
  maxResults: max_results,
17
60
  includeMetadata: true
18
61
  });
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,13 +17,23 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
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
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
  var grep_content_tool_exports = {};
20
30
  __export(grep_content_tool_exports, {
21
31
  createGrepContentTool: () => createGrepContentTool
22
32
  });
23
33
  module.exports = __toCommonJS(grep_content_tool_exports);
34
+ var path = __toESM(require("node:path"), 1);
24
35
  var import_zod = require("zod");
36
+ var import_core = require("@dexto/core");
25
37
  const GrepContentInputSchema = import_zod.z.object({
26
38
  pattern: import_zod.z.string().describe("Regular expression pattern to search for"),
27
39
  path: import_zod.z.string().optional().describe("Directory to search in (defaults to working directory)"),
@@ -32,15 +44,55 @@ const GrepContentInputSchema = import_zod.z.object({
32
44
  case_insensitive: import_zod.z.boolean().optional().default(false).describe("Perform case-insensitive search (default: false)"),
33
45
  max_results: import_zod.z.number().int().positive().optional().default(100).describe("Maximum number of results to return (default: 100)")
34
46
  }).strict();
35
- function createGrepContentTool(fileSystemService) {
47
+ function createGrepContentTool(options) {
48
+ const { fileSystemService, directoryApproval } = options;
49
+ let pendingApprovalSearchDir;
36
50
  return {
37
51
  id: "grep_content",
38
52
  description: 'Search for text patterns in files using regular expressions. Returns matching lines with file path, line number, and optional context lines. Use glob parameter to filter specific file types (e.g., "*.ts"). Supports case-insensitive search. Great for finding code patterns, function definitions, or specific text across multiple files.',
39
53
  inputSchema: GrepContentInputSchema,
54
+ /**
55
+ * Check if this grep operation needs directory access approval.
56
+ * Returns custom approval request if the search directory is outside allowed paths.
57
+ */
58
+ getApprovalOverride: async (args) => {
59
+ const { path: searchPath } = args;
60
+ const searchDir = path.resolve(searchPath || process.cwd());
61
+ const isAllowed = await fileSystemService.isPathWithinConfigAllowed(searchDir);
62
+ if (isAllowed) {
63
+ return null;
64
+ }
65
+ if (directoryApproval?.isSessionApproved(searchDir)) {
66
+ return null;
67
+ }
68
+ pendingApprovalSearchDir = searchDir;
69
+ return {
70
+ type: import_core.ApprovalType.DIRECTORY_ACCESS,
71
+ metadata: {
72
+ path: searchDir,
73
+ parentDir: searchDir,
74
+ operation: "search",
75
+ toolName: "grep_content"
76
+ }
77
+ };
78
+ },
79
+ /**
80
+ * Handle approved directory access - remember the directory for session
81
+ */
82
+ onApprovalGranted: (response) => {
83
+ if (!directoryApproval || !pendingApprovalSearchDir) return;
84
+ const data = response.data;
85
+ const rememberDirectory = data?.rememberDirectory ?? false;
86
+ directoryApproval.addApproved(
87
+ pendingApprovalSearchDir,
88
+ rememberDirectory ? "session" : "once"
89
+ );
90
+ pendingApprovalSearchDir = void 0;
91
+ },
40
92
  execute: async (input, _context) => {
41
- const { pattern, path, glob, context_lines, case_insensitive, max_results } = input;
93
+ const { pattern, path: path2, glob, context_lines, case_insensitive, max_results } = input;
42
94
  const result = await fileSystemService.searchContent(pattern, {
43
- path,
95
+ path: path2,
44
96
  glob,
45
97
  contextLines: context_lines,
46
98
  caseInsensitive: case_insensitive,
@@ -1,5 +1,6 @@
1
1
  import { InternalTool } from '@dexto/core';
2
- import { FileSystemService } from './filesystem-service.cjs';
2
+ import { FileToolOptions } from './file-tool-types.cjs';
3
+ import './filesystem-service.cjs';
3
4
  import './types.cjs';
4
5
 
5
6
  /**
@@ -9,8 +10,8 @@ import './types.cjs';
9
10
  */
10
11
 
11
12
  /**
12
- * Create the grep_content internal tool
13
+ * Create the grep_content internal tool with directory approval support
13
14
  */
14
- declare function createGrepContentTool(fileSystemService: FileSystemService): InternalTool;
15
+ declare function createGrepContentTool(options: FileToolOptions): InternalTool;
15
16
 
16
17
  export { createGrepContentTool };
@@ -1,5 +1,6 @@
1
1
  import { InternalTool } from '@dexto/core';
2
- import { FileSystemService } from './filesystem-service.js';
2
+ import { FileToolOptions } from './file-tool-types.js';
3
+ import './filesystem-service.js';
3
4
  import './types.js';
4
5
 
5
6
  /**
@@ -9,8 +10,8 @@ import './types.js';
9
10
  */
10
11
 
11
12
  /**
12
- * Create the grep_content internal tool
13
+ * Create the grep_content internal tool with directory approval support
13
14
  */
14
- declare function createGrepContentTool(fileSystemService: FileSystemService): InternalTool;
15
+ declare function createGrepContentTool(options: FileToolOptions): InternalTool;
15
16
 
16
17
  export { createGrepContentTool };
@@ -1,4 +1,6 @@
1
+ import * as path from "node:path";
1
2
  import { z } from "zod";
3
+ import { ApprovalType } from "@dexto/core";
2
4
  const GrepContentInputSchema = z.object({
3
5
  pattern: z.string().describe("Regular expression pattern to search for"),
4
6
  path: z.string().optional().describe("Directory to search in (defaults to working directory)"),
@@ -9,15 +11,55 @@ const GrepContentInputSchema = z.object({
9
11
  case_insensitive: z.boolean().optional().default(false).describe("Perform case-insensitive search (default: false)"),
10
12
  max_results: z.number().int().positive().optional().default(100).describe("Maximum number of results to return (default: 100)")
11
13
  }).strict();
12
- function createGrepContentTool(fileSystemService) {
14
+ function createGrepContentTool(options) {
15
+ const { fileSystemService, directoryApproval } = options;
16
+ let pendingApprovalSearchDir;
13
17
  return {
14
18
  id: "grep_content",
15
19
  description: 'Search for text patterns in files using regular expressions. Returns matching lines with file path, line number, and optional context lines. Use glob parameter to filter specific file types (e.g., "*.ts"). Supports case-insensitive search. Great for finding code patterns, function definitions, or specific text across multiple files.',
16
20
  inputSchema: GrepContentInputSchema,
21
+ /**
22
+ * Check if this grep operation needs directory access approval.
23
+ * Returns custom approval request if the search directory is outside allowed paths.
24
+ */
25
+ getApprovalOverride: async (args) => {
26
+ const { path: searchPath } = args;
27
+ const searchDir = path.resolve(searchPath || process.cwd());
28
+ const isAllowed = await fileSystemService.isPathWithinConfigAllowed(searchDir);
29
+ if (isAllowed) {
30
+ return null;
31
+ }
32
+ if (directoryApproval?.isSessionApproved(searchDir)) {
33
+ return null;
34
+ }
35
+ pendingApprovalSearchDir = searchDir;
36
+ return {
37
+ type: ApprovalType.DIRECTORY_ACCESS,
38
+ metadata: {
39
+ path: searchDir,
40
+ parentDir: searchDir,
41
+ operation: "search",
42
+ toolName: "grep_content"
43
+ }
44
+ };
45
+ },
46
+ /**
47
+ * Handle approved directory access - remember the directory for session
48
+ */
49
+ onApprovalGranted: (response) => {
50
+ if (!directoryApproval || !pendingApprovalSearchDir) return;
51
+ const data = response.data;
52
+ const rememberDirectory = data?.rememberDirectory ?? false;
53
+ directoryApproval.addApproved(
54
+ pendingApprovalSearchDir,
55
+ rememberDirectory ? "session" : "once"
56
+ );
57
+ pendingApprovalSearchDir = void 0;
58
+ },
17
59
  execute: async (input, _context) => {
18
- const { pattern, path, glob, context_lines, case_insensitive, max_results } = input;
60
+ const { pattern, path: path2, glob, context_lines, case_insensitive, max_results } = input;
19
61
  const result = await fileSystemService.searchContent(pattern, {
20
- path,
62
+ path: path2,
21
63
  glob,
22
64
  contextLines: context_lines,
23
65
  caseInsensitive: case_insensitive,
@@ -102,8 +102,8 @@ const fileSystemToolsProvider = {
102
102
  read_file: () => (0, import_read_file_tool.createReadFileTool)(fileToolOptions),
103
103
  write_file: () => (0, import_write_file_tool.createWriteFileTool)(fileToolOptions),
104
104
  edit_file: () => (0, import_edit_file_tool.createEditFileTool)(fileToolOptions),
105
- glob_files: () => (0, import_glob_files_tool.createGlobFilesTool)(fileSystemService),
106
- grep_content: () => (0, import_grep_content_tool.createGrepContentTool)(fileSystemService)
105
+ glob_files: () => (0, import_glob_files_tool.createGlobFilesTool)(fileToolOptions),
106
+ grep_content: () => (0, import_grep_content_tool.createGrepContentTool)(fileToolOptions)
107
107
  };
108
108
  const toolsToCreate = config.enabledTools ?? FILESYSTEM_TOOL_NAMES;
109
109
  if (config.enabledTools) {
@@ -79,8 +79,8 @@ const fileSystemToolsProvider = {
79
79
  read_file: () => createReadFileTool(fileToolOptions),
80
80
  write_file: () => createWriteFileTool(fileToolOptions),
81
81
  edit_file: () => createEditFileTool(fileToolOptions),
82
- glob_files: () => createGlobFilesTool(fileSystemService),
83
- grep_content: () => createGrepContentTool(fileSystemService)
82
+ glob_files: () => createGlobFilesTool(fileToolOptions),
83
+ grep_content: () => createGrepContentTool(fileToolOptions)
84
84
  };
85
85
  const toolsToCreate = config.enabledTools ?? FILESYSTEM_TOOL_NAMES;
86
86
  if (config.enabledTools) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexto/tools-filesystem",
3
- "version": "1.5.3",
3
+ "version": "1.5.5",
4
4
  "description": "FileSystem tools provider for Dexto agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "glob": "^11.1.0",
23
23
  "safe-regex": "^2.1.1",
24
24
  "zod": "^3.25.0",
25
- "@dexto/core": "1.5.3"
25
+ "@dexto/core": "1.5.5"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/diff": "^5.2.3",