erosolar-cli 2.1.285 → 2.1.287

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.
@@ -15,7 +15,7 @@
15
15
  * - Analysis: Code quality, performance, patterns
16
16
  * - Git: Status, commits, branches, diffs
17
17
  */
18
- import { execSync, spawn } from 'child_process';
18
+ import { spawn } from 'child_process';
19
19
  import { EventEmitter } from 'node:events';
20
20
  import * as fs from 'fs';
21
21
  import * as path from 'path';
@@ -96,15 +96,16 @@ export class UnifiedOrchestrator extends EventEmitter {
96
96
  /**
97
97
  * Execute a shell command with Claude Code-style event emission.
98
98
  * Events are emitted in the tool lifecycle pattern:
99
- * - tool:start -> tool:progress (optional) -> tool:complete/tool:error
99
+ * - tool:start -> tool:progress (streamed) -> tool:complete/tool:error
100
+ *
101
+ * Streaming keeps the UI responsive instead of blocking on execSync.
100
102
  */
101
- exec(command, timeout = 60000) {
103
+ async exec(command, timeout = 60000) {
102
104
  const start = Date.now();
103
105
  this.commandIndex++;
104
106
  const toolId = `exec-${this.commandIndex}-${Date.now()}`;
105
107
  const toolName = this.inferToolName(command);
106
108
  const description = this.describeCommand(command);
107
- // Emit Claude Code-style tool:start event
108
109
  this.emitOrchestratorEvent('tool:start', {
109
110
  toolId,
110
111
  toolName,
@@ -112,63 +113,84 @@ export class UnifiedOrchestrator extends EventEmitter {
112
113
  index: this.commandIndex,
113
114
  args: { command },
114
115
  });
115
- // Legacy event for backward compatibility
116
116
  this.emitOrchestratorEvent('command:start', {
117
117
  command,
118
118
  index: this.commandIndex,
119
119
  total: undefined,
120
120
  });
121
- try {
122
- const output = execSync(command, {
121
+ return await new Promise((resolve) => {
122
+ let outputBuffer = '';
123
+ let resolved = false;
124
+ const complete = (success, exitCode, errorMessage) => {
125
+ if (resolved)
126
+ return;
127
+ resolved = true;
128
+ cleanup();
129
+ const duration = Date.now() - start;
130
+ const combinedOutput = outputBuffer || (errorMessage ?? '');
131
+ const result = {
132
+ success,
133
+ output: combinedOutput,
134
+ error: errorMessage,
135
+ duration,
136
+ command,
137
+ exitCode: exitCode ?? undefined,
138
+ };
139
+ this.results.push(result);
140
+ const completeEvent = {
141
+ toolId,
142
+ toolName,
143
+ success,
144
+ output: this.truncateOutput(combinedOutput),
145
+ duration,
146
+ exitCode: exitCode ?? undefined,
147
+ };
148
+ this.emitOrchestratorEvent(success ? 'tool:complete' : 'tool:error', completeEvent);
149
+ this.emitOrchestratorEvent(success ? 'command:complete' : 'command:error', {
150
+ command,
151
+ result,
152
+ duration,
153
+ });
154
+ resolve(result);
155
+ };
156
+ const child = spawn(command, {
123
157
  cwd: this.workingDir,
124
- encoding: 'utf-8',
125
- timeout,
126
- maxBuffer: 50 * 1024 * 1024,
127
- stdio: ['pipe', 'pipe', 'pipe'],
128
- });
129
- const duration = Date.now() - start;
130
- const result = { success: true, output: output || '', duration, command, exitCode: 0 };
131
- this.results.push(result);
132
- // Emit Claude Code-style tool:complete event
133
- this.emitOrchestratorEvent('tool:complete', {
134
- toolId,
135
- toolName,
136
- success: true,
137
- output: this.truncateOutput(output || ''),
138
- duration,
139
- exitCode: 0,
158
+ shell: true,
159
+ env: process.env,
140
160
  });
141
- // Legacy event
142
- this.emitOrchestratorEvent('command:complete', {
143
- command,
144
- result,
145
- duration,
146
- });
147
- return result;
148
- }
149
- catch (e) {
150
- const err = e;
151
- const output = (err.stdout || err.stderr || err.message || '');
152
- const duration = Date.now() - start;
153
- const result = { success: false, output, error: err.message, duration, command, exitCode: err.status };
154
- this.results.push(result);
155
- // Emit Claude Code-style tool:error event
156
- this.emitOrchestratorEvent('tool:error', {
157
- toolId,
158
- toolName,
159
- success: false,
160
- output: this.truncateOutput(output),
161
- duration,
162
- exitCode: err.status,
161
+ let timer = null;
162
+ const handleData = (data) => {
163
+ const text = data.toString();
164
+ outputBuffer += text;
165
+ this.emitOrchestratorEvent('tool:progress', {
166
+ toolId,
167
+ toolName,
168
+ output: this.truncateOutput(text, 200),
169
+ });
170
+ };
171
+ child.stdout?.on('data', handleData);
172
+ child.stderr?.on('data', handleData);
173
+ const cleanup = () => {
174
+ if (timer) {
175
+ clearTimeout(timer);
176
+ timer = null;
177
+ }
178
+ child.stdout?.off('data', handleData);
179
+ child.stderr?.off('data', handleData);
180
+ };
181
+ timer = setTimeout(() => {
182
+ child.kill('SIGKILL');
183
+ complete(false, child.exitCode, `Timeout after ${timeout}ms`);
184
+ }, timeout);
185
+ child.on('error', (error) => {
186
+ complete(false, child.exitCode, error.message);
163
187
  });
164
- // Legacy event
165
- this.emitOrchestratorEvent('command:error', {
166
- command,
167
- result,
168
- duration,
188
+ child.on('close', (code, signal) => {
189
+ const success = code === 0;
190
+ const message = success ? undefined : signal ? `Exited with signal ${signal}` : `Exited with code ${code ?? -1}`;
191
+ complete(success, code, message);
169
192
  });
170
- return result;
171
- }
193
+ });
172
194
  }
173
195
  /** Infer a tool name from the command for Claude Code-style display */
174
196
  inferToolName(command) {
@@ -258,12 +280,16 @@ export class UnifiedOrchestrator extends EventEmitter {
258
280
  return output.slice(0, maxLength - 3) + '...';
259
281
  }
260
282
  /** Execute multiple commands sequentially */
261
- execMany(commands, timeout) {
262
- return commands.map(cmd => this.exec(cmd, timeout));
283
+ async execMany(commands, timeout) {
284
+ const results = [];
285
+ for (const cmd of commands) {
286
+ results.push(await this.exec(cmd, timeout));
287
+ }
288
+ return results;
263
289
  }
264
290
  /** Execute multiple commands in parallel */
265
291
  async execParallel(commands, timeout) {
266
- return Promise.all(commands.map(cmd => Promise.resolve(this.exec(cmd, timeout))));
292
+ return Promise.all(commands.map(cmd => this.exec(cmd, timeout)));
267
293
  }
268
294
  /** Start a background process */
269
295
  execBackground(command, id) {
@@ -325,13 +351,13 @@ export class UnifiedOrchestrator extends EventEmitter {
325
351
  return this.exec('rm -rf node_modules dist .tsbuildinfo .eslintcache coverage 2>&1; echo "Cleaned"', 30000);
326
352
  }
327
353
  /** Run full CI pipeline */
328
- ci() {
329
- return [
330
- this.lint(),
331
- this.typecheck(),
332
- this.test(),
333
- this.build(),
334
- ];
354
+ async ci() {
355
+ const results = [];
356
+ results.push(await this.lint());
357
+ results.push(await this.typecheck());
358
+ results.push(await this.test());
359
+ results.push(await this.build());
360
+ return results;
335
361
  }
336
362
  // ==========================================================================
337
363
  // SECURITY TOOLS
@@ -527,39 +553,39 @@ export class UnifiedOrchestrator extends EventEmitter {
527
553
  ]);
528
554
  }
529
555
  /** Full offensive assessment */
530
- fullOffensive(target) {
556
+ async fullOffensive(target) {
531
557
  const results = [];
532
- results.push(...this.enumerate());
533
- results.push(...this.networkMap());
534
- results.push(...this.privescCheck());
535
- results.push(...this.credentialHunt());
536
- results.push(...this.persistenceCheck());
558
+ results.push(...await this.enumerate());
559
+ results.push(...await this.networkMap());
560
+ results.push(...await this.privescCheck());
561
+ results.push(...await this.credentialHunt());
562
+ results.push(...await this.persistenceCheck());
537
563
  if (os.platform() === 'darwin') {
538
- results.push(...this.macosOffensive());
564
+ results.push(...await this.macosOffensive());
539
565
  }
540
566
  if (target) {
541
- results.push(...this.targetRecon(target));
542
- results.push(...this.serviceDetect(target));
567
+ results.push(...await this.targetRecon(target));
568
+ results.push(...await this.serviceDetect(target));
543
569
  }
544
570
  return results;
545
571
  }
546
572
  /** Attack chain execution */
547
- attackChain(target, depth = 'medium') {
573
+ async attackChain(target, depth = 'medium') {
548
574
  const results = [];
549
575
  // Phase 1: Recon
550
- results.push(...this.targetRecon(target));
576
+ results.push(...await this.targetRecon(target));
551
577
  // Phase 2: Enumeration
552
- results.push(...this.subdomainEnum(target));
578
+ results.push(...await this.subdomainEnum(target));
553
579
  if (depth !== 'light') {
554
580
  // Phase 3: Service detection
555
- results.push(...this.serviceDetect(target));
556
- results.push(...this.sslAnalyze(target));
581
+ results.push(...await this.serviceDetect(target));
582
+ results.push(...await this.sslAnalyze(target));
557
583
  }
558
584
  if (depth === 'deep') {
559
585
  // Phase 4: Deep analysis
560
- results.push(...this.webFingerprint(`https://${target}`));
561
- results.push(...this.pathEnum(`https://${target}`));
562
- results.push(...this.cloudDetect(target));
586
+ results.push(...await this.webFingerprint(`https://${target}`));
587
+ results.push(...await this.pathEnum(`https://${target}`));
588
+ results.push(...await this.cloudDetect(target));
563
589
  }
564
590
  return results;
565
591
  }
@@ -702,10 +728,10 @@ export class UnifiedOrchestrator extends EventEmitter {
702
728
  return fs.existsSync(fullPath);
703
729
  }
704
730
  /** List directory */
705
- listDir(dirPath = '.', recursive = false) {
731
+ async listDir(dirPath = '.', recursive = false) {
706
732
  const fullPath = path.isAbsolute(dirPath) ? dirPath : path.join(this.workingDir, dirPath);
707
733
  if (recursive) {
708
- const result = this.exec(`find "${fullPath}" -type f 2>/dev/null | head -100`);
734
+ const result = await this.exec(`find "${fullPath}" -type f 2>/dev/null | head -100`);
709
735
  return result.output.split('\n').filter(Boolean);
710
736
  }
711
737
  return fs.readdirSync(fullPath);
@@ -984,63 +1010,63 @@ export class UnifiedOrchestrator extends EventEmitter {
984
1010
  this.setPhase('executing');
985
1011
  // Analyze objective and execute appropriate tools
986
1012
  if (this.matchesIntent(objective, ['build', 'compile', 'typescript', 'tsc'])) {
987
- this.typecheck();
988
- this.build();
1013
+ await this.typecheck();
1014
+ await this.build();
989
1015
  }
990
1016
  if (this.matchesIntent(objective, ['test', 'spec', 'jest', 'mocha'])) {
991
- this.test();
1017
+ await this.test();
992
1018
  }
993
1019
  if (this.matchesIntent(objective, ['lint', 'eslint', 'format', 'prettier'])) {
994
- this.lint();
995
- this.format(true);
1020
+ await this.lint();
1021
+ await this.format(true);
996
1022
  }
997
1023
  if (this.matchesIntent(objective, ['security', 'audit', 'vulnerab', 'scan'])) {
998
- this.securityAudit();
999
- this.vulnerabilityScan();
1024
+ await this.securityAudit();
1025
+ await this.vulnerabilityScan();
1000
1026
  }
1001
1027
  if (this.matchesIntent(objective, ['attack', 'offensive', 'pentest', 'red team', 'recon'])) {
1002
1028
  if (target) {
1003
- this.targetRecon(target);
1004
- this.serviceDetect(target);
1005
- this.sslAnalyze(target);
1029
+ await this.targetRecon(target);
1030
+ await this.serviceDetect(target);
1031
+ await this.sslAnalyze(target);
1006
1032
  }
1007
- this.enumerate();
1008
- this.credentialHunt();
1009
- this.persistenceCheck();
1033
+ await this.enumerate();
1034
+ await this.credentialHunt();
1035
+ await this.persistenceCheck();
1010
1036
  }
1011
1037
  if (this.matchesIntent(objective, ['defense', 'blue team', 'harden', 'protect'])) {
1012
- this.defenseCheck();
1013
- this.securityAudit();
1014
- this.persistenceCheck();
1038
+ await this.defenseCheck();
1039
+ await this.securityAudit();
1040
+ await this.persistenceCheck();
1015
1041
  }
1016
1042
  if (this.matchesIntent(objective, ['investigate', 'forensic', 'analyze'])) {
1017
- this.investigateFiles();
1018
- this.investigateProcesses();
1019
- this.investigateNetwork();
1043
+ await this.investigateFiles();
1044
+ await this.investigateProcesses();
1045
+ await this.investigateNetwork();
1020
1046
  }
1021
1047
  if (this.matchesIntent(objective, ['bug', 'fix', 'error', 'issue', 'problem'])) {
1022
- this.typecheck();
1023
- this.lint();
1024
- this.analyzeQuality();
1025
- this.findDeadCode();
1048
+ await this.typecheck();
1049
+ await this.lint();
1050
+ await this.analyzeQuality();
1051
+ await this.findDeadCode();
1026
1052
  }
1027
1053
  if (this.matchesIntent(objective, ['ci', 'pipeline', 'full', 'complete', 'all'])) {
1028
- this.ci();
1029
- this.securityAudit();
1030
- this.analyzeQuality();
1054
+ await this.ci();
1055
+ await this.securityAudit();
1056
+ await this.analyzeQuality();
1031
1057
  }
1032
1058
  if (this.matchesIntent(objective, ['git', 'status', 'commit', 'branch'])) {
1033
- this.gitStatus();
1034
- this.gitLog(10);
1035
- this.gitDiff();
1059
+ await this.gitStatus();
1060
+ await this.gitLog(10);
1061
+ await this.gitDiff();
1036
1062
  }
1037
1063
  if (this.matchesIntent(objective, ['clean', 'remove', 'delete', 'clear'])) {
1038
- this.clean();
1064
+ await this.clean();
1039
1065
  }
1040
1066
  if (this.matchesIntent(objective, ['health', 'check', 'status'])) {
1041
- this.gitStatus();
1042
- this.typecheck();
1043
- this.deps('audit');
1067
+ await this.gitStatus();
1068
+ await this.typecheck();
1069
+ await this.deps('audit');
1044
1070
  }
1045
1071
  // Phase: Reporting - Analyze results and generate report
1046
1072
  this.setPhase('reporting');
@@ -1097,10 +1123,10 @@ export class UnifiedOrchestrator extends EventEmitter {
1097
1123
  // ==========================================================================
1098
1124
  // STATIC METHODS
1099
1125
  // ==========================================================================
1100
- static run(command, workingDir) {
1126
+ static async run(command, workingDir) {
1101
1127
  return new UnifiedOrchestrator(workingDir).exec(command);
1102
1128
  }
1103
- static runMany(commands, workingDir) {
1129
+ static async runMany(commands, workingDir) {
1104
1130
  return new UnifiedOrchestrator(workingDir).execMany(commands);
1105
1131
  }
1106
1132
  }
@@ -1153,80 +1179,80 @@ export const containerEnum = (dir) => new UnifiedOrchestrator(dir).containerEnum
1153
1179
  export const fullOffensive = (target, dir) => new UnifiedOrchestrator(dir).fullOffensive(target);
1154
1180
  export const attackChain = (target, depth, dir) => new UnifiedOrchestrator(dir).attackChain(target, depth);
1155
1181
  // Composite Operations - Full Pipelines
1156
- export const fullEngineering = (dir) => {
1182
+ export const fullEngineering = async (dir) => {
1157
1183
  const o = new UnifiedOrchestrator(dir);
1158
- o.exec('npm run clean 2>&1 || true');
1159
- o.deps('install');
1160
- o.ci();
1161
- o.analyzeQuality();
1184
+ await o.exec('npm run clean 2>&1 || true');
1185
+ await o.deps('install');
1186
+ await o.ci();
1187
+ await o.analyzeQuality();
1162
1188
  for (const r of o.getResults())
1163
1189
  o.analyze(r.output, 'engineering');
1164
1190
  return o.generateReport('Full Engineering');
1165
1191
  };
1166
- export const fullSecurity = (dir) => {
1192
+ export const fullSecurity = async (dir) => {
1167
1193
  const o = new UnifiedOrchestrator(dir);
1168
- o.securityAudit();
1169
- o.vulnerabilityScan();
1170
- o.defenseCheck();
1171
- o.persistenceCheck();
1194
+ await o.securityAudit();
1195
+ await o.vulnerabilityScan();
1196
+ await o.defenseCheck();
1197
+ await o.persistenceCheck();
1172
1198
  for (const r of o.getResults())
1173
1199
  o.analyze(r.output, 'security');
1174
1200
  return o.generateReport('Full Security');
1175
1201
  };
1176
- export const fullDefensive = (dir) => {
1202
+ export const fullDefensive = async (dir) => {
1177
1203
  const o = new UnifiedOrchestrator(dir);
1178
- o.defenseCheck();
1179
- o.persistenceCheck();
1180
- o.securityAudit();
1204
+ await o.defenseCheck();
1205
+ await o.persistenceCheck();
1206
+ await o.securityAudit();
1181
1207
  for (const r of o.getResults())
1182
1208
  o.analyze(r.output, 'defensive');
1183
1209
  return o.generateReport('Full Defensive');
1184
1210
  };
1185
- export const fullInvestigation = (dir) => {
1211
+ export const fullInvestigation = async (dir) => {
1186
1212
  const o = new UnifiedOrchestrator(dir);
1187
- o.investigateFiles();
1188
- o.investigateProcesses();
1189
- o.investigateNetwork();
1190
- o.investigateBrowser();
1191
- o.investigateEmail();
1192
- o.investigateIMessage();
1213
+ await o.investigateFiles();
1214
+ await o.investigateProcesses();
1215
+ await o.investigateNetwork();
1216
+ await o.investigateBrowser();
1217
+ await o.investigateEmail();
1218
+ await o.investigateIMessage();
1193
1219
  for (const r of o.getResults())
1194
1220
  o.analyze(r.output, 'investigation');
1195
1221
  return o.generateReport('Full Investigation');
1196
1222
  };
1197
- export const redTeam = (target, dir) => {
1223
+ export const redTeam = async (target, dir) => {
1198
1224
  const o = new UnifiedOrchestrator(dir);
1199
1225
  if (target)
1200
- o.targetRecon(target);
1201
- o.enumerate();
1202
- o.vulnerabilityScan();
1203
- o.persistenceCheck();
1204
- o.credentialHunt();
1205
- o.networkMap();
1226
+ await o.targetRecon(target);
1227
+ await o.enumerate();
1228
+ await o.vulnerabilityScan();
1229
+ await o.persistenceCheck();
1230
+ await o.credentialHunt();
1231
+ await o.networkMap();
1206
1232
  if (os.platform() === 'darwin')
1207
- o.macosOffensive();
1233
+ await o.macosOffensive();
1208
1234
  for (const r of o.getResults())
1209
1235
  o.analyze(r.output, 'redteam');
1210
1236
  return o.generateReport('Red Team Operation');
1211
1237
  };
1212
- export const blueTeam = (dir) => {
1238
+ export const blueTeam = async (dir) => {
1213
1239
  const o = new UnifiedOrchestrator(dir);
1214
- o.defenseCheck();
1215
- o.securityAudit();
1216
- o.persistenceCheck();
1217
- o.investigateProcesses();
1218
- o.investigateNetwork();
1240
+ await o.defenseCheck();
1241
+ await o.securityAudit();
1242
+ await o.persistenceCheck();
1243
+ await o.investigateProcesses();
1244
+ await o.investigateNetwork();
1219
1245
  for (const r of o.getResults())
1220
1246
  o.analyze(r.output, 'blueteam');
1221
1247
  return o.generateReport('Blue Team Operation');
1222
1248
  };
1223
- export const intelligence = (target, dir) => {
1249
+ export const intelligence = async (target, dir) => {
1224
1250
  const o = new UnifiedOrchestrator(dir);
1225
- o.recon(target);
1251
+ await o.recon(target);
1226
1252
  if (target)
1227
- o.targetRecon(target);
1228
- o.enumerate();
1229
- o.investigateNetwork();
1253
+ await o.targetRecon(target);
1254
+ await o.enumerate();
1255
+ await o.investigateNetwork();
1230
1256
  for (const r of o.getResults())
1231
1257
  o.analyze(r.output, 'intelligence');
1232
1258
  return o.generateReport('Intelligence Collection');