@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 +23 -22
- package/dist/errors.js +24 -23
- package/dist/filesystem-service.cjs +7 -0
- package/dist/filesystem-service.d.cts +5 -0
- package/dist/filesystem-service.d.ts +5 -0
- package/dist/filesystem-service.js +7 -0
- package/dist/glob-files-tool.cjs +56 -3
- package/dist/glob-files-tool.d.cts +4 -3
- package/dist/glob-files-tool.d.ts +4 -3
- package/dist/glob-files-tool.js +46 -3
- package/dist/grep-content-tool.cjs +55 -3
- package/dist/grep-content-tool.d.cts +4 -3
- package/dist/grep-content-tool.d.ts +4 -3
- package/dist/grep-content-tool.js +45 -3
- package/dist/tool-provider.cjs +2 -2
- package/dist/tool-provider.js +2 -2
- package/package.json +2 -2
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
package/dist/glob-files-tool.cjs
CHANGED
|
@@ -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(
|
|
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:
|
|
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 {
|
|
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(
|
|
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 {
|
|
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(
|
|
15
|
+
declare function createGlobFilesTool(options: FileToolOptions): InternalTool;
|
|
15
16
|
|
|
16
17
|
export { createGlobFilesTool };
|
package/dist/glob-files-tool.js
CHANGED
|
@@ -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(
|
|
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:
|
|
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(
|
|
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 {
|
|
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(
|
|
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 {
|
|
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(
|
|
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(
|
|
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,
|
package/dist/tool-provider.cjs
CHANGED
|
@@ -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)(
|
|
106
|
-
grep_content: () => (0, import_grep_content_tool.createGrepContentTool)(
|
|
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) {
|
package/dist/tool-provider.js
CHANGED
|
@@ -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(
|
|
83
|
-
grep_content: () => createGrepContentTool(
|
|
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
|
+
"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.
|
|
25
|
+
"@dexto/core": "1.5.5"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/diff": "^5.2.3",
|