@dexto/core 1.5.4 → 1.5.6

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 (102) hide show
  1. package/dist/agent/DextoAgent.cjs +61 -155
  2. package/dist/agent/DextoAgent.d.ts +11 -54
  3. package/dist/agent/DextoAgent.d.ts.map +1 -1
  4. package/dist/agent/DextoAgent.js +61 -155
  5. package/dist/context/compaction/strategies/reactive-overflow.cjs +5 -3
  6. package/dist/context/compaction/strategies/reactive-overflow.d.ts +1 -0
  7. package/dist/context/compaction/strategies/reactive-overflow.d.ts.map +1 -1
  8. package/dist/context/compaction/strategies/reactive-overflow.js +5 -3
  9. package/dist/context/compaction/types.d.ts +13 -1
  10. package/dist/context/compaction/types.d.ts.map +1 -1
  11. package/dist/errors/types.cjs +0 -2
  12. package/dist/errors/types.d.ts +1 -5
  13. package/dist/errors/types.d.ts.map +1 -1
  14. package/dist/errors/types.js +0 -2
  15. package/dist/events/index.cjs +0 -2
  16. package/dist/events/index.d.ts +6 -25
  17. package/dist/events/index.d.ts.map +1 -1
  18. package/dist/events/index.js +0 -2
  19. package/dist/llm/executor/stream-processor.cjs +85 -27
  20. package/dist/llm/executor/stream-processor.d.ts +4 -0
  21. package/dist/llm/executor/stream-processor.d.ts.map +1 -1
  22. package/dist/llm/executor/stream-processor.js +85 -27
  23. package/dist/llm/executor/turn-executor.cjs +58 -130
  24. package/dist/llm/executor/turn-executor.d.ts +9 -43
  25. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  26. package/dist/llm/executor/turn-executor.js +58 -130
  27. package/dist/llm/executor/types.d.ts +0 -28
  28. package/dist/llm/executor/types.d.ts.map +1 -1
  29. package/dist/llm/services/vercel.cjs +2 -5
  30. package/dist/llm/services/vercel.d.ts +1 -6
  31. package/dist/llm/services/vercel.d.ts.map +1 -1
  32. package/dist/llm/services/vercel.js +2 -5
  33. package/dist/logger/logger.cjs +6 -7
  34. package/dist/logger/logger.d.ts +1 -0
  35. package/dist/logger/logger.d.ts.map +1 -1
  36. package/dist/logger/logger.js +6 -7
  37. package/dist/session/chat-session.cjs +19 -12
  38. package/dist/session/chat-session.d.ts +3 -6
  39. package/dist/session/chat-session.d.ts.map +1 -1
  40. package/dist/session/chat-session.js +19 -12
  41. package/dist/session/session-manager.cjs +0 -135
  42. package/dist/session/session-manager.d.ts +0 -43
  43. package/dist/session/session-manager.d.ts.map +1 -1
  44. package/dist/session/session-manager.js +0 -135
  45. package/dist/telemetry/telemetry.cjs +12 -5
  46. package/dist/telemetry/telemetry.d.ts.map +1 -1
  47. package/dist/telemetry/telemetry.js +12 -5
  48. package/dist/tools/schemas.cjs +2 -2
  49. package/dist/tools/schemas.js +2 -2
  50. package/package.json +15 -5
  51. package/dist/filesystem/error-codes.cjs +0 -53
  52. package/dist/filesystem/error-codes.d.ts +0 -31
  53. package/dist/filesystem/error-codes.d.ts.map +0 -1
  54. package/dist/filesystem/error-codes.js +0 -30
  55. package/dist/filesystem/errors.cjs +0 -303
  56. package/dist/filesystem/errors.d.ts +0 -109
  57. package/dist/filesystem/errors.d.ts.map +0 -1
  58. package/dist/filesystem/errors.js +0 -280
  59. package/dist/filesystem/filesystem-service.cjs +0 -534
  60. package/dist/filesystem/filesystem-service.d.ts +0 -97
  61. package/dist/filesystem/filesystem-service.d.ts.map +0 -1
  62. package/dist/filesystem/filesystem-service.js +0 -501
  63. package/dist/filesystem/index.cjs +0 -37
  64. package/dist/filesystem/index.d.ts +0 -11
  65. package/dist/filesystem/index.d.ts.map +0 -1
  66. package/dist/filesystem/index.js +0 -11
  67. package/dist/filesystem/path-validator.cjs +0 -250
  68. package/dist/filesystem/path-validator.d.ts +0 -103
  69. package/dist/filesystem/path-validator.d.ts.map +0 -1
  70. package/dist/filesystem/path-validator.js +0 -217
  71. package/dist/filesystem/types.cjs +0 -16
  72. package/dist/filesystem/types.d.ts +0 -175
  73. package/dist/filesystem/types.d.ts.map +0 -1
  74. package/dist/filesystem/types.js +0 -0
  75. package/dist/process/command-validator.cjs +0 -554
  76. package/dist/process/command-validator.d.ts +0 -49
  77. package/dist/process/command-validator.d.ts.map +0 -1
  78. package/dist/process/command-validator.js +0 -531
  79. package/dist/process/error-codes.cjs +0 -47
  80. package/dist/process/error-codes.d.ts +0 -25
  81. package/dist/process/error-codes.d.ts.map +0 -1
  82. package/dist/process/error-codes.js +0 -24
  83. package/dist/process/errors.cjs +0 -244
  84. package/dist/process/errors.d.ts +0 -87
  85. package/dist/process/errors.d.ts.map +0 -1
  86. package/dist/process/errors.js +0 -221
  87. package/dist/process/index.cjs +0 -37
  88. package/dist/process/index.d.ts +0 -11
  89. package/dist/process/index.d.ts.map +0 -1
  90. package/dist/process/index.js +0 -11
  91. package/dist/process/process-service.cjs +0 -497
  92. package/dist/process/process-service.d.ts +0 -69
  93. package/dist/process/process-service.d.ts.map +0 -1
  94. package/dist/process/process-service.js +0 -464
  95. package/dist/process/types.cjs +0 -16
  96. package/dist/process/types.d.ts +0 -107
  97. package/dist/process/types.d.ts.map +0 -1
  98. package/dist/process/types.js +0 -0
  99. package/dist/session/compaction-service.cjs +0 -139
  100. package/dist/session/compaction-service.d.ts +0 -81
  101. package/dist/session/compaction-service.d.ts.map +0 -1
  102. package/dist/session/compaction-service.js +0 -106
@@ -1,534 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
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
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var filesystem_service_exports = {};
30
- __export(filesystem_service_exports, {
31
- FileSystemService: () => FileSystemService
32
- });
33
- module.exports = __toCommonJS(filesystem_service_exports);
34
- var fs = __toESM(require("node:fs/promises"), 1);
35
- var path = __toESM(require("node:path"), 1);
36
- var import_glob = require("glob");
37
- var import_path = require("../utils/path.js");
38
- var import_path_validator = require("./path-validator.js");
39
- var import_errors = require("./errors.js");
40
- var import_types2 = require("../logger/v2/types.js");
41
- const DEFAULT_ENCODING = "utf-8";
42
- const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
43
- const DEFAULT_MAX_RESULTS = 1e3;
44
- const DEFAULT_MAX_SEARCH_RESULTS = 100;
45
- class FileSystemService {
46
- config;
47
- pathValidator;
48
- initialized = false;
49
- logger;
50
- constructor(config = {}, logger) {
51
- this.config = {
52
- allowedPaths: config.allowedPaths || ["."],
53
- blockedPaths: config.blockedPaths || [".git", "node_modules/.bin", ".env"],
54
- blockedExtensions: config.blockedExtensions || [".exe", ".dll", ".so"],
55
- maxFileSize: config.maxFileSize || DEFAULT_MAX_FILE_SIZE,
56
- enableBackups: config.enableBackups ?? false,
57
- backupPath: config.backupPath,
58
- // Optional absolute override, defaults handled by getBackupDir()
59
- backupRetentionDays: config.backupRetentionDays || 7,
60
- workingDirectory: config.workingDirectory
61
- };
62
- this.logger = logger.createChild(import_types2.DextoLogComponent.FILESYSTEM);
63
- this.pathValidator = new import_path_validator.PathValidator(this.config, this.logger);
64
- }
65
- /**
66
- * Get backup directory path (context-aware with optional override)
67
- * TODO: Migrate to explicit configuration via CLI enrichment layer (per-agent paths)
68
- */
69
- getBackupDir() {
70
- return this.config.backupPath || (0, import_path.getDextoPath)("backups");
71
- }
72
- /**
73
- * Initialize the service
74
- */
75
- async initialize() {
76
- if (this.initialized) {
77
- this.logger.debug("FileSystemService already initialized");
78
- return;
79
- }
80
- if (this.config.enableBackups) {
81
- try {
82
- const backupDir = this.getBackupDir();
83
- await fs.mkdir(backupDir, { recursive: true });
84
- this.logger.debug(`Backup directory created/verified: ${backupDir}`);
85
- } catch (error) {
86
- this.logger.warn(
87
- `Failed to create backup directory: ${error instanceof Error ? error.message : String(error)}`
88
- );
89
- }
90
- }
91
- this.initialized = true;
92
- this.logger.info("FileSystemService initialized successfully");
93
- }
94
- /**
95
- * Check if a file path is within the configured allowed paths.
96
- * This is a public method for external consumers (like ToolManager) to check
97
- * if a path requires directory approval before file operations.
98
- *
99
- * @param filePath The file path to check (can be relative or absolute)
100
- * @returns true if the path is within allowed paths, false otherwise
101
- */
102
- async isPathWithinAllowed(filePath) {
103
- return this.pathValidator.isPathWithinAllowed(filePath);
104
- }
105
- /**
106
- * Get the list of configured allowed paths.
107
- * Useful for displaying to users when directory approval is needed.
108
- *
109
- * @returns Array of allowed path strings
110
- */
111
- getAllowedPaths() {
112
- return this.pathValidator.getAllowedPaths();
113
- }
114
- /**
115
- * Get the parent directory of a file path (resolved to absolute).
116
- * Useful for directory approval requests.
117
- *
118
- * @param filePath The file path
119
- * @returns The absolute parent directory path
120
- */
121
- getParentDirectory(filePath) {
122
- return path.dirname(path.resolve(filePath));
123
- }
124
- /**
125
- * Set a callback to check if a path is in an approved directory.
126
- * This allows PathValidator to consult ApprovalManager without a direct dependency.
127
- *
128
- * @param checker Function that returns true if path is in an approved directory
129
- */
130
- setDirectoryApprovalChecker(checker) {
131
- this.pathValidator.setDirectoryApprovalChecker(checker);
132
- }
133
- /**
134
- * Read a file with validation and size limits
135
- */
136
- async readFile(filePath, options = {}) {
137
- if (!this.initialized) {
138
- throw import_errors.FileSystemError.notInitialized();
139
- }
140
- const validation = await this.pathValidator.validatePath(filePath);
141
- if (!validation.isValid || !validation.normalizedPath) {
142
- throw import_errors.FileSystemError.invalidPath(filePath, validation.error || "Unknown error");
143
- }
144
- const normalizedPath = validation.normalizedPath;
145
- try {
146
- const stats = await fs.stat(normalizedPath);
147
- if (!stats.isFile()) {
148
- throw import_errors.FileSystemError.invalidPath(normalizedPath, "Path is not a file");
149
- }
150
- if (stats.size > this.config.maxFileSize) {
151
- throw import_errors.FileSystemError.fileTooLarge(
152
- normalizedPath,
153
- stats.size,
154
- this.config.maxFileSize
155
- );
156
- }
157
- } catch (error) {
158
- if (error.code === "ENOENT") {
159
- throw import_errors.FileSystemError.fileNotFound(normalizedPath);
160
- }
161
- if (error.code === "EACCES") {
162
- throw import_errors.FileSystemError.permissionDenied(normalizedPath, "read");
163
- }
164
- throw import_errors.FileSystemError.readFailed(
165
- normalizedPath,
166
- error instanceof Error ? error.message : String(error)
167
- );
168
- }
169
- try {
170
- const encoding = options.encoding || DEFAULT_ENCODING;
171
- const content = await fs.readFile(normalizedPath, encoding);
172
- const lines = content.split("\n");
173
- const limit = options.limit;
174
- const offset1 = options.offset;
175
- let selectedLines;
176
- let truncated = false;
177
- if (offset1 && offset1 > 0 || limit !== void 0) {
178
- const start = offset1 && offset1 > 0 ? Math.max(0, offset1 - 1) : 0;
179
- const end = limit !== void 0 ? start + limit : lines.length;
180
- selectedLines = lines.slice(start, end);
181
- truncated = end < lines.length;
182
- } else {
183
- selectedLines = lines;
184
- }
185
- return {
186
- content: selectedLines.join("\n"),
187
- lines: selectedLines.length,
188
- encoding,
189
- truncated,
190
- size: Buffer.byteLength(content, encoding)
191
- };
192
- } catch (error) {
193
- throw import_errors.FileSystemError.readFailed(
194
- normalizedPath,
195
- error instanceof Error ? error.message : String(error)
196
- );
197
- }
198
- }
199
- /**
200
- * Find files matching a glob pattern
201
- */
202
- async globFiles(pattern, options = {}) {
203
- if (!this.initialized) {
204
- throw import_errors.FileSystemError.notInitialized();
205
- }
206
- const cwd = options.cwd || this.config.workingDirectory || process.cwd();
207
- const maxResults = options.maxResults || DEFAULT_MAX_RESULTS;
208
- try {
209
- const files = await (0, import_glob.glob)(pattern, {
210
- cwd,
211
- absolute: true,
212
- nodir: true,
213
- // Only files
214
- follow: false
215
- // Don't follow symlinks
216
- });
217
- const validFiles = [];
218
- for (const file of files) {
219
- const validation = await this.pathValidator.validatePath(file);
220
- if (!validation.isValid || !validation.normalizedPath) {
221
- this.logger.debug(`Skipping invalid path: ${file}`);
222
- continue;
223
- }
224
- if (options.includeMetadata !== false) {
225
- try {
226
- const stats = await fs.stat(validation.normalizedPath);
227
- validFiles.push({
228
- path: validation.normalizedPath,
229
- size: stats.size,
230
- modified: stats.mtime,
231
- isDirectory: stats.isDirectory()
232
- });
233
- } catch (error) {
234
- this.logger.debug(
235
- `Failed to stat file ${file}: ${error instanceof Error ? error.message : String(error)}`
236
- );
237
- }
238
- } else {
239
- validFiles.push({
240
- path: validation.normalizedPath,
241
- size: 0,
242
- modified: /* @__PURE__ */ new Date(),
243
- isDirectory: false
244
- });
245
- }
246
- if (validFiles.length >= maxResults) {
247
- break;
248
- }
249
- }
250
- const limited = validFiles.length >= maxResults;
251
- return {
252
- files: validFiles,
253
- truncated: limited,
254
- totalFound: validFiles.length
255
- };
256
- } catch (error) {
257
- throw import_errors.FileSystemError.globFailed(
258
- pattern,
259
- error instanceof Error ? error.message : String(error)
260
- );
261
- }
262
- }
263
- /**
264
- * Search for content in files (grep-like functionality)
265
- */
266
- async searchContent(pattern, options = {}) {
267
- if (!this.initialized) {
268
- throw import_errors.FileSystemError.notInitialized();
269
- }
270
- const searchPath = options.path || this.config.workingDirectory || process.cwd();
271
- const globPattern = options.glob || "**/*";
272
- const maxResults = options.maxResults || DEFAULT_MAX_SEARCH_RESULTS;
273
- const contextLines = options.contextLines || 0;
274
- try {
275
- const flags = options.caseInsensitive ? "i" : "";
276
- const regex = new RegExp(pattern, flags);
277
- const globResult = await this.globFiles(globPattern, {
278
- cwd: searchPath,
279
- maxResults: 1e4
280
- // Search more files, but limit results
281
- });
282
- const matches = [];
283
- let filesSearched = 0;
284
- for (const fileInfo of globResult.files) {
285
- try {
286
- const fileContent = await this.readFile(fileInfo.path);
287
- const lines = fileContent.content.split("\n");
288
- filesSearched++;
289
- for (let i = 0; i < lines.length; i++) {
290
- const line = lines[i];
291
- if (regex.test(line)) {
292
- let context;
293
- if (contextLines > 0) {
294
- const before = [];
295
- const after = [];
296
- for (let j = Math.max(0, i - contextLines); j < i; j++) {
297
- before.push(lines[j]);
298
- }
299
- for (let j = i + 1; j < Math.min(lines.length, i + contextLines + 1); j++) {
300
- after.push(lines[j]);
301
- }
302
- context = { before, after };
303
- }
304
- matches.push({
305
- file: fileInfo.path,
306
- lineNumber: i + 1,
307
- // 1-based line numbers
308
- line,
309
- ...context !== void 0 && { context }
310
- });
311
- if (matches.length >= maxResults) {
312
- return {
313
- matches,
314
- totalMatches: matches.length,
315
- truncated: true,
316
- filesSearched
317
- };
318
- }
319
- }
320
- }
321
- } catch (error) {
322
- this.logger.debug(
323
- `Skipping file ${fileInfo.path}: ${error instanceof Error ? error.message : String(error)}`
324
- );
325
- }
326
- }
327
- return {
328
- matches,
329
- totalMatches: matches.length,
330
- truncated: false,
331
- filesSearched
332
- };
333
- } catch (error) {
334
- if (error instanceof Error && error.message.includes("Invalid regular expression")) {
335
- throw import_errors.FileSystemError.invalidPattern(pattern, "Invalid regular expression syntax");
336
- }
337
- throw import_errors.FileSystemError.searchFailed(
338
- pattern,
339
- error instanceof Error ? error.message : String(error)
340
- );
341
- }
342
- }
343
- /**
344
- * Write content to a file
345
- */
346
- async writeFile(filePath, content, options = {}) {
347
- if (!this.initialized) {
348
- throw import_errors.FileSystemError.notInitialized();
349
- }
350
- const validation = await this.pathValidator.validatePath(filePath);
351
- if (!validation.isValid || !validation.normalizedPath) {
352
- throw import_errors.FileSystemError.invalidPath(filePath, validation.error || "Unknown error");
353
- }
354
- const normalizedPath = validation.normalizedPath;
355
- const encoding = options.encoding || DEFAULT_ENCODING;
356
- let backupPath;
357
- let fileExists = false;
358
- try {
359
- await fs.access(normalizedPath);
360
- fileExists = true;
361
- } catch {
362
- }
363
- if (fileExists && (options.backup ?? this.config.enableBackups)) {
364
- backupPath = await this.createBackup(normalizedPath);
365
- }
366
- try {
367
- if (options.createDirs) {
368
- const dir = path.dirname(normalizedPath);
369
- await fs.mkdir(dir, { recursive: true });
370
- }
371
- await fs.writeFile(normalizedPath, content, encoding);
372
- const bytesWritten = Buffer.byteLength(content, encoding);
373
- this.logger.debug(`File written: ${normalizedPath} (${bytesWritten} bytes)`);
374
- return {
375
- success: true,
376
- path: normalizedPath,
377
- bytesWritten,
378
- backupPath
379
- };
380
- } catch (error) {
381
- throw import_errors.FileSystemError.writeFailed(
382
- normalizedPath,
383
- error instanceof Error ? error.message : String(error)
384
- );
385
- }
386
- }
387
- /**
388
- * Edit a file by replacing text
389
- */
390
- async editFile(filePath, operation, options = {}) {
391
- if (!this.initialized) {
392
- throw import_errors.FileSystemError.notInitialized();
393
- }
394
- const validation = await this.pathValidator.validatePath(filePath);
395
- if (!validation.isValid || !validation.normalizedPath) {
396
- throw import_errors.FileSystemError.invalidPath(filePath, validation.error || "Unknown error");
397
- }
398
- const normalizedPath = validation.normalizedPath;
399
- const fileContent = await this.readFile(normalizedPath);
400
- const originalContent = fileContent.content;
401
- const occurrences = (originalContent.match(
402
- new RegExp(operation.oldString.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g")
403
- ) || []).length;
404
- if (occurrences === 0) {
405
- throw import_errors.FileSystemError.stringNotFound(normalizedPath, operation.oldString);
406
- }
407
- if (!operation.replaceAll && occurrences > 1) {
408
- throw import_errors.FileSystemError.stringNotUnique(normalizedPath, operation.oldString, occurrences);
409
- }
410
- let backupPath;
411
- if (options.backup ?? this.config.enableBackups) {
412
- backupPath = await this.createBackup(normalizedPath);
413
- }
414
- try {
415
- let newContent;
416
- if (operation.replaceAll) {
417
- newContent = originalContent.replace(
418
- new RegExp(operation.oldString.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
419
- operation.newString
420
- );
421
- } else {
422
- newContent = originalContent.replace(operation.oldString, operation.newString);
423
- }
424
- await fs.writeFile(normalizedPath, newContent, options.encoding || DEFAULT_ENCODING);
425
- this.logger.debug(`File edited: ${normalizedPath} (${occurrences} replacements)`);
426
- return {
427
- success: true,
428
- path: normalizedPath,
429
- changesCount: occurrences,
430
- backupPath,
431
- originalContent,
432
- newContent
433
- };
434
- } catch (error) {
435
- throw import_errors.FileSystemError.editFailed(
436
- normalizedPath,
437
- error instanceof Error ? error.message : String(error)
438
- );
439
- }
440
- }
441
- /**
442
- * Create a backup of a file
443
- */
444
- async createBackup(filePath) {
445
- const backupDir = this.getBackupDir();
446
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
447
- const basename = path.basename(filePath);
448
- const backupFilename = `${basename}.${timestamp}.backup`;
449
- const backupPath = path.join(backupDir, backupFilename);
450
- try {
451
- await fs.mkdir(backupDir, { recursive: true });
452
- await fs.copyFile(filePath, backupPath);
453
- this.logger.debug(`Backup created: ${backupPath}`);
454
- await this.cleanupOldBackups();
455
- return backupPath;
456
- } catch (error) {
457
- throw import_errors.FileSystemError.backupFailed(
458
- filePath,
459
- error instanceof Error ? error.message : String(error)
460
- );
461
- }
462
- }
463
- /**
464
- * Clean up old backup files based on retention policy
465
- */
466
- async cleanupOldBackups() {
467
- if (!this.config.enableBackups) {
468
- return 0;
469
- }
470
- let backupDir;
471
- try {
472
- backupDir = this.getBackupDir();
473
- } catch (error) {
474
- this.logger.warn(
475
- `Failed to resolve backup directory: ${error instanceof Error ? error.message : String(error)}`
476
- );
477
- return 0;
478
- }
479
- try {
480
- await fs.access(backupDir);
481
- } catch {
482
- return 0;
483
- }
484
- const cutoffDate = new Date(
485
- Date.now() - this.config.backupRetentionDays * 24 * 60 * 60 * 1e3
486
- );
487
- let deletedCount = 0;
488
- try {
489
- const files = await fs.readdir(backupDir);
490
- const backupFiles = files.filter((file) => file.endsWith(".backup"));
491
- for (const file of backupFiles) {
492
- const filePath = path.join(backupDir, file);
493
- try {
494
- const stats = await fs.stat(filePath);
495
- if (stats.mtime < cutoffDate) {
496
- await fs.unlink(filePath);
497
- deletedCount++;
498
- this.logger.debug(`Cleaned up old backup: ${file}`);
499
- }
500
- } catch (error) {
501
- this.logger.warn(
502
- `Failed to process backup file ${file}: ${error instanceof Error ? error.message : String(error)}`
503
- );
504
- }
505
- }
506
- if (deletedCount > 0) {
507
- this.logger.info(`Backup cleanup: removed ${deletedCount} old backup files`);
508
- }
509
- return deletedCount;
510
- } catch (error) {
511
- this.logger.warn(
512
- `Failed to cleanup backup directory: ${error instanceof Error ? error.message : String(error)}`
513
- );
514
- return 0;
515
- }
516
- }
517
- /**
518
- * Get service configuration
519
- */
520
- getConfig() {
521
- return { ...this.config };
522
- }
523
- /**
524
- * Check if a path is allowed (async for non-blocking symlink resolution)
525
- */
526
- async isPathAllowed(filePath) {
527
- const validation = await this.pathValidator.validatePath(filePath);
528
- return validation.isValid;
529
- }
530
- }
531
- // Annotate the CommonJS export names for ESM import in node:
532
- 0 && (module.exports = {
533
- FileSystemService
534
- });
@@ -1,97 +0,0 @@
1
- /**
2
- * FileSystem Service
3
- *
4
- * Secure file system operations for Dexto internal tools
5
- */
6
- import { FileSystemConfig, FileContent, ReadFileOptions, GlobOptions, GlobResult, GrepOptions, SearchResult, WriteFileOptions, WriteResult, EditFileOptions, EditResult, EditOperation } from './types.js';
7
- import { type DirectoryApprovalChecker } from './path-validator.js';
8
- import type { IDextoLogger } from '../logger/v2/types.js';
9
- /**
10
- * FileSystemService - Handles all file system operations with security checks
11
- * TODO: Add tests for this class
12
- * TODO: instantiate only when internal file tools are enabled to avoid file dependencies which won't work in serverless
13
- */
14
- export declare class FileSystemService {
15
- private config;
16
- private pathValidator;
17
- private initialized;
18
- private logger;
19
- constructor(config: Partial<FileSystemConfig> | undefined, logger: IDextoLogger);
20
- /**
21
- * Get backup directory path (context-aware with optional override)
22
- * TODO: Migrate to explicit configuration via CLI enrichment layer (per-agent paths)
23
- */
24
- private getBackupDir;
25
- /**
26
- * Initialize the service
27
- */
28
- initialize(): Promise<void>;
29
- /**
30
- * Check if a file path is within the configured allowed paths.
31
- * This is a public method for external consumers (like ToolManager) to check
32
- * if a path requires directory approval before file operations.
33
- *
34
- * @param filePath The file path to check (can be relative or absolute)
35
- * @returns true if the path is within allowed paths, false otherwise
36
- */
37
- isPathWithinAllowed(filePath: string): Promise<boolean>;
38
- /**
39
- * Get the list of configured allowed paths.
40
- * Useful for displaying to users when directory approval is needed.
41
- *
42
- * @returns Array of allowed path strings
43
- */
44
- getAllowedPaths(): string[];
45
- /**
46
- * Get the parent directory of a file path (resolved to absolute).
47
- * Useful for directory approval requests.
48
- *
49
- * @param filePath The file path
50
- * @returns The absolute parent directory path
51
- */
52
- getParentDirectory(filePath: string): string;
53
- /**
54
- * Set a callback to check if a path is in an approved directory.
55
- * This allows PathValidator to consult ApprovalManager without a direct dependency.
56
- *
57
- * @param checker Function that returns true if path is in an approved directory
58
- */
59
- setDirectoryApprovalChecker(checker: DirectoryApprovalChecker): void;
60
- /**
61
- * Read a file with validation and size limits
62
- */
63
- readFile(filePath: string, options?: ReadFileOptions): Promise<FileContent>;
64
- /**
65
- * Find files matching a glob pattern
66
- */
67
- globFiles(pattern: string, options?: GlobOptions): Promise<GlobResult>;
68
- /**
69
- * Search for content in files (grep-like functionality)
70
- */
71
- searchContent(pattern: string, options?: GrepOptions): Promise<SearchResult>;
72
- /**
73
- * Write content to a file
74
- */
75
- writeFile(filePath: string, content: string, options?: WriteFileOptions): Promise<WriteResult>;
76
- /**
77
- * Edit a file by replacing text
78
- */
79
- editFile(filePath: string, operation: EditOperation, options?: EditFileOptions): Promise<EditResult>;
80
- /**
81
- * Create a backup of a file
82
- */
83
- private createBackup;
84
- /**
85
- * Clean up old backup files based on retention policy
86
- */
87
- cleanupOldBackups(): Promise<number>;
88
- /**
89
- * Get service configuration
90
- */
91
- getConfig(): Readonly<FileSystemConfig>;
92
- /**
93
- * Check if a path is allowed (async for non-blocking symlink resolution)
94
- */
95
- isPathAllowed(filePath: string): Promise<boolean>;
96
- }
97
- //# sourceMappingURL=filesystem-service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filesystem-service.d.ts","sourceRoot":"","sources":["../../src/filesystem/filesystem-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EACH,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,WAAW,EACX,UAAU,EACV,WAAW,EACX,YAAY,EAEZ,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,UAAU,EACV,aAAa,EAGhB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAiB,KAAK,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAEnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAQ1D;;;;GAIG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,YAAK,EAAE,MAAM,EAAE,YAAY;IAiBxE;;;OAGG;IACH,OAAO,CAAC,YAAY;IAKpB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBjC;;;;;;;OAOG;IACG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;;;;OAKG;IACH,eAAe,IAAI,MAAM,EAAE;IAI3B;;;;;;OAMG;IACH,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAI5C;;;;;OAKG;IACH,2BAA2B,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI;IAIpE;;OAEG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,WAAW,CAAC;IA+ErF;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC;IAwEhF;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IAqGtF;;OAEG;IACG,SAAS,CACX,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAqB,GAC/B,OAAO,CAAC,WAAW,CAAC;IA0DvB;;OAEG;IACG,QAAQ,CACV,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,aAAa,EACxB,OAAO,GAAE,eAAoB,GAC9B,OAAO,CAAC,UAAU,CAAC;IAuEtB;;OAEG;YACW,YAAY;IA0B1B;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IA6D1C;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,gBAAgB,CAAC;IAIvC;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAI1D"}