@loxia-labs/loxia-autopilot-one 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +267 -0
  2. package/README.md +509 -0
  3. package/bin/cli.js +117 -0
  4. package/package.json +94 -0
  5. package/scripts/install-scanners.js +236 -0
  6. package/src/analyzers/CSSAnalyzer.js +297 -0
  7. package/src/analyzers/ConfigValidator.js +690 -0
  8. package/src/analyzers/ESLintAnalyzer.js +320 -0
  9. package/src/analyzers/JavaScriptAnalyzer.js +261 -0
  10. package/src/analyzers/PrettierFormatter.js +247 -0
  11. package/src/analyzers/PythonAnalyzer.js +266 -0
  12. package/src/analyzers/SecurityAnalyzer.js +729 -0
  13. package/src/analyzers/TypeScriptAnalyzer.js +247 -0
  14. package/src/analyzers/codeCloneDetector/analyzer.js +344 -0
  15. package/src/analyzers/codeCloneDetector/detector.js +203 -0
  16. package/src/analyzers/codeCloneDetector/index.js +160 -0
  17. package/src/analyzers/codeCloneDetector/parser.js +199 -0
  18. package/src/analyzers/codeCloneDetector/reporter.js +148 -0
  19. package/src/analyzers/codeCloneDetector/scanner.js +59 -0
  20. package/src/core/agentPool.js +1474 -0
  21. package/src/core/agentScheduler.js +2147 -0
  22. package/src/core/contextManager.js +709 -0
  23. package/src/core/messageProcessor.js +732 -0
  24. package/src/core/orchestrator.js +548 -0
  25. package/src/core/stateManager.js +877 -0
  26. package/src/index.js +631 -0
  27. package/src/interfaces/cli.js +549 -0
  28. package/src/interfaces/webServer.js +2162 -0
  29. package/src/modules/fileExplorer/controller.js +280 -0
  30. package/src/modules/fileExplorer/index.js +37 -0
  31. package/src/modules/fileExplorer/middleware.js +92 -0
  32. package/src/modules/fileExplorer/routes.js +125 -0
  33. package/src/modules/fileExplorer/types.js +44 -0
  34. package/src/services/aiService.js +1232 -0
  35. package/src/services/apiKeyManager.js +164 -0
  36. package/src/services/benchmarkService.js +366 -0
  37. package/src/services/budgetService.js +539 -0
  38. package/src/services/contextInjectionService.js +247 -0
  39. package/src/services/conversationCompactionService.js +637 -0
  40. package/src/services/errorHandler.js +810 -0
  41. package/src/services/fileAttachmentService.js +544 -0
  42. package/src/services/modelRouterService.js +366 -0
  43. package/src/services/modelsService.js +322 -0
  44. package/src/services/qualityInspector.js +796 -0
  45. package/src/services/tokenCountingService.js +536 -0
  46. package/src/tools/agentCommunicationTool.js +1344 -0
  47. package/src/tools/agentDelayTool.js +485 -0
  48. package/src/tools/asyncToolManager.js +604 -0
  49. package/src/tools/baseTool.js +800 -0
  50. package/src/tools/browserTool.js +920 -0
  51. package/src/tools/cloneDetectionTool.js +621 -0
  52. package/src/tools/dependencyResolverTool.js +1215 -0
  53. package/src/tools/fileContentReplaceTool.js +875 -0
  54. package/src/tools/fileSystemTool.js +1107 -0
  55. package/src/tools/fileTreeTool.js +853 -0
  56. package/src/tools/imageTool.js +901 -0
  57. package/src/tools/importAnalyzerTool.js +1060 -0
  58. package/src/tools/jobDoneTool.js +248 -0
  59. package/src/tools/seekTool.js +956 -0
  60. package/src/tools/staticAnalysisTool.js +1778 -0
  61. package/src/tools/taskManagerTool.js +2873 -0
  62. package/src/tools/terminalTool.js +2304 -0
  63. package/src/tools/webTool.js +1430 -0
  64. package/src/types/agent.js +519 -0
  65. package/src/types/contextReference.js +972 -0
  66. package/src/types/conversation.js +730 -0
  67. package/src/types/toolCommand.js +747 -0
  68. package/src/utilities/attachmentValidator.js +292 -0
  69. package/src/utilities/configManager.js +582 -0
  70. package/src/utilities/constants.js +722 -0
  71. package/src/utilities/directoryAccessManager.js +535 -0
  72. package/src/utilities/fileProcessor.js +307 -0
  73. package/src/utilities/logger.js +436 -0
  74. package/src/utilities/tagParser.js +1246 -0
  75. package/src/utilities/toolConstants.js +317 -0
  76. package/web-ui/build/index.html +15 -0
  77. package/web-ui/build/logo.png +0 -0
  78. package/web-ui/build/logo2.png +0 -0
  79. package/web-ui/build/static/index-CjkkcnFA.js +344 -0
  80. package/web-ui/build/static/index-Dy2bYbOa.css +1 -0
@@ -0,0 +1,747 @@
1
+ /**
2
+ * Tool Command Data Model - Type definitions and validation for tool executions
3
+ *
4
+ * Purpose:
5
+ * - Define the structure and properties of tool commands and executions
6
+ * - Provide validation functions for tool command data
7
+ * - Handle tool execution lifecycle and state management
8
+ */
9
+
10
+ import { TOOL_STATUS, TOOL_NAMES, OPERATION_STATUS } from '../utilities/constants.js';
11
+
12
+ /**
13
+ * Tool Command data model
14
+ * @typedef {Object} ToolCommand
15
+ * @property {string} id - Unique command identifier
16
+ * @property {string} toolId - Tool identifier (e.g., 'terminal', 'filesys')
17
+ * @property {string} command - Command to execute
18
+ * @property {Object} parameters - Command parameters
19
+ * @property {string} status - Execution status (pending, executing, completed, failed)
20
+ * @property {string} agentId - ID of agent executing the command
21
+ * @property {string} conversationId - ID of parent conversation
22
+ * @property {string} messageId - ID of parent message
23
+ * @property {ToolExecution} execution - Execution details
24
+ * @property {ToolMetadata} metadata - Command metadata
25
+ * @property {string} createdAt - ISO timestamp of creation
26
+ * @property {string} [startedAt] - ISO timestamp when execution started
27
+ * @property {string} [completedAt] - ISO timestamp when execution completed
28
+ * @property {number} priority - Command priority (1-5)
29
+ * @property {number} timeout - Timeout in milliseconds
30
+ * @property {number} retryCount - Number of retry attempts
31
+ * @property {number} maxRetries - Maximum retry attempts allowed
32
+ */
33
+
34
+ /**
35
+ * Tool Execution details
36
+ * @typedef {Object} ToolExecution
37
+ * @property {string} executionId - Unique execution identifier
38
+ * @property {Object} input - Input parameters provided to tool
39
+ * @property {Object} [output] - Tool execution output
40
+ * @property {string} [error] - Error message if execution failed
41
+ * @property {string} [errorCode] - Error code for programmatic handling
42
+ * @property {number} executionTime - Time taken for execution (ms)
43
+ * @property {number} memoryUsage - Memory usage during execution (bytes)
44
+ * @property {number} cpuUsage - CPU usage percentage
45
+ * @property {Object} metrics - Execution metrics and performance data
46
+ * @property {ExecutionLog[]} logs - Execution logs and output
47
+ * @property {Object} environment - Execution environment information
48
+ * @property {string} [workingDirectory] - Working directory for execution
49
+ * @property {Object} [environmentVariables] - Environment variables used
50
+ */
51
+
52
+ /**
53
+ * Tool Metadata
54
+ * @typedef {Object} ToolMetadata
55
+ * @property {string} toolVersion - Version of the tool used
56
+ * @property {string[]} capabilities - Tool capabilities used
57
+ * @property {Object} configuration - Tool-specific configuration
58
+ * @property {boolean} requiresAuth - Whether tool requires authentication
59
+ * @property {string[]} dependencies - Tool dependencies
60
+ * @property {Object} constraints - Execution constraints
61
+ * @property {string[]} tags - Metadata tags
62
+ * @property {Object} customFields - Custom metadata fields
63
+ */
64
+
65
+ /**
66
+ * Execution Log entry
67
+ * @typedef {Object} ExecutionLog
68
+ * @property {string} id - Log entry identifier
69
+ * @property {string} level - Log level (debug, info, warn, error)
70
+ * @property {string} message - Log message
71
+ * @property {string} timestamp - ISO timestamp
72
+ * @property {Object} [data] - Additional log data
73
+ * @property {string} [source] - Log source component
74
+ */
75
+
76
+ /**
77
+ * Tool Definition
78
+ * @typedef {Object} ToolDefinition
79
+ * @property {string} id - Tool identifier
80
+ * @property {string} name - Human-readable tool name
81
+ * @property {string} description - Tool description
82
+ * @property {string} version - Tool version
83
+ * @property {ToolCapability[]} capabilities - Tool capabilities
84
+ * @property {ParameterSchema} parameterSchema - Parameter validation schema
85
+ * @property {Object} configuration - Default configuration
86
+ * @property {string[]} requiredPermissions - Required permissions
87
+ * @property {Object} constraints - Tool constraints and limits
88
+ * @property {boolean} isAsync - Whether tool executes asynchronously
89
+ * @property {number} defaultTimeout - Default timeout in milliseconds
90
+ */
91
+
92
+ /**
93
+ * Tool Capability
94
+ * @typedef {Object} ToolCapability
95
+ * @property {string} id - Capability identifier
96
+ * @property {string} name - Capability name
97
+ * @property {string} description - Capability description
98
+ * @property {string[]} commands - Supported commands
99
+ * @property {Object} parameters - Capability-specific parameters
100
+ * @property {Object} constraints - Capability constraints
101
+ */
102
+
103
+ /**
104
+ * Parameter Schema
105
+ * @typedef {Object} ParameterSchema
106
+ * @property {Object} properties - Parameter definitions
107
+ * @property {string[]} required - Required parameter names
108
+ * @property {Object} additionalProperties - Additional property settings
109
+ * @property {Object} examples - Example parameter sets
110
+ */
111
+
112
+ /**
113
+ * Tool Command validation functions
114
+ */
115
+ export class ToolCommandValidator {
116
+ /**
117
+ * Validate tool command data structure
118
+ * @param {Object} command - Tool command to validate
119
+ * @returns {Object} Validation result
120
+ */
121
+ static validate(command) {
122
+ const errors = [];
123
+ const warnings = [];
124
+
125
+ // Required fields
126
+ if (!command.id || typeof command.id !== 'string') {
127
+ errors.push('Command ID is required and must be a string');
128
+ }
129
+
130
+ if (!command.toolId || typeof command.toolId !== 'string') {
131
+ errors.push('Tool ID is required and must be a string');
132
+ }
133
+
134
+ if (!command.command || typeof command.command !== 'string') {
135
+ errors.push('Command is required and must be a string');
136
+ }
137
+
138
+ if (!command.agentId || typeof command.agentId !== 'string') {
139
+ errors.push('Agent ID is required and must be a string');
140
+ }
141
+
142
+ // Tool ID validation
143
+ if (command.toolId && !Object.values(TOOL_NAMES).includes(command.toolId) && !command.toolId.startsWith('custom_')) {
144
+ warnings.push(`Unknown tool ID: ${command.toolId}`);
145
+ }
146
+
147
+ // Status validation
148
+ if (command.status && !Object.values(TOOL_STATUS).includes(command.status)) {
149
+ errors.push(`Invalid tool status: ${command.status}`);
150
+ }
151
+
152
+ // Parameters validation
153
+ if (command.parameters && typeof command.parameters !== 'object') {
154
+ errors.push('Parameters must be an object');
155
+ }
156
+
157
+ // Priority validation
158
+ if (command.priority !== undefined) {
159
+ if (typeof command.priority !== 'number' || command.priority < 1 || command.priority > 5) {
160
+ errors.push('Priority must be a number between 1 and 5');
161
+ }
162
+ }
163
+
164
+ // Timeout validation
165
+ if (command.timeout !== undefined) {
166
+ if (typeof command.timeout !== 'number' || command.timeout < 0) {
167
+ errors.push('Timeout must be a non-negative number');
168
+ }
169
+
170
+ if (command.timeout > 3600000) { // 1 hour
171
+ warnings.push('Timeout is very long (>1 hour)');
172
+ }
173
+ }
174
+
175
+ // Retry validation
176
+ if (command.retryCount !== undefined && typeof command.retryCount !== 'number') {
177
+ errors.push('Retry count must be a number');
178
+ }
179
+
180
+ if (command.maxRetries !== undefined && typeof command.maxRetries !== 'number') {
181
+ errors.push('Max retries must be a number');
182
+ }
183
+
184
+ if (command.retryCount && command.maxRetries && command.retryCount > command.maxRetries) {
185
+ warnings.push('Retry count exceeds max retries');
186
+ }
187
+
188
+ // Execution validation
189
+ if (command.execution) {
190
+ const executionValidation = this.validateExecution(command.execution);
191
+ errors.push(...executionValidation.errors);
192
+ warnings.push(...executionValidation.warnings);
193
+ }
194
+
195
+ // Timestamp validation
196
+ const timestampFields = ['createdAt', 'startedAt', 'completedAt'];
197
+ timestampFields.forEach(field => {
198
+ if (command[field] && !this.isValidTimestamp(command[field])) {
199
+ errors.push(`Invalid timestamp for ${field}: ${command[field]}`);
200
+ }
201
+ });
202
+
203
+ return {
204
+ isValid: errors.length === 0,
205
+ errors,
206
+ warnings
207
+ };
208
+ }
209
+
210
+ /**
211
+ * Validate tool execution data
212
+ * @param {Object} execution - Execution data to validate
213
+ * @returns {Object} Validation result
214
+ */
215
+ static validateExecution(execution) {
216
+ const errors = [];
217
+ const warnings = [];
218
+
219
+ if (!execution.executionId || typeof execution.executionId !== 'string') {
220
+ errors.push('Execution ID is required and must be a string');
221
+ }
222
+
223
+ if (!execution.input || typeof execution.input !== 'object') {
224
+ errors.push('Execution input is required and must be an object');
225
+ }
226
+
227
+ if (execution.executionTime !== undefined) {
228
+ if (typeof execution.executionTime !== 'number' || execution.executionTime < 0) {
229
+ errors.push('Execution time must be a non-negative number');
230
+ }
231
+ }
232
+
233
+ if (execution.memoryUsage !== undefined) {
234
+ if (typeof execution.memoryUsage !== 'number' || execution.memoryUsage < 0) {
235
+ errors.push('Memory usage must be a non-negative number');
236
+ }
237
+ }
238
+
239
+ if (execution.cpuUsage !== undefined) {
240
+ if (typeof execution.cpuUsage !== 'number' || execution.cpuUsage < 0 || execution.cpuUsage > 100) {
241
+ errors.push('CPU usage must be a number between 0 and 100');
242
+ }
243
+ }
244
+
245
+ if (execution.logs && !Array.isArray(execution.logs)) {
246
+ errors.push('Execution logs must be an array');
247
+ }
248
+
249
+ if (execution.logs) {
250
+ execution.logs.forEach((log, index) => {
251
+ if (!log.level || !log.message || !log.timestamp) {
252
+ errors.push(`Log entry ${index} missing required fields`);
253
+ }
254
+ });
255
+ }
256
+
257
+ return { errors, warnings };
258
+ }
259
+
260
+ /**
261
+ * Validate tool definition
262
+ * @param {Object} toolDef - Tool definition to validate
263
+ * @returns {Object} Validation result
264
+ */
265
+ static validateToolDefinition(toolDef) {
266
+ const errors = [];
267
+ const warnings = [];
268
+
269
+ // Required fields
270
+ if (!toolDef.id || typeof toolDef.id !== 'string') {
271
+ errors.push('Tool ID is required and must be a string');
272
+ }
273
+
274
+ if (!toolDef.name || typeof toolDef.name !== 'string') {
275
+ errors.push('Tool name is required and must be a string');
276
+ }
277
+
278
+ if (!toolDef.description || typeof toolDef.description !== 'string') {
279
+ errors.push('Tool description is required and must be a string');
280
+ }
281
+
282
+ if (!toolDef.version || typeof toolDef.version !== 'string') {
283
+ errors.push('Tool version is required and must be a string');
284
+ }
285
+
286
+ // Capabilities validation
287
+ if (!toolDef.capabilities || !Array.isArray(toolDef.capabilities)) {
288
+ errors.push('Tool capabilities are required and must be an array');
289
+ }
290
+
291
+ if (toolDef.capabilities && toolDef.capabilities.length === 0) {
292
+ warnings.push('Tool has no capabilities defined');
293
+ }
294
+
295
+ // Parameter schema validation
296
+ if (toolDef.parameterSchema && typeof toolDef.parameterSchema !== 'object') {
297
+ errors.push('Parameter schema must be an object');
298
+ }
299
+
300
+ // Timeout validation
301
+ if (toolDef.defaultTimeout !== undefined) {
302
+ if (typeof toolDef.defaultTimeout !== 'number' || toolDef.defaultTimeout <= 0) {
303
+ errors.push('Default timeout must be a positive number');
304
+ }
305
+ }
306
+
307
+ return { errors, warnings };
308
+ }
309
+
310
+ /**
311
+ * Validate command parameters against tool definition
312
+ * @param {Object} parameters - Parameters to validate
313
+ * @param {ParameterSchema} schema - Parameter schema
314
+ * @returns {Object} Validation result
315
+ */
316
+ static validateParameters(parameters, schema) {
317
+ const errors = [];
318
+ const warnings = [];
319
+
320
+ if (!schema || !schema.properties) {
321
+ return { errors: [], warnings: ['No parameter schema provided'] };
322
+ }
323
+
324
+ // Check required parameters
325
+ if (schema.required) {
326
+ schema.required.forEach(paramName => {
327
+ if (!(paramName in parameters)) {
328
+ errors.push(`Required parameter missing: ${paramName}`);
329
+ }
330
+ });
331
+ }
332
+
333
+ // Validate parameter types and constraints
334
+ Object.entries(parameters).forEach(([paramName, paramValue]) => {
335
+ const paramDef = schema.properties[paramName];
336
+
337
+ if (!paramDef) {
338
+ if (!schema.additionalProperties) {
339
+ warnings.push(`Unknown parameter: ${paramName}`);
340
+ }
341
+ return;
342
+ }
343
+
344
+ // Type validation
345
+ if (paramDef.type) {
346
+ const actualType = Array.isArray(paramValue) ? 'array' : typeof paramValue;
347
+ if (actualType !== paramDef.type) {
348
+ errors.push(`Parameter ${paramName} must be of type ${paramDef.type}, got ${actualType}`);
349
+ }
350
+ }
351
+
352
+ // Range validation for numbers
353
+ if (paramDef.type === 'number') {
354
+ if (paramDef.minimum !== undefined && paramValue < paramDef.minimum) {
355
+ errors.push(`Parameter ${paramName} must be >= ${paramDef.minimum}`);
356
+ }
357
+ if (paramDef.maximum !== undefined && paramValue > paramDef.maximum) {
358
+ errors.push(`Parameter ${paramName} must be <= ${paramDef.maximum}`);
359
+ }
360
+ }
361
+
362
+ // Length validation for strings
363
+ if (paramDef.type === 'string') {
364
+ if (paramDef.minLength !== undefined && paramValue.length < paramDef.minLength) {
365
+ errors.push(`Parameter ${paramName} must be at least ${paramDef.minLength} characters`);
366
+ }
367
+ if (paramDef.maxLength !== undefined && paramValue.length > paramDef.maxLength) {
368
+ errors.push(`Parameter ${paramName} must be at most ${paramDef.maxLength} characters`);
369
+ }
370
+ }
371
+
372
+ // Enum validation
373
+ if (paramDef.enum && !paramDef.enum.includes(paramValue)) {
374
+ errors.push(`Parameter ${paramName} must be one of: ${paramDef.enum.join(', ')}`);
375
+ }
376
+ });
377
+
378
+ return { errors, warnings };
379
+ }
380
+
381
+ /**
382
+ * Check if a timestamp is valid ISO string
383
+ * @param {string} timestamp - Timestamp to validate
384
+ * @returns {boolean} True if valid
385
+ */
386
+ static isValidTimestamp(timestamp) {
387
+ if (typeof timestamp !== 'string') return false;
388
+ const date = new Date(timestamp);
389
+ return date instanceof Date && !isNaN(date.getTime());
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Tool Command factory functions
395
+ */
396
+ export class ToolCommandFactory {
397
+ /**
398
+ * Create a new tool command
399
+ * @param {string} toolId - Tool identifier
400
+ * @param {string} command - Command to execute
401
+ * @param {Object} parameters - Command parameters
402
+ * @param {Object} options - Additional options
403
+ * @returns {ToolCommand} New tool command object
404
+ */
405
+ static create(toolId, command, parameters, options = {}) {
406
+ const now = new Date().toISOString();
407
+ const commandId = this.generateCommandId();
408
+ const executionId = this.generateExecutionId();
409
+
410
+ return {
411
+ id: commandId,
412
+ toolId,
413
+ command,
414
+ parameters: parameters || {},
415
+ status: TOOL_STATUS.PENDING,
416
+ agentId: options.agentId || '',
417
+ conversationId: options.conversationId || '',
418
+ messageId: options.messageId || '',
419
+ execution: {
420
+ executionId,
421
+ input: { command, parameters },
422
+ output: null,
423
+ error: null,
424
+ errorCode: null,
425
+ executionTime: 0,
426
+ memoryUsage: 0,
427
+ cpuUsage: 0,
428
+ metrics: {},
429
+ logs: [],
430
+ environment: options.environment || {},
431
+ workingDirectory: options.workingDirectory || null,
432
+ environmentVariables: options.environmentVariables || {}
433
+ },
434
+ metadata: this.createDefaultMetadata(options.metadata),
435
+ createdAt: now,
436
+ startedAt: null,
437
+ completedAt: null,
438
+ priority: options.priority || 3,
439
+ timeout: options.timeout || 30000,
440
+ retryCount: 0,
441
+ maxRetries: options.maxRetries || 3
442
+ };
443
+ }
444
+
445
+ /**
446
+ * Create execution log entry
447
+ * @param {string} level - Log level
448
+ * @param {string} message - Log message
449
+ * @param {Object} data - Additional log data
450
+ * @returns {ExecutionLog} Log entry
451
+ */
452
+ static createLogEntry(level, message, data = null) {
453
+ return {
454
+ id: this.generateLogId(),
455
+ level,
456
+ message,
457
+ timestamp: new Date().toISOString(),
458
+ data,
459
+ source: 'tool-execution'
460
+ };
461
+ }
462
+
463
+ /**
464
+ * Create default tool metadata
465
+ * @param {Object} overrides - Metadata overrides
466
+ * @returns {ToolMetadata} Default metadata
467
+ */
468
+ static createDefaultMetadata(overrides = {}) {
469
+ return {
470
+ toolVersion: '1.0.0',
471
+ capabilities: [],
472
+ configuration: {},
473
+ requiresAuth: false,
474
+ dependencies: [],
475
+ constraints: {},
476
+ tags: [],
477
+ customFields: {},
478
+ ...overrides
479
+ };
480
+ }
481
+
482
+ /**
483
+ * Generate unique command ID
484
+ * @returns {string} Unique command ID
485
+ */
486
+ static generateCommandId() {
487
+ const timestamp = Date.now().toString(36);
488
+ const random = Math.random().toString(36).substr(2, 9);
489
+ return `cmd_${timestamp}_${random}`;
490
+ }
491
+
492
+ /**
493
+ * Generate unique execution ID
494
+ * @returns {string} Unique execution ID
495
+ */
496
+ static generateExecutionId() {
497
+ const timestamp = Date.now().toString(36);
498
+ const random = Math.random().toString(36).substr(2, 9);
499
+ return `exec_${timestamp}_${random}`;
500
+ }
501
+
502
+ /**
503
+ * Generate unique log ID
504
+ * @returns {string} Unique log ID
505
+ */
506
+ static generateLogId() {
507
+ const timestamp = Date.now().toString(36);
508
+ const random = Math.random().toString(36).substr(2, 6);
509
+ return `log_${timestamp}_${random}`;
510
+ }
511
+ }
512
+
513
+ /**
514
+ * Tool Command utility functions
515
+ */
516
+ export class ToolCommandUtils {
517
+ /**
518
+ * Check if command is still pending
519
+ * @param {ToolCommand} command - Command to check
520
+ * @returns {boolean} True if pending
521
+ */
522
+ static isPending(command) {
523
+ return command.status === TOOL_STATUS.PENDING;
524
+ }
525
+
526
+ /**
527
+ * Check if command is currently executing
528
+ * @param {ToolCommand} command - Command to check
529
+ * @returns {boolean} True if executing
530
+ */
531
+ static isExecuting(command) {
532
+ return command.status === TOOL_STATUS.EXECUTING;
533
+ }
534
+
535
+ /**
536
+ * Check if command has completed successfully
537
+ * @param {ToolCommand} command - Command to check
538
+ * @returns {boolean} True if completed
539
+ */
540
+ static isCompleted(command) {
541
+ return command.status === TOOL_STATUS.COMPLETED;
542
+ }
543
+
544
+ /**
545
+ * Check if command has failed
546
+ * @param {ToolCommand} command - Command to check
547
+ * @returns {boolean} True if failed
548
+ */
549
+ static isFailed(command) {
550
+ return command.status === TOOL_STATUS.FAILED;
551
+ }
552
+
553
+ /**
554
+ * Check if command has timed out
555
+ * @param {ToolCommand} command - Command to check
556
+ * @returns {boolean} True if timed out
557
+ */
558
+ static isTimedOut(command) {
559
+ if (!command.startedAt || command.status !== TOOL_STATUS.EXECUTING) {
560
+ return false;
561
+ }
562
+
563
+ const startTime = new Date(command.startedAt);
564
+ const now = new Date();
565
+ const elapsed = now.getTime() - startTime.getTime();
566
+
567
+ return elapsed > command.timeout;
568
+ }
569
+
570
+ /**
571
+ * Calculate command execution time
572
+ * @param {ToolCommand} command - Command to analyze
573
+ * @returns {number|null} Execution time in milliseconds, null if not applicable
574
+ */
575
+ static getExecutionTime(command) {
576
+ if (!command.startedAt) return null;
577
+
578
+ const endTime = command.completedAt ? new Date(command.completedAt) : new Date();
579
+ const startTime = new Date(command.startedAt);
580
+
581
+ return endTime.getTime() - startTime.getTime();
582
+ }
583
+
584
+ /**
585
+ * Get command progress information
586
+ * @param {ToolCommand} command - Command to analyze
587
+ * @returns {Object} Progress information
588
+ */
589
+ static getProgress(command) {
590
+ const executionTime = this.getExecutionTime(command);
591
+ const isTimedOut = this.isTimedOut(command);
592
+
593
+ let progressPercentage = 0;
594
+ if (command.status === TOOL_STATUS.COMPLETED) {
595
+ progressPercentage = 100;
596
+ } else if (command.status === TOOL_STATUS.EXECUTING && executionTime) {
597
+ // Estimate progress based on execution time vs timeout
598
+ progressPercentage = Math.min(95, (executionTime / command.timeout) * 100);
599
+ }
600
+
601
+ return {
602
+ status: command.status,
603
+ percentage: Math.round(progressPercentage),
604
+ executionTime,
605
+ isTimedOut,
606
+ remainingTime: command.status === TOOL_STATUS.EXECUTING && executionTime
607
+ ? Math.max(0, command.timeout - executionTime)
608
+ : null
609
+ };
610
+ }
611
+
612
+ /**
613
+ * Extract key metrics from command execution
614
+ * @param {ToolCommand} command - Command to analyze
615
+ * @returns {Object} Execution metrics
616
+ */
617
+ static getMetrics(command) {
618
+ const execution = command.execution || {};
619
+ const progress = this.getProgress(command);
620
+
621
+ return {
622
+ executionTime: execution.executionTime || progress.executionTime || 0,
623
+ memoryUsage: execution.memoryUsage || 0,
624
+ cpuUsage: execution.cpuUsage || 0,
625
+ status: command.status,
626
+ retryCount: command.retryCount,
627
+ priority: command.priority,
628
+ logEntries: execution.logs ? execution.logs.length : 0,
629
+ hasError: !!execution.error,
630
+ errorCode: execution.errorCode || null
631
+ };
632
+ }
633
+
634
+ /**
635
+ * Format command for display
636
+ * @param {ToolCommand} command - Command to format
637
+ * @returns {Object} Formatted command data
638
+ */
639
+ static formatForDisplay(command) {
640
+ const progress = this.getProgress(command);
641
+ const metrics = this.getMetrics(command);
642
+
643
+ return {
644
+ id: command.id,
645
+ toolId: command.toolId,
646
+ command: command.command,
647
+ status: command.status,
648
+ progress: progress.percentage,
649
+ executionTime: metrics.executionTime,
650
+ createdAt: command.createdAt,
651
+ startedAt: command.startedAt,
652
+ completedAt: command.completedAt,
653
+ hasError: metrics.hasError,
654
+ retryCount: command.retryCount
655
+ };
656
+ }
657
+
658
+ /**
659
+ * Sanitize command for API responses
660
+ * @param {ToolCommand} command - Command to sanitize
661
+ * @returns {Object} Sanitized command data
662
+ */
663
+ static sanitize(command) {
664
+ const sanitized = { ...command };
665
+
666
+ // Remove sensitive execution data
667
+ if (sanitized.execution) {
668
+ delete sanitized.execution.environmentVariables;
669
+ delete sanitized.execution.environment;
670
+
671
+ // Truncate long logs
672
+ if (sanitized.execution.logs && sanitized.execution.logs.length > 10) {
673
+ sanitized.execution.logs = sanitized.execution.logs.slice(-10);
674
+ }
675
+ }
676
+
677
+ // Remove sensitive parameters
678
+ if (sanitized.parameters) {
679
+ const sensitiveKeys = ['password', 'token', 'secret', 'key', 'auth'];
680
+ Object.keys(sanitized.parameters).forEach(key => {
681
+ if (sensitiveKeys.some(sensitive => key.toLowerCase().includes(sensitive))) {
682
+ sanitized.parameters[key] = '[REDACTED]';
683
+ }
684
+ });
685
+ }
686
+
687
+ return sanitized;
688
+ }
689
+
690
+ /**
691
+ * Create command summary for reporting
692
+ * @param {ToolCommand[]} commands - Commands to summarize
693
+ * @returns {Object} Command summary
694
+ */
695
+ static summarizeCommands(commands) {
696
+ const summary = {
697
+ total: commands.length,
698
+ byStatus: {},
699
+ byTool: {},
700
+ totalExecutionTime: 0,
701
+ averageExecutionTime: 0,
702
+ successRate: 0,
703
+ mostUsedTools: [],
704
+ recentCommands: []
705
+ };
706
+
707
+ // Count by status
708
+ Object.values(TOOL_STATUS).forEach(status => {
709
+ summary.byStatus[status] = commands.filter(cmd => cmd.status === status).length;
710
+ });
711
+
712
+ // Count by tool
713
+ commands.forEach(command => {
714
+ summary.byTool[command.toolId] = (summary.byTool[command.toolId] || 0) + 1;
715
+
716
+ const executionTime = this.getExecutionTime(command) || 0;
717
+ summary.totalExecutionTime += executionTime;
718
+ });
719
+
720
+ // Calculate averages and rates
721
+ if (commands.length > 0) {
722
+ summary.averageExecutionTime = summary.totalExecutionTime / commands.length;
723
+ const successfulCommands = summary.byStatus[TOOL_STATUS.COMPLETED] || 0;
724
+ summary.successRate = (successfulCommands / commands.length) * 100;
725
+ }
726
+
727
+ // Most used tools
728
+ summary.mostUsedTools = Object.entries(summary.byTool)
729
+ .sort((a, b) => b[1] - a[1])
730
+ .slice(0, 5)
731
+ .map(([toolId, count]) => ({ toolId, count }));
732
+
733
+ // Recent commands
734
+ summary.recentCommands = commands
735
+ .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
736
+ .slice(0, 10)
737
+ .map(cmd => this.formatForDisplay(cmd));
738
+
739
+ return summary;
740
+ }
741
+ }
742
+
743
+ export default {
744
+ ToolCommandValidator,
745
+ ToolCommandFactory,
746
+ ToolCommandUtils
747
+ };