@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.3
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/README.md +44 -54
- package/bin/cli.js +1 -115
- package/bin/loxia-terminal-v2.js +3 -0
- package/bin/loxia-terminal.js +3 -0
- package/bin/start-with-terminal.js +3 -0
- package/package.json +14 -15
- package/scripts/install-scanners.js +1 -235
- package/src/analyzers/CSSAnalyzer.js +1 -297
- package/src/analyzers/ConfigValidator.js +1 -690
- package/src/analyzers/ESLintAnalyzer.js +1 -320
- package/src/analyzers/JavaScriptAnalyzer.js +1 -261
- package/src/analyzers/PrettierFormatter.js +1 -247
- package/src/analyzers/PythonAnalyzer.js +1 -266
- package/src/analyzers/SecurityAnalyzer.js +1 -729
- package/src/analyzers/TypeScriptAnalyzer.js +1 -247
- package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
- package/src/analyzers/codeCloneDetector/detector.js +1 -203
- package/src/analyzers/codeCloneDetector/index.js +1 -160
- package/src/analyzers/codeCloneDetector/parser.js +1 -199
- package/src/analyzers/codeCloneDetector/reporter.js +1 -148
- package/src/analyzers/codeCloneDetector/scanner.js +1 -59
- package/src/core/agentPool.js +1 -1474
- package/src/core/agentScheduler.js +1 -2147
- package/src/core/contextManager.js +1 -709
- package/src/core/messageProcessor.js +1 -732
- package/src/core/orchestrator.js +1 -548
- package/src/core/stateManager.js +1 -877
- package/src/index.js +1 -631
- package/src/interfaces/cli.js +1 -549
- package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
- package/src/interfaces/terminal/api/apiClient.js +1 -0
- package/src/interfaces/terminal/api/messageRouter.js +1 -0
- package/src/interfaces/terminal/api/session.js +1 -0
- package/src/interfaces/terminal/api/websocket.js +1 -0
- package/src/interfaces/terminal/components/AgentCreator.js +1 -0
- package/src/interfaces/terminal/components/AgentEditor.js +1 -0
- package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
- package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
- package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
- package/src/interfaces/terminal/components/Header.js +1 -0
- package/src/interfaces/terminal/components/HelpPanel.js +1 -0
- package/src/interfaces/terminal/components/InputBox.js +1 -0
- package/src/interfaces/terminal/components/Layout.js +1 -0
- package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
- package/src/interfaces/terminal/components/MessageList.js +1 -0
- package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
- package/src/interfaces/terminal/components/SearchPanel.js +1 -0
- package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
- package/src/interfaces/terminal/components/StatusBar.js +1 -0
- package/src/interfaces/terminal/components/TextInput.js +1 -0
- package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
- package/src/interfaces/terminal/config/constants.js +1 -0
- package/src/interfaces/terminal/index.js +1 -0
- package/src/interfaces/terminal/state/useAgentControl.js +1 -0
- package/src/interfaces/terminal/state/useAgents.js +1 -0
- package/src/interfaces/terminal/state/useConnection.js +1 -0
- package/src/interfaces/terminal/state/useMessages.js +1 -0
- package/src/interfaces/terminal/state/useTools.js +1 -0
- package/src/interfaces/terminal/utils/debugLogger.js +1 -0
- package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
- package/src/interfaces/terminal/utils/theme.js +1 -0
- package/src/interfaces/webServer.js +1 -2162
- package/src/modules/fileExplorer/controller.js +1 -280
- package/src/modules/fileExplorer/index.js +1 -37
- package/src/modules/fileExplorer/middleware.js +1 -92
- package/src/modules/fileExplorer/routes.js +1 -125
- package/src/modules/fileExplorer/types.js +1 -44
- package/src/services/aiService.js +1 -1232
- package/src/services/apiKeyManager.js +1 -164
- package/src/services/benchmarkService.js +1 -366
- package/src/services/budgetService.js +1 -539
- package/src/services/contextInjectionService.js +1 -247
- package/src/services/conversationCompactionService.js +1 -637
- package/src/services/errorHandler.js +1 -810
- package/src/services/fileAttachmentService.js +1 -544
- package/src/services/modelRouterService.js +1 -366
- package/src/services/modelsService.js +1 -322
- package/src/services/qualityInspector.js +1 -796
- package/src/services/tokenCountingService.js +1 -536
- package/src/tools/agentCommunicationTool.js +1 -1344
- package/src/tools/agentDelayTool.js +1 -485
- package/src/tools/asyncToolManager.js +1 -604
- package/src/tools/baseTool.js +1 -800
- package/src/tools/browserTool.js +1 -920
- package/src/tools/cloneDetectionTool.js +1 -621
- package/src/tools/dependencyResolverTool.js +1 -1215
- package/src/tools/fileContentReplaceTool.js +1 -875
- package/src/tools/fileSystemTool.js +1 -1107
- package/src/tools/fileTreeTool.js +1 -853
- package/src/tools/imageTool.js +1 -901
- package/src/tools/importAnalyzerTool.js +1 -1060
- package/src/tools/jobDoneTool.js +1 -248
- package/src/tools/seekTool.js +1 -956
- package/src/tools/staticAnalysisTool.js +1 -1778
- package/src/tools/taskManagerTool.js +1 -2873
- package/src/tools/terminalTool.js +1 -2304
- package/src/tools/webTool.js +1 -1430
- package/src/types/agent.js +1 -519
- package/src/types/contextReference.js +1 -972
- package/src/types/conversation.js +1 -730
- package/src/types/toolCommand.js +1 -747
- package/src/utilities/attachmentValidator.js +1 -292
- package/src/utilities/configManager.js +1 -582
- package/src/utilities/constants.js +1 -722
- package/src/utilities/directoryAccessManager.js +1 -535
- package/src/utilities/fileProcessor.js +1 -307
- package/src/utilities/logger.js +1 -436
- package/src/utilities/tagParser.js +1 -1246
- package/src/utilities/toolConstants.js +1 -317
- package/web-ui/build/index.html +2 -2
- package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
- package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
|
@@ -1,1107 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FileSystemTool - Handle file system operations safely
|
|
3
|
-
*
|
|
4
|
-
* Purpose:
|
|
5
|
-
* - Read, write, and manipulate files
|
|
6
|
-
* - Directory operations
|
|
7
|
-
* - File metadata and permissions
|
|
8
|
-
* - Safe file operations with validation
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { BaseTool } from './baseTool.js';
|
|
12
|
-
import TagParser from '../utilities/tagParser.js';
|
|
13
|
-
import DirectoryAccessManager from '../utilities/directoryAccessManager.js';
|
|
14
|
-
import fs from 'fs/promises';
|
|
15
|
-
import path from 'path';
|
|
16
|
-
import crypto from 'crypto';
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
TOOL_STATUS,
|
|
20
|
-
FILE_EXTENSIONS,
|
|
21
|
-
SYSTEM_DEFAULTS
|
|
22
|
-
} from '../utilities/constants.js';
|
|
23
|
-
|
|
24
|
-
class FileSystemTool extends BaseTool {
|
|
25
|
-
constructor(config = {}, logger = null) {
|
|
26
|
-
super(config, logger);
|
|
27
|
-
|
|
28
|
-
// Tool metadata
|
|
29
|
-
this.requiresProject = true;
|
|
30
|
-
this.isAsync = false; // Most file operations are quick
|
|
31
|
-
this.timeout = config.timeout || 30000; // 30 seconds
|
|
32
|
-
this.maxConcurrentOperations = config.maxConcurrentOperations || 5;
|
|
33
|
-
|
|
34
|
-
// Security settings
|
|
35
|
-
this.maxFileSize = config.maxFileSize || SYSTEM_DEFAULTS.MAX_FILE_SIZE;
|
|
36
|
-
this.allowedExtensions = config.allowedExtensions || null; // null = all allowed
|
|
37
|
-
this.blockedExtensions = config.blockedExtensions || ['.exe', '.bat', '.cmd', '.scr', '.com'];
|
|
38
|
-
this.allowedDirectories = config.allowedDirectories || null; // null = project dir only
|
|
39
|
-
|
|
40
|
-
// File operation history
|
|
41
|
-
this.operationHistory = [];
|
|
42
|
-
|
|
43
|
-
// Directory access manager
|
|
44
|
-
this.directoryAccessManager = new DirectoryAccessManager(config, logger);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Get tool description for LLM consumption
|
|
49
|
-
* @returns {string} Tool description
|
|
50
|
-
*/
|
|
51
|
-
getDescription() {
|
|
52
|
-
return `
|
|
53
|
-
File System Tool: Perform file and directory operations safely within the project scope.
|
|
54
|
-
|
|
55
|
-
CRITICAL: Both XML and JSON formats are fully supported. When using XML format, commands are automatically converted to the appropriate structure internally - you don't need to manually wrap them in an actions array.
|
|
56
|
-
|
|
57
|
-
USAGE - TWO FORMATS SUPPORTED:
|
|
58
|
-
|
|
59
|
-
FORMAT 1 - XML STYLE (Recommended):
|
|
60
|
-
[tool id="filesystem"]
|
|
61
|
-
<read file-path="src/index.js" />
|
|
62
|
-
<write output-path="src/components/Button.js">
|
|
63
|
-
const Button = () => {
|
|
64
|
-
return <button>Click me</button>;
|
|
65
|
-
};
|
|
66
|
-
export default Button;
|
|
67
|
-
</write>
|
|
68
|
-
[/tool]
|
|
69
|
-
|
|
70
|
-
FORMAT 2 - JSON STYLE:
|
|
71
|
-
\`\`\`json
|
|
72
|
-
{
|
|
73
|
-
"toolId": "filesystem",
|
|
74
|
-
"actions": [
|
|
75
|
-
{
|
|
76
|
-
"type": "read",
|
|
77
|
-
"filePath": "src/index.js"
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
"type": "write",
|
|
81
|
-
"outputPath": "src/components/Button.js",
|
|
82
|
-
"content": "const Button = () => { return <button>Click me</button>; };"
|
|
83
|
-
}
|
|
84
|
-
]
|
|
85
|
-
}
|
|
86
|
-
\`\`\`
|
|
87
|
-
|
|
88
|
-
IMPORTANT:
|
|
89
|
-
- Use either format consistently. Do NOT mix formats in a single command.
|
|
90
|
-
- XML format is recommended for single operations and better readability
|
|
91
|
-
- JSON format is recommended for complex multi-action operations
|
|
92
|
-
- Both formats work equally well and produce the same results
|
|
93
|
-
|
|
94
|
-
SUPPORTED ACTIONS:
|
|
95
|
-
- read: Read file contents
|
|
96
|
-
- write: Write content to file
|
|
97
|
-
- append: Append content to existing file
|
|
98
|
-
- delete: Delete a file
|
|
99
|
-
- copy: Copy file from source to destination
|
|
100
|
-
- move: Move/rename file
|
|
101
|
-
- create-dir: Create directory
|
|
102
|
-
- list: List directory contents
|
|
103
|
-
- exists: Check if file/directory exists
|
|
104
|
-
- stats: Get file/directory metadata
|
|
105
|
-
|
|
106
|
-
PARAMETERS:
|
|
107
|
-
- file-path: Path to file to read
|
|
108
|
-
- output-path: Path where to write/create file
|
|
109
|
-
- source-path: Source path for copy/move operations
|
|
110
|
-
- dest-path: Destination path for copy/move operations
|
|
111
|
-
- directory: Directory path for directory operations
|
|
112
|
-
- content: Content to write/append
|
|
113
|
-
- encoding: File encoding (default: utf8)
|
|
114
|
-
- create-dirs: Create parent directories if they don't exist (true/false)
|
|
115
|
-
|
|
116
|
-
EXAMPLES:
|
|
117
|
-
|
|
118
|
-
SIMPLE FILE CREATION (XML format - recommended):
|
|
119
|
-
[tool id="filesystem"]
|
|
120
|
-
<write output-path="hello.c">
|
|
121
|
-
#include <stdio.h>
|
|
122
|
-
|
|
123
|
-
int main() {
|
|
124
|
-
printf("Hello, World!\\n");
|
|
125
|
-
return 0;
|
|
126
|
-
}
|
|
127
|
-
</write>
|
|
128
|
-
[/tool]
|
|
129
|
-
|
|
130
|
-
READING FILES (XML format):
|
|
131
|
-
[tool id="filesystem"]
|
|
132
|
-
<read file-path="package.json" />
|
|
133
|
-
[/tool]
|
|
134
|
-
|
|
135
|
-
MULTIPLE OPERATIONS (JSON format recommended):
|
|
136
|
-
\`\`\`json
|
|
137
|
-
{
|
|
138
|
-
"toolId": "filesystem",
|
|
139
|
-
"actions": [
|
|
140
|
-
{
|
|
141
|
-
"type": "read",
|
|
142
|
-
"filePath": "src/index.js"
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
"type": "write",
|
|
146
|
-
"outputPath": "src/backup.js",
|
|
147
|
-
"content": "// Backup file\\nconsole.log('backup');"
|
|
148
|
-
}
|
|
149
|
-
]
|
|
150
|
-
}
|
|
151
|
-
\`\`\`
|
|
152
|
-
|
|
153
|
-
OTHER XML EXAMPLES:
|
|
154
|
-
[tool id="filesystem"]
|
|
155
|
-
<copy source-path="template.js" dest-path="src/component.js" />
|
|
156
|
-
<create-dir directory="src/components/ui" />
|
|
157
|
-
<list directory="src" />
|
|
158
|
-
[/tool]
|
|
159
|
-
|
|
160
|
-
SECURITY:
|
|
161
|
-
- Operations restricted to project directory
|
|
162
|
-
- File size limits enforced (max ${Math.round(this.maxFileSize / 1024 / 1024)}MB)
|
|
163
|
-
- Dangerous file types blocked
|
|
164
|
-
- Path traversal protection
|
|
165
|
-
- Backup created for destructive operations
|
|
166
|
-
|
|
167
|
-
ENCODING SUPPORT:
|
|
168
|
-
- utf8 (default)
|
|
169
|
-
- ascii
|
|
170
|
-
- base64
|
|
171
|
-
- binary
|
|
172
|
-
- hex
|
|
173
|
-
`;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Parse parameters from tool command content
|
|
178
|
-
* @param {string} content - Raw tool command content
|
|
179
|
-
* @returns {Object} Parsed parameters
|
|
180
|
-
*/
|
|
181
|
-
parseParameters(content) {
|
|
182
|
-
try {
|
|
183
|
-
const params = {};
|
|
184
|
-
const actions = [];
|
|
185
|
-
|
|
186
|
-
this.logger?.debug('FileSystem tool parsing parameters', {
|
|
187
|
-
contentLength: content.length,
|
|
188
|
-
contentPreview: content.substring(0, 200)
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// Extract self-closing tags (read, delete, copy, etc.)
|
|
192
|
-
const selfClosingTags = [
|
|
193
|
-
'read', 'delete', 'copy', 'move', 'create-dir',
|
|
194
|
-
'list', 'exists', 'stats', 'append'
|
|
195
|
-
];
|
|
196
|
-
|
|
197
|
-
for (const tagName of selfClosingTags) {
|
|
198
|
-
const tags = TagParser.extractTagsWithAttributes(content, tagName);
|
|
199
|
-
for (const tag of tags) {
|
|
200
|
-
const action = {
|
|
201
|
-
type: tagName,
|
|
202
|
-
...tag.attributes
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
// Normalize common attribute names
|
|
206
|
-
if (action['file-path']) {
|
|
207
|
-
action.filePath = action['file-path'];
|
|
208
|
-
delete action['file-path'];
|
|
209
|
-
}
|
|
210
|
-
if (action['output-path']) {
|
|
211
|
-
action.outputPath = action['output-path'];
|
|
212
|
-
delete action['output-path'];
|
|
213
|
-
}
|
|
214
|
-
if (action['source-path']) {
|
|
215
|
-
action.sourcePath = action['source-path'];
|
|
216
|
-
delete action['source-path'];
|
|
217
|
-
}
|
|
218
|
-
if (action['dest-path']) {
|
|
219
|
-
action.destPath = action['dest-path'];
|
|
220
|
-
delete action['dest-path'];
|
|
221
|
-
}
|
|
222
|
-
if (action['create-dirs']) {
|
|
223
|
-
action.createDirs = action['create-dirs'] === 'true';
|
|
224
|
-
delete action['create-dirs'];
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
actions.push(action);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Extract write and append tags with content
|
|
232
|
-
const writeMatches = content.matchAll(/<write\s+([^>]*)>(.*?)<\/write>/gs);
|
|
233
|
-
for (const match of writeMatches) {
|
|
234
|
-
const parser = new TagParser();
|
|
235
|
-
const attributes = parser.parseAttributes(match[1]);
|
|
236
|
-
const writeContent = match[2].trim();
|
|
237
|
-
|
|
238
|
-
const action = {
|
|
239
|
-
type: 'write',
|
|
240
|
-
content: writeContent,
|
|
241
|
-
...attributes
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
// Normalize attribute names
|
|
245
|
-
if (action['output-path']) {
|
|
246
|
-
action.outputPath = action['output-path'];
|
|
247
|
-
delete action['output-path'];
|
|
248
|
-
}
|
|
249
|
-
if (action['create-dirs']) {
|
|
250
|
-
action.createDirs = action['create-dirs'] === 'true';
|
|
251
|
-
delete action['create-dirs'];
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
actions.push(action);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const appendMatches = content.matchAll(/<append\s+([^>]*)>(.*?)<\/append>/gs);
|
|
258
|
-
for (const match of appendMatches) {
|
|
259
|
-
const parser = new TagParser();
|
|
260
|
-
const attributes = parser.parseAttributes(match[1]);
|
|
261
|
-
const appendContent = match[2].trim();
|
|
262
|
-
|
|
263
|
-
const action = {
|
|
264
|
-
type: 'append',
|
|
265
|
-
content: appendContent,
|
|
266
|
-
...attributes
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
// Normalize attribute names
|
|
270
|
-
if (action['file-path']) {
|
|
271
|
-
action.filePath = action['file-path'];
|
|
272
|
-
delete action['file-path'];
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
actions.push(action);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
params.actions = actions;
|
|
279
|
-
params.rawContent = content.trim();
|
|
280
|
-
|
|
281
|
-
this.logger?.debug('Parsed FileSystem tool parameters', {
|
|
282
|
-
totalActions: actions.length,
|
|
283
|
-
actionTypes: actions.map(a => a.type),
|
|
284
|
-
actions: actions.map(a => ({
|
|
285
|
-
type: a.type,
|
|
286
|
-
filePath: a.filePath,
|
|
287
|
-
outputPath: a.outputPath,
|
|
288
|
-
hasContent: !!a.content
|
|
289
|
-
}))
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
return params;
|
|
293
|
-
|
|
294
|
-
} catch (error) {
|
|
295
|
-
throw new Error(`Failed to parse filesystem parameters: ${error.message}`);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Get required parameters
|
|
301
|
-
* @returns {Array<string>} Array of required parameter names
|
|
302
|
-
*/
|
|
303
|
-
getRequiredParameters() {
|
|
304
|
-
return ['actions'];
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Custom parameter validation
|
|
309
|
-
* @param {Object} params - Parameters to validate
|
|
310
|
-
* @returns {Object} Validation result
|
|
311
|
-
*/
|
|
312
|
-
customValidateParameters(params) {
|
|
313
|
-
const errors = [];
|
|
314
|
-
|
|
315
|
-
if (!params.actions || !Array.isArray(params.actions) || params.actions.length === 0) {
|
|
316
|
-
errors.push('At least one action is required');
|
|
317
|
-
} else {
|
|
318
|
-
// Validate each action
|
|
319
|
-
for (const [index, action] of params.actions.entries()) {
|
|
320
|
-
if (!action.type) {
|
|
321
|
-
errors.push(`Action ${index + 1}: type is required`);
|
|
322
|
-
continue;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
switch (action.type) {
|
|
326
|
-
case 'read':
|
|
327
|
-
case 'delete':
|
|
328
|
-
case 'exists':
|
|
329
|
-
case 'stats':
|
|
330
|
-
if (!action.filePath) {
|
|
331
|
-
errors.push(`Action ${index + 1}: file-path is required for ${action.type}`);
|
|
332
|
-
}
|
|
333
|
-
break;
|
|
334
|
-
|
|
335
|
-
case 'write':
|
|
336
|
-
if (!action.outputPath) {
|
|
337
|
-
errors.push(`Action ${index + 1}: output-path is required for write`);
|
|
338
|
-
}
|
|
339
|
-
if (!action.content && action.content !== '') {
|
|
340
|
-
errors.push(`Action ${index + 1}: content is required for write`);
|
|
341
|
-
}
|
|
342
|
-
break;
|
|
343
|
-
|
|
344
|
-
case 'append':
|
|
345
|
-
if (!action.filePath) {
|
|
346
|
-
errors.push(`Action ${index + 1}: file-path is required for append`);
|
|
347
|
-
}
|
|
348
|
-
if (!action.content && action.content !== '') {
|
|
349
|
-
errors.push(`Action ${index + 1}: content is required for append`);
|
|
350
|
-
}
|
|
351
|
-
break;
|
|
352
|
-
|
|
353
|
-
case 'copy':
|
|
354
|
-
case 'move':
|
|
355
|
-
if (!action.sourcePath) {
|
|
356
|
-
errors.push(`Action ${index + 1}: source-path is required for ${action.type}`);
|
|
357
|
-
}
|
|
358
|
-
if (!action.destPath) {
|
|
359
|
-
errors.push(`Action ${index + 1}: dest-path is required for ${action.type}`);
|
|
360
|
-
}
|
|
361
|
-
break;
|
|
362
|
-
|
|
363
|
-
case 'create-dir':
|
|
364
|
-
case 'list':
|
|
365
|
-
if (!action.directory) {
|
|
366
|
-
errors.push(`Action ${index + 1}: directory is required for ${action.type}`);
|
|
367
|
-
}
|
|
368
|
-
break;
|
|
369
|
-
|
|
370
|
-
default:
|
|
371
|
-
errors.push(`Action ${index + 1}: unknown action type: ${action.type}`);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// Validate file extensions if specified
|
|
375
|
-
if (action.filePath && !this.isAllowedFileExtension(action.filePath)) {
|
|
376
|
-
errors.push(`Action ${index + 1}: file type not allowed: ${path.extname(action.filePath)}`);
|
|
377
|
-
}
|
|
378
|
-
if (action.outputPath && !this.isAllowedFileExtension(action.outputPath)) {
|
|
379
|
-
errors.push(`Action ${index + 1}: file type not allowed: ${path.extname(action.outputPath)}`);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
return {
|
|
385
|
-
valid: errors.length === 0,
|
|
386
|
-
errors
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Execute tool with parsed parameters
|
|
392
|
-
* @param {Object} params - Parsed parameters
|
|
393
|
-
* @param {Object} context - Execution context
|
|
394
|
-
* @returns {Promise<Object>} Execution result
|
|
395
|
-
*/
|
|
396
|
-
async execute(params, context) {
|
|
397
|
-
// Validate params structure
|
|
398
|
-
if (!params || typeof params !== 'object') {
|
|
399
|
-
throw new Error('Invalid parameters: params must be an object');
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
const { actions } = params;
|
|
403
|
-
|
|
404
|
-
// Validate actions array
|
|
405
|
-
if (!actions) {
|
|
406
|
-
throw new Error('Invalid parameters: actions is required. Received params: ' + JSON.stringify(Object.keys(params)));
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
if (!Array.isArray(actions)) {
|
|
410
|
-
throw new Error('Invalid parameters: actions must be an array. Received type: ' + typeof actions);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
if (actions.length === 0) {
|
|
414
|
-
throw new Error('Invalid parameters: actions array is empty');
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
const { projectDir, agentId, directoryAccess } = context;
|
|
418
|
-
|
|
419
|
-
// Get directory access configuration from agent or create default
|
|
420
|
-
const accessConfig = directoryAccess ||
|
|
421
|
-
this.directoryAccessManager.createDirectoryAccess({
|
|
422
|
-
workingDirectory: projectDir || process.cwd(),
|
|
423
|
-
writeEnabledDirectories: [projectDir || process.cwd()],
|
|
424
|
-
restrictToProject: true
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
// IMPORTANT: If the agent has directoryAccess configured, use its workingDirectory
|
|
428
|
-
// This ensures UI-configured project directories are respected
|
|
429
|
-
if (directoryAccess && directoryAccess.workingDirectory) {
|
|
430
|
-
// Agent has explicitly configured working directory from UI - use it
|
|
431
|
-
console.log('FileSystem DEBUG: Using agent configured working directory:', directoryAccess.workingDirectory);
|
|
432
|
-
console.log('FileSystem DEBUG: Full directoryAccess object:', JSON.stringify(directoryAccess, null, 2));
|
|
433
|
-
} else {
|
|
434
|
-
// Using fallback to projectDir or process.cwd()
|
|
435
|
-
console.log('FileSystem DEBUG: Using fallback working directory:', projectDir || process.cwd());
|
|
436
|
-
console.log('FileSystem DEBUG: directoryAccess is:', directoryAccess);
|
|
437
|
-
console.log('FileSystem DEBUG: projectDir is:', projectDir);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
const results = [];
|
|
441
|
-
|
|
442
|
-
for (const action of actions) {
|
|
443
|
-
try {
|
|
444
|
-
let result;
|
|
445
|
-
|
|
446
|
-
switch (action.type) {
|
|
447
|
-
case 'read':
|
|
448
|
-
result = await this.readFile(action.filePath, accessConfig, action.encoding);
|
|
449
|
-
break;
|
|
450
|
-
|
|
451
|
-
case 'write':
|
|
452
|
-
result = await this.writeFile(action.outputPath, action.content, accessConfig, {
|
|
453
|
-
encoding: action.encoding,
|
|
454
|
-
createDirs: action.createDirs
|
|
455
|
-
});
|
|
456
|
-
break;
|
|
457
|
-
|
|
458
|
-
case 'append':
|
|
459
|
-
result = await this.appendToFile(action.filePath, action.content, accessConfig, action.encoding);
|
|
460
|
-
break;
|
|
461
|
-
|
|
462
|
-
case 'delete':
|
|
463
|
-
result = await this.deleteFile(action.filePath, accessConfig);
|
|
464
|
-
break;
|
|
465
|
-
|
|
466
|
-
case 'copy':
|
|
467
|
-
result = await this.copyFile(action.sourcePath, action.destPath, accessConfig);
|
|
468
|
-
break;
|
|
469
|
-
|
|
470
|
-
case 'move':
|
|
471
|
-
result = await this.moveFile(action.sourcePath, action.destPath, accessConfig);
|
|
472
|
-
break;
|
|
473
|
-
|
|
474
|
-
case 'create-dir':
|
|
475
|
-
result = await this.createDirectory(action.directory, accessConfig);
|
|
476
|
-
break;
|
|
477
|
-
|
|
478
|
-
case 'list':
|
|
479
|
-
result = await this.listDirectory(action.directory, accessConfig);
|
|
480
|
-
break;
|
|
481
|
-
|
|
482
|
-
case 'exists':
|
|
483
|
-
result = await this.checkExists(action.filePath, accessConfig);
|
|
484
|
-
break;
|
|
485
|
-
|
|
486
|
-
case 'stats':
|
|
487
|
-
result = await this.getFileStats(action.filePath, accessConfig);
|
|
488
|
-
break;
|
|
489
|
-
|
|
490
|
-
default:
|
|
491
|
-
throw new Error(`Unknown action type: ${action.type}`);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
results.push(result);
|
|
495
|
-
this.addToHistory(action, result, context.agentId);
|
|
496
|
-
|
|
497
|
-
} catch (error) {
|
|
498
|
-
const errorResult = {
|
|
499
|
-
success: false,
|
|
500
|
-
action: action.type,
|
|
501
|
-
error: error.message,
|
|
502
|
-
filePath: action.filePath || action.outputPath || action.directory
|
|
503
|
-
};
|
|
504
|
-
|
|
505
|
-
results.push(errorResult);
|
|
506
|
-
this.addToHistory(action, errorResult, context.agentId);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
return {
|
|
511
|
-
success: true,
|
|
512
|
-
actions: results,
|
|
513
|
-
executedActions: actions.length,
|
|
514
|
-
toolUsed: 'filesys'
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/**
|
|
519
|
-
* Read file contents
|
|
520
|
-
* @private
|
|
521
|
-
*/
|
|
522
|
-
async readFile(filePath, accessConfig, encoding = 'utf8') {
|
|
523
|
-
const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
|
|
524
|
-
const fullPath = this.resolvePath(filePath, workingDir);
|
|
525
|
-
|
|
526
|
-
// Validate read access using DirectoryAccessManager
|
|
527
|
-
const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
|
|
528
|
-
if (!accessResult.allowed) {
|
|
529
|
-
throw new Error(`Read access denied: ${accessResult.reason} (${accessResult.path})`);
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
try {
|
|
533
|
-
const stats = await fs.stat(fullPath);
|
|
534
|
-
|
|
535
|
-
if (stats.size > this.maxFileSize) {
|
|
536
|
-
throw new Error(`File too large: ${stats.size} bytes (max ${this.maxFileSize})`);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
const content = await fs.readFile(fullPath, encoding);
|
|
540
|
-
|
|
541
|
-
return {
|
|
542
|
-
success: true,
|
|
543
|
-
action: 'read',
|
|
544
|
-
filePath: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
|
|
545
|
-
content,
|
|
546
|
-
size: stats.size,
|
|
547
|
-
encoding,
|
|
548
|
-
lastModified: stats.mtime.toISOString(),
|
|
549
|
-
message: `Read ${stats.size} bytes from ${filePath}`
|
|
550
|
-
};
|
|
551
|
-
|
|
552
|
-
} catch (error) {
|
|
553
|
-
throw new Error(`Failed to read file ${filePath}: ${error.message}`);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* Write content to file
|
|
559
|
-
* @private
|
|
560
|
-
*/
|
|
561
|
-
async writeFile(outputPath, content, accessConfig, options = {}) {
|
|
562
|
-
const { encoding = 'utf8', createDirs = true } = options;
|
|
563
|
-
const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
|
|
564
|
-
const fullPath = this.resolvePath(outputPath, workingDir);
|
|
565
|
-
|
|
566
|
-
// Validate write access using DirectoryAccessManager
|
|
567
|
-
const accessResult = this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig);
|
|
568
|
-
if (!accessResult.allowed) {
|
|
569
|
-
throw new Error(`Write access denied: ${accessResult.reason} (${accessResult.path})`);
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
try {
|
|
573
|
-
// Check content size
|
|
574
|
-
const contentSize = Buffer.byteLength(content, encoding);
|
|
575
|
-
if (contentSize > this.maxFileSize) {
|
|
576
|
-
throw new Error(`Content too large: ${contentSize} bytes (max ${this.maxFileSize})`);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
// Create parent directories if requested
|
|
580
|
-
if (createDirs) {
|
|
581
|
-
const dirPath = path.dirname(fullPath);
|
|
582
|
-
await fs.mkdir(dirPath, { recursive: true });
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
// Create backup if file exists
|
|
586
|
-
let backupPath = null;
|
|
587
|
-
try {
|
|
588
|
-
await fs.access(fullPath);
|
|
589
|
-
backupPath = `${fullPath}.backup-${Date.now()}`;
|
|
590
|
-
await fs.copyFile(fullPath, backupPath);
|
|
591
|
-
} catch {
|
|
592
|
-
// File doesn't exist, no backup needed
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
await fs.writeFile(fullPath, content, encoding);
|
|
596
|
-
|
|
597
|
-
const stats = await fs.stat(fullPath);
|
|
598
|
-
|
|
599
|
-
const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
|
|
600
|
-
|
|
601
|
-
return {
|
|
602
|
-
success: true,
|
|
603
|
-
action: 'write',
|
|
604
|
-
outputPath: relativePath,
|
|
605
|
-
fullPath: fullPath,
|
|
606
|
-
size: stats.size,
|
|
607
|
-
encoding,
|
|
608
|
-
backupPath: backupPath ? this.directoryAccessManager.createRelativePath(backupPath, accessConfig) : null,
|
|
609
|
-
backupFullPath: backupPath || null,
|
|
610
|
-
message: `Wrote ${stats.size} bytes to ${fullPath}`
|
|
611
|
-
};
|
|
612
|
-
|
|
613
|
-
} catch (error) {
|
|
614
|
-
throw new Error(`Failed to write file ${fullPath}: ${error.message}`);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
/**
|
|
619
|
-
* Append content to file
|
|
620
|
-
* @private
|
|
621
|
-
*/
|
|
622
|
-
async appendToFile(filePath, content, accessConfig, encoding = 'utf8') {
|
|
623
|
-
const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
|
|
624
|
-
const fullPath = this.resolvePath(filePath, workingDir);
|
|
625
|
-
|
|
626
|
-
// Validate write access using DirectoryAccessManager
|
|
627
|
-
const accessResult = this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig);
|
|
628
|
-
if (!accessResult.allowed) {
|
|
629
|
-
throw new Error(`Write access denied: ${accessResult.reason} (${accessResult.path})`);
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
try {
|
|
633
|
-
// Check if file exists and get current size
|
|
634
|
-
let currentSize = 0;
|
|
635
|
-
try {
|
|
636
|
-
const stats = await fs.stat(fullPath);
|
|
637
|
-
currentSize = stats.size;
|
|
638
|
-
} catch {
|
|
639
|
-
// File doesn't exist, will be created
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
const contentSize = Buffer.byteLength(content, encoding);
|
|
643
|
-
if (currentSize + contentSize > this.maxFileSize) {
|
|
644
|
-
throw new Error(`File would become too large: ${currentSize + contentSize} bytes (max ${this.maxFileSize})`);
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
await fs.appendFile(fullPath, content, encoding);
|
|
648
|
-
|
|
649
|
-
const stats = await fs.stat(fullPath);
|
|
650
|
-
const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
|
|
651
|
-
|
|
652
|
-
return {
|
|
653
|
-
success: true,
|
|
654
|
-
action: 'append',
|
|
655
|
-
filePath: relativePath,
|
|
656
|
-
fullPath: fullPath,
|
|
657
|
-
appendedBytes: contentSize,
|
|
658
|
-
totalSize: stats.size,
|
|
659
|
-
encoding,
|
|
660
|
-
message: `Appended ${contentSize} bytes to ${fullPath}`
|
|
661
|
-
};
|
|
662
|
-
|
|
663
|
-
} catch (error) {
|
|
664
|
-
throw new Error(`Failed to append to file ${fullPath}: ${error.message}`);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
/**
|
|
669
|
-
* Delete file
|
|
670
|
-
* @private
|
|
671
|
-
*/
|
|
672
|
-
async deleteFile(filePath, accessConfig) {
|
|
673
|
-
const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
|
|
674
|
-
const fullPath = this.resolvePath(filePath, workingDir);
|
|
675
|
-
|
|
676
|
-
// Validate write access for deletion
|
|
677
|
-
const accessResult = this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig);
|
|
678
|
-
if (!accessResult.allowed) {
|
|
679
|
-
throw new Error(`Delete access denied: ${accessResult.reason} (${accessResult.path})`);
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
try {
|
|
683
|
-
const stats = await fs.stat(fullPath);
|
|
684
|
-
|
|
685
|
-
// Create backup before deletion
|
|
686
|
-
const backupPath = `${fullPath}.deleted-backup-${Date.now()}`;
|
|
687
|
-
await fs.copyFile(fullPath, backupPath);
|
|
688
|
-
|
|
689
|
-
await fs.unlink(fullPath);
|
|
690
|
-
|
|
691
|
-
const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
|
|
692
|
-
const backupRelativePath = this.directoryAccessManager.createRelativePath(backupPath, accessConfig);
|
|
693
|
-
|
|
694
|
-
return {
|
|
695
|
-
success: true,
|
|
696
|
-
action: 'delete',
|
|
697
|
-
filePath: relativePath,
|
|
698
|
-
fullPath: fullPath,
|
|
699
|
-
size: stats.size,
|
|
700
|
-
backupPath: backupRelativePath,
|
|
701
|
-
backupFullPath: backupPath,
|
|
702
|
-
message: `Deleted ${fullPath} (backup created)`
|
|
703
|
-
};
|
|
704
|
-
|
|
705
|
-
} catch (error) {
|
|
706
|
-
throw new Error(`Failed to delete file ${fullPath}: ${error.message}`);
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
/**
|
|
711
|
-
* Copy file
|
|
712
|
-
* @private
|
|
713
|
-
*/
|
|
714
|
-
async copyFile(sourcePath, destPath, accessConfig) {
|
|
715
|
-
const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
|
|
716
|
-
const fullSourcePath = this.resolvePath(sourcePath, workingDir);
|
|
717
|
-
const fullDestPath = this.resolvePath(destPath, workingDir);
|
|
718
|
-
|
|
719
|
-
// Validate read access for source
|
|
720
|
-
const sourceAccessResult = this.directoryAccessManager.validateReadAccess(fullSourcePath, accessConfig);
|
|
721
|
-
if (!sourceAccessResult.allowed) {
|
|
722
|
-
throw new Error(`Source read access denied: ${sourceAccessResult.reason} (${sourceAccessResult.path})`);
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
// Validate write access for destination
|
|
726
|
-
const destAccessResult = this.directoryAccessManager.validateWriteAccess(fullDestPath, accessConfig);
|
|
727
|
-
if (!destAccessResult.allowed) {
|
|
728
|
-
throw new Error(`Destination write access denied: ${destAccessResult.reason} (${destAccessResult.path})`);
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
try {
|
|
732
|
-
const sourceStats = await fs.stat(fullSourcePath);
|
|
733
|
-
|
|
734
|
-
if (sourceStats.size > this.maxFileSize) {
|
|
735
|
-
throw new Error(`Source file too large: ${sourceStats.size} bytes`);
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
// Create destination directory if needed
|
|
739
|
-
const destDir = path.dirname(fullDestPath);
|
|
740
|
-
await fs.mkdir(destDir, { recursive: true });
|
|
741
|
-
|
|
742
|
-
await fs.copyFile(fullSourcePath, fullDestPath);
|
|
743
|
-
|
|
744
|
-
const sourceRelativePath = this.directoryAccessManager.createRelativePath(fullSourcePath, accessConfig);
|
|
745
|
-
const destRelativePath = this.directoryAccessManager.createRelativePath(fullDestPath, accessConfig);
|
|
746
|
-
|
|
747
|
-
return {
|
|
748
|
-
success: true,
|
|
749
|
-
action: 'copy',
|
|
750
|
-
sourcePath: sourceRelativePath,
|
|
751
|
-
destPath: destRelativePath,
|
|
752
|
-
sourceFullPath: fullSourcePath,
|
|
753
|
-
destFullPath: fullDestPath,
|
|
754
|
-
size: sourceStats.size,
|
|
755
|
-
message: `Copied ${fullSourcePath} to ${fullDestPath}`
|
|
756
|
-
};
|
|
757
|
-
|
|
758
|
-
} catch (error) {
|
|
759
|
-
throw new Error(`Failed to copy ${fullSourcePath} to ${fullDestPath}: ${error.message}`);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
/**
|
|
764
|
-
* Move/rename file
|
|
765
|
-
* @private
|
|
766
|
-
*/
|
|
767
|
-
async moveFile(sourcePath, destPath, accessConfig) {
|
|
768
|
-
const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
|
|
769
|
-
const fullSourcePath = this.resolvePath(sourcePath, workingDir);
|
|
770
|
-
const fullDestPath = this.resolvePath(destPath, workingDir);
|
|
771
|
-
|
|
772
|
-
// Validate read access for source
|
|
773
|
-
const readResult = this.directoryAccessManager.validateReadAccess(fullSourcePath, accessConfig);
|
|
774
|
-
if (!readResult.allowed) {
|
|
775
|
-
throw new Error(`Read access denied for source: ${readResult.reason} (${readResult.path})`);
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
// Validate write access for destination
|
|
779
|
-
const writeResult = this.directoryAccessManager.validateWriteAccess(fullDestPath, accessConfig);
|
|
780
|
-
if (!writeResult.allowed) {
|
|
781
|
-
throw new Error(`Write access denied for destination: ${writeResult.reason} (${writeResult.path})`);
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
try {
|
|
785
|
-
const sourceStats = await fs.stat(fullSourcePath);
|
|
786
|
-
|
|
787
|
-
// Create destination directory if needed
|
|
788
|
-
const destDir = path.dirname(fullDestPath);
|
|
789
|
-
await fs.mkdir(destDir, { recursive: true });
|
|
790
|
-
|
|
791
|
-
await fs.rename(fullSourcePath, fullDestPath);
|
|
792
|
-
|
|
793
|
-
const relativeSource = this.directoryAccessManager.createRelativePath(fullSourcePath, accessConfig);
|
|
794
|
-
const relativeDest = this.directoryAccessManager.createRelativePath(fullDestPath, accessConfig);
|
|
795
|
-
|
|
796
|
-
return {
|
|
797
|
-
success: true,
|
|
798
|
-
action: 'move',
|
|
799
|
-
sourcePath: relativeSource,
|
|
800
|
-
destPath: relativeDest,
|
|
801
|
-
fullSourcePath: fullSourcePath,
|
|
802
|
-
fullDestPath: fullDestPath,
|
|
803
|
-
size: sourceStats.size,
|
|
804
|
-
message: `Moved ${sourcePath} to ${destPath}`
|
|
805
|
-
};
|
|
806
|
-
|
|
807
|
-
} catch (error) {
|
|
808
|
-
throw new Error(`Failed to move ${sourcePath} to ${destPath}: ${error.message}`);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
/**
|
|
813
|
-
* Create directory
|
|
814
|
-
* @private
|
|
815
|
-
*/
|
|
816
|
-
async createDirectory(directory, accessConfig) {
|
|
817
|
-
const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
|
|
818
|
-
const fullPath = this.resolvePath(directory, workingDir);
|
|
819
|
-
|
|
820
|
-
// Validate write access using DirectoryAccessManager
|
|
821
|
-
const accessResult = this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig);
|
|
822
|
-
if (!accessResult.allowed) {
|
|
823
|
-
throw new Error(`Write access denied: ${accessResult.reason} (${accessResult.path})`);
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
try {
|
|
827
|
-
await fs.mkdir(fullPath, { recursive: true });
|
|
828
|
-
|
|
829
|
-
const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
|
|
830
|
-
|
|
831
|
-
return {
|
|
832
|
-
success: true,
|
|
833
|
-
action: 'create-dir',
|
|
834
|
-
directory: relativePath,
|
|
835
|
-
fullPath: fullPath,
|
|
836
|
-
message: `Created directory ${directory}`
|
|
837
|
-
};
|
|
838
|
-
|
|
839
|
-
} catch (error) {
|
|
840
|
-
throw new Error(`Failed to create directory ${directory}: ${error.message}`);
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
/**
|
|
845
|
-
* List directory contents
|
|
846
|
-
* @private
|
|
847
|
-
*/
|
|
848
|
-
async listDirectory(directory, accessConfig) {
|
|
849
|
-
const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
|
|
850
|
-
const fullPath = this.resolvePath(directory, workingDir);
|
|
851
|
-
|
|
852
|
-
// Validate read access using DirectoryAccessManager
|
|
853
|
-
const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
|
|
854
|
-
if (!accessResult.allowed) {
|
|
855
|
-
throw new Error(`Read access denied: ${accessResult.reason} (${accessResult.path})`);
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
try {
|
|
859
|
-
const entries = await fs.readdir(fullPath, { withFileTypes: true });
|
|
860
|
-
|
|
861
|
-
const contents = [];
|
|
862
|
-
for (const entry of entries) {
|
|
863
|
-
const entryPath = path.join(fullPath, entry.name);
|
|
864
|
-
const stats = await fs.stat(entryPath);
|
|
865
|
-
|
|
866
|
-
contents.push({
|
|
867
|
-
name: entry.name,
|
|
868
|
-
type: entry.isDirectory() ? 'directory' : 'file',
|
|
869
|
-
size: entry.isFile() ? stats.size : undefined,
|
|
870
|
-
lastModified: stats.mtime.toISOString(),
|
|
871
|
-
permissions: stats.mode,
|
|
872
|
-
isSymlink: entry.isSymbolicLink()
|
|
873
|
-
});
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
|
|
877
|
-
|
|
878
|
-
return {
|
|
879
|
-
success: true,
|
|
880
|
-
action: 'list',
|
|
881
|
-
directory: relativePath,
|
|
882
|
-
fullPath: fullPath,
|
|
883
|
-
contents,
|
|
884
|
-
totalItems: contents.length,
|
|
885
|
-
directories: contents.filter(item => item.type === 'directory').length,
|
|
886
|
-
files: contents.filter(item => item.type === 'file').length,
|
|
887
|
-
message: `Listed ${contents.length} items in ${directory}`
|
|
888
|
-
};
|
|
889
|
-
|
|
890
|
-
} catch (error) {
|
|
891
|
-
throw new Error(`Failed to list directory ${directory}: ${error.message}`);
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
/**
|
|
896
|
-
* Check if file/directory exists
|
|
897
|
-
* @private
|
|
898
|
-
*/
|
|
899
|
-
async checkExists(filePath, accessConfig) {
|
|
900
|
-
const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
|
|
901
|
-
const fullPath = this.resolvePath(filePath, workingDir);
|
|
902
|
-
|
|
903
|
-
// Validate read access
|
|
904
|
-
const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
|
|
905
|
-
if (!accessResult.allowed) {
|
|
906
|
-
throw new Error(`Read access denied: ${accessResult.reason} (${accessResult.path})`);
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
try {
|
|
910
|
-
const stats = await fs.stat(fullPath);
|
|
911
|
-
|
|
912
|
-
const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
|
|
913
|
-
|
|
914
|
-
return {
|
|
915
|
-
success: true,
|
|
916
|
-
action: 'exists',
|
|
917
|
-
filePath: relativePath,
|
|
918
|
-
fullPath: fullPath,
|
|
919
|
-
exists: true,
|
|
920
|
-
type: stats.isDirectory() ? 'directory' : 'file',
|
|
921
|
-
message: `${filePath} exists as ${stats.isDirectory() ? 'directory' : 'file'}`
|
|
922
|
-
};
|
|
923
|
-
|
|
924
|
-
} catch (error) {
|
|
925
|
-
if (error.code === 'ENOENT') {
|
|
926
|
-
const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
|
|
927
|
-
return {
|
|
928
|
-
success: true,
|
|
929
|
-
action: 'exists',
|
|
930
|
-
filePath: relativePath,
|
|
931
|
-
fullPath: fullPath,
|
|
932
|
-
exists: false,
|
|
933
|
-
message: `${filePath} does not exist`
|
|
934
|
-
};
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
throw new Error(`Failed to check existence of ${filePath}: ${error.message}`);
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
/**
|
|
942
|
-
* Get file statistics
|
|
943
|
-
* @private
|
|
944
|
-
*/
|
|
945
|
-
async getFileStats(filePath, accessConfig) {
|
|
946
|
-
const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
|
|
947
|
-
const fullPath = this.resolvePath(filePath, workingDir);
|
|
948
|
-
|
|
949
|
-
// Validate read access
|
|
950
|
-
const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
|
|
951
|
-
if (!accessResult.allowed) {
|
|
952
|
-
throw new Error(`Read access denied: ${accessResult.reason} (${accessResult.path})`);
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
try {
|
|
956
|
-
const stats = await fs.stat(fullPath);
|
|
957
|
-
|
|
958
|
-
const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
|
|
959
|
-
|
|
960
|
-
return {
|
|
961
|
-
success: true,
|
|
962
|
-
action: 'stats',
|
|
963
|
-
filePath: relativePath,
|
|
964
|
-
fullPath: fullPath,
|
|
965
|
-
stats: {
|
|
966
|
-
size: stats.size,
|
|
967
|
-
type: stats.isDirectory() ? 'directory' : 'file',
|
|
968
|
-
lastModified: stats.mtime.toISOString(),
|
|
969
|
-
lastAccessed: stats.atime.toISOString(),
|
|
970
|
-
created: stats.birthtime.toISOString(),
|
|
971
|
-
permissions: stats.mode,
|
|
972
|
-
isSymlink: stats.isSymbolicLink()
|
|
973
|
-
},
|
|
974
|
-
message: `Retrieved stats for ${filePath}`
|
|
975
|
-
};
|
|
976
|
-
|
|
977
|
-
} catch (error) {
|
|
978
|
-
throw new Error(`Failed to get stats for ${filePath}: ${error.message}`);
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
/**
|
|
983
|
-
* Resolve file path safely (legacy method for compatibility)
|
|
984
|
-
* @private
|
|
985
|
-
*/
|
|
986
|
-
resolvePath(filePath, workingDir) {
|
|
987
|
-
if (path.isAbsolute(filePath)) {
|
|
988
|
-
return path.normalize(filePath);
|
|
989
|
-
}
|
|
990
|
-
return path.resolve(workingDir, filePath);
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
/**
|
|
994
|
-
* Validate path access using DirectoryAccessManager
|
|
995
|
-
* @private
|
|
996
|
-
*/
|
|
997
|
-
validatePathAccess(fullPath, accessConfig, operation = 'read') {
|
|
998
|
-
const accessResult = operation === 'write'
|
|
999
|
-
? this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig)
|
|
1000
|
-
: this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
|
|
1001
|
-
|
|
1002
|
-
if (!accessResult.allowed) {
|
|
1003
|
-
throw new Error(`${operation} access denied: ${accessResult.reason} (${accessResult.path})`);
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
return accessResult;
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
/**
|
|
1010
|
-
* Check if file extension is allowed
|
|
1011
|
-
* @private
|
|
1012
|
-
*/
|
|
1013
|
-
isAllowedFileExtension(filePath) {
|
|
1014
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
1015
|
-
|
|
1016
|
-
if (this.blockedExtensions.includes(ext)) {
|
|
1017
|
-
return false;
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
if (this.allowedExtensions && !this.allowedExtensions.includes(ext)) {
|
|
1021
|
-
return false;
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
return true;
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
/**
|
|
1028
|
-
* Add operation to history
|
|
1029
|
-
* @private
|
|
1030
|
-
*/
|
|
1031
|
-
addToHistory(action, result, agentId) {
|
|
1032
|
-
const historyEntry = {
|
|
1033
|
-
timestamp: new Date().toISOString(),
|
|
1034
|
-
agentId,
|
|
1035
|
-
action: action.type,
|
|
1036
|
-
filePath: action.filePath || action.outputPath || action.directory,
|
|
1037
|
-
success: result.success,
|
|
1038
|
-
size: result.size
|
|
1039
|
-
};
|
|
1040
|
-
|
|
1041
|
-
this.operationHistory.push(historyEntry);
|
|
1042
|
-
|
|
1043
|
-
// Keep only last 200 entries
|
|
1044
|
-
if (this.operationHistory.length > 200) {
|
|
1045
|
-
this.operationHistory = this.operationHistory.slice(-200);
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
/**
|
|
1050
|
-
* Get supported actions for this tool
|
|
1051
|
-
* @returns {Array<string>} Array of supported action names
|
|
1052
|
-
*/
|
|
1053
|
-
getSupportedActions() {
|
|
1054
|
-
return [
|
|
1055
|
-
'read', 'write', 'append', 'delete', 'copy', 'move',
|
|
1056
|
-
'create-dir', 'list', 'exists', 'stats'
|
|
1057
|
-
];
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
/**
|
|
1061
|
-
* Get parameter schema for validation
|
|
1062
|
-
* @returns {Object} Parameter schema
|
|
1063
|
-
*/
|
|
1064
|
-
getParameterSchema() {
|
|
1065
|
-
return {
|
|
1066
|
-
type: 'object',
|
|
1067
|
-
properties: {
|
|
1068
|
-
actions: {
|
|
1069
|
-
type: 'array',
|
|
1070
|
-
minItems: 1,
|
|
1071
|
-
items: {
|
|
1072
|
-
type: 'object',
|
|
1073
|
-
properties: {
|
|
1074
|
-
type: {
|
|
1075
|
-
type: 'string',
|
|
1076
|
-
enum: this.getSupportedActions()
|
|
1077
|
-
},
|
|
1078
|
-
filePath: { type: 'string' },
|
|
1079
|
-
outputPath: { type: 'string' },
|
|
1080
|
-
sourcePath: { type: 'string' },
|
|
1081
|
-
destPath: { type: 'string' },
|
|
1082
|
-
directory: { type: 'string' },
|
|
1083
|
-
content: { type: 'string' },
|
|
1084
|
-
encoding: { type: 'string' },
|
|
1085
|
-
createDirs: { type: 'boolean' }
|
|
1086
|
-
},
|
|
1087
|
-
required: ['type']
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
},
|
|
1091
|
-
required: ['actions']
|
|
1092
|
-
};
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
/**
|
|
1096
|
-
* Get operation history for debugging
|
|
1097
|
-
* @returns {Array} Operation history
|
|
1098
|
-
*/
|
|
1099
|
-
getOperationHistory(agentId = null) {
|
|
1100
|
-
if (agentId) {
|
|
1101
|
-
return this.operationHistory.filter(entry => entry.agentId === agentId);
|
|
1102
|
-
}
|
|
1103
|
-
return [...this.operationHistory];
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
export default FileSystemTool;
|
|
1
|
+
const a0_0xde1dc1=a0_0x44f0;(function(_0x13f930,_0x25a8b7){const _0x32d6f8=a0_0x44f0,_0x532a45=_0x13f930();while(!![]){try{const _0x44e6da=parseInt(_0x32d6f8(0x20d))/0x1+parseInt(_0x32d6f8(0x21b))/0x2+parseInt(_0x32d6f8(0x1fb))/0x3+parseInt(_0x32d6f8(0x1c0))/0x4*(-parseInt(_0x32d6f8(0x206))/0x5)+-parseInt(_0x32d6f8(0x230))/0x6+-parseInt(_0x32d6f8(0x200))/0x7*(-parseInt(_0x32d6f8(0x1ed))/0x8)+-parseInt(_0x32d6f8(0x23f))/0x9*(parseInt(_0x32d6f8(0x23b))/0xa);if(_0x44e6da===_0x25a8b7)break;else _0x532a45['push'](_0x532a45['shift']());}catch(_0x5a19dc){_0x532a45['push'](_0x532a45['shift']());}}}(a0_0x57f3,0x79574));import{BaseTool}from'./baseTool.js';import a0_0x1322e1 from'../utilities/tagParser.js';import a0_0x55f9ed from'../utilities/directoryAccessManager.js';import a0_0x1890e5 from'fs/promises';import a0_0x39d076 from'path';function a0_0x44f0(_0x4b2f6b,_0x55bbef){_0x4b2f6b=_0x4b2f6b-0x1b0;const _0x57f30b=a0_0x57f3();let _0x44f0cb=_0x57f30b[_0x4b2f6b];if(a0_0x44f0['mtvRDM']===undefined){var _0x1adb49=function(_0x443d2f){const _0x263b7d='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x1322e1='',_0x55f9ed='';for(let _0x1890e5=0x0,_0x39d076,_0x542aea,_0x1e95e8=0x0;_0x542aea=_0x443d2f['charAt'](_0x1e95e8++);~_0x542aea&&(_0x39d076=_0x1890e5%0x4?_0x39d076*0x40+_0x542aea:_0x542aea,_0x1890e5++%0x4)?_0x1322e1+=String['fromCharCode'](0xff&_0x39d076>>(-0x2*_0x1890e5&0x6)):0x0){_0x542aea=_0x263b7d['indexOf'](_0x542aea);}for(let _0x1d4ffd=0x0,_0x3eded9=_0x1322e1['length'];_0x1d4ffd<_0x3eded9;_0x1d4ffd++){_0x55f9ed+='%'+('00'+_0x1322e1['charCodeAt'](_0x1d4ffd)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x55f9ed);};a0_0x44f0['WbaPtL']=_0x1adb49,a0_0x44f0['FgZwcQ']={},a0_0x44f0['mtvRDM']=!![];}const _0x6239cf=_0x57f30b[0x0],_0x1eb5aa=_0x4b2f6b+_0x6239cf,_0xc8be45=a0_0x44f0['FgZwcQ'][_0x1eb5aa];return!_0xc8be45?(_0x44f0cb=a0_0x44f0['WbaPtL'](_0x44f0cb),a0_0x44f0['FgZwcQ'][_0x1eb5aa]=_0x44f0cb):_0x44f0cb=_0xc8be45,_0x44f0cb;}import a0_0x542aea from'crypto';function a0_0x57f3(){const _0xe799d5=['ywDLBNrjza','zgvIDwC','Bw92zq','rMfPBgvKihrVigDLDcbZDgf0CYbMB3iG','qxqGBgvHC3qGB25LigfJDgLVBIbPCYbYzxf1AxjLza','sw52ywXPzcbWyxjHBwv0zxjZoIbHy3rPB25Zig11C3qGyMuGyw4GyxjYyxKUifjLy2vPDMvKihr5Cgu6ia','C291CMnLugf0Aa','igj5DgvZigzYB20G','y3jLyxrLrgLYzwn0B3j5qwnJzxnZ','rMfPBgvKihrVignOzwnRigv4Axn0zw5JzsbVzIa','CMvHza','ywXSB3DLzev4DgvUC2LVBNm','BM9YBwfSAxPL','ywn0Aw9UCW','yNL0zuXLBMD0Aa','rMfPBgvKihrVignVChKG','nZq5nLvdzezhvW','B3v0Chv0lxbHDgG','y3jLyxrLlwrPCNm','qwn0Aw9Uia','rMfPBgvKihrVigfWCgvUzcb0BYbMAwXLia','Cgf0Aa','zgLYzwn0B3j5qwnJzxnZtwfUywDLCG','oIbVDxrWDxqTCgf0AcbPCYbYzxf1AxjLzcbMB3iGD3jPDgu','CMf3q29UDgvUDa','zMLSzvbHDgG','CgfYC2vbDhrYAwj1DgvZ','rMLSzsb3B3vSzcbIzwnVBwuGDg9VigXHCMDLoIa','igL0zw1ZigLUia','ru5pru5u','mtu4nte2n3jvA25uqW','y3jLyxrLuMvSyxrPDMvqyxrO','yMLYDgH0Aw1L','y2HLy2TfEgLZDhm','AxntEw1IB2XPy0XPBMS','ntu3mNfqBej3Aa','BM93','lMrLBgv0zwqTyMfJA3vWlq','uMvHzcbHy2nLC3mGzgvUAwvKoIa','CgfYC2vqyxjHBwv0zxjZ','C3rHDa','mJeWmJvMyNrNqKm','ywXSB3DLza','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','D3jPDgu','zgvSzxrLrMLSzq','Aw5JBhvKzxm','B3bLCMf0Aw9UsgLZDg9YEq','nJy0oty5sNfizhfZ','CMvHzgrPCG','oIbMAwXLihr5CguGBM90igfSBg93zwq6ia','Dg9mB3DLCKnHC2u','Bwf4q29Uy3vYCMvUDe9WzxjHDgLVBNm','uMv0CMLLDMvKihn0yxrZigzVCIa','y29Kzq','CMvHC29U','zMLSzs1WyxrO','Bwf4rMLSzvnPEMu','zMLSzq','v3jPDguGywnJzxnZigrLBMLLzdOG','DgLTzw91Da','zgvZDc1WyxrO','ote0nda2C3L5BKjZ','yxbWzw5K','BgvUz3rO','oIbKAxjLy3rVCNKGAxmGCMvXDwLYzwqGzM9Yia','CMvXDwLYzxnqCM9Qzwn0','AxnbC3LUyW','D29YA2LUz0rPCMvJDg9YEq','z2v0v29YA2LUz0rPCMvJDg9YEq','oIbMAwXLlxbHDgGGAxmGCMvXDwLYzwqGzM9Yia','q29WAwvKia','D3jPDgvgAwXL','ywXSB3DLzerPCMvJDg9YAwvZ','B3v0Chv0ugf0Aa','y3jLyxrLrgLYCW','DhjPBq','Bwf0y2HbBgW','BwvZC2fNzq','oIbJB250zw50igLZihjLCxvPCMvKigzVCIb3CML0zq','zgvSzxrL','ChvZAa','rMLSzvn5C3rLBsberujvrZOGvxnPBMCGzMfSBgjHy2SGD29YA2LUzYbKAxjLy3rVCNK6','nteZnJiWnfDVv2vRzq','BwTKAxi','DMfSAwrHDgvxCML0zufJy2vZCW','igj5DgvZihrVia','DhLWzq','Dhj1zq','y3DK','C3rHDhm','rMLSzvn5C3rLBsberujvrZOGChjVAMvJDerPCIbPCZO','zgvZDfbHDgG','y3jLyxrLrgLYzwn0B3j5','oteWy2zvExfx','zMLSDgvY','qxbWzw5KzwqG','ywnJzxnZ','nZyXntHdvMXcseG','zgLYzwn0B3j5','oIb0ExbLigLZihjLCxvPCMvK','lMv4zq','y29WEq','rMLSzvn5C3rLBsb0B29SihbHCNnPBMCGCgfYyw1LDgvYCW','ugfYC2vKiezPBgvtExn0zw0GDg9VBcbWyxjHBwv0zxjZ','uMvHzca','rMfPBgvKihrVigXPC3qGzgLYzwn0B3j5ia','Bg9N','Dg9ju09tDhjPBMC','CMvHzezPBgu','CMvZB2X2zvbHDgG','BwfW','C291CMnLlxbHDgG','sw52ywXPzcbWyxjHBwv0zxjZoIbHy3rPB25ZigLZihjLCxvPCMvKlIbszwnLAxzLzcbWyxjHBxm6ia','z2v0rMLSzvn0yxrZ','BMfTzq','v3jPDguGywnJzxnZigrLBMLLzcbMB3iGzgvZDgLUyxrPB246ia','CMvUyw1L','y3jLyxrLlwrPCG','AxneAxjLy3rVCNK','rMfPBgvKihrVihbHCNnLigzPBgvZExn0zw0GCgfYyw1LDgvYCZOG','tw92zwqG','yxbWzw5Kvg9gAwXL','q29UDgvUDcb0B28GBgfYz2u6ia','rMfPBgvKihrVihDYAxrLigzPBguG','ywrKvg9iAxn0B3j5','mJyWB2j4qxDZ','y29UDgvUDa','igrVzxmGBM90igv4Axn0','C2XPy2u','u291CMnLihjLywqGywnJzxnZigrLBMLLzdOG','yMXVy2TLzev4DgvUC2LVBNm','oIbMAwXLlxbHDgGGAxmGCMvXDwLYzwqGzM9YigfWCgvUza','DMfSAwrHDgvqyxrOqwnJzxnZ','lNnJCG','rMfPBgvKihrVihjLywqGzMLSzsa','C3rYAw5NAwz5','igj5DgvZicHTyxGG','AxnbCNjHEq','zxHPC3rZ','C2L6zq','icHIywnRDxaGy3jLyxrLzcK','BgLZDa','ihrVia','z2v0ugfYyw1LDgvYu2nOzw1H','rgvZDgLUyxrPB24GD3jPDguGywnJzxnZigrLBMLLzdOG','sw52ywXPzcbWyxjHBwv0zxjZoIbHy3rPB25ZigfYCMf5igLZigvTChr5','zxH0BMfTzq','Bg9Nz2vY','C3rYAw5N','zw5JB2rPBMC','DMfSAwrHDgvszwfKqwnJzxnZ','DxrMoa','y29WEuzPBgu','Bw92zuzPBgu'];a0_0x57f3=function(){return _0xe799d5;};return a0_0x57f3();}import{TOOL_STATUS,FILE_EXTENSIONS,SYSTEM_DEFAULTS}from'../utilities/constants.js';class FileSystemTool extends BaseTool{constructor(_0x1e95e8={},_0x1d4ffd=null){const _0x2b2a67=a0_0x44f0;super(_0x1e95e8,_0x1d4ffd),this[_0x2b2a67(0x21f)]=!![],this[_0x2b2a67(0x220)]=![],this['timeout']=_0x1e95e8[_0x2b2a67(0x219)]||0x7530,this[_0x2b2a67(0x211)]=_0x1e95e8['maxConcurrentOperations']||0x5,this[_0x2b2a67(0x216)]=_0x1e95e8['maxFileSize']||SYSTEM_DEFAULTS['MAX_FILE_SIZE'],this['allowedExtensions']=_0x1e95e8[_0x2b2a67(0x1e8)]||null,this[_0x2b2a67(0x1c5)]=_0x1e95e8[_0x2b2a67(0x1c5)]||[_0x2b2a67(0x242),'.bat','.cmd',_0x2b2a67(0x1c8),'.com'],this['allowedDirectories']=_0x1e95e8[_0x2b2a67(0x226)]||null,this['operationHistory']=[],this[_0x2b2a67(0x1f3)]=new a0_0x55f9ed(_0x1e95e8,_0x1d4ffd);}['getDescription'](){const _0x478623=a0_0x44f0;return _0x478623(0x208)+Math['round'](this[_0x478623(0x216)]/0x400/0x400)+'MB)\x0a-\x20Dangerous\x20file\x20types\x20blocked\x0a-\x20Path\x20traversal\x20protection\x0a-\x20Backup\x20created\x20for\x20destructive\x20operations\x0a\x0aENCODING\x20SUPPORT:\x0a-\x20utf8\x20(default)\x0a-\x20ascii\x0a-\x20base64\x0a-\x20binary\x0a-\x20hex\x0a\x20\x20\x20\x20';}[a0_0xde1dc1(0x204)](_0x3eded9){const _0x38ada2=a0_0xde1dc1;try{const _0x191aca={},_0x1dd3d1=[];this[_0x38ada2(0x1d6)]?.[_0x38ada2(0x1de)](_0x38ada2(0x244),{'contentLength':_0x3eded9[_0x38ada2(0x21d)],'contentPreview':_0x3eded9['substring'](0x0,0xc8)});const _0x254e2c=[_0x38ada2(0x1e7),'delete',_0x38ada2(0x243),'move',_0x38ada2(0x1b8),_0x38ada2(0x1d0),'exists',_0x38ada2(0x237),'append'];for(const _0x3a9398 of _0x254e2c){const _0x36527f=a0_0x1322e1['extractTagsWithAttributes'](_0x3eded9,_0x3a9398);for(const _0x40b11d of _0x36527f){const _0x53629d={'type':_0x3a9398,..._0x40b11d['attributes']};_0x53629d['file-path']&&(_0x53629d['filePath']=_0x53629d[_0x38ada2(0x215)],delete _0x53629d[_0x38ada2(0x215)]),_0x53629d['output-path']&&(_0x53629d['outputPath']=_0x53629d[_0x38ada2(0x1ee)],delete _0x53629d[_0x38ada2(0x1ee)]),_0x53629d[_0x38ada2(0x1b2)]&&(_0x53629d['sourcePath']=_0x53629d[_0x38ada2(0x1b2)],delete _0x53629d['source-path']),_0x53629d[_0x38ada2(0x21a)]&&(_0x53629d['destPath']=_0x53629d['dest-path'],delete _0x53629d['dest-path']),_0x53629d['create-dirs']&&(_0x53629d[_0x38ada2(0x228)]=_0x53629d['create-dirs']===_0x38ada2(0x235),delete _0x53629d['create-dirs']),_0x1dd3d1[_0x38ada2(0x22e)](_0x53629d);}}const _0x4985b7=_0x3eded9['matchAll'](/<write\s+([^>]*)>(.*?)<\/write>/gs);for(const _0x5e77f6 of _0x4985b7){const _0x478cf4=new a0_0x1322e1(),_0x44b086=_0x478cf4['parseAttributes'](_0x5e77f6[0x1]),_0x2a2181=_0x5e77f6[0x2]['trim'](),_0x763033={'type':_0x38ada2(0x209),'content':_0x2a2181,..._0x44b086};_0x763033['output-path']&&(_0x763033['outputPath']=_0x763033[_0x38ada2(0x1ee)],delete _0x763033[_0x38ada2(0x1ee)]),_0x763033[_0x38ada2(0x1ef)]&&(_0x763033['createDirs']=_0x763033['create-dirs']===_0x38ada2(0x235),delete _0x763033[_0x38ada2(0x1ef)]),_0x1dd3d1[_0x38ada2(0x22e)](_0x763033);}const _0x188a67=_0x3eded9[_0x38ada2(0x22a)](/<append\s+([^>]*)>(.*?)<\/append>/gs);for(const _0x43c245 of _0x188a67){const _0x4d4421=new a0_0x1322e1(),_0x5c4a1b=_0x4d4421[_0x38ada2(0x1f7)](_0x43c245[0x1]),_0x360098=_0x43c245[0x2][_0x38ada2(0x229)](),_0x48aa7b={'type':_0x38ada2(0x21c),'content':_0x360098,..._0x5c4a1b};_0x48aa7b['file-path']&&(_0x48aa7b['filePath']=_0x48aa7b['file-path'],delete _0x48aa7b['file-path']),_0x1dd3d1[_0x38ada2(0x22e)](_0x48aa7b);}return _0x191aca[_0x38ada2(0x1ea)]=_0x1dd3d1,_0x191aca[_0x38ada2(0x1f5)]=_0x3eded9['trim'](),this['logger']?.['debug'](_0x38ada2(0x245),{'totalActions':_0x1dd3d1['length'],'actionTypes':_0x1dd3d1[_0x38ada2(0x1b1)](_0x258f59=>_0x258f59[_0x38ada2(0x234)]),'actions':_0x1dd3d1['map'](_0x6b0042=>({'type':_0x6b0042[_0x38ada2(0x234)],'filePath':_0x6b0042['filePath'],'outputPath':_0x6b0042[_0x38ada2(0x227)],'hasContent':!!_0x6b0042['content']}))}),_0x191aca;}catch(_0x477be2){throw new Error(_0x38ada2(0x1ba)+_0x477be2['message']);}}['getRequiredParameters'](){return['actions'];}['customValidateParameters'](_0x1e98a2){const _0x2f36d5=a0_0xde1dc1,_0x572d05=[];if(!_0x1e98a2[_0x2f36d5(0x1ea)]||!Array[_0x2f36d5(0x1cc)](_0x1e98a2['actions'])||_0x1e98a2[_0x2f36d5(0x1ea)][_0x2f36d5(0x21d)]===0x0)_0x572d05['push'](_0x2f36d5(0x1e1));else for(const [_0x2cd6ef,_0x5db642]of _0x1e98a2[_0x2f36d5(0x1ea)]['entries']()){if(!_0x5db642[_0x2f36d5(0x234)]){_0x572d05[_0x2f36d5(0x22e)]('Action\x20'+(_0x2cd6ef+0x1)+_0x2f36d5(0x241));continue;}switch(_0x5db642['type']){case'read':case'delete':case _0x2f36d5(0x1cd):case'stats':!_0x5db642[_0x2f36d5(0x1f6)]&&_0x572d05[_0x2f36d5(0x22e)](_0x2f36d5(0x1f0)+(_0x2cd6ef+0x1)+_0x2f36d5(0x223)+_0x5db642['type']);break;case'write':!_0x5db642[_0x2f36d5(0x227)]&&_0x572d05[_0x2f36d5(0x22e)]('Action\x20'+(_0x2cd6ef+0x1)+_0x2f36d5(0x1f4));!_0x5db642['content']&&_0x5db642[_0x2f36d5(0x1c1)]!==''&&_0x572d05['push'](_0x2f36d5(0x1f0)+(_0x2cd6ef+0x1)+_0x2f36d5(0x22c));break;case'append':!_0x5db642[_0x2f36d5(0x1f6)]&&_0x572d05[_0x2f36d5(0x22e)]('Action\x20'+(_0x2cd6ef+0x1)+_0x2f36d5(0x1c6));!_0x5db642['content']&&_0x5db642[_0x2f36d5(0x1c1)]!==''&&_0x572d05[_0x2f36d5(0x22e)](_0x2f36d5(0x1f0)+(_0x2cd6ef+0x1)+':\x20content\x20is\x20required\x20for\x20append');break;case'copy':case _0x2f36d5(0x1df):!_0x5db642[_0x2f36d5(0x1e3)]&&_0x572d05['push'](_0x2f36d5(0x1f0)+(_0x2cd6ef+0x1)+':\x20source-path\x20is\x20required\x20for\x20'+_0x5db642['type']);!_0x5db642[_0x2f36d5(0x239)]&&_0x572d05[_0x2f36d5(0x22e)]('Action\x20'+(_0x2cd6ef+0x1)+':\x20dest-path\x20is\x20required\x20for\x20'+_0x5db642['type']);break;case'create-dir':case'list':!_0x5db642['directory']&&_0x572d05['push'](_0x2f36d5(0x1f0)+(_0x2cd6ef+0x1)+_0x2f36d5(0x21e)+_0x5db642[_0x2f36d5(0x234)]);break;default:_0x572d05[_0x2f36d5(0x22e)](_0x2f36d5(0x1f0)+(_0x2cd6ef+0x1)+':\x20unknown\x20action\x20type:\x20'+_0x5db642['type']);}_0x5db642['filePath']&&!this['isAllowedFileExtension'](_0x5db642[_0x2f36d5(0x1f6)])&&_0x572d05[_0x2f36d5(0x22e)](_0x2f36d5(0x1f0)+(_0x2cd6ef+0x1)+':\x20file\x20type\x20not\x20allowed:\x20'+a0_0x39d076[_0x2f36d5(0x1d5)](_0x5db642[_0x2f36d5(0x1f6)])),_0x5db642[_0x2f36d5(0x227)]&&!this['isAllowedFileExtension'](_0x5db642['outputPath'])&&_0x572d05['push']('Action\x20'+(_0x2cd6ef+0x1)+_0x2f36d5(0x20f)+a0_0x39d076['extname'](_0x5db642['outputPath']));}return{'valid':_0x572d05[_0x2f36d5(0x21d)]===0x0,'errors':_0x572d05};}async['execute'](_0x450f9c,_0x1f11d7){const _0x58d290=a0_0xde1dc1;if(!_0x450f9c||typeof _0x450f9c!=='object')throw new Error('Invalid\x20parameters:\x20params\x20must\x20be\x20an\x20object');const {actions:_0x50d8c2}=_0x450f9c;if(!_0x50d8c2)throw new Error(_0x58d290(0x1b3)+JSON[_0x58d290(0x1ca)](Object['keys'](_0x450f9c)));if(!Array[_0x58d290(0x1cc)](_0x50d8c2))throw new Error(_0x58d290(0x1e2)+typeof _0x50d8c2);if(_0x50d8c2[_0x58d290(0x21d)]===0x0)throw new Error(_0x58d290(0x1d4));const {projectDir:_0x530395,agentId:_0x3ee424,directoryAccess:_0x27a559}=_0x1f11d7,_0x56705c=_0x27a559||this['directoryAccessManager'][_0x58d290(0x1e5)]({'workingDirectory':_0x530395||process[_0x58d290(0x236)](),'writeEnabledDirectories':[_0x530395||process['cwd']()],'restrictToProject':!![]});_0x27a559&&_0x27a559['workingDirectory']?(console[_0x58d290(0x248)]('FileSystem\x20DEBUG:\x20Using\x20agent\x20configured\x20working\x20directory:',_0x27a559[_0x58d290(0x221)]),console['log']('FileSystem\x20DEBUG:\x20Full\x20directoryAccess\x20object:',JSON['stringify'](_0x27a559,null,0x2))):(console['log'](_0x58d290(0x22f),_0x530395||process[_0x58d290(0x236)]()),console['log']('FileSystem\x20DEBUG:\x20directoryAccess\x20is:',_0x27a559),console['log'](_0x58d290(0x238),_0x530395));const _0x29e3ca=[];for(const _0x2db957 of _0x50d8c2){try{let _0x34c65c;switch(_0x2db957[_0x58d290(0x234)]){case'read':_0x34c65c=await this[_0x58d290(0x24a)](_0x2db957['filePath'],_0x56705c,_0x2db957[_0x58d290(0x1d8)]);break;case _0x58d290(0x209):_0x34c65c=await this['writeFile'](_0x2db957[_0x58d290(0x227)],_0x2db957['content'],_0x56705c,{'encoding':_0x2db957[_0x58d290(0x1d8)],'createDirs':_0x2db957['createDirs']});break;case _0x58d290(0x21c):_0x34c65c=await this[_0x58d290(0x1bc)](_0x2db957[_0x58d290(0x1f6)],_0x2db957[_0x58d290(0x1c1)],_0x56705c,_0x2db957['encoding']);break;case _0x58d290(0x22d):_0x34c65c=await this[_0x58d290(0x20a)](_0x2db957['filePath'],_0x56705c);break;case'copy':_0x34c65c=await this[_0x58d290(0x1db)](_0x2db957[_0x58d290(0x1e3)],_0x2db957[_0x58d290(0x239)],_0x56705c);break;case'move':_0x34c65c=await this['moveFile'](_0x2db957['sourcePath'],_0x2db957['destPath'],_0x56705c);break;case _0x58d290(0x1b8):_0x34c65c=await this[_0x58d290(0x23a)](_0x2db957['directory'],_0x56705c);break;case _0x58d290(0x1d0):_0x34c65c=await this['listDirectory'](_0x2db957['directory'],_0x56705c);break;case _0x58d290(0x1cd):_0x34c65c=await this[_0x58d290(0x1fe)](_0x2db957['filePath'],_0x56705c);break;case'stats':_0x34c65c=await this['getFileStats'](_0x2db957['filePath'],_0x56705c);break;default:throw new Error('Unknown\x20action\x20type:\x20'+_0x2db957[_0x58d290(0x234)]);}_0x29e3ca['push'](_0x34c65c),this['addToHistory'](_0x2db957,_0x34c65c,_0x1f11d7['agentId']);}catch(_0x47ff4e){const _0x5b1af6={'success':![],'action':_0x2db957[_0x58d290(0x234)],'error':_0x47ff4e[_0x58d290(0x22b)],'filePath':_0x2db957['filePath']||_0x2db957[_0x58d290(0x227)]||_0x2db957['directory']};_0x29e3ca['push'](_0x5b1af6),this[_0x58d290(0x1bf)](_0x2db957,_0x5b1af6,_0x1f11d7[_0x58d290(0x1dd)]);}}return{'success':!![],'actions':_0x29e3ca,'executedActions':_0x50d8c2[_0x58d290(0x21d)],'toolUsed':'filesys'};}async[a0_0xde1dc1(0x24a)](_0x2f7f20,_0x322695,_0x5d7070='utf8'){const _0x2e5b4d=a0_0xde1dc1,_0x3fa676=this[_0x2e5b4d(0x1f3)]['getWorkingDirectory'](_0x322695),_0x4f3a16=this[_0x2e5b4d(0x1b0)](_0x2f7f20,_0x3fa676),_0x1c9595=this['directoryAccessManager']['validateReadAccess'](_0x4f3a16,_0x322695);if(!_0x1c9595[_0x2e5b4d(0x207)])throw new Error(_0x2e5b4d(0x203)+_0x1c9595['reason']+'\x20('+_0x1c9595['path']+')');try{const _0x1a6cff=await a0_0x1890e5['stat'](_0x4f3a16);if(_0x1a6cff['size']>this[_0x2e5b4d(0x216)])throw new Error('File\x20too\x20large:\x20'+_0x1a6cff['size']+_0x2e5b4d(0x1cb)+this[_0x2e5b4d(0x216)]+')');const _0x348ac7=await a0_0x1890e5[_0x2e5b4d(0x24a)](_0x4f3a16,_0x5d7070);return{'success':!![],'action':'read','filePath':this[_0x2e5b4d(0x1f3)]['createRelativePath'](_0x4f3a16,_0x322695),'content':_0x348ac7,'size':_0x1a6cff[_0x2e5b4d(0x1ce)],'encoding':_0x5d7070,'lastModified':_0x1a6cff['mtime']['toISOString'](),'message':_0x2e5b4d(0x246)+_0x1a6cff[_0x2e5b4d(0x1ce)]+_0x2e5b4d(0x1e4)+_0x2f7f20};}catch(_0x151b42){throw new Error(_0x2e5b4d(0x1c9)+_0x2f7f20+':\x20'+_0x151b42['message']);}}async[a0_0xde1dc1(0x225)](_0x2e610d,_0x50ee87,_0x5c4426,_0x173cc3={}){const _0x5e1765=a0_0xde1dc1,{encoding:encoding='utf8',createDirs:createDirs=!![]}=_0x173cc3,_0x19890b=this['directoryAccessManager']['getWorkingDirectory'](_0x5c4426),_0x20f026=this[_0x5e1765(0x1b0)](_0x2e610d,_0x19890b),_0x36a197=this['directoryAccessManager'][_0x5e1765(0x232)](_0x20f026,_0x5c4426);if(!_0x36a197[_0x5e1765(0x207)])throw new Error(_0x5e1765(0x218)+_0x36a197['reason']+'\x20('+_0x36a197['path']+')');try{const _0xac4ee2=Buffer[_0x5e1765(0x1eb)](_0x50ee87,encoding);if(_0xac4ee2>this['maxFileSize'])throw new Error(_0x5e1765(0x1bd)+_0xac4ee2+'\x20bytes\x20(max\x20'+this[_0x5e1765(0x216)]+')');if(createDirs){const _0xe66b4e=a0_0x39d076['dirname'](_0x20f026);await a0_0x1890e5[_0x5e1765(0x231)](_0xe66b4e,{'recursive':!![]});}let _0x164479=null;try{await a0_0x1890e5[_0x5e1765(0x23e)](_0x20f026),_0x164479=_0x20f026+'.backup-'+Date[_0x5e1765(0x201)](),await a0_0x1890e5[_0x5e1765(0x1db)](_0x20f026,_0x164479);}catch{}await a0_0x1890e5[_0x5e1765(0x225)](_0x20f026,_0x50ee87,encoding);const _0x2a83ef=await a0_0x1890e5[_0x5e1765(0x205)](_0x20f026),_0x3ed8d0=this['directoryAccessManager'][_0x5e1765(0x1fc)](_0x20f026,_0x5c4426);return{'success':!![],'action':_0x5e1765(0x209),'outputPath':_0x3ed8d0,'fullPath':_0x20f026,'size':_0x2a83ef['size'],'encoding':encoding,'backupPath':_0x164479?this[_0x5e1765(0x1f3)]['createRelativePath'](_0x164479,_0x5c4426):null,'backupFullPath':_0x164479||null,'message':'Wrote\x20'+_0x2a83ef['size']+_0x5e1765(0x233)+_0x20f026};}catch(_0x4fac60){throw new Error(_0x5e1765(0x1be)+_0x20f026+':\x20'+_0x4fac60['message']);}}async[a0_0xde1dc1(0x1bc)](_0x47df00,_0x5a0dce,_0x3d3a5a,_0x5cafb0=a0_0xde1dc1(0x1da)){const _0x181280=a0_0xde1dc1,_0x141fb9=this[_0x181280(0x1f3)]['getWorkingDirectory'](_0x3d3a5a),_0x12ea04=this[_0x181280(0x1b0)](_0x47df00,_0x141fb9),_0x20adbc=this['directoryAccessManager'][_0x181280(0x232)](_0x12ea04,_0x3d3a5a);if(!_0x20adbc[_0x181280(0x207)])throw new Error('Write\x20access\x20denied:\x20'+_0x20adbc['reason']+'\x20('+_0x20adbc[_0x181280(0x1f2)]+')');try{let _0x592304=0x0;try{const _0x7d9f4f=await a0_0x1890e5[_0x181280(0x205)](_0x12ea04);_0x592304=_0x7d9f4f['size'];}catch{}const _0x488dc7=Buffer['byteLength'](_0x5a0dce,_0x5cafb0);if(_0x592304+_0x488dc7>this['maxFileSize'])throw new Error(_0x181280(0x1f8)+(_0x592304+_0x488dc7)+_0x181280(0x1cb)+this[_0x181280(0x216)]+')');await a0_0x1890e5['appendFile'](_0x12ea04,_0x5a0dce,_0x5cafb0);const _0x4cc2e7=await a0_0x1890e5[_0x181280(0x205)](_0x12ea04),_0x130a2f=this[_0x181280(0x1f3)]['createRelativePath'](_0x12ea04,_0x3d3a5a);return{'success':!![],'action':'append','filePath':_0x130a2f,'fullPath':_0x12ea04,'appendedBytes':_0x488dc7,'totalSize':_0x4cc2e7[_0x181280(0x1ce)],'encoding':_0x5cafb0,'message':_0x181280(0x23d)+_0x488dc7+_0x181280(0x233)+_0x12ea04};}catch(_0xd21e42){throw new Error(_0x181280(0x1f1)+_0x12ea04+':\x20'+_0xd21e42['message']);}}async[a0_0xde1dc1(0x20a)](_0x247d10,_0x3d5b5e){const _0xe74ac5=a0_0xde1dc1,_0x264d7d=this['directoryAccessManager']['getWorkingDirectory'](_0x3d5b5e),_0x5f00ed=this['resolvePath'](_0x247d10,_0x264d7d),_0x14b909=this['directoryAccessManager']['validateWriteAccess'](_0x5f00ed,_0x3d5b5e);if(!_0x14b909['allowed'])throw new Error('Delete\x20access\x20denied:\x20'+_0x14b909[_0xe74ac5(0x214)]+'\x20('+_0x14b909[_0xe74ac5(0x1f2)]+')');try{const _0x2202ce=await a0_0x1890e5[_0xe74ac5(0x205)](_0x5f00ed),_0x34ff24=_0x5f00ed+_0xe74ac5(0x202)+Date[_0xe74ac5(0x201)]();await a0_0x1890e5['copyFile'](_0x5f00ed,_0x34ff24),await a0_0x1890e5['unlink'](_0x5f00ed);const _0x2bde9c=this[_0xe74ac5(0x1f3)]['createRelativePath'](_0x5f00ed,_0x3d5b5e),_0x5b6a45=this[_0xe74ac5(0x1f3)][_0xe74ac5(0x1fc)](_0x34ff24,_0x3d5b5e);return{'success':!![],'action':_0xe74ac5(0x22d),'filePath':_0x2bde9c,'fullPath':_0x5f00ed,'size':_0x2202ce[_0xe74ac5(0x1ce)],'backupPath':_0x5b6a45,'backupFullPath':_0x34ff24,'message':'Deleted\x20'+_0x5f00ed+_0xe74ac5(0x1cf)};}catch(_0x1a57c1){throw new Error('Failed\x20to\x20delete\x20file\x20'+_0x5f00ed+':\x20'+_0x1a57c1[_0xe74ac5(0x22b)]);}}async[a0_0xde1dc1(0x1db)](_0x3368c9,_0x4932c5,_0x47b7ad){const _0x2dcf98=a0_0xde1dc1,_0x5a6ce1=this[_0x2dcf98(0x1f3)][_0x2dcf98(0x222)](_0x47b7ad),_0x2b535e=this[_0x2dcf98(0x1b0)](_0x3368c9,_0x5a6ce1),_0x34eda7=this[_0x2dcf98(0x1b0)](_0x4932c5,_0x5a6ce1),_0x2ee60b=this[_0x2dcf98(0x1f3)][_0x2dcf98(0x1d9)](_0x2b535e,_0x47b7ad);if(!_0x2ee60b['allowed'])throw new Error(_0x2dcf98(0x1c4)+_0x2ee60b[_0x2dcf98(0x214)]+'\x20('+_0x2ee60b['path']+')');const _0x489e16=this[_0x2dcf98(0x1f3)][_0x2dcf98(0x232)](_0x34eda7,_0x47b7ad);if(!_0x489e16['allowed'])throw new Error(_0x2dcf98(0x1d3)+_0x489e16['reason']+'\x20('+_0x489e16[_0x2dcf98(0x1f2)]+')');try{const _0xab1243=await a0_0x1890e5[_0x2dcf98(0x205)](_0x2b535e);if(_0xab1243[_0x2dcf98(0x1ce)]>this['maxFileSize'])throw new Error('Source\x20file\x20too\x20large:\x20'+_0xab1243[_0x2dcf98(0x1ce)]+'\x20bytes');const _0x5ae4a4=a0_0x39d076['dirname'](_0x34eda7);await a0_0x1890e5['mkdir'](_0x5ae4a4,{'recursive':!![]}),await a0_0x1890e5['copyFile'](_0x2b535e,_0x34eda7);const _0x415679=this[_0x2dcf98(0x1f3)]['createRelativePath'](_0x2b535e,_0x47b7ad),_0x55b780=this['directoryAccessManager'][_0x2dcf98(0x1fc)](_0x34eda7,_0x47b7ad);return{'success':!![],'action':_0x2dcf98(0x243),'sourcePath':_0x415679,'destPath':_0x55b780,'sourceFullPath':_0x2b535e,'destFullPath':_0x34eda7,'size':_0xab1243[_0x2dcf98(0x1ce)],'message':_0x2dcf98(0x224)+_0x2b535e+'\x20to\x20'+_0x34eda7};}catch(_0x19b514){throw new Error(_0x2dcf98(0x1ec)+_0x2b535e+_0x2dcf98(0x1d1)+_0x34eda7+':\x20'+_0x19b514[_0x2dcf98(0x22b)]);}}async[a0_0xde1dc1(0x1dc)](_0x1d3627,_0x2cc050,_0x32d007){const _0x9d4017=a0_0xde1dc1,_0x2c131a=this['directoryAccessManager']['getWorkingDirectory'](_0x32d007),_0xe986f7=this[_0x9d4017(0x1b0)](_0x1d3627,_0x2c131a),_0x2b5fdd=this['resolvePath'](_0x2cc050,_0x2c131a),_0x1dd135=this['directoryAccessManager'][_0x9d4017(0x1d9)](_0xe986f7,_0x32d007);if(!_0x1dd135[_0x9d4017(0x207)])throw new Error('Read\x20access\x20denied\x20for\x20source:\x20'+_0x1dd135['reason']+'\x20('+_0x1dd135['path']+')');const _0xd63c76=this[_0x9d4017(0x1f3)][_0x9d4017(0x232)](_0x2b5fdd,_0x32d007);if(!_0xd63c76['allowed'])throw new Error(_0x9d4017(0x1b6)+_0xd63c76['reason']+'\x20('+_0xd63c76[_0x9d4017(0x1f2)]+')');try{const _0x4da4b3=await a0_0x1890e5['stat'](_0xe986f7),_0x17e777=a0_0x39d076['dirname'](_0x2b5fdd);await a0_0x1890e5[_0x9d4017(0x231)](_0x17e777,{'recursive':!![]}),await a0_0x1890e5[_0x9d4017(0x1b7)](_0xe986f7,_0x2b5fdd);const _0x32b9ce=this[_0x9d4017(0x1f3)][_0x9d4017(0x1fc)](_0xe986f7,_0x32d007),_0x1ac4a2=this[_0x9d4017(0x1f3)]['createRelativePath'](_0x2b5fdd,_0x32d007);return{'success':!![],'action':_0x9d4017(0x1df),'sourcePath':_0x32b9ce,'destPath':_0x1ac4a2,'fullSourcePath':_0xe986f7,'fullDestPath':_0x2b5fdd,'size':_0x4da4b3[_0x9d4017(0x1ce)],'message':_0x9d4017(0x1bb)+_0x1d3627+_0x9d4017(0x1d1)+_0x2cc050};}catch(_0x2e389d){throw new Error('Failed\x20to\x20move\x20'+_0x1d3627+_0x9d4017(0x1d1)+_0x2cc050+':\x20'+_0x2e389d['message']);}}async['createDirectory'](_0x3f5e8c,_0x4c107a){const _0x335328=a0_0xde1dc1,_0x5f3072=this[_0x335328(0x1f3)]['getWorkingDirectory'](_0x4c107a),_0x13b9ff=this[_0x335328(0x1b0)](_0x3f5e8c,_0x5f3072),_0x46e77f=this['directoryAccessManager'][_0x335328(0x232)](_0x13b9ff,_0x4c107a);if(!_0x46e77f['allowed'])throw new Error('Write\x20access\x20denied:\x20'+_0x46e77f[_0x335328(0x214)]+'\x20('+_0x46e77f['path']+')');try{await a0_0x1890e5[_0x335328(0x231)](_0x13b9ff,{'recursive':!![]});const _0x567fc1=this['directoryAccessManager']['createRelativePath'](_0x13b9ff,_0x4c107a);return{'success':!![],'action':'create-dir','directory':_0x567fc1,'fullPath':_0x13b9ff,'message':'Created\x20directory\x20'+_0x3f5e8c};}catch(_0x451b52){throw new Error('Failed\x20to\x20create\x20directory\x20'+_0x3f5e8c+':\x20'+_0x451b52['message']);}}async['listDirectory'](_0x231f5a,_0x1a528a){const _0x5be060=a0_0xde1dc1,_0x206b39=this['directoryAccessManager'][_0x5be060(0x222)](_0x1a528a),_0x3b66bf=this[_0x5be060(0x1b0)](_0x231f5a,_0x206b39),_0x519243=this['directoryAccessManager'][_0x5be060(0x1d9)](_0x3b66bf,_0x1a528a);if(!_0x519243[_0x5be060(0x207)])throw new Error(_0x5be060(0x203)+_0x519243['reason']+'\x20('+_0x519243['path']+')');try{const _0x3afc3b=await a0_0x1890e5[_0x5be060(0x20e)](_0x3b66bf,{'withFileTypes':!![]}),_0x49e00e=[];for(const _0x2b56b5 of _0x3afc3b){const _0x411b12=a0_0x39d076['join'](_0x3b66bf,_0x2b56b5[_0x5be060(0x1b5)]),_0x58d326=await a0_0x1890e5[_0x5be060(0x205)](_0x411b12);_0x49e00e['push']({'name':_0x2b56b5[_0x5be060(0x1b5)],'type':_0x2b56b5['isDirectory']()?'directory':'file','size':_0x2b56b5['isFile']()?_0x58d326['size']:undefined,'lastModified':_0x58d326['mtime'][_0x5be060(0x249)](),'permissions':_0x58d326['mode'],'isSymlink':_0x2b56b5[_0x5be060(0x1ff)]()});}const _0x2a15a9=this['directoryAccessManager'][_0x5be060(0x1fc)](_0x3b66bf,_0x1a528a);return{'success':!![],'action':'list','directory':_0x2a15a9,'fullPath':_0x3b66bf,'contents':_0x49e00e,'totalItems':_0x49e00e['length'],'directories':_0x49e00e[_0x5be060(0x23c)](_0x5eb5a6=>_0x5eb5a6[_0x5be060(0x234)]==='directory')[_0x5be060(0x21d)],'files':_0x49e00e['filter'](_0x120546=>_0x120546[_0x5be060(0x234)]===_0x5be060(0x217))[_0x5be060(0x21d)],'message':'Listed\x20'+_0x49e00e[_0x5be060(0x21d)]+_0x5be060(0x1f9)+_0x231f5a};}catch(_0x4e04a7){throw new Error(_0x5be060(0x247)+_0x231f5a+':\x20'+_0x4e04a7[_0x5be060(0x22b)]);}}async[a0_0xde1dc1(0x1fe)](_0x4c94c1,_0x3eeb1e){const _0x1ca1dc=a0_0xde1dc1,_0x5b086f=this[_0x1ca1dc(0x1f3)]['getWorkingDirectory'](_0x3eeb1e),_0x2e7391=this[_0x1ca1dc(0x1b0)](_0x4c94c1,_0x5b086f),_0x50ce06=this['directoryAccessManager']['validateReadAccess'](_0x2e7391,_0x3eeb1e);if(!_0x50ce06['allowed'])throw new Error('Read\x20access\x20denied:\x20'+_0x50ce06['reason']+'\x20('+_0x50ce06['path']+')');try{const _0x4d867b=await a0_0x1890e5['stat'](_0x2e7391),_0x358dca=this['directoryAccessManager'][_0x1ca1dc(0x1fc)](_0x2e7391,_0x3eeb1e);return{'success':!![],'action':_0x1ca1dc(0x1cd),'filePath':_0x358dca,'fullPath':_0x2e7391,'exists':!![],'type':_0x4d867b['isDirectory']()?'directory':_0x1ca1dc(0x217),'message':_0x4c94c1+'\x20exists\x20as\x20'+(_0x4d867b[_0x1ca1dc(0x1b9)]()?_0x1ca1dc(0x240):_0x1ca1dc(0x217))};}catch(_0x5cb14e){if(_0x5cb14e[_0x1ca1dc(0x213)]===_0x1ca1dc(0x1fa)){const _0x448cc8=this[_0x1ca1dc(0x1f3)]['createRelativePath'](_0x2e7391,_0x3eeb1e);return{'success':!![],'action':'exists','filePath':_0x448cc8,'fullPath':_0x2e7391,'exists':![],'message':_0x4c94c1+_0x1ca1dc(0x1c2)};}throw new Error(_0x1ca1dc(0x1e6)+_0x4c94c1+':\x20'+_0x5cb14e[_0x1ca1dc(0x22b)]);}}async[a0_0xde1dc1(0x1b4)](_0x31ff71,_0x5b81ec){const _0x22826a=a0_0xde1dc1,_0x57685e=this['directoryAccessManager']['getWorkingDirectory'](_0x5b81ec),_0x40c08a=this[_0x22826a(0x1b0)](_0x31ff71,_0x57685e),_0x243ba7=this[_0x22826a(0x1f3)][_0x22826a(0x1d9)](_0x40c08a,_0x5b81ec);if(!_0x243ba7[_0x22826a(0x207)])throw new Error(_0x22826a(0x203)+_0x243ba7[_0x22826a(0x214)]+'\x20('+_0x243ba7['path']+')');try{const _0x256fba=await a0_0x1890e5[_0x22826a(0x205)](_0x40c08a),_0x924dfb=this[_0x22826a(0x1f3)][_0x22826a(0x1fc)](_0x40c08a,_0x5b81ec);return{'success':!![],'action':_0x22826a(0x237),'filePath':_0x924dfb,'fullPath':_0x40c08a,'stats':{'size':_0x256fba[_0x22826a(0x1ce)],'type':_0x256fba[_0x22826a(0x1b9)]()?_0x22826a(0x240):'file','lastModified':_0x256fba['mtime']['toISOString'](),'lastAccessed':_0x256fba['atime']['toISOString'](),'created':_0x256fba[_0x22826a(0x1fd)]['toISOString'](),'permissions':_0x256fba['mode'],'isSymlink':_0x256fba['isSymbolicLink']()},'message':_0x22826a(0x212)+_0x31ff71};}catch(_0x10cf56){throw new Error(_0x22826a(0x1e0)+_0x31ff71+':\x20'+_0x10cf56['message']);}}[a0_0xde1dc1(0x1b0)](_0x1ac211,_0x1a3e1b){const _0x4251ff=a0_0xde1dc1;if(a0_0x39d076['isAbsolute'](_0x1ac211))return a0_0x39d076[_0x4251ff(0x1e9)](_0x1ac211);return a0_0x39d076['resolve'](_0x1a3e1b,_0x1ac211);}[a0_0xde1dc1(0x1c7)](_0x321987,_0xe1233d,_0x291ce2=a0_0xde1dc1(0x1e7)){const _0xf6378a=a0_0xde1dc1,_0xc922c4=_0x291ce2==='write'?this['directoryAccessManager']['validateWriteAccess'](_0x321987,_0xe1233d):this['directoryAccessManager']['validateReadAccess'](_0x321987,_0xe1233d);if(!_0xc922c4[_0xf6378a(0x207)])throw new Error(_0x291ce2+'\x20access\x20denied:\x20'+_0xc922c4[_0xf6378a(0x214)]+'\x20('+_0xc922c4['path']+')');return _0xc922c4;}['isAllowedFileExtension'](_0x4aa8d6){const _0x57805a=a0_0xde1dc1,_0x3d3089=a0_0x39d076[_0x57805a(0x1d5)](_0x4aa8d6)[_0x57805a(0x210)]();if(this['blockedExtensions']['includes'](_0x3d3089))return![];if(this['allowedExtensions']&&!this['allowedExtensions'][_0x57805a(0x20b)](_0x3d3089))return![];return!![];}['addToHistory'](_0x5bf60b,_0x42d9d7,_0x19a454){const _0x3c972b=a0_0xde1dc1,_0x54f64d={'timestamp':new Date()[_0x3c972b(0x249)](),'agentId':_0x19a454,'action':_0x5bf60b['type'],'filePath':_0x5bf60b[_0x3c972b(0x1f6)]||_0x5bf60b[_0x3c972b(0x227)]||_0x5bf60b[_0x3c972b(0x240)],'success':_0x42d9d7['success'],'size':_0x42d9d7['size']};this[_0x3c972b(0x20c)]['push'](_0x54f64d),this['operationHistory'][_0x3c972b(0x21d)]>0xc8&&(this['operationHistory']=this[_0x3c972b(0x20c)][_0x3c972b(0x1c3)](-0xc8));}['getSupportedActions'](){const _0xfd120c=a0_0xde1dc1;return[_0xfd120c(0x1e7),'write',_0xfd120c(0x21c),_0xfd120c(0x22d),_0xfd120c(0x243),'move',_0xfd120c(0x1b8),'list','exists',_0xfd120c(0x237)];}[a0_0xde1dc1(0x1d2)](){const _0x1a8f39=a0_0xde1dc1;return{'type':'object','properties':{'actions':{'type':'array','minItems':0x1,'items':{'type':'object','properties':{'type':{'type':'string','enum':this['getSupportedActions']()},'filePath':{'type':'string'},'outputPath':{'type':_0x1a8f39(0x1d7)},'sourcePath':{'type':_0x1a8f39(0x1d7)},'destPath':{'type':'string'},'directory':{'type':_0x1a8f39(0x1d7)},'content':{'type':'string'},'encoding':{'type':_0x1a8f39(0x1d7)},'createDirs':{'type':'boolean'}},'required':['type']}}},'required':[_0x1a8f39(0x1ea)]};}['getOperationHistory'](_0x3c8476=null){const _0x253cfa=a0_0xde1dc1;if(_0x3c8476)return this['operationHistory'][_0x253cfa(0x23c)](_0x23f207=>_0x23f207['agentId']===_0x3c8476);return[...this['operationHistory']];}}export default FileSystemTool;
|