@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.
Files changed (120) hide show
  1. package/README.md +44 -54
  2. package/bin/cli.js +1 -115
  3. package/bin/loxia-terminal-v2.js +3 -0
  4. package/bin/loxia-terminal.js +3 -0
  5. package/bin/start-with-terminal.js +3 -0
  6. package/package.json +14 -15
  7. package/scripts/install-scanners.js +1 -235
  8. package/src/analyzers/CSSAnalyzer.js +1 -297
  9. package/src/analyzers/ConfigValidator.js +1 -690
  10. package/src/analyzers/ESLintAnalyzer.js +1 -320
  11. package/src/analyzers/JavaScriptAnalyzer.js +1 -261
  12. package/src/analyzers/PrettierFormatter.js +1 -247
  13. package/src/analyzers/PythonAnalyzer.js +1 -266
  14. package/src/analyzers/SecurityAnalyzer.js +1 -729
  15. package/src/analyzers/TypeScriptAnalyzer.js +1 -247
  16. package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
  17. package/src/analyzers/codeCloneDetector/detector.js +1 -203
  18. package/src/analyzers/codeCloneDetector/index.js +1 -160
  19. package/src/analyzers/codeCloneDetector/parser.js +1 -199
  20. package/src/analyzers/codeCloneDetector/reporter.js +1 -148
  21. package/src/analyzers/codeCloneDetector/scanner.js +1 -59
  22. package/src/core/agentPool.js +1 -1474
  23. package/src/core/agentScheduler.js +1 -2147
  24. package/src/core/contextManager.js +1 -709
  25. package/src/core/messageProcessor.js +1 -732
  26. package/src/core/orchestrator.js +1 -548
  27. package/src/core/stateManager.js +1 -877
  28. package/src/index.js +1 -631
  29. package/src/interfaces/cli.js +1 -549
  30. package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
  31. package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
  32. package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
  33. package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
  34. package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
  35. package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
  36. package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
  37. package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
  38. package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
  39. package/src/interfaces/terminal/api/apiClient.js +1 -0
  40. package/src/interfaces/terminal/api/messageRouter.js +1 -0
  41. package/src/interfaces/terminal/api/session.js +1 -0
  42. package/src/interfaces/terminal/api/websocket.js +1 -0
  43. package/src/interfaces/terminal/components/AgentCreator.js +1 -0
  44. package/src/interfaces/terminal/components/AgentEditor.js +1 -0
  45. package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
  46. package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
  47. package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
  48. package/src/interfaces/terminal/components/Header.js +1 -0
  49. package/src/interfaces/terminal/components/HelpPanel.js +1 -0
  50. package/src/interfaces/terminal/components/InputBox.js +1 -0
  51. package/src/interfaces/terminal/components/Layout.js +1 -0
  52. package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
  53. package/src/interfaces/terminal/components/MessageList.js +1 -0
  54. package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
  55. package/src/interfaces/terminal/components/SearchPanel.js +1 -0
  56. package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
  57. package/src/interfaces/terminal/components/StatusBar.js +1 -0
  58. package/src/interfaces/terminal/components/TextInput.js +1 -0
  59. package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
  60. package/src/interfaces/terminal/config/constants.js +1 -0
  61. package/src/interfaces/terminal/index.js +1 -0
  62. package/src/interfaces/terminal/state/useAgentControl.js +1 -0
  63. package/src/interfaces/terminal/state/useAgents.js +1 -0
  64. package/src/interfaces/terminal/state/useConnection.js +1 -0
  65. package/src/interfaces/terminal/state/useMessages.js +1 -0
  66. package/src/interfaces/terminal/state/useTools.js +1 -0
  67. package/src/interfaces/terminal/utils/debugLogger.js +1 -0
  68. package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
  69. package/src/interfaces/terminal/utils/theme.js +1 -0
  70. package/src/interfaces/webServer.js +1 -2162
  71. package/src/modules/fileExplorer/controller.js +1 -280
  72. package/src/modules/fileExplorer/index.js +1 -37
  73. package/src/modules/fileExplorer/middleware.js +1 -92
  74. package/src/modules/fileExplorer/routes.js +1 -125
  75. package/src/modules/fileExplorer/types.js +1 -44
  76. package/src/services/aiService.js +1 -1232
  77. package/src/services/apiKeyManager.js +1 -164
  78. package/src/services/benchmarkService.js +1 -366
  79. package/src/services/budgetService.js +1 -539
  80. package/src/services/contextInjectionService.js +1 -247
  81. package/src/services/conversationCompactionService.js +1 -637
  82. package/src/services/errorHandler.js +1 -810
  83. package/src/services/fileAttachmentService.js +1 -544
  84. package/src/services/modelRouterService.js +1 -366
  85. package/src/services/modelsService.js +1 -322
  86. package/src/services/qualityInspector.js +1 -796
  87. package/src/services/tokenCountingService.js +1 -536
  88. package/src/tools/agentCommunicationTool.js +1 -1344
  89. package/src/tools/agentDelayTool.js +1 -485
  90. package/src/tools/asyncToolManager.js +1 -604
  91. package/src/tools/baseTool.js +1 -800
  92. package/src/tools/browserTool.js +1 -920
  93. package/src/tools/cloneDetectionTool.js +1 -621
  94. package/src/tools/dependencyResolverTool.js +1 -1215
  95. package/src/tools/fileContentReplaceTool.js +1 -875
  96. package/src/tools/fileSystemTool.js +1 -1107
  97. package/src/tools/fileTreeTool.js +1 -853
  98. package/src/tools/imageTool.js +1 -901
  99. package/src/tools/importAnalyzerTool.js +1 -1060
  100. package/src/tools/jobDoneTool.js +1 -248
  101. package/src/tools/seekTool.js +1 -956
  102. package/src/tools/staticAnalysisTool.js +1 -1778
  103. package/src/tools/taskManagerTool.js +1 -2873
  104. package/src/tools/terminalTool.js +1 -2304
  105. package/src/tools/webTool.js +1 -1430
  106. package/src/types/agent.js +1 -519
  107. package/src/types/contextReference.js +1 -972
  108. package/src/types/conversation.js +1 -730
  109. package/src/types/toolCommand.js +1 -747
  110. package/src/utilities/attachmentValidator.js +1 -292
  111. package/src/utilities/configManager.js +1 -582
  112. package/src/utilities/constants.js +1 -722
  113. package/src/utilities/directoryAccessManager.js +1 -535
  114. package/src/utilities/fileProcessor.js +1 -307
  115. package/src/utilities/logger.js +1 -436
  116. package/src/utilities/tagParser.js +1 -1246
  117. package/src/utilities/toolConstants.js +1 -317
  118. package/web-ui/build/index.html +2 -2
  119. package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
  120. package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
@@ -1,2304 +1 @@
1
- /**
2
- * TerminalTool - Execute terminal/command line operations
3
- *
4
- * Purpose:
5
- * - Execute system commands safely
6
- * - Handle directory navigation
7
- * - Manage command output and errors
8
- * - Support both synchronous and asynchronous execution
9
- */
10
-
11
- import { BaseTool } from './baseTool.js';
12
- import TagParser from '../utilities/tagParser.js';
13
- import DirectoryAccessManager from '../utilities/directoryAccessManager.js';
14
- import { spawn, exec } from 'child_process';
15
- import path from 'path';
16
- import fs from 'fs/promises';
17
-
18
- import {
19
- TOOL_STATUS,
20
- SYSTEM_DEFAULTS
21
- } from '../utilities/constants.js';
22
-
23
- /**
24
- * PromptDetector - Detects interactive prompts in command output
25
- * Phase 2: Prompt Detection System
26
- */
27
- class PromptDetector {
28
- constructor() {
29
- // Common prompt patterns (case-insensitive)
30
- this.promptPatterns = [
31
- // Yes/No prompts
32
- { pattern: /\(y\/n\)/i, type: 'yes-no', description: 'Yes/No question' },
33
- { pattern: /\(Y\/n\)/i, type: 'yes-no-default-yes', description: 'Yes/No (default Yes)' },
34
- { pattern: /\(y\/N\)/i, type: 'yes-no-default-no', description: 'Yes/No (default No)' },
35
- { pattern: /\[y\/n\]/i, type: 'yes-no', description: 'Yes/No question' },
36
- { pattern: /\[Y\/n\]/i, type: 'yes-no-default-yes', description: 'Yes/No (default Yes)' },
37
- { pattern: /\[y\/N\]/i, type: 'yes-no-default-no', description: 'Yes/No (default No)' },
38
-
39
- // Continue prompts
40
- { pattern: /continue\?/i, type: 'continue', description: 'Continue prompt' },
41
- { pattern: /proceed\?/i, type: 'continue', description: 'Proceed prompt' },
42
- { pattern: /press any key to continue/i, type: 'keypress', description: 'Press any key' },
43
- { pattern: /press enter to continue/i, type: 'keypress', description: 'Press enter' },
44
- { pattern: /hit enter to continue/i, type: 'keypress', description: 'Hit enter' },
45
-
46
- // Password/Authentication prompts
47
- { pattern: /password:/i, type: 'password', description: 'Password prompt' },
48
- { pattern: /enter password/i, type: 'password', description: 'Password prompt' },
49
- { pattern: /passphrase:/i, type: 'password', description: 'Passphrase prompt' },
50
- { pattern: /username:/i, type: 'username', description: 'Username prompt' },
51
- { pattern: /enter username/i, type: 'username', description: 'Username prompt' },
52
-
53
- // Input prompts
54
- { pattern: /enter\s+\w+:/i, type: 'input', description: 'Generic input prompt' },
55
- { pattern: /please enter/i, type: 'input', description: 'Generic input prompt' },
56
- { pattern: /input:/i, type: 'input', description: 'Generic input prompt' },
57
-
58
- // Confirmation prompts
59
- { pattern: /are you sure\?/i, type: 'confirmation', description: 'Confirmation prompt' },
60
- { pattern: /do you want to/i, type: 'confirmation', description: 'Confirmation prompt' },
61
- { pattern: /would you like to/i, type: 'confirmation', description: 'Confirmation prompt' },
62
-
63
- // Selection prompts
64
- { pattern: /select an option/i, type: 'selection', description: 'Selection prompt' },
65
- { pattern: /choose/i, type: 'selection', description: 'Selection prompt' },
66
- { pattern: /\d+\)\s+\w+/g, type: 'menu', description: 'Menu selection' } // Matches: 1) Option
67
- ];
68
- }
69
-
70
- /**
71
- * Analyze output for prompt patterns
72
- * @param {string} output - Output text to analyze (stdout or stderr)
73
- * @param {string} source - Source of output ('stdout' or 'stderr')
74
- * @returns {Object|null} Prompt detection result or null
75
- */
76
- detectPrompt(output, source = 'stdout') {
77
- if (!output || output.trim().length === 0) {
78
- return null;
79
- }
80
-
81
- // Get the last few lines (prompts are usually at the end)
82
- const lines = output.split('\n');
83
- const lastLines = lines.slice(-5).join('\n'); // Check last 5 lines
84
-
85
- // Check each pattern
86
- for (const promptDef of this.promptPatterns) {
87
- const match = lastLines.match(promptDef.pattern);
88
- if (match) {
89
- return {
90
- detected: true,
91
- type: promptDef.type,
92
- description: promptDef.description,
93
- matchedText: match[0],
94
- matchIndex: match.index,
95
- source: source,
96
- fullContext: lastLines,
97
- timestamp: Date.now()
98
- };
99
- }
100
- }
101
-
102
- // Check for generic prompt indicators
103
- // Look for lines ending with : or ? without newline after
104
- const lastLine = lines[lines.length - 1] || '';
105
- if (lastLine.trim().length > 0) {
106
- const endsWithColon = /:\s*$/.test(lastLine);
107
- const endsWithQuestion = /\?\s*$/.test(lastLine);
108
-
109
- if (endsWithColon || endsWithQuestion) {
110
- // Might be a prompt - check if it's asking for input
111
- const looksLikePrompt = /\b(enter|type|provide|specify|input)\b/i.test(lastLine);
112
- if (looksLikePrompt) {
113
- return {
114
- detected: true,
115
- type: 'generic',
116
- description: 'Generic input prompt detected',
117
- matchedText: lastLine.trim(),
118
- source: source,
119
- fullContext: lastLines,
120
- timestamp: Date.now(),
121
- confidence: 0.7 // Lower confidence for generic detection
122
- };
123
- }
124
- }
125
- }
126
-
127
- return null;
128
- }
129
-
130
- /**
131
- * Check if output indicates command is waiting (no prompt but no output)
132
- * @param {number} lastOutputTime - Timestamp of last output
133
- * @param {number} hangThresholdMs - Milliseconds to consider as hanging
134
- * @returns {Object} Hang detection result
135
- */
136
- detectHang(lastOutputTime, hangThresholdMs = 30000) {
137
- const now = Date.now();
138
- const timeSinceLastOutput = now - lastOutputTime;
139
-
140
- return {
141
- isHanging: timeSinceLastOutput >= hangThresholdMs,
142
- timeSinceLastOutput: timeSinceLastOutput,
143
- threshold: hangThresholdMs,
144
- likelyWaiting: timeSinceLastOutput >= hangThresholdMs / 2 // 50% threshold
145
- };
146
- }
147
- }
148
-
149
- class TerminalTool extends BaseTool {
150
- constructor(config = {}, logger = null) {
151
- super(config, logger);
152
-
153
- // Tool metadata
154
- this.requiresProject = false;
155
- this.isAsync = false; // Most commands are quick, use sync execution
156
- this.timeout = config.timeout || 120000; // 2 minutes default
157
- this.maxConcurrentOperations = config.maxConcurrentOperations || 3;
158
-
159
- // Current working directories per context
160
- this.workingDirectories = new Map();
161
-
162
- // Command history
163
- this.commandHistory = [];
164
-
165
- // Security settings
166
- this.allowedCommands = config.allowedCommands || null; // null = all allowed
167
- this.blockedCommands = config.blockedCommands || [
168
- 'rm -rf /',
169
- 'format',
170
- 'del /f /q',
171
- 'shutdown',
172
- 'reboot',
173
- 'halt'
174
- ];
175
-
176
- // Directory access manager
177
- this.directoryAccessManager = new DirectoryAccessManager(config, logger);
178
-
179
- // Prompt detector (Phase 2)
180
- this.promptDetector = new PromptDetector();
181
-
182
- // Phase 3 & 4: Background command tracking
183
- this.commandTracker = new Map(); // commandId -> { agentId, pid, process, state, buffers, timestamps }
184
- this.commandIdCounter = 0;
185
-
186
- // Resource limits
187
- this.MAX_BACKGROUND_COMMANDS_PER_AGENT = config.maxBackgroundCommandsPerAgent || 5;
188
- this.MAX_BACKGROUND_COMMANDS_GLOBAL = config.maxBackgroundCommandsGlobal || 20;
189
- this.MAX_COMMAND_AGE_MINUTES = config.maxCommandAgeMinutes || 60;
190
-
191
- // Terminal detection
192
- this.detectedTerminal = null;
193
- this.platformType = null;
194
- this.initializeTerminalDetection();
195
- }
196
-
197
- /**
198
- * Get tool description for LLM consumption
199
- * @returns {string} Tool description
200
- */
201
- getDescription() {
202
- return `
203
- Terminal Tool: Execute system commands and manage terminal operations safely.
204
-
205
- IMPORTANT: For file and directory creation, prefer using the FileSystem tool.
206
- Reserve the Terminal tool for command-line operations like npm, git, curl, etc.
207
-
208
- USAGE:
209
- [tool id="terminal"]
210
- <run-command>npm install express</run-command>
211
- <change-directory>project/backend</change-directory>
212
- [/tool]
213
-
214
- ALTERNATIVE JSON FORMAT:
215
- \`\`\`json
216
- {
217
- "toolId": "terminal",
218
- "actions": [
219
- {
220
- "type": "run-command",
221
- "command": "npm install express"
222
- },
223
- {
224
- "type": "change-directory",
225
- "directory": "project/backend"
226
- }
227
- ]
228
- }
229
- \`\`\`
230
-
231
- SUPPORTED ACTIONS:
232
- - run-command: Execute a command in the current directory
233
- - change-directory: Change current working directory
234
- - list-directory: List contents of current or specified directory
235
- - create-directory: Create a new directory (prefer FileSystem tool)
236
- - get-working-directory: Get current working directory
237
-
238
- PARAMETERS:
239
- - command: The command to execute
240
- - directory: Directory path for navigation/operations
241
- - timeout: Optional timeout in milliseconds (max ${this.timeout}ms)
242
- - async: Whether to run command asynchronously (true/false)
243
-
244
- BACKGROUND COMMAND MANAGEMENT (Advanced):
245
- For long-running commands (npm install, git operations, builds), use background command tracking:
246
-
247
- **startBackgroundCommand(command, workingDir, {agentId, context})**
248
- - Starts command in background with stdin kept open
249
- - Returns commandId for tracking
250
- - Max ${this.MAX_BACKGROUND_COMMANDS_PER_AGENT} per agent, ${this.MAX_BACKGROUND_COMMANDS_GLOBAL} global
251
- - Auto-detects prompts and updates state to 'waiting_for_input'
252
-
253
- **getCommandStatus(commandId, agentId)**
254
- - Get real-time status: running, waiting_for_input, completed, failed
255
- - Returns stdout/stderr buffers, exit code, timestamps
256
- - Shows prompt detection info if interactive prompt detected
257
-
258
- **sendInput(commandId, input, agentId)**
259
- - Send input to command's stdin (answers prompts)
260
- - Automatically adds newline if not present
261
- - Updates state from 'waiting_for_input' to 'running'
262
-
263
- **killCommand(commandId, agentId)**
264
- - Terminate background command (SIGTERM → SIGKILL)
265
- - Safe to call on already-completed commands
266
-
267
- **listAgentCommands(agentId)**
268
- - List all commands (running and completed) for agent
269
- - Useful for monitoring multiple background processes
270
-
271
- BACKGROUND COMMAND WORKFLOW:
272
- 1. Start: const {commandId} = await terminal.startBackgroundCommand('npm install', dir, {agentId})
273
- 2. Wait: Use agent-delay tool to wait while command runs
274
- 3. Check: const status = terminal.getCommandStatus(commandId, agentId)
275
- 4. If prompt detected: terminal.sendInput(commandId, 'y', agentId)
276
- 5. Verify: Check status.state === 'completed' && status.exitCode === 0
277
-
278
- EXAMPLES:
279
- Basic command execution:
280
- [tool id="terminal"]
281
- <run-command>npm install</run-command>
282
- [/tool]
283
-
284
- Execute curl command:
285
- [tool id="terminal"]
286
- <run-command>curl -s https://api.github.com/zen</run-command>
287
- [/tool]
288
-
289
- Change directory and run command:
290
- [tool id="terminal"]
291
- <change-directory>../frontend</change-directory>
292
- <run-command>npm run build</run-command>
293
- [/tool]
294
-
295
- Package management:
296
- [tool id="terminal"]
297
- <run-command>pip install -r requirements.txt</run-command>
298
- [/tool]
299
-
300
- Git operations:
301
- [tool id="terminal"]
302
- <run-command>git status</run-command>
303
- [/tool]
304
-
305
- [tool id="terminal"]
306
- <run-command>git add .</run-command>
307
- <run-command>git commit -m "Update files"</run-command>
308
- [/tool]
309
-
310
- Directory operations (if FileSystem tool unavailable):
311
- [tool id="terminal"]
312
- <create-directory>backend</create-directory>
313
- [/tool]
314
-
315
- SECURITY NOTES:
316
- - Dangerous commands are blocked for safety
317
- - Commands execute in isolated environment
318
- - Output is captured and returned safely
319
- - Long-running commands may time out - use agent-delay tool to wait
320
-
321
- BEST PRACTICES:
322
- - Use FileSystem tool for file/directory creation and management
323
- - Use Terminal tool for command-line utilities (npm, git, curl, grep, etc.)
324
- - After starting long-running commands, use agent-delay tool to pause checking
325
- - Always check command output to verify success
326
-
327
- CURRENT DIRECTORY:
328
- The tool maintains a current working directory context per agent.
329
- Use change-directory to navigate, and subsequent commands will execute from that location.
330
- `;
331
- }
332
-
333
- /**
334
- * Parse parameters from tool command content
335
- * @param {string} content - Raw tool command content
336
- * @returns {Object} Parsed parameters
337
- */
338
- parseParameters(content) {
339
- try {
340
- const params = {};
341
-
342
- // Extract individual action parameters
343
- const runCommandMatches = TagParser.extractContent(content, 'run-command');
344
- const changeDirMatches = TagParser.extractContent(content, 'change-directory');
345
- const listDirMatches = TagParser.extractContent(content, 'list-directory');
346
- const createDirMatches = TagParser.extractContent(content, 'create-directory');
347
- const getWdMatches = TagParser.extractContent(content, 'get-working-directory');
348
- const timeoutMatches = TagParser.extractContent(content, 'timeout');
349
- const asyncMatches = TagParser.extractContent(content, 'async');
350
-
351
- // Build actions array
352
- const actions = [];
353
-
354
- if (runCommandMatches.length > 0) {
355
- actions.push({
356
- type: 'run-command',
357
- command: runCommandMatches[0].trim()
358
- });
359
- }
360
-
361
- if (changeDirMatches.length > 0) {
362
- actions.push({
363
- type: 'change-directory',
364
- directory: changeDirMatches[0].trim()
365
- });
366
- }
367
-
368
- if (listDirMatches.length > 0) {
369
- actions.push({
370
- type: 'list-directory',
371
- directory: listDirMatches[0].trim() || '.'
372
- });
373
- }
374
-
375
- if (createDirMatches.length > 0) {
376
- actions.push({
377
- type: 'create-directory',
378
- directory: createDirMatches[0].trim()
379
- });
380
- }
381
-
382
- if (getWdMatches.length > 0) {
383
- actions.push({
384
- type: 'get-working-directory'
385
- });
386
- }
387
-
388
- params.actions = actions;
389
-
390
- // Parse additional options
391
- if (timeoutMatches.length > 0) {
392
- params.timeout = parseInt(timeoutMatches[0], 10);
393
- }
394
-
395
- if (asyncMatches.length > 0) {
396
- params.async = asyncMatches[0].toLowerCase() === 'true';
397
- }
398
-
399
- params.rawContent = content.trim();
400
-
401
- return params;
402
-
403
- } catch (error) {
404
- throw new Error(`Failed to parse terminal parameters: ${error.message}`);
405
- }
406
- }
407
-
408
- /**
409
- * Get required parameters
410
- * @returns {Array<string>} Array of required parameter names
411
- */
412
- getRequiredParameters() {
413
- return ['actions'];
414
- }
415
-
416
- /**
417
- * Custom parameter validation
418
- * @param {Object} params - Parameters to validate
419
- * @returns {Object} Validation result
420
- */
421
- customValidateParameters(params) {
422
- const errors = [];
423
-
424
- if (!params.actions || !Array.isArray(params.actions) || params.actions.length === 0) {
425
- errors.push('At least one action is required');
426
- } else {
427
- // Validate each action
428
- for (const [index, action] of params.actions.entries()) {
429
- if (!action.type) {
430
- errors.push(`Action ${index + 1}: type is required`);
431
- continue;
432
- }
433
-
434
- switch (action.type) {
435
- case 'run-command':
436
- if (!action.command || !action.command.trim()) {
437
- errors.push(`Action ${index + 1}: command is required for run-command`);
438
- } else if (this.isBlockedCommand(action.command)) {
439
- errors.push(`Action ${index + 1}: command is blocked for security: ${action.command}`);
440
- } else if (this.allowedCommands && !this.isAllowedCommand(action.command)) {
441
- errors.push(`Action ${index + 1}: command is not in allowed list: ${action.command}`);
442
- }
443
- break;
444
-
445
- case 'change-directory':
446
- case 'list-directory':
447
- case 'create-directory':
448
- if (!action.directory || !action.directory.trim()) {
449
- errors.push(`Action ${index + 1}: directory is required for ${action.type}`);
450
- }
451
- break;
452
-
453
- case 'get-working-directory':
454
- // No additional validation needed
455
- break;
456
-
457
- default:
458
- errors.push(`Action ${index + 1}: unknown action type: ${action.type}`);
459
- }
460
- }
461
- }
462
-
463
- if (params.timeout && (params.timeout < 1000 || params.timeout > this.timeout)) {
464
- errors.push(`Timeout must be between 1000 and ${this.timeout} milliseconds`);
465
- }
466
-
467
- return {
468
- valid: errors.length === 0,
469
- errors
470
- };
471
- }
472
-
473
- /**
474
- * Execute tool with parsed parameters
475
- * @param {Object} params - Parsed parameters
476
- * @param {Object} context - Execution context
477
- * @returns {Promise<Object>} Execution result
478
- */
479
- async execute(params, context) {
480
- const { actions, timeout: customTimeout, async: forceAsync } = params;
481
- const { agentId, projectDir, directoryAccess } = context;
482
-
483
- // Get directory access configuration from agent or create default
484
- const accessConfig = directoryAccess ||
485
- this.directoryAccessManager.createDirectoryAccess({
486
- workingDirectory: projectDir || process.cwd(),
487
- writeEnabledDirectories: [projectDir || process.cwd()],
488
- restrictToProject: true
489
- });
490
-
491
- // IMPORTANT: If the agent has directoryAccess configured, use its workingDirectory
492
- // This ensures UI-configured project directories are respected
493
- if (directoryAccess && directoryAccess.workingDirectory) {
494
- // Agent has explicitly configured working directory from UI - use it
495
- console.log('Terminal DEBUG: Using agent configured working directory:', directoryAccess.workingDirectory);
496
- } else {
497
- // Using fallback to projectDir or process.cwd()
498
- console.log('Terminal DEBUG: Using fallback working directory:', projectDir || process.cwd());
499
- }
500
-
501
- // Get or set current working directory for this agent
502
- const contextKey = `${agentId}-${projectDir || 'default'}`;
503
- let currentWorkingDir = this.workingDirectories.get(contextKey) ||
504
- this.directoryAccessManager.getWorkingDirectory(accessConfig);
505
-
506
- const results = [];
507
-
508
- for (const action of actions) {
509
- try {
510
- let result;
511
-
512
- switch (action.type) {
513
- case 'run-command':
514
- result = await this.executeCommand(action.command, currentWorkingDir, {
515
- timeout: customTimeout || this.timeout,
516
- async: forceAsync || false,
517
- agentId,
518
- context: {
519
- toolsRegistry: context.toolsRegistry,
520
- aiService: context.aiService,
521
- apiKey: context.apiKey,
522
- customApiKeys: context.customApiKeys,
523
- platformProvided: context.platformProvided
524
- }
525
- });
526
- break;
527
-
528
- case 'change-directory':
529
- result = await this.changeDirectory(action.directory, currentWorkingDir, accessConfig);
530
- currentWorkingDir = result.newDirectory;
531
- this.workingDirectories.set(contextKey, currentWorkingDir);
532
- break;
533
-
534
- case 'list-directory':
535
- result = await this.listDirectory(action.directory === '.' ? currentWorkingDir : action.directory);
536
- break;
537
-
538
- case 'create-directory':
539
- result = await this.createDirectory(action.directory, currentWorkingDir);
540
- break;
541
-
542
- case 'get-working-directory':
543
- result = {
544
- success: true,
545
- action: 'get-working-directory',
546
- workingDirectory: currentWorkingDir,
547
- message: `Current working directory: ${currentWorkingDir}`
548
- };
549
- break;
550
-
551
- default:
552
- throw new Error(`Unknown action type: ${action.type}`);
553
- }
554
-
555
- results.push(result);
556
-
557
- // Add to command history
558
- this.addToHistory(action, result, agentId);
559
-
560
- } catch (error) {
561
- const errorResult = {
562
- success: false,
563
- action: action.type,
564
- error: error.message,
565
- command: action.command || action.directory,
566
- workingDirectory: currentWorkingDir
567
- };
568
-
569
- results.push(errorResult);
570
- this.addToHistory(action, errorResult, agentId);
571
- }
572
- }
573
-
574
- // Determine overall success based on individual action results
575
- const overallSuccess = results.every(result => result.success);
576
- const failedActions = results.filter(result => !result.success);
577
-
578
- return {
579
- success: overallSuccess,
580
- actions: results,
581
- workingDirectory: currentWorkingDir,
582
- executedActions: actions.length,
583
- failedActions: failedActions.length,
584
- toolUsed: 'terminal',
585
- message: overallSuccess
586
- ? `All ${actions.length} actions completed successfully`
587
- : `${failedActions.length} of ${actions.length} actions failed`
588
- };
589
- }
590
-
591
- /**
592
- * Execute a command in the specified directory
593
- * @private
594
- */
595
- async executeCommand(command, workingDir, options = {}) {
596
- const { timeout = this.timeout, async: isAsync = false, agentId, context } = options;
597
-
598
- // Translate command for current terminal (now async with AI support)
599
- const originalCommand = command;
600
- let translatedCommand;
601
-
602
- try {
603
- translatedCommand = await this.translateCommand(command, {
604
- agentId,
605
- toolsRegistry: context?.toolsRegistry,
606
- messageProcessor: context?.messageProcessor,
607
- aiService: context?.aiService,
608
- apiKey: context?.apiKey,
609
- customApiKeys: context?.customApiKeys,
610
- platformProvided: context?.platformProvided
611
- });
612
- } catch (error) {
613
- this.logger?.warn('Command translation failed, using original command', {
614
- originalCommand,
615
- error: error.message
616
- });
617
- translatedCommand = command;
618
- }
619
-
620
- return new Promise((resolve, reject) => {
621
- const startTime = Date.now();
622
-
623
- this.logger?.info(`Executing command: ${translatedCommand}`, {
624
- originalCommand,
625
- translatedCommand,
626
- terminal: this.detectedTerminal,
627
- workingDirectory: workingDir,
628
- timeout,
629
- agentId
630
- });
631
-
632
- const childProcess = exec(translatedCommand, {
633
- cwd: workingDir,
634
- timeout,
635
- maxBuffer: 1024 * 1024, // 1MB buffer
636
- env: { ...process.env }
637
- }, (error, stdout, stderr) => {
638
- const executionTime = Date.now() - startTime;
639
-
640
- if (error) {
641
- this.logger?.error(`Command failed: ${translatedCommand}`, {
642
- originalCommand,
643
- translatedCommand,
644
- error: error.message,
645
- workingDirectory: workingDir,
646
- executionTime
647
- });
648
-
649
- resolve({
650
- success: false,
651
- action: 'run-command',
652
- command: originalCommand,
653
- translatedCommand: translatedCommand !== originalCommand ? translatedCommand : undefined,
654
- error: error.message,
655
- stderr: stderr.trim(),
656
- stdout: stdout.trim(),
657
- exitCode: error.code,
658
- executionTime,
659
- workingDirectory: workingDir
660
- });
661
- return;
662
- }
663
-
664
- this.logger?.info(`Command completed: ${translatedCommand}`, {
665
- originalCommand,
666
- translatedCommand,
667
- executionTime,
668
- stdoutLength: stdout.length,
669
- stderrLength: stderr.length
670
- });
671
-
672
- resolve({
673
- success: true,
674
- action: 'run-command',
675
- command: originalCommand,
676
- translatedCommand: translatedCommand !== originalCommand ? translatedCommand : undefined,
677
- stdout: stdout.trim(),
678
- stderr: stderr.trim(),
679
- exitCode: 0,
680
- executionTime,
681
- workingDirectory: workingDir,
682
- message: `Command executed successfully in ${executionTime}ms`
683
- });
684
- });
685
-
686
- // Handle timeout
687
- setTimeout(() => {
688
- if (!childProcess.killed) {
689
- childProcess.kill('SIGTERM');
690
- reject(new Error(`Command timed out after ${timeout}ms: ${translatedCommand} (original: ${originalCommand})`));
691
- }
692
- }, timeout);
693
- });
694
- }
695
-
696
- /**
697
- * Execute a command using spawn() for streaming output
698
- * @param {string} command - Command to execute
699
- * @param {string} workingDir - Working directory
700
- * @param {Object} options - Execution options
701
- * @returns {Promise<Object>} Execution result
702
- * @private
703
- */
704
- async executeCommandWithSpawn(command, workingDir, options = {}) {
705
- const { timeout = this.timeout, agentId, context } = options;
706
-
707
- // Translate command for current terminal
708
- const originalCommand = command;
709
- let translatedCommand;
710
-
711
- try {
712
- translatedCommand = await this.translateCommand(command, {
713
- agentId,
714
- toolsRegistry: context?.toolsRegistry,
715
- messageProcessor: context?.messageProcessor,
716
- aiService: context?.aiService,
717
- apiKey: context?.apiKey,
718
- customApiKeys: context?.customApiKeys,
719
- platformProvided: context?.platformProvided
720
- });
721
- } catch (error) {
722
- this.logger?.warn('Command translation failed, using original command', {
723
- originalCommand,
724
- error: error.message
725
- });
726
- translatedCommand = command;
727
- }
728
-
729
- return new Promise((resolve, reject) => {
730
- const startTime = Date.now();
731
-
732
- this.logger?.info(`Executing command with spawn: ${translatedCommand}`, {
733
- originalCommand,
734
- translatedCommand,
735
- terminal: this.detectedTerminal,
736
- workingDirectory: workingDir,
737
- timeout,
738
- agentId
739
- });
740
-
741
- // Parse command into program and args
742
- // For shell commands, we need to run them through a shell
743
- let childProcess;
744
-
745
- if (this.detectedTerminal === 'cmd' || this.detectedTerminal === 'powershell') {
746
- // Windows: Use cmd /c or powershell -Command
747
- const shell = this.detectedTerminal === 'powershell' ? 'powershell' : 'cmd';
748
- const shellArgs = this.detectedTerminal === 'powershell'
749
- ? ['-Command', translatedCommand]
750
- : ['/c', translatedCommand];
751
-
752
- childProcess = spawn(shell, shellArgs, {
753
- cwd: workingDir,
754
- env: { ...process.env },
755
- windowsHide: true
756
- });
757
- } else {
758
- // Unix: Use sh -c
759
- childProcess = spawn('sh', ['-c', translatedCommand], {
760
- cwd: workingDir,
761
- env: { ...process.env }
762
- });
763
- }
764
-
765
- // Buffers for stdout and stderr
766
- let stdoutData = '';
767
- let stderrData = '';
768
- let isTimedOut = false;
769
- let exitCode = null;
770
-
771
- // Phase 2: Prompt detection tracking
772
- let lastOutputTime = Date.now();
773
- let promptDetectionResult = null;
774
-
775
- // Set up timeout
776
- const timeoutId = setTimeout(() => {
777
- if (!childProcess.killed && exitCode === null) {
778
- isTimedOut = true;
779
- this.logger?.warn(`Command timed out, killing process: ${translatedCommand}`, {
780
- timeout,
781
- agentId
782
- });
783
- childProcess.kill('SIGTERM');
784
-
785
- // If SIGTERM doesn't work, try SIGKILL after 5s
786
- setTimeout(() => {
787
- if (!childProcess.killed) {
788
- childProcess.kill('SIGKILL');
789
- }
790
- }, 5000);
791
- }
792
- }, timeout);
793
-
794
- // Stream stdout
795
- childProcess.stdout.on('data', (chunk) => {
796
- const data = chunk.toString();
797
- stdoutData += data;
798
- lastOutputTime = Date.now(); // Update last output time
799
-
800
- this.logger?.debug(`Command output chunk: ${data.substring(0, 100)}`, {
801
- agentId,
802
- command: originalCommand.substring(0, 50)
803
- });
804
-
805
- // Phase 2: Check for prompts in stdout
806
- if (!promptDetectionResult) {
807
- const detection = this.promptDetector.detectPrompt(stdoutData, 'stdout');
808
- if (detection) {
809
- promptDetectionResult = detection;
810
- this.logger?.info('Prompt detected in stdout', {
811
- type: detection.type,
812
- description: detection.description,
813
- matchedText: detection.matchedText,
814
- agentId,
815
- command: originalCommand.substring(0, 50)
816
- });
817
- }
818
- }
819
- });
820
-
821
- // Stream stderr
822
- childProcess.stderr.on('data', (chunk) => {
823
- const data = chunk.toString();
824
- stderrData += data;
825
- lastOutputTime = Date.now(); // Update last output time
826
-
827
- this.logger?.debug(`Command error chunk: ${data.substring(0, 100)}`, {
828
- agentId,
829
- command: originalCommand.substring(0, 50)
830
- });
831
-
832
- // Phase 2: Check for prompts in stderr
833
- if (!promptDetectionResult) {
834
- const detection = this.promptDetector.detectPrompt(stderrData, 'stderr');
835
- if (detection) {
836
- promptDetectionResult = detection;
837
- this.logger?.info('Prompt detected in stderr', {
838
- type: detection.type,
839
- description: detection.description,
840
- matchedText: detection.matchedText,
841
- agentId,
842
- command: originalCommand.substring(0, 50)
843
- });
844
- }
845
- }
846
- });
847
-
848
- // Handle process exit
849
- childProcess.on('exit', (code, signal) => {
850
- clearTimeout(timeoutId);
851
- exitCode = code;
852
- const executionTime = Date.now() - startTime;
853
-
854
- // Phase 2: Calculate time since last output
855
- const timeSinceLastOutput = Date.now() - lastOutputTime;
856
-
857
- this.logger?.info(`Command process exited: ${translatedCommand}`, {
858
- exitCode: code,
859
- signal,
860
- executionTime,
861
- timedOut: isTimedOut,
862
- stdoutLength: stdoutData.length,
863
- stderrLength: stderrData.length,
864
- promptDetected: !!promptDetectionResult,
865
- timeSinceLastOutput
866
- });
867
-
868
- // Build common result object with Phase 2 additions
869
- const baseResult = {
870
- action: 'run-command',
871
- command: originalCommand,
872
- translatedCommand: translatedCommand !== originalCommand ? translatedCommand : undefined,
873
- stdout: stdoutData.trim(),
874
- stderr: stderrData.trim(),
875
- exitCode: code,
876
- executionTime,
877
- workingDirectory: workingDir,
878
- // Phase 2: Prompt detection fields
879
- promptDetected: !!promptDetectionResult,
880
- promptInfo: promptDetectionResult || undefined,
881
- lastOutputTime: lastOutputTime,
882
- timeSinceLastOutput: timeSinceLastOutput
883
- };
884
-
885
- // If timed out, reject
886
- if (isTimedOut) {
887
- resolve({
888
- ...baseResult,
889
- success: false,
890
- error: `Command timed out after ${timeout}ms`,
891
- exitCode: code || -1,
892
- timedOut: true
893
- });
894
- return;
895
- }
896
-
897
- // If exit code is not 0, consider it a failure
898
- if (code !== 0) {
899
- this.logger?.error(`Command failed with exit code ${code}: ${translatedCommand}`, {
900
- originalCommand,
901
- translatedCommand,
902
- exitCode: code,
903
- stderr: stderrData.substring(0, 200),
904
- executionTime,
905
- promptDetected: !!promptDetectionResult
906
- });
907
-
908
- resolve({
909
- ...baseResult,
910
- success: false,
911
- error: `Command exited with code ${code}`
912
- });
913
- return;
914
- }
915
-
916
- // Success
917
- this.logger?.info(`Command completed successfully: ${translatedCommand}`, {
918
- originalCommand,
919
- executionTime,
920
- stdoutLength: stdoutData.length,
921
- stderrLength: stderrData.length,
922
- promptDetected: !!promptDetectionResult
923
- });
924
-
925
- resolve({
926
- ...baseResult,
927
- success: true,
928
- exitCode: 0,
929
- message: `Command executed successfully in ${executionTime}ms`
930
- });
931
- });
932
-
933
- // Handle spawn errors
934
- childProcess.on('error', (error) => {
935
- clearTimeout(timeoutId);
936
- const executionTime = Date.now() - startTime;
937
- const timeSinceLastOutput = Date.now() - lastOutputTime;
938
-
939
- this.logger?.error(`Command spawn error: ${translatedCommand}`, {
940
- originalCommand,
941
- error: error.message,
942
- executionTime,
943
- promptDetected: !!promptDetectionResult
944
- });
945
-
946
- resolve({
947
- success: false,
948
- action: 'run-command',
949
- command: originalCommand,
950
- translatedCommand: translatedCommand !== originalCommand ? translatedCommand : undefined,
951
- error: error.message,
952
- stderr: stderrData.trim(),
953
- stdout: stdoutData.trim(),
954
- exitCode: -1,
955
- executionTime,
956
- workingDirectory: workingDir,
957
- // Phase 2: Prompt detection fields
958
- promptDetected: !!promptDetectionResult,
959
- promptInfo: promptDetectionResult || undefined,
960
- lastOutputTime: lastOutputTime,
961
- timeSinceLastOutput: timeSinceLastOutput
962
- });
963
- });
964
- });
965
- }
966
-
967
- /**
968
- * Change current working directory
969
- * @private
970
- */
971
- async changeDirectory(targetDir, currentDir, accessConfig) {
972
- try {
973
- let newDirectory;
974
-
975
- if (path.isAbsolute(targetDir)) {
976
- newDirectory = targetDir;
977
- } else {
978
- newDirectory = path.resolve(currentDir, targetDir);
979
- }
980
-
981
- // Verify directory exists
982
- const stats = await fs.stat(newDirectory);
983
- if (!stats.isDirectory()) {
984
- throw new Error(`Not a directory: ${newDirectory}`);
985
- }
986
-
987
- // Security check: validate directory access using DirectoryAccessManager
988
- const accessResult = this.directoryAccessManager.validateReadAccess(newDirectory, accessConfig);
989
- if (!accessResult.allowed) {
990
- this.logger?.warn(`Directory change blocked: ${accessResult.reason}`, {
991
- targetDirectory: newDirectory,
992
- reason: accessResult.reason,
993
- category: accessResult.category
994
- });
995
- throw new Error(`Access denied: ${accessResult.reason}`);
996
- }
997
-
998
- return {
999
- success: true,
1000
- action: 'change-directory',
1001
- previousDirectory: currentDir,
1002
- newDirectory,
1003
- message: `Changed directory to ${newDirectory}`
1004
- };
1005
-
1006
- } catch (error) {
1007
- throw new Error(`Failed to change directory to ${targetDir}: ${error.message}`);
1008
- }
1009
- }
1010
-
1011
- /**
1012
- * List directory contents
1013
- * @private
1014
- */
1015
- async listDirectory(dirPath) {
1016
- try {
1017
- const files = await fs.readdir(dirPath, { withFileTypes: true });
1018
-
1019
- const contents = files.map(file => ({
1020
- name: file.name,
1021
- type: file.isDirectory() ? 'directory' : 'file',
1022
- isSymlink: file.isSymbolicLink()
1023
- }));
1024
-
1025
- return {
1026
- success: true,
1027
- action: 'list-directory',
1028
- directory: dirPath,
1029
- contents,
1030
- totalItems: contents.length,
1031
- directories: contents.filter(item => item.type === 'directory').length,
1032
- files: contents.filter(item => item.type === 'file').length,
1033
- message: `Listed ${contents.length} items in ${dirPath}`
1034
- };
1035
-
1036
- } catch (error) {
1037
- throw new Error(`Failed to list directory ${dirPath}: ${error.message}`);
1038
- }
1039
- }
1040
-
1041
- /**
1042
- * Create directory
1043
- * @private
1044
- */
1045
- async createDirectory(dirPath, currentDir) {
1046
- try {
1047
- let fullPath;
1048
-
1049
- if (path.isAbsolute(dirPath)) {
1050
- fullPath = dirPath;
1051
- } else {
1052
- fullPath = path.resolve(currentDir, dirPath);
1053
- }
1054
-
1055
- await fs.mkdir(fullPath, { recursive: true });
1056
-
1057
- return {
1058
- success: true,
1059
- action: 'create-directory',
1060
- directory: fullPath,
1061
- relativePath: path.relative(currentDir, fullPath),
1062
- message: `Created directory: ${fullPath}`
1063
- };
1064
-
1065
- } catch (error) {
1066
- throw new Error(`Failed to create directory ${dirPath}: ${error.message}`);
1067
- }
1068
- }
1069
-
1070
- /**
1071
- * Check if command is blocked for security
1072
- * @private
1073
- */
1074
- isBlockedCommand(command) {
1075
- const cmdLower = command.toLowerCase().trim();
1076
-
1077
- return this.blockedCommands.some(blocked => {
1078
- const blockedLower = blocked.toLowerCase();
1079
- return cmdLower === blockedLower || cmdLower.startsWith(blockedLower + ' ');
1080
- });
1081
- }
1082
-
1083
- /**
1084
- * Check if command is in allowed list
1085
- * @private
1086
- */
1087
- isAllowedCommand(command) {
1088
- if (!this.allowedCommands) return true;
1089
-
1090
- const cmdLower = command.toLowerCase().trim();
1091
- const cmdBase = cmdLower.split(' ')[0];
1092
-
1093
- return this.allowedCommands.some(allowed =>
1094
- allowed.toLowerCase() === cmdBase ||
1095
- cmdLower.startsWith(allowed.toLowerCase() + ' ')
1096
- );
1097
- }
1098
-
1099
- /**
1100
- * Add command to history
1101
- * @private
1102
- */
1103
- addToHistory(action, result, agentId) {
1104
- const historyEntry = {
1105
- timestamp: new Date().toISOString(),
1106
- agentId,
1107
- action: action.type,
1108
- command: action.command || action.directory,
1109
- success: result.success,
1110
- executionTime: result.executionTime || 0,
1111
- workingDirectory: result.workingDirectory
1112
- };
1113
-
1114
- this.commandHistory.push(historyEntry);
1115
-
1116
- // Keep only last 100 entries
1117
- if (this.commandHistory.length > 100) {
1118
- this.commandHistory = this.commandHistory.slice(-100);
1119
- }
1120
- }
1121
-
1122
- /**
1123
- * Get supported actions for this tool
1124
- * @returns {Array<string>} Array of supported action names
1125
- */
1126
- getSupportedActions() {
1127
- return ['run-command', 'change-directory', 'list-directory', 'create-directory', 'get-working-directory'];
1128
- }
1129
-
1130
- /**
1131
- * Get parameter schema for validation
1132
- * @returns {Object} Parameter schema
1133
- */
1134
- getParameterSchema() {
1135
- return {
1136
- type: 'object',
1137
- properties: {
1138
- actions: {
1139
- type: 'array',
1140
- minItems: 1,
1141
- items: {
1142
- type: 'object',
1143
- properties: {
1144
- type: {
1145
- type: 'string',
1146
- enum: this.getSupportedActions()
1147
- },
1148
- command: { type: 'string' },
1149
- directory: { type: 'string' }
1150
- },
1151
- required: ['type']
1152
- }
1153
- },
1154
- timeout: {
1155
- type: 'integer',
1156
- minimum: 1000,
1157
- maximum: this.timeout
1158
- },
1159
- async: {
1160
- type: 'boolean'
1161
- }
1162
- },
1163
- required: ['actions']
1164
- };
1165
- }
1166
-
1167
- /**
1168
- * Get command history for debugging
1169
- * @returns {Array} Command history
1170
- */
1171
- getCommandHistory(agentId = null) {
1172
- if (agentId) {
1173
- return this.commandHistory.filter(entry => entry.agentId === agentId);
1174
- }
1175
- return [...this.commandHistory];
1176
- }
1177
-
1178
- /**
1179
- * Clear working directory context for agent
1180
- * @param {string} agentId - Agent identifier
1181
- */
1182
- clearWorkingDirectory(agentId) {
1183
- for (const [key] of this.workingDirectories) {
1184
- if (key.startsWith(`${agentId}-`)) {
1185
- this.workingDirectories.delete(key);
1186
- }
1187
- }
1188
- }
1189
-
1190
- /**
1191
- * Get current working directory for agent
1192
- * @param {string} agentId - Agent identifier
1193
- * @param {string} projectDir - Project directory
1194
- * @returns {string} Current working directory
1195
- */
1196
- getCurrentWorkingDirectory(agentId, projectDir = null) {
1197
- const contextKey = `${agentId}-${projectDir || 'default'}`;
1198
- return this.workingDirectories.get(contextKey) || projectDir || process.cwd();
1199
- }
1200
-
1201
- /**
1202
- * Initialize terminal detection
1203
- * @private
1204
- */
1205
- initializeTerminalDetection() {
1206
- // Detect platform
1207
- this.platformType = process.platform;
1208
-
1209
- // Detect terminal type based on environment
1210
- if (process.platform === 'win32') {
1211
- // Windows detection
1212
- if (process.env.PSModulePath) {
1213
- this.detectedTerminal = 'powershell';
1214
- } else if (process.env.SHELL && process.env.SHELL.includes('bash')) {
1215
- this.detectedTerminal = 'bash'; // Git Bash or WSL
1216
- } else {
1217
- this.detectedTerminal = 'cmd'; // Windows Command Prompt
1218
- }
1219
- } else if (process.platform === 'darwin') {
1220
- this.detectedTerminal = 'bash'; // macOS
1221
- } else {
1222
- this.detectedTerminal = 'bash'; // Linux/Unix
1223
- }
1224
-
1225
- this.logger?.info('Terminal detected', {
1226
- platform: this.platformType,
1227
- terminal: this.detectedTerminal,
1228
- shell: process.env.SHELL
1229
- });
1230
- }
1231
-
1232
- /**
1233
- * Translate command for current terminal using AI if needed
1234
- * @param {string} command - Original command
1235
- * @param {Object} context - Execution context with aiService access
1236
- * @returns {Promise<string>} Translated command
1237
- * @private
1238
- */
1239
- async translateCommand(command, context = {}) {
1240
- const trimmedCommand = command.trim();
1241
-
1242
- // Perform comprehensive command analysis
1243
- const analysis = this.analyzeCommandCompatibility(trimmedCommand);
1244
-
1245
- this.logger?.info('Command compatibility analysis', {
1246
- command: trimmedCommand,
1247
- detectedTerminal: analysis.detectedTerminal,
1248
- commandType: analysis.commandType,
1249
- commandCategory: analysis.commandCategory,
1250
- compatible: analysis.compatible,
1251
- issues: analysis.specificIssues,
1252
- suggestedAction: analysis.suggestedAction,
1253
- confidence: analysis.confidence
1254
- });
1255
-
1256
- if (analysis.compatible) {
1257
- return command;
1258
- }
1259
-
1260
- // Try simple translations first (fast path)
1261
- let simpleTranslation = null;
1262
- if (this.detectedTerminal === 'cmd') {
1263
- simpleTranslation = this.translateToWindowsCmd(trimmedCommand);
1264
- } else if (this.detectedTerminal === 'powershell') {
1265
- simpleTranslation = this.translateToPowerShell(trimmedCommand);
1266
- } else if (this.detectedTerminal === 'bash') {
1267
- simpleTranslation = this.translateToBash(trimmedCommand);
1268
- }
1269
-
1270
- // If simple translation looks sufficient and command is simple, use it
1271
- if (simpleTranslation && this.isSimpleCommand(trimmedCommand)) {
1272
- this.logger?.info('Using simple translation', {
1273
- original: command,
1274
- translated: simpleTranslation,
1275
- method: 'simple'
1276
- });
1277
- return simpleTranslation;
1278
- }
1279
-
1280
- // For complex commands, use AI translation
1281
- if (context.aiService || (context.toolsRegistry && context.agentId)) {
1282
- this.logger?.info('Attempting AI translation for complex command', {
1283
- command: command.substring(0, 100) + '...',
1284
- hasAiService: !!context.aiService,
1285
- hasToolsRegistry: !!context.toolsRegistry,
1286
- agentId: context.agentId
1287
- });
1288
-
1289
- try {
1290
- const aiTranslation = await this.translateCommandWithAI(command, context);
1291
- if (aiTranslation && aiTranslation.trim() !== command.trim()) {
1292
- this.logger?.info('Using AI translation', {
1293
- original: command,
1294
- translated: aiTranslation,
1295
- method: 'ai'
1296
- });
1297
- return aiTranslation;
1298
- } else {
1299
- this.logger?.warn('AI translation returned same command', {
1300
- original: command,
1301
- translated: aiTranslation
1302
- });
1303
- }
1304
- } catch (error) {
1305
- this.logger?.warn('AI translation failed, falling back to simple translation', {
1306
- original: command,
1307
- error: error.message,
1308
- stack: error.stack
1309
- });
1310
- }
1311
- } else {
1312
- this.logger?.warn('AI translation not available - missing context', {
1313
- hasAiService: !!context.aiService,
1314
- hasToolsRegistry: !!context.toolsRegistry,
1315
- hasAgentId: !!context.agentId,
1316
- contextKeys: Object.keys(context)
1317
- });
1318
- }
1319
-
1320
- // Fallback to simple translation or original command
1321
- return simpleTranslation || command;
1322
- }
1323
-
1324
- /**
1325
- * Check if command is simple enough for regex translation
1326
- * @param {string} command - Command to check
1327
- * @returns {boolean} Whether command is simple
1328
- * @private
1329
- */
1330
- isSimpleCommand(command) {
1331
- // Check for complex command patterns using simple string methods
1332
- const cmd = command.toLowerCase();
1333
-
1334
- // Multi-line or escape sequences
1335
- if (command.includes('\\n') || command.includes('\\r') || command.includes('\\t')) return false;
1336
- if (command.includes('\n') || command.includes('\r')) return false;
1337
-
1338
- // Code content
1339
- if (command.includes('#include') || command.includes('printf') || command.includes('main()')) return false;
1340
- if (command.includes('def ') || command.includes('function ') || command.includes('class ')) return false;
1341
-
1342
- // Single quotes (problematic on Windows CMD)
1343
- if (command.includes("echo '") && !command.includes('echo "')) return false;
1344
-
1345
- // Long complex strings (likely contain complex content)
1346
- const singleQuoteMatch = command.match(/'([^']*)'/);
1347
- if (singleQuoteMatch && singleQuoteMatch[1].length > 50) return false;
1348
-
1349
- // Unix-style paths in redirections on Windows
1350
- if (this.detectedTerminal === 'cmd' && command.includes('>') && command.includes('/') && !command.includes('\\')) {
1351
- return false;
1352
- }
1353
-
1354
- // Multiple commands
1355
- if (command.includes(' && ') || command.includes(' || ') || command.includes('; ')) return false;
1356
-
1357
- // Command substitution or complex shell features
1358
- if (command.includes('$(') || command.includes('`') || command.includes('{') || command.includes('[')) return false;
1359
-
1360
- // Loops and conditionals
1361
- if (cmd.includes('for ') || cmd.includes('while ') || cmd.includes('if ')) return false;
1362
- if (cmd.includes('export ') || cmd.includes('source ')) return false;
1363
-
1364
- // Pipes and redirections
1365
- if (command.includes(' | ') || command.includes(' > &')) return false;
1366
-
1367
- return true; // Command is simple
1368
- }
1369
-
1370
- /**
1371
- * Translate command using AI service
1372
- * @param {string} command - Original command
1373
- * @param {Object} context - Execution context
1374
- * @returns {Promise<string>} AI-translated command
1375
- * @private
1376
- */
1377
- async translateCommandWithAI(command, context) {
1378
- // Get AI service - either directly provided or through tools registry
1379
- let aiService = context.aiService;
1380
- if (!aiService && context.toolsRegistry && context.agentId) {
1381
- // Try to get AI service through the system (this would need to be passed through context)
1382
- const messageProcessor = context.messageProcessor; // Would need to be passed in context
1383
- if (messageProcessor && messageProcessor.aiService) {
1384
- aiService = messageProcessor.aiService;
1385
- }
1386
- }
1387
-
1388
- if (!aiService) {
1389
- throw new Error('AI service not available for command translation');
1390
- }
1391
-
1392
- const translationPrompt = this.buildTranslationPrompt(command);
1393
-
1394
- // Use a lightweight model for translation
1395
- const model = 'gpt-4-mini'; // Fast and cost-effective for simple translations
1396
-
1397
- try {
1398
- const response = await aiService.sendMessage(model, translationPrompt, {
1399
- agentId: context.agentId,
1400
- temperature: 0.1, // Low temperature for consistent translations
1401
- maxTokens: 200, // Short response expected
1402
- apiKey: context.apiKey,
1403
- customApiKeys: context.customApiKeys,
1404
- platformProvided: context.platformProvided
1405
- });
1406
-
1407
- // Extract the translated command from the response
1408
- const translatedCommand = this.extractTranslatedCommand(response.content);
1409
-
1410
- this.logger?.debug('AI command translation completed', {
1411
- original: command,
1412
- translated: translatedCommand,
1413
- model: model,
1414
- terminal: this.detectedTerminal
1415
- });
1416
-
1417
- return translatedCommand;
1418
-
1419
- } catch (error) {
1420
- this.logger?.error('AI command translation failed', {
1421
- command,
1422
- terminal: this.detectedTerminal,
1423
- error: error.message
1424
- });
1425
- throw error;
1426
- }
1427
- }
1428
-
1429
- /**
1430
- * Build translation prompt for AI service
1431
- * @param {string} command - Command to translate
1432
- * @returns {string} Translation prompt
1433
- * @private
1434
- */
1435
- buildTranslationPrompt(command) {
1436
- const terminalInfo = {
1437
- 'cmd': 'Windows Command Prompt (cmd.exe)',
1438
- 'powershell': 'Windows PowerShell',
1439
- 'bash': 'Bash shell (Linux/Unix/macOS)'
1440
- };
1441
-
1442
- const currentTerminal = terminalInfo[this.detectedTerminal] || this.detectedTerminal;
1443
-
1444
- // Get detailed analysis for better translation context
1445
- const analysis = this.analyzeCommandCompatibility(command);
1446
-
1447
- let prompt = `Translate this command to work correctly in ${currentTerminal}:
1448
-
1449
- ORIGINAL COMMAND:
1450
- \`\`\`
1451
- ${command}
1452
- \`\`\`
1453
-
1454
- COMMAND ANALYSIS:
1455
- - Command Type: ${analysis.commandType}
1456
- - Category: ${analysis.commandCategory}
1457
- - Target Terminal: ${currentTerminal}
1458
- - Compatibility Issues: ${analysis.specificIssues.join(', ') || 'None detected'}`;
1459
-
1460
- // Add alternative suggestions if available
1461
- if (analysis.commandType === 'unix' && analysis.alternatives && analysis.alternatives[this.detectedTerminal]) {
1462
- prompt += `\n- Suggested Alternative: ${analysis.alternatives[this.detectedTerminal]}`;
1463
- }
1464
-
1465
- prompt += `
1466
-
1467
- REQUIREMENTS:
1468
- 1. Make the command work correctly in ${currentTerminal}
1469
- 2. Preserve the original intent and functionality
1470
- 3. Handle file paths, quoting, and syntax correctly
1471
- 4. If creating files, ensure proper encoding and line endings
1472
- 5. Address the specific compatibility issues identified above
1473
- 6. Return ONLY the translated command, nothing else
1474
-
1475
- TRANSLATED COMMAND:`;
1476
-
1477
- return prompt;
1478
- }
1479
-
1480
- /**
1481
- * Extract translated command from AI response
1482
- * @param {string} response - AI response content
1483
- * @returns {string} Extracted command
1484
- * @private
1485
- */
1486
- extractTranslatedCommand(response) {
1487
- // Remove markdown code blocks if present
1488
- let extracted = response.replace(/```[a-z]*\n?(.*?)\n?```/s, '$1');
1489
-
1490
- // Remove common prefixes
1491
- extracted = extracted.replace(/^(TRANSLATED COMMAND:|Command:|Result:)\s*/i, '');
1492
-
1493
- // Take first line if multiple lines (unless it's intentionally multiline)
1494
- const lines = extracted.trim().split('\n');
1495
- if (lines.length > 1 && !extracted.includes('&&') && !extracted.includes('||')) {
1496
- extracted = lines[0].trim();
1497
- }
1498
-
1499
- return extracted.trim();
1500
- }
1501
-
1502
- /**
1503
- * Analyze command compatibility with current terminal
1504
- * @param {string} command - Command to check
1505
- * @returns {Object} Compatibility analysis result
1506
- * @private
1507
- */
1508
- analyzeCommandCompatibility(command) {
1509
- const analysis = this.classifyCommand(command);
1510
- const isCompatible = this.isCommandCompatibleWithTerminal(analysis, this.detectedTerminal);
1511
-
1512
- return {
1513
- compatible: isCompatible,
1514
- detectedTerminal: this.detectedTerminal,
1515
- commandType: analysis.type,
1516
- commandCategory: analysis.category,
1517
- specificIssues: analysis.issues,
1518
- suggestedAction: isCompatible ? 'execute' : 'translate',
1519
- confidence: analysis.confidence
1520
- };
1521
- }
1522
-
1523
- /**
1524
- * Legacy wrapper for backward compatibility
1525
- * @param {string} command - Command to check
1526
- * @returns {boolean} Whether command is compatible
1527
- * @private
1528
- */
1529
- isCommandCompatible(command) {
1530
- return this.analyzeCommandCompatibility(command).compatible;
1531
- }
1532
-
1533
- /**
1534
- * Classify command type and detect potential issues
1535
- * @param {string} command - Command to analyze
1536
- * @returns {Object} Command classification
1537
- * @private
1538
- */
1539
- classifyCommand(command) {
1540
- const cmd = command.toLowerCase().trim();
1541
- const firstWord = cmd.split(' ')[0];
1542
- const issues = [];
1543
- let confidence = 0.9;
1544
-
1545
- // Unix/Linux commands
1546
- const unixCommands = {
1547
- // File operations
1548
- 'ls': { category: 'file-listing', alternatives: { cmd: 'dir', powershell: 'Get-ChildItem' }},
1549
- 'cat': { category: 'file-viewing', alternatives: { cmd: 'type', powershell: 'Get-Content' }},
1550
- 'grep': { category: 'text-search', alternatives: { cmd: 'findstr', powershell: 'Select-String' }},
1551
- 'find': { category: 'file-search', alternatives: { cmd: 'dir /s', powershell: 'Get-ChildItem -Recurse' }},
1552
- 'head': { category: 'file-viewing', alternatives: { cmd: 'more', powershell: 'Get-Content -Head' }},
1553
- 'tail': { category: 'file-viewing', alternatives: { cmd: 'more +n', powershell: 'Get-Content -Tail' }},
1554
- 'wc': { category: 'text-analysis', alternatives: { cmd: 'find /c', powershell: 'Measure-Object' }},
1555
-
1556
- // File manipulation
1557
- 'cp': { category: 'file-copy', alternatives: { cmd: 'copy', powershell: 'Copy-Item' }},
1558
- 'mv': { category: 'file-move', alternatives: { cmd: 'move', powershell: 'Move-Item' }},
1559
- 'rm': { category: 'file-delete', alternatives: { cmd: 'del', powershell: 'Remove-Item' }},
1560
- 'mkdir': { category: 'directory-create', alternatives: { cmd: 'mkdir', powershell: 'New-Item -Type Directory' }},
1561
- 'rmdir': { category: 'directory-delete', alternatives: { cmd: 'rmdir', powershell: 'Remove-Item' }},
1562
- 'touch': { category: 'file-create', alternatives: { cmd: 'type nul >', powershell: 'New-Item -Type File' }},
1563
-
1564
- // Permissions and ownership
1565
- 'chmod': { category: 'permissions', alternatives: { cmd: 'icacls', powershell: 'Set-Acl' }},
1566
- 'chown': { category: 'ownership', alternatives: { cmd: 'takeown', powershell: 'Set-Acl' }},
1567
-
1568
- // Process management
1569
- 'ps': { category: 'process-list', alternatives: { cmd: 'tasklist', powershell: 'Get-Process' }},
1570
- 'kill': { category: 'process-kill', alternatives: { cmd: 'taskkill', powershell: 'Stop-Process' }},
1571
- 'killall': { category: 'process-kill', alternatives: { cmd: 'taskkill /f /im', powershell: 'Get-Process | Stop-Process' }},
1572
- 'top': { category: 'process-monitor', alternatives: { cmd: 'tasklist', powershell: 'Get-Process | Sort-Object CPU' }},
1573
-
1574
- // Network
1575
- 'wget': { category: 'download', alternatives: { cmd: 'curl', powershell: 'Invoke-WebRequest' }},
1576
- 'curl': { category: 'http-client', alternatives: { cmd: 'curl', powershell: 'Invoke-RestMethod' }},
1577
- 'ping': { category: 'network-test', alternatives: { cmd: 'ping', powershell: 'Test-NetConnection' }},
1578
-
1579
- // Text processing
1580
- 'awk': { category: 'text-processing', alternatives: { cmd: 'for /f', powershell: 'ForEach-Object' }},
1581
- 'sed': { category: 'text-edit', alternatives: { cmd: 'powershell -c', powershell: 'native' }},
1582
- 'sort': { category: 'text-sort', alternatives: { cmd: 'sort', powershell: 'Sort-Object' }},
1583
- 'uniq': { category: 'text-dedupe', alternatives: { cmd: 'sort /unique', powershell: 'Sort-Object -Unique' }},
1584
-
1585
- // Environment
1586
- 'pwd': { category: 'directory-current', alternatives: { cmd: 'cd', powershell: 'Get-Location' }},
1587
- 'whoami': { category: 'user-info', alternatives: { cmd: 'echo %USERNAME%', powershell: 'whoami' }},
1588
- 'env': { category: 'environment', alternatives: { cmd: 'set', powershell: 'Get-ChildItem Env:' }},
1589
- 'export': { category: 'environment', alternatives: { cmd: 'set', powershell: '$env:' }},
1590
- 'source': { category: 'script-execute', alternatives: { cmd: 'call', powershell: '. ' }},
1591
-
1592
- // Archives
1593
- 'tar': { category: 'archive', alternatives: { cmd: '7z', powershell: 'Compress-Archive' }},
1594
- 'zip': { category: 'archive', alternatives: { cmd: 'powershell Compress-Archive', powershell: 'Compress-Archive' }},
1595
- 'unzip': { category: 'archive', alternatives: { cmd: 'powershell Expand-Archive', powershell: 'Expand-Archive' }},
1596
-
1597
- // System info
1598
- 'df': { category: 'disk-info', alternatives: { cmd: 'fsutil volume diskfree', powershell: 'Get-WmiObject -Class Win32_LogicalDisk' }},
1599
- 'du': { category: 'disk-usage', alternatives: { cmd: 'dir /s', powershell: 'Get-ChildItem -Recurse | Measure-Object' }},
1600
- 'free': { category: 'memory-info', alternatives: { cmd: 'systeminfo', powershell: 'Get-WmiObject -Class Win32_PhysicalMemory' }},
1601
- 'uname': { category: 'system-info', alternatives: { cmd: 'systeminfo', powershell: 'Get-ComputerInfo' }}
1602
- };
1603
-
1604
- // Windows CMD commands
1605
- const cmdCommands = {
1606
- 'dir': { category: 'file-listing', alternatives: { unix: 'ls', powershell: 'Get-ChildItem' }},
1607
- 'type': { category: 'file-viewing', alternatives: { unix: 'cat', powershell: 'Get-Content' }},
1608
- 'copy': { category: 'file-copy', alternatives: { unix: 'cp', powershell: 'Copy-Item' }},
1609
- 'move': { category: 'file-move', alternatives: { unix: 'mv', powershell: 'Move-Item' }},
1610
- 'del': { category: 'file-delete', alternatives: { unix: 'rm', powershell: 'Remove-Item' }},
1611
- 'tasklist': { category: 'process-list', alternatives: { unix: 'ps', powershell: 'Get-Process' }},
1612
- 'taskkill': { category: 'process-kill', alternatives: { unix: 'kill', powershell: 'Stop-Process' }},
1613
- 'findstr': { category: 'text-search', alternatives: { unix: 'grep', powershell: 'Select-String' }}
1614
- };
1615
-
1616
- // PowerShell commands
1617
- const powershellCommands = {
1618
- 'get-childitem': { category: 'file-listing', alternatives: { unix: 'ls', cmd: 'dir' }},
1619
- 'get-content': { category: 'file-viewing', alternatives: { unix: 'cat', cmd: 'type' }},
1620
- 'copy-item': { category: 'file-copy', alternatives: { unix: 'cp', cmd: 'copy' }},
1621
- 'move-item': { category: 'file-move', alternatives: { unix: 'mv', cmd: 'move' }},
1622
- 'remove-item': { category: 'file-delete', alternatives: { unix: 'rm', cmd: 'del' }},
1623
- 'get-process': { category: 'process-list', alternatives: { unix: 'ps', cmd: 'tasklist' }},
1624
- 'stop-process': { category: 'process-kill', alternatives: { unix: 'kill', cmd: 'taskkill' }}
1625
- };
1626
-
1627
- // Determine command type
1628
- let commandType = 'unknown';
1629
- let category = 'unknown';
1630
- let alternatives = {};
1631
-
1632
- if (unixCommands[firstWord]) {
1633
- commandType = 'unix';
1634
- category = unixCommands[firstWord].category;
1635
- alternatives = unixCommands[firstWord].alternatives;
1636
- } else if (cmdCommands[firstWord]) {
1637
- commandType = 'windows-cmd';
1638
- category = cmdCommands[firstWord].category;
1639
- alternatives = cmdCommands[firstWord].alternatives;
1640
- } else if (powershellCommands[firstWord]) {
1641
- commandType = 'powershell';
1642
- category = powershellCommands[firstWord].category;
1643
- alternatives = powershellCommands[firstWord].alternatives;
1644
- } else {
1645
- // Check for built-in commands that work everywhere
1646
- const universalCommands = ['echo', 'cd', 'exit', 'help'];
1647
- if (universalCommands.includes(firstWord)) {
1648
- commandType = 'universal';
1649
- category = 'builtin';
1650
- } else {
1651
- commandType = 'unknown';
1652
- confidence = 0.3;
1653
- }
1654
- }
1655
-
1656
- // Check for syntax issues
1657
- if (command.includes("'") && !command.includes('"')) {
1658
- issues.push('single-quotes-problematic');
1659
- }
1660
- if (command.includes('/') && !command.includes('\\') && !command.includes('http') && command.includes('>')) {
1661
- issues.push('unix-style-paths');
1662
- }
1663
- if (command.includes('\\n') || command.includes('\\t')) {
1664
- issues.push('escape-sequences');
1665
- }
1666
- if (command.includes(' && ') || command.includes(' || ') || command.includes(';')) {
1667
- issues.push('command-chaining');
1668
- }
1669
-
1670
- return {
1671
- type: commandType,
1672
- category: category,
1673
- alternatives: alternatives,
1674
- issues: issues,
1675
- confidence: confidence,
1676
- firstWord: firstWord,
1677
- fullCommand: command
1678
- };
1679
- }
1680
-
1681
- /**
1682
- * Check if classified command is compatible with terminal
1683
- * @param {Object} analysis - Command analysis
1684
- * @param {string} terminal - Target terminal type
1685
- * @returns {boolean} Whether compatible
1686
- * @private
1687
- */
1688
- isCommandCompatibleWithTerminal(analysis, terminal) {
1689
- switch (terminal) {
1690
- case 'cmd':
1691
- if (analysis.type === 'unix') return false;
1692
- if (analysis.issues.includes('single-quotes-problematic')) return false;
1693
- if (analysis.issues.includes('unix-style-paths')) return false;
1694
- return analysis.type === 'windows-cmd' || analysis.type === 'universal';
1695
-
1696
- case 'powershell':
1697
- if (analysis.type === 'unix' && !analysis.alternatives.powershell) return false;
1698
- return true; // PowerShell is quite compatible
1699
-
1700
- case 'bash':
1701
- if (analysis.type === 'windows-cmd') return false;
1702
- return analysis.type === 'unix' || analysis.type === 'universal';
1703
-
1704
- default:
1705
- return false;
1706
- }
1707
- }
1708
-
1709
- /**
1710
- * Translate command to Windows CMD syntax
1711
- * @param {string} command - Original command
1712
- * @returns {string} Windows CMD equivalent
1713
- * @private
1714
- */
1715
- translateToWindowsCmd(command) {
1716
- let translated = command;
1717
-
1718
- // Common Unix to Windows translations
1719
- const translations = new Map([
1720
- // Directory listing
1721
- [/^ls\s*$/, 'dir'],
1722
- [/^ls\s+-la?$/, 'dir'],
1723
- [/^ls\s+-l$/, 'dir'],
1724
- [/^ls\s+-a$/, 'dir /a'],
1725
-
1726
- // File operations
1727
- [/^cat\s+(.+)$/, 'type $1'],
1728
- [/^cp\s+(.+)\s+(.+)$/, 'copy $1 $2'],
1729
- [/^mv\s+(.+)\s+(.+)$/, 'move $1 $2'],
1730
- [/^rm\s+(.+)$/, 'del $1'],
1731
- [/^mkdir\s+(.+)$/, 'mkdir $1'],
1732
- [/^rmdir\s+(.+)$/, 'rmdir $1'],
1733
-
1734
- // Process management
1735
- [/^ps\s*$/, 'tasklist'],
1736
- [/^kill\s+(.+)$/, 'taskkill /PID $1'],
1737
-
1738
- // Environment
1739
- [/^pwd\s*$/, 'cd'],
1740
- [/^whoami\s*$/, 'echo %USERNAME%'],
1741
-
1742
- // Network
1743
- [/^ping\s+(.+)$/, 'ping $1'],
1744
- [/^wget\s+(.+)$/, 'curl -O $1'],
1745
- [/^curl\s+(.+)$/, 'curl $1']
1746
- ]);
1747
-
1748
- // Apply translations
1749
- for (const [regex, replacement] of translations) {
1750
- if (regex.test(translated)) {
1751
- translated = translated.replace(regex, replacement);
1752
- break;
1753
- }
1754
- }
1755
-
1756
- // Fix echo command with single quotes
1757
- translated = translated.replace(/echo\s+'([^']+)'\s*>/g, 'echo "$1" >');
1758
- translated = translated.replace(/echo\s+'([^']+)'$/g, 'echo "$1"');
1759
-
1760
- // Fix multi-line echo commands
1761
- if (translated.includes("echo '") && translated.includes("\\n")) {
1762
- // Convert multi-line echo to multiple echo commands or use different approach
1763
- const match = translated.match(/echo\s+'(.+?)'\s*>\s*(.+)$/);
1764
- if (match) {
1765
- const content = match[1].replace(/\\n/g, '\n');
1766
- const filename = match[2];
1767
- const lines = content.split('\n');
1768
-
1769
- // Create a batch file approach for multi-line content
1770
- translated = `(${lines.map(line => `echo ${line}`).join(' & ')}) > ${filename}`;
1771
- }
1772
- }
1773
-
1774
- this.logger?.info('Command translated for Windows CMD', {
1775
- original: command,
1776
- translated: translated
1777
- });
1778
-
1779
- return translated;
1780
- }
1781
-
1782
- /**
1783
- * Translate command to PowerShell syntax
1784
- * @param {string} command - Original command
1785
- * @returns {string} PowerShell equivalent
1786
- * @private
1787
- */
1788
- translateToPowerShell(command) {
1789
- let translated = command;
1790
-
1791
- const translations = new Map([
1792
- [/^ls\s*$/, 'Get-ChildItem'],
1793
- [/^ls\s+-la?$/, 'Get-ChildItem -Force'],
1794
- [/^cat\s+(.+)$/, 'Get-Content $1'],
1795
- [/^cp\s+(.+)\s+(.+)$/, 'Copy-Item $1 $2'],
1796
- [/^mv\s+(.+)\s+(.+)$/, 'Move-Item $1 $2'],
1797
- [/^rm\s+(.+)$/, 'Remove-Item $1'],
1798
- [/^pwd\s*$/, 'Get-Location'],
1799
- [/^ps\s*$/, 'Get-Process']
1800
- ]);
1801
-
1802
- for (const [regex, replacement] of translations) {
1803
- if (regex.test(translated)) {
1804
- translated = translated.replace(regex, replacement);
1805
- break;
1806
- }
1807
- }
1808
-
1809
- this.logger?.info('Command translated for PowerShell', {
1810
- original: command,
1811
- translated: translated
1812
- });
1813
-
1814
- return translated;
1815
- }
1816
-
1817
- /**
1818
- * Translate command to Bash syntax
1819
- * @param {string} command - Original command
1820
- * @returns {string} Bash equivalent
1821
- * @private
1822
- */
1823
- translateToBash(command) {
1824
- // For bash, mainly fix Windows-specific commands
1825
- let translated = command;
1826
-
1827
- const translations = new Map([
1828
- [/^dir\s*$/, 'ls'],
1829
- [/^dir\s+\/a$/, 'ls -a'],
1830
- [/^type\s+(.+)$/, 'cat $1'],
1831
- [/^copy\s+(.+)\s+(.+)$/, 'cp $1 $2'],
1832
- [/^move\s+(.+)\s+(.+)$/, 'mv $1 $2'],
1833
- [/^del\s+(.+)$/, 'rm $1'],
1834
- [/^tasklist\s*$/, 'ps'],
1835
- [/^cd\s*$/, 'pwd']
1836
- ]);
1837
-
1838
- for (const [regex, replacement] of translations) {
1839
- if (regex.test(translated)) {
1840
- translated = translated.replace(regex, replacement);
1841
- break;
1842
- }
1843
- }
1844
-
1845
- return translated;
1846
- }
1847
-
1848
- /**
1849
- * Resource cleanup
1850
- * @param {string} operationId - Operation identifier
1851
- */
1852
- async cleanup(operationId) {
1853
- // Clean up any hanging processes or temporary resources
1854
- // This would be expanded based on specific needs
1855
- }
1856
-
1857
- /**
1858
- * Phase 3 & 4: Start a background command
1859
- * @param {string} command - Command to execute
1860
- * @param {string} workingDir - Working directory
1861
- * @param {Object} options - Execution options
1862
- * @returns {Promise<Object>} Command info with commandId
1863
- */
1864
- async startBackgroundCommand(command, workingDir, options = {}) {
1865
- const { agentId, context } = options;
1866
-
1867
- if (!agentId) {
1868
- throw new Error('agentId is required for background commands');
1869
- }
1870
-
1871
- // Check agent resource limits (only count active commands: running or waiting_for_input)
1872
- const agentCommands = this.getAgentCommands(agentId);
1873
- const activeAgentCommands = agentCommands.filter(cmd =>
1874
- cmd.state === 'running' || cmd.state === 'waiting_for_input'
1875
- );
1876
- if (activeAgentCommands.length >= this.MAX_BACKGROUND_COMMANDS_PER_AGENT) {
1877
- throw new Error(`Maximum background commands per agent exceeded (${this.MAX_BACKGROUND_COMMANDS_PER_AGENT})`);
1878
- }
1879
-
1880
- // Check global resource limits (only count active commands)
1881
- const allCommands = Array.from(this.commandTracker.values());
1882
- const activeGlobalCommands = allCommands.filter(cmd =>
1883
- cmd.state === 'running' || cmd.state === 'waiting_for_input'
1884
- );
1885
- if (activeGlobalCommands.length >= this.MAX_BACKGROUND_COMMANDS_GLOBAL) {
1886
- throw new Error(`Maximum global background commands exceeded (${this.MAX_BACKGROUND_COMMANDS_GLOBAL})`);
1887
- }
1888
-
1889
- // Generate unique command ID
1890
- const commandId = `${agentId}-cmd-${Date.now()}-${++this.commandIdCounter}`;
1891
-
1892
- // Translate command
1893
- const originalCommand = command;
1894
- let translatedCommand;
1895
-
1896
- try {
1897
- translatedCommand = await this.translateCommand(command, {
1898
- agentId,
1899
- toolsRegistry: context?.toolsRegistry,
1900
- messageProcessor: context?.messageProcessor,
1901
- aiService: context?.aiService,
1902
- apiKey: context?.apiKey,
1903
- customApiKeys: context?.customApiKeys,
1904
- platformProvided: context?.platformProvided
1905
- });
1906
- } catch (error) {
1907
- this.logger?.warn('Command translation failed, using original command', {
1908
- originalCommand,
1909
- error: error.message
1910
- });
1911
- translatedCommand = command;
1912
- }
1913
-
1914
- this.logger?.info(`Starting background command: ${translatedCommand}`, {
1915
- commandId,
1916
- agentId,
1917
- originalCommand,
1918
- workingDirectory: workingDir
1919
- });
1920
-
1921
- // Spawn process with stdin kept open
1922
- let childProcess;
1923
-
1924
- if (this.detectedTerminal === 'cmd' || this.detectedTerminal === 'powershell') {
1925
- const shell = this.detectedTerminal === 'powershell' ? 'powershell' : 'cmd';
1926
- const shellArgs = this.detectedTerminal === 'powershell'
1927
- ? ['-Command', translatedCommand]
1928
- : ['/c', translatedCommand];
1929
-
1930
- childProcess = spawn(shell, shellArgs, {
1931
- cwd: workingDir,
1932
- env: { ...process.env },
1933
- windowsHide: true,
1934
- stdio: ['pipe', 'pipe', 'pipe'] // Keep stdin open
1935
- });
1936
- } else {
1937
- childProcess = spawn('sh', ['-c', translatedCommand], {
1938
- cwd: workingDir,
1939
- env: { ...process.env },
1940
- stdio: ['pipe', 'pipe', 'pipe'] // Keep stdin open
1941
- });
1942
- }
1943
-
1944
- // Initialize command tracking
1945
- const commandInfo = {
1946
- commandId,
1947
- agentId,
1948
- pid: childProcess.pid,
1949
- command: originalCommand,
1950
- translatedCommand,
1951
- workingDirectory: workingDir,
1952
- startTime: new Date().toISOString(),
1953
- state: 'running',
1954
- exitCode: null,
1955
- stdoutBuffer: '',
1956
- stderrBuffer: '',
1957
- lastOutputTime: Date.now(),
1958
- promptDetected: null,
1959
- process: childProcess
1960
- };
1961
-
1962
- this.commandTracker.set(commandId, commandInfo);
1963
-
1964
- // Set up stream handlers
1965
- childProcess.stdout.on('data', (chunk) => {
1966
- const data = chunk.toString();
1967
- commandInfo.stdoutBuffer += data;
1968
- commandInfo.lastOutputTime = Date.now();
1969
-
1970
- // Check for prompts
1971
- if (!commandInfo.promptDetected) {
1972
- const detection = this.promptDetector.detectPrompt(commandInfo.stdoutBuffer, 'stdout');
1973
- if (detection) {
1974
- commandInfo.promptDetected = detection;
1975
- commandInfo.state = 'waiting_for_input';
1976
- this.logger?.info('Prompt detected in background command', {
1977
- commandId,
1978
- agentId,
1979
- type: detection.type,
1980
- matchedText: detection.matchedText
1981
- });
1982
- }
1983
- }
1984
- });
1985
-
1986
- childProcess.stderr.on('data', (chunk) => {
1987
- const data = chunk.toString();
1988
- commandInfo.stderrBuffer += data;
1989
- commandInfo.lastOutputTime = Date.now();
1990
-
1991
- // Check for prompts in stderr too
1992
- if (!commandInfo.promptDetected) {
1993
- const detection = this.promptDetector.detectPrompt(commandInfo.stderrBuffer, 'stderr');
1994
- if (detection) {
1995
- commandInfo.promptDetected = detection;
1996
- commandInfo.state = 'waiting_for_input';
1997
- this.logger?.info('Prompt detected in background command stderr', {
1998
- commandId,
1999
- agentId,
2000
- type: detection.type,
2001
- matchedText: detection.matchedText
2002
- });
2003
- }
2004
- }
2005
- });
2006
-
2007
- childProcess.on('exit', (code, signal) => {
2008
- commandInfo.exitCode = code;
2009
- commandInfo.state = code === 0 ? 'completed' : 'failed';
2010
- commandInfo.endTime = new Date().toISOString();
2011
-
2012
- this.logger?.info('Background command exited', {
2013
- commandId,
2014
- agentId,
2015
- exitCode: code,
2016
- signal,
2017
- state: commandInfo.state
2018
- });
2019
- });
2020
-
2021
- childProcess.on('error', (error) => {
2022
- commandInfo.state = 'failed';
2023
- commandInfo.error = error.message;
2024
- commandInfo.endTime = new Date().toISOString();
2025
-
2026
- this.logger?.error('Background command error', {
2027
- commandId,
2028
- agentId,
2029
- error: error.message
2030
- });
2031
- });
2032
-
2033
- // Return command info
2034
- return {
2035
- success: true,
2036
- commandId,
2037
- pid: childProcess.pid,
2038
- command: originalCommand,
2039
- translatedCommand,
2040
- workingDirectory: workingDir,
2041
- message: `Background command started with ID: ${commandId}`
2042
- };
2043
- }
2044
-
2045
- /**
2046
- * Phase 3: Send input to a background command (stdin)
2047
- * @param {string} commandId - Command identifier
2048
- * @param {string} input - Input to send (will add newline automatically)
2049
- * @param {string} agentId - Agent identifier for ownership validation
2050
- * @returns {Object} Result
2051
- */
2052
- sendInput(commandId, input, agentId) {
2053
- // Validate ownership
2054
- const commandInfo = this.validateCommandOwnership(commandId, agentId);
2055
-
2056
- if (commandInfo.state === 'completed' || commandInfo.state === 'failed') {
2057
- throw new Error(`Cannot send input to ${commandInfo.state} command`);
2058
- }
2059
-
2060
- if (!commandInfo.process || commandInfo.process.killed) {
2061
- throw new Error('Command process is not running');
2062
- }
2063
-
2064
- // Send input with newline
2065
- const inputWithNewline = input.endsWith('\n') ? input : input + '\n';
2066
- commandInfo.process.stdin.write(inputWithNewline);
2067
-
2068
- this.logger?.info('Input sent to background command', {
2069
- commandId,
2070
- agentId,
2071
- inputLength: input.length
2072
- });
2073
-
2074
- // Update state if it was waiting
2075
- if (commandInfo.state === 'waiting_for_input') {
2076
- commandInfo.state = 'running';
2077
- commandInfo.promptDetected = null; // Clear prompt after answering
2078
- }
2079
-
2080
- return {
2081
- success: true,
2082
- commandId,
2083
- message: 'Input sent successfully'
2084
- };
2085
- }
2086
-
2087
- /**
2088
- * Phase 4: Get status of a background command
2089
- * @param {string} commandId - Command identifier
2090
- * @param {string} agentId - Agent identifier for ownership validation
2091
- * @returns {Object} Command status
2092
- */
2093
- getCommandStatus(commandId, agentId) {
2094
- const commandInfo = this.validateCommandOwnership(commandId, agentId);
2095
-
2096
- const timeSinceLastOutput = Date.now() - commandInfo.lastOutputTime;
2097
-
2098
- return {
2099
- success: true,
2100
- commandId,
2101
- pid: commandInfo.pid,
2102
- command: commandInfo.command,
2103
- state: commandInfo.state,
2104
- exitCode: commandInfo.exitCode,
2105
- startTime: commandInfo.startTime,
2106
- endTime: commandInfo.endTime,
2107
- workingDirectory: commandInfo.workingDirectory,
2108
- stdout: commandInfo.stdoutBuffer,
2109
- stderr: commandInfo.stderrBuffer,
2110
- stdoutLength: commandInfo.stdoutBuffer.length,
2111
- stderrLength: commandInfo.stderrBuffer.length,
2112
- lastOutputTime: commandInfo.lastOutputTime,
2113
- timeSinceLastOutput,
2114
- promptDetected: !!commandInfo.promptDetected,
2115
- promptInfo: commandInfo.promptDetected || undefined
2116
- };
2117
- }
2118
-
2119
- /**
2120
- * Phase 4: Kill a background command
2121
- * @param {string} commandId - Command identifier
2122
- * @param {string} agentId - Agent identifier for ownership validation
2123
- * @returns {Object} Result
2124
- */
2125
- killCommand(commandId, agentId) {
2126
- const commandInfo = this.validateCommandOwnership(commandId, agentId);
2127
-
2128
- if (commandInfo.state === 'completed' || commandInfo.state === 'failed') {
2129
- return {
2130
- success: true,
2131
- commandId,
2132
- message: 'Command already terminated',
2133
- state: commandInfo.state
2134
- };
2135
- }
2136
-
2137
- if (commandInfo.process && !commandInfo.process.killed) {
2138
- commandInfo.process.kill('SIGTERM');
2139
-
2140
- // If SIGTERM doesn't work, try SIGKILL after 5s
2141
- setTimeout(() => {
2142
- if (commandInfo.process && !commandInfo.process.killed) {
2143
- commandInfo.process.kill('SIGKILL');
2144
- }
2145
- }, 5000);
2146
-
2147
- this.logger?.info('Background command killed', {
2148
- commandId,
2149
- agentId
2150
- });
2151
-
2152
- return {
2153
- success: true,
2154
- commandId,
2155
- message: 'Command killed successfully'
2156
- };
2157
- }
2158
-
2159
- return {
2160
- success: false,
2161
- commandId,
2162
- error: 'Command process not found or already killed'
2163
- };
2164
- }
2165
-
2166
- /**
2167
- * Phase 4: List all commands for an agent
2168
- * @param {string} agentId - Agent identifier
2169
- * @returns {Array} List of command info objects
2170
- */
2171
- listAgentCommands(agentId) {
2172
- const commands = this.getAgentCommands(agentId);
2173
-
2174
- return commands.map(cmd => ({
2175
- commandId: cmd.commandId,
2176
- command: cmd.command,
2177
- state: cmd.state,
2178
- pid: cmd.pid,
2179
- exitCode: cmd.exitCode,
2180
- startTime: cmd.startTime,
2181
- endTime: cmd.endTime,
2182
- promptDetected: !!cmd.promptDetected,
2183
- timeSinceLastOutput: Date.now() - cmd.lastOutputTime
2184
- }));
2185
- }
2186
-
2187
- /**
2188
- * Phase 4: Get agent's commands (helper method)
2189
- * @param {string} agentId - Agent identifier
2190
- * @returns {Array} Array of command info objects
2191
- * @private
2192
- */
2193
- getAgentCommands(agentId) {
2194
- return Array.from(this.commandTracker.values())
2195
- .filter(cmd => cmd.agentId === agentId);
2196
- }
2197
-
2198
- /**
2199
- * Phase 4: Validate command ownership
2200
- * @param {string} commandId - Command identifier
2201
- * @param {string} agentId - Agent identifier
2202
- * @returns {Object} Command info if valid
2203
- * @throws {Error} If command not found or access denied
2204
- * @private
2205
- */
2206
- validateCommandOwnership(commandId, agentId) {
2207
- const commandInfo = this.commandTracker.get(commandId);
2208
-
2209
- if (!commandInfo) {
2210
- throw new Error(`Command not found: ${commandId}`);
2211
- }
2212
-
2213
- if (commandInfo.agentId !== agentId) {
2214
- throw new Error(`Access denied: Command belongs to agent ${commandInfo.agentId}`);
2215
- }
2216
-
2217
- return commandInfo;
2218
- }
2219
-
2220
- /**
2221
- * Phase 4: Cleanup all commands for an agent (called when agent is deleted)
2222
- * @param {string} agentId - Agent identifier
2223
- * @returns {Promise<Object>} Cleanup result
2224
- */
2225
- async cleanupAgent(agentId) {
2226
- const commands = this.getAgentCommands(agentId);
2227
-
2228
- let killedCount = 0;
2229
- let removedCount = 0;
2230
-
2231
- for (const commandInfo of commands) {
2232
- // Kill process if still running
2233
- if (commandInfo.process && !commandInfo.process.killed) {
2234
- commandInfo.process.kill('SIGTERM');
2235
- killedCount++;
2236
-
2237
- // Force kill after delay
2238
- setTimeout(() => {
2239
- if (commandInfo.process && !commandInfo.process.killed) {
2240
- commandInfo.process.kill('SIGKILL');
2241
- }
2242
- }, 3000);
2243
- }
2244
-
2245
- // Remove from tracker
2246
- this.commandTracker.delete(commandInfo.commandId);
2247
- removedCount++;
2248
- }
2249
-
2250
- this.logger?.info('Agent commands cleaned up', {
2251
- agentId,
2252
- killedCount,
2253
- removedCount
2254
- });
2255
-
2256
- return {
2257
- success: true,
2258
- agentId,
2259
- killedCount,
2260
- removedCount,
2261
- message: `Cleaned up ${removedCount} commands for agent ${agentId}`
2262
- };
2263
- }
2264
-
2265
- /**
2266
- * Phase 4: Auto-cleanup stale completed commands
2267
- * @returns {Object} Cleanup result
2268
- */
2269
- cleanupStaleCommands() {
2270
- const now = Date.now();
2271
- let removedCount = 0;
2272
-
2273
- for (const [commandId, commandInfo] of this.commandTracker.entries()) {
2274
- // Only clean up completed/failed commands
2275
- if (commandInfo.state !== 'completed' && commandInfo.state !== 'failed') {
2276
- continue;
2277
- }
2278
-
2279
- // Check age
2280
- const startTime = new Date(commandInfo.startTime).getTime();
2281
- const ageMinutes = (now - startTime) / 1000 / 60;
2282
-
2283
- if (ageMinutes > this.MAX_COMMAND_AGE_MINUTES) {
2284
- this.commandTracker.delete(commandId);
2285
- removedCount++;
2286
- }
2287
- }
2288
-
2289
- if (removedCount > 0) {
2290
- this.logger?.info('Stale commands cleaned up', {
2291
- removedCount,
2292
- ageThresholdMinutes: this.MAX_COMMAND_AGE_MINUTES
2293
- });
2294
- }
2295
-
2296
- return {
2297
- success: true,
2298
- removedCount,
2299
- message: `Cleaned up ${removedCount} stale commands`
2300
- };
2301
- }
2302
- }
2303
-
2304
- export default TerminalTool;
1
+ const a0_0xc176c6=a0_0x4a54;(function(_0x1bb787,_0x4162be){const _0x7cfd03=a0_0x4a54,_0x4a526e=_0x1bb787();while(!![]){try{const _0x12465f=parseInt(_0x7cfd03(0x170))/0x1*(parseInt(_0x7cfd03(0x19c))/0x2)+parseInt(_0x7cfd03(0xd5))/0x3+-parseInt(_0x7cfd03(0xe8))/0x4+-parseInt(_0x7cfd03(0x13b))/0x5+parseInt(_0x7cfd03(0x17d))/0x6*(-parseInt(_0x7cfd03(0x1c0))/0x7)+parseInt(_0x7cfd03(0xde))/0x8*(parseInt(_0x7cfd03(0x18d))/0x9)+parseInt(_0x7cfd03(0x177))/0xa;if(_0x12465f===_0x4162be)break;else _0x4a526e['push'](_0x4a526e['shift']());}catch(_0x3db251){_0x4a526e['push'](_0x4a526e['shift']());}}}(a0_0x5f48,0xa4e1f));function a0_0x4a54(_0x39f5b1,_0x2d64c0){_0x39f5b1=_0x39f5b1-0xaf;const _0x5f48b0=a0_0x5f48();let _0x4a54e8=_0x5f48b0[_0x39f5b1];if(a0_0x4a54['pdVauq']===undefined){var _0x5815d5=function(_0x5ea3bf){const _0x187eda='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x131d98='',_0x4caa1b='';for(let _0x3c91a6=0x0,_0x5eb71c,_0x38c167,_0x1093e2=0x0;_0x38c167=_0x5ea3bf['charAt'](_0x1093e2++);~_0x38c167&&(_0x5eb71c=_0x3c91a6%0x4?_0x5eb71c*0x40+_0x38c167:_0x38c167,_0x3c91a6++%0x4)?_0x131d98+=String['fromCharCode'](0xff&_0x5eb71c>>(-0x2*_0x3c91a6&0x6)):0x0){_0x38c167=_0x187eda['indexOf'](_0x38c167);}for(let _0x304a46=0x0,_0x48b21a=_0x131d98['length'];_0x304a46<_0x48b21a;_0x304a46++){_0x4caa1b+='%'+('00'+_0x131d98['charCodeAt'](_0x304a46)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x4caa1b);};a0_0x4a54['PLatlx']=_0x5815d5,a0_0x4a54['iXXxuZ']={},a0_0x4a54['pdVauq']=!![];}const _0x2bc38a=_0x5f48b0[0x0],_0x2df9c2=_0x39f5b1+_0x2bc38a,_0x33bfc1=a0_0x4a54['iXXxuZ'][_0x2df9c2];return!_0x33bfc1?(_0x4a54e8=a0_0x4a54['PLatlx'](_0x4a54e8),a0_0x4a54['iXXxuZ'][_0x2df9c2]=_0x4a54e8):_0x4a54e8=_0x33bfc1,_0x4a54e8;}import{BaseTool}from'./baseTool.js';function a0_0x5f48(){const _0x4d4c00=['Dw5PEa','AM9PBG','z2v0qwDLBNrdB21Tyw5KCW','CMvSyxrPDMu','C3vJy2vZCW','D2fYBG','zgv0zwn0uhjVBxb0','DgfZA2XPC3q','zxHPDenVzgu','zgLZAY11C2fNzq','yxjJAgL2zq','Bg9N','yxn5BMm','ugfZC3bOCMfZzsbWCM9TChq','BhmGlwe','igfJDgLVBNmGzMfPBgvK','igL0zw1ZigLUia','AxndB21Tyw5Kq29TCgf0AwjSzq','zw52','mwnkBLj6rG','r2v0lvDTAu9IAMvJDcaTq2XHC3mGv2LUmZjFtg9NAwnHBerPC2S','Bwf4q29TBwfUzefNzu1PBNv0zxm','cI0GvgfYz2v0ifrLCM1PBMfSoIa','Aw5MBW','u2vSzwn0Aw9UihbYB21WDa','C29Tzq','nda2ndCWyvPjzeLp','CM0GlxjMic8','Dg9ju09tDhjPBMC','q29TBwfUzcbWCM9JzxnZig5VDcbMB3vUzcbVCIbHBhjLywr5igTPBgXLza','Bw92zq','ugfZC3DVCMqGChjVBxb0','nLbZsgfQBq','A2LSBa','twf4Aw11BsbNBg9IywWGyMfJA2DYB3vUzcbJB21Tyw5KCYbLEgnLzwrLzcaO','Ahr0Cc1JBgLLBNq','q29TBwfUzcbLCNjVCIbJAhvUAZOG','ufnnB2r1BgvqyxrO','zxjYB3i','cGPsrvfvsvjftuvovfm6cJeUie1HA2uGDgHLignVBw1HBMqGD29YAYbJB3jYzwn0BhKGAw4G','cI0Gq29TCgf0AwjPBgL0EsbjC3n1zxm6ia','zxHPDa','quKGDhjHBNnSyxrPB24GCMv0DxjUzwqGC2fTzsbJB21Tyw5K','y2XLyw51Ca','z2v0','tufyx0jbq0ThuK9vtKrFq09ntuforfnFuevsx0fhru5u','y29TBwfUzfrYywnRzxi','zxHLy3v0Aw9UvgLTzq','mJuYB2PbvfD4','Bwf4qMfJA2DYB3vUzenVBw1HBMrZr2XVyMfS','C3rKAw4','q29TBwfUzcb0CMfUC2XHDgLVBIbMywLSzwqSihvZAw5Nig9YAwDPBMfSignVBw1HBMq','Bwf0y2HLzfrLEhq','C3rHCNruAw1L','ihbLCIbHz2vUDcWG','Dg9VBhnszwDPC3rYEq','zgLYzwn0B3j5qwnJzxnZtwfUywDLCG','qwnJzxnZigrLBMLLzdOG','y3vZDg9TqxbPs2v5CW','cI0Gq2f0zwDVCNK6ia','zMLSzs1KzwXLDgu','CgXHDgzVCM1uExbL','BgLZDefNzw50q29TBwfUzhm','mteYnZK0oevHqu10sW','ihWG','zM9YBwf0','A2v5ChjLC3m','D29YA2LUz0rPCMvJDg9YEq','lwnTzc0','CMvWBgfJzq','y29WEq','CMvZB2X2zq','zw5KvgLTzq','CgXHDgzVCM1qCM92AwrLza','r2v0lvbYB2nLC3mGFcbtDg9WlvbYB2nLC3m','zMLSzs1JCMvHDgu','zgf0yq','zgLYzwn0B3j5','BwTKAxiGjde','C3rHCNrZv2L0Aa','twvHC3vYzs1pyMPLy3q','C291CMnLia','vxnLCM5HBwuGChjVBxb0','C2LUz2XLlxf1B3rLCY1WCM9IBgvTyxrPyW','y3jLyxrLrgLYzwn0B3j5','C3bSAxq','ChjVBxb0ugf0DgvYBNm','r2v0lvbYB2nLC3mGFcbtB3j0lu9IAMvJDcbdufu','AxntEw1IB2XPy0XPBMS','C2XPy2u','sw52B2TLlvDLyLjLCxvLC3q','y3vYBcaKmq','DgLTzw91Da','ywn0Aw9UCW','ChjVy2vZCW','CgLUzW','D2HPBguG','u2v0lufJBa','Bw9Yzq','mJqWmJGYn3reBw1xCa','qMfJA2DYB3vUzcbJB21Tyw5Kigv4AxrLza','yNvPBhrPBG','y3vYBa','zxH0CMfJDenVBNrLBNq','ywXSB3DLza','oIb1BMTUB3DUigfJDgLVBIb0ExbLoIa','zgLYzwn0B3j5lwn1CNjLBNq','uhjLC3mGzw50zxi','zxHLy3v0zq','uhjLC3mGyw55igTLEq','zwnOBYaI','DMfSAwrHDgvdB21Tyw5Kt3DUzxjZAgLW','q29TChjLC3mTqxjJAgL2zq','DgfZA2TPBgW','q3jLyxrLzcbKAxjLy3rVCNK6ia','r2v0lvDTAu9IAMvJDcaTq2XHC3mGv2LUmZjFugH5C2LJywXnzw1VCNK','q29TBwfUzcbMywLSzwqGD2L0AcbLEgL0ignVzguG','Aw5KzxG','zgvSicqX','zxHLy3v0zunVBw1HBMq','y3jLyxrLlwrPCMvJDg9YEq','C3rKB3v0','oGOkt1jjr0LoquWGq09ntufordOkygbGcG','rMfPBgvKihrVignOyw5NzsbKAxjLy3rVCNKGDg8G','DhjHBNnSyxrLvg9qB3DLCLnOzwXS','BM93','yw5HBhL6zunVBw1HBMrdB21WyxrPyMLSAxr5','zgvZy3jPChrPB24','y29TCgf0AwjSzq','Cg93zxjZAgvSBcaTyW','vxnPBMCGquKGDhjHBNnSyxrPB24','zNn1DgLSihzVBhvTzsbKAxnRzNjLzq','qMfJA2DYB3vUzcbJB21Tyw5Kihn0yxj0zwqGD2L0AcbjrdOG','DMfSDwvZ','oIbJB21Tyw5KigLZigjSB2nRzwqGzM9YihnLy3vYAxr5oIa','C2H1DgrVD24','zgvSic9Mic9X','yMXVy2TLzenVBw1HBMrZ','CMvHC29U','zgv0zwn0zwruzxjTAw5HBa','DgfRzw93BG','CgLUzYaKmq','zMLUzcaVyW','zgLYzwn0B3j5lwrLBgv0zq','oIb0ExbLigLZihjLCxvPCMvK','z2v0u3vWCg9YDgvKqwn0Aw9UCW','zgvMia','BwfW','zMLSzs1SAxn0Aw5N','zwnOBYaIjdeI','C3rHy2S','zgLY','C2vSzwn0Aw9U','tufyx0nptu1btKrFquDfx01jtLvurvm','y21K','zM9Yia','igfJDgLVBNmGy29TCgXLDgvKihn1y2nLC3nMDwXSEq','rMfPBgvKihrVigXPC3qGzgLYzwn0B3j5ia','zNvUy3rPB24G','AgfSDa','ChjVy2vZCY1RAwXS','q29TBwfUzcbVDxrWDxqGy2H1BMS6ia','y3vYBcaTtYaKmq','tufyx0jbq0ThuK9vtKrFq09ntuforfnFr0XpqKfm','AxnZDwvZ','sw5WDxqGC2vUDcb0BYbIywnRz3jVDw5KignVBw1HBMq','zMLSzq','Dgv4Dc1LzgL0','ywLtzxj2AwnL','Dhj1zq','q29WEs1jDgvTicqXicqY','DgvZDa','Dg9mB3DLCKnHC2u','Dw5RBM93BG','zw50CMLLCW','y2f0zwDVCNK','C2v0','ihX8ia','BgvUz3rO','u2vSzwn0lvn0CMLUzW','zMfPBgvK','AxneAxjLy3rVCNK','q2HHBMDLzcbKAxjLy3rVCNKGDg8G','uMvTB3zLluL0zw0','rxHLy3v0Aw5NignVBw1HBMq6ia','oIbJB21Tyw5KigLZihjLCxvPCMvKigzVCIbYDw4Ty29TBwfUza','zgv0zwn0sgfUzW','Bg9Nz2vY','ignVBw1HBMrZigzVCIbHz2vUDca','ChjVy2vZCY1SAxn0','y29UzMLYBwf0Aw9U','y29WEsaKmsaKmG','D29YA2LUz0rPCMvJDg9YAwvZ','q29TBwfUzcb0Aw1LzcbVDxqSigTPBgXPBMCGChjVy2vZCZOG','z2v0vgLTzq','u29YDc1pyMPLy3qGlvvUAxf1zq','y2f0','q29TBwfUzcbMywLSzwq6ia','C3vIC3rYAw5N','DxnLCM5HBwu','mty1nZK4mgjivM1lEa','CgXHDgzVCM0','BwTKAxi','icyG','ChjVBxb0rgv0zwn0B3i','Bw9YzsaRBG','zwnOBYaN','BgLZDc1KAxjLy3rVCNK','y2XLyw51Cfn0ywXLq29TBwfUzhm','mtu4odqWvwffrLvw','D2LUzg93CY1JBwq','zMLSzs12Awv3Aw5N','zw52AxjVBM1LBNq','u0Lhvevstq','ywXSB3DLzenVBw1HBMrZ','sw52B2TLlvjLC3rnzxrOB2q','A2LSBgvK','C3bLy2LMAwnjC3n1zxm','u3rHCNrPBMCGyMfJA2DYB3vUzcbJB21Tyw5KoIa','mJiYndGYohzNveHTwG','Dw5PEc1ZDhLSzs1WyxrOCW','y29TBwfUza','q29TBwfUzcbWCM9JzxnZigv4AxrLzdOG','r2v0lunOAwXKsxrLBsaTuMvJDxjZzsb8ie1Lyxn1CMuTt2jQzwn0','tM90igeGzgLYzwn0B3j5oIa','i2LUy2X1zgu','ChvZAa','zxH0CMfJDfrYyw5ZBgf0zwrdB21Tyw5K','CNvUlwnVBw1HBMq','y2HHBMDLlwrPCMvJDg9YEq','Cg93zxjZAgvSBcbdB21WCMvZCY1bCMnOAxzL','D2fPDgLUz19MB3jFAw5WDxq','BMfTzq','y3aGjdeGjdi','CgLK','C3LZDgvTAw5MBW','Bwf4q29Uy3vYCMvUDe9WzxjHDgLVBNm','C3rYAw5N','DgfZA2TPBgWGl1bjrcaKmq','u3rHBguGy29TBwfUzhmGy2XLyw5Lzcb1Ca','qwn0Aw9Uia','twvUDsbZzwXLy3rPB24','BwvZC2fNzq','r2v0lunOAwXKsxrLBq','y3vZDg9TvMfSAwrHDgvqyxjHBwv0zxjZ','yNvPBgruCMfUC2XHDgLVBLbYB21WDa','yxbPs2v5','AxntAw1WBgvdB21Tyw5K','C2vUzeLUChv0','Dgv4Dc1Kzwr1Cgu','qMfJA2DYB3vUzcbJB21Tyw5KigvYCM9Y','q3vYCMvUDcb3B3jRAw5NigrPCMvJDg9YEtOG','y29TBwfUzeHPC3rVCNK','A2LSBenVBw1HBMq','Aw5WDxq','y29TBwfUzenHDgvNB3j5','EwvZlw5V','CMvHzgrPCG','CM0Gjde','DhjHBNnSyxrLq29TBwfUzfDPDgHbsq','C3LZDgvTlwLUzM8','icyMia','BxyGjdeGjdi','z2v0q3vYCMvUDfDVCMTPBMDeAxjLy3rVCNK','qxr0zw1WDgLUzYbbssb0CMfUC2XHDgLVBIbMB3iGy29TCgXLEcbJB21Tyw5K','vgLTzw91DcbTDxn0igjLigjLDhDLzw4GmtaWmcbHBMqG','ywX0zxjUyxrPDMvZ','ywDLBNrjza','B2jQzwn0','Aw50zwDLCG','CgfYC2vqyxjHBwv0zxjZ','y29TBwfUzeLK','ksa+ia','tMv3luL0zw0Glvr5CguGrMLSzq','C3rHDgu','Dg9tDhjPBMC','BwvZC2fNzvbYB2nLC3nVCG','ChDK','igDSB2jHBaOTief1Dg8Tzgv0zwn0CYbWCM9TChrZigfUzcb1CgrHDgvZihn0yxrLihrVicD3ywL0Aw5Nx2zVCL9PBNb1DcCkcIOQz2v0q29TBwfUzfn0yxr1CYHJB21Tyw5KswqSigfNzw50swqPkIOklsbhzxqGCMvHBc10Aw1Lihn0yxr1CZOGCNvUBMLUzYWGD2fPDgLUz19MB3jFAw5WDxqSignVBxbSzxrLzcWGzMfPBgvKcI0GuMv0DxjUCYbZDgrVDxqVC3rKzxjYigj1zMzLCNmSigv4AxqGy29KzsWGDgLTzxn0yw1WCWOTifnOB3DZihbYB21WDcbKzxrLy3rPB24GAw5MBYbPzIbPBNrLCMfJDgL2zsbWCM9TChqGzgv0zwn0zwqkcIOQC2vUzeLUChv0kgnVBw1HBMrjzcWGAw5WDxqSigfNzw50swqPkIOklsbtzw5KigLUChv0ihrVignVBw1HBMqNCYbZDgrPBIaOyw5ZD2vYCYbWCM9TChrZkqOTief1Dg9TyxrPy2fSBhKGywrKCYbUzxDSAw5LigLMig5VDcbWCMvZzw50cI0GvxbKyxrLCYbZDgf0zsbMCM9TicD3ywL0Aw5Nx2zVCL9PBNb1DcCGDg8Gj3j1BM5PBMCNcGOQkMTPBgXdB21Tyw5KkgnVBw1HBMrjzcWGywDLBNrjzcKQkGOTifrLCM1PBMf0zsbIywnRz3jVDw5KignVBw1HBMqGkfnjr1rfuK0G4OAsifnjr0TjteWPcI0Gu2fMzsb0BYbJywXSig9UigfSCMvHzhKTy29TCgXLDgvKignVBw1HBMrZcGOQkMXPC3rbz2vUDenVBw1HBMrZkgfNzw50swqPkIOklsbmAxn0igfSBcbJB21Tyw5KCYaOCNvUBMLUzYbHBMqGy29TCgXLDgvKksbMB3iGywDLBNqklsbvC2vMDwWGzM9Yig1VBML0B3jPBMCGBxvSDgLWBguGyMfJA2DYB3vUzcbWCM9JzxnZzxmkcKjbq0ThuK9vtKqGq09ntuforcbxt1jlrKXpvZOkms4Gu3rHCNq6ignVBNn0ihTJB21Tyw5Kswr9id0GyxDHAxqGDgvYBwLUywWUC3rHCNrcywnRz3jVDw5Kq29TBwfUzcGNBNbTigLUC3rHBgWNlcbKAxiSihTHz2vUDeLKFsKkmI4Gv2fPDdOGvxnLigfNzw50lwrLBgf5ihrVB2WGDg8GD2fPDcb3AgLSzsbJB21Tyw5Kihj1BNmkmY4Gq2HLy2S6ignVBNn0ihn0yxr1CYa9ihrLCM1PBMfSlMDLDenVBw1HBMrtDgf0DxmOy29TBwfUzeLKlcbHz2vUDeLKkqO0lIbjzIbWCM9TChqGzgv0zwn0zwq6ihrLCM1PBMfSlNnLBMrjBNb1DcHJB21Tyw5KswqSicD5jYWGywDLBNrjzcKkns4GvMvYAwz5oIbdAgvJAYbZDgf0DxmUC3rHDguGpt09icDJB21WBgv0zwqNicyMihn0yxr1CY5LEgL0q29Kzsa9pt0GmaOkrvHbtvbmrvm6cKjHC2LJignVBw1HBMqGzxHLy3v0Aw9UoGPBDg9VBcbPzd0IDgvYBwLUywWIxqO8CNvUlwnVBw1HBMq+BNbTigLUC3rHBgW8l3j1BI1JB21Tyw5KpGPBl3rVB2XDcGPfEgvJDxrLign1CMWGy29TBwfUzdOkw3rVB2WGAwq9iNrLCM1PBMfSiL0kphj1BI1JB21Tyw5KpMn1CMWGlxmGAhr0Chm6lY9HCgKUz2L0AhvIlMnVBs96zw48l3j1BI1JB21Tyw5KpGPBl3rVB2XDcGPdAgfUz2uGzgLYzwn0B3j5igfUzcbYDw4Gy29TBwfUzdOkw3rVB2WGAwq9iNrLCM1PBMfSiL0kpgnOyw5Nzs1KAxjLy3rVCNK+lI4VzNjVBNrLBMq8l2nOyw5Nzs1KAxjLy3rVCNK+cJXYDw4Ty29TBwfUzd5UCg0GCNvUigj1AwXKpc9YDw4Ty29TBwfUzd4kwY90B29SxqOkugfJA2fNzsbTyw5Hz2vTzw50oGPBDg9VBcbPzd0IDgvYBwLUywWIxqO8CNvUlwnVBw1HBMq+CgLWigLUC3rHBgWGlxiGCMvXDwLYzw1LBNrZlNr4DdWVCNvUlwnVBw1HBMq+cLSVDg9VBf0kcKDPDcbVCgvYyxrPB25ZoGPBDg9VBcbPzd0IDgvYBwLUywWIxqO8CNvUlwnVBw1HBMq+z2L0ihn0yxr1CZWVCNvUlwnVBw1HBMq+cLSVDg9VBf0kcLT0B29SigLKpsj0zxjTAw5HBcjDcJXYDw4Ty29TBwfUzd5NAxqGywrKic48l3j1BI1JB21Tyw5KpGO8CNvUlwnVBw1HBMq+z2L0ignVBw1PDcaTBsaIvxbKyxrLigzPBgvZiJWVCNvUlwnVBw1HBMq+cLSVDg9VBf0kcKrPCMvJDg9YEsbVCgvYyxrPB25ZicHPzIbgAwXLu3LZDgvTihrVB2WGDw5HDMfPBgfIBguPoGPBDg9VBcbPzd0IDgvYBwLUywWIxqO8y3jLyxrLlwrPCMvJDg9YEt5IywnRzw5Kpc9JCMvHDguTzgLYzwn0B3j5pGPBl3rVB2XDcGPtrunvuKLuwsbot1rfuZOklsbeyw5NzxjVDxmGy29TBwfUzhmGyxjLigjSB2nRzwqGzM9YihnHzMv0EqOTienVBw1HBMrZigv4zwn1DguGAw4GAxnVBgf0zwqGzw52AxjVBM1LBNqklsbpDxrWDxqGAxmGy2fWDhvYzwqGyw5KihjLDhvYBMvKihnHzMvSEqOTieXVBMCTCNvUBMLUzYbJB21Tyw5KCYbTyxKGDgLTzsbVDxqGlsb1C2uGywDLBNqTzgvSyxKGDg9VBcb0BYb3ywL0cGPcrvnuifbsqunusunfuZOklsbvC2uGrMLSzvn5C3rLBsb0B29SigzVCIbMAwXLl2rPCMvJDg9YEsbJCMvHDgLVBIbHBMqGBwfUywDLBwvUDaOTifvZzsbuzxjTAw5HBcb0B29SigzVCIbJB21Tyw5KlwXPBMuGDxrPBgL0AwvZicHUCg0SigDPDcWGy3vYBcWGz3jLCcWGzxrJlIKklsbbzNrLCIbZDgfYDgLUzYbSB25Nlxj1BM5PBMCGy29TBwfUzhmSihvZzsbHz2vUDc1KzwXHEsb0B29SihrVihbHDxnLignOzwnRAw5NcI0GqwX3yxLZignOzwnRignVBw1HBMqGB3v0Chv0ihrVihzLCMLMEsbZDwnJzxnZcGPdvvjsru5uierjuKvdve9swtOkvgHLihrVB2WGBwfPBNrHAw5ZigeGy3vYCMvUDcb3B3jRAw5NigrPCMvJDg9YEsbJB250zxH0ihbLCIbHz2vUDc4kvxnLignOyw5Nzs1KAxjLy3rVCNKGDg8GBMf2AwDHDguSigfUzcbZDwjZzxf1zw50ignVBw1HBMrZihDPBgWGzxHLy3v0zsbMCM9TihrOyxqGBg9JyxrPB24UcIaGica','quKGy29TBwfUzcb0CMfUC2XHDgLVBIbJB21WBgv0zwq','CgLWzq','uhjVy2vLzcbWCM9TChq','r2vUzxjPyYbPBNb1DcbWCM9TChq','qwXSia','AwnHy2XZ','DhLWzq','CMf3q29UDgvUDa','y29TCgXLDgvK','yMfZAa','zwnOBW','uhjVBxb0igrLDgvJDgvKigLUigjHy2TNCM91BMqGy29TBwfUzcbZDgrLCNi','Aw5PDgLHBgL6zvrLCM1PBMfSrgv0zwn0Aw9U','zw5KC1DPDgG','ywrKvg9iAxn0B3j5','y3jLyxrLrgLYzwn0B3j5qwnJzxnZ','rxHWyw5KlufYy2HPDMu','Bwf0y2G','C3rKzxjYqNvMzMvY','y2XHC3nPzNLdB21Tyw5K','DhjPBq','zwnOBYaIjdeIid4','q29WEs1jDgvT','nJKXotCWvffRBwrs','BgfZDe91Dhb1DfrPBwu','r2v0lunVBNrLBNqGluHLywq','zNjVBq','y29TBwfUzfr5Cgu','q29TBwfUzcb0Aw1LzcbVDxqGywz0zxiG','BwfPBIGP','r2v0lvbYB2nLC3m','AxnbyNnVBhv0zq','q29UzMLYBwf0Aw9UihbYB21WDa','zxzLCNK','zMLSzs1TB3zL','C3rKB3v0qNvMzMvY','wwvZl05Vihf1zxn0Aw9U','y2XLyxjxB3jRAw5NrgLYzwn0B3j5','Aw5JBhvKzxm','C3rKzxjY','y29UzMLKzw5Jzq','sgL0igvUDgvY','u0HfteW','u3rVCc1qCM9JzxnZ','Cg93zxjZAgvSBa','AxncBg9JA2vKq29TBwfUza','CNvUBMLUzW','AxndB21Tyw5Kq29TCgf0AwjSzvDPDgHuzxjTAw5HBa','zwnOBYa','qwnJzxnZigrLBMLLzdOGq29TBwfUzcbIzwXVBMDZihrVigfNzw50ia','zMLSzs1JB3b5','zMLSDgvY','tw92zs1jDgvT','DhjHBNnSyxrLq29TBwfUza','z2v0lxDVCMTPBMCTzgLYzwn0B3j5','Cgf0DgvYBG','ChjVBxb0rgv0zwn0zwq'];a0_0x5f48=function(){return _0x4d4c00;};return a0_0x5f48();}import a0_0x131d98 from'../utilities/tagParser.js';import a0_0x4caa1b from'../utilities/directoryAccessManager.js';import{spawn,exec}from'child_process';import a0_0x3c91a6 from'path';import a0_0x5eb71c from'fs/promises';import{TOOL_STATUS,SYSTEM_DEFAULTS}from'../utilities/constants.js';class PromptDetector{constructor(){const _0x33fa63=a0_0x4a54;this[_0x33fa63(0x1b3)]=[{'pattern':/\(y\/n\)/i,'type':_0x33fa63(0x10d),'description':'Yes/No\x20question'},{'pattern':/\(Y\/n\)/i,'type':'yes-no-default-yes','description':'Yes/No (default Yes)'},{'pattern':/\(y\/N\)/i,'type':'yes-no-default-no','description':'Yes/No (default No)'},{'pattern':/\[y\/n\]/i,'type':'yes-no','description':_0x33fa63(0x148)},{'pattern':/\[Y\/n\]/i,'type':'yes-no-default-yes','description':'Yes/No (default Yes)'},{'pattern':/\[y\/N\]/i,'type':'yes-no-default-no','description':'Yes/No (default No)'},{'pattern':/continue\?/i,'type':'continue','description':'Continue\x20prompt'},{'pattern':/proceed\?/i,'type':'continue','description':_0x33fa63(0x126)},{'pattern':/press any key to continue/i,'type':'keypress','description':_0x33fa63(0x1ca)},{'pattern':/press enter to continue/i,'type':_0x33fa63(0x19f),'description':_0x33fa63(0x1c8)},{'pattern':/hit enter to continue/i,'type':'keypress','description':_0x33fa63(0x14d)},{'pattern':/password:/i,'type':'password','description':'Password\x20prompt'},{'pattern':/enter password/i,'type':'password','description':_0x33fa63(0x17c)},{'pattern':/passphrase:/i,'type':'password','description':_0x33fa63(0x16a)},{'pattern':/username:/i,'type':'username','description':'Username\x20prompt'},{'pattern':/enter username/i,'type':_0x33fa63(0xd4),'description':_0x33fa63(0x1af)},{'pattern':/enter\s+\w+:/i,'type':_0x33fa63(0x10b),'description':_0x33fa63(0x127)},{'pattern':/please enter/i,'type':_0x33fa63(0x10b),'description':_0x33fa63(0x127)},{'pattern':/input:/i,'type':'input','description':'Generic\x20input\x20prompt'},{'pattern':/are you sure\?/i,'type':_0x33fa63(0xcb),'description':_0x33fa63(0x144)},{'pattern':/do you want to/i,'type':_0x33fa63(0xcb),'description':_0x33fa63(0x144)},{'pattern':/would you like to/i,'type':_0x33fa63(0xcb),'description':'Confirmation\x20prompt'},{'pattern':/select an option/i,'type':_0x33fa63(0x1f5),'description':_0x33fa63(0x175)},{'pattern':/choose/i,'type':'selection','description':_0x33fa63(0x175)},{'pattern':/\d+\)\s+\w+/g,'type':'menu','description':_0x33fa63(0xfe)}];}['detectPrompt'](_0x38c167,_0x1093e2=a0_0xc176c6(0x1d6)){const _0x174740=a0_0xc176c6;if(!_0x38c167||_0x38c167['trim']()['length']===0x0)return null;const _0x304a46=_0x38c167[_0x174740(0x1b2)]('\x0a'),_0x48b21a=_0x304a46['slice'](-0x5)[_0x174740(0x15e)]('\x0a');for(const _0x1b8f29 of this['promptPatterns']){const _0x289449=_0x48b21a[_0x174740(0x135)](_0x1b8f29[_0x174740(0x15b)]);if(_0x289449)return{'detected':!![],'type':_0x1b8f29['type'],'description':_0x1b8f29['description'],'matchedText':_0x289449[0x0],'matchIndex':_0x289449[_0x174740(0x1d2)],'source':_0x1093e2,'fullContext':_0x48b21a,'timestamp':Date['now']()};}const _0xa2813a=_0x304a46[_0x304a46[_0x174740(0xbf)]-0x1]||'';if(_0xa2813a['trim']()['length']>0x0){const _0x386aaf=/:\s*$/['test'](_0xa2813a),_0x52632e=/\?\s*$/[_0x174740(0xb8)](_0xa2813a);if(_0x386aaf||_0x52632e){const _0x5d05fc=/\b(enter|type|provide|specify|input)\b/i['test'](_0xa2813a);if(_0x5d05fc)return{'detected':!![],'type':'generic','description':'Generic\x20input\x20prompt\x20detected','matchedText':_0xa2813a['trim'](),'source':_0x1093e2,'fullContext':_0x48b21a,'timestamp':Date['now'](),'confidence':0.7};}}return null;}[a0_0xc176c6(0xc7)](_0x2389f9,_0x4d95b8=0x7530){const _0x2c1c9a=a0_0xc176c6,_0x8fcce8=Date[_0x2c1c9a(0x1da)](),_0x23f410=_0x8fcce8-_0x2389f9;return{'isHanging':_0x23f410>=_0x4d95b8,'timeSinceLastOutput':_0x23f410,'threshold':_0x4d95b8,'likelyWaiting':_0x23f410>=_0x4d95b8/0x2};}}class TerminalTool extends BaseTool{constructor(_0x5d6015={},_0x27f8c9=null){const _0x2c405f=a0_0xc176c6;super(_0x5d6015,_0x27f8c9),this['requiresProject']=![],this['isAsync']=![],this['timeout']=_0x5d6015[_0x2c405f(0x1b9)]||0x1d4c0,this[_0x2c405f(0xf9)]=_0x5d6015['maxConcurrentOperations']||0x3,this['workingDirectories']=new Map(),this['commandHistory']=[],this[_0x2c405f(0xe3)]=_0x5d6015['allowedCommands']||null,this['blockedCommands']=_0x5d6015[_0x2c405f(0x1e6)]||[_0x2c405f(0x178),_0x2c405f(0x19e),_0x2c405f(0x1e5),_0x2c405f(0x1e4),'reboot',_0x2c405f(0x1fc)],this[_0x2c405f(0x195)]=new a0_0x4caa1b(_0x5d6015,_0x27f8c9),this[_0x2c405f(0xd9)]=new PromptDetector(),this['commandTracker']=new Map(),this['commandIdCounter']=0x0,this['MAX_BACKGROUND_COMMANDS_PER_AGENT']=_0x5d6015['maxBackgroundCommandsPerAgent']||0x5,this['MAX_BACKGROUND_COMMANDS_GLOBAL']=_0x5d6015[_0x2c405f(0x18e)]||0x14,this['MAX_COMMAND_AGE_MINUTES']=_0x5d6015[_0x2c405f(0x172)]||0x3c,this['detectedTerminal']=null,this['platformType']=null,this[_0x2c405f(0x130)]();}['getDescription'](){const _0xc127c4=a0_0xc176c6;return'\x0aTerminal\x20Tool:\x20Execute\x20system\x20commands\x20and\x20manage\x20terminal\x20operations\x20safely.\x0a\x0aIMPORTANT:\x20For\x20file\x20and\x20directory\x20creation,\x20prefer\x20using\x20the\x20FileSystem\x20tool.\x0aReserve\x20the\x20Terminal\x20tool\x20for\x20command-line\x20operations\x20like\x20npm,\x20git,\x20curl,\x20etc.\x0a\x0aUSAGE:\x0a[tool\x20id=\x22terminal\x22]\x0a<run-command>npm\x20install\x20express</run-command>\x0a<change-directory>project/backend</change-directory>\x0a[/tool]\x0a\x0aALTERNATIVE\x20JSON\x20FORMAT:\x0a```json\x0a{\x0a\x20\x20\x22toolId\x22:\x20\x22terminal\x22,\x0a\x20\x20\x22actions\x22:\x20[\x0a\x20\x20\x20\x20{\x0a\x20\x20\x20\x20\x20\x20\x22type\x22:\x20\x22run-command\x22,\x0a\x20\x20\x20\x20\x20\x20\x22command\x22:\x20\x22npm\x20install\x20express\x22\x0a\x20\x20\x20\x20},\x0a\x20\x20\x20\x20{\x0a\x20\x20\x20\x20\x20\x20\x22type\x22:\x20\x22change-directory\x22,\x0a\x20\x20\x20\x20\x20\x20\x22directory\x22:\x20\x22project/backend\x22\x0a\x20\x20\x20\x20}\x0a\x20\x20]\x0a}\x0a```\x0a\x0aSUPPORTED\x20ACTIONS:\x0a-\x20run-command:\x20Execute\x20a\x20command\x20in\x20the\x20current\x20directory\x0a-\x20change-directory:\x20Change\x20current\x20working\x20directory\x0a-\x20list-directory:\x20List\x20contents\x20of\x20current\x20or\x20specified\x20directory\x0a-\x20create-directory:\x20Create\x20a\x20new\x20directory\x20(prefer\x20FileSystem\x20tool)\x0a-\x20get-working-directory:\x20Get\x20current\x20working\x20directory\x0a\x0aPARAMETERS:\x0a-\x20command:\x20The\x20command\x20to\x20execute\x0a-\x20directory:\x20Directory\x20path\x20for\x20navigation/operations\x0a-\x20timeout:\x20Optional\x20timeout\x20in\x20milliseconds\x20(max\x20'+this[_0xc127c4(0x1b9)]+'ms)\x0a-\x20async:\x20Whether\x20to\x20run\x20command\x20asynchronously\x20(true/false)\x0a\x0aBACKGROUND\x20COMMAND\x20MANAGEMENT\x20(Advanced):\x0aFor\x20long-running\x20commands\x20(npm\x20install,\x20git\x20operations,\x20builds),\x20use\x20background\x20command\x20tracking:\x0a\x0a**startBackgroundCommand(command,\x20workingDir,\x20{agentId,\x20context})**\x0a-\x20Starts\x20command\x20in\x20background\x20with\x20stdin\x20kept\x20open\x0a-\x20Returns\x20commandId\x20for\x20tracking\x0a-\x20Max\x20'+this[_0xc127c4(0x18a)]+_0xc127c4(0x193)+this['MAX_BACKGROUND_COMMANDS_GLOBAL']+_0xc127c4(0x123);}[a0_0xc176c6(0x11b)](_0x43cf0d){const _0x463078=a0_0xc176c6;try{const _0x59c90f={},_0xa62c36=a0_0x131d98['extractContent'](_0x43cf0d,_0x463078(0xf1)),_0x2c1bbf=a0_0x131d98[_0x463078(0x1c4)](_0x43cf0d,_0x463078(0xf2)),_0x46bcac=a0_0x131d98[_0x463078(0x1c4)](_0x43cf0d,_0x463078(0xdc)),_0x42194e=a0_0x131d98['extractContent'](_0x43cf0d,_0x463078(0x1d5)),_0x3dd5a8=a0_0x131d98['extractContent'](_0x43cf0d,'get-working-directory'),_0x55fade=a0_0x131d98[_0x463078(0x1c4)](_0x43cf0d,_0x463078(0x1b9)),_0x3361c4=a0_0x131d98[_0x463078(0x1c4)](_0x43cf0d,'async'),_0x3fae32=[];return _0xa62c36[_0x463078(0xbf)]>0x0&&_0x3fae32[_0x463078(0xef)]({'type':'run-command','command':_0xa62c36[0x0]['trim']()}),_0x2c1bbf['length']>0x0&&_0x3fae32[_0x463078(0xef)]({'type':'change-directory','directory':_0x2c1bbf[0x0]['trim']()}),_0x46bcac['length']>0x0&&_0x3fae32[_0x463078(0xef)]({'type':_0x463078(0xdc),'directory':_0x46bcac[0x0][_0x463078(0x138)]()||'.'}),_0x42194e[_0x463078(0xbf)]>0x0&&_0x3fae32[_0x463078(0xef)]({'type':_0x463078(0x1d5),'directory':_0x42194e[0x0]['trim']()}),_0x3dd5a8['length']>0x0&&_0x3fae32[_0x463078(0xef)]({'type':'get-working-directory'}),_0x59c90f['actions']=_0x3fae32,_0x55fade['length']>0x0&&(_0x59c90f[_0x463078(0x1b9)]=parseInt(_0x55fade[0x0],0xa)),_0x3361c4[_0x463078(0xbf)]>0x0&&(_0x59c90f[_0x463078(0x169)]=_0x3361c4[0x0][_0x463078(0xb9)]()===_0x463078(0xb6)),_0x59c90f[_0x463078(0x12b)]=_0x43cf0d['trim'](),_0x59c90f;}catch(_0x413214){throw new Error('Failed\x20to\x20parse\x20terminal\x20parameters:\x20'+_0x413214['message']);}}['getRequiredParameters'](){return['actions'];}[a0_0xc176c6(0x101)](_0x40e13c){const _0x431c0f=a0_0xc176c6,_0x24effd=[];if(!_0x40e13c['actions']||!Array['isArray'](_0x40e13c[_0x431c0f(0x1ba)])||_0x40e13c[_0x431c0f(0x1ba)][_0x431c0f(0xbf)]===0x0)_0x24effd[_0x431c0f(0xef)]('At\x20least\x20one\x20action\x20is\x20required');else for(const [_0x6168ee,_0x222075]of _0x40e13c[_0x431c0f(0x1ba)]['entries']()){if(!_0x222075[_0x431c0f(0x12a)]){_0x24effd[_0x431c0f(0xef)](_0x431c0f(0xfd)+(_0x6168ee+0x1)+_0x431c0f(0x1ed));continue;}switch(_0x222075[_0x431c0f(0x12a)]){case'run-command':if(!_0x222075[_0x431c0f(0xea)]||!_0x222075['command'][_0x431c0f(0x138)]())_0x24effd[_0x431c0f(0xef)]('Action\x20'+(_0x6168ee+0x1)+_0x431c0f(0xc6));else{if(this[_0x431c0f(0x151)](_0x222075[_0x431c0f(0xea)]))_0x24effd[_0x431c0f(0xef)]('Action\x20'+(_0x6168ee+0x1)+_0x431c0f(0x1e3)+_0x222075[_0x431c0f(0xea)]);else this[_0x431c0f(0xe3)]&&!this['isAllowedCommand'](_0x222075['command'])&&_0x24effd['push'](_0x431c0f(0xfd)+(_0x6168ee+0x1)+':\x20command\x20is\x20not\x20in\x20allowed\x20list:\x20'+_0x222075[_0x431c0f(0xea)]);}break;case _0x431c0f(0xf2):case'list-directory':case _0x431c0f(0x1d5):(!_0x222075[_0x431c0f(0x1aa)]||!_0x222075['directory'][_0x431c0f(0x138)]())&&_0x24effd[_0x431c0f(0xef)]('Action\x20'+(_0x6168ee+0x1)+':\x20directory\x20is\x20required\x20for\x20'+_0x222075[_0x431c0f(0x12a)]);break;case'get-working-directory':break;default:_0x24effd[_0x431c0f(0xef)]('Action\x20'+(_0x6168ee+0x1)+_0x431c0f(0x1c6)+_0x222075[_0x431c0f(0x12a)]);}}return _0x40e13c[_0x431c0f(0x1b9)]&&(_0x40e13c[_0x431c0f(0x1b9)]<0x3e8||_0x40e13c[_0x431c0f(0x1b9)]>this['timeout'])&&_0x24effd['push'](_0x431c0f(0x116)+this[_0x431c0f(0x1b9)]+'\x20milliseconds'),{'valid':_0x24effd['length']===0x0,'errors':_0x24effd};}async[a0_0xc176c6(0x1c9)](_0x228fc0,_0x195a24){const _0x32e975=a0_0xc176c6,{actions:_0x19262a,timeout:_0x36b3b8,async:_0xc546ce}=_0x228fc0,{agentId:_0x498db7,projectDir:_0x20122a,directoryAccess:_0x2c5f62}=_0x195a24,_0x3a9ec6=_0x2c5f62||this[_0x32e975(0x195)][_0x32e975(0x133)]({'workingDirectory':_0x20122a||process['cwd'](),'writeEnabledDirectories':[_0x20122a||process['cwd']()],'restrictToProject':!![]});_0x2c5f62&&_0x2c5f62['workingDirectory']?console[_0x32e975(0x168)]('Terminal\x20DEBUG:\x20Using\x20agent\x20configured\x20working\x20directory:',_0x2c5f62[_0x32e975(0x1a0)]):console['log']('Terminal\x20DEBUG:\x20Using\x20fallback\x20working\x20directory:',_0x20122a||process['cwd']());const _0x4e17c7=_0x498db7+'-'+(_0x20122a||'default');let _0x327a74=this[_0x32e975(0xcd)][_0x32e975(0x189)](_0x4e17c7)||this[_0x32e975(0x195)]['getWorkingDirectory'](_0x3a9ec6);const _0x55a20f=[];for(const _0x498db1 of _0x19262a){try{let _0x37c547;switch(_0x498db1[_0x32e975(0x12a)]){case _0x32e975(0xf1):_0x37c547=await this['executeCommand'](_0x498db1[_0x32e975(0xea)],_0x327a74,{'timeout':_0x36b3b8||this['timeout'],'async':_0xc546ce||![],'agentId':_0x498db7,'context':{'toolsRegistry':_0x195a24[_0x32e975(0x194)],'aiService':_0x195a24[_0x32e975(0xb5)],'apiKey':_0x195a24[_0x32e975(0x103)],'customApiKeys':_0x195a24['customApiKeys'],'platformProvided':_0x195a24['platformProvided']}});break;case _0x32e975(0xf2):_0x37c547=await this['changeDirectory'](_0x498db1['directory'],_0x327a74,_0x3a9ec6),_0x327a74=_0x37c547['newDirectory'],this['workingDirectories'][_0x32e975(0xbd)](_0x4e17c7,_0x327a74);break;case _0x32e975(0xdc):_0x37c547=await this['listDirectory'](_0x498db1['directory']==='.'?_0x327a74:_0x498db1[_0x32e975(0x1aa)]);break;case'create-directory':_0x37c547=await this[_0x32e975(0x1b1)](_0x498db1[_0x32e975(0x1aa)],_0x327a74);break;case'get-working-directory':_0x37c547={'success':!![],'action':_0x32e975(0x15a),'workingDirectory':_0x327a74,'message':_0x32e975(0x108)+_0x327a74};break;default:throw new Error('Unknown\x20action\x20type:\x20'+_0x498db1['type']);}_0x55a20f['push'](_0x37c547),this[_0x32e975(0x132)](_0x498db1,_0x37c547,_0x498db7);}catch(_0x283592){const _0x295b5f={'success':![],'action':_0x498db1['type'],'error':_0x283592[_0x32e975(0xff)],'command':_0x498db1['command']||_0x498db1['directory'],'workingDirectory':_0x327a74};_0x55a20f[_0x32e975(0xef)](_0x295b5f),this[_0x32e975(0x132)](_0x498db1,_0x295b5f,_0x498db7);}}const _0x568853=_0x55a20f[_0x32e975(0x145)](_0x399745=>_0x399745[_0x32e975(0x161)]),_0x8bfae5=_0x55a20f[_0x32e975(0x157)](_0x230281=>!_0x230281['success']);return{'success':_0x568853,'actions':_0x55a20f,'workingDirectory':_0x327a74,'executedActions':_0x19262a['length'],'failedActions':_0x8bfae5['length'],'toolUsed':'terminal','message':_0x568853?_0x32e975(0x128)+_0x19262a['length']+_0x32e975(0x1f9):_0x8bfae5[_0x32e975(0xbf)]+'\x20of\x20'+_0x19262a[_0x32e975(0xbf)]+_0x32e975(0x16c)};}async[a0_0xc176c6(0x1d4)](_0x1446d9,_0x4340d9,_0x51d3c5={}){const _0x5b5c80=a0_0xc176c6,{timeout:timeout=this[_0x5b5c80(0x1b9)],async:_0x5003ee=![],agentId:_0x42a127,context:_0x58896b}=_0x51d3c5,_0x21ecea=_0x1446d9;let _0x36a361;try{_0x36a361=await this[_0x5b5c80(0x159)](_0x1446d9,{'agentId':_0x42a127,'toolsRegistry':_0x58896b?.[_0x5b5c80(0x194)],'messageProcessor':_0x58896b?.['messageProcessor'],'aiService':_0x58896b?.[_0x5b5c80(0xb5)],'apiKey':_0x58896b?.[_0x5b5c80(0x103)],'customApiKeys':_0x58896b?.[_0x5b5c80(0x197)],'platformProvided':_0x58896b?.['platformProvided']});}catch(_0x5f0b60){this[_0x5b5c80(0xc8)]?.['warn'](_0x5b5c80(0x190),{'originalCommand':_0x21ecea,'error':_0x5f0b60['message']}),_0x36a361=_0x1446d9;}return new Promise((_0x1c37a6,_0x4ac426)=>{const _0x555873=_0x5b5c80,_0x6e3568=Date[_0x555873(0x1da)]();this[_0x555873(0xc8)]?.[_0x555873(0x174)](_0x555873(0xc5)+_0x36a361,{'originalCommand':_0x21ecea,'translatedCommand':_0x36a361,'terminal':this[_0x555873(0x1e8)],'workingDirectory':_0x4340d9,'timeout':timeout,'agentId':_0x42a127});const _0xdd46de=exec(_0x36a361,{'cwd':_0x4340d9,'timeout':timeout,'maxBuffer':0x400*0x400,'env':{...process[_0x555873(0x16f)]}},(_0x2f051b,_0xc8de32,_0x42e095)=>{const _0x233fb9=_0x555873,_0x4eee75=Date['now']()-_0x6e3568;if(_0x2f051b){this[_0x233fb9(0xc8)]?.[_0x233fb9(0x183)](_0x233fb9(0xd2)+_0x36a361,{'originalCommand':_0x21ecea,'translatedCommand':_0x36a361,'error':_0x2f051b['message'],'workingDirectory':_0x4340d9,'executionTime':_0x4eee75}),_0x1c37a6({'success':![],'action':_0x233fb9(0xf1),'command':_0x21ecea,'translatedCommand':_0x36a361!==_0x21ecea?_0x36a361:undefined,'error':_0x2f051b['message'],'stderr':_0x42e095['trim'](),'stdout':_0xc8de32[_0x233fb9(0x138)](),'exitCode':_0x2f051b['code'],'executionTime':_0x4eee75,'workingDirectory':_0x4340d9});return;}this[_0x233fb9(0xc8)]?.['info']('Command\x20completed:\x20'+_0x36a361,{'originalCommand':_0x21ecea,'translatedCommand':_0x36a361,'executionTime':_0x4eee75,'stdoutLength':_0xc8de32['length'],'stderrLength':_0x42e095[_0x233fb9(0xbf)]}),_0x1c37a6({'success':!![],'action':_0x233fb9(0xf1),'command':_0x21ecea,'translatedCommand':_0x36a361!==_0x21ecea?_0x36a361:undefined,'stdout':_0xc8de32[_0x233fb9(0x138)](),'stderr':_0x42e095[_0x233fb9(0x138)](),'exitCode':0x0,'executionTime':_0x4eee75,'workingDirectory':_0x4340d9,'message':'Command\x20executed\x20successfully\x20in\x20'+_0x4eee75+'ms'});});setTimeout(()=>{const _0x5c0400=_0x555873;!_0xdd46de['killed']&&(_0xdd46de[_0x5c0400(0x17e)]('SIGTERM'),_0x4ac426(new Error('Command\x20timed\x20out\x20after\x20'+timeout+'ms:\x20'+_0x36a361+'\x20(original:\x20'+_0x21ecea+')')));},timeout);});}async['executeCommandWithSpawn'](_0x1fe199,_0x28ce76,_0x2294d2={}){const _0x50900e=a0_0xc176c6,{timeout:timeout=this['timeout'],agentId:_0x3c212a,context:_0x1fafa4}=_0x2294d2,_0x42d89f=_0x1fe199;let _0x3ed151;try{_0x3ed151=await this['translateCommand'](_0x1fe199,{'agentId':_0x3c212a,'toolsRegistry':_0x1fafa4?.['toolsRegistry'],'messageProcessor':_0x1fafa4?.['messageProcessor'],'aiService':_0x1fafa4?.[_0x50900e(0xb5)],'apiKey':_0x1fafa4?.['apiKey'],'customApiKeys':_0x1fafa4?.[_0x50900e(0x197)],'platformProvided':_0x1fafa4?.[_0x50900e(0x1a6)]});}catch(_0x2b74db){this[_0x50900e(0xc8)]?.['warn']('Command\x20translation\x20failed,\x20using\x20original\x20command',{'originalCommand':_0x42d89f,'error':_0x2b74db[_0x50900e(0xff)]}),_0x3ed151=_0x1fe199;}return new Promise((_0xfdf721,_0x31a50b)=>{const _0x21390f=_0x50900e,_0x4dd875=Date[_0x21390f(0x1da)]();this[_0x21390f(0xc8)]?.[_0x21390f(0x174)]('Executing\x20command\x20with\x20spawn:\x20'+_0x3ed151,{'originalCommand':_0x42d89f,'translatedCommand':_0x3ed151,'terminal':this['detectedTerminal'],'workingDirectory':_0x28ce76,'timeout':timeout,'agentId':_0x3c212a});let _0x49386c;if(this[_0x21390f(0x1e8)]===_0x21390f(0x1f7)||this['detectedTerminal']===_0x21390f(0x150)){const _0x4b454f=this[_0x21390f(0x1e8)]==='powershell'?_0x21390f(0x150):_0x21390f(0x1f7),_0x547d06=this['detectedTerminal']==='powershell'?['-Command',_0x3ed151]:['/c',_0x3ed151];_0x49386c=spawn(_0x4b454f,_0x547d06,{'cwd':_0x28ce76,'env':{...process['env']},'windowsHide':!![]});}else _0x49386c=spawn('sh',['-c',_0x3ed151],{'cwd':_0x28ce76,'env':{...process[_0x21390f(0x16f)]}});let _0x588561='',_0x17abf4='',_0x23548e=![],_0x225621=null,_0x2cff58=Date['now'](),_0x5c207c=null;const _0xf9723c=setTimeout(()=>{const _0x110f62=_0x21390f;!_0x49386c['killed']&&_0x225621===null&&(_0x23548e=!![],this['logger']?.['warn'](_0x110f62(0xce)+_0x3ed151,{'timeout':timeout,'agentId':_0x3c212a}),_0x49386c['kill'](_0x110f62(0xe2)),setTimeout(()=>{const _0x18e92c=_0x110f62;!_0x49386c['killed']&&_0x49386c[_0x18e92c(0x17e)]('SIGKILL');},0x1388));},timeout);_0x49386c[_0x21390f(0x1d6)]['on']('data',_0x1eaff0=>{const _0x1a95e7=_0x21390f,_0x5904b8=_0x1eaff0['toString']();_0x588561+=_0x5904b8,_0x2cff58=Date[_0x1a95e7(0x1da)](),this['logger']?.['debug'](_0x1a95e7(0x1fe)+_0x5904b8['substring'](0x0,0x64),{'agentId':_0x3c212a,'command':_0x42d89f[_0x1a95e7(0xd3)](0x0,0x32)});if(!_0x5c207c){const _0x496d7b=this['promptDetector'][_0x1a95e7(0x163)](_0x588561,_0x1a95e7(0x1d6));_0x496d7b&&(_0x5c207c=_0x496d7b,this[_0x1a95e7(0xc8)]?.['info']('Prompt\x20detected\x20in\x20stdout',{'type':_0x496d7b[_0x1a95e7(0x12a)],'description':_0x496d7b['description'],'matchedText':_0x496d7b[_0x1a95e7(0x191)],'agentId':_0x3c212a,'command':_0x42d89f['substring'](0x0,0x32)}));}}),_0x49386c['stderr']['on']('data',_0x4d14ca=>{const _0x5264c9=_0x21390f,_0x356a48=_0x4d14ca[_0x5264c9(0x120)]();_0x17abf4+=_0x356a48,_0x2cff58=Date[_0x5264c9(0x1da)](),this['logger']?.['debug'](_0x5264c9(0x181)+_0x356a48[_0x5264c9(0xd3)](0x0,0x64),{'agentId':_0x3c212a,'command':_0x42d89f['substring'](0x0,0x32)});if(!_0x5c207c){const _0x13ab9b=this[_0x5264c9(0xd9)]['detectPrompt'](_0x17abf4,_0x5264c9(0x14b));_0x13ab9b&&(_0x5c207c=_0x13ab9b,this['logger']?.[_0x5264c9(0x174)]('Prompt\x20detected\x20in\x20stderr',{'type':_0x13ab9b[_0x5264c9(0x12a)],'description':_0x13ab9b[_0x5264c9(0x1dc)],'matchedText':_0x13ab9b['matchedText'],'agentId':_0x3c212a,'command':_0x42d89f[_0x5264c9(0xd3)](0x0,0x32)}));}}),_0x49386c['on']('exit',(_0x2c1ce2,_0x421daa)=>{const _0xb12987=_0x21390f;clearTimeout(_0xf9723c),_0x225621=_0x2c1ce2;const _0x2aa1c6=Date[_0xb12987(0x1da)]()-_0x4dd875,_0x1fabfc=Date[_0xb12987(0x1da)]()-_0x2cff58;this['logger']?.['info'](_0xb12987(0xeb)+_0x3ed151,{'exitCode':_0x2c1ce2,'signal':_0x421daa,'executionTime':_0x2aa1c6,'timedOut':_0x23548e,'stdoutLength':_0x588561[_0xb12987(0xbf)],'stderrLength':_0x17abf4['length'],'promptDetected':!!_0x5c207c,'timeSinceLastOutput':_0x1fabfc});const _0x367a52={'action':_0xb12987(0xf1),'command':_0x42d89f,'translatedCommand':_0x3ed151!==_0x42d89f?_0x3ed151:undefined,'stdout':_0x588561['trim'](),'stderr':_0x17abf4['trim'](),'exitCode':_0x2c1ce2,'executionTime':_0x2aa1c6,'workingDirectory':_0x28ce76,'promptDetected':!!_0x5c207c,'promptInfo':_0x5c207c||undefined,'lastOutputTime':_0x2cff58,'timeSinceLastOutput':_0x1fabfc};if(_0x23548e){_0xfdf721({..._0x367a52,'success':![],'error':_0xb12987(0x140)+timeout+'ms','exitCode':_0x2c1ce2||-0x1,'timedOut':!![]});return;}if(_0x2c1ce2!==0x0){this['logger']?.['error'](_0xb12987(0x1d1)+_0x2c1ce2+':\x20'+_0x3ed151,{'originalCommand':_0x42d89f,'translatedCommand':_0x3ed151,'exitCode':_0x2c1ce2,'stderr':_0x17abf4['substring'](0x0,0xc8),'executionTime':_0x2aa1c6,'promptDetected':!!_0x5c207c}),_0xfdf721({..._0x367a52,'success':![],'error':'Command\x20exited\x20with\x20code\x20'+_0x2c1ce2});return;}this['logger']?.[_0xb12987(0x174)]('Command\x20completed\x20successfully:\x20'+_0x3ed151,{'originalCommand':_0x42d89f,'executionTime':_0x2aa1c6,'stdoutLength':_0x588561['length'],'stderrLength':_0x17abf4[_0xb12987(0xbf)],'promptDetected':!!_0x5c207c}),_0xfdf721({..._0x367a52,'success':!![],'exitCode':0x0,'message':'Command\x20executed\x20successfully\x20in\x20'+_0x2aa1c6+'ms'});}),_0x49386c['on'](_0x21390f(0x183),_0x86607e=>{const _0x52f205=_0x21390f;clearTimeout(_0xf9723c);const _0x4ca36f=Date[_0x52f205(0x1da)]()-_0x4dd875,_0x3853ed=Date[_0x52f205(0x1da)]()-_0x2cff58;this['logger']?.[_0x52f205(0x183)]('Command\x20spawn\x20error:\x20'+_0x3ed151,{'originalCommand':_0x42d89f,'error':_0x86607e[_0x52f205(0xff)],'executionTime':_0x4ca36f,'promptDetected':!!_0x5c207c}),_0xfdf721({'success':![],'action':_0x52f205(0xf1),'command':_0x42d89f,'translatedCommand':_0x3ed151!==_0x42d89f?_0x3ed151:undefined,'error':_0x86607e[_0x52f205(0xff)],'stderr':_0x17abf4['trim'](),'stdout':_0x588561[_0x52f205(0x138)](),'exitCode':-0x1,'executionTime':_0x4ca36f,'workingDirectory':_0x28ce76,'promptDetected':!!_0x5c207c,'promptInfo':_0x5c207c||undefined,'lastOutputTime':_0x2cff58,'timeSinceLastOutput':_0x3853ed});});});}async['changeDirectory'](_0x2edab1,_0x42f6b9,_0x154adf){const _0x2ebf20=a0_0xc176c6;try{let _0x1da714;a0_0x3c91a6[_0x2ebf20(0x143)](_0x2edab1)?_0x1da714=_0x2edab1:_0x1da714=a0_0x3c91a6[_0x2ebf20(0x1a4)](_0x42f6b9,_0x2edab1);const _0x102786=await a0_0x5eb71c['stat'](_0x1da714);if(!_0x102786['isDirectory']())throw new Error(_0x2ebf20(0xed)+_0x1da714);const _0x553fe7=this[_0x2ebf20(0x195)]['validateReadAccess'](_0x1da714,_0x154adf);if(!_0x553fe7[_0x2ebf20(0x1c5)]){this[_0x2ebf20(0xc8)]?.[_0x2ebf20(0x162)]('Directory\x20change\x20blocked:\x20'+_0x553fe7['reason'],{'targetDirectory':_0x1da714,'reason':_0x553fe7[_0x2ebf20(0x1e7)],'category':_0x553fe7[_0x2ebf20(0xbc)]});throw new Error(_0x2ebf20(0x196)+_0x553fe7['reason']);}return{'success':!![],'action':'change-directory','previousDirectory':_0x42f6b9,'newDirectory':_0x1da714,'message':_0x2ebf20(0xc3)+_0x1da714};}catch(_0x5a18ec){throw new Error(_0x2ebf20(0x1d8)+_0x2edab1+':\x20'+_0x5a18ec[_0x2ebf20(0xff)]);}}async['listDirectory'](_0x1e7a0f){const _0x5ba6da=a0_0xc176c6;try{const _0x4050eb=await a0_0x5eb71c[_0x5ba6da(0x10e)](_0x1e7a0f,{'withFileTypes':!![]}),_0x2fd9a2=_0x4050eb[_0x5ba6da(0x1f0)](_0x1ed17f=>({'name':_0x1ed17f[_0x5ba6da(0xf5)],'type':_0x1ed17f[_0x5ba6da(0xc2)]()?'directory':'file','isSymlink':_0x1ed17f[_0x5ba6da(0x1b5)]()}));return{'success':!![],'action':'list-directory','directory':_0x1e7a0f,'contents':_0x2fd9a2,'totalItems':_0x2fd9a2[_0x5ba6da(0xbf)],'directories':_0x2fd9a2['filter'](_0x31954f=>_0x31954f['type']==='directory')['length'],'files':_0x2fd9a2[_0x5ba6da(0x157)](_0x19814a=>_0x19814a['type']===_0x5ba6da(0xb3))['length'],'message':'Listed\x20'+_0x2fd9a2['length']+_0x5ba6da(0x16d)+_0x1e7a0f};}catch(_0x5e14fe){throw new Error(_0x5ba6da(0x1fa)+_0x1e7a0f+':\x20'+_0x5e14fe[_0x5ba6da(0xff)]);}}async['createDirectory'](_0x4e35bd,_0x3141bc){const _0x27ef13=a0_0xc176c6;try{let _0x38bff6;return a0_0x3c91a6[_0x27ef13(0x143)](_0x4e35bd)?_0x38bff6=_0x4e35bd:_0x38bff6=a0_0x3c91a6['resolve'](_0x3141bc,_0x4e35bd),await a0_0x5eb71c[_0x27ef13(0xd7)](_0x38bff6,{'recursive':!![]}),{'success':!![],'action':'create-directory','directory':_0x38bff6,'relativePath':a0_0x3c91a6[_0x27ef13(0x160)](_0x3141bc,_0x38bff6),'message':_0x27ef13(0x1cf)+_0x38bff6};}catch(_0x590ca6){throw new Error('Failed\x20to\x20create\x20directory\x20'+_0x4e35bd+':\x20'+_0x590ca6[_0x27ef13(0xff)]);}}[a0_0xc176c6(0x151)](_0x30442a){const _0x465697=a0_0xc176c6,_0x3f663c=_0x30442a['toLowerCase']()['trim']();return this[_0x465697(0x1e6)][_0x465697(0x176)](_0x29f874=>{const _0x53c420=_0x465697,_0x34171d=_0x29f874['toLowerCase']();return _0x3f663c===_0x34171d||_0x3f663c[_0x53c420(0x1ac)](_0x34171d+'\x20');});}['isAllowedCommand'](_0x57ef7c){const _0x374815=a0_0xc176c6;if(!this[_0x374815(0xe3)])return!![];const _0x4c6021=_0x57ef7c[_0x374815(0xb9)]()[_0x374815(0x138)](),_0x4caf0c=_0x4c6021['split']('\x20')[0x0];return this[_0x374815(0xe3)]['some'](_0x12950c=>_0x12950c[_0x374815(0xb9)]()===_0x4caf0c||_0x4c6021['startsWith'](_0x12950c['toLowerCase']()+'\x20'));}['addToHistory'](_0x884d45,_0xcd2e4d,_0x4d05d4){const _0x3690b8=a0_0xc176c6,_0x5105d0={'timestamp':new Date()['toISOString'](),'agentId':_0x4d05d4,'action':_0x884d45['type'],'command':_0x884d45['command']||_0x884d45['directory'],'success':_0xcd2e4d['success'],'executionTime':_0xcd2e4d[_0x3690b8(0x18c)]||0x0,'workingDirectory':_0xcd2e4d[_0x3690b8(0x1a0)]};this[_0x3690b8(0x109)][_0x3690b8(0xef)](_0x5105d0),this['commandHistory'][_0x3690b8(0xbf)]>0x64&&(this['commandHistory']=this['commandHistory'][_0x3690b8(0x1b6)](-0x64));}['getSupportedActions'](){const _0x174b8f=a0_0xc176c6;return[_0x174b8f(0xf1),_0x174b8f(0xf2),_0x174b8f(0xdc),_0x174b8f(0x1d5),'get-working-directory'];}['getParameterSchema'](){const _0x2d71e1=a0_0xc176c6;return{'type':'object','properties':{'actions':{'type':'array','minItems':0x1,'items':{'type':_0x2d71e1(0x119),'properties':{'type':{'type':'string','enum':this[_0x2d71e1(0x1ee)]()},'command':{'type':_0x2d71e1(0xfa)},'directory':{'type':_0x2d71e1(0xfa)}},'required':['type']}},'timeout':{'type':_0x2d71e1(0x11a),'minimum':0x3e8,'maximum':this[_0x2d71e1(0x1b9)]},'async':{'type':'boolean'}},'required':['actions']};}['getCommandHistory'](_0x19071d=null){const _0x596f41=a0_0xc176c6;if(_0x19071d)return this[_0x596f41(0x109)]['filter'](_0x358297=>_0x358297[_0x596f41(0x118)]===_0x19071d);return[...this[_0x596f41(0x109)]];}[a0_0xc176c6(0x149)](_0x1c8718){const _0x964b25=a0_0xc176c6;for(const [_0x3c8b1d]of this['workingDirectories']){_0x3c8b1d[_0x964b25(0x1ac)](_0x1c8718+'-')&&this[_0x964b25(0xcd)]['delete'](_0x3c8b1d);}}[a0_0xc176c6(0x114)](_0x23d3c5,_0x70fb3=null){const _0x298ce4=a0_0xc176c6,_0x571123=_0x23d3c5+'-'+(_0x70fb3||'default');return this[_0x298ce4(0xcd)]['get'](_0x571123)||_0x70fb3||process['cwd']();}[a0_0xc176c6(0x130)](){const _0x19d9d2=a0_0xc176c6;this[_0x19d9d2(0x19a)]=process['platform'];if(process[_0x19d9d2(0xd6)]==='win32'){if(process['env'][_0x19d9d2(0x182)])this[_0x19d9d2(0x1e8)]='powershell';else process['env']['SHELL']&&process['env'][_0x19d9d2(0x14e)]['includes']('bash')?this[_0x19d9d2(0x1e8)]='bash':this[_0x19d9d2(0x1e8)]='cmd';}else process['platform']==='darwin'?this[_0x19d9d2(0x1e8)]=_0x19d9d2(0x12d):this['detectedTerminal']=_0x19d9d2(0x12d);this['logger']?.['info']('Terminal\x20detected',{'platform':this[_0x19d9d2(0x19a)],'terminal':this['detectedTerminal'],'shell':process[_0x19d9d2(0x16f)]['SHELL']});}async[a0_0xc176c6(0x159)](_0x3f4111,_0x195510={}){const _0x5e480c=a0_0xc176c6,_0x303a8c=_0x3f4111['trim'](),_0x4d8831=this['analyzeCommandCompatibility'](_0x303a8c);this['logger']?.[_0x5e480c(0x174)]('Command\x20compatibility\x20analysis',{'command':_0x303a8c,'detectedTerminal':_0x4d8831[_0x5e480c(0x1e8)],'commandType':_0x4d8831['commandType'],'commandCategory':_0x4d8831[_0x5e480c(0x10c)],'compatible':_0x4d8831[_0x5e480c(0x1dd)],'issues':_0x4d8831[_0x5e480c(0xe6)],'suggestedAction':_0x4d8831['suggestedAction'],'confidence':_0x4d8831['confidence']});if(_0x4d8831['compatible'])return _0x3f4111;let _0x2027a4=null;if(this['detectedTerminal']==='cmd')_0x2027a4=this['translateToWindowsCmd'](_0x303a8c);else{if(this[_0x5e480c(0x1e8)]==='powershell')_0x2027a4=this['translateToPowerShell'](_0x303a8c);else this['detectedTerminal']===_0x5e480c(0x12d)&&(_0x2027a4=this['translateToBash'](_0x303a8c));}if(_0x2027a4&&this[_0x5e480c(0x104)](_0x303a8c))return this['logger']?.[_0x5e480c(0x174)]('Using\x20simple\x20translation',{'original':_0x3f4111,'translated':_0x2027a4,'method':'simple'}),_0x2027a4;if(_0x195510['aiService']||_0x195510[_0x5e480c(0x194)]&&_0x195510['agentId']){this[_0x5e480c(0xc8)]?.[_0x5e480c(0x174)](_0x5e480c(0x115),{'command':_0x3f4111['substring'](0x0,0x64)+'...','hasAiService':!!_0x195510['aiService'],'hasToolsRegistry':!!_0x195510['toolsRegistry'],'agentId':_0x195510[_0x5e480c(0x118)]});try{const _0x55150d=await this['translateCommandWithAI'](_0x3f4111,_0x195510);if(_0x55150d&&_0x55150d[_0x5e480c(0x138)]()!==_0x3f4111[_0x5e480c(0x138)]())return this['logger']?.[_0x5e480c(0x174)](_0x5e480c(0x1df),{'original':_0x3f4111,'translated':_0x55150d,'method':'ai'}),_0x55150d;else this[_0x5e480c(0xc8)]?.[_0x5e480c(0x162)](_0x5e480c(0x187),{'original':_0x3f4111,'translated':_0x55150d});}catch(_0x2c0d9f){this['logger']?.[_0x5e480c(0x162)]('AI\x20translation\x20failed,\x20falling\x20back\x20to\x20simple\x20translation',{'original':_0x3f4111,'error':_0x2c0d9f['message'],'stack':_0x2c0d9f[_0x5e480c(0x1f3)]});}}else this[_0x5e480c(0xc8)]?.[_0x5e480c(0x162)]('AI\x20translation\x20not\x20available\x20-\x20missing\x20context',{'hasAiService':!!_0x195510['aiService'],'hasToolsRegistry':!!_0x195510[_0x5e480c(0x194)],'hasAgentId':!!_0x195510[_0x5e480c(0x118)],'contextKeys':Object['keys'](_0x195510)});return _0x2027a4||_0x3f4111;}['isSimpleCommand'](_0x561044){const _0x3109db=a0_0xc176c6,_0x110abc=_0x561044[_0x3109db(0xb9)]();if(_0x561044[_0x3109db(0x14a)]('\x5cn')||_0x561044[_0x3109db(0x14a)]('\x5cr')||_0x561044['includes']('\x5ct'))return![];if(_0x561044['includes']('\x0a')||_0x561044['includes']('\x0d'))return![];if(_0x561044[_0x3109db(0x14a)](_0x3109db(0xee))||_0x561044[_0x3109db(0x14a)]('printf')||_0x561044['includes'](_0x3109db(0x141)))return![];if(_0x561044[_0x3109db(0x14a)](_0x3109db(0x1ef))||_0x561044['includes'](_0x3109db(0x1fb))||_0x561044['includes']('class\x20'))return![];if(_0x561044[_0x3109db(0x14a)](_0x3109db(0xdb))&&!_0x561044['includes'](_0x3109db(0x1cb)))return![];const _0x3e9f68=_0x561044[_0x3109db(0x135)](/'([^']*)'/);if(_0x3e9f68&&_0x3e9f68[0x1]['length']>0x32)return![];if(this[_0x3109db(0x1e8)]===_0x3109db(0x1f7)&&_0x561044['includes']('>')&&_0x561044[_0x3109db(0x14a)]('/')&&!_0x561044['includes']('\x5c'))return![];if(_0x561044[_0x3109db(0x14a)](_0x3109db(0x112))||_0x561044['includes']('\x20||\x20')||_0x561044[_0x3109db(0x14a)](';\x20'))return![];if(_0x561044['includes']('$(')||_0x561044['includes']('`')||_0x561044[_0x3109db(0x14a)]('{')||_0x561044[_0x3109db(0x14a)]('['))return![];if(_0x110abc['includes'](_0x3109db(0x1f8))||_0x110abc[_0x3109db(0x14a)](_0x3109db(0x1bd))||_0x110abc[_0x3109db(0x14a)]('if\x20'))return![];if(_0x110abc['includes']('export ')||_0x110abc['includes'](_0x3109db(0x1ae)))return![];if(_0x561044[_0x3109db(0x14a)](_0x3109db(0x19d))||_0x561044['includes']('\x20>\x20&'))return![];return!![];}async[a0_0xc176c6(0x110)](_0x23004a,_0x54ec1f){const _0x159ef5=a0_0xc176c6;let _0x2103e3=_0x54ec1f[_0x159ef5(0xb5)];if(!_0x2103e3&&_0x54ec1f[_0x159ef5(0x194)]&&_0x54ec1f['agentId']){const _0x51428c=_0x54ec1f[_0x159ef5(0x121)];_0x51428c&&_0x51428c[_0x159ef5(0xb5)]&&(_0x2103e3=_0x51428c['aiService']);}if(!_0x2103e3)throw new Error('AI\x20service\x20not\x20available\x20for\x20command\x20translation');const _0x41af10=this[_0x159ef5(0x102)](_0x23004a),_0x1f6d14='gpt-4-mini';try{const _0x1497cf=await _0x2103e3['sendMessage'](_0x1f6d14,_0x41af10,{'agentId':_0x54ec1f[_0x159ef5(0x118)],'temperature':0.1,'maxTokens':0xc8,'apiKey':_0x54ec1f[_0x159ef5(0x103)],'customApiKeys':_0x54ec1f[_0x159ef5(0x197)],'platformProvided':_0x54ec1f[_0x159ef5(0x1a6)]}),_0x1ac16d=this[_0x159ef5(0xf0)](_0x1497cf['content']);return this[_0x159ef5(0xc8)]?.['debug'](_0x159ef5(0x124),{'original':_0x23004a,'translated':_0x1ac16d,'model':_0x1f6d14,'terminal':this['detectedTerminal']}),_0x1ac16d;}catch(_0x88ccd1){this[_0x159ef5(0xc8)]?.[_0x159ef5(0x183)]('AI\x20command\x20translation\x20failed',{'command':_0x23004a,'terminal':this[_0x159ef5(0x1e8)],'error':_0x88ccd1['message']});throw _0x88ccd1;}}['buildTranslationPrompt'](_0x30f302){const _0x5c67e7=a0_0xc176c6,_0x102b5d={'cmd':'Windows\x20Command\x20Prompt\x20(cmd.exe)','powershell':'Windows\x20PowerShell','bash':'Bash\x20shell\x20(Linux/Unix/macOS)'},_0x5887d0=_0x102b5d[this['detectedTerminal']]||this['detectedTerminal'],_0x554bc8=this[_0x5c67e7(0x1db)](_0x30f302);let _0x1d06b2='Translate\x20this\x20command\x20to\x20work\x20correctly\x20in\x20'+_0x5887d0+_0x5c67e7(0x1d7)+_0x30f302+'\x0a```\x0a\x0aCOMMAND\x20ANALYSIS:\x0a-\x20Command\x20Type:\x20'+_0x554bc8[_0x5c67e7(0x13f)]+_0x5c67e7(0x198)+_0x554bc8[_0x5c67e7(0x10c)]+_0x5c67e7(0x173)+_0x5887d0+_0x5c67e7(0x185)+(_0x554bc8['specificIssues'][_0x5c67e7(0x15e)](',\x20')||'None\x20detected');return _0x554bc8[_0x5c67e7(0x13f)]===_0x5c67e7(0x15d)&&_0x554bc8['alternatives']&&_0x554bc8['alternatives'][this[_0x5c67e7(0x1e8)]]&&(_0x1d06b2+='\x0a-\x20Suggested\x20Alternative:\x20'+_0x554bc8[_0x5c67e7(0x117)][this['detectedTerminal']]),_0x1d06b2+=_0x5c67e7(0x184)+_0x5887d0+'\x0a2.\x20Preserve\x20the\x20original\x20intent\x20and\x20functionality\x0a3.\x20Handle\x20file\x20paths,\x20quoting,\x20and\x20syntax\x20correctly\x0a4.\x20If\x20creating\x20files,\x20ensure\x20proper\x20encoding\x20and\x20line\x20endings\x0a5.\x20Address\x20the\x20specific\x20compatibility\x20issues\x20identified\x20above\x0a6.\x20Return\x20ONLY\x20the\x20translated\x20command,\x20nothing\x20else\x0a\x0aTRANSLATED\x20COMMAND:',_0x1d06b2;}['extractTranslatedCommand'](_0x32ae5a){const _0x56b705=a0_0xc176c6;let _0x1ff764=_0x32ae5a['replace'](/```[a-z]*\n?(.*?)\n?```/s,'$1');_0x1ff764=_0x1ff764['replace'](/^(TRANSLATED COMMAND:|Command:|Result:)\s*/i,'');const _0x3fa6fb=_0x1ff764['trim']()[_0x56b705(0x1b2)]('\x0a');return _0x3fa6fb['length']>0x1&&!_0x1ff764['includes']('&&')&&!_0x1ff764['includes']('||')&&(_0x1ff764=_0x3fa6fb[0x0]['trim']()),_0x1ff764[_0x56b705(0x138)]();}['analyzeCommandCompatibility'](_0x591fa8){const _0x240def=a0_0xc176c6,_0x3c8588=this[_0x240def(0x137)](_0x591fa8),_0x4c6710=this[_0x240def(0x153)](_0x3c8588,this[_0x240def(0x1e8)]);return{'compatible':_0x4c6710,'detectedTerminal':this[_0x240def(0x1e8)],'commandType':_0x3c8588['type'],'commandCategory':_0x3c8588['category'],'specificIssues':_0x3c8588['issues'],'suggestedAction':_0x4c6710?'execute':'translate','confidence':_0x3c8588[_0x240def(0x14c)]};}[a0_0xc176c6(0x16e)](_0x268881){const _0x17e93e=a0_0xc176c6;return this[_0x17e93e(0x1db)](_0x268881)[_0x17e93e(0x1dd)];}['classifyCommand'](_0x548ed3){const _0x2e430d=a0_0xc176c6,_0x1aaf36=_0x548ed3['toLowerCase']()['trim'](),_0x1c2c2f=_0x1aaf36['split']('\x20')[0x0],_0x41207f=[];let _0x18b6e2=0.9;const _0x2e1489={'ls':{'category':'file-listing','alternatives':{'cmd':'dir','powershell':_0x2e430d(0x100)}},'cat':{'category':_0x2e430d(0xe0),'alternatives':{'cmd':'type','powershell':'Get-Content'}},'grep':{'category':'text-search','alternatives':{'cmd':'findstr','powershell':_0x2e430d(0xc0)}},'find':{'category':'file-search','alternatives':{'cmd':'dir\x20/s','powershell':'Get-ChildItem\x20-Recurse'}},'head':{'category':'file-viewing','alternatives':{'cmd':_0x2e430d(0x1bf),'powershell':_0x2e430d(0x13d)}},'tail':{'category':'file-viewing','alternatives':{'cmd':_0x2e430d(0xda),'powershell':'Get-Content\x20-Tail'}},'wc':{'category':'text-analysis','alternatives':{'cmd':_0x2e430d(0x1eb),'powershell':_0x2e430d(0x1ad)}},'cp':{'category':_0x2e430d(0x156),'alternatives':{'cmd':'copy','powershell':_0x2e430d(0x13a)}},'mv':{'category':'file-move','alternatives':{'cmd':'move','powershell':_0x2e430d(0x158)}},'rm':{'category':_0x2e430d(0x199),'alternatives':{'cmd':'del','powershell':'Remove-Item'}},'mkdir':{'category':'directory-create','alternatives':{'cmd':_0x2e430d(0xd7),'powershell':'New-Item\x20-Type\x20Directory'}},'rmdir':{'category':_0x2e430d(0x1ec),'alternatives':{'cmd':'rmdir','powershell':_0x2e430d(0xc4)}},'touch':{'category':_0x2e430d(0x1a8),'alternatives':{'cmd':'type\x20nul\x20>','powershell':_0x2e430d(0x11e)}},'chmod':{'category':'permissions','alternatives':{'cmd':_0x2e430d(0x129),'powershell':_0x2e430d(0x1be)}},'chown':{'category':'ownership','alternatives':{'cmd':_0x2e430d(0x1e9),'powershell':_0x2e430d(0x1be)}},'ps':{'category':'process-list','alternatives':{'cmd':'tasklist','powershell':'Get-Process'}},'kill':{'category':'process-kill','alternatives':{'cmd':_0x2e430d(0x1ce),'powershell':_0x2e430d(0x14f)}},'killall':{'category':'process-kill','alternatives':{'cmd':'taskkill\x20/f\x20/im','powershell':_0x2e430d(0x1a7)}},'top':{'category':'process-monitor','alternatives':{'cmd':_0x2e430d(0x164),'powershell':_0x2e430d(0x1b4)}},'wget':{'category':'download','alternatives':{'cmd':'curl','powershell':_0x2e430d(0x1b7)}},'curl':{'category':_0x2e430d(0x180),'alternatives':{'cmd':_0x2e430d(0x1c3),'powershell':_0x2e430d(0xe4)}},'ping':{'category':'network-test','alternatives':{'cmd':_0x2e430d(0x1bc),'powershell':'Test-NetConnection'}},'awk':{'category':'text-processing','alternatives':{'cmd':'for\x20/f','powershell':'ForEach-Object'}},'sed':{'category':_0x2e430d(0xb4),'alternatives':{'cmd':_0x2e430d(0x1de),'powershell':'native'}},'sort':{'category':'text-sort','alternatives':{'cmd':'sort','powershell':'Sort-Object'}},'uniq':{'category':_0x2e430d(0x106),'alternatives':{'cmd':'sort\x20/unique','powershell':_0x2e430d(0xd0)}},'pwd':{'category':_0x2e430d(0x1c7),'alternatives':{'cmd':'cd','powershell':'Get-Location'}},'whoami':{'category':'user-info','alternatives':{'cmd':'echo\x20%USERNAME%','powershell':'whoami'}},'env':{'category':_0x2e430d(0xe1),'alternatives':{'cmd':'set','powershell':'Get-ChildItem\x20Env:'}},'export':{'category':_0x2e430d(0xe1),'alternatives':{'cmd':_0x2e430d(0xbd),'powershell':'$env:'}},'source':{'category':'script-execute','alternatives':{'cmd':'call','powershell':'.\x20'}},'tar':{'category':'archive','alternatives':{'cmd':'7z','powershell':_0x2e430d(0x1cd)}},'zip':{'category':'archive','alternatives':{'cmd':_0x2e430d(0xf3),'powershell':'Compress-Archive'}},'unzip':{'category':_0x2e430d(0x167),'alternatives':{'cmd':'powershell\x20Expand-Archive','powershell':_0x2e430d(0x134)}},'df':{'category':'disk-info','alternatives':{'cmd':_0x2e430d(0x1e0),'powershell':_0x2e430d(0x171)}},'du':{'category':_0x2e430d(0x166),'alternatives':{'cmd':'dir\x20/s','powershell':_0x2e430d(0xec)}},'free':{'category':'memory-info','alternatives':{'cmd':_0x2e430d(0xf8),'powershell':_0x2e430d(0x1d0)}},'uname':{'category':_0x2e430d(0x111),'alternatives':{'cmd':'systeminfo','powershell':'Get-ComputerInfo'}}},_0x76095={'dir':{'category':_0x2e430d(0x1f1),'alternatives':{'unix':'ls','powershell':_0x2e430d(0x100)}},'type':{'category':'file-viewing','alternatives':{'unix':_0x2e430d(0xd1),'powershell':'Get-Content'}},'copy':{'category':'file-copy','alternatives':{'unix':'cp','powershell':_0x2e430d(0x13a)}},'move':{'category':'file-move','alternatives':{'unix':'mv','powershell':'Move-Item'}},'del':{'category':_0x2e430d(0x199),'alternatives':{'unix':'rm','powershell':'Remove-Item'}},'tasklist':{'category':_0x2e430d(0xca),'alternatives':{'unix':'ps','powershell':_0x2e430d(0x142)}},'taskkill':{'category':_0x2e430d(0x1fd),'alternatives':{'unix':'kill','powershell':'Stop-Process'}},'findstr':{'category':'text-search','alternatives':{'unix':'grep','powershell':_0x2e430d(0xc0)}}},_0x5e217e={'get-childitem':{'category':_0x2e430d(0x1f1),'alternatives':{'unix':'ls','cmd':_0x2e430d(0x1f4)}},'get-content':{'category':'file-viewing','alternatives':{'unix':_0x2e430d(0xd1),'cmd':_0x2e430d(0x12a)}},'copy-item':{'category':_0x2e430d(0x156),'alternatives':{'unix':'cp','cmd':_0x2e430d(0x1a3)}},'move-item':{'category':_0x2e430d(0x146),'alternatives':{'unix':'mv','cmd':_0x2e430d(0x17b)}},'remove-item':{'category':'file-delete','alternatives':{'unix':'rm','cmd':'del'}},'get-process':{'category':'process-list','alternatives':{'unix':'ps','cmd':'tasklist'}},'stop-process':{'category':_0x2e430d(0x1fd),'alternatives':{'unix':_0x2e430d(0x17e),'cmd':_0x2e430d(0x1ce)}}};let _0x364aa6='unknown',_0x409c6f=_0x2e430d(0xba),_0x11f0c7={};if(_0x2e1489[_0x1c2c2f])_0x364aa6='unix',_0x409c6f=_0x2e1489[_0x1c2c2f]['category'],_0x11f0c7=_0x2e1489[_0x1c2c2f][_0x2e430d(0x117)];else{if(_0x76095[_0x1c2c2f])_0x364aa6='windows-cmd',_0x409c6f=_0x76095[_0x1c2c2f][_0x2e430d(0xbc)],_0x11f0c7=_0x76095[_0x1c2c2f]['alternatives'];else{if(_0x5e217e[_0x1c2c2f])_0x364aa6='powershell',_0x409c6f=_0x5e217e[_0x1c2c2f]['category'],_0x11f0c7=_0x5e217e[_0x1c2c2f][_0x2e430d(0x117)];else{const _0x17ba47=[_0x2e430d(0x12e),'cd',_0x2e430d(0x186),'help'];_0x17ba47[_0x2e430d(0x14a)](_0x1c2c2f)?(_0x364aa6='universal',_0x409c6f=_0x2e430d(0x1c2)):(_0x364aa6=_0x2e430d(0xba),_0x18b6e2=0.3);}}}return _0x548ed3[_0x2e430d(0x14a)]('\x27')&&!_0x548ed3['includes']('\x22')&&_0x41207f[_0x2e430d(0xef)]('single-quotes-problematic'),_0x548ed3['includes']('/')&&!_0x548ed3[_0x2e430d(0x14a)]('\x5c')&&!_0x548ed3[_0x2e430d(0x14a)]('http')&&_0x548ed3[_0x2e430d(0x14a)]('>')&&_0x41207f[_0x2e430d(0xef)](_0x2e430d(0xe9)),(_0x548ed3[_0x2e430d(0x14a)]('\x5cn')||_0x548ed3['includes']('\x5ct'))&&_0x41207f[_0x2e430d(0xef)]('escape-sequences'),(_0x548ed3['includes'](_0x2e430d(0x112))||_0x548ed3[_0x2e430d(0x14a)](_0x2e430d(0xbe))||_0x548ed3[_0x2e430d(0x14a)](';'))&&_0x41207f[_0x2e430d(0xef)]('command-chaining'),{'type':_0x364aa6,'category':_0x409c6f,'alternatives':_0x11f0c7,'issues':_0x41207f,'confidence':_0x18b6e2,'firstWord':_0x1c2c2f,'fullCommand':_0x548ed3};}[a0_0xc176c6(0x153)](_0x55d2a5,_0x68cd0e){const _0x4b911b=a0_0xc176c6;switch(_0x68cd0e){case'cmd':if(_0x55d2a5['type']===_0x4b911b(0x15d))return![];if(_0x55d2a5['issues']['includes'](_0x4b911b(0x1b0)))return![];if(_0x55d2a5[_0x4b911b(0xb1)][_0x4b911b(0x14a)](_0x4b911b(0xe9)))return![];return _0x55d2a5[_0x4b911b(0x12a)]===_0x4b911b(0xdf)||_0x55d2a5[_0x4b911b(0x12a)]==='universal';case _0x4b911b(0x150):if(_0x55d2a5[_0x4b911b(0x12a)]===_0x4b911b(0x15d)&&!_0x55d2a5['alternatives']['powershell'])return![];return!![];case'bash':if(_0x55d2a5[_0x4b911b(0x12a)]===_0x4b911b(0xdf))return![];return _0x55d2a5[_0x4b911b(0x12a)]===_0x4b911b(0x15d)||_0x55d2a5['type']==='universal';default:return![];}}['translateToWindowsCmd'](_0x13229b){const _0x79a123=a0_0xc176c6;let _0x32a178=_0x13229b;const _0x33c00b=new Map([[/^ls\s*$/,_0x79a123(0x1f4)],[/^ls\s+-la?$/,_0x79a123(0x1f4)],[/^ls\s+-l$/,'dir'],[/^ls\s+-a$/,'dir\x20/a'],[/^cat\s+(.+)$/,'type\x20$1'],[/^cp\s+(.+)\s+(.+)$/,_0x79a123(0xcc)],[/^mv\s+(.+)\s+(.+)$/,'move\x20$1\x20$2'],[/^rm\s+(.+)$/,_0x79a123(0x1d3)],[/^mkdir\s+(.+)$/,_0x79a123(0x1ab)],[/^rmdir\s+(.+)$/,'rmdir\x20$1'],[/^ps\s*$/,'tasklist'],[/^kill\s+(.+)$/,_0x79a123(0xfb)],[/^pwd\s*$/,'cd'],[/^whoami\s*$/,'echo\x20%USERNAME%'],[/^ping\s+(.+)$/,_0x79a123(0x1ea)],[/^wget\s+(.+)$/,_0x79a123(0xaf)],[/^curl\s+(.+)$/,_0x79a123(0x1b8)]]);for(const [_0x4ee9dd,_0x484faa]of _0x33c00b){if(_0x4ee9dd['test'](_0x32a178)){_0x32a178=_0x32a178['replace'](_0x4ee9dd,_0x484faa);break;}}_0x32a178=_0x32a178[_0x79a123(0x1a2)](/echo\s+'([^']+)'\s*>/g,_0x79a123(0x139)),_0x32a178=_0x32a178['replace'](/echo\s+'([^']+)'$/g,_0x79a123(0x1f2));if(_0x32a178[_0x79a123(0x14a)]('echo\x20\x27')&&_0x32a178['includes']('\x5cn')){const _0x4c20c6=_0x32a178['match'](/echo\s+'(.+?)'\s*>\s*(.+)$/);if(_0x4c20c6){const _0x2e7100=_0x4c20c6[0x1][_0x79a123(0x1a2)](/\\n/g,'\x0a'),_0x2ac397=_0x4c20c6[0x2],_0x2762b1=_0x2e7100['split']('\x0a');_0x32a178='('+_0x2762b1['map'](_0x1b44d4=>_0x79a123(0x154)+_0x1b44d4)['join'](_0x79a123(0xd8))+_0x79a123(0x11d)+_0x2ac397;}}return this['logger']?.['info']('Command\x20translated\x20for\x20Windows\x20CMD',{'original':_0x13229b,'translated':_0x32a178}),_0x32a178;}[a0_0xc176c6(0x1d9)](_0x2da7dd){const _0xb4f655=a0_0xc176c6;let _0x1eca2a=_0x2da7dd;const _0x593032=new Map([[/^ls\s*$/,_0xb4f655(0x100)],[/^ls\s+-la?$/,'Get-ChildItem\x20-Force'],[/^cat\s+(.+)$/,'Get-Content\x20$1'],[/^cp\s+(.+)\s+(.+)$/,_0xb4f655(0xb7)],[/^mv\s+(.+)\s+(.+)$/,'Move-Item\x20$1\x20$2'],[/^rm\s+(.+)$/,'Remove-Item\x20$1'],[/^pwd\s*$/,'Get-Location'],[/^ps\s*$/,'Get-Process']]);for(const [_0x27de94,_0x16aa82]of _0x593032){if(_0x27de94[_0xb4f655(0xb8)](_0x1eca2a)){_0x1eca2a=_0x1eca2a[_0xb4f655(0x1a2)](_0x27de94,_0x16aa82);break;}}return this['logger']?.[_0xb4f655(0x174)]('Command\x20translated\x20for\x20PowerShell',{'original':_0x2da7dd,'translated':_0x1eca2a}),_0x1eca2a;}['translateToBash'](_0x2029cc){const _0x5bffff=a0_0xc176c6;let _0x200cff=_0x2029cc;const _0x1b8ec5=new Map([[/^dir\s*$/,'ls'],[/^dir\s+\/a$/,_0x5bffff(0x16b)],[/^type\s+(.+)$/,'cat\x20$1'],[/^copy\s+(.+)\s+(.+)$/,_0x5bffff(0xf6)],[/^move\s+(.+)\s+(.+)$/,_0x5bffff(0x113)],[/^del\s+(.+)$/,_0x5bffff(0x10f)],[/^tasklist\s*$/,'ps'],[/^cd\s*$/,_0x5bffff(0x122)]]);for(const [_0x23500f,_0x4cf4af]of _0x1b8ec5){if(_0x23500f['test'](_0x200cff)){_0x200cff=_0x200cff[_0x5bffff(0x1a2)](_0x23500f,_0x4cf4af);break;}}return _0x200cff;}async[a0_0xc176c6(0x188)](_0x2a4e39){}async['startBackgroundCommand'](_0xd7bd41,_0x171132,_0x31e233={}){const _0x3e89ab=a0_0xc176c6,{agentId:_0x58a4bc,context:_0x255cd3}=_0x31e233;if(!_0x58a4bc)throw new Error('agentId\x20is\x20required\x20for\x20background\x20commands');const _0x24155b=this[_0x3e89ab(0x15f)](_0x58a4bc),_0x1bf374=_0x24155b[_0x3e89ab(0x157)](_0x563c9e=>_0x563c9e['state']==='running'||_0x563c9e[_0x3e89ab(0x11f)]===_0x3e89ab(0xf4));if(_0x1bf374['length']>=this[_0x3e89ab(0x18a)])throw new Error('Maximum\x20background\x20commands\x20per\x20agent\x20exceeded\x20('+this['MAX_BACKGROUND_COMMANDS_PER_AGENT']+')');const _0x35878e=Array['from'](this['commandTracker'][_0x3e89ab(0x1e2)]()),_0xace7df=_0x35878e['filter'](_0x47beba=>_0x47beba[_0x3e89ab(0x11f)]===_0x3e89ab(0x152)||_0x47beba['state']===_0x3e89ab(0xf4));if(_0xace7df[_0x3e89ab(0xbf)]>=this[_0x3e89ab(0xb0)])throw new Error(_0x3e89ab(0x17f)+this[_0x3e89ab(0xb0)]+')');const _0x2b52f1=_0x58a4bc+_0x3e89ab(0x1a1)+Date[_0x3e89ab(0x1da)]()+'-'+ ++this['commandIdCounter'],_0x1a2788=_0xd7bd41;let _0x4075b1;try{_0x4075b1=await this['translateCommand'](_0xd7bd41,{'agentId':_0x58a4bc,'toolsRegistry':_0x255cd3?.[_0x3e89ab(0x194)],'messageProcessor':_0x255cd3?.[_0x3e89ab(0x121)],'aiService':_0x255cd3?.[_0x3e89ab(0xb5)],'apiKey':_0x255cd3?.[_0x3e89ab(0x103)],'customApiKeys':_0x255cd3?.[_0x3e89ab(0x197)],'platformProvided':_0x255cd3?.['platformProvided']});}catch(_0x50a45d){this['logger']?.['warn']('Command\x20translation\x20failed,\x20using\x20original\x20command',{'originalCommand':_0x1a2788,'error':_0x50a45d['message']}),_0x4075b1=_0xd7bd41;}this[_0x3e89ab(0xc8)]?.['info'](_0x3e89ab(0xe7)+_0x4075b1,{'commandId':_0x2b52f1,'agentId':_0x58a4bc,'originalCommand':_0x1a2788,'workingDirectory':_0x171132});let _0x4cd0cf;if(this['detectedTerminal']===_0x3e89ab(0x1f7)||this[_0x3e89ab(0x1e8)]===_0x3e89ab(0x150)){const _0x27e03d=this['detectedTerminal']===_0x3e89ab(0x150)?'powershell':'cmd',_0x1c54e5=this['detectedTerminal']==='powershell'?['-Command',_0x4075b1]:['/c',_0x4075b1];_0x4cd0cf=spawn(_0x27e03d,_0x1c54e5,{'cwd':_0x171132,'env':{...process[_0x3e89ab(0x16f)]},'windowsHide':!![],'stdio':[_0x3e89ab(0x125),_0x3e89ab(0x125),_0x3e89ab(0x125)]});}else _0x4cd0cf=spawn('sh',['-c',_0x4075b1],{'cwd':_0x171132,'env':{...process[_0x3e89ab(0x16f)]},'stdio':[_0x3e89ab(0x125),'pipe',_0x3e89ab(0x125)]});const _0x25738e={'commandId':_0x2b52f1,'agentId':_0x58a4bc,'pid':_0x4cd0cf['pid'],'command':_0x1a2788,'translatedCommand':_0x4075b1,'workingDirectory':_0x171132,'startTime':new Date()[_0x3e89ab(0x179)](),'state':'running','exitCode':null,'stdoutBuffer':'','stderrBuffer':'','lastOutputTime':Date['now'](),'promptDetected':null,'process':_0x4cd0cf};return this[_0x3e89ab(0x18b)][_0x3e89ab(0xbd)](_0x2b52f1,_0x25738e),_0x4cd0cf[_0x3e89ab(0x1d6)]['on']('data',_0x24c85a=>{const _0x3680bf=_0x3e89ab,_0x2c6fc7=_0x24c85a[_0x3680bf(0x120)]();_0x25738e['stdoutBuffer']+=_0x2c6fc7,_0x25738e[_0x3680bf(0x13c)]=Date[_0x3680bf(0x1da)]();if(!_0x25738e[_0x3680bf(0x15c)]){const _0xf0de5c=this['promptDetector']['detectPrompt'](_0x25738e['stdoutBuffer'],'stdout');_0xf0de5c&&(_0x25738e[_0x3680bf(0x15c)]=_0xf0de5c,_0x25738e['state']=_0x3680bf(0xf4),this[_0x3680bf(0xc8)]?.[_0x3680bf(0x174)]('Prompt\x20detected\x20in\x20background\x20command',{'commandId':_0x2b52f1,'agentId':_0x58a4bc,'type':_0xf0de5c[_0x3680bf(0x12a)],'matchedText':_0xf0de5c[_0x3680bf(0x191)]}));}}),_0x4cd0cf['stderr']['on'](_0x3e89ab(0x1a9),_0x2fe117=>{const _0x4bd431=_0x3e89ab,_0x407417=_0x2fe117['toString']();_0x25738e['stderrBuffer']+=_0x407417,_0x25738e[_0x4bd431(0x13c)]=Date[_0x4bd431(0x1da)]();if(!_0x25738e[_0x4bd431(0x15c)]){const _0x40436d=this['promptDetector'][_0x4bd431(0x163)](_0x25738e[_0x4bd431(0x136)],_0x4bd431(0x14b));_0x40436d&&(_0x25738e['promptDetected']=_0x40436d,_0x25738e['state']='waiting_for_input',this[_0x4bd431(0xc8)]?.['info'](_0x4bd431(0x12f),{'commandId':_0x2b52f1,'agentId':_0x58a4bc,'type':_0x40436d['type'],'matchedText':_0x40436d[_0x4bd431(0x191)]}));}}),_0x4cd0cf['on'](_0x3e89ab(0x186),(_0x5217bb,_0x532007)=>{const _0x5e3471=_0x3e89ab;_0x25738e[_0x5e3471(0x165)]=_0x5217bb,_0x25738e['state']=_0x5217bb===0x0?_0x5e3471(0x12c):'failed',_0x25738e[_0x5e3471(0x1a5)]=new Date()[_0x5e3471(0x179)](),this['logger']?.[_0x5e3471(0x174)](_0x5e3471(0x1c1),{'commandId':_0x2b52f1,'agentId':_0x58a4bc,'exitCode':_0x5217bb,'signal':_0x532007,'state':_0x25738e[_0x5e3471(0x11f)]});}),_0x4cd0cf['on']('error',_0xb1c236=>{const _0x3bacab=_0x3e89ab;_0x25738e['state']='failed',_0x25738e[_0x3bacab(0x183)]=_0xb1c236[_0x3bacab(0xff)],_0x25738e[_0x3bacab(0x1a5)]=new Date()['toISOString'](),this['logger']?.['error'](_0x3bacab(0x107),{'commandId':_0x2b52f1,'agentId':_0x58a4bc,'error':_0xb1c236['message']});}),{'success':!![],'commandId':_0x2b52f1,'pid':_0x4cd0cf[_0x3e89ab(0xf7)],'command':_0x1a2788,'translatedCommand':_0x4075b1,'workingDirectory':_0x171132,'message':_0x3e89ab(0x1e1)+_0x2b52f1};}[a0_0xc176c6(0x105)](_0x340d06,_0x56d253,_0x2b36b6){const _0x20d925=a0_0xc176c6,_0x5c7cac=this[_0x20d925(0x1cc)](_0x340d06,_0x2b36b6);if(_0x5c7cac[_0x20d925(0x11f)]==='completed'||_0x5c7cac[_0x20d925(0x11f)]===_0x20d925(0xc1))throw new Error('Cannot\x20send\x20input\x20to\x20'+_0x5c7cac[_0x20d925(0x11f)]+'\x20command');if(!_0x5c7cac['process']||_0x5c7cac['process']['killed'])throw new Error('Command\x20process\x20is\x20not\x20running');const _0x31201d=_0x56d253[_0x20d925(0x131)]('\x0a')?_0x56d253:_0x56d253+'\x0a';return _0x5c7cac['process'][_0x20d925(0x18f)]['write'](_0x31201d),this['logger']?.['info'](_0x20d925(0xb2),{'commandId':_0x340d06,'agentId':_0x2b36b6,'inputLength':_0x56d253[_0x20d925(0xbf)]}),_0x5c7cac['state']===_0x20d925(0xf4)&&(_0x5c7cac[_0x20d925(0x11f)]=_0x20d925(0x152),_0x5c7cac[_0x20d925(0x15c)]=null),{'success':!![],'commandId':_0x340d06,'message':'Input\x20sent\x20successfully'};}['getCommandStatus'](_0x3af1de,_0x46c98f){const _0x5d0d18=a0_0xc176c6,_0x183f2e=this['validateCommandOwnership'](_0x3af1de,_0x46c98f),_0x16ffe8=Date[_0x5d0d18(0x1da)]()-_0x183f2e['lastOutputTime'];return{'success':!![],'commandId':_0x3af1de,'pid':_0x183f2e[_0x5d0d18(0xf7)],'command':_0x183f2e['command'],'state':_0x183f2e['state'],'exitCode':_0x183f2e['exitCode'],'startTime':_0x183f2e[_0x5d0d18(0x192)],'endTime':_0x183f2e[_0x5d0d18(0x1a5)],'workingDirectory':_0x183f2e['workingDirectory'],'stdout':_0x183f2e[_0x5d0d18(0x147)],'stderr':_0x183f2e[_0x5d0d18(0x136)],'stdoutLength':_0x183f2e[_0x5d0d18(0x147)][_0x5d0d18(0xbf)],'stderrLength':_0x183f2e[_0x5d0d18(0x136)]['length'],'lastOutputTime':_0x183f2e[_0x5d0d18(0x13c)],'timeSinceLastOutput':_0x16ffe8,'promptDetected':!!_0x183f2e[_0x5d0d18(0x15c)],'promptInfo':_0x183f2e['promptDetected']||undefined};}[a0_0xc176c6(0x10a)](_0x5e603b,_0x57e83c){const _0x16d6be=a0_0xc176c6,_0x358ded=this[_0x16d6be(0x1cc)](_0x5e603b,_0x57e83c);if(_0x358ded['state']==='completed'||_0x358ded['state']===_0x16d6be(0xc1))return{'success':!![],'commandId':_0x5e603b,'message':'Command\x20already\x20terminated','state':_0x358ded['state']};if(_0x358ded['process']&&!_0x358ded[_0x16d6be(0x1bb)][_0x16d6be(0xe5)])return _0x358ded[_0x16d6be(0x1bb)]['kill'](_0x16d6be(0xe2)),setTimeout(()=>{const _0x389fd7=_0x16d6be;_0x358ded[_0x389fd7(0x1bb)]&&!_0x358ded[_0x389fd7(0x1bb)]['killed']&&_0x358ded['process']['kill']('SIGKILL');},0x1388),this[_0x16d6be(0xc8)]?.['info']('Background\x20command\x20killed',{'commandId':_0x5e603b,'agentId':_0x57e83c}),{'success':!![],'commandId':_0x5e603b,'message':'Command\x20killed\x20successfully'};return{'success':![],'commandId':_0x5e603b,'error':_0x16d6be(0x17a)};}[a0_0xc176c6(0x19b)](_0x413ff2){const _0x3a5da4=a0_0xc176c6,_0x4f5d9b=this[_0x3a5da4(0x15f)](_0x413ff2);return _0x4f5d9b[_0x3a5da4(0x1f0)](_0x37dede=>({'commandId':_0x37dede['commandId'],'command':_0x37dede['command'],'state':_0x37dede[_0x3a5da4(0x11f)],'pid':_0x37dede['pid'],'exitCode':_0x37dede[_0x3a5da4(0x165)],'startTime':_0x37dede['startTime'],'endTime':_0x37dede[_0x3a5da4(0x1a5)],'promptDetected':!!_0x37dede[_0x3a5da4(0x15c)],'timeSinceLastOutput':Date[_0x3a5da4(0x1da)]()-_0x37dede[_0x3a5da4(0x13c)]}));}['getAgentCommands'](_0x524f2d){const _0x147c19=a0_0xc176c6;return Array[_0x147c19(0x13e)](this[_0x147c19(0x18b)][_0x147c19(0x1e2)]())['filter'](_0x3d24cb=>_0x3d24cb['agentId']===_0x524f2d);}[a0_0xc176c6(0x1cc)](_0x26c80b,_0x1a2e8c){const _0x8e0231=a0_0xc176c6,_0x47cb8e=this['commandTracker']['get'](_0x26c80b);if(!_0x47cb8e)throw new Error('Command\x20not\x20found:\x20'+_0x26c80b);if(_0x47cb8e['agentId']!==_0x1a2e8c)throw new Error(_0x8e0231(0x155)+_0x47cb8e[_0x8e0231(0x118)]);return _0x47cb8e;}async['cleanupAgent'](_0x15328d){const _0xc54fc=a0_0xc176c6,_0x3a8d7a=this[_0xc54fc(0x15f)](_0x15328d);let _0x5be609=0x0,_0x194ca2=0x0;for(const _0x3561dd of _0x3a8d7a){_0x3561dd[_0xc54fc(0x1bb)]&&!_0x3561dd['process'][_0xc54fc(0xe5)]&&(_0x3561dd['process']['kill']('SIGTERM'),_0x5be609++,setTimeout(()=>{const _0x2a2a8b=_0xc54fc;_0x3561dd['process']&&!_0x3561dd[_0x2a2a8b(0x1bb)][_0x2a2a8b(0xe5)]&&_0x3561dd[_0x2a2a8b(0x1bb)]['kill']('SIGKILL');},0xbb8)),this[_0xc54fc(0x18b)]['delete'](_0x3561dd[_0xc54fc(0x11c)]),_0x194ca2++;}return this['logger']?.['info']('Agent\x20commands\x20cleaned\x20up',{'agentId':_0x15328d,'killedCount':_0x5be609,'removedCount':_0x194ca2}),{'success':!![],'agentId':_0x15328d,'killedCount':_0x5be609,'removedCount':_0x194ca2,'message':'Cleaned\x20up\x20'+_0x194ca2+_0xc54fc(0xc9)+_0x15328d};}[a0_0xc176c6(0xdd)](){const _0x45f2dc=a0_0xc176c6,_0x130cf9=Date['now']();let _0x29f2aa=0x0;for(const [_0x4e4358,_0x561751]of this['commandTracker'][_0x45f2dc(0xbb)]()){if(_0x561751[_0x45f2dc(0x11f)]!=='completed'&&_0x561751[_0x45f2dc(0x11f)]!=='failed')continue;const _0x128765=new Date(_0x561751[_0x45f2dc(0x192)])[_0x45f2dc(0xcf)](),_0x5a6ee9=(_0x130cf9-_0x128765)/0x3e8/0x3c;_0x5a6ee9>this[_0x45f2dc(0x1f6)]&&(this['commandTracker']['delete'](_0x4e4358),_0x29f2aa++);}return _0x29f2aa>0x0&&this['logger']?.['info'](_0x45f2dc(0xfc),{'removedCount':_0x29f2aa,'ageThresholdMinutes':this['MAX_COMMAND_AGE_MINUTES']}),{'success':!![],'removedCount':_0x29f2aa,'message':'Cleaned\x20up\x20'+_0x29f2aa+'\x20stale\x20commands'};}}export default TerminalTool;