erosolar-cli 2.1.281 → 2.1.283
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/orchestrationCapability.d.ts.map +1 -1
- package/dist/capabilities/orchestrationCapability.js +37 -18
- package/dist/capabilities/orchestrationCapability.js.map +1 -1
- package/dist/core/unifiedOrchestrator.d.ts +54 -4
- package/dist/core/unifiedOrchestrator.d.ts.map +1 -1
- package/dist/core/unifiedOrchestrator.js +198 -22
- package/dist/core/unifiedOrchestrator.js.map +1 -1
- package/dist/shell/interactiveShell.d.ts +4 -0
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +143 -9
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/tools/tao/rl.d.ts.map +1 -1
- package/dist/tools/tao/rl.js +2 -1
- package/dist/tools/tao/rl.js.map +1 -1
- package/dist/ui/orchestration/OrchestrationUIBridge.d.ts +117 -0
- package/dist/ui/orchestration/OrchestrationUIBridge.d.ts.map +1 -0
- package/dist/ui/orchestration/OrchestrationUIBridge.js +435 -0
- package/dist/ui/orchestration/OrchestrationUIBridge.js.map +1 -0
- package/dist/ui/orchestration/StatusOrchestrator.d.ts +24 -0
- package/dist/ui/orchestration/StatusOrchestrator.d.ts.map +1 -1
- package/dist/ui/orchestration/StatusOrchestrator.js +94 -0
- package/dist/ui/orchestration/StatusOrchestrator.js.map +1 -1
- package/dist/ui/orchestration/index.d.ts +15 -0
- package/dist/ui/orchestration/index.d.ts.map +1 -0
- package/dist/ui/orchestration/index.js +18 -0
- package/dist/ui/orchestration/index.js.map +1 -0
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ import { promisify } from 'node:util';
|
|
|
5
5
|
import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import { join, resolve } from 'node:path';
|
|
7
7
|
import { UnifiedOrchestrator, } from '../core/unifiedOrchestrator.js';
|
|
8
|
+
import { createOrchestrationUIBridge, } from '../ui/orchestration/OrchestrationUIBridge.js';
|
|
8
9
|
// Alias for backward compatibility
|
|
9
10
|
const AgentOrchestrator = UnifiedOrchestrator;
|
|
10
11
|
import { display } from '../ui/display.js';
|
|
@@ -1850,6 +1851,83 @@ export class InteractiveShell {
|
|
|
1850
1851
|
this.appendInlineNotice('Please respond with "yes" to proceed or "no" to cancel.', 'warning');
|
|
1851
1852
|
this.syncRendererInput();
|
|
1852
1853
|
}
|
|
1854
|
+
isOffensiveIntent(text) {
|
|
1855
|
+
const lower = text.toLowerCase();
|
|
1856
|
+
const keywords = [
|
|
1857
|
+
'attack',
|
|
1858
|
+
'offensive',
|
|
1859
|
+
'exploit',
|
|
1860
|
+
'apt',
|
|
1861
|
+
'kill-chain',
|
|
1862
|
+
'pentest',
|
|
1863
|
+
'pwn',
|
|
1864
|
+
'red team',
|
|
1865
|
+
'execute_real',
|
|
1866
|
+
'malicious',
|
|
1867
|
+
'counter-attack',
|
|
1868
|
+
'counterattack',
|
|
1869
|
+
'retaliate',
|
|
1870
|
+
'symmetric response',
|
|
1871
|
+
];
|
|
1872
|
+
return keywords.some((kw) => lower.includes(kw));
|
|
1873
|
+
}
|
|
1874
|
+
showAttackConfirmationPrompt(request) {
|
|
1875
|
+
const lines = [];
|
|
1876
|
+
lines.push(theme.gradient.primary('⚖️ Confirm operation type'));
|
|
1877
|
+
lines.push('');
|
|
1878
|
+
lines.push(theme.bold('Choose how to proceed:'));
|
|
1879
|
+
lines.push(`${theme.info('1)')} Symmetric cyber response (defensive/retaliatory)`);
|
|
1880
|
+
lines.push(`${theme.info('2)')} Offensive attack (malicious intent)`);
|
|
1881
|
+
lines.push('');
|
|
1882
|
+
lines.push(theme.ui.muted(`Request: ${request.slice(0, 120)}${request.length > 120 ? '…' : ''}`));
|
|
1883
|
+
lines.push('');
|
|
1884
|
+
lines.push('Type 1 or 2 to continue, or cancel/no to abort.');
|
|
1885
|
+
this.showInlinePanel(lines);
|
|
1886
|
+
this.syncRendererInput();
|
|
1887
|
+
}
|
|
1888
|
+
async handleAttackConfirmationInput(input) {
|
|
1889
|
+
const pending = this.pendingInteraction;
|
|
1890
|
+
if (!pending || pending.type !== 'attack-confirmation') {
|
|
1891
|
+
return;
|
|
1892
|
+
}
|
|
1893
|
+
const normalized = input.trim().toLowerCase();
|
|
1894
|
+
if (!normalized) {
|
|
1895
|
+
this.appendInlineNotice('Type 1 for symmetric response, 2 for offensive, or cancel.', 'warning');
|
|
1896
|
+
this.syncRendererInput();
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1899
|
+
if (['cancel', 'c', 'no', 'n'].includes(normalized)) {
|
|
1900
|
+
this.pendingInteraction = null;
|
|
1901
|
+
this.showInlineStatus('Operation cancelled.', 'info', { autoClearMs: 1400 });
|
|
1902
|
+
this.syncRendererInput();
|
|
1903
|
+
return;
|
|
1904
|
+
}
|
|
1905
|
+
let choice = null;
|
|
1906
|
+
if (normalized === '1' || normalized.startsWith('sym')) {
|
|
1907
|
+
choice = 'symmetric';
|
|
1908
|
+
}
|
|
1909
|
+
else if (normalized === '2' || normalized.startsWith('off')) {
|
|
1910
|
+
choice = 'offensive';
|
|
1911
|
+
}
|
|
1912
|
+
if (!choice) {
|
|
1913
|
+
this.appendInlineNotice('Choose 1 (symmetric) or 2 (offensive), or cancel.', 'warning');
|
|
1914
|
+
this.syncRendererInput();
|
|
1915
|
+
return;
|
|
1916
|
+
}
|
|
1917
|
+
this.pendingInteraction = null;
|
|
1918
|
+
const prefix = choice === 'symmetric'
|
|
1919
|
+
? 'SYMMETRIC CYBER RESPONSE (defensive/retaliatory): '
|
|
1920
|
+
: 'OFFENSIVE ATTACK REQUEST (authorized): ';
|
|
1921
|
+
const forwardedRequest = `${prefix}${pending.request}`;
|
|
1922
|
+
this.showInlineStatus(choice === 'symmetric'
|
|
1923
|
+
? 'Proceeding with symmetric cyber response...'
|
|
1924
|
+
: 'Proceeding with offensive attack workflow...', choice === 'symmetric' ? 'info' : 'warning', { autoClearMs: 1600 });
|
|
1925
|
+
this.syncRendererInput();
|
|
1926
|
+
await this.processRequest(forwardedRequest, {
|
|
1927
|
+
...(pending.options ?? {}),
|
|
1928
|
+
skipAttackConfirmation: true,
|
|
1929
|
+
});
|
|
1930
|
+
}
|
|
1853
1931
|
setupHandlers() {
|
|
1854
1932
|
// Handle terminal resize
|
|
1855
1933
|
output.on('resize', () => {
|
|
@@ -2929,6 +3007,9 @@ Begin execution immediately.`;
|
|
|
2929
3007
|
case 'critical-approval':
|
|
2930
3008
|
await this.handleCriticalApprovalInput(input);
|
|
2931
3009
|
return true;
|
|
3010
|
+
case 'attack-confirmation':
|
|
3011
|
+
await this.handleAttackConfirmationInput(input);
|
|
3012
|
+
return true;
|
|
2932
3013
|
default:
|
|
2933
3014
|
return false;
|
|
2934
3015
|
}
|
|
@@ -5947,9 +6028,9 @@ serving as both intelligence and deterrence documentation.`;
|
|
|
5947
6028
|
}
|
|
5948
6029
|
/**
|
|
5949
6030
|
* Execute unified attack chain with real TAO technique execution.
|
|
6031
|
+
* Uses OrchestrationUIBridge for real-time UI updates.
|
|
5950
6032
|
*/
|
|
5951
6033
|
async executeUnifiedAttackChain(mode, targets, extraOptions = {}) {
|
|
5952
|
-
const orchestrator = new AgentOrchestrator(this.workingDir);
|
|
5953
6034
|
// Build options
|
|
5954
6035
|
const options = {
|
|
5955
6036
|
mode,
|
|
@@ -5960,9 +6041,23 @@ serving as both intelligence and deterrence documentation.`;
|
|
|
5960
6041
|
};
|
|
5961
6042
|
this.isProcessing = true;
|
|
5962
6043
|
this.showAttackChainBanner(mode, targets);
|
|
6044
|
+
// Create UI bridge for real-time updates
|
|
6045
|
+
const uiBridge = createOrchestrationUIBridge(display, {
|
|
6046
|
+
updateCoordinator: this.uiAdapter.getUpdateCoordinator(),
|
|
6047
|
+
showRealTimeOutput: true,
|
|
6048
|
+
showProgressBar: true,
|
|
6049
|
+
verboseMode: true,
|
|
6050
|
+
});
|
|
6051
|
+
// Subscribe to events for enhanced feedback
|
|
6052
|
+
const unsubscribeFinding = uiBridge.on('finding', (event) => {
|
|
6053
|
+
const finding = event.data;
|
|
6054
|
+
display.showSystemMessage(`[${finding.severity.toUpperCase()}] ${finding.title}`);
|
|
6055
|
+
});
|
|
5963
6056
|
try {
|
|
5964
|
-
const
|
|
5965
|
-
|
|
6057
|
+
const objective = `Execute ${mode} operation against: ${targets.join(', ') || 'infrastructure deployment'}`;
|
|
6058
|
+
const result = await uiBridge.execute(objective, options);
|
|
6059
|
+
// Display results - the bridge already shows real-time updates,
|
|
6060
|
+
// but we still show the final summary
|
|
5966
6061
|
this.displayAttackChainResult(result);
|
|
5967
6062
|
}
|
|
5968
6063
|
catch (error) {
|
|
@@ -5970,6 +6065,7 @@ serving as both intelligence and deterrence documentation.`;
|
|
|
5970
6065
|
this.showSlashWarning(`Attack chain failed: ${message}`);
|
|
5971
6066
|
}
|
|
5972
6067
|
finally {
|
|
6068
|
+
uiBridge.dispose();
|
|
5973
6069
|
this.isProcessing = false;
|
|
5974
6070
|
this.syncRendererInput();
|
|
5975
6071
|
}
|
|
@@ -7524,6 +7620,15 @@ serving as both intelligence and deterrence documentation.`;
|
|
|
7524
7620
|
if (!trimmedRequest) {
|
|
7525
7621
|
return;
|
|
7526
7622
|
}
|
|
7623
|
+
if (!options?.skipAttackConfirmation && this.isOffensiveIntent(trimmedRequest)) {
|
|
7624
|
+
this.pendingInteraction = {
|
|
7625
|
+
type: 'attack-confirmation',
|
|
7626
|
+
request: trimmedRequest,
|
|
7627
|
+
options: { orchestrate: options?.orchestrate ?? true, ...options },
|
|
7628
|
+
};
|
|
7629
|
+
this.showAttackConfirmationPrompt(trimmedRequest);
|
|
7630
|
+
return;
|
|
7631
|
+
}
|
|
7527
7632
|
if (this.isProcessing) {
|
|
7528
7633
|
this.enqueueFollowUpAction({ type: 'request', text: trimmedRequest });
|
|
7529
7634
|
return;
|
|
@@ -7586,18 +7691,36 @@ serving as both intelligence and deterrence documentation.`;
|
|
|
7586
7691
|
let responseText = '';
|
|
7587
7692
|
let orchestratorResult = null;
|
|
7588
7693
|
// Always use AI agent - orchestrator tools are available to the AI as needed
|
|
7589
|
-
const orchestrate = options?.orchestrate ??
|
|
7694
|
+
const orchestrate = options?.orchestrate ?? true;
|
|
7590
7695
|
try {
|
|
7591
7696
|
// Start streaming - no header needed, the input area already provides context
|
|
7592
7697
|
this.startStreamingHeartbeat('Streaming response');
|
|
7593
7698
|
// Inject authorization context for security-related requests
|
|
7594
7699
|
const preparedRequest = this.prepareSecurityRequest(trimmedRequest);
|
|
7595
7700
|
if (orchestrate) {
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7701
|
+
// Use OrchestrationUIBridge for real-time UI updates during orchestration
|
|
7702
|
+
const uiBridge = createOrchestrationUIBridge(display, {
|
|
7703
|
+
updateCoordinator: this.uiAdapter.getUpdateCoordinator(),
|
|
7704
|
+
showRealTimeOutput: true,
|
|
7705
|
+
showProgressBar: true,
|
|
7706
|
+
verboseMode: true,
|
|
7599
7707
|
});
|
|
7600
|
-
|
|
7708
|
+
// Subscribe to progress events for status updates
|
|
7709
|
+
uiBridge.on('progress', (event) => {
|
|
7710
|
+
const progress = event.data;
|
|
7711
|
+
if (progress.currentCommand) {
|
|
7712
|
+
this.renderer?.setActivity(`Running: ${progress.currentCommand.slice(0, 40)}`);
|
|
7713
|
+
}
|
|
7714
|
+
});
|
|
7715
|
+
try {
|
|
7716
|
+
orchestratorResult = await uiBridge.execute(preparedRequest, {
|
|
7717
|
+
verbose: true,
|
|
7718
|
+
});
|
|
7719
|
+
responseText = orchestratorResult.finalResponse ?? '';
|
|
7720
|
+
}
|
|
7721
|
+
finally {
|
|
7722
|
+
uiBridge.dispose();
|
|
7723
|
+
}
|
|
7601
7724
|
}
|
|
7602
7725
|
else {
|
|
7603
7726
|
responseText = await agent.send(preparedRequest, true);
|
|
@@ -7642,12 +7765,20 @@ serving as both intelligence and deterrence documentation.`;
|
|
|
7642
7765
|
return 'Received an empty reply while orchestrating; showing last response.';
|
|
7643
7766
|
case 'no-action':
|
|
7644
7767
|
return 'No concrete actions were detected; the response may be a plan-only summary.';
|
|
7768
|
+
case 'no-commands':
|
|
7769
|
+
return 'No actions were executed; ensure the request includes a specific, actionable task.';
|
|
7645
7770
|
case 'verification-needed':
|
|
7646
7771
|
return 'Verification is recommended based on the model response.';
|
|
7647
7772
|
case 'blocked':
|
|
7648
7773
|
return 'The model reported being blocked; check keys, permissions, or missing context.';
|
|
7774
|
+
case 'failed-commands':
|
|
7775
|
+
return 'Some orchestration commands failed; inspect failed commands and retry.';
|
|
7776
|
+
case 'critical-findings':
|
|
7777
|
+
return 'Critical findings detected; address the recommendations and rerun.';
|
|
7649
7778
|
case 'incomplete':
|
|
7650
|
-
return
|
|
7779
|
+
return orchestratorResult.statusSummary
|
|
7780
|
+
? `Orchestration incomplete: ${orchestratorResult.statusSummary}`
|
|
7781
|
+
: 'Orchestration stopped without a clear completion signal; review the output.';
|
|
7651
7782
|
default:
|
|
7652
7783
|
return null;
|
|
7653
7784
|
}
|
|
@@ -7665,6 +7796,9 @@ serving as both intelligence and deterrence documentation.`;
|
|
|
7665
7796
|
display.showSystemMessage(`Next steps: ${orchestratorResult.recommendations.join(' | ')}`);
|
|
7666
7797
|
}
|
|
7667
7798
|
}
|
|
7799
|
+
// Nudge follow-up when orchestration stops early
|
|
7800
|
+
this.showInlineStatus('Orchestration incomplete: review findings and rerun or apply fixes.', 'warning', { autoClearMs: 3200 });
|
|
7801
|
+
this.renderer?.setActivity('Review findings');
|
|
7668
7802
|
}
|
|
7669
7803
|
else if (orchestratorResult && orchestratorResult.exitReason === 'complete') {
|
|
7670
7804
|
// Task fully complete - show emphasis with elapsed time
|