@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.4

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 +15 -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_0x492ede=a0_0x51ec;(function(_0x7c0f5,_0x29b2b2){const _0x51cd94=a0_0x51ec,_0x5246e5=_0x7c0f5();while(!![]){try{const _0x22287a=-parseInt(_0x51cd94(0x1a9))/0x1*(-parseInt(_0x51cd94(0x145))/0x2)+-parseInt(_0x51cd94(0x10e))/0x3+-parseInt(_0x51cd94(0xaf))/0x4+-parseInt(_0x51cd94(0xb5))/0x5*(parseInt(_0x51cd94(0x131))/0x6)+parseInt(_0x51cd94(0xf8))/0x7*(-parseInt(_0x51cd94(0x1ad))/0x8)+parseInt(_0x51cd94(0x1ab))/0x9*(-parseInt(_0x51cd94(0x1a7))/0xa)+parseInt(_0x51cd94(0x143))/0xb;if(_0x22287a===_0x29b2b2)break;else _0x5246e5['push'](_0x5246e5['shift']());}catch(_0x517d93){_0x5246e5['push'](_0x5246e5['shift']());}}}(a0_0x1590,0xb30a1));function a0_0x51ec(_0x3e158f,_0x4deb0f){_0x3e158f=_0x3e158f-0x8c;const _0x159058=a0_0x1590();let _0x51ecdd=_0x159058[_0x3e158f];if(a0_0x51ec['snwPuF']===undefined){var _0x639cfc=function(_0x550d4c){const _0x2b1cc8='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x25a245='',_0x19528a='';for(let _0x469784=0x0,_0x1bc23b,_0x55e351,_0x35b828=0x0;_0x55e351=_0x550d4c['charAt'](_0x35b828++);~_0x55e351&&(_0x1bc23b=_0x469784%0x4?_0x1bc23b*0x40+_0x55e351:_0x55e351,_0x469784++%0x4)?_0x25a245+=String['fromCharCode'](0xff&_0x1bc23b>>(-0x2*_0x469784&0x6)):0x0){_0x55e351=_0x2b1cc8['indexOf'](_0x55e351);}for(let _0xbcb487=0x0,_0x1768d4=_0x25a245['length'];_0xbcb487<_0x1768d4;_0xbcb487++){_0x19528a+='%'+('00'+_0x25a245['charCodeAt'](_0xbcb487)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x19528a);};a0_0x51ec['Efayte']=_0x639cfc,a0_0x51ec['aDvgFB']={},a0_0x51ec['snwPuF']=!![];}const _0x5f1a46=_0x159058[0x0],_0x22ce00=_0x3e158f+_0x5f1a46,_0x1d87bc=a0_0x51ec['aDvgFB'][_0x22ce00];return!_0x1d87bc?(_0x51ecdd=a0_0x51ec['Efayte'](_0x51ecdd),a0_0x51ec['aDvgFB'][_0x22ce00]=_0x51ecdd):_0x51ecdd=_0x1d87bc,_0x51ecdd;}import{BaseTool}from'./baseTool.js';import a0_0x25a245 from'../utilities/tagParser.js';import a0_0x19528a from'../utilities/directoryAccessManager.js';import{spawn,exec}from'child_process';import a0_0x469784 from'path';import a0_0x1bc23b from'fs/promises';function a0_0x1590(){const _0x138899=['C2v0','CM0GlxjMic8','Cg93zxjZAgvSBcbfEhbHBMqTqxjJAgL2zq','uMvTB3zLluL0zw0Gjde','zNvUy3rPB24G','ksa+ia','y29UzMLYBwf0Aw9U','y2f0','n2LizeTcrW','yxn5BMm','q29TBwfUzcbUB3qGzM91BMq6ia','A2v5ChjLC3m','z2v0vgLTzq','Aw5KzxG','y3jLyxrLlwrPCMvJDg9YEq','CgXHDgzVCM1uExbL','y21K','zxjYB3i','vw5RBM93BIbHy3rPB24GDhLWztOG','yxjJAgL2zq','z2v0lxDVCMTPBMCTzgLYzwn0B3j5','z2v0rgvZy3jPChrPB24','DhjHBNnSyxrLq29TBwfUza','z3b0ltqTBwLUAq','C3rKB3v0qNvMzMvY','D2fPDgLUz19MB3jFAw5WDxq','quKGDhjHBNnSyxrPB24GzMfPBgvKlcbMywXSAw5NigjHy2SGDg8GC2LTCgXLihrYyw5ZBgf0Aw9U','quKGDhjHBNnSyxrPB24GCMv0DxjUzwqGC2fTzsbJB21Tyw5K','qMfJA2DYB3vUzcbJB21Tyw5KigTPBgXLza','Cg93zxjZAgvSBa','otyWntuYzvfhu0fz','DhjHBNnSyxrLq29TBwfUzfDPDgHbsq','y29WEsaKmsaKmG','ywLtzxj2AwnL','Bwf0y2HLzfrLEhq','C3rHDgu','q29TBwfUzcbJB21WyxrPyMLSAxr5igfUywX5C2LZ','Bwf4q29TBwfUzefNzu1PBNv0zxm','Aw5WDxq','BgvUz3rO','zM9Yic9M','y3vYBcaKmq','z2v0q29TBwfUzeHPC3rVCNK','CgvYBwLZC2LVBNm','AM9PBG','Bxm6ia','sw52B2TLlvjLC3rnzxrOB2q','C3rHCNrZv2L0Aa','zMLSzs1JB3b5','zMLSzq','CNvUlwnVBw1HBMq','D29YA2LUz0rPCMvJDg9YEq','r2v0lunOAwXKsxrLBq','AxndB21Tyw5Kq29TCgf0AwjSzq','D2LUmZi','zxHLy3v0zunVBw1HBMq','q29TBwfUzcb0CMfUC2XHDgLVBIbMywLSzwqSihvZAw5Nig9YAwDPBMfSignVBw1HBMq','CMvZB2X2zq','u2vSzwn0lvn0CMLUzW','r2vUzxjPyYbPBNb1DcbWCM9TChqGzgv0zwn0zwq','q29TBwfUzcbMywLSzwq6ia','C3LZDgvTAw5MBW','y3vZDg9TqxbPs2v5CW','CgfZC3DVCMq','BwvZC2fNzq','nJbbzfrMDfy','u2vSzwn0Aw9UihbYB21WDa','Bw9YzsaRBG','y29UDgLUDwu','zg93BMXVywq','r2v0lunVBNrLBNqGjde','rxHLy3v0Aw5NignVBw1HBMqGD2L0AcbZCgf3BJOG','cI0GvgfYz2v0ifrLCM1PBMfSoIa','z2v0ugfYyw1LDgvYu2nOzw1H','AxnZDwvZ','q29TBwfUzcbRAwXSzwqGC3vJy2vZC2z1BgX5','zgLY','y2HHBMDLrgLYzwn0B3j5','CNvUBMLUzW','r2vUzxjPyYbPBNb1DcbWCM9TChq','zgvIDwC','zgvZy3jPChrPB24','zwnOBYaLvvnfuK5btuuL','ndaYmJmZmJzbA3PAA0q','tMv3luL0zw0Glvr5CguGrMLSzq','nKLLqvPfuW','r2v0lvbYB2nLC3mGFcbtDg9WlvbYB2nLC3m','quKGy29TBwfUzcb0CMfUC2XHDgLVBIbJB21WBgv0zwq','qwXSia','zxHLy3v0zq','oIbJB21Tyw5KigLZihjLCxvPCMvKigzVCIbYDw4Ty29TBwfUza','y2fSBa','AxnbC3LUyW','D2HPBguG','tufyx0nptu1btKrFquDfx01jtLvurvm','Aw5MBW','A2LSBa','quKGy29TBwfUzcb0CMfUC2XHDgLVBIbMywLSzwq','q29TBwfUzcb0Aw1LzcbVDxqGywz0zxiG','zgvSic9Mic9X','Bwf4qMfJA2DYB3vUzenVBw1HBMrZugvYqwDLBNq','CgXHDgzVCM0','DMfSAwrHDgvdB21Tyw5Kt3DUzxjZAgLW','qMfZAcbZAgvSBcaOtgLUDxGVvw5PEc9TywnpuYK','D2fYBG','cGPsrvfvsvjftuvovfm6cJeUie1HA2uGDgHLignVBw1HBMqGD29YAYbJB3jYzwn0BhKGAw4G','r2v0luXVy2f0Aw9U','BxmPcI0Gyxn5BMm6ifDOzxrOzxiGDg8GCNvUignVBw1HBMqGyxn5BMnOCM9UB3vZBhKGkhrYDwuVzMfSC2uPcGPcqunlr1jpvu5eienptu1btKqGtufoquDftuvovcaOqwr2yw5JzwqPoGPgB3iGBg9UzY1YDw5UAw5NignVBw1HBMrZicHUCg0GAw5ZDgfSBcWGz2L0ig9WzxjHDgLVBNmSigj1AwXKCYKSihvZzsbIywnRz3jVDw5KignVBw1HBMqGDhjHy2TPBMC6cGOQkNn0yxj0qMfJA2DYB3vUzenVBw1HBMqOy29TBwfUzcWGD29YA2LUz0rPCIWGE2fNzw50swqSignVBNrLEhr9ksOQcI0Gu3rHCNrZignVBw1HBMqGAw4GyMfJA2DYB3vUzcb3AxrOihn0zgLUigTLChqGB3bLBGOTifjLDhvYBNmGy29TBwfUzeLKigzVCIb0CMfJA2LUzWOTie1HEca','y2XLyw51CefNzw50','q29UzMLYBwf0Aw9UihbYB21WDa','Dg9ju09tDhjPBMC','BMv0D29YAY10zxn0','D2LUzg93CY1JBwq','Dw5PEa','ihX8ia','zMLSzs12Awv3Aw5N','zxHPDenVzgu','y2XLyxjxB3jRAw5NrgLYzwn0B3j5','Dw5PEc1ZDhLSzs1WyxrOCW','z2v0q3vYCMvUDfDVCMTPBMDeAxjLy3rVCNK','y29TBwfUzeHPC3rVCNK','q3jLyxrLzcbKAxjLy3rVCNK6ia','zMLUzcaVyW','ChvZAa','qwDLBNqGy29TBwfUzhmGy2XLyw5Lzcb1Ca','q29UDgLUDwuGChjVBxb0','q2fUBM90ihnLBMqGAw5WDxqGDg8G','cI0Gq2f0zwDVCNK6ia','Bwf4qMfJA2DYB3vUzenVBw1HBMrZr2XVyMfS','qwnJzxnZigrLBMLLzdOG','q29TBwfUzcb0CMfUC2XHDgvKigzVCIbxAw5KB3DZiennra','r2v0lvDTAu9IAMvJDcaTq2XHC3mGv2LUmZjFugH5C2LJywXnzw1VCNK','C3vJy2vZCW','qwn0Aw9Uia','ignVBw1HBMrZigzVCIbHz2vUDca','y29TBwfUza','yw5HBhL6zunVBw1HBMrdB21WyxrPyMLSAxr5','z2v0v29YA2LUz0rPCMvJDg9YEq','Aw5JBhvKzxm','DhjHBNnSyxrLvg9qB3DLCLnOzwXS','ywrKvg9iAxn0B3j5','CM1KAxi','oGOkt1jjr0LoquWGq09ntufordOkygbGcG','u0HfteW','zM9YBwf0','D29YA2LUz0rPCMvJDg9YAwvZ','tufyx0jbq0ThuK9vtKrFq09ntuforfnFr0XpqKfm','BgfZDe91Dhb1DfrPBwu','ywX0zxjUyxrPDMvZ','DgfZA2TPBgWGl1bjrcaKmq','BwTKAxi','y29UDgvUDa','zMLSzs1JCMvHDgu','AxndB21Tyw5Kq29TCgf0AwjSzvDPDgHuzxjTAw5HBa','q29TBwfUzcbJB21WBgv0zwq6ia','twvUDsbZzwXLy3rPB24','uhjLC3mGzw50zxi','wwvZl05Vihf1zxn0Aw9U','Dw5RBM93BG','vxnLCM5HBwuGChjVBxb0','u0Lhvevstq','zw50CMLLCW','uhjVBxb0igrLDgvJDgvKigLUigjHy2TNCM91BMqGy29TBwfUzcbZDgrLCNi','sgL0igvUDgvY','yM9VBgvHBG','q2XLyw5Lzcb1Cca','Bwf4q29Uy3vYCMvUDe9WzxjHDgLVBNm','y2HHBMDLlwrPCMvJDg9YEq','ig9Mia','BwfW','zMLSDgvY','DMfSDwvZ','DgfZA2TPBgWGl2yGl2LT','Dg9tDhjPBMC','rM9YrwfJAc1pyMPLy3q','r2v0lunOAwXKsxrLBsaTuMvJDxjZzsb8ie1Lyxn1CMuTt2jQzwn0','ywXSB3DLzenVBw1HBMrZ','y2XLyw51Cfn0ywXLq29TBwfUzhm','C3rHy2S','C3rKB3v0','C3bLy2LMAwnjC3n1zxm','Cgf0DgvYBG','EwvZlw5V','mtb3z0HlvvO','Aw50zwDLCG','mZiZotK4ENPWDK1x','qMfJA2DYB3vUzcbJB21Tyw5Kihn0yxj0zwqGD2L0AcbjrdOG','mtiXmte0mtDdsNvPEKy','y29Kzq','ota3mtKYDuHkz09O','y29TBwfUzeLKq291BNrLCG','ChjVy2vZCW','r2v0lvbYB2nLC3m','Dw5PDMvYC2fS','ywn0Aw9UCW','z2v0u3vWCg9YDgvKqwn0Aw9UCW','q29TBwfUzcbWCM9JzxnZigLZig5VDcbYDw5UAw5N','zxHLy3v0Aw9UvgLTzq','A2LSBgvK','yMXVy2TLzenVBw1HBMrZ','rMfPBgvKihrVignYzwf0zsbKAxjLy3rVCNKG','zgvSzxrL','zxnJyxbLlxnLCxvLBMnLCW','q29TBwfUzcbLCNjVCIbJAhvUAZOG','ywDLBNrjza','CgLWzq','cMbGyaOkq09ntuforcbbtKfmwvnjuZOklsbdB21Tyw5Kifr5Cgu6ia','yNvPBgruCMfUC2XHDgLVBLbYB21WDa','y29TCgf0AwjSzq','tw92zs1jDgvT','BwvUDq','ufnnB2r1BgvqyxrO','BM93','CMvXDwLYzxnqCM9Qzwn0','CgXHDgzVCM1qCM92AwrLza','zgvMia','y29TCgXLDgvK','DgvZDa','DxnLCI1PBMzV','ChjVBxb0rgv0zwn0B3i','q29TBwfUzcbWCM9JzxnZig5VDcbMB3vUzcbVCIbHBhjLywr5igTPBgXLza','BgLZDefNzw50q29TBwfUzhm','DgfZA2XPC3q','C2H1DgrVD24','y29TBwfUzfr5Cgu','C2vUze1LC3nHz2u','y29WEq','tw92zs1jDgvTicqXicqY','zMfPBgvK','C3rYAw5N','uMvTB3zLluL0zw0','vxnPBMCGquKGDhjHBNnSyxrPB24','CMvWBgfJzq','zxHLy3v0zunVBw1HBMrxAxrOu3bHD24','zgLZAY1PBMzV','Bwf0y2G','C3vIC3rYAw5N','Dg9VBhnszwDPC3rYEq','BwvZC2fNzvbYB2nLC3nVCG','C2XPy2u','zgLYic9Z','AxnbCNjHEq','AxnbBgXVD2vKq29TBwfUza','y3vZDg9TvMfSAwrHDgvqyxjHBwv0zxjZ','rMfPBgvKihrVihbHCNnLihrLCM1PBMfSihbHCMfTzxrLCNm6ia','sw5WDxqGC2vUDcbZDwnJzxnZzNvSBhK','Cg93zxjZAgvSBcaTyW','rxHWyw5KlufYy2HPDMu','zgf0yq','Ahr0Cc1JBgLLBNq','AxneAxjLy3rVCNK','zw52','cJiUifbYzxnLCNzLihrOzsbVCMLNAw5HBcbPBNrLBNqGyw5Kigz1BMn0Aw9UywXPDhKkmY4GsgfUzgXLigzPBguGCgf0AhmSihf1B3rPBMCSigfUzcbZEw50yxGGy29YCMvJDgX5cJqUieLMignYzwf0Aw5NigzPBgvZlcbLBNn1CMuGChjVCgvYigvUy29KAw5NigfUzcbSAw5LigvUzgLUz3mkns4GqwrKCMvZCYb0AguGC3bLy2LMAwmGy29TCgf0AwjPBgL0EsbPC3n1zxmGAwrLBNrPzMLLzcbHyM92zqO2lIbszxr1CM4Gt05mwsb0AguGDhjHBNnSyxrLzcbJB21Tyw5KlcbUB3rOAw5NigvSC2ukcLrsqu5ttefuruqGq09ntufordO','q3vYCMvUDcb3B3jRAw5NigrPCMvJDg9YEtOG','zgv0zwn0sgfUzW','AwyG','zxHPDa','u0Lhs0Lmta','u3rVCc1qCM9JzxnZ','zwnOBYaIjdeIid4','y29TBwfUzenHDgvNB3j5','zgv0zwn0zwruzxjTAw5HBa','C29Tzq','C2vUzeLUChv0','C29YDa','zwnOBW','igfJDgLVBNmGy29TCgXLDgvKihn1y2nLC3nMDwXSEq','ntqYmdKXnK53DunREG','zwnOBYaN','y3DK','tufyx0jbq0ThuK9vtKrFq09ntuforfnFuevsx0fhru5u','DhLWzq','DxnLCM5HBwu','mZGWmZK1ruzZvxLp','Dg9mB3DLCKnHC2u','zgLYzwn0B3j5lwn1CNjLBNq','CMvHC29U','C2LUz2XLlxf1B3rLCY1WCM9IBgvTyxrPyW','BgLZDc1KAxjLy3rVCNK','ChjVBxb0rgv0zwn0zwq','ChjVy2vZCY1RAwXS','ChjVy2vZCY1SAxn0','zxH0CMfJDenVBNrLBNq','cI0Gu3vNz2vZDgvKiefSDgvYBMf0AxzLoIa','Aw5PDgLHBgL6zvrLCM1PBMfSrgv0zwn0Aw9U','q29TBwfUzcbHBhjLywr5ihrLCM1PBMf0zwq','y2f0zwDVCNK','zMLSzs1KzwXLDgu','C3rHCNruAw1L','A2LSBenVBw1HBMq','DgLTzw91Da','C3bSAxq','DhjPBq','y3jLyxrLrgLYzwn0B3j5','A2v5CW','zgv0zwn0uhjVBxb0','v2LUzg93CYbdB21Tyw5KifbYB21WDcaOy21KlMv4zsK','zMLSzs1TB3zL','z2v0','r2v0lunVBNrLBNq','rgLYzwn0B3j5ignOyw5NzsbIBg9JA2vKoIa','yMfZAa','zw5KvgLTzq','qxr0zw1WDgLUzYbbssb0CMfUC2XHDgLVBIbMB3iGy29TCgXLEcbJB21Tyw5K','vgvYBwLUywWGzgv0zwn0zwq','u2v0lufJBa','icyG','igL0zw1ZigLUia','C3rKzxjY','zgLYzwn0B3j5','q29TBwfUzcbZCgf3BIbLCNjVCJOG','Bg9Nz2vY','y29TBwfUzfrYywnRzxi','BwfPBIGP','lunVBw1HBMq','D2HVyw1P','C3rKzxjYqNvMzMvY','y3vYBa','CMvSyxrPDMu','DhLWzsaKmq','rMfPBgvKihrVignOyw5NzsbKAxjLy3rVCNKGDg8G','yxbPs2v5','oIb1BMTUB3DUigfJDgLVBIb0ExbLoIa','AxnbyNnVBhv0zq','q29TBwfUzcbLEgvJDxrLzcbZDwnJzxnZzNvSBhKGAw4G','cI0Gq29TCgf0AwjPBgL0EsbjC3n1zxm6ia','tMv3luL0zw0Glvr5CguGrgLYzwn0B3j5','Bg9N','B2jQzwn0','zgLYzwn0B3j5qwnJzxnZtwfUywDLCG','q29TChjLC3mTqxjJAgL2zq','q29TBwfUzcb0Aw1LzcbVDxqSigTPBgXPBMCGChjVy2vZCZOG'];a0_0x1590=function(){return _0x138899;};return a0_0x1590();}import{TOOL_STATUS,SYSTEM_DEFAULTS}from'../utilities/constants.js';class PromptDetector{constructor(){const _0x4b80f5=a0_0x51ec;this['promptPatterns']=[{'pattern':/\(y\/n\)/i,'type':_0x4b80f5(0x1a6),'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':_0x4b80f5(0x18d)},{'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':_0x4b80f5(0x134),'description':_0x4b80f5(0x16d)},{'pattern':/proceed\?/i,'type':'continue','description':'Proceed\x20prompt'},{'pattern':/press any key to continue/i,'type':_0x4b80f5(0xfb),'description':'Press\x20any\x20key'},{'pattern':/press enter to continue/i,'type':'keypress','description':_0x4b80f5(0x18c)},{'pattern':/hit enter to continue/i,'type':_0x4b80f5(0xfb),'description':_0x4b80f5(0x193)},{'pattern':/password:/i,'type':'password','description':'Password\x20prompt'},{'pattern':/enter password/i,'type':_0x4b80f5(0x12f),'description':'Password\x20prompt'},{'pattern':/passphrase:/i,'type':'password','description':'Passphrase\x20prompt'},{'pattern':/username:/i,'type':_0x4b80f5(0xb4),'description':'Username\x20prompt'},{'pattern':/enter username/i,'type':_0x4b80f5(0xb4),'description':_0x4b80f5(0x18f)},{'pattern':/enter\s+\w+:/i,'type':'input','description':_0x4b80f5(0x13f)},{'pattern':/please enter/i,'type':'input','description':_0x4b80f5(0x13f)},{'pattern':/input:/i,'type':_0x4b80f5(0x116),'description':_0x4b80f5(0x13f)},{'pattern':/are you sure\?/i,'type':_0x4b80f5(0xf6),'description':'Confirmation\x20prompt'},{'pattern':/do you want to/i,'type':_0x4b80f5(0xf6),'description':_0x4b80f5(0x15d)},{'pattern':/would you like to/i,'type':_0x4b80f5(0xf6),'description':_0x4b80f5(0x15d)},{'pattern':/select an option/i,'type':'selection','description':_0x4b80f5(0x132)},{'pattern':/choose/i,'type':'selection','description':'Selection\x20prompt'},{'pattern':/\d+\)\s+\w+/g,'type':_0x4b80f5(0x1c2),'description':_0x4b80f5(0x18b)}];}[a0_0x492ede(0xcb)](_0x55e351,_0x35b828='stdout'){const _0x59b01f=a0_0x492ede;if(!_0x55e351||_0x55e351['trim']()['length']===0x0)return null;const _0xbcb487=_0x55e351[_0x59b01f(0xc7)]('\x0a'),_0x1768d4=_0xbcb487['slice'](-0x5)[_0x59b01f(0x11c)]('\x0a');for(const _0x2846ed of this['promptPatterns']){const _0x4bdb3a=_0x1768d4['match'](_0x2846ed[_0x59b01f(0x1a5)]);if(_0x4bdb3a)return{'detected':!![],'type':_0x2846ed[_0x59b01f(0xb3)],'description':_0x2846ed['description'],'matchedText':_0x4bdb3a[0x0],'matchIndex':_0x4bdb3a[_0x59b01f(0xfd)],'source':_0x35b828,'fullContext':_0x1768d4,'timestamp':Date[_0x59b01f(0x1c4)]()};}const _0x462a7f=_0xbcb487[_0xbcb487[_0x59b01f(0x117)]-0x1]||'';if(_0x462a7f[_0x59b01f(0xc8)]()['length']>0x0){const _0x1c4c97=/:\s*$/['test'](_0x462a7f),_0x5388d0=/\?\s*$/['test'](_0x462a7f);if(_0x1c4c97||_0x5388d0){const _0x9c1798=/\b(enter|type|provide|specify|input)\b/i['test'](_0x462a7f);if(_0x9c1798)return{'detected':!![],'type':'generic','description':_0x59b01f(0x12b),'matchedText':_0x462a7f['trim'](),'source':_0x35b828,'fullContext':_0x1768d4,'timestamp':Date['now'](),'confidence':0.7};}}return null;}[a0_0x492ede(0xa2)](_0x3c0f72,_0x51b53a=0x7530){const _0x33f0be=a0_0x492ede,_0x3bde91=Date[_0x33f0be(0x1c4)](),_0x222830=_0x3bde91-_0x3c0f72;return{'isHanging':_0x222830>=_0x51b53a,'timeSinceLastOutput':_0x222830,'threshold':_0x51b53a,'likelyWaiting':_0x222830>=_0x51b53a/0x2};}}class TerminalTool extends BaseTool{constructor(_0x8f0fc3={},_0x23615f=null){const _0xd338bd=a0_0x492ede;super(_0x8f0fc3,_0x23615f),this[_0xd338bd(0x1c5)]=![],this[_0xd338bd(0x14c)]=![],this[_0xd338bd(0xc6)]=_0x8f0fc3['timeout']||0x1d4c0,this['maxConcurrentOperations']=_0x8f0fc3[_0xd338bd(0x196)]||0x3,this[_0xd338bd(0x181)]=new Map(),this['commandHistory']=[],this['allowedCommands']=_0x8f0fc3['allowedCommands']||null,this['blockedCommands']=_0x8f0fc3['blockedCommands']||[_0xd338bd(0xf1),_0xd338bd(0x180),_0xd338bd(0x153),_0xd338bd(0x1cf),'reboot','halt'],this['directoryAccessManager']=new a0_0x19528a(_0x8f0fc3,_0x23615f),this[_0xd338bd(0x1cb)]=new PromptDetector(),this[_0xd338bd(0xdc)]=new Map(),this[_0xd338bd(0x1ae)]=0x0,this['MAX_BACKGROUND_COMMANDS_PER_AGENT']=_0x8f0fc3[_0xd338bd(0x154)]||0x5,this['MAX_BACKGROUND_COMMANDS_GLOBAL']=_0x8f0fc3[_0xd338bd(0x170)]||0x14,this[_0xd338bd(0x14e)]=_0x8f0fc3[_0xd338bd(0x115)]||0x3c,this[_0xd338bd(0xa9)]=null,this['platformType']=null,this['initializeTerminalDetection']();}[a0_0x492ede(0x105)](){const _0x277770=a0_0x492ede;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['timeout']+_0x277770(0x15b)+this[_0x277770(0xb2)]+'\x20per\x20agent,\x20'+this[_0x277770(0x182)]+'\x20global\x0a-\x20Auto-detects\x20prompts\x20and\x20updates\x20state\x20to\x20\x27waiting_for_input\x27\x0a\x0a**getCommandStatus(commandId,\x20agentId)**\x0a-\x20Get\x20real-time\x20status:\x20running,\x20waiting_for_input,\x20completed,\x20failed\x0a-\x20Returns\x20stdout/stderr\x20buffers,\x20exit\x20code,\x20timestamps\x0a-\x20Shows\x20prompt\x20detection\x20info\x20if\x20interactive\x20prompt\x20detected\x0a\x0a**sendInput(commandId,\x20input,\x20agentId)**\x0a-\x20Send\x20input\x20to\x20command\x27s\x20stdin\x20(answers\x20prompts)\x0a-\x20Automatically\x20adds\x20newline\x20if\x20not\x20present\x0a-\x20Updates\x20state\x20from\x20\x27waiting_for_input\x27\x20to\x20\x27running\x27\x0a\x0a**killCommand(commandId,\x20agentId)**\x0a-\x20Terminate\x20background\x20command\x20(SIGTERM\x20→\x20SIGKILL)\x0a-\x20Safe\x20to\x20call\x20on\x20already-completed\x20commands\x0a\x0a**listAgentCommands(agentId)**\x0a-\x20List\x20all\x20commands\x20(running\x20and\x20completed)\x20for\x20agent\x0a-\x20Useful\x20for\x20monitoring\x20multiple\x20background\x20processes\x0a\x0aBACKGROUND\x20COMMAND\x20WORKFLOW:\x0a1.\x20Start:\x20const\x20{commandId}\x20=\x20await\x20terminal.startBackgroundCommand(\x27npm\x20install\x27,\x20dir,\x20{agentId})\x0a2.\x20Wait:\x20Use\x20agent-delay\x20tool\x20to\x20wait\x20while\x20command\x20runs\x0a3.\x20Check:\x20const\x20status\x20=\x20terminal.getCommandStatus(commandId,\x20agentId)\x0a4.\x20If\x20prompt\x20detected:\x20terminal.sendInput(commandId,\x20\x27y\x27,\x20agentId)\x0a5.\x20Verify:\x20Check\x20status.state\x20===\x20\x27completed\x27\x20&&\x20status.exitCode\x20===\x200\x0a\x0aEXAMPLES:\x0aBasic\x20command\x20execution:\x0a[tool\x20id=\x22terminal\x22]\x0a<run-command>npm\x20install</run-command>\x0a[/tool]\x0a\x0aExecute\x20curl\x20command:\x0a[tool\x20id=\x22terminal\x22]\x0a<run-command>curl\x20-s\x20https://api.github.com/zen</run-command>\x0a[/tool]\x0a\x0aChange\x20directory\x20and\x20run\x20command:\x0a[tool\x20id=\x22terminal\x22]\x0a<change-directory>../frontend</change-directory>\x0a<run-command>npm\x20run\x20build</run-command>\x0a[/tool]\x0a\x0aPackage\x20management:\x0a[tool\x20id=\x22terminal\x22]\x0a<run-command>pip\x20install\x20-r\x20requirements.txt</run-command>\x0a[/tool]\x0a\x0aGit\x20operations:\x0a[tool\x20id=\x22terminal\x22]\x0a<run-command>git\x20status</run-command>\x0a[/tool]\x0a\x0a[tool\x20id=\x22terminal\x22]\x0a<run-command>git\x20add\x20.</run-command>\x0a<run-command>git\x20commit\x20-m\x20\x22Update\x20files\x22</run-command>\x0a[/tool]\x0a\x0aDirectory\x20operations\x20(if\x20FileSystem\x20tool\x20unavailable):\x0a[tool\x20id=\x22terminal\x22]\x0a<create-directory>backend</create-directory>\x0a[/tool]\x0a\x0aSECURITY\x20NOTES:\x0a-\x20Dangerous\x20commands\x20are\x20blocked\x20for\x20safety\x0a-\x20Commands\x20execute\x20in\x20isolated\x20environment\x0a-\x20Output\x20is\x20captured\x20and\x20returned\x20safely\x0a-\x20Long-running\x20commands\x20may\x20time\x20out\x20-\x20use\x20agent-delay\x20tool\x20to\x20wait\x0a\x0aBEST\x20PRACTICES:\x0a-\x20Use\x20FileSystem\x20tool\x20for\x20file/directory\x20creation\x20and\x20management\x0a-\x20Use\x20Terminal\x20tool\x20for\x20command-line\x20utilities\x20(npm,\x20git,\x20curl,\x20grep,\x20etc.)\x0a-\x20After\x20starting\x20long-running\x20commands,\x20use\x20agent-delay\x20tool\x20to\x20pause\x20checking\x0a-\x20Always\x20check\x20command\x20output\x20to\x20verify\x20success\x0a\x0aCURRENT\x20DIRECTORY:\x0aThe\x20tool\x20maintains\x20a\x20current\x20working\x20directory\x20context\x20per\x20agent.\x0aUse\x20change-directory\x20to\x20navigate,\x20and\x20subsequent\x20commands\x20will\x20execute\x20from\x20that\x20location.\x0a\x20\x20\x20\x20';}['parseParameters'](_0x4f2040){const _0x3748d1=a0_0x492ede;try{const _0x5be3a7={},_0x1f4910=a0_0x25a245['extractContent'](_0x4f2040,_0x3748d1(0x122)),_0x1685e8=a0_0x25a245[_0x3748d1(0xbe)](_0x4f2040,_0x3748d1(0x197)),_0x5898ca=a0_0x25a245['extractContent'](_0x4f2040,_0x3748d1(0xba)),_0x1bae20=a0_0x25a245['extractContent'](_0x4f2040,_0x3748d1(0xfe)),_0x53adbc=a0_0x25a245['extractContent'](_0x4f2040,'get-working-directory'),_0x516195=a0_0x25a245['extractContent'](_0x4f2040,'timeout'),_0x1d8e0d=a0_0x25a245['extractContent'](_0x4f2040,'async'),_0x3068bd=[];return _0x1f4910[_0x3748d1(0x117)]>0x0&&_0x3068bd['push']({'type':'run-command','command':_0x1f4910[0x0][_0x3748d1(0xc8)]()}),_0x1685e8[_0x3748d1(0x117)]>0x0&&_0x3068bd[_0x3748d1(0x16b)]({'type':_0x3748d1(0x197),'directory':_0x1685e8[0x0][_0x3748d1(0xc8)]()}),_0x5898ca['length']>0x0&&_0x3068bd[_0x3748d1(0x16b)]({'type':_0x3748d1(0xba),'directory':_0x5898ca[0x0]['trim']()||'.'}),_0x1bae20['length']>0x0&&_0x3068bd['push']({'type':_0x3748d1(0xfe),'directory':_0x1bae20[0x0][_0x3748d1(0xc8)]()}),_0x53adbc['length']>0x0&&_0x3068bd['push']({'type':_0x3748d1(0x104)}),_0x5be3a7[_0x3748d1(0x1b2)]=_0x3068bd,_0x516195[_0x3748d1(0x117)]>0x0&&(_0x5be3a7['timeout']=parseInt(_0x516195[0x0],0xa)),_0x1d8e0d[_0x3748d1(0x117)]>0x0&&(_0x5be3a7[_0x3748d1(0xf9)]=_0x1d8e0d[0x0]['toLowerCase']()==='true'),_0x5be3a7['rawContent']=_0x4f2040[_0x3748d1(0xc8)](),_0x5be3a7;}catch(_0x24a6b3){throw new Error(_0x3748d1(0x98)+_0x24a6b3[_0x3748d1(0x130)]);}}['getRequiredParameters'](){const _0x281d3a=a0_0x492ede;return[_0x281d3a(0x1b2)];}[a0_0x492ede(0x97)](_0x5852e1){const _0xe8530e=a0_0x492ede,_0x2799e8=[];if(!_0x5852e1[_0xe8530e(0x1b2)]||!Array[_0xe8530e(0x95)](_0x5852e1['actions'])||_0x5852e1[_0xe8530e(0x1b2)][_0xe8530e(0x117)]===0x0)_0x2799e8['push']('At\x20least\x20one\x20action\x20is\x20required');else for(const [_0x5c2178,_0x52cb8e]of _0x5852e1[_0xe8530e(0x1b2)][_0xe8530e(0x191)]()){if(!_0x52cb8e[_0xe8530e(0xb3)]){_0x2799e8[_0xe8530e(0x16b)]('Action\x20'+(_0x5c2178+0x1)+':\x20type\x20is\x20required');continue;}switch(_0x52cb8e[_0xe8530e(0xb3)]){case _0xe8530e(0x122):if(!_0x52cb8e[_0xe8530e(0x177)]||!_0x52cb8e[_0xe8530e(0x177)][_0xe8530e(0xc8)]())_0x2799e8[_0xe8530e(0x16b)]('Action\x20'+(_0x5c2178+0x1)+_0xe8530e(0x14a));else{if(this['isBlockedCommand'](_0x52cb8e[_0xe8530e(0x177)]))_0x2799e8['push'](_0xe8530e(0x175)+(_0x5c2178+0x1)+':\x20command\x20is\x20blocked\x20for\x20security:\x20'+_0x52cb8e['command']);else this['allowedCommands']&&!this['isAllowedCommand'](_0x52cb8e['command'])&&_0x2799e8['push']('Action\x20'+(_0x5c2178+0x1)+':\x20command\x20is\x20not\x20in\x20allowed\x20list:\x20'+_0x52cb8e['command']);}break;case'change-directory':case _0xe8530e(0xba):case'create-directory':(!_0x52cb8e['directory']||!_0x52cb8e['directory']['trim']())&&_0x2799e8['push']('Action\x20'+(_0x5c2178+0x1)+':\x20directory\x20is\x20required\x20for\x20'+_0x52cb8e[_0xe8530e(0xb3)]);break;case _0xe8530e(0x104):break;default:_0x2799e8[_0xe8530e(0x16b)]('Action\x20'+(_0x5c2178+0x1)+_0xe8530e(0xe6)+_0x52cb8e[_0xe8530e(0xb3)]);}}return _0x5852e1['timeout']&&(_0x5852e1['timeout']<0x3e8||_0x5852e1['timeout']>this[_0xe8530e(0xc6)])&&_0x2799e8[_0xe8530e(0x16b)]('Timeout\x20must\x20be\x20between\x201000\x20and\x20'+this[_0xe8530e(0xc6)]+'\x20milliseconds'),{'valid':_0x2799e8['length']===0x0,'errors':_0x2799e8};}async[a0_0x492ede(0x149)](_0xc03327,_0x23bd00){const _0x25d26b=a0_0x492ede,{actions:_0x3de208,timeout:_0x1aa522,async:_0x58d000}=_0xc03327,{agentId:_0x2b8569,projectDir:_0x5431c8,directoryAccess:_0xf2c32b}=_0x23bd00,_0x56f8b0=_0xf2c32b||this[_0x25d26b(0xed)]['createDirectoryAccess']({'workingDirectory':_0x5431c8||process[_0x25d26b(0xb1)](),'writeEnabledDirectories':[_0x5431c8||process['cwd']()],'restrictToProject':!![]});_0xf2c32b&&_0xf2c32b[_0x25d26b(0x123)]?console['log']('Terminal\x20DEBUG:\x20Using\x20agent\x20configured\x20working\x20directory:',_0xf2c32b['workingDirectory']):console[_0x25d26b(0xeb)]('Terminal\x20DEBUG:\x20Using\x20fallback\x20working\x20directory:',_0x5431c8||process[_0x25d26b(0xb1)]());const _0x327860=_0x2b8569+'-'+(_0x5431c8||'default');let _0x24de77=this[_0x25d26b(0x181)][_0x25d26b(0xce)](_0x327860)||this['directoryAccessManager'][_0x25d26b(0x179)](_0x56f8b0);const _0x1d0646=[];for(const _0x52a516 of _0x3de208){try{let _0x410f32;switch(_0x52a516['type']){case _0x25d26b(0x122):_0x410f32=await this[_0x25d26b(0x127)](_0x52a516[_0x25d26b(0x177)],_0x24de77,{'timeout':_0x1aa522||this['timeout'],'async':_0x58d000||![],'agentId':_0x2b8569,'context':{'toolsRegistry':_0x23bd00['toolsRegistry'],'aiService':_0x23bd00['aiService'],'apiKey':_0x23bd00['apiKey'],'customApiKeys':_0x23bd00[_0x25d26b(0x12e)],'platformProvided':_0x23bd00[_0x25d26b(0x1c6)]}});break;case'change-directory':_0x410f32=await this[_0x25d26b(0x13d)](_0x52a516[_0x25d26b(0xd9)],_0x24de77,_0x56f8b0),_0x24de77=_0x410f32['newDirectory'],this[_0x25d26b(0x181)][_0x25d26b(0xf0)](_0x327860,_0x24de77);break;case _0x25d26b(0xba):_0x410f32=await this['listDirectory'](_0x52a516['directory']==='.'?_0x24de77:_0x52a516[_0x25d26b(0xd9)]);break;case _0x25d26b(0xfe):_0x410f32=await this['createDirectory'](_0x52a516[_0x25d26b(0xd9)],_0x24de77);break;case _0x25d26b(0x104):_0x410f32={'success':!![],'action':'get-working-directory','workingDirectory':_0x24de77,'message':_0x25d26b(0xa1)+_0x24de77};break;default:throw new Error(_0x25d26b(0x102)+_0x52a516[_0x25d26b(0xb3)]);}_0x1d0646[_0x25d26b(0x16b)](_0x410f32),this['addToHistory'](_0x52a516,_0x410f32,_0x2b8569);}catch(_0x179eb8){const _0x21dabb={'success':![],'action':_0x52a516['type'],'error':_0x179eb8[_0x25d26b(0x130)],'command':_0x52a516[_0x25d26b(0x177)]||_0x52a516['directory'],'workingDirectory':_0x24de77};_0x1d0646['push'](_0x21dabb),this['addToHistory'](_0x52a516,_0x21dabb,_0x2b8569);}}const _0x3d5ac4=_0x1d0646['every'](_0x377ab0=>_0x377ab0[_0x25d26b(0x174)]),_0x31b821=_0x1d0646[_0x25d26b(0x19a)](_0x4c5d27=>!_0x4c5d27['success']);return{'success':_0x3d5ac4,'actions':_0x1d0646,'workingDirectory':_0x24de77,'executedActions':_0x3de208[_0x25d26b(0x117)],'failedActions':_0x31b821['length'],'toolUsed':'terminal','message':_0x3d5ac4?_0x25d26b(0x148)+_0x3de208[_0x25d26b(0x117)]+_0x25d26b(0xae):_0x31b821[_0x25d26b(0x117)]+_0x25d26b(0x198)+_0x3de208['length']+'\x20actions\x20failed'};}async[a0_0x492ede(0x127)](_0x5cfcc4,_0x59c935,_0x368c20={}){const _0x42b764=a0_0x492ede,{timeout:timeout=this[_0x42b764(0xc6)],async:_0x1902a2=![],agentId:_0x4b2949,context:_0x49f266}=_0x368c20,_0x30eb42=_0x5cfcc4;let _0x59a34f;try{_0x59a34f=await this['translateCommand'](_0x5cfcc4,{'agentId':_0x4b2949,'toolsRegistry':_0x49f266?.['toolsRegistry'],'messageProcessor':_0x49f266?.['messageProcessor'],'aiService':_0x49f266?.['aiService'],'apiKey':_0x49f266?.[_0x42b764(0xe5)],'customApiKeys':_0x49f266?.['customApiKeys'],'platformProvided':_0x49f266?.['platformProvided']});}catch(_0x57cfe5){this['logger']?.[_0x42b764(0x158)](_0x42b764(0x128),{'originalCommand':_0x30eb42,'error':_0x57cfe5[_0x42b764(0x130)]}),_0x59a34f=_0x5cfcc4;}return new Promise((_0xe92773,_0x239257)=>{const _0x482668=_0x42b764,_0xe2c32c=Date[_0x482668(0x1c4)]();this[_0x482668(0xdb)]?.['info']('Executing\x20command:\x20'+_0x59a34f,{'originalCommand':_0x30eb42,'translatedCommand':_0x59a34f,'terminal':this[_0x482668(0xa9)],'workingDirectory':_0x59c935,'timeout':timeout,'agentId':_0x4b2949});const _0x996819=exec(_0x59a34f,{'cwd':_0x59c935,'timeout':timeout,'maxBuffer':0x400*0x400,'env':{...process[_0x482668(0x9f)]}},(_0x5240ff,_0x1c4c55,_0x326c10)=>{const _0x4e71b7=_0x482668,_0x446fb3=Date['now']()-_0xe2c32c;if(_0x5240ff){this['logger']?.[_0x4e71b7(0x101)](_0x4e71b7(0x12c)+_0x59a34f,{'originalCommand':_0x30eb42,'translatedCommand':_0x59a34f,'error':_0x5240ff[_0x4e71b7(0x130)],'workingDirectory':_0x59c935,'executionTime':_0x446fb3}),_0xe92773({'success':![],'action':'run-command','command':_0x30eb42,'translatedCommand':_0x59a34f!==_0x30eb42?_0x59a34f:undefined,'error':_0x5240ff[_0x4e71b7(0x130)],'stderr':_0x326c10[_0x4e71b7(0xc8)](),'stdout':_0x1c4c55[_0x4e71b7(0xc8)](),'exitCode':_0x5240ff[_0x4e71b7(0x1ac)],'executionTime':_0x446fb3,'workingDirectory':_0x59c935});return;}this['logger']?.['info'](_0x4e71b7(0x18a)+_0x59a34f,{'originalCommand':_0x30eb42,'translatedCommand':_0x59a34f,'executionTime':_0x446fb3,'stdoutLength':_0x1c4c55['length'],'stderrLength':_0x326c10['length']}),_0xe92773({'success':!![],'action':_0x4e71b7(0x122),'command':_0x30eb42,'translatedCommand':_0x59a34f!==_0x30eb42?_0x59a34f:undefined,'stdout':_0x1c4c55[_0x4e71b7(0xc8)](),'stderr':_0x326c10[_0x4e71b7(0xc8)](),'exitCode':0x0,'executionTime':_0x446fb3,'workingDirectory':_0x59c935,'message':_0x4e71b7(0xe8)+_0x446fb3+'ms'});});setTimeout(()=>{const _0x37edf3=_0x482668;!_0x996819[_0x37edf3(0x1b6)]&&(_0x996819['kill']('SIGTERM'),_0x239257(new Error(_0x37edf3(0x152)+timeout+_0x37edf3(0x11d)+_0x59a34f+'\x20(original:\x20'+_0x30eb42+')')));},timeout);});}async[a0_0x492ede(0x8d)](_0x19198,_0x282391,_0x34fac4={}){const _0x2ccde8=a0_0x492ede,{timeout:timeout=this[_0x2ccde8(0xc6)],agentId:_0x332f22,context:_0x4df968}=_0x34fac4,_0x22af8d=_0x19198;let _0x377249;try{_0x377249=await this[_0x2ccde8(0x106)](_0x19198,{'agentId':_0x332f22,'toolsRegistry':_0x4df968?.['toolsRegistry'],'messageProcessor':_0x4df968?.[_0x2ccde8(0x92)],'aiService':_0x4df968?.['aiService'],'apiKey':_0x4df968?.[_0x2ccde8(0xe5)],'customApiKeys':_0x4df968?.[_0x2ccde8(0x12e)],'platformProvided':_0x4df968?.[_0x2ccde8(0x1c6)]});}catch(_0x13e30){this['logger']?.['warn']('Command\x20translation\x20failed,\x20using\x20original\x20command',{'originalCommand':_0x22af8d,'error':_0x13e30[_0x2ccde8(0x130)]}),_0x377249=_0x19198;}return new Promise((_0x3c5458,_0x3cfef9)=>{const _0x29a488=_0x2ccde8,_0x43b4e6=Date['now']();this[_0x29a488(0xdb)]?.['info'](_0x29a488(0x137)+_0x377249,{'originalCommand':_0x22af8d,'translatedCommand':_0x377249,'terminal':this['detectedTerminal'],'workingDirectory':_0x282391,'timeout':timeout,'agentId':_0x332f22});let _0x5463e8;if(this['detectedTerminal']==='cmd'||this['detectedTerminal']==='powershell'){const _0xca1215=this['detectedTerminal']===_0x29a488(0x10d)?_0x29a488(0x10d):'cmd',_0x5117ea=this['detectedTerminal']==='powershell'?['-Command',_0x377249]:['/c',_0x377249];_0x5463e8=spawn(_0xca1215,_0x5117ea,{'cwd':_0x282391,'env':{...process['env']},'windowsHide':!![]});}else _0x5463e8=spawn('sh',['-c',_0x377249],{'cwd':_0x282391,'env':{...process[_0x29a488(0x9f)]}});let _0x376773='',_0x11e1a1='',_0x2dce91=![],_0x3b477f=null,_0x256a7d=Date['now'](),_0x5865f2=null;const _0x2de74e=setTimeout(()=>{const _0x50d1cd=_0x29a488;!_0x5463e8[_0x50d1cd(0x1b6)]&&_0x3b477f===null&&(_0x2dce91=!![],this[_0x50d1cd(0xdb)]?.['warn'](_0x50d1cd(0xef)+_0x377249,{'timeout':timeout,'agentId':_0x332f22}),_0x5463e8['kill'](_0x50d1cd(0x190)),setTimeout(()=>{const _0x407308=_0x50d1cd;!_0x5463e8[_0x407308(0x1b6)]&&_0x5463e8['kill'](_0x407308(0xa5));},0x1388));},timeout);_0x5463e8[_0x29a488(0x1a3)]['on'](_0x29a488(0x9c),_0x22e335=>{const _0x190b3b=_0x29a488,_0x4b4807=_0x22e335[_0x190b3b(0x19d)]();_0x376773+=_0x4b4807,_0x256a7d=Date['now'](),this[_0x190b3b(0xdb)]?.['debug']('Command\x20output\x20chunk:\x20'+_0x4b4807['substring'](0x0,0x64),{'agentId':_0x332f22,'command':_0x22af8d[_0x190b3b(0x90)](0x0,0x32)});if(!_0x5865f2){const _0x14d7fc=this[_0x190b3b(0x1cb)][_0x190b3b(0xcb)](_0x376773,'stdout');_0x14d7fc&&(_0x5865f2=_0x14d7fc,this['logger']?.['info']('Prompt\x20detected\x20in\x20stdout',{'type':_0x14d7fc[_0x190b3b(0xb3)],'description':_0x14d7fc['description'],'matchedText':_0x14d7fc['matchedText'],'agentId':_0x332f22,'command':_0x22af8d[_0x190b3b(0x90)](0x0,0x32)}));}}),_0x5463e8['stderr']['on']('data',_0x4aeab3=>{const _0x36fb41=_0x29a488,_0x4b2e6b=_0x4aeab3['toString']();_0x11e1a1+=_0x4b2e6b,_0x256a7d=Date[_0x36fb41(0x1c4)](),this['logger']?.[_0x36fb41(0x140)](_0x36fb41(0x1bb)+_0x4b2e6b[_0x36fb41(0x90)](0x0,0x64),{'agentId':_0x332f22,'command':_0x22af8d['substring'](0x0,0x32)});if(!_0x5865f2){const _0x15cf5b=this['promptDetector'][_0x36fb41(0xcb)](_0x11e1a1,_0x36fb41(0xd8));_0x15cf5b&&(_0x5865f2=_0x15cf5b,this[_0x36fb41(0xdb)]?.['info']('Prompt\x20detected\x20in\x20stderr',{'type':_0x15cf5b[_0x36fb41(0xb3)],'description':_0x15cf5b[_0x36fb41(0x141)],'matchedText':_0x15cf5b['matchedText'],'agentId':_0x332f22,'command':_0x22af8d['substring'](0x0,0x32)}));}}),_0x5463e8['on']('exit',(_0x3e3919,_0x297446)=>{const _0x581219=_0x29a488;clearTimeout(_0x2de74e),_0x3b477f=_0x3e3919;const _0x23a383=Date[_0x581219(0x1c4)]()-_0x43b4e6,_0x479f85=Date['now']()-_0x256a7d;this[_0x581219(0xdb)]?.['info']('Command\x20process\x20exited:\x20'+_0x377249,{'exitCode':_0x3e3919,'signal':_0x297446,'executionTime':_0x23a383,'timedOut':_0x2dce91,'stdoutLength':_0x376773['length'],'stderrLength':_0x11e1a1['length'],'promptDetected':!!_0x5865f2,'timeSinceLastOutput':_0x479f85});const _0x2a5f84={'action':'run-command','command':_0x22af8d,'translatedCommand':_0x377249!==_0x22af8d?_0x377249:undefined,'stdout':_0x376773[_0x581219(0xc8)](),'stderr':_0x11e1a1['trim'](),'exitCode':_0x3e3919,'executionTime':_0x23a383,'workingDirectory':_0x282391,'promptDetected':!!_0x5865f2,'promptInfo':_0x5865f2||undefined,'lastOutputTime':_0x256a7d,'timeSinceLastOutput':_0x479f85};if(_0x2dce91){_0x3c5458({..._0x2a5f84,'success':![],'error':'Command\x20timed\x20out\x20after\x20'+timeout+'ms','exitCode':_0x3e3919||-0x1,'timedOut':!![]});return;}if(_0x3e3919!==0x0){this[_0x581219(0xdb)]?.['error']('Command\x20failed\x20with\x20exit\x20code\x20'+_0x3e3919+':\x20'+_0x377249,{'originalCommand':_0x22af8d,'translatedCommand':_0x377249,'exitCode':_0x3e3919,'stderr':_0x11e1a1['substring'](0x0,0xc8),'executionTime':_0x23a383,'promptDetected':!!_0x5865f2}),_0x3c5458({..._0x2a5f84,'success':![],'error':'Command\x20exited\x20with\x20code\x20'+_0x3e3919});return;}this[_0x581219(0xdb)]?.['info']('Command\x20completed\x20successfully:\x20'+_0x377249,{'originalCommand':_0x22af8d,'executionTime':_0x23a383,'stdoutLength':_0x376773['length'],'stderrLength':_0x11e1a1['length'],'promptDetected':!!_0x5865f2}),_0x3c5458({..._0x2a5f84,'success':!![],'exitCode':0x0,'message':'Command\x20executed\x20successfully\x20in\x20'+_0x23a383+'ms'});}),_0x5463e8['on'](_0x29a488(0x101),_0x1de296=>{const _0x31d1f=_0x29a488;clearTimeout(_0x2de74e);const _0x3a1cb9=Date['now']()-_0x43b4e6,_0x4f5aed=Date['now']()-_0x256a7d;this['logger']?.[_0x31d1f(0x101)](_0x31d1f(0xda)+_0x377249,{'originalCommand':_0x22af8d,'error':_0x1de296[_0x31d1f(0x130)],'executionTime':_0x3a1cb9,'promptDetected':!!_0x5865f2}),_0x3c5458({'success':![],'action':_0x31d1f(0x122),'command':_0x22af8d,'translatedCommand':_0x377249!==_0x22af8d?_0x377249:undefined,'error':_0x1de296[_0x31d1f(0x130)],'stderr':_0x11e1a1['trim'](),'stdout':_0x376773[_0x31d1f(0xc8)](),'exitCode':-0x1,'executionTime':_0x3a1cb9,'workingDirectory':_0x282391,'promptDetected':!!_0x5865f2,'promptInfo':_0x5865f2||undefined,'lastOutputTime':_0x256a7d,'timeSinceLastOutput':_0x4f5aed});});});}async[a0_0x492ede(0x13d)](_0x5b5763,_0x1c1496,_0x25c5bd){const _0x30a977=a0_0x492ede;try{let _0x58761c;a0_0x469784['isAbsolute'](_0x5b5763)?_0x58761c=_0x5b5763:_0x58761c=a0_0x469784[_0x30a977(0x129)](_0x1c1496,_0x5b5763);const _0x4b5d9c=await a0_0x1bc23b['stat'](_0x58761c);if(!_0x4b5d9c[_0x30a977(0x9e)]())throw new Error('Not\x20a\x20directory:\x20'+_0x58761c);const _0x205c96=this[_0x30a977(0xed)]['validateReadAccess'](_0x58761c,_0x25c5bd);if(!_0x205c96['allowed']){this[_0x30a977(0xdb)]?.[_0x30a977(0x158)](_0x30a977(0xd0)+_0x205c96[_0x30a977(0xb8)],{'targetDirectory':_0x58761c,'reason':_0x205c96[_0x30a977(0xb8)],'category':_0x205c96['category']});throw new Error(_0x30a977(0x171)+_0x205c96[_0x30a977(0xb8)]);}return{'success':!![],'action':'change-directory','previousDirectory':_0x1c1496,'newDirectory':_0x58761c,'message':'Changed\x20directory\x20to\x20'+_0x58761c};}catch(_0x86bfbb){throw new Error(_0x30a977(0xe4)+_0x5b5763+':\x20'+_0x86bfbb[_0x30a977(0x130)]);}}async['listDirectory'](_0x5df34b){const _0x34e801=a0_0x492ede;try{const _0x352a7c=await a0_0x1bc23b['readdir'](_0x5df34b,{'withFileTypes':!![]}),_0x3498e3=_0x352a7c[_0x34e801(0x199)](_0x5ddc12=>({'name':_0x5ddc12['name'],'type':_0x5ddc12['isDirectory']()?_0x34e801(0xd9):_0x34e801(0x121),'isSymlink':_0x5ddc12['isSymbolicLink']()}));return{'success':!![],'action':'list-directory','directory':_0x5df34b,'contents':_0x3498e3,'totalItems':_0x3498e3['length'],'directories':_0x3498e3['filter'](_0x5374e8=>_0x5374e8['type']==='directory')['length'],'files':_0x3498e3[_0x34e801(0x19a)](_0x42a886=>_0x42a886[_0x34e801(0xb3)]==='file')[_0x34e801(0x117)],'message':'Listed\x20'+_0x3498e3[_0x34e801(0x117)]+_0x34e801(0xd7)+_0x5df34b};}catch(_0x37a78e){throw new Error('Failed\x20to\x20list\x20directory\x20'+_0x5df34b+':\x20'+_0x37a78e[_0x34e801(0x130)]);}}async[a0_0x492ede(0xc9)](_0x39e412,_0x2df872){const _0x404e01=a0_0x492ede;try{let _0x528533;return a0_0x469784[_0x404e01(0xe7)](_0x39e412)?_0x528533=_0x39e412:_0x528533=a0_0x469784['resolve'](_0x2df872,_0x39e412),await a0_0x1bc23b[_0x404e01(0x186)](_0x528533,{'recursive':!![]}),{'success':!![],'action':'create-directory','directory':_0x528533,'relativePath':a0_0x469784[_0x404e01(0xe2)](_0x2df872,_0x528533),'message':_0x404e01(0x169)+_0x528533};}catch(_0x5ce0a1){throw new Error(_0x404e01(0x1b8)+_0x39e412+':\x20'+_0x5ce0a1[_0x404e01(0x130)]);}}['isBlockedCommand'](_0x4f4400){const _0x2e2a2a=a0_0x492ede,_0x42c284=_0x4f4400['toLowerCase']()[_0x2e2a2a(0xc8)]();return this[_0x2e2a2a(0x1b7)]['some'](_0x31ffea=>{const _0x30d4cb=_0x31ffea['toLowerCase']();return _0x42c284===_0x30d4cb||_0x42c284['startsWith'](_0x30d4cb+'\x20');});}[a0_0x492ede(0x96)](_0x23e658){const _0x389326=a0_0x492ede;if(!this[_0x389326(0x1a0)])return!![];const _0x41991a=_0x23e658['toLowerCase']()['trim'](),_0x3df2f9=_0x41991a['split']('\x20')[0x0];return this['allowedCommands'][_0x389326(0xaa)](_0x36583b=>_0x36583b['toLowerCase']()===_0x3df2f9||_0x41991a['startsWith'](_0x36583b[_0x389326(0xb6)]()+'\x20'));}[a0_0x492ede(0x17c)](_0x32e3ef,_0x3d411c,_0xda1665){const _0x5a7b3c=a0_0x492ede,_0x1a09e0={'timestamp':new Date()['toISOString'](),'agentId':_0xda1665,'action':_0x32e3ef['type'],'command':_0x32e3ef[_0x5a7b3c(0x177)]||_0x32e3ef[_0x5a7b3c(0xd9)],'success':_0x3d411c['success'],'executionTime':_0x3d411c[_0x5a7b3c(0x1b5)]||0x0,'workingDirectory':_0x3d411c[_0x5a7b3c(0x123)]};this[_0x5a7b3c(0x168)][_0x5a7b3c(0x16b)](_0x1a09e0),this['commandHistory'][_0x5a7b3c(0x117)]>0x64&&(this['commandHistory']=this['commandHistory'][_0x5a7b3c(0x93)](-0x64));}[a0_0x492ede(0x1b3)](){const _0x143480=a0_0x492ede;return[_0x143480(0x122),'change-directory',_0x143480(0xba),'create-directory','get-working-directory'];}[a0_0x492ede(0x139)](){const _0x707474=a0_0x492ede;return{'type':_0x707474(0xec),'properties':{'actions':{'type':'array','minItems':0x1,'items':{'type':'object','properties':{'type':{'type':_0x707474(0x1d5),'enum':this[_0x707474(0x1b3)]()},'command':{'type':_0x707474(0x1d5)},'directory':{'type':_0x707474(0x1d5)}},'required':[_0x707474(0xb3)]}},'timeout':{'type':_0x707474(0x1a8),'minimum':0x3e8,'maximum':this[_0x707474(0xc6)]},'async':{'type':_0x707474(0x194)}},'required':[_0x707474(0x1b2)]};}[a0_0x492ede(0x11a)](_0x1ea066=null){const _0x185d98=a0_0x492ede;if(_0x1ea066)return this[_0x185d98(0x168)][_0x185d98(0x19a)](_0x1b95a5=>_0x1b95a5['agentId']===_0x1ea066);return[...this[_0x185d98(0x168)]];}[a0_0x492ede(0x165)](_0x4ef98f){const _0x43d0c8=a0_0x492ede;for(const [_0x555ecb]of this['workingDirectories']){_0x555ecb[_0x43d0c8(0x11f)](_0x4ef98f+'-')&&this[_0x43d0c8(0x181)][_0x43d0c8(0x1b9)](_0x555ecb);}}[a0_0x492ede(0x167)](_0xb8606a,_0x4ea0f5=null){const _0x3be198=a0_0x492ede,_0x1415d9=_0xb8606a+'-'+(_0x4ea0f5||'default');return this[_0x3be198(0x181)]['get'](_0x1415d9)||_0x4ea0f5||process['cwd']();}[a0_0x492ede(0xc0)](){const _0xd6135d=a0_0x492ede;this['platformType']=process['platform'];if(process['platform']===_0xd6135d(0x126)){if(process[_0xd6135d(0x9f)][_0xd6135d(0x1c3)])this[_0xd6135d(0xa9)]=_0xd6135d(0x10d);else process[_0xd6135d(0x9f)]['SHELL']&&process['env'][_0xd6135d(0x17f)][_0xd6135d(0x17a)](_0xd6135d(0xd1))?this[_0xd6135d(0xa9)]=_0xd6135d(0xd1):this['detectedTerminal']='cmd';}else process[_0xd6135d(0x155)]==='darwin'?this[_0xd6135d(0xa9)]='bash':this['detectedTerminal']='bash';this[_0xd6135d(0xdb)]?.[_0xd6135d(0x14f)](_0xd6135d(0xd4),{'platform':this[_0xd6135d(0xff)],'terminal':this['detectedTerminal'],'shell':process[_0xd6135d(0x9f)][_0xd6135d(0x17f)]});}async['translateCommand'](_0x44bde0,_0x21821e={}){const _0x1b5d7d=a0_0x492ede,_0xbe6d60=_0x44bde0['trim'](),_0x35776a=this[_0x1b5d7d(0x178)](_0xbe6d60);this[_0x1b5d7d(0xdb)]?.['info'](_0x1b5d7d(0x114),{'command':_0xbe6d60,'detectedTerminal':_0x35776a[_0x1b5d7d(0xa9)],'commandType':_0x35776a[_0x1b5d7d(0x1d0)],'commandCategory':_0x35776a[_0x1b5d7d(0xa8)],'compatible':_0x35776a[_0x1b5d7d(0x1c0)],'issues':_0x35776a[_0x1b5d7d(0x1a4)],'suggestedAction':_0x35776a['suggestedAction'],'confidence':_0x35776a['confidence']});if(_0x35776a[_0x1b5d7d(0x1c0)])return _0x44bde0;let _0x16089a=null;if(this['detectedTerminal']===_0x1b5d7d(0x100))_0x16089a=this['translateToWindowsCmd'](_0xbe6d60);else{if(this[_0x1b5d7d(0xa9)]===_0x1b5d7d(0x10d))_0x16089a=this[_0x1b5d7d(0x17b)](_0xbe6d60);else this[_0x1b5d7d(0xa9)]===_0x1b5d7d(0xd1)&&(_0x16089a=this['translateToBash'](_0xbe6d60));}if(_0x16089a&&this['isSimpleCommand'](_0xbe6d60))return this[_0x1b5d7d(0xdb)]?.[_0x1b5d7d(0x14f)]('Using\x20simple\x20translation',{'original':_0x44bde0,'translated':_0x16089a,'method':'simple'}),_0x16089a;if(_0x21821e[_0x1b5d7d(0x111)]||_0x21821e[_0x1b5d7d(0x91)]&&_0x21821e['agentId']){this[_0x1b5d7d(0xdb)]?.['info'](_0x1b5d7d(0xd3),{'command':_0x44bde0['substring'](0x0,0x64)+'...','hasAiService':!!_0x21821e['aiService'],'hasToolsRegistry':!!_0x21821e['toolsRegistry'],'agentId':_0x21821e['agentId']});try{const _0x363bad=await this[_0x1b5d7d(0x10f)](_0x44bde0,_0x21821e);if(_0x363bad&&_0x363bad[_0x1b5d7d(0xc8)]()!==_0x44bde0[_0x1b5d7d(0xc8)]())return this['logger']?.[_0x1b5d7d(0x14f)](_0x1b5d7d(0x1d7),{'original':_0x44bde0,'translated':_0x363bad,'method':'ai'}),_0x363bad;else this[_0x1b5d7d(0xdb)]?.[_0x1b5d7d(0x158)](_0x1b5d7d(0x10b),{'original':_0x44bde0,'translated':_0x363bad});}catch(_0x670631){this['logger']?.['warn'](_0x1b5d7d(0x10a),{'original':_0x44bde0,'error':_0x670631['message'],'stack':_0x670631[_0x1b5d7d(0x1a2)]});}}else this['logger']?.['warn']('AI\x20translation\x20not\x20available\x20-\x20missing\x20context',{'hasAiService':!!_0x21821e[_0x1b5d7d(0x111)],'hasToolsRegistry':!!_0x21821e['toolsRegistry'],'hasAgentId':!!_0x21821e[_0x1b5d7d(0x1bc)],'contextKeys':Object[_0x1b5d7d(0xca)](_0x21821e)});return _0x16089a||_0x44bde0;}['isSimpleCommand'](_0x50320f){const _0x39cda8=a0_0x492ede,_0x5bae0f=_0x50320f['toLowerCase']();if(_0x50320f[_0x39cda8(0x17a)]('\x5cn')||_0x50320f[_0x39cda8(0x17a)]('\x5cr')||_0x50320f[_0x39cda8(0x17a)]('\x5ct'))return![];if(_0x50320f['includes']('\x0a')||_0x50320f[_0x39cda8(0x17a)]('\x0d'))return![];if(_0x50320f[_0x39cda8(0x17a)]('#include')||_0x50320f['includes']('printf')||_0x50320f['includes'](_0x39cda8(0xdd)))return![];if(_0x50320f[_0x39cda8(0x17a)](_0x39cda8(0x1c7))||_0x50320f[_0x39cda8(0x17a)](_0x39cda8(0xf4))||_0x50320f['includes']('class\x20'))return![];if(_0x50320f[_0x39cda8(0x17a)]('echo\x20\x27')&&!_0x50320f['includes']('echo\x20\x22'))return![];const _0x4761b6=_0x50320f[_0x39cda8(0x8f)](/'([^']*)'/);if(_0x4761b6&&_0x4761b6[0x1][_0x39cda8(0x117)]>0x32)return![];if(this['detectedTerminal']==='cmd'&&_0x50320f['includes']('>')&&_0x50320f['includes']('/')&&!_0x50320f[_0x39cda8(0x17a)]('\x5c'))return![];if(_0x50320f['includes']('\x20&&\x20')||_0x50320f[_0x39cda8(0x17a)](_0x39cda8(0x162))||_0x50320f['includes'](';\x20'))return![];if(_0x50320f[_0x39cda8(0x17a)]('$(')||_0x50320f[_0x39cda8(0x17a)]('`')||_0x50320f[_0x39cda8(0x17a)]('{')||_0x50320f['includes']('['))return![];if(_0x5bae0f['includes']('for\x20')||_0x5bae0f['includes'](_0x39cda8(0x14d))||_0x5bae0f['includes'](_0x39cda8(0xa3)))return![];if(_0x5bae0f['includes']('export ')||_0x5bae0f['includes']('source\x20'))return![];if(_0x50320f['includes']('\x20|\x20')||_0x50320f[_0x39cda8(0x17a)]('\x20>\x20&'))return![];return!![];}async['translateCommandWithAI'](_0x3108f2,_0x21b223){const _0x4f46b4=a0_0x492ede;let _0x2e4dcf=_0x21b223['aiService'];if(!_0x2e4dcf&&_0x21b223[_0x4f46b4(0x91)]&&_0x21b223['agentId']){const _0x5aadbb=_0x21b223[_0x4f46b4(0x92)];_0x5aadbb&&_0x5aadbb['aiService']&&(_0x2e4dcf=_0x5aadbb[_0x4f46b4(0x111)]);}if(!_0x2e4dcf)throw new Error('AI\x20service\x20not\x20available\x20for\x20command\x20translation');const _0x27b269=this['buildTranslationPrompt'](_0x3108f2),_0x5153d4=_0x4f46b4(0x107);try{const _0x20e76f=await _0x2e4dcf[_0x4f46b4(0x1d1)](_0x5153d4,_0x27b269,{'agentId':_0x21b223[_0x4f46b4(0x1bc)],'temperature':0.1,'maxTokens':0xc8,'apiKey':_0x21b223[_0x4f46b4(0xe5)],'customApiKeys':_0x21b223['customApiKeys'],'platformProvided':_0x21b223['platformProvided']}),_0xc8047d=this['extractTranslatedCommand'](_0x20e76f[_0x4f46b4(0x187)]);return this['logger']?.[_0x4f46b4(0x140)](_0x4f46b4(0x147),{'original':_0x3108f2,'translated':_0xc8047d,'model':_0x5153d4,'terminal':this['detectedTerminal']}),_0xc8047d;}catch(_0x149f8b){this[_0x4f46b4(0xdb)]?.['error'](_0x4f46b4(0x151),{'command':_0x3108f2,'terminal':this['detectedTerminal'],'error':_0x149f8b[_0x4f46b4(0x130)]});throw _0x149f8b;}}[a0_0x492ede(0x1bf)](_0x105aa6){const _0x36d994=a0_0x492ede,_0x96c034={'cmd':_0x36d994(0xcc),'powershell':'Windows\x20PowerShell','bash':_0x36d994(0x157)},_0x29998e=_0x96c034[this['detectedTerminal']]||this[_0x36d994(0xa9)],_0x1c8658=this[_0x36d994(0x178)](_0x105aa6);let _0x3788fb='Translate\x20this\x20command\x20to\x20work\x20correctly\x20in\x20'+_0x29998e+_0x36d994(0x17e)+_0x105aa6+_0x36d994(0x1be)+_0x1c8658[_0x36d994(0x1d0)]+_0x36d994(0x16f)+_0x1c8658[_0x36d994(0xa8)]+_0x36d994(0x138)+_0x29998e+_0x36d994(0xe9)+(_0x1c8658['specificIssues'][_0x36d994(0x11c)](',\x20')||'None\x20detected');return _0x1c8658[_0x36d994(0x1d0)]==='unix'&&_0x1c8658[_0x36d994(0x184)]&&_0x1c8658['alternatives'][this['detectedTerminal']]&&(_0x3788fb+=_0x36d994(0xbf)+_0x1c8658['alternatives'][this[_0x36d994(0xa9)]]),_0x3788fb+=_0x36d994(0x159)+_0x29998e+_0x36d994(0xa0),_0x3788fb;}['extractTranslatedCommand'](_0x5520e5){const _0x8637ae=a0_0x492ede;let _0x3e38e7=_0x5520e5['replace'](/```[a-z]*\n?(.*?)\n?```/s,'$1');_0x3e38e7=_0x3e38e7['replace'](/^(TRANSLATED COMMAND:|Command:|Result:)\s*/i,'');const _0x19ef33=_0x3e38e7['trim']()['split']('\x0a');return _0x19ef33[_0x8637ae(0x117)]>0x1&&!_0x3e38e7['includes']('&&')&&!_0x3e38e7[_0x8637ae(0x17a)]('||')&&(_0x3e38e7=_0x19ef33[0x0]['trim']()),_0x3e38e7['trim']();}['analyzeCommandCompatibility'](_0x56c65f){const _0x458ac6=a0_0x492ede,_0x31ccda=this['classifyCommand'](_0x56c65f),_0x16a67a=this[_0x458ac6(0x189)](_0x31ccda,this['detectedTerminal']);return{'compatible':_0x16a67a,'detectedTerminal':this['detectedTerminal'],'commandType':_0x31ccda['type'],'commandCategory':_0x31ccda[_0x458ac6(0xc2)],'specificIssues':_0x31ccda[_0x458ac6(0x13a)],'suggestedAction':_0x16a67a?_0x458ac6(0x149):'translate','confidence':_0x31ccda['confidence']};}[a0_0x492ede(0x125)](_0x1cda23){const _0x1b0d7f=a0_0x492ede;return this[_0x1b0d7f(0x178)](_0x1cda23)[_0x1b0d7f(0x1c0)];}['classifyCommand'](_0x3e191e){const _0x39b07e=a0_0x492ede,_0x1c62bd=_0x3e191e['toLowerCase']()[_0x39b07e(0xc8)](),_0x135ec8=_0x1c62bd['split']('\x20')[0x0],_0x50b8b4=[];let _0x4a9982=0.9;const _0x53d1a5={'ls':{'category':'file-listing','alternatives':{'cmd':_0x39b07e(0x13c),'powershell':_0x39b07e(0x124)}},'cat':{'category':'file-viewing','alternatives':{'cmd':'type','powershell':_0x39b07e(0xcf)}},'grep':{'category':'text-search','alternatives':{'cmd':'findstr','powershell':_0x39b07e(0x12a)}},'find':{'category':'file-search','alternatives':{'cmd':_0x39b07e(0x94),'powershell':'Get-ChildItem\x20-Recurse'}},'head':{'category':'file-viewing','alternatives':{'cmd':'more','powershell':'Get-Content\x20-Head'}},'tail':{'category':'file-viewing','alternatives':{'cmd':_0x39b07e(0x133),'powershell':'Get-Content\x20-Tail'}},'wc':{'category':'text-analysis','alternatives':{'cmd':_0x39b07e(0x16a),'powershell':'Measure-Object'}},'cp':{'category':_0x39b07e(0x120),'alternatives':{'cmd':_0x39b07e(0x1d2),'powershell':'Copy-Item'}},'mv':{'category':_0x39b07e(0xcd),'alternatives':{'cmd':'move','powershell':'Move-Item'}},'rm':{'category':'file-delete','alternatives':{'cmd':'del','powershell':'Remove-Item'}},'mkdir':{'category':'directory-create','alternatives':{'cmd':_0x39b07e(0x186),'powershell':_0x39b07e(0xea)}},'rmdir':{'category':'directory-delete','alternatives':{'cmd':_0x39b07e(0x17d),'powershell':'Remove-Item'}},'touch':{'category':_0x39b07e(0x188),'alternatives':{'cmd':'type\x20nul\x20>','powershell':_0x39b07e(0x144)}},'chmod':{'category':_0x39b07e(0x11b),'alternatives':{'cmd':'icacls','powershell':'Set-Acl'}},'chown':{'category':'ownership','alternatives':{'cmd':'takeown','powershell':_0x39b07e(0xd5)}},'ps':{'category':_0x39b07e(0xbd),'alternatives':{'cmd':'tasklist','powershell':_0x39b07e(0x1b0)}},'kill':{'category':'process-kill','alternatives':{'cmd':'taskkill','powershell':'Stop-Process'}},'killall':{'category':_0x39b07e(0xbc),'alternatives':{'cmd':_0x39b07e(0x19c),'powershell':_0x39b07e(0x146)}},'top':{'category':'process-monitor','alternatives':{'cmd':_0x39b07e(0x1ce),'powershell':'Get-Process\x20|\x20Sort-Object\x20CPU'}},'wget':{'category':_0x39b07e(0x135),'alternatives':{'cmd':_0x39b07e(0xe1),'powershell':'Invoke-WebRequest'}},'curl':{'category':_0x39b07e(0x9d),'alternatives':{'cmd':_0x39b07e(0xe1),'powershell':_0x39b07e(0x11e)}},'ping':{'category':_0x39b07e(0x15f),'alternatives':{'cmd':'ping','powershell':'Test-NetConnection'}},'awk':{'category':'text-processing','alternatives':{'cmd':_0x39b07e(0x118),'powershell':_0x39b07e(0x19e)}},'sed':{'category':'text-edit','alternatives':{'cmd':_0x39b07e(0x9a),'powershell':'native'}},'sort':{'category':'text-sort','alternatives':{'cmd':_0x39b07e(0xac),'powershell':'Sort-Object'}},'uniq':{'category':'text-dedupe','alternatives':{'cmd':'sort\x20/unique','powershell':'Sort-Object\x20-Unique'}},'pwd':{'category':_0x39b07e(0xb7),'alternatives':{'cmd':'cd','powershell':_0x39b07e(0x15a)}},'whoami':{'category':_0x39b07e(0x1ca),'alternatives':{'cmd':_0x39b07e(0x142),'powershell':_0x39b07e(0xdf)}},'env':{'category':'environment','alternatives':{'cmd':_0x39b07e(0xf0),'powershell':'Get-ChildItem\x20Env:'}},'export':{'category':'environment','alternatives':{'cmd':'set','powershell':'$env:'}},'source':{'category':'script-execute','alternatives':{'cmd':_0x39b07e(0x14b),'powershell':'.\x20'}},'tar':{'category':'archive','alternatives':{'cmd':'7z','powershell':_0x39b07e(0xee)}},'zip':{'category':_0x39b07e(0x103),'alternatives':{'cmd':'powershell\x20Compress-Archive','powershell':_0x39b07e(0xee)}},'unzip':{'category':_0x39b07e(0x103),'alternatives':{'cmd':_0x39b07e(0xf2),'powershell':_0x39b07e(0x9b)}},'df':{'category':_0x39b07e(0x8e),'alternatives':{'cmd':'fsutil\x20volume\x20diskfree','powershell':'Get-WmiObject\x20-Class\x20Win32_LogicalDisk'}},'du':{'category':'disk-usage','alternatives':{'cmd':_0x39b07e(0x94),'powershell':_0x39b07e(0x19f)}},'free':{'category':'memory-info','alternatives':{'cmd':'systeminfo','powershell':_0x39b07e(0x173)}},'uname':{'category':'system-info','alternatives':{'cmd':_0x39b07e(0x12d),'powershell':'Get-ComputerInfo'}}},_0xf720c6={'dir':{'category':'file-listing','alternatives':{'unix':'ls','powershell':'Get-ChildItem'}},'type':{'category':_0x39b07e(0x163),'alternatives':{'unix':_0x39b07e(0xf7),'powershell':_0x39b07e(0xcf)}},'copy':{'category':_0x39b07e(0x120),'alternatives':{'unix':'cp','powershell':'Copy-Item'}},'move':{'category':'file-move','alternatives':{'unix':'mv','powershell':_0x39b07e(0x1c1)}},'del':{'category':'file-delete','alternatives':{'unix':'rm','powershell':_0x39b07e(0x1d6)}},'tasklist':{'category':'process-list','alternatives':{'unix':'ps','powershell':_0x39b07e(0x1b0)}},'taskkill':{'category':'process-kill','alternatives':{'unix':'kill','powershell':_0x39b07e(0xa6)}},'findstr':{'category':'text-search','alternatives':{'unix':'grep','powershell':'Select-String'}}},_0x1a7782={'get-childitem':{'category':'file-listing','alternatives':{'unix':'ls','cmd':'dir'}},'get-content':{'category':'file-viewing','alternatives':{'unix':'cat','cmd':_0x39b07e(0xb3)}},'copy-item':{'category':'file-copy','alternatives':{'unix':'cp','cmd':'copy'}},'move-item':{'category':_0x39b07e(0xcd),'alternatives':{'unix':'mv','cmd':'move'}},'remove-item':{'category':_0x39b07e(0xc3),'alternatives':{'unix':'rm','cmd':'del'}},'get-process':{'category':_0x39b07e(0xbd),'alternatives':{'unix':'ps','cmd':_0x39b07e(0x1ce)}},'stop-process':{'category':'process-kill','alternatives':{'unix':_0x39b07e(0x150),'cmd':'taskkill'}}};let _0x1f2b2d='unknown',_0x43c665=_0x39b07e(0x18e),_0x10f34a={};if(_0x53d1a5[_0x135ec8])_0x1f2b2d='unix',_0x43c665=_0x53d1a5[_0x135ec8]['category'],_0x10f34a=_0x53d1a5[_0x135ec8]['alternatives'];else{if(_0xf720c6[_0x135ec8])_0x1f2b2d=_0x39b07e(0x160),_0x43c665=_0xf720c6[_0x135ec8][_0x39b07e(0xc2)],_0x10f34a=_0xf720c6[_0x135ec8]['alternatives'];else{if(_0x1a7782[_0x135ec8])_0x1f2b2d='powershell',_0x43c665=_0x1a7782[_0x135ec8][_0x39b07e(0xc2)],_0x10f34a=_0x1a7782[_0x135ec8][_0x39b07e(0x184)];else{const _0x26a420=[_0x39b07e(0xad),'cd','exit','help'];_0x26a420[_0x39b07e(0x17a)](_0x135ec8)?(_0x1f2b2d=_0x39b07e(0x1b1),_0x43c665='builtin'):(_0x1f2b2d=_0x39b07e(0x18e),_0x4a9982=0.3);}}}return _0x3e191e[_0x39b07e(0x17a)]('\x27')&&!_0x3e191e['includes']('\x22')&&_0x50b8b4[_0x39b07e(0x16b)]('single-quotes-problematic'),_0x3e191e['includes']('/')&&!_0x3e191e['includes']('\x5c')&&!_0x3e191e[_0x39b07e(0x17a)]('http')&&_0x3e191e[_0x39b07e(0x17a)]('>')&&_0x50b8b4[_0x39b07e(0x16b)]('unix-style-paths'),(_0x3e191e['includes']('\x5cn')||_0x3e191e['includes']('\x5ct'))&&_0x50b8b4[_0x39b07e(0x16b)](_0x39b07e(0x1ba)),(_0x3e191e['includes']('\x20&&\x20')||_0x3e191e['includes']('\x20||\x20')||_0x3e191e['includes'](';'))&&_0x50b8b4['push']('command-chaining'),{'type':_0x1f2b2d,'category':_0x43c665,'alternatives':_0x10f34a,'issues':_0x50b8b4,'confidence':_0x4a9982,'firstWord':_0x135ec8,'fullCommand':_0x3e191e};}[a0_0x492ede(0x189)](_0xcc71b4,_0x15297a){const _0x2f1d76=a0_0x492ede;switch(_0x15297a){case _0x2f1d76(0x100):if(_0xcc71b4[_0x2f1d76(0xb3)]===_0x2f1d76(0x161))return![];if(_0xcc71b4[_0x2f1d76(0x13a)][_0x2f1d76(0x17a)](_0x2f1d76(0xb9)))return![];if(_0xcc71b4['issues']['includes'](_0x2f1d76(0x166)))return![];return _0xcc71b4['type']==='windows-cmd'||_0xcc71b4['type']==='universal';case _0x2f1d76(0x10d):if(_0xcc71b4[_0x2f1d76(0xb3)]==='unix'&&!_0xcc71b4['alternatives'][_0x2f1d76(0x10d)])return![];return!![];case _0x2f1d76(0xd1):if(_0xcc71b4['type']==='windows-cmd')return![];return _0xcc71b4[_0x2f1d76(0xb3)]===_0x2f1d76(0x161)||_0xcc71b4[_0x2f1d76(0xb3)]==='universal';default:return![];}}['translateToWindowsCmd'](_0x188fc8){const _0x2743a4=a0_0x492ede;let _0x57d5d9=_0x188fc8;const _0x577bcc=new Map([[/^ls\s*$/,_0x2743a4(0x13c)],[/^ls\s+-la?$/,'dir'],[/^ls\s+-l$/,_0x2743a4(0x13c)],[/^ls\s+-a$/,'dir\x20/a'],[/^cat\s+(.+)$/,_0x2743a4(0xe3)],[/^cp\s+(.+)\s+(.+)$/,_0x2743a4(0x110)],[/^mv\s+(.+)\s+(.+)$/,'move\x20$1\x20$2'],[/^rm\s+(.+)$/,'del\x20$1'],[/^mkdir\s+(.+)$/,'mkdir\x20$1'],[/^rmdir\s+(.+)$/,'rmdir\x20$1'],[/^ps\s*$/,_0x2743a4(0x1ce)],[/^kill\s+(.+)$/,_0x2743a4(0x185)],[/^pwd\s*$/,'cd'],[/^whoami\s*$/,'echo\x20%USERNAME%'],[/^ping\s+(.+)$/,'ping\x20$1'],[/^wget\s+(.+)$/,'curl\x20-O\x20$1'],[/^curl\s+(.+)$/,_0x2743a4(0x119)]]);for(const [_0xfc1ec,_0x3c87b1]of _0x577bcc){if(_0xfc1ec[_0x2743a4(0x1c9)](_0x57d5d9)){_0x57d5d9=_0x57d5d9['replace'](_0xfc1ec,_0x3c87b1);break;}}_0x57d5d9=_0x57d5d9[_0x2743a4(0x8c)](/echo\s+'([^']+)'\s*>/g,_0x2743a4(0xa7)),_0x57d5d9=_0x57d5d9[_0x2743a4(0x8c)](/echo\s+'([^']+)'$/g,'echo\x20\x22$1\x22');if(_0x57d5d9[_0x2743a4(0x17a)](_0x2743a4(0xb0))&&_0x57d5d9['includes']('\x5cn')){const _0x11819c=_0x57d5d9[_0x2743a4(0x8f)](/echo\s+'(.+?)'\s*>\s*(.+)$/);if(_0x11819c){const _0x4b14a3=_0x11819c[0x1][_0x2743a4(0x8c)](/\\n/g,'\x0a'),_0x4e922c=_0x11819c[0x2],_0x7d2b2b=_0x4b14a3[_0x2743a4(0xc7)]('\x0a');_0x57d5d9='('+_0x7d2b2b[_0x2743a4(0x199)](_0x3e3ba1=>'echo\x20'+_0x3e3ba1)[_0x2743a4(0x11c)](_0x2743a4(0xd6))+_0x2743a4(0xf5)+_0x4e922c;}}return this[_0x2743a4(0xdb)]?.['info'](_0x2743a4(0x172),{'original':_0x188fc8,'translated':_0x57d5d9}),_0x57d5d9;}['translateToPowerShell'](_0x2e6198){const _0x8066c6=a0_0x492ede;let _0x28fda8=_0x2e6198;const _0x30af71=new Map([[/^ls\s*$/,_0x8066c6(0x124)],[/^ls\s+-la?$/,'Get-ChildItem\x20-Force'],[/^cat\s+(.+)$/,_0x8066c6(0x136)],[/^cp\s+(.+)\s+(.+)$/,'Copy-Item\x20$1\x20$2'],[/^mv\s+(.+)\s+(.+)$/,_0x8066c6(0x1d3)],[/^rm\s+(.+)$/,_0x8066c6(0xf3)],[/^pwd\s*$/,'Get-Location'],[/^ps\s*$/,_0x8066c6(0x1b0)]]);for(const [_0x11747e,_0x22e33a]of _0x30af71){if(_0x11747e['test'](_0x28fda8)){_0x28fda8=_0x28fda8['replace'](_0x11747e,_0x22e33a);break;}}return this['logger']?.['info']('Command\x20translated\x20for\x20PowerShell',{'original':_0x2e6198,'translated':_0x28fda8}),_0x28fda8;}['translateToBash'](_0x18462d){const _0xf8f485=a0_0x492ede;let _0xee44cf=_0x18462d;const _0x563e5c=new Map([[/^dir\s*$/,'ls'],[/^dir\s+\/a$/,'ls\x20-a'],[/^type\s+(.+)$/,'cat\x20$1'],[/^copy\s+(.+)\s+(.+)$/,'cp\x20$1\x20$2'],[/^move\s+(.+)\s+(.+)$/,'mv\x20$1\x20$2'],[/^del\s+(.+)$/,'rm\x20$1'],[/^tasklist\s*$/,'ps'],[/^cd\s*$/,'pwd']]);for(const [_0x14f077,_0x4a688d]of _0x563e5c){if(_0x14f077['test'](_0xee44cf)){_0xee44cf=_0xee44cf[_0xf8f485(0x8c)](_0x14f077,_0x4a688d);break;}}return _0xee44cf;}async['cleanup'](_0x3b2b5f){}async['startBackgroundCommand'](_0x474d2f,_0x25a7d1,_0x5a23bd={}){const _0x5883b5=a0_0x492ede,{agentId:_0x418857,context:_0x115cda}=_0x5a23bd;if(!_0x418857)throw new Error('agentId\x20is\x20required\x20for\x20background\x20commands');const _0x2d472=this['getAgentCommands'](_0x418857),_0xfd06a2=_0x2d472['filter'](_0x1a94db=>_0x1a94db[_0x5883b5(0x113)]===_0x5883b5(0x13e)||_0x1a94db['state']==='waiting_for_input');if(_0xfd06a2['length']>=this[_0x5883b5(0xb2)])throw new Error('Maximum\x20background\x20commands\x20per\x20agent\x20exceeded\x20('+this['MAX_BACKGROUND_COMMANDS_PER_AGENT']+')');const _0xec3889=Array['from'](this[_0x5883b5(0xdc)][_0x5883b5(0x19b)]()),_0x50ac15=_0xec3889['filter'](_0x13c28e=>_0x13c28e['state']===_0x5883b5(0x13e)||_0x13c28e['state']===_0x5883b5(0x109));if(_0x50ac15['length']>=this[_0x5883b5(0x182)])throw new Error('Maximum\x20global\x20background\x20commands\x20exceeded\x20('+this[_0x5883b5(0x182)]+')');const _0x366edb=_0x418857+'-cmd-'+Date[_0x5883b5(0x1c4)]()+'-'+ ++this[_0x5883b5(0x1ae)],_0x3d160b=_0x474d2f;let _0x454d3d;try{_0x454d3d=await this[_0x5883b5(0x106)](_0x474d2f,{'agentId':_0x418857,'toolsRegistry':_0x115cda?.['toolsRegistry'],'messageProcessor':_0x115cda?.['messageProcessor'],'aiService':_0x115cda?.['aiService'],'apiKey':_0x115cda?.[_0x5883b5(0xe5)],'customApiKeys':_0x115cda?.[_0x5883b5(0x12e)],'platformProvided':_0x115cda?.[_0x5883b5(0x1c6)]});}catch(_0x5e756b){this[_0x5883b5(0xdb)]?.[_0x5883b5(0x158)](_0x5883b5(0x128),{'originalCommand':_0x3d160b,'error':_0x5e756b[_0x5883b5(0x130)]}),_0x454d3d=_0x474d2f;}this['logger']?.['info']('Starting\x20background\x20command:\x20'+_0x454d3d,{'commandId':_0x366edb,'agentId':_0x418857,'originalCommand':_0x3d160b,'workingDirectory':_0x25a7d1});let _0x1ddee7;if(this['detectedTerminal']==='cmd'||this['detectedTerminal']==='powershell'){const _0x51dc00=this[_0x5883b5(0xa9)]===_0x5883b5(0x10d)?_0x5883b5(0x10d):'cmd',_0x540adb=this[_0x5883b5(0xa9)]===_0x5883b5(0x10d)?[_0x5883b5(0xde),_0x454d3d]:['/c',_0x454d3d];_0x1ddee7=spawn(_0x51dc00,_0x540adb,{'cwd':_0x25a7d1,'env':{...process['env']},'windowsHide':!![],'stdio':[_0x5883b5(0x1bd),_0x5883b5(0x1bd),'pipe']});}else _0x1ddee7=spawn('sh',['-c',_0x454d3d],{'cwd':_0x25a7d1,'env':{...process[_0x5883b5(0x9f)]},'stdio':['pipe',_0x5883b5(0x1bd),'pipe']});const _0x3e0d38={'commandId':_0x366edb,'agentId':_0x418857,'pid':_0x1ddee7['pid'],'command':_0x3d160b,'translatedCommand':_0x454d3d,'workingDirectory':_0x25a7d1,'startTime':new Date()['toISOString'](),'state':_0x5883b5(0x13e),'exitCode':null,'stdoutBuffer':'','stderrBuffer':'','lastOutputTime':Date[_0x5883b5(0x1c4)](),'promptDetected':null,'process':_0x1ddee7};return this['commandTracker']['set'](_0x366edb,_0x3e0d38),_0x1ddee7[_0x5883b5(0x1a3)]['on'](_0x5883b5(0x9c),_0x47aac1=>{const _0x5b405a=_0x5883b5,_0x360942=_0x47aac1['toString']();_0x3e0d38[_0x5b405a(0x108)]+=_0x360942,_0x3e0d38[_0x5b405a(0x183)]=Date[_0x5b405a(0x1c4)]();if(!_0x3e0d38['promptDetected']){const _0x579f83=this[_0x5b405a(0x1cb)][_0x5b405a(0xcb)](_0x3e0d38[_0x5b405a(0x108)],'stdout');_0x579f83&&(_0x3e0d38['promptDetected']=_0x579f83,_0x3e0d38['state']='waiting_for_input',this[_0x5b405a(0xdb)]?.['info']('Prompt\x20detected\x20in\x20background\x20command',{'commandId':_0x366edb,'agentId':_0x418857,'type':_0x579f83[_0x5b405a(0xb3)],'matchedText':_0x579f83[_0x5b405a(0x112)]}));}}),_0x1ddee7[_0x5883b5(0xd8)]['on'](_0x5883b5(0x9c),_0x370f0c=>{const _0x1c66cd=_0x5883b5,_0x3cadb2=_0x370f0c['toString']();_0x3e0d38['stderrBuffer']+=_0x3cadb2,_0x3e0d38[_0x1c66cd(0x183)]=Date['now']();if(!_0x3e0d38['promptDetected']){const _0x1b8451=this['promptDetector'][_0x1c66cd(0xcb)](_0x3e0d38[_0x1c66cd(0xe0)],_0x1c66cd(0xd8));_0x1b8451&&(_0x3e0d38['promptDetected']=_0x1b8451,_0x3e0d38['state']=_0x1c66cd(0x109),this[_0x1c66cd(0xdb)]?.[_0x1c66cd(0x14f)](_0x1c66cd(0x192),{'commandId':_0x366edb,'agentId':_0x418857,'type':_0x1b8451['type'],'matchedText':_0x1b8451[_0x1c66cd(0x112)]}));}}),_0x1ddee7['on'](_0x5883b5(0xa4),(_0x3188ee,_0x3ed2a8)=>{const _0x5d0f69=_0x5883b5;_0x3e0d38[_0x5d0f69(0x164)]=_0x3188ee,_0x3e0d38['state']=_0x3188ee===0x0?'completed':'failed',_0x3e0d38[_0x5d0f69(0xd2)]=new Date()[_0x5d0f69(0x15e)](),this[_0x5d0f69(0xdb)]?.[_0x5d0f69(0x14f)]('Background\x20command\x20exited',{'commandId':_0x366edb,'agentId':_0x418857,'exitCode':_0x3188ee,'signal':_0x3ed2a8,'state':_0x3e0d38[_0x5d0f69(0x113)]});}),_0x1ddee7['on'](_0x5883b5(0x101),_0xb0a0e8=>{const _0x542c0b=_0x5883b5;_0x3e0d38[_0x542c0b(0x113)]='failed',_0x3e0d38[_0x542c0b(0x101)]=_0xb0a0e8['message'],_0x3e0d38[_0x542c0b(0xd2)]=new Date()[_0x542c0b(0x15e)](),this[_0x542c0b(0xdb)]?.['error']('Background\x20command\x20error',{'commandId':_0x366edb,'agentId':_0x418857,'error':_0xb0a0e8[_0x542c0b(0x130)]});}),{'success':!![],'commandId':_0x366edb,'pid':_0x1ddee7['pid'],'command':_0x3d160b,'translatedCommand':_0x454d3d,'workingDirectory':_0x25a7d1,'message':_0x5883b5(0x1aa)+_0x366edb};}[a0_0x492ede(0xab)](_0x300160,_0x8ec8b2,_0x28f294){const _0x346db2=a0_0x492ede,_0x1ece3a=this[_0x346db2(0x156)](_0x300160,_0x28f294);if(_0x1ece3a['state']===_0x346db2(0x1c8)||_0x1ece3a['state']==='failed')throw new Error(_0x346db2(0x16e)+_0x1ece3a['state']+'\x20command');if(!_0x1ece3a['process']||_0x1ece3a[_0x346db2(0x1af)]['killed'])throw new Error(_0x346db2(0x1b4));const _0x2e10bf=_0x8ec8b2['endsWith']('\x0a')?_0x8ec8b2:_0x8ec8b2+'\x0a';return _0x1ece3a[_0x346db2(0x1af)]['stdin']['write'](_0x2e10bf),this['logger']?.['info']('Input\x20sent\x20to\x20background\x20command',{'commandId':_0x300160,'agentId':_0x28f294,'inputLength':_0x8ec8b2[_0x346db2(0x117)]}),_0x1ece3a['state']==='waiting_for_input'&&(_0x1ece3a['state']='running',_0x1ece3a['promptDetected']=null),{'success':!![],'commandId':_0x300160,'message':_0x346db2(0x99)};}['getCommandStatus'](_0xd6218c,_0x2cc875){const _0x4df033=a0_0x492ede,_0x2f6392=this[_0x4df033(0x156)](_0xd6218c,_0x2cc875),_0x253bc6=Date[_0x4df033(0x1c4)]()-_0x2f6392['lastOutputTime'];return{'success':!![],'commandId':_0xd6218c,'pid':_0x2f6392['pid'],'command':_0x2f6392[_0x4df033(0x177)],'state':_0x2f6392[_0x4df033(0x113)],'exitCode':_0x2f6392['exitCode'],'startTime':_0x2f6392['startTime'],'endTime':_0x2f6392['endTime'],'workingDirectory':_0x2f6392[_0x4df033(0x123)],'stdout':_0x2f6392[_0x4df033(0x108)],'stderr':_0x2f6392[_0x4df033(0xe0)],'stdoutLength':_0x2f6392['stdoutBuffer'][_0x4df033(0x117)],'stderrLength':_0x2f6392[_0x4df033(0xe0)][_0x4df033(0x117)],'lastOutputTime':_0x2f6392['lastOutputTime'],'timeSinceLastOutput':_0x253bc6,'promptDetected':!!_0x2f6392[_0x4df033(0xbb)],'promptInfo':_0x2f6392['promptDetected']||undefined};}[a0_0x492ede(0xc5)](_0x585b07,_0x220e75){const _0x27b20f=a0_0x492ede,_0x3d401e=this['validateCommandOwnership'](_0x585b07,_0x220e75);if(_0x3d401e['state']==='completed'||_0x3d401e['state']===_0x27b20f(0x1d4))return{'success':!![],'commandId':_0x585b07,'message':_0x27b20f(0xc1),'state':_0x3d401e[_0x27b20f(0x113)]};if(_0x3d401e['process']&&!_0x3d401e['process'][_0x27b20f(0x1b6)])return _0x3d401e[_0x27b20f(0x1af)][_0x27b20f(0x150)]('SIGTERM'),setTimeout(()=>{const _0x6549fe=_0x27b20f;_0x3d401e['process']&&!_0x3d401e[_0x6549fe(0x1af)][_0x6549fe(0x1b6)]&&_0x3d401e[_0x6549fe(0x1af)]['kill'](_0x6549fe(0xa5));},0x1388),this[_0x27b20f(0xdb)]?.['info'](_0x27b20f(0x10c),{'commandId':_0x585b07,'agentId':_0x220e75}),{'success':!![],'commandId':_0x585b07,'message':_0x27b20f(0x13b)};return{'success':![],'commandId':_0x585b07,'error':_0x27b20f(0x1cc)};}[a0_0x492ede(0x1cd)](_0x14b681){const _0x4de011=a0_0x492ede,_0x331f6f=this['getAgentCommands'](_0x14b681);return _0x331f6f['map'](_0x5e8bbd=>({'commandId':_0x5e8bbd['commandId'],'command':_0x5e8bbd['command'],'state':_0x5e8bbd['state'],'pid':_0x5e8bbd['pid'],'exitCode':_0x5e8bbd[_0x4de011(0x164)],'startTime':_0x5e8bbd[_0x4de011(0xc4)],'endTime':_0x5e8bbd['endTime'],'promptDetected':!!_0x5e8bbd[_0x4de011(0xbb)],'timeSinceLastOutput':Date[_0x4de011(0x1c4)]()-_0x5e8bbd[_0x4de011(0x183)]}));}['getAgentCommands'](_0x2c41f1){const _0xee0bc9=a0_0x492ede;return Array['from'](this['commandTracker'][_0xee0bc9(0x19b)]())[_0xee0bc9(0x19a)](_0x41810a=>_0x41810a[_0xee0bc9(0x1bc)]===_0x2c41f1);}[a0_0x492ede(0x156)](_0x30b5fe,_0x49b0b6){const _0x153d7a=a0_0x492ede,_0x2be09e=this[_0x153d7a(0xdc)][_0x153d7a(0xce)](_0x30b5fe);if(!_0x2be09e)throw new Error(_0x153d7a(0xfa)+_0x30b5fe);if(_0x2be09e[_0x153d7a(0x1bc)]!==_0x49b0b6)throw new Error('Access\x20denied:\x20Command\x20belongs\x20to\x20agent\x20'+_0x2be09e[_0x153d7a(0x1bc)]);return _0x2be09e;}async[a0_0x492ede(0x15c)](_0x27f9e4){const _0x567b46=a0_0x492ede,_0x22208c=this['getAgentCommands'](_0x27f9e4);let _0x49a15b=0x0,_0x44c616=0x0;for(const _0x41ee95 of _0x22208c){_0x41ee95['process']&&!_0x41ee95['process']['killed']&&(_0x41ee95[_0x567b46(0x1af)][_0x567b46(0x150)](_0x567b46(0x190)),_0x49a15b++,setTimeout(()=>{const _0x4d543c=_0x567b46;_0x41ee95[_0x4d543c(0x1af)]&&!_0x41ee95['process'][_0x4d543c(0x1b6)]&&_0x41ee95['process'][_0x4d543c(0x150)]('SIGKILL');},0xbb8)),this[_0x567b46(0xdc)]['delete'](_0x41ee95['commandId']),_0x44c616++;}return this[_0x567b46(0xdb)]?.[_0x567b46(0x14f)](_0x567b46(0x16c),{'agentId':_0x27f9e4,'killedCount':_0x49a15b,'removedCount':_0x44c616}),{'success':!![],'agentId':_0x27f9e4,'killedCount':_0x49a15b,'removedCount':_0x44c616,'message':_0x567b46(0x195)+_0x44c616+_0x567b46(0x176)+_0x27f9e4};}[a0_0x492ede(0x1a1)](){const _0x6aee08=a0_0x492ede,_0x3c60fc=Date['now']();let _0x1237b7=0x0;for(const [_0x4da572,_0x37b5a4]of this['commandTracker']['entries']()){if(_0x37b5a4['state']!=='completed'&&_0x37b5a4['state']!==_0x6aee08(0x1d4))continue;const _0x188bdd=new Date(_0x37b5a4['startTime'])[_0x6aee08(0xfc)](),_0xf96f4a=(_0x3c60fc-_0x188bdd)/0x3e8/0x3c;_0xf96f4a>this['MAX_COMMAND_AGE_MINUTES']&&(this['commandTracker']['delete'](_0x4da572),_0x1237b7++);}return _0x1237b7>0x0&&this[_0x6aee08(0xdb)]?.[_0x6aee08(0x14f)]('Stale\x20commands\x20cleaned\x20up',{'removedCount':_0x1237b7,'ageThresholdMinutes':this['MAX_COMMAND_AGE_MINUTES']}),{'success':!![],'removedCount':_0x1237b7,'message':_0x6aee08(0x195)+_0x1237b7+'\x20stale\x20commands'};}}export default TerminalTool;