@dexto/tools-filesystem 1.5.8 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/directory-approval.cjs +98 -0
  2. package/dist/directory-approval.d.ts +24 -0
  3. package/dist/directory-approval.d.ts.map +1 -0
  4. package/dist/directory-approval.integration.test.cjs +175 -390
  5. package/dist/directory-approval.integration.test.d.ts +14 -2
  6. package/dist/directory-approval.integration.test.d.ts.map +1 -0
  7. package/dist/directory-approval.integration.test.js +178 -390
  8. package/dist/directory-approval.js +63 -0
  9. package/dist/edit-file-tool.cjs +109 -120
  10. package/dist/edit-file-tool.d.ts +22 -9
  11. package/dist/edit-file-tool.d.ts.map +1 -0
  12. package/dist/edit-file-tool.js +116 -110
  13. package/dist/edit-file-tool.test.cjs +109 -29
  14. package/dist/edit-file-tool.test.d.ts +7 -2
  15. package/dist/edit-file-tool.test.d.ts.map +1 -0
  16. package/dist/edit-file-tool.test.js +109 -29
  17. package/dist/error-codes.cjs +4 -0
  18. package/dist/error-codes.d.ts +6 -3
  19. package/dist/error-codes.d.ts.map +1 -0
  20. package/dist/error-codes.js +4 -0
  21. package/dist/errors.cjs +48 -0
  22. package/dist/errors.d.ts +20 -7
  23. package/dist/errors.d.ts.map +1 -0
  24. package/dist/errors.js +48 -0
  25. package/dist/file-tool-types.d.ts +8 -40
  26. package/dist/file-tool-types.d.ts.map +1 -0
  27. package/dist/filesystem-service.cjs +325 -10
  28. package/dist/filesystem-service.d.ts +41 -12
  29. package/dist/filesystem-service.d.ts.map +1 -0
  30. package/dist/filesystem-service.js +326 -11
  31. package/dist/filesystem-service.test.cjs +10 -2
  32. package/dist/filesystem-service.test.d.ts +7 -2
  33. package/dist/filesystem-service.test.d.ts.map +1 -0
  34. package/dist/filesystem-service.test.js +10 -2
  35. package/dist/glob-files-tool.cjs +32 -46
  36. package/dist/glob-files-tool.d.ts +19 -9
  37. package/dist/glob-files-tool.d.ts.map +1 -0
  38. package/dist/glob-files-tool.js +33 -47
  39. package/dist/grep-content-tool.cjs +40 -45
  40. package/dist/grep-content-tool.d.ts +28 -9
  41. package/dist/grep-content-tool.d.ts.map +1 -0
  42. package/dist/grep-content-tool.js +41 -46
  43. package/dist/index.cjs +6 -3
  44. package/dist/index.d.cts +852 -14
  45. package/dist/index.d.ts +11 -5
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +4 -2
  48. package/dist/path-validator.cjs +28 -2
  49. package/dist/path-validator.d.ts +20 -9
  50. package/dist/path-validator.d.ts.map +1 -0
  51. package/dist/path-validator.js +28 -2
  52. package/dist/path-validator.test.d.ts +7 -2
  53. package/dist/path-validator.test.d.ts.map +1 -0
  54. package/dist/read-file-tool.cjs +26 -59
  55. package/dist/read-file-tool.d.ts +19 -9
  56. package/dist/read-file-tool.d.ts.map +1 -0
  57. package/dist/read-file-tool.js +27 -50
  58. package/dist/tool-factory-config.cjs +61 -0
  59. package/dist/{tool-provider.d.ts → tool-factory-config.d.ts} +13 -30
  60. package/dist/tool-factory-config.d.ts.map +1 -0
  61. package/dist/tool-factory-config.js +36 -0
  62. package/dist/tool-factory.cjs +123 -0
  63. package/dist/tool-factory.d.ts +4 -0
  64. package/dist/tool-factory.d.ts.map +1 -0
  65. package/dist/tool-factory.js +102 -0
  66. package/dist/types.d.ts +82 -18
  67. package/dist/types.d.ts.map +1 -0
  68. package/dist/write-file-tool.cjs +93 -99
  69. package/dist/write-file-tool.d.ts +22 -9
  70. package/dist/write-file-tool.d.ts.map +1 -0
  71. package/dist/write-file-tool.js +97 -91
  72. package/dist/write-file-tool.test.cjs +139 -33
  73. package/dist/write-file-tool.test.d.ts +7 -2
  74. package/dist/write-file-tool.test.d.ts.map +1 -0
  75. package/dist/write-file-tool.test.js +139 -33
  76. package/package.json +5 -4
  77. package/dist/directory-approval.integration.test.d.cts +0 -2
  78. package/dist/edit-file-tool.d.cts +0 -17
  79. package/dist/edit-file-tool.test.d.cts +0 -2
  80. package/dist/error-codes.d.cts +0 -32
  81. package/dist/errors.d.cts +0 -112
  82. package/dist/file-tool-types.d.cts +0 -46
  83. package/dist/filesystem-service.d.cts +0 -112
  84. package/dist/filesystem-service.test.d.cts +0 -2
  85. package/dist/glob-files-tool.d.cts +0 -17
  86. package/dist/grep-content-tool.d.cts +0 -17
  87. package/dist/path-validator.d.cts +0 -97
  88. package/dist/path-validator.test.d.cts +0 -2
  89. package/dist/read-file-tool.d.cts +0 -17
  90. package/dist/tool-provider.cjs +0 -123
  91. package/dist/tool-provider.d.cts +0 -77
  92. package/dist/tool-provider.js +0 -99
  93. package/dist/types.d.cts +0 -178
  94. package/dist/write-file-tool.d.cts +0 -17
  95. package/dist/write-file-tool.test.d.cts +0 -2
@@ -6,13 +6,26 @@ import { createEditFileTool } from "./edit-file-tool.js";
6
6
  import { FileSystemService } from "./filesystem-service.js";
7
7
  import { ToolErrorCode } from "@dexto/core";
8
8
  import { DextoRuntimeError } from "@dexto/core";
9
- const createMockLogger = () => ({
10
- debug: vi.fn(),
11
- info: vi.fn(),
12
- warn: vi.fn(),
13
- error: vi.fn(),
14
- createChild: vi.fn().mockReturnThis()
15
- });
9
+ const createMockLogger = () => {
10
+ const logger = {
11
+ debug: vi.fn(),
12
+ silly: vi.fn(),
13
+ info: vi.fn(),
14
+ warn: vi.fn(),
15
+ error: vi.fn(),
16
+ trackException: vi.fn(),
17
+ createChild: vi.fn(() => logger),
18
+ createFileOnlyChild: vi.fn(() => logger),
19
+ setLevel: vi.fn(),
20
+ getLevel: vi.fn(() => "debug"),
21
+ getLogFilePath: vi.fn(() => null),
22
+ destroy: vi.fn(async () => void 0)
23
+ };
24
+ return logger;
25
+ };
26
+ function createToolContext(logger, overrides = {}) {
27
+ return { logger, ...overrides };
28
+ }
16
29
  describe("edit_file tool", () => {
17
30
  let mockLogger;
18
31
  let tempDir;
@@ -43,8 +56,43 @@ describe("edit_file tool", () => {
43
56
  }
44
57
  });
45
58
  describe("File Modification Detection", () => {
59
+ it("should generate preview for files outside config-allowed roots (preview read only)", async () => {
60
+ const tool = createEditFileTool(async () => fileSystemService);
61
+ const previewFn = tool.presentation?.preview;
62
+ expect(previewFn).toBeDefined();
63
+ const rawExternalDir = await fs.mkdtemp(
64
+ path.join(os.tmpdir(), "dexto-edit-outside-allowed-")
65
+ );
66
+ const externalDir = await fs.realpath(rawExternalDir);
67
+ const externalFile = path.join(externalDir, "external.txt");
68
+ try {
69
+ await fs.writeFile(externalFile, "hello world");
70
+ const toolCallId = "preview-outside-roots";
71
+ const parsedInput = tool.inputSchema.parse({
72
+ file_path: externalFile,
73
+ old_string: "world",
74
+ new_string: "universe"
75
+ });
76
+ const preview = await previewFn(
77
+ parsedInput,
78
+ createToolContext(mockLogger, { toolCallId })
79
+ );
80
+ expect(preview).toBeDefined();
81
+ expect(preview?.type).toBe("diff");
82
+ if (preview?.type === "diff") {
83
+ expect(preview.title).toBe("Update file");
84
+ expect(preview.filename).toBe(externalFile);
85
+ } else {
86
+ expect.fail("Expected diff preview");
87
+ }
88
+ } finally {
89
+ await fs.rm(externalDir, { recursive: true, force: true });
90
+ }
91
+ });
46
92
  it("should succeed when file is not modified between preview and execute", async () => {
47
- const tool = createEditFileTool({ fileSystemService });
93
+ const tool = createEditFileTool(async () => fileSystemService);
94
+ const previewFn = tool.presentation?.preview;
95
+ expect(previewFn).toBeDefined();
48
96
  const testFile = path.join(tempDir, "test.txt");
49
97
  await fs.writeFile(testFile, "hello world");
50
98
  const toolCallId = "test-call-123";
@@ -53,16 +101,25 @@ describe("edit_file tool", () => {
53
101
  old_string: "world",
54
102
  new_string: "universe"
55
103
  };
56
- const preview = await tool.generatePreview(input, { toolCallId });
104
+ const parsedInput = tool.inputSchema.parse(input);
105
+ const preview = await previewFn(
106
+ parsedInput,
107
+ createToolContext(mockLogger, { toolCallId })
108
+ );
57
109
  expect(preview).toBeDefined();
58
- const result = await tool.execute(input, { toolCallId });
110
+ const result = await tool.execute(
111
+ parsedInput,
112
+ createToolContext(mockLogger, { toolCallId })
113
+ );
59
114
  expect(result.success).toBe(true);
60
115
  expect(result.path).toBe(testFile);
61
116
  const content = await fs.readFile(testFile, "utf-8");
62
117
  expect(content).toBe("hello universe");
63
118
  });
64
119
  it("should fail when file is modified between preview and execute", async () => {
65
- const tool = createEditFileTool({ fileSystemService });
120
+ const tool = createEditFileTool(async () => fileSystemService);
121
+ const previewFn = tool.presentation?.preview;
122
+ expect(previewFn).toBeDefined();
66
123
  const testFile = path.join(tempDir, "test.txt");
67
124
  await fs.writeFile(testFile, "hello world");
68
125
  const toolCallId = "test-call-456";
@@ -71,11 +128,15 @@ describe("edit_file tool", () => {
71
128
  old_string: "world",
72
129
  new_string: "universe"
73
130
  };
74
- const preview = await tool.generatePreview(input, { toolCallId });
131
+ const parsedInput = tool.inputSchema.parse(input);
132
+ const preview = await previewFn(
133
+ parsedInput,
134
+ createToolContext(mockLogger, { toolCallId })
135
+ );
75
136
  expect(preview).toBeDefined();
76
137
  await fs.writeFile(testFile, "hello world - user added this");
77
138
  try {
78
- await tool.execute(input, { toolCallId });
139
+ await tool.execute(parsedInput, createToolContext(mockLogger, { toolCallId }));
79
140
  expect.fail("Should have thrown an error");
80
141
  } catch (error) {
81
142
  expect(error).toBeInstanceOf(DextoRuntimeError);
@@ -87,7 +148,9 @@ describe("edit_file tool", () => {
87
148
  expect(content).toBe("hello world - user added this");
88
149
  });
89
150
  it("should detect file modification with correct error code", async () => {
90
- const tool = createEditFileTool({ fileSystemService });
151
+ const tool = createEditFileTool(async () => fileSystemService);
152
+ const previewFn = tool.presentation?.preview;
153
+ expect(previewFn).toBeDefined();
91
154
  const testFile = path.join(tempDir, "test.txt");
92
155
  await fs.writeFile(testFile, "hello world");
93
156
  const toolCallId = "test-call-789";
@@ -96,10 +159,11 @@ describe("edit_file tool", () => {
96
159
  old_string: "world",
97
160
  new_string: "universe"
98
161
  };
99
- await tool.generatePreview(input, { toolCallId });
162
+ const parsedInput = tool.inputSchema.parse(input);
163
+ await previewFn(parsedInput, createToolContext(mockLogger, { toolCallId }));
100
164
  await fs.writeFile(testFile, "hello world modified");
101
165
  try {
102
- await tool.execute(input, { toolCallId });
166
+ await tool.execute(parsedInput, createToolContext(mockLogger, { toolCallId }));
103
167
  expect.fail("Should have thrown an error");
104
168
  } catch (error) {
105
169
  expect(error).toBeInstanceOf(DextoRuntimeError);
@@ -113,7 +177,9 @@ describe("edit_file tool", () => {
113
177
  }
114
178
  });
115
179
  it("should work without toolCallId (no modification check)", async () => {
116
- const tool = createEditFileTool({ fileSystemService });
180
+ const tool = createEditFileTool(async () => fileSystemService);
181
+ const previewFn = tool.presentation?.preview;
182
+ expect(previewFn).toBeDefined();
117
183
  const testFile = path.join(tempDir, "test.txt");
118
184
  await fs.writeFile(testFile, "hello world");
119
185
  const input = {
@@ -121,10 +187,11 @@ describe("edit_file tool", () => {
121
187
  old_string: "world",
122
188
  new_string: "universe"
123
189
  };
124
- await tool.generatePreview(input, {});
190
+ const parsedInput = tool.inputSchema.parse(input);
191
+ await previewFn(parsedInput, createToolContext(mockLogger));
125
192
  await fs.writeFile(testFile, "hello world changed");
126
193
  try {
127
- await tool.execute(input, {});
194
+ await tool.execute(parsedInput, createToolContext(mockLogger));
128
195
  } catch (error) {
129
196
  expect(error).toBeInstanceOf(DextoRuntimeError);
130
197
  expect(error.code).not.toBe(
@@ -133,7 +200,9 @@ describe("edit_file tool", () => {
133
200
  }
134
201
  });
135
202
  it("should clean up hash cache after successful execution", async () => {
136
- const tool = createEditFileTool({ fileSystemService });
203
+ const tool = createEditFileTool(async () => fileSystemService);
204
+ const previewFn = tool.presentation?.preview;
205
+ expect(previewFn).toBeDefined();
137
206
  const testFile = path.join(tempDir, "test.txt");
138
207
  await fs.writeFile(testFile, "hello world");
139
208
  const toolCallId = "test-call-cleanup";
@@ -142,21 +211,28 @@ describe("edit_file tool", () => {
142
211
  old_string: "world",
143
212
  new_string: "universe"
144
213
  };
145
- await tool.generatePreview(input, { toolCallId });
146
- await tool.execute(input, { toolCallId });
214
+ const parsedInput = tool.inputSchema.parse(input);
215
+ await previewFn(parsedInput, createToolContext(mockLogger, { toolCallId }));
216
+ await tool.execute(parsedInput, createToolContext(mockLogger, { toolCallId }));
147
217
  const input2 = {
148
218
  file_path: testFile,
149
219
  old_string: "universe",
150
220
  new_string: "galaxy"
151
221
  };
152
- await tool.generatePreview(input2, { toolCallId });
153
- const result = await tool.execute(input2, { toolCallId });
222
+ const parsedInput2 = tool.inputSchema.parse(input2);
223
+ await previewFn(parsedInput2, createToolContext(mockLogger, { toolCallId }));
224
+ const result = await tool.execute(
225
+ parsedInput2,
226
+ createToolContext(mockLogger, { toolCallId })
227
+ );
154
228
  expect(result.success).toBe(true);
155
229
  const content = await fs.readFile(testFile, "utf-8");
156
230
  expect(content).toBe("hello galaxy");
157
231
  });
158
232
  it("should clean up hash cache after failed execution", async () => {
159
- const tool = createEditFileTool({ fileSystemService });
233
+ const tool = createEditFileTool(async () => fileSystemService);
234
+ const previewFn = tool.presentation?.preview;
235
+ expect(previewFn).toBeDefined();
160
236
  const testFile = path.join(tempDir, "test.txt");
161
237
  await fs.writeFile(testFile, "hello world");
162
238
  const toolCallId = "test-call-fail-cleanup";
@@ -165,15 +241,19 @@ describe("edit_file tool", () => {
165
241
  old_string: "world",
166
242
  new_string: "universe"
167
243
  };
168
- await tool.generatePreview(input, { toolCallId });
244
+ const parsedInput = tool.inputSchema.parse(input);
245
+ await previewFn(parsedInput, createToolContext(mockLogger, { toolCallId }));
169
246
  await fs.writeFile(testFile, "hello world modified");
170
247
  try {
171
- await tool.execute(input, { toolCallId });
248
+ await tool.execute(parsedInput, createToolContext(mockLogger, { toolCallId }));
172
249
  } catch {
173
250
  }
174
251
  await fs.writeFile(testFile, "hello world");
175
- await tool.generatePreview(input, { toolCallId });
176
- const result = await tool.execute(input, { toolCallId });
252
+ await previewFn(parsedInput, createToolContext(mockLogger, { toolCallId }));
253
+ const result = await tool.execute(
254
+ parsedInput,
255
+ createToolContext(mockLogger, { toolCallId })
256
+ );
177
257
  expect(result.success).toBe(true);
178
258
  });
179
259
  });
@@ -34,7 +34,11 @@ var FileSystemErrorCode = /* @__PURE__ */ ((FileSystemErrorCode2) => {
34
34
  FileSystemErrorCode2["FILE_TOO_LARGE"] = "FILESYSTEM_FILE_TOO_LARGE";
35
35
  FileSystemErrorCode2["TOO_MANY_RESULTS"] = "FILESYSTEM_TOO_MANY_RESULTS";
36
36
  FileSystemErrorCode2["READ_FAILED"] = "FILESYSTEM_READ_FAILED";
37
+ FileSystemErrorCode2["LIST_FAILED"] = "FILESYSTEM_LIST_FAILED";
37
38
  FileSystemErrorCode2["WRITE_FAILED"] = "FILESYSTEM_WRITE_FAILED";
39
+ FileSystemErrorCode2["CREATE_DIR_FAILED"] = "FILESYSTEM_CREATE_DIR_FAILED";
40
+ FileSystemErrorCode2["DELETE_FAILED"] = "FILESYSTEM_DELETE_FAILED";
41
+ FileSystemErrorCode2["RENAME_FAILED"] = "FILESYSTEM_RENAME_FAILED";
38
42
  FileSystemErrorCode2["BACKUP_FAILED"] = "FILESYSTEM_BACKUP_FAILED";
39
43
  FileSystemErrorCode2["EDIT_FAILED"] = "FILESYSTEM_EDIT_FAILED";
40
44
  FileSystemErrorCode2["STRING_NOT_UNIQUE"] = "FILESYSTEM_STRING_NOT_UNIQUE";
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Standardized error codes for file system operations
5
5
  */
6
- declare enum FileSystemErrorCode {
6
+ export declare enum FileSystemErrorCode {
7
7
  FILE_NOT_FOUND = "FILESYSTEM_FILE_NOT_FOUND",
8
8
  DIRECTORY_NOT_FOUND = "FILESYSTEM_DIRECTORY_NOT_FOUND",
9
9
  PERMISSION_DENIED = "FILESYSTEM_PERMISSION_DENIED",
@@ -16,7 +16,11 @@ declare enum FileSystemErrorCode {
16
16
  FILE_TOO_LARGE = "FILESYSTEM_FILE_TOO_LARGE",
17
17
  TOO_MANY_RESULTS = "FILESYSTEM_TOO_MANY_RESULTS",
18
18
  READ_FAILED = "FILESYSTEM_READ_FAILED",
19
+ LIST_FAILED = "FILESYSTEM_LIST_FAILED",
19
20
  WRITE_FAILED = "FILESYSTEM_WRITE_FAILED",
21
+ CREATE_DIR_FAILED = "FILESYSTEM_CREATE_DIR_FAILED",
22
+ DELETE_FAILED = "FILESYSTEM_DELETE_FAILED",
23
+ RENAME_FAILED = "FILESYSTEM_RENAME_FAILED",
20
24
  BACKUP_FAILED = "FILESYSTEM_BACKUP_FAILED",
21
25
  EDIT_FAILED = "FILESYSTEM_EDIT_FAILED",
22
26
  STRING_NOT_UNIQUE = "FILESYSTEM_STRING_NOT_UNIQUE",
@@ -28,5 +32,4 @@ declare enum FileSystemErrorCode {
28
32
  INVALID_CONFIG = "FILESYSTEM_INVALID_CONFIG",
29
33
  SERVICE_NOT_INITIALIZED = "FILESYSTEM_SERVICE_NOT_INITIALIZED"
30
34
  }
31
-
32
- export { FileSystemErrorCode };
35
+ //# sourceMappingURL=error-codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,oBAAY,mBAAmB;IAE3B,cAAc,8BAA8B;IAC5C,mBAAmB,mCAAmC;IAGtD,iBAAiB,iCAAiC;IAClD,gBAAgB,gCAAgC;IAChD,YAAY,4BAA4B;IAGxC,YAAY,4BAA4B;IACxC,uBAAuB,uCAAuC;IAC9D,sBAAsB,sCAAsC;IAC5D,gBAAgB,gCAAgC;IAGhD,cAAc,8BAA8B;IAC5C,gBAAgB,gCAAgC;IAGhD,WAAW,2BAA2B;IACtC,WAAW,2BAA2B;IACtC,YAAY,4BAA4B;IACxC,iBAAiB,iCAAiC;IAClD,aAAa,6BAA6B;IAC1C,aAAa,6BAA6B;IAC1C,aAAa,6BAA6B;IAC1C,WAAW,2BAA2B;IACtC,iBAAiB,iCAAiC;IAClD,gBAAgB,gCAAgC;IAGhD,WAAW,2BAA2B;IACtC,aAAa,6BAA6B;IAC1C,eAAe,+BAA+B;IAC9C,aAAa,6BAA6B;IAG1C,cAAc,8BAA8B;IAC5C,uBAAuB,uCAAuC;CACjE"}
@@ -11,7 +11,11 @@ var FileSystemErrorCode = /* @__PURE__ */ ((FileSystemErrorCode2) => {
11
11
  FileSystemErrorCode2["FILE_TOO_LARGE"] = "FILESYSTEM_FILE_TOO_LARGE";
12
12
  FileSystemErrorCode2["TOO_MANY_RESULTS"] = "FILESYSTEM_TOO_MANY_RESULTS";
13
13
  FileSystemErrorCode2["READ_FAILED"] = "FILESYSTEM_READ_FAILED";
14
+ FileSystemErrorCode2["LIST_FAILED"] = "FILESYSTEM_LIST_FAILED";
14
15
  FileSystemErrorCode2["WRITE_FAILED"] = "FILESYSTEM_WRITE_FAILED";
16
+ FileSystemErrorCode2["CREATE_DIR_FAILED"] = "FILESYSTEM_CREATE_DIR_FAILED";
17
+ FileSystemErrorCode2["DELETE_FAILED"] = "FILESYSTEM_DELETE_FAILED";
18
+ FileSystemErrorCode2["RENAME_FAILED"] = "FILESYSTEM_RENAME_FAILED";
15
19
  FileSystemErrorCode2["BACKUP_FAILED"] = "FILESYSTEM_BACKUP_FAILED";
16
20
  FileSystemErrorCode2["EDIT_FAILED"] = "FILESYSTEM_EDIT_FAILED";
17
21
  FileSystemErrorCode2["STRING_NOT_UNIQUE"] = "FILESYSTEM_STRING_NOT_UNIQUE";
package/dist/errors.cjs CHANGED
@@ -161,6 +161,54 @@ class FileSystemError {
161
161
  { path, cause }
162
162
  );
163
163
  }
164
+ /**
165
+ * List directory operation failed
166
+ */
167
+ static listFailed(path, cause) {
168
+ return new import_core.DextoRuntimeError(
169
+ import_error_codes.FileSystemErrorCode.LIST_FAILED,
170
+ FILESYSTEM_SCOPE,
171
+ import_core.ErrorType.SYSTEM,
172
+ `Failed to list directory: ${path}. ${cause}`,
173
+ { path, cause }
174
+ );
175
+ }
176
+ /**
177
+ * Create directory operation failed
178
+ */
179
+ static createDirFailed(path, cause) {
180
+ return new import_core.DextoRuntimeError(
181
+ import_error_codes.FileSystemErrorCode.CREATE_DIR_FAILED,
182
+ FILESYSTEM_SCOPE,
183
+ import_core.ErrorType.SYSTEM,
184
+ `Failed to create directory: ${path}. ${cause}`,
185
+ { path, cause }
186
+ );
187
+ }
188
+ /**
189
+ * Delete operation failed
190
+ */
191
+ static deleteFailed(path, cause) {
192
+ return new import_core.DextoRuntimeError(
193
+ import_error_codes.FileSystemErrorCode.DELETE_FAILED,
194
+ FILESYSTEM_SCOPE,
195
+ import_core.ErrorType.SYSTEM,
196
+ `Failed to delete path: ${path}. ${cause}`,
197
+ { path, cause }
198
+ );
199
+ }
200
+ /**
201
+ * Rename operation failed
202
+ */
203
+ static renameFailed(path, cause) {
204
+ return new import_core.DextoRuntimeError(
205
+ import_error_codes.FileSystemErrorCode.RENAME_FAILED,
206
+ FILESYSTEM_SCOPE,
207
+ import_core.ErrorType.SYSTEM,
208
+ `Failed to rename path: ${path}. ${cause}`,
209
+ { path, cause }
210
+ );
211
+ }
164
212
  /**
165
213
  * Write operation failed
166
214
  */
package/dist/errors.d.ts CHANGED
@@ -1,12 +1,10 @@
1
- import { DextoRuntimeError } from '@dexto/core';
2
-
3
1
  /**
4
2
  * FileSystem Service Errors
5
3
  *
6
4
  * Error classes for file system operations
7
5
  */
8
-
9
- interface FileSystemErrorContext {
6
+ import { DextoRuntimeError } from '@dexto/core';
7
+ export interface FileSystemErrorContext {
10
8
  path?: string;
11
9
  pattern?: string;
12
10
  size?: number;
@@ -17,7 +15,7 @@ interface FileSystemErrorContext {
17
15
  /**
18
16
  * Factory class for creating FileSystem-related errors
19
17
  */
20
- declare class FileSystemError {
18
+ export declare class FileSystemError {
21
19
  private constructor();
22
20
  /**
23
21
  * File not found error
@@ -63,6 +61,22 @@ declare class FileSystemError {
63
61
  * Read operation failed
64
62
  */
65
63
  static readFailed(path: string, cause: string): DextoRuntimeError;
64
+ /**
65
+ * List directory operation failed
66
+ */
67
+ static listFailed(path: string, cause: string): DextoRuntimeError;
68
+ /**
69
+ * Create directory operation failed
70
+ */
71
+ static createDirFailed(path: string, cause: string): DextoRuntimeError;
72
+ /**
73
+ * Delete operation failed
74
+ */
75
+ static deleteFailed(path: string, cause: string): DextoRuntimeError;
76
+ /**
77
+ * Rename operation failed
78
+ */
79
+ static renameFailed(path: string, cause: string): DextoRuntimeError;
66
80
  /**
67
81
  * Write operation failed
68
82
  */
@@ -108,5 +122,4 @@ declare class FileSystemError {
108
122
  */
109
123
  static notInitialized(): DextoRuntimeError;
110
124
  }
111
-
112
- export { FileSystemError, type FileSystemErrorContext };
125
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/dist/errors.js CHANGED
@@ -138,6 +138,54 @@ class FileSystemError {
138
138
  { path, cause }
139
139
  );
140
140
  }
141
+ /**
142
+ * List directory operation failed
143
+ */
144
+ static listFailed(path, cause) {
145
+ return new DextoRuntimeError(
146
+ FileSystemErrorCode.LIST_FAILED,
147
+ FILESYSTEM_SCOPE,
148
+ ErrorType.SYSTEM,
149
+ `Failed to list directory: ${path}. ${cause}`,
150
+ { path, cause }
151
+ );
152
+ }
153
+ /**
154
+ * Create directory operation failed
155
+ */
156
+ static createDirFailed(path, cause) {
157
+ return new DextoRuntimeError(
158
+ FileSystemErrorCode.CREATE_DIR_FAILED,
159
+ FILESYSTEM_SCOPE,
160
+ ErrorType.SYSTEM,
161
+ `Failed to create directory: ${path}. ${cause}`,
162
+ { path, cause }
163
+ );
164
+ }
165
+ /**
166
+ * Delete operation failed
167
+ */
168
+ static deleteFailed(path, cause) {
169
+ return new DextoRuntimeError(
170
+ FileSystemErrorCode.DELETE_FAILED,
171
+ FILESYSTEM_SCOPE,
172
+ ErrorType.SYSTEM,
173
+ `Failed to delete path: ${path}. ${cause}`,
174
+ { path, cause }
175
+ );
176
+ }
177
+ /**
178
+ * Rename operation failed
179
+ */
180
+ static renameFailed(path, cause) {
181
+ return new DextoRuntimeError(
182
+ FileSystemErrorCode.RENAME_FAILED,
183
+ FILESYSTEM_SCOPE,
184
+ ErrorType.SYSTEM,
185
+ `Failed to rename path: ${path}. ${cause}`,
186
+ { path, cause }
187
+ );
188
+ }
141
189
  /**
142
190
  * Write operation failed
143
191
  */
@@ -1,46 +1,14 @@
1
- import { FileSystemService } from './filesystem-service.js';
2
- import '@dexto/core';
3
- import './types.js';
4
-
5
1
  /**
6
2
  * File Tool Types
7
3
  *
8
- * Types shared between file tools for directory approval support.
4
+ * Types shared between file tools and factories.
9
5
  */
10
-
6
+ import type { ToolExecutionContext } from '@dexto/core';
7
+ import type { FileSystemService } from './filesystem-service.js';
11
8
  /**
12
- * Callbacks for directory access approval.
13
- * Allows file tools to check and request approval for accessing paths
14
- * outside the configured working directory.
9
+ * Getter for a lazily-initialized {@link FileSystemService}.
10
+ * Tool factories construct tools before runtime services are available, so tools
11
+ * resolve the service on-demand using {@link ToolExecutionContext}.
15
12
  */
16
- interface DirectoryApprovalCallbacks {
17
- /**
18
- * Check if a path is within any session-approved directory.
19
- * Used to determine if directory approval prompt is needed.
20
- * @param filePath The file path to check (absolute or relative)
21
- * @returns true if path is in a session-approved directory
22
- */
23
- isSessionApproved: (filePath: string) => boolean;
24
- /**
25
- * Add a directory to the approved list for this session.
26
- * Called after user approves directory access.
27
- * @param directory Absolute path to the directory to approve
28
- * @param type 'session' (remembered) or 'once' (single use)
29
- */
30
- addApproved: (directory: string, type: 'session' | 'once') => void;
31
- }
32
- /**
33
- * Options for creating file tools with directory approval support
34
- */
35
- interface FileToolOptions {
36
- /** FileSystemService instance for file operations */
37
- fileSystemService: FileSystemService;
38
- /**
39
- * Optional callbacks for directory approval.
40
- * If provided, file tools can request approval for accessing paths
41
- * outside the configured working directory.
42
- */
43
- directoryApproval?: DirectoryApprovalCallbacks | undefined;
44
- }
45
-
46
- export type { DirectoryApprovalCallbacks, FileToolOptions };
13
+ export type FileSystemServiceGetter = (context: ToolExecutionContext) => Promise<FileSystemService>;
14
+ //# sourceMappingURL=file-tool-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-tool-types.d.ts","sourceRoot":"","sources":["../src/file-tool-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC"}