erosolar-cli 2.1.243 → 2.1.245
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capabilities/index.d.ts +1 -0
- package/dist/capabilities/index.d.ts.map +1 -1
- package/dist/capabilities/index.js +1 -0
- package/dist/capabilities/index.js.map +1 -1
- package/dist/capabilities/unifiedInvestigationCapability.d.ts +22 -0
- package/dist/capabilities/unifiedInvestigationCapability.d.ts.map +1 -0
- package/dist/capabilities/unifiedInvestigationCapability.js +41 -0
- package/dist/capabilities/unifiedInvestigationCapability.js.map +1 -0
- package/dist/core/agentOrchestrator.d.ts +130 -1
- package/dist/core/agentOrchestrator.d.ts.map +1 -1
- package/dist/core/agentOrchestrator.js +553 -1
- package/dist/core/agentOrchestrator.js.map +1 -1
- package/dist/core/unifiedFraudOrchestrator.d.ts +664 -0
- package/dist/core/unifiedFraudOrchestrator.d.ts.map +1 -0
- package/dist/core/unifiedFraudOrchestrator.js +2299 -0
- package/dist/core/unifiedFraudOrchestrator.js.map +1 -0
- package/dist/plugins/tools/nodeDefaults.d.ts.map +1 -1
- package/dist/plugins/tools/nodeDefaults.js +2 -0
- package/dist/plugins/tools/nodeDefaults.js.map +1 -1
- package/dist/plugins/tools/unifiedInvestigation/unifiedInvestigationPlugin.d.ts +3 -0
- package/dist/plugins/tools/unifiedInvestigation/unifiedInvestigationPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/unifiedInvestigation/unifiedInvestigationPlugin.js +14 -0
- package/dist/plugins/tools/unifiedInvestigation/unifiedInvestigationPlugin.js.map +1 -0
- package/dist/shell/interactiveShell.d.ts +51 -0
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +361 -1
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/tools/taoTools.d.ts.map +1 -1
- package/dist/tools/taoTools.js +1401 -4
- package/dist/tools/taoTools.js.map +1 -1
- package/dist/tools/unifiedInvestigationTools.d.ts +19 -0
- package/dist/tools/unifiedInvestigationTools.d.ts.map +1 -0
- package/dist/tools/unifiedInvestigationTools.js +1163 -0
- package/dist/tools/unifiedInvestigationTools.js.map +1 -0
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import { exec } from 'node:child_process';
|
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import { join, resolve } from 'node:path';
|
|
7
|
-
import { AgentOrchestrator } from '../core/agentOrchestrator.js';
|
|
7
|
+
import { AgentOrchestrator, } from '../core/agentOrchestrator.js';
|
|
8
8
|
import { display } from '../ui/display.js';
|
|
9
9
|
import { theme } from '../ui/theme.js';
|
|
10
10
|
import { getTerminalColumns } from '../ui/layout.js';
|
|
@@ -279,6 +279,37 @@ export class InteractiveShell {
|
|
|
279
279
|
description: 'Switch between auto and approval mode for high-impact actions',
|
|
280
280
|
category: 'configuration',
|
|
281
281
|
});
|
|
282
|
+
// Attack chain commands
|
|
283
|
+
this.slashCommands.push({
|
|
284
|
+
command: '/attack',
|
|
285
|
+
description: 'Execute unified attack chain (usage: /attack <mode> <targets>)',
|
|
286
|
+
category: 'security',
|
|
287
|
+
});
|
|
288
|
+
this.slashCommands.push({
|
|
289
|
+
command: '/recon',
|
|
290
|
+
description: 'Run reconnaissance against targets (usage: /recon <targets>)',
|
|
291
|
+
category: 'security',
|
|
292
|
+
});
|
|
293
|
+
this.slashCommands.push({
|
|
294
|
+
command: '/apt',
|
|
295
|
+
description: 'Run full APT kill-chain simulation (usage: /apt <targets>)',
|
|
296
|
+
category: 'security',
|
|
297
|
+
});
|
|
298
|
+
this.slashCommands.push({
|
|
299
|
+
command: '/redteam',
|
|
300
|
+
description: 'Execute red team operation with infrastructure (usage: /redteam <targets>)',
|
|
301
|
+
category: 'security',
|
|
302
|
+
});
|
|
303
|
+
this.slashCommands.push({
|
|
304
|
+
command: '/intel',
|
|
305
|
+
description: 'Gather intelligence on targets (usage: /intel <targets>)',
|
|
306
|
+
category: 'security',
|
|
307
|
+
});
|
|
308
|
+
this.slashCommands.push({
|
|
309
|
+
command: '/infra',
|
|
310
|
+
description: 'Deploy operational infrastructure (usage: /infra [region])',
|
|
311
|
+
category: 'security',
|
|
312
|
+
});
|
|
282
313
|
this.statusTracker = config.statusTracker;
|
|
283
314
|
this.ui = config.ui;
|
|
284
315
|
this.uiAdapter = config.ui.adapter;
|
|
@@ -2958,6 +2989,16 @@ export class InteractiveShell {
|
|
|
2958
2989
|
case '/logout':
|
|
2959
2990
|
this.handleLogoutCommand();
|
|
2960
2991
|
break;
|
|
2992
|
+
// Attack chain commands - handled via TaoOps tool
|
|
2993
|
+
case '/attack':
|
|
2994
|
+
case '/recon':
|
|
2995
|
+
case '/apt':
|
|
2996
|
+
case '/redteam':
|
|
2997
|
+
case '/intel':
|
|
2998
|
+
case '/infra':
|
|
2999
|
+
// These commands are handled through the UnifiedAttackChain tool
|
|
3000
|
+
this.processInput(`Execute ${command.slice(1)} operation: ${input.slice(command.length).trim() || 'analyze current target'}`);
|
|
3001
|
+
break;
|
|
2961
3002
|
default:
|
|
2962
3003
|
if (!(await this.tryCustomSlashCommand(command, input))) {
|
|
2963
3004
|
this.showInlineStatus(`Unknown command "${command}".`, 'warning', { autoClearMs: 1800 });
|
|
@@ -4725,6 +4766,325 @@ export class InteractiveShell {
|
|
|
4725
4766
|
this.showSlashInfo('Running comprehensive security review...');
|
|
4726
4767
|
await this.processRequest('Please perform a comprehensive security review of the codebase. Check for OWASP top 10 vulnerabilities, insecure patterns, and potential attack vectors.');
|
|
4727
4768
|
}
|
|
4769
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
4770
|
+
// ATTACK CHAIN COMMAND HANDLERS
|
|
4771
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
4772
|
+
/**
|
|
4773
|
+
* Execute unified attack chain with specified mode and targets.
|
|
4774
|
+
* Usage: /attack <mode> <targets>
|
|
4775
|
+
* Modes: recon, apt, redteam, intel, infra, all
|
|
4776
|
+
*/
|
|
4777
|
+
async handleAttackCommand(input) {
|
|
4778
|
+
if (this.isProcessing) {
|
|
4779
|
+
this.showSlashWarning('Wait for the current operation to finish.');
|
|
4780
|
+
return;
|
|
4781
|
+
}
|
|
4782
|
+
const parts = input.replace('/attack', '').trim().split(/\s+/);
|
|
4783
|
+
if (parts.length < 1 || !parts[0]) {
|
|
4784
|
+
this.showAttackChainHelp();
|
|
4785
|
+
return;
|
|
4786
|
+
}
|
|
4787
|
+
const modeArg = parts[0].toLowerCase();
|
|
4788
|
+
const targets = parts.slice(1);
|
|
4789
|
+
// Map command argument to unified mode
|
|
4790
|
+
const modeMap = {
|
|
4791
|
+
'recon': 'attack-chain',
|
|
4792
|
+
'apt': 'apt-simulation',
|
|
4793
|
+
'redteam': 'red-team',
|
|
4794
|
+
'intel': 'intel-collection',
|
|
4795
|
+
'infra': 'infrastructure',
|
|
4796
|
+
'compliance': 'compliance',
|
|
4797
|
+
'all': 'apt-simulation',
|
|
4798
|
+
};
|
|
4799
|
+
const mode = modeMap[modeArg];
|
|
4800
|
+
if (!mode) {
|
|
4801
|
+
this.showSlashWarning(`Unknown attack mode: ${modeArg}. Use: recon, apt, redteam, intel, infra`);
|
|
4802
|
+
return;
|
|
4803
|
+
}
|
|
4804
|
+
await this.executeUnifiedAttackChain(mode, targets, {
|
|
4805
|
+
goals: modeArg === 'all' ? ['all'] : undefined,
|
|
4806
|
+
});
|
|
4807
|
+
}
|
|
4808
|
+
/**
|
|
4809
|
+
* Run reconnaissance against targets.
|
|
4810
|
+
* Usage: /recon <targets>
|
|
4811
|
+
*/
|
|
4812
|
+
async handleReconCommand(input) {
|
|
4813
|
+
if (this.isProcessing) {
|
|
4814
|
+
this.showSlashWarning('Wait for the current operation to finish.');
|
|
4815
|
+
return;
|
|
4816
|
+
}
|
|
4817
|
+
const targets = input.replace('/recon', '').trim().split(/\s+/).filter(t => t);
|
|
4818
|
+
if (targets.length === 0) {
|
|
4819
|
+
this.showSlashWarning('Usage: /recon <target1> [target2] ...');
|
|
4820
|
+
return;
|
|
4821
|
+
}
|
|
4822
|
+
await this.executeUnifiedAttackChain('attack-chain', targets, {
|
|
4823
|
+
goals: ['reconnaissance'],
|
|
4824
|
+
attackDepth: 'standard',
|
|
4825
|
+
});
|
|
4826
|
+
}
|
|
4827
|
+
/**
|
|
4828
|
+
* Run full APT kill-chain simulation.
|
|
4829
|
+
* Usage: /apt <targets>
|
|
4830
|
+
*/
|
|
4831
|
+
async handleAPTCommand(input) {
|
|
4832
|
+
if (this.isProcessing) {
|
|
4833
|
+
this.showSlashWarning('Wait for the current operation to finish.');
|
|
4834
|
+
return;
|
|
4835
|
+
}
|
|
4836
|
+
const parts = input.replace('/apt', '').trim().split(/\s+/).filter(t => t);
|
|
4837
|
+
if (parts.length === 0) {
|
|
4838
|
+
this.showSlashWarning('Usage: /apt <target1> [target2] ... [--stealth] [--deep]');
|
|
4839
|
+
return;
|
|
4840
|
+
}
|
|
4841
|
+
// Parse flags
|
|
4842
|
+
const stealth = parts.includes('--stealth');
|
|
4843
|
+
const deep = parts.includes('--deep');
|
|
4844
|
+
const targets = parts.filter(p => !p.startsWith('--'));
|
|
4845
|
+
await this.executeUnifiedAttackChain('apt-simulation', targets, {
|
|
4846
|
+
stealthMode: stealth,
|
|
4847
|
+
attackDepth: deep ? 'deep' : 'standard',
|
|
4848
|
+
});
|
|
4849
|
+
}
|
|
4850
|
+
/**
|
|
4851
|
+
* Execute red team operation with infrastructure.
|
|
4852
|
+
* Usage: /redteam <targets>
|
|
4853
|
+
*/
|
|
4854
|
+
async handleRedTeamCommand(input) {
|
|
4855
|
+
if (this.isProcessing) {
|
|
4856
|
+
this.showSlashWarning('Wait for the current operation to finish.');
|
|
4857
|
+
return;
|
|
4858
|
+
}
|
|
4859
|
+
const parts = input.replace('/redteam', '').trim().split(/\s+/).filter(t => t);
|
|
4860
|
+
if (parts.length === 0) {
|
|
4861
|
+
this.showSlashWarning('Usage: /redteam <target1> [target2] ... [--region=us|ukraine]');
|
|
4862
|
+
return;
|
|
4863
|
+
}
|
|
4864
|
+
// Parse region flag
|
|
4865
|
+
const regionFlag = parts.find(p => p.startsWith('--region='));
|
|
4866
|
+
const region = regionFlag?.split('=')[1];
|
|
4867
|
+
const targets = parts.filter(p => !p.startsWith('--'));
|
|
4868
|
+
await this.executeUnifiedAttackChain('red-team', targets, {
|
|
4869
|
+
region: region ?? 'us',
|
|
4870
|
+
stealthMode: true,
|
|
4871
|
+
attackDepth: 'deep',
|
|
4872
|
+
});
|
|
4873
|
+
}
|
|
4874
|
+
/**
|
|
4875
|
+
* Gather intelligence on targets.
|
|
4876
|
+
* Usage: /intel <targets>
|
|
4877
|
+
*/
|
|
4878
|
+
async handleIntelCommand(input) {
|
|
4879
|
+
if (this.isProcessing) {
|
|
4880
|
+
this.showSlashWarning('Wait for the current operation to finish.');
|
|
4881
|
+
return;
|
|
4882
|
+
}
|
|
4883
|
+
const targets = input.replace('/intel', '').trim().split(/\s+/).filter(t => t);
|
|
4884
|
+
if (targets.length === 0) {
|
|
4885
|
+
this.showSlashWarning('Usage: /intel <target1> [target2] ...');
|
|
4886
|
+
return;
|
|
4887
|
+
}
|
|
4888
|
+
await this.executeUnifiedAttackChain('intel-collection', targets, {
|
|
4889
|
+
goals: ['reconnaissance', 'collection'],
|
|
4890
|
+
collectIntel: true,
|
|
4891
|
+
minimizeFootprint: true,
|
|
4892
|
+
});
|
|
4893
|
+
}
|
|
4894
|
+
/**
|
|
4895
|
+
* Deploy operational infrastructure.
|
|
4896
|
+
* Usage: /infra [region]
|
|
4897
|
+
*/
|
|
4898
|
+
async handleInfraCommand(input) {
|
|
4899
|
+
if (this.isProcessing) {
|
|
4900
|
+
this.showSlashWarning('Wait for the current operation to finish.');
|
|
4901
|
+
return;
|
|
4902
|
+
}
|
|
4903
|
+
const parts = input.replace('/infra', '').trim().split(/\s+/).filter(t => t);
|
|
4904
|
+
const region = (parts[0] || 'us');
|
|
4905
|
+
await this.executeUnifiedAttackChain('infrastructure', [], {
|
|
4906
|
+
region,
|
|
4907
|
+
generateInfrastructure: true,
|
|
4908
|
+
});
|
|
4909
|
+
}
|
|
4910
|
+
/**
|
|
4911
|
+
* Execute unified attack chain with real TAO technique execution.
|
|
4912
|
+
*/
|
|
4913
|
+
async executeUnifiedAttackChain(mode, targets, extraOptions = {}) {
|
|
4914
|
+
if (!this.agent && !this.rebuildAgent()) {
|
|
4915
|
+
this.showSlashWarning('Configure an API key via /secrets before running attack chains.');
|
|
4916
|
+
return;
|
|
4917
|
+
}
|
|
4918
|
+
const agent = this.agent;
|
|
4919
|
+
const orchestrator = new AgentOrchestrator(agent);
|
|
4920
|
+
// Build options
|
|
4921
|
+
const options = {
|
|
4922
|
+
unifiedMode: mode,
|
|
4923
|
+
attackTargets: targets,
|
|
4924
|
+
streaming: true,
|
|
4925
|
+
...extraOptions,
|
|
4926
|
+
// Callbacks for real-time progress display
|
|
4927
|
+
onTechniqueStart: (techniqueId, target) => {
|
|
4928
|
+
this.showAttackChainProgress(`▶ ${techniqueId} → ${target}`);
|
|
4929
|
+
},
|
|
4930
|
+
onTechniqueComplete: (result) => {
|
|
4931
|
+
const status = result.success ? theme.success('✓') : theme.error('✗');
|
|
4932
|
+
const risk = result.detectionRisk > 0.7 ? theme.warning('⚠ HIGH RISK') : '';
|
|
4933
|
+
this.showAttackChainProgress(`${status} ${result.techniqueName} (${result.duration}ms) ${risk}`);
|
|
4934
|
+
if (result.artifacts.length > 0) {
|
|
4935
|
+
this.showAttackChainProgress(` └─ ${result.artifacts.length} artifacts collected`);
|
|
4936
|
+
}
|
|
4937
|
+
},
|
|
4938
|
+
onGoalAchieved: (goal, artifacts) => {
|
|
4939
|
+
this.showAttackChainProgress(theme.success(`★ Goal achieved: ${goal} (${artifacts.length} artifacts)`));
|
|
4940
|
+
},
|
|
4941
|
+
};
|
|
4942
|
+
this.isProcessing = true;
|
|
4943
|
+
this.showAttackChainBanner(mode, targets);
|
|
4944
|
+
try {
|
|
4945
|
+
const result = await orchestrator.runUnified(`Execute ${mode} operation against: ${targets.join(', ') || 'infrastructure deployment'}`, options);
|
|
4946
|
+
// Display results
|
|
4947
|
+
this.displayAttackChainResult(result);
|
|
4948
|
+
}
|
|
4949
|
+
catch (error) {
|
|
4950
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4951
|
+
this.showSlashWarning(`Attack chain failed: ${message}`);
|
|
4952
|
+
}
|
|
4953
|
+
finally {
|
|
4954
|
+
this.isProcessing = false;
|
|
4955
|
+
this.syncRendererInput();
|
|
4956
|
+
}
|
|
4957
|
+
}
|
|
4958
|
+
/**
|
|
4959
|
+
* Show attack chain help.
|
|
4960
|
+
*/
|
|
4961
|
+
showAttackChainHelp() {
|
|
4962
|
+
const lines = [
|
|
4963
|
+
theme.gradient.primary('Attack Chain Commands'),
|
|
4964
|
+
'',
|
|
4965
|
+
theme.bold('/attack <mode> <targets>') + ' - Execute unified attack chain',
|
|
4966
|
+
' Modes: recon, apt, redteam, intel, infra, compliance, all',
|
|
4967
|
+
'',
|
|
4968
|
+
theme.bold('/recon <targets>') + ' - Run reconnaissance',
|
|
4969
|
+
theme.bold('/apt <targets> [--stealth] [--deep]') + ' - Full APT simulation',
|
|
4970
|
+
theme.bold('/redteam <targets> [--region=us|ukraine]') + ' - Red team with infra',
|
|
4971
|
+
theme.bold('/intel <targets>') + ' - Intelligence collection',
|
|
4972
|
+
theme.bold('/infra [region]') + ' - Deploy infrastructure',
|
|
4973
|
+
'',
|
|
4974
|
+
theme.secondary('Examples:'),
|
|
4975
|
+
' /recon example.com',
|
|
4976
|
+
' /apt target.com --stealth --deep',
|
|
4977
|
+
' /redteam corp.local --region=ukraine',
|
|
4978
|
+
' /intel competitor.com investor.com',
|
|
4979
|
+
' /infra us',
|
|
4980
|
+
'',
|
|
4981
|
+
theme.warning('⚠ For authorized testing only. Requires proper authorization.'),
|
|
4982
|
+
];
|
|
4983
|
+
display.showSystemMessage(lines.join('\n'));
|
|
4984
|
+
}
|
|
4985
|
+
/**
|
|
4986
|
+
* Show attack chain execution banner.
|
|
4987
|
+
*/
|
|
4988
|
+
showAttackChainBanner(mode, targets) {
|
|
4989
|
+
const modeLabels = {
|
|
4990
|
+
'standard': 'Standard',
|
|
4991
|
+
'attack-chain': 'Attack Chain',
|
|
4992
|
+
'apt-simulation': 'APT Simulation',
|
|
4993
|
+
'infrastructure': 'Infrastructure',
|
|
4994
|
+
'red-team': 'Red Team',
|
|
4995
|
+
'intel-collection': 'Intelligence Collection',
|
|
4996
|
+
'compliance': 'Compliance',
|
|
4997
|
+
};
|
|
4998
|
+
const lines = [
|
|
4999
|
+
'',
|
|
5000
|
+
theme.gradient.primary('═══════════════════════════════════════════════════════════'),
|
|
5001
|
+
theme.gradient.primary(` ${modeLabels[mode]} Operation`),
|
|
5002
|
+
theme.gradient.primary('═══════════════════════════════════════════════════════════'),
|
|
5003
|
+
'',
|
|
5004
|
+
];
|
|
5005
|
+
if (targets.length > 0) {
|
|
5006
|
+
lines.push(theme.bold('Targets:'));
|
|
5007
|
+
for (const target of targets) {
|
|
5008
|
+
lines.push(` • ${target}`);
|
|
5009
|
+
}
|
|
5010
|
+
lines.push('');
|
|
5011
|
+
}
|
|
5012
|
+
lines.push(theme.ui.muted('Press Ctrl+C to abort operation.'));
|
|
5013
|
+
lines.push('');
|
|
5014
|
+
display.showSystemMessage(lines.join('\n'));
|
|
5015
|
+
}
|
|
5016
|
+
/**
|
|
5017
|
+
* Show attack chain progress update.
|
|
5018
|
+
*/
|
|
5019
|
+
showAttackChainProgress(message) {
|
|
5020
|
+
display.showSystemMessage(message);
|
|
5021
|
+
}
|
|
5022
|
+
/**
|
|
5023
|
+
* Display attack chain execution result.
|
|
5024
|
+
*/
|
|
5025
|
+
displayAttackChainResult(result) {
|
|
5026
|
+
const lines = [
|
|
5027
|
+
'',
|
|
5028
|
+
theme.gradient.primary('═══════════════════════════════════════════════════════════'),
|
|
5029
|
+
theme.gradient.primary(' Execution Complete'),
|
|
5030
|
+
theme.gradient.primary('═══════════════════════════════════════════════════════════'),
|
|
5031
|
+
'',
|
|
5032
|
+
];
|
|
5033
|
+
// Status summary
|
|
5034
|
+
lines.push(theme.bold('Status: ') + (result.exitReason === 'attack-chain-complete'
|
|
5035
|
+
? theme.success('SUCCESS')
|
|
5036
|
+
: theme.error('INCOMPLETE')));
|
|
5037
|
+
lines.push('');
|
|
5038
|
+
// Metrics
|
|
5039
|
+
if (result.realMetrics) {
|
|
5040
|
+
const m = result.realMetrics;
|
|
5041
|
+
lines.push(theme.bold('Metrics:'));
|
|
5042
|
+
lines.push(` Techniques: ${m.successfulTechniques}/${m.totalTechniquesExecuted} successful`);
|
|
5043
|
+
lines.push(` Duration: ${(m.totalDuration / 1000).toFixed(1)}s`);
|
|
5044
|
+
lines.push(` Detection Risk: ${(m.averageDetectionRisk * 100).toFixed(0)}%`);
|
|
5045
|
+
lines.push(` Artifacts: ${m.artifactsCollected}`);
|
|
5046
|
+
lines.push(` Phases: ${m.phasesCompleted.join(', ') || 'none'}`);
|
|
5047
|
+
lines.push('');
|
|
5048
|
+
}
|
|
5049
|
+
// Goals achieved
|
|
5050
|
+
if (result.achievedGoals && result.achievedGoals.length > 0) {
|
|
5051
|
+
lines.push(theme.bold('Goals Achieved:'));
|
|
5052
|
+
for (const goal of result.achievedGoals) {
|
|
5053
|
+
lines.push(` ${theme.success('✓')} ${goal}`);
|
|
5054
|
+
}
|
|
5055
|
+
lines.push('');
|
|
5056
|
+
}
|
|
5057
|
+
// Infrastructure
|
|
5058
|
+
if (result.infrastructureStack) {
|
|
5059
|
+
const stack = result.infrastructureStack;
|
|
5060
|
+
lines.push(theme.bold('Infrastructure:'));
|
|
5061
|
+
lines.push(` Name: ${stack.name}`);
|
|
5062
|
+
lines.push(` Region: ${stack.region}`);
|
|
5063
|
+
lines.push(` Components: ${stack.components.length}`);
|
|
5064
|
+
lines.push(` Cost: $${stack.costEstimate.monthly}/month`);
|
|
5065
|
+
lines.push('');
|
|
5066
|
+
}
|
|
5067
|
+
// Recommendations
|
|
5068
|
+
if (result.recommendations.length > 0) {
|
|
5069
|
+
lines.push(theme.bold('Recommendations:'));
|
|
5070
|
+
for (const rec of result.recommendations) {
|
|
5071
|
+
lines.push(` • ${rec}`);
|
|
5072
|
+
}
|
|
5073
|
+
lines.push('');
|
|
5074
|
+
}
|
|
5075
|
+
// Tools used
|
|
5076
|
+
if (result.toolsUsed.length > 0) {
|
|
5077
|
+
lines.push(theme.bold(`Tools Used: `) + theme.ui.muted(`(${result.toolsUsed.length})`));
|
|
5078
|
+
const toolList = result.toolsUsed.slice(0, 10).join(', ');
|
|
5079
|
+
lines.push(` ${toolList}${result.toolsUsed.length > 10 ? '...' : ''}`);
|
|
5080
|
+
lines.push('');
|
|
5081
|
+
}
|
|
5082
|
+
display.showSystemMessage(lines.join('\n'));
|
|
5083
|
+
// Show final response if substantial
|
|
5084
|
+
if (result.finalResponse && result.finalResponse.length > 100) {
|
|
5085
|
+
display.showAssistantMessage(result.finalResponse, { isFinal: true });
|
|
5086
|
+
}
|
|
5087
|
+
}
|
|
4728
5088
|
handleBugCommand() {
|
|
4729
5089
|
const lines = [];
|
|
4730
5090
|
lines.push(theme.bold('Report an Issue'));
|