erosolar-cli 1.7.393 โ 1.7.395
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/core/offsecAlphaZero.d.ts +56 -0
- package/dist/core/offsecAlphaZero.d.ts.map +1 -0
- package/dist/core/offsecAlphaZero.js +395 -0
- package/dist/core/offsecAlphaZero.js.map +1 -0
- package/dist/core/preferences.d.ts +1 -0
- package/dist/core/preferences.d.ts.map +1 -1
- package/dist/core/preferences.js +7 -0
- package/dist/core/preferences.js.map +1 -1
- package/dist/shell/interactiveShell.d.ts +23 -5
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +486 -135
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/keyboardShortcuts.d.ts.map +1 -1
- package/dist/shell/keyboardShortcuts.js +11 -8
- package/dist/shell/keyboardShortcuts.js.map +1 -1
- package/dist/shell/liveStatus.d.ts +1 -0
- package/dist/shell/liveStatus.d.ts.map +1 -1
- package/dist/shell/liveStatus.js +32 -7
- package/dist/shell/liveStatus.js.map +1 -1
- package/dist/shell/terminalInput.d.ts +25 -2
- package/dist/shell/terminalInput.d.ts.map +1 -1
- package/dist/shell/terminalInput.js +270 -60
- package/dist/shell/terminalInput.js.map +1 -1
- package/dist/shell/terminalInputAdapter.d.ts +14 -0
- package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
- package/dist/shell/terminalInputAdapter.js +14 -0
- package/dist/shell/terminalInputAdapter.js.map +1 -1
- package/dist/shell/updateManager.d.ts +8 -1
- package/dist/shell/updateManager.d.ts.map +1 -1
- package/dist/shell/updateManager.js +4 -2
- package/dist/shell/updateManager.js.map +1 -1
- package/dist/ui/ShellUIAdapter.d.ts +6 -12
- package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
- package/dist/ui/ShellUIAdapter.js +26 -37
- package/dist/ui/ShellUIAdapter.js.map +1 -1
- package/dist/ui/shortcutsHelp.d.ts.map +1 -1
- package/dist/ui/shortcutsHelp.js +22 -21
- package/dist/ui/shortcutsHelp.js.map +1 -1
- package/dist/ui/unified/index.d.ts +2 -2
- package/dist/ui/unified/index.d.ts.map +1 -1
- package/dist/ui/unified/index.js.map +1 -1
- package/dist/ui/unified/layout.d.ts.map +1 -1
- package/dist/ui/unified/layout.js +31 -25
- package/dist/ui/unified/layout.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,11 +30,11 @@ import { analyzeImprovementOpportunities, runSelfImprovementCycle, getImprovemen
|
|
|
30
30
|
import { listAvailablePlugins } from '../plugins/index.js';
|
|
31
31
|
import { isErosolarRepo, isValidSourceRepo, getRepoName, analyzeSource, runSelfEvolution, stopEvolution, getEvolutionStatus, emergencyEvolutionRollback, learnSourcePatterns, generateFix, } from '../core/selfEvolution.js';
|
|
32
32
|
import { analyzeTokenUsage, discoverModularTargets, getModularStatusDisplay, generateContextOptimizations, getGuidelines, deleteGuideline, getPendingActions, executeModularAction, } from '../core/alphaZeroModular.js';
|
|
33
|
+
import { startOffsecRun, resumeOffsecRun, recordOffsecOutcome, getOffsecNextActions, simulateOffsecRollout, formatOffsecStatus, listOffsecRuns, } from '../core/offsecAlphaZero.js';
|
|
33
34
|
import { generateTestFlows, detectBugs, detectUIUpdates, saveTestFlows, saveBugReports, saveUIUpdates, getTestFlowStatus, } from '../core/intelligentTestFlows.js';
|
|
34
35
|
import { TerminalInputAdapter } from './terminalInputAdapter.js';
|
|
35
36
|
import { renderSessionFrame } from '../ui/unified/layout.js';
|
|
36
37
|
import { isUpdateInProgress, maybeOfferCliUpdate } from './updateManager.js';
|
|
37
|
-
import { writeLock } from '../ui/writeLock.js';
|
|
38
38
|
import { enterStreamingMode, exitStreamingMode } from '../ui/globalWriteLock.js';
|
|
39
39
|
import { setGlobalAIEnhancer } from '../tools/localExplore.js';
|
|
40
40
|
import { createProvider } from '../providers/providerFactory.js';
|
|
@@ -101,7 +101,6 @@ export class InteractiveShell {
|
|
|
101
101
|
ctrlCHandledThisPress = false;
|
|
102
102
|
pendingCleanup = null;
|
|
103
103
|
cleanupInProgress = false;
|
|
104
|
-
slashPreviewVisible = false;
|
|
105
104
|
lastLoggedPrompt = null;
|
|
106
105
|
lastLoggedPromptAt = 0;
|
|
107
106
|
skillRepository;
|
|
@@ -119,6 +118,7 @@ export class InteractiveShell {
|
|
|
119
118
|
statusSubscription = null;
|
|
120
119
|
followUpQueue = [];
|
|
121
120
|
isDrainingQueue = false;
|
|
121
|
+
apiKeyGateActive = false;
|
|
122
122
|
activeContextWindowTokens = null;
|
|
123
123
|
latestTokenUsage = { used: null, limit: null };
|
|
124
124
|
planApprovalBridgeRegistered = false;
|
|
@@ -128,6 +128,8 @@ export class InteractiveShell {
|
|
|
128
128
|
autosaveEnabled;
|
|
129
129
|
autoContinueEnabled;
|
|
130
130
|
verificationEnabled = true;
|
|
131
|
+
alphaZeroModeEnabled;
|
|
132
|
+
alphaZeroVerificationSnapshot = null;
|
|
131
133
|
editGuardMode = 'display-edits';
|
|
132
134
|
pendingPermissionInput = null;
|
|
133
135
|
pendingHistoryLoad = null;
|
|
@@ -152,6 +154,8 @@ export class InteractiveShell {
|
|
|
152
154
|
// Auto-build tracking
|
|
153
155
|
autoBuildInFlight = false;
|
|
154
156
|
lastAutoBuildRun = null;
|
|
157
|
+
// Offsec AlphaZero tracking
|
|
158
|
+
offsecRunId = null;
|
|
155
159
|
// Streaming UX tracking
|
|
156
160
|
streamingHeartbeatStart = null;
|
|
157
161
|
streamingHeartbeatFrame = 0;
|
|
@@ -159,6 +163,7 @@ export class InteractiveShell {
|
|
|
159
163
|
lastStreamingElapsedSeconds = null; // Preserve final elapsed time
|
|
160
164
|
statusLineState = null;
|
|
161
165
|
statusMessageOverride = null;
|
|
166
|
+
hasShownThoughtProcess = false;
|
|
162
167
|
promptRefreshTimer = null;
|
|
163
168
|
launchPaletteShown = false;
|
|
164
169
|
version;
|
|
@@ -174,6 +179,7 @@ export class InteractiveShell {
|
|
|
174
179
|
this.thinkingMode = this.sessionPreferences.thinkingMode;
|
|
175
180
|
this.autosaveEnabled = this.sessionPreferences.autosave;
|
|
176
181
|
this.autoContinueEnabled = this.sessionPreferences.autoContinue;
|
|
182
|
+
this.alphaZeroModeEnabled = this.sessionPreferences.alphaZeroMode;
|
|
177
183
|
this.sessionRestoreConfig = config.sessionRestore ?? { mode: 'none' };
|
|
178
184
|
this._enabledPlugins = config.enabledPlugins ?? [];
|
|
179
185
|
this.version = config.version ?? '0.0.0';
|
|
@@ -224,6 +230,16 @@ export class InteractiveShell {
|
|
|
224
230
|
description: 'Show available and loaded plugins',
|
|
225
231
|
category: 'configuration',
|
|
226
232
|
});
|
|
233
|
+
this.slashCommands.push({
|
|
234
|
+
command: '/offsec',
|
|
235
|
+
description: 'AlphaZero offensive security run (start/status/next)',
|
|
236
|
+
category: 'automation',
|
|
237
|
+
});
|
|
238
|
+
this.slashCommands.push({
|
|
239
|
+
command: '/alphazero',
|
|
240
|
+
description: 'Toggle AlphaZero RL mode with full-cycle verification',
|
|
241
|
+
category: 'mode',
|
|
242
|
+
});
|
|
227
243
|
this.statusTracker = config.statusTracker;
|
|
228
244
|
this.ui = config.ui;
|
|
229
245
|
this.uiAdapter = config.ui.adapter;
|
|
@@ -235,7 +251,11 @@ export class InteractiveShell {
|
|
|
235
251
|
});
|
|
236
252
|
// Set up tool status callback to update status during tool execution
|
|
237
253
|
this.uiAdapter.setToolStatusCallback((status) => {
|
|
238
|
-
|
|
254
|
+
const statusText = status?.text ?? null;
|
|
255
|
+
if (statusText) {
|
|
256
|
+
this.terminalInput.recordRecentAction(`[tool] ${statusText}`);
|
|
257
|
+
}
|
|
258
|
+
this.updateStatusMessage(statusText, { logRecent: false });
|
|
239
259
|
});
|
|
240
260
|
this.skillRepository = new SkillRepository({
|
|
241
261
|
workingDir: this.workingDir,
|
|
@@ -255,6 +275,7 @@ export class InteractiveShell {
|
|
|
255
275
|
onToggleVerify: () => this.toggleVerificationMode(),
|
|
256
276
|
onToggleAutoContinue: () => this.toggleAutoContinueMode(),
|
|
257
277
|
onToggleThinking: () => this.cycleThinkingMode(),
|
|
278
|
+
onToggleAlphaZero: () => this.toggleAlphaZeroMode('shortcut'),
|
|
258
279
|
onClearContext: () => this.handleClearContext(),
|
|
259
280
|
});
|
|
260
281
|
// Initialize Alpha Zero 2 metrics tracking
|
|
@@ -282,7 +303,7 @@ export class InteractiveShell {
|
|
|
282
303
|
this.terminalInput.streamContent(banner + '\n\n');
|
|
283
304
|
// Render chat box after banner is streamed
|
|
284
305
|
this.refreshControlBar();
|
|
285
|
-
this.
|
|
306
|
+
this.renderPromptArea(true);
|
|
286
307
|
this.rebuildAgent();
|
|
287
308
|
this.setupHandlers();
|
|
288
309
|
this.refreshBannerSessionInfo();
|
|
@@ -297,7 +318,13 @@ export class InteractiveShell {
|
|
|
297
318
|
this.parallelAgentDisplayLines = manager.formatDisplay();
|
|
298
319
|
// Trigger UI refresh if streaming
|
|
299
320
|
if (this.streamingHeartbeatStart) {
|
|
300
|
-
this.
|
|
321
|
+
this.uiUpdates.enqueue({
|
|
322
|
+
lane: 'stream',
|
|
323
|
+
mode: ['streaming', 'processing'],
|
|
324
|
+
coalesceKey: 'parallel-agents',
|
|
325
|
+
description: 'parallel agent status',
|
|
326
|
+
run: () => this.displayParallelAgents(),
|
|
327
|
+
});
|
|
301
328
|
}
|
|
302
329
|
};
|
|
303
330
|
manager.on('agent:started', updateDisplay);
|
|
@@ -378,7 +405,7 @@ export class InteractiveShell {
|
|
|
378
405
|
}
|
|
379
406
|
this.showLaunchCommandPalette();
|
|
380
407
|
// Ensure the terminal input is visible
|
|
381
|
-
this.
|
|
408
|
+
this.renderPromptArea();
|
|
382
409
|
}
|
|
383
410
|
showLaunchCommandPalette() {
|
|
384
411
|
// Disabled: Quick commands palette takes up too much space
|
|
@@ -475,9 +502,11 @@ export class InteractiveShell {
|
|
|
475
502
|
// Mode toggles
|
|
476
503
|
'/thinking',
|
|
477
504
|
'/autocontinue',
|
|
505
|
+
'/alphazero',
|
|
478
506
|
// Discovery and plugins
|
|
479
507
|
'/local', '/discover',
|
|
480
508
|
'/plugins',
|
|
509
|
+
'/offsec',
|
|
481
510
|
'/skills',
|
|
482
511
|
// Self-improvement
|
|
483
512
|
'/evolve', '/modular', '/a0',
|
|
@@ -507,7 +536,6 @@ export class InteractiveShell {
|
|
|
507
536
|
if (text.length > 0) {
|
|
508
537
|
this.resetCtrlCSequence();
|
|
509
538
|
}
|
|
510
|
-
this.handleSlashCommandPreviewChange();
|
|
511
539
|
}
|
|
512
540
|
/**
|
|
513
541
|
* Edit guard mode change handler (Shift+Tab from terminal input)
|
|
@@ -526,7 +554,7 @@ export class InteractiveShell {
|
|
|
526
554
|
display.showSystemMessage('โ๏ธ Display edits mode enabled.');
|
|
527
555
|
}
|
|
528
556
|
}
|
|
529
|
-
this.
|
|
557
|
+
this.renderPromptArea();
|
|
530
558
|
}
|
|
531
559
|
toggleVerificationMode() {
|
|
532
560
|
this.setVerificationMode(!this.verificationEnabled, 'shortcut');
|
|
@@ -539,8 +567,8 @@ export class InteractiveShell {
|
|
|
539
567
|
return;
|
|
540
568
|
}
|
|
541
569
|
const message = enabled
|
|
542
|
-
? 'โ
Verification on. Auto-tests will run after edits. (
|
|
543
|
-
: 'โญ๏ธ Verification off. Skipping auto-tests until re-enabled. (
|
|
570
|
+
? 'โ
Verification on. Auto-tests will run after edits. (Ctrl+Shift+V to toggle)'
|
|
571
|
+
: 'โญ๏ธ Verification off. Skipping auto-tests until re-enabled. (Ctrl+Shift+V to toggle)';
|
|
544
572
|
display.showSystemMessage(message);
|
|
545
573
|
}
|
|
546
574
|
toggleAutoContinueMode() {
|
|
@@ -561,10 +589,41 @@ export class InteractiveShell {
|
|
|
561
589
|
(this.autoContinueEnabled
|
|
562
590
|
? 'The model will be auto-prompted to continue when it expresses intent but does not use tools.'
|
|
563
591
|
: 'The model will not be auto-prompted to continue.') +
|
|
564
|
-
' Toggle with
|
|
592
|
+
' Toggle with Ctrl+Shift+C.');
|
|
593
|
+
}
|
|
594
|
+
toggleAlphaZeroMode(source = 'shortcut') {
|
|
595
|
+
this.setAlphaZeroMode(!this.alphaZeroModeEnabled, source);
|
|
596
|
+
}
|
|
597
|
+
setAlphaZeroMode(enabled, source) {
|
|
598
|
+
const changed = this.alphaZeroModeEnabled !== enabled;
|
|
599
|
+
this.alphaZeroModeEnabled = enabled;
|
|
600
|
+
saveSessionPreferences({ alphaZeroMode: this.alphaZeroModeEnabled });
|
|
601
|
+
// Force verification on while AlphaZero mode is active to guarantee deep checks
|
|
602
|
+
if (enabled) {
|
|
603
|
+
if (this.alphaZeroVerificationSnapshot === null) {
|
|
604
|
+
this.alphaZeroVerificationSnapshot = this.verificationEnabled;
|
|
605
|
+
}
|
|
606
|
+
if (!this.verificationEnabled) {
|
|
607
|
+
this.setVerificationMode(true, 'command');
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
else if (this.alphaZeroVerificationSnapshot !== null) {
|
|
611
|
+
this.setVerificationMode(this.alphaZeroVerificationSnapshot, 'command');
|
|
612
|
+
this.alphaZeroVerificationSnapshot = null;
|
|
613
|
+
}
|
|
614
|
+
this.refreshControlBar();
|
|
615
|
+
if (!changed && source === 'shortcut') {
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
if (enabled) {
|
|
619
|
+
display.showSystemMessage('โ AlphaZero RL mode enabled. Difficult prompts will use the duel/self-critique playbook with full lifecycle verification.');
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
display.showInfo('AlphaZero RL mode disabled. Returning to standard flow.');
|
|
623
|
+
}
|
|
565
624
|
}
|
|
566
625
|
/**
|
|
567
|
-
* Cycle through thinking modes (
|
|
626
|
+
* Cycle through thinking modes (Ctrl+Shift+T keyboard shortcut).
|
|
568
627
|
*/
|
|
569
628
|
cycleThinkingMode() {
|
|
570
629
|
const modes = ['concise', 'balanced', 'extended'];
|
|
@@ -640,7 +699,7 @@ export class InteractiveShell {
|
|
|
640
699
|
if (['n', 'no', 'cancel', '/cancel'].includes(lower)) {
|
|
641
700
|
this.pendingPermissionInput = null;
|
|
642
701
|
display.showInfo('Request cancelled.');
|
|
643
|
-
this.
|
|
702
|
+
this.renderPromptArea();
|
|
644
703
|
return null;
|
|
645
704
|
}
|
|
646
705
|
// Treat any other input as a replacement request that also needs confirmation
|
|
@@ -658,7 +717,7 @@ export class InteractiveShell {
|
|
|
658
717
|
]
|
|
659
718
|
.filter(Boolean)
|
|
660
719
|
.join('\n'));
|
|
661
|
-
this.
|
|
720
|
+
this.renderPromptArea();
|
|
662
721
|
}
|
|
663
722
|
/**
|
|
664
723
|
* Handle Ctrl+C presses in three stages:
|
|
@@ -673,7 +732,7 @@ export class InteractiveShell {
|
|
|
673
732
|
this.clearChatInput();
|
|
674
733
|
const prefix = hadBuffer ? 'Input cleared.' : 'Nothing to clear.';
|
|
675
734
|
display.showSystemMessage(`${prefix} Press Ctrl+C again to pause the AI; a third time quits.`);
|
|
676
|
-
this.
|
|
735
|
+
this.renderPromptArea();
|
|
677
736
|
return;
|
|
678
737
|
}
|
|
679
738
|
if (this.ctrlCPressCount === 2) {
|
|
@@ -774,8 +833,11 @@ export class InteractiveShell {
|
|
|
774
833
|
/**
|
|
775
834
|
* Update status bar message
|
|
776
835
|
*/
|
|
777
|
-
updateStatusMessage(message) {
|
|
836
|
+
updateStatusMessage(message, options = {}) {
|
|
778
837
|
this.statusMessageOverride = message;
|
|
838
|
+
if (message && options.logRecent !== false) {
|
|
839
|
+
this.terminalInput.recordRecentAction(`[status] ${message}`);
|
|
840
|
+
}
|
|
779
841
|
// During streaming we still want the spinner prefix; when idle force a fast refresh.
|
|
780
842
|
this.refreshStatusLine(!this.isProcessing);
|
|
781
843
|
}
|
|
@@ -787,26 +849,26 @@ export class InteractiveShell {
|
|
|
787
849
|
const trimmed = input.trim();
|
|
788
850
|
if (!trimmed) {
|
|
789
851
|
display.showWarning('Enter a number, "save", "defaults", or "cancel".');
|
|
790
|
-
this.
|
|
852
|
+
this.renderPromptArea();
|
|
791
853
|
return;
|
|
792
854
|
}
|
|
793
855
|
const normalized = trimmed.toLowerCase();
|
|
794
856
|
if (normalized === 'cancel') {
|
|
795
857
|
this.pendingInteraction = null;
|
|
796
858
|
display.showInfo('Tool selection cancelled.');
|
|
797
|
-
this.
|
|
859
|
+
this.renderPromptArea();
|
|
798
860
|
return;
|
|
799
861
|
}
|
|
800
862
|
if (normalized === 'defaults') {
|
|
801
863
|
pending.selection = buildEnabledToolSet(null);
|
|
802
864
|
this.renderToolMenu(pending);
|
|
803
|
-
this.
|
|
865
|
+
this.renderPromptArea();
|
|
804
866
|
return;
|
|
805
867
|
}
|
|
806
868
|
if (normalized === 'save') {
|
|
807
869
|
await this.persistToolSelection(pending);
|
|
808
870
|
this.pendingInteraction = null;
|
|
809
|
-
this.
|
|
871
|
+
this.renderPromptArea();
|
|
810
872
|
return;
|
|
811
873
|
}
|
|
812
874
|
const choice = Number.parseInt(trimmed, 10);
|
|
@@ -824,11 +886,11 @@ export class InteractiveShell {
|
|
|
824
886
|
}
|
|
825
887
|
this.renderToolMenu(pending);
|
|
826
888
|
}
|
|
827
|
-
this.
|
|
889
|
+
this.renderPromptArea();
|
|
828
890
|
return;
|
|
829
891
|
}
|
|
830
892
|
display.showWarning('Enter a number, "save", "defaults", or "cancel".');
|
|
831
|
-
this.
|
|
893
|
+
this.renderPromptArea();
|
|
832
894
|
}
|
|
833
895
|
async persistToolSelection(interaction) {
|
|
834
896
|
if (setsEqual(interaction.selection, interaction.initialSelection)) {
|
|
@@ -855,36 +917,36 @@ export class InteractiveShell {
|
|
|
855
917
|
if (!this.agentMenu) {
|
|
856
918
|
this.pendingInteraction = null;
|
|
857
919
|
display.showWarning('Agent selection is unavailable in this CLI.');
|
|
858
|
-
this.
|
|
920
|
+
this.renderPromptArea();
|
|
859
921
|
return;
|
|
860
922
|
}
|
|
861
923
|
const trimmed = input.trim();
|
|
862
924
|
if (!trimmed) {
|
|
863
925
|
display.showWarning('Enter a number or type "cancel".');
|
|
864
|
-
this.
|
|
926
|
+
this.renderPromptArea();
|
|
865
927
|
return;
|
|
866
928
|
}
|
|
867
929
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
868
930
|
this.pendingInteraction = null;
|
|
869
931
|
display.showInfo('Agent selection cancelled.');
|
|
870
|
-
this.
|
|
932
|
+
this.renderPromptArea();
|
|
871
933
|
return;
|
|
872
934
|
}
|
|
873
935
|
const choice = Number.parseInt(trimmed, 10);
|
|
874
936
|
if (!Number.isFinite(choice)) {
|
|
875
937
|
display.showWarning('Please enter a valid number.');
|
|
876
|
-
this.
|
|
938
|
+
this.renderPromptArea();
|
|
877
939
|
return;
|
|
878
940
|
}
|
|
879
941
|
const option = pending.options[choice - 1];
|
|
880
942
|
if (!option) {
|
|
881
943
|
display.showWarning('That option is not available.');
|
|
882
|
-
this.
|
|
944
|
+
this.renderPromptArea();
|
|
883
945
|
return;
|
|
884
946
|
}
|
|
885
947
|
await this.persistAgentSelection(option.name);
|
|
886
948
|
this.pendingInteraction = null;
|
|
887
|
-
this.
|
|
949
|
+
this.renderPromptArea();
|
|
888
950
|
}
|
|
889
951
|
async persistAgentSelection(profileName) {
|
|
890
952
|
if (!this.agentMenu) {
|
|
@@ -957,7 +1019,7 @@ export class InteractiveShell {
|
|
|
957
1019
|
lines.push(` ${theme.primary('[text]')} Submit your own solution instead`);
|
|
958
1020
|
lines.push('');
|
|
959
1021
|
display.showSystemMessage(lines.join('\n'));
|
|
960
|
-
this.
|
|
1022
|
+
this.renderPromptArea();
|
|
961
1023
|
}
|
|
962
1024
|
async handlePlanApprovalInput(input) {
|
|
963
1025
|
const pending = this.pendingInteraction;
|
|
@@ -966,7 +1028,7 @@ export class InteractiveShell {
|
|
|
966
1028
|
const trimmed = input.trim();
|
|
967
1029
|
if (!trimmed) {
|
|
968
1030
|
display.showWarning('Enter a command or your own solution.');
|
|
969
|
-
this.
|
|
1031
|
+
this.renderPromptArea();
|
|
970
1032
|
return;
|
|
971
1033
|
}
|
|
972
1034
|
const lower = trimmed.toLowerCase();
|
|
@@ -974,7 +1036,7 @@ export class InteractiveShell {
|
|
|
974
1036
|
if (lower === 'cancel' || lower === 'c') {
|
|
975
1037
|
this.pendingInteraction = null;
|
|
976
1038
|
display.showInfo('Plan cancelled. You can continue with a different approach.');
|
|
977
|
-
this.
|
|
1039
|
+
this.renderPromptArea();
|
|
978
1040
|
return;
|
|
979
1041
|
}
|
|
980
1042
|
// Select all
|
|
@@ -994,7 +1056,7 @@ export class InteractiveShell {
|
|
|
994
1056
|
const selectedSteps = pending.steps.filter(s => pending.selectedSteps.has(s.id));
|
|
995
1057
|
if (selectedSteps.length === 0) {
|
|
996
1058
|
display.showWarning('No steps selected. Select steps or enter your own solution.');
|
|
997
|
-
this.
|
|
1059
|
+
this.renderPromptArea();
|
|
998
1060
|
return;
|
|
999
1061
|
}
|
|
1000
1062
|
this.pendingInteraction = null;
|
|
@@ -1027,15 +1089,17 @@ export class InteractiveShell {
|
|
|
1027
1089
|
return;
|
|
1028
1090
|
}
|
|
1029
1091
|
display.showWarning('Invalid input. Enter a step number, command (go/cancel/all/none), or your own solution.');
|
|
1030
|
-
this.
|
|
1092
|
+
this.renderPromptArea();
|
|
1031
1093
|
}
|
|
1032
1094
|
setupHandlers() {
|
|
1033
1095
|
// Handle terminal resize
|
|
1034
1096
|
output.on('resize', () => {
|
|
1097
|
+
this.terminalInput.resetContentPosition();
|
|
1035
1098
|
this.terminalInput.handleResize();
|
|
1099
|
+
this.terminalInput.forceRender();
|
|
1036
1100
|
});
|
|
1037
1101
|
// Show initial input UI
|
|
1038
|
-
this.
|
|
1102
|
+
this.renderPromptArea();
|
|
1039
1103
|
}
|
|
1040
1104
|
/**
|
|
1041
1105
|
* Set up command autocomplete with all available slash commands.
|
|
@@ -1066,6 +1130,14 @@ export class InteractiveShell {
|
|
|
1066
1130
|
catch {
|
|
1067
1131
|
// Custom commands are optional
|
|
1068
1132
|
}
|
|
1133
|
+
// Add manual commands that are not yet in the schema
|
|
1134
|
+
if (!commands.some((cmd) => cmd.command === '/alphazero')) {
|
|
1135
|
+
commands.push({
|
|
1136
|
+
command: '/alphazero',
|
|
1137
|
+
description: 'Toggle AlphaZero RL mode',
|
|
1138
|
+
category: 'mode',
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1069
1141
|
// Sort commands alphabetically
|
|
1070
1142
|
commands.sort((a, b) => a.command.localeCompare(b.command));
|
|
1071
1143
|
this.terminalInput.setAvailableCommands(commands);
|
|
@@ -1106,7 +1178,16 @@ export class InteractiveShell {
|
|
|
1106
1178
|
const parts = detail?.trim() ? [detail.trim()] : [];
|
|
1107
1179
|
const queued = this.followUpQueue.length;
|
|
1108
1180
|
if (queued > 0) {
|
|
1109
|
-
|
|
1181
|
+
const nextText = this.followUpQueue[0]?.text ?? '';
|
|
1182
|
+
const normalized = nextText.replace(/\s+/g, ' ').trim();
|
|
1183
|
+
const previewLimit = 48;
|
|
1184
|
+
const preview = normalized
|
|
1185
|
+
? normalized.length > previewLimit
|
|
1186
|
+
? `${normalized.slice(0, previewLimit - 1)}โฆ`
|
|
1187
|
+
: normalized
|
|
1188
|
+
: '';
|
|
1189
|
+
const suffix = preview ? ` (next: ${preview})` : '';
|
|
1190
|
+
parts.push(`${queued} follow-up${queued === 1 ? '' : 's'} queued${suffix}`);
|
|
1110
1191
|
}
|
|
1111
1192
|
return parts.join(' โข ');
|
|
1112
1193
|
}
|
|
@@ -1133,27 +1214,55 @@ export class InteractiveShell {
|
|
|
1133
1214
|
this.terminalInput.setModeToggles({
|
|
1134
1215
|
verificationEnabled: this.verificationEnabled,
|
|
1135
1216
|
autoContinueEnabled: this.autoContinueEnabled,
|
|
1136
|
-
verificationHotkey: '
|
|
1137
|
-
autoContinueHotkey: '
|
|
1217
|
+
verificationHotkey: 'ctrl+shift+v',
|
|
1218
|
+
autoContinueHotkey: 'ctrl+shift+c',
|
|
1138
1219
|
thinkingModeLabel: this.thinkingMode,
|
|
1139
|
-
thinkingHotkey: '
|
|
1220
|
+
thinkingHotkey: 'ctrl+shift+t',
|
|
1221
|
+
alphaZeroEnabled: this.alphaZeroModeEnabled,
|
|
1222
|
+
alphaZeroHotkey: 'ctrl+shift+a',
|
|
1223
|
+
alphaZeroLabel: 'AlphaZero RL',
|
|
1140
1224
|
});
|
|
1141
1225
|
this.refreshStatusLine();
|
|
1142
|
-
this.
|
|
1226
|
+
this.renderPromptArea();
|
|
1143
1227
|
}
|
|
1144
1228
|
writeLocked(content) {
|
|
1145
1229
|
if (!content) {
|
|
1146
1230
|
return;
|
|
1147
1231
|
}
|
|
1148
|
-
//
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1232
|
+
// Route through display stream so scroll regions and streaming locks stay in sync
|
|
1233
|
+
display.stream(content);
|
|
1234
|
+
}
|
|
1235
|
+
isStreamingUiActive() {
|
|
1236
|
+
return this.streamingHeartbeatStart !== null;
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Render the prompt/control bar. During streaming, rely on the streaming frame
|
|
1240
|
+
* renderer and enqueue through the UIUpdateCoordinator to avoid fighting the
|
|
1241
|
+
* scroll region or duplicating the prompt.
|
|
1242
|
+
*/
|
|
1243
|
+
renderPromptArea(force = false) {
|
|
1244
|
+
if (this.isStreamingUiActive()) {
|
|
1245
|
+
this.uiUpdates.enqueue({
|
|
1246
|
+
lane: 'prompt',
|
|
1247
|
+
mode: ['streaming', 'processing'],
|
|
1248
|
+
coalesceKey: 'prompt:streaming-frame',
|
|
1249
|
+
description: 'render streaming prompt frame',
|
|
1250
|
+
run: () => {
|
|
1251
|
+
if (force) {
|
|
1252
|
+
this.terminalInput.renderStreamingFrame(true);
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
this.terminalInput.renderStreamingFrame();
|
|
1256
|
+
},
|
|
1257
|
+
});
|
|
1152
1258
|
return;
|
|
1153
1259
|
}
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
}
|
|
1260
|
+
if (force) {
|
|
1261
|
+
this.terminalInput.forceRender();
|
|
1262
|
+
}
|
|
1263
|
+
else {
|
|
1264
|
+
this.terminalInput.render();
|
|
1265
|
+
}
|
|
1157
1266
|
}
|
|
1158
1267
|
/**
|
|
1159
1268
|
* Refresh the status line in the persistent input area.
|
|
@@ -1199,7 +1308,7 @@ export class InteractiveShell {
|
|
|
1199
1308
|
provider: this.providerLabel(this.sessionState.provider),
|
|
1200
1309
|
});
|
|
1201
1310
|
if (forceRender) {
|
|
1202
|
-
this.
|
|
1311
|
+
this.renderPromptArea(true);
|
|
1203
1312
|
}
|
|
1204
1313
|
}
|
|
1205
1314
|
/**
|
|
@@ -1232,45 +1341,11 @@ export class InteractiveShell {
|
|
|
1232
1341
|
}
|
|
1233
1342
|
return parts.join(' โข ');
|
|
1234
1343
|
}
|
|
1235
|
-
handleSlashCommandPreviewChange() {
|
|
1236
|
-
if (this.pendingInteraction) {
|
|
1237
|
-
this.slashPreviewVisible = false;
|
|
1238
|
-
return;
|
|
1239
|
-
}
|
|
1240
|
-
const shouldShow = this.shouldShowSlashCommandPreview();
|
|
1241
|
-
if (shouldShow && !this.slashPreviewVisible) {
|
|
1242
|
-
this.slashPreviewVisible = true;
|
|
1243
|
-
this.showSlashCommandPreview();
|
|
1244
|
-
return;
|
|
1245
|
-
}
|
|
1246
|
-
if (!shouldShow && this.slashPreviewVisible) {
|
|
1247
|
-
this.slashPreviewVisible = false;
|
|
1248
|
-
this.uiAdapter.hideSlashCommandPreview();
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
shouldShowSlashCommandPreview() {
|
|
1252
|
-
const line = this.currentInput ?? '';
|
|
1253
|
-
if (!line.trim()) {
|
|
1254
|
-
return false;
|
|
1255
|
-
}
|
|
1256
|
-
const trimmed = line.trimStart();
|
|
1257
|
-
return trimmed.startsWith('/');
|
|
1258
|
-
}
|
|
1259
|
-
showSlashCommandPreview() {
|
|
1260
|
-
// Filter commands based on current input
|
|
1261
|
-
const line = this.currentInput ?? '';
|
|
1262
|
-
const trimmed = line.trimStart();
|
|
1263
|
-
// Filter commands that match the current input
|
|
1264
|
-
const filtered = this.slashCommands.filter(cmd => cmd.command.startsWith(trimmed) || trimmed === '/');
|
|
1265
|
-
// Show in the unified UI with dynamic overlay
|
|
1266
|
-
this.uiAdapter.showSlashCommandPreview(filtered);
|
|
1267
|
-
// Don't reprompt - this causes flickering
|
|
1268
|
-
}
|
|
1269
1344
|
/**
|
|
1270
1345
|
* Ensure the terminal input is ready for interactive input.
|
|
1271
1346
|
*/
|
|
1272
1347
|
ensureReadlineReady() {
|
|
1273
|
-
this.
|
|
1348
|
+
this.renderPromptArea();
|
|
1274
1349
|
}
|
|
1275
1350
|
/**
|
|
1276
1351
|
* Log user prompt to the scroll region so it's part of the conversation flow.
|
|
@@ -1292,7 +1367,7 @@ export class InteractiveShell {
|
|
|
1292
1367
|
}
|
|
1293
1368
|
requestPromptRefresh(force = false) {
|
|
1294
1369
|
if (force) {
|
|
1295
|
-
this.
|
|
1370
|
+
this.renderPromptArea(true);
|
|
1296
1371
|
return;
|
|
1297
1372
|
}
|
|
1298
1373
|
if (this.promptRefreshTimer) {
|
|
@@ -1300,7 +1375,7 @@ export class InteractiveShell {
|
|
|
1300
1375
|
}
|
|
1301
1376
|
this.promptRefreshTimer = setTimeout(() => {
|
|
1302
1377
|
this.promptRefreshTimer = null;
|
|
1303
|
-
this.
|
|
1378
|
+
this.renderPromptArea();
|
|
1304
1379
|
}, 48);
|
|
1305
1380
|
}
|
|
1306
1381
|
clearPromptRefreshTimer() {
|
|
@@ -1309,6 +1384,25 @@ export class InteractiveShell {
|
|
|
1309
1384
|
this.promptRefreshTimer = null;
|
|
1310
1385
|
}
|
|
1311
1386
|
}
|
|
1387
|
+
async withStreamingUi(label, run) {
|
|
1388
|
+
if (this.isStreamingUiActive()) {
|
|
1389
|
+
return run();
|
|
1390
|
+
}
|
|
1391
|
+
this.terminalInput.setStreaming(true);
|
|
1392
|
+
this.startStreamingHeartbeat(label);
|
|
1393
|
+
try {
|
|
1394
|
+
return await run();
|
|
1395
|
+
}
|
|
1396
|
+
finally {
|
|
1397
|
+
this.stopStreamingHeartbeat();
|
|
1398
|
+
this.terminalInput.setStreaming(false);
|
|
1399
|
+
const nextMode = this.isProcessing ? 'processing' : 'idle';
|
|
1400
|
+
this.uiUpdates.setMode(nextMode);
|
|
1401
|
+
if (nextMode === 'processing') {
|
|
1402
|
+
queueMicrotask(() => this.uiUpdates.setMode('idle'));
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1312
1406
|
startStreamingHeartbeat(label = 'Streaming') {
|
|
1313
1407
|
this.stopStreamingHeartbeat();
|
|
1314
1408
|
// Enter global streaming mode - blocks all non-streaming UI output
|
|
@@ -1389,7 +1483,7 @@ export class InteractiveShell {
|
|
|
1389
1483
|
else {
|
|
1390
1484
|
this.setIdleStatus();
|
|
1391
1485
|
}
|
|
1392
|
-
this.
|
|
1486
|
+
this.renderPromptArea();
|
|
1393
1487
|
}
|
|
1394
1488
|
enqueueFollowUpAction(action) {
|
|
1395
1489
|
this.followUpQueue.push(action);
|
|
@@ -1408,7 +1502,7 @@ export class InteractiveShell {
|
|
|
1408
1502
|
this.refreshQueueIndicators();
|
|
1409
1503
|
this.scheduleQueueProcessing();
|
|
1410
1504
|
// Re-show the prompt so user can continue typing more follow-ups
|
|
1411
|
-
this.
|
|
1505
|
+
this.renderPromptArea();
|
|
1412
1506
|
}
|
|
1413
1507
|
scheduleQueueProcessing() {
|
|
1414
1508
|
if (!this.followUpQueue.length) {
|
|
@@ -1449,8 +1543,6 @@ export class InteractiveShell {
|
|
|
1449
1543
|
}
|
|
1450
1544
|
}
|
|
1451
1545
|
async processInputBlock(line, _wasRapidMultiLine = false) {
|
|
1452
|
-
this.slashPreviewVisible = false;
|
|
1453
|
-
this.uiAdapter.hideSlashCommandPreview();
|
|
1454
1546
|
const trimmed = line.trim();
|
|
1455
1547
|
if (await this.handlePendingInteraction(trimmed)) {
|
|
1456
1548
|
return;
|
|
@@ -1465,12 +1557,12 @@ export class InteractiveShell {
|
|
|
1465
1557
|
}
|
|
1466
1558
|
if (lower === 'clear') {
|
|
1467
1559
|
display.clear();
|
|
1468
|
-
this.
|
|
1560
|
+
this.renderPromptArea();
|
|
1469
1561
|
return;
|
|
1470
1562
|
}
|
|
1471
1563
|
if (lower === 'help') {
|
|
1472
1564
|
this.showHelp();
|
|
1473
|
-
this.
|
|
1565
|
+
this.renderPromptArea();
|
|
1474
1566
|
return;
|
|
1475
1567
|
}
|
|
1476
1568
|
if (trimmed.startsWith('/')) {
|
|
@@ -1480,12 +1572,12 @@ export class InteractiveShell {
|
|
|
1480
1572
|
// Check for continuous/infinite loop commands
|
|
1481
1573
|
if (this.isContinuousCommand(trimmed)) {
|
|
1482
1574
|
await this.processContinuousRequest(trimmed);
|
|
1483
|
-
this.
|
|
1575
|
+
this.renderPromptArea();
|
|
1484
1576
|
return;
|
|
1485
1577
|
}
|
|
1486
1578
|
// Direct execution for all inputs, including multi-line pastes
|
|
1487
1579
|
await this.processRequest(trimmed);
|
|
1488
|
-
this.
|
|
1580
|
+
this.renderPromptArea();
|
|
1489
1581
|
}
|
|
1490
1582
|
/**
|
|
1491
1583
|
* Check if the command is a continuous/infinite loop command
|
|
@@ -1523,6 +1615,60 @@ export class InteractiveShell {
|
|
|
1523
1615
|
];
|
|
1524
1616
|
return patterns.some(pattern => pattern.test(lower));
|
|
1525
1617
|
}
|
|
1618
|
+
isDifficultProblem(input) {
|
|
1619
|
+
const normalized = input.toLowerCase();
|
|
1620
|
+
const wordCount = normalized.split(/\s+/).filter(Boolean).length;
|
|
1621
|
+
if (normalized.length > 600 || wordCount > 80) {
|
|
1622
|
+
return true;
|
|
1623
|
+
}
|
|
1624
|
+
const signals = [
|
|
1625
|
+
'root cause',
|
|
1626
|
+
'postmortem',
|
|
1627
|
+
'crash',
|
|
1628
|
+
'incident',
|
|
1629
|
+
'outage',
|
|
1630
|
+
'optimiz',
|
|
1631
|
+
'performance',
|
|
1632
|
+
'throughput',
|
|
1633
|
+
'latency',
|
|
1634
|
+
'scalab',
|
|
1635
|
+
'architecture',
|
|
1636
|
+
'rewrite',
|
|
1637
|
+
'migration',
|
|
1638
|
+
'refactor',
|
|
1639
|
+
'reverse engineer',
|
|
1640
|
+
'security',
|
|
1641
|
+
'exploit',
|
|
1642
|
+
'injection',
|
|
1643
|
+
'vulnerability',
|
|
1644
|
+
'compliance',
|
|
1645
|
+
'multi-step',
|
|
1646
|
+
'complex',
|
|
1647
|
+
'difficult',
|
|
1648
|
+
'hard problem',
|
|
1649
|
+
'debug',
|
|
1650
|
+
'trace',
|
|
1651
|
+
'profil',
|
|
1652
|
+
'bottleneck',
|
|
1653
|
+
];
|
|
1654
|
+
return signals.some((signal) => normalized.includes(signal));
|
|
1655
|
+
}
|
|
1656
|
+
buildAlphaZeroPrompt(request, flaggedDifficult) {
|
|
1657
|
+
const playbook = [
|
|
1658
|
+
'AlphaZero RL MODE is ACTIVE. Operate as a self-play reinforcement loop.',
|
|
1659
|
+
flaggedDifficult
|
|
1660
|
+
? 'Treat this as a difficult, high-risk task and over-verify the result.'
|
|
1661
|
+
: 'Apply the reinforcement loop even if the task looks small.',
|
|
1662
|
+
'Follow this closed-loop playbook:',
|
|
1663
|
+
'- Draft two competing solution strategies and merge the strongest ideas before executing.',
|
|
1664
|
+
'- Execute with tools while logging decisions and evidence.',
|
|
1665
|
+
'- Self-critique and repair until the quality is excellent (aim โฅ90/100).',
|
|
1666
|
+
'- Run full-lifecycle verification like a human reviewer: build/tests, manual sanity checks, edge cases, performance/safety/security probes, docs/UX/readiness notes.',
|
|
1667
|
+
'- Keep a verification ledger: each check with PASS/FAIL, evidence, and remaining risks. If anything fails, fix and re-verify before claiming completion.',
|
|
1668
|
+
'Finish with a concise sign-off that lists what was achieved and the proof of completion.',
|
|
1669
|
+
];
|
|
1670
|
+
return `${playbook.join('\n')}\n\nPrimary user request:\n${request.trim()}`;
|
|
1671
|
+
}
|
|
1526
1672
|
async handlePendingInteraction(input) {
|
|
1527
1673
|
if (!this.pendingInteraction) {
|
|
1528
1674
|
return false;
|
|
@@ -1530,7 +1676,7 @@ export class InteractiveShell {
|
|
|
1530
1676
|
switch (this.pendingInteraction.type) {
|
|
1531
1677
|
case 'model-loading':
|
|
1532
1678
|
display.showInfo('Still fetching model options. Please wait a moment.');
|
|
1533
|
-
this.
|
|
1679
|
+
this.renderPromptArea();
|
|
1534
1680
|
return true;
|
|
1535
1681
|
case 'model-provider':
|
|
1536
1682
|
await this.handleModelProviderSelection(input);
|
|
@@ -1561,7 +1707,7 @@ export class InteractiveShell {
|
|
|
1561
1707
|
const [command] = input.split(/\s+/);
|
|
1562
1708
|
if (!command) {
|
|
1563
1709
|
display.showWarning('Enter a slash command.');
|
|
1564
|
-
this.
|
|
1710
|
+
this.renderPromptArea();
|
|
1565
1711
|
return;
|
|
1566
1712
|
}
|
|
1567
1713
|
switch (command) {
|
|
@@ -1619,6 +1765,9 @@ export class InteractiveShell {
|
|
|
1619
1765
|
case '/autocontinue':
|
|
1620
1766
|
this.handleAutoContinueCommand(input);
|
|
1621
1767
|
break;
|
|
1768
|
+
case '/alphazero':
|
|
1769
|
+
this.handleAlphaZeroCommand(input);
|
|
1770
|
+
break;
|
|
1622
1771
|
case '/shortcuts':
|
|
1623
1772
|
case '/keys':
|
|
1624
1773
|
this.handleShortcutsCommand();
|
|
@@ -1646,6 +1795,9 @@ export class InteractiveShell {
|
|
|
1646
1795
|
case '/a0':
|
|
1647
1796
|
void this.handleModularCommand(input);
|
|
1648
1797
|
break;
|
|
1798
|
+
case '/offsec':
|
|
1799
|
+
void this.handleOffsecCommand(input);
|
|
1800
|
+
break;
|
|
1649
1801
|
case '/test':
|
|
1650
1802
|
case '/tests':
|
|
1651
1803
|
void this.handleTestCommand(input);
|
|
@@ -1720,7 +1872,7 @@ export class InteractiveShell {
|
|
|
1720
1872
|
}
|
|
1721
1873
|
break;
|
|
1722
1874
|
}
|
|
1723
|
-
this.
|
|
1875
|
+
this.renderPromptArea();
|
|
1724
1876
|
}
|
|
1725
1877
|
async tryCustomSlashCommand(command, fullInput) {
|
|
1726
1878
|
const custom = this.customCommandMap.get(command);
|
|
@@ -1757,6 +1909,7 @@ export class InteractiveShell {
|
|
|
1757
1909
|
` ${theme.info('Option+V')} ${theme.ui.muted('Toggle verification')}`,
|
|
1758
1910
|
` ${theme.info('Option+C')} ${theme.ui.muted('Toggle auto-continue')}`,
|
|
1759
1911
|
` ${theme.info('Option+T')} ${theme.ui.muted('Cycle thinking mode')}`,
|
|
1912
|
+
` ${theme.info('Option+A')} ${theme.ui.muted('Toggle AlphaZero RL mode')}`,
|
|
1760
1913
|
` ${theme.info('Option+E')} ${theme.ui.muted('Toggle edit permission mode')}`,
|
|
1761
1914
|
` ${theme.info('Option+X')} ${theme.ui.muted('Clear/compact context')}`,
|
|
1762
1915
|
'',
|
|
@@ -2042,6 +2195,24 @@ export class InteractiveShell {
|
|
|
2042
2195
|
};
|
|
2043
2196
|
display.showInfo(`Thinking mode set to ${theme.info(value)} โ ${descriptions[this.thinkingMode]}`);
|
|
2044
2197
|
}
|
|
2198
|
+
handleAlphaZeroCommand(input) {
|
|
2199
|
+
const value = input.slice('/alphazero'.length).trim().toLowerCase();
|
|
2200
|
+
if (!value || value === 'status') {
|
|
2201
|
+
const status = this.alphaZeroModeEnabled ? theme.success('on') : theme.ui.muted('off');
|
|
2202
|
+
const verification = this.verificationEnabled ? 'verification locked on' : 'verification optional';
|
|
2203
|
+
display.showInfo(`AlphaZero RL mode is ${status}. When enabled, difficult prompts use duel/self-critique and human-style verification (${verification}).`);
|
|
2204
|
+
return;
|
|
2205
|
+
}
|
|
2206
|
+
if (['on', 'enable', 'enabled'].includes(value)) {
|
|
2207
|
+
this.setAlphaZeroMode(true, 'command');
|
|
2208
|
+
return;
|
|
2209
|
+
}
|
|
2210
|
+
if (['off', 'disable', 'disabled'].includes(value)) {
|
|
2211
|
+
this.setAlphaZeroMode(false, 'command');
|
|
2212
|
+
return;
|
|
2213
|
+
}
|
|
2214
|
+
display.showWarning('Usage: /alphazero [on|off|status]');
|
|
2215
|
+
}
|
|
2045
2216
|
handleShortcutsCommand() {
|
|
2046
2217
|
// Display keyboard shortcuts help (Claude Code style)
|
|
2047
2218
|
display.showSystemMessage(formatShortcutsHelp());
|
|
@@ -2907,6 +3078,150 @@ export class InteractiveShell {
|
|
|
2907
3078
|
display.showInfo('Note: /modular is now part of /evolve. Use /evolve tokens, /evolve targets, etc.');
|
|
2908
3079
|
await this.handleEvolveCommand(evolveInput);
|
|
2909
3080
|
}
|
|
3081
|
+
/**
|
|
3082
|
+
* Handle /offsec command - AlphaZero offensive security run helper
|
|
3083
|
+
*/
|
|
3084
|
+
async handleOffsecCommand(input) {
|
|
3085
|
+
const args = input.trim().split(/\s+/).slice(1);
|
|
3086
|
+
const sub = (args[0]?.toLowerCase() ?? 'status');
|
|
3087
|
+
const usage = 'Usage: /offsec start <objective> [--scope target1,target2]\n' +
|
|
3088
|
+
' /offsec status [runId]\n' +
|
|
3089
|
+
' /offsec next [count]\n' +
|
|
3090
|
+
' /offsec auto [steps]\n' +
|
|
3091
|
+
' /offsec win|fail|detect <actionId> [note]\n' +
|
|
3092
|
+
' /offsec resume <runId>\n' +
|
|
3093
|
+
' /offsec runs';
|
|
3094
|
+
const loadRun = (explicitId) => {
|
|
3095
|
+
const run = resumeOffsecRun(explicitId ?? this.offsecRunId);
|
|
3096
|
+
if (!run) {
|
|
3097
|
+
display.showWarning('No offsec run found. Start one with /offsec start "<objective>".');
|
|
3098
|
+
}
|
|
3099
|
+
return run;
|
|
3100
|
+
};
|
|
3101
|
+
if (sub === 'start') {
|
|
3102
|
+
const rest = args.slice(1);
|
|
3103
|
+
const scope = [];
|
|
3104
|
+
const objectiveParts = [];
|
|
3105
|
+
for (let i = 0; i < rest.length; i++) {
|
|
3106
|
+
if (rest[i]?.toLowerCase() === '--scope') {
|
|
3107
|
+
const scopeArg = rest[i + 1];
|
|
3108
|
+
if (scopeArg) {
|
|
3109
|
+
scope.push(...scopeArg.split(',').map((s) => s.trim()).filter(Boolean));
|
|
3110
|
+
}
|
|
3111
|
+
i += 1;
|
|
3112
|
+
continue;
|
|
3113
|
+
}
|
|
3114
|
+
objectiveParts.push(rest[i]);
|
|
3115
|
+
}
|
|
3116
|
+
const objective = objectiveParts.join(' ').trim();
|
|
3117
|
+
if (!objective) {
|
|
3118
|
+
display.showWarning('Provide an objective. Example: /offsec start gain shell on api.example.com --scope api.example.com');
|
|
3119
|
+
display.showInfo(usage);
|
|
3120
|
+
return;
|
|
3121
|
+
}
|
|
3122
|
+
const run = startOffsecRun(objective, scope);
|
|
3123
|
+
this.offsecRunId = run.id;
|
|
3124
|
+
const next = getOffsecNextActions(run.id, 3);
|
|
3125
|
+
display.showSystemMessage(theme.gradient.primary('๐ก๏ธ Offsec AlphaZero run started'));
|
|
3126
|
+
display.showSystemMessage(formatOffsecStatus(run, next));
|
|
3127
|
+
return;
|
|
3128
|
+
}
|
|
3129
|
+
if (sub === 'resume') {
|
|
3130
|
+
const targetRun = args[1] ?? this.offsecRunId;
|
|
3131
|
+
const run = resumeOffsecRun(targetRun);
|
|
3132
|
+
if (!run) {
|
|
3133
|
+
display.showWarning(`No offsec run found for id ${targetRun ?? '<unset>'}`);
|
|
3134
|
+
return;
|
|
3135
|
+
}
|
|
3136
|
+
this.offsecRunId = run.id;
|
|
3137
|
+
display.showSystemMessage(theme.gradient.primary(`Resumed offsec run ${run.id}`));
|
|
3138
|
+
display.showSystemMessage(formatOffsecStatus(run, getOffsecNextActions(run.id, 3)));
|
|
3139
|
+
return;
|
|
3140
|
+
}
|
|
3141
|
+
if (sub === 'runs') {
|
|
3142
|
+
const runs = listOffsecRuns();
|
|
3143
|
+
if (runs.length === 0) {
|
|
3144
|
+
display.showInfo('No offsec runs recorded yet.');
|
|
3145
|
+
return;
|
|
3146
|
+
}
|
|
3147
|
+
const lines = [];
|
|
3148
|
+
lines.push(theme.gradient.primary('Recorded offsec runs'));
|
|
3149
|
+
for (const run of runs.slice(0, 10)) {
|
|
3150
|
+
lines.push(`- ${run.id} :: ${run.objective} (updated ${run.updatedAt})`);
|
|
3151
|
+
}
|
|
3152
|
+
if (runs.length > 10) {
|
|
3153
|
+
lines.push(`...and ${runs.length - 10} more`);
|
|
3154
|
+
}
|
|
3155
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3156
|
+
return;
|
|
3157
|
+
}
|
|
3158
|
+
const run = resumeOffsecRun(args[1] ?? this.offsecRunId);
|
|
3159
|
+
if (!run) {
|
|
3160
|
+
return;
|
|
3161
|
+
}
|
|
3162
|
+
this.offsecRunId = run.id;
|
|
3163
|
+
if (sub === 'status' || sub === 'help') {
|
|
3164
|
+
const next = getOffsecNextActions(run.id, 3);
|
|
3165
|
+
display.showSystemMessage(formatOffsecStatus(run, next));
|
|
3166
|
+
if (next.length === 0) {
|
|
3167
|
+
display.showInfo('No pending actions. Mark outcomes or start a new run.');
|
|
3168
|
+
}
|
|
3169
|
+
return;
|
|
3170
|
+
}
|
|
3171
|
+
if (sub === 'next') {
|
|
3172
|
+
const count = Number.isFinite(Number(args[1])) ? Math.max(1, parseInt(args[1], 10)) : 3;
|
|
3173
|
+
const next = getOffsecNextActions(run.id, count);
|
|
3174
|
+
if (next.length === 0) {
|
|
3175
|
+
display.showInfo('No pending actions to suggest.');
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
3178
|
+
const lines = [];
|
|
3179
|
+
lines.push(theme.gradient.primary(`Top ${next.length} actions`));
|
|
3180
|
+
for (const action of next) {
|
|
3181
|
+
lines.push(`- [${action.id}] ${action.label} (${action.category}) score=${action.score}`);
|
|
3182
|
+
lines.push(` cmd: ${action.command}`);
|
|
3183
|
+
lines.push(` path: ${action.path.join(' -> ')}`);
|
|
3184
|
+
}
|
|
3185
|
+
lines.push('Mark progress with /offsec win|fail|detect <actionId> [note]');
|
|
3186
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3187
|
+
return;
|
|
3188
|
+
}
|
|
3189
|
+
if (sub === 'auto') {
|
|
3190
|
+
const steps = Number.isFinite(Number(args[1])) ? Math.max(1, parseInt(args[1], 10)) : 5;
|
|
3191
|
+
const plan = simulateOffsecRollout(run.id, steps);
|
|
3192
|
+
if (plan.length === 0) {
|
|
3193
|
+
display.showInfo('No pending actions to simulate.');
|
|
3194
|
+
return;
|
|
3195
|
+
}
|
|
3196
|
+
const lines = [];
|
|
3197
|
+
lines.push(theme.gradient.primary(`Simulated ${plan.length} steps (AlphaZero-style rollout)`));
|
|
3198
|
+
for (const action of plan) {
|
|
3199
|
+
lines.push(`- [${action.id}] ${action.label} (${action.category}) score=${action.score}`);
|
|
3200
|
+
}
|
|
3201
|
+
lines.push('Use /offsec next to view updated ranking.');
|
|
3202
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3203
|
+
return;
|
|
3204
|
+
}
|
|
3205
|
+
if (sub === 'win' || sub === 'fail' || sub === 'detect') {
|
|
3206
|
+
const actionId = args[1];
|
|
3207
|
+
if (!actionId) {
|
|
3208
|
+
display.showWarning('Specify an action id. Example: /offsec win a3 "got shell via RCE"');
|
|
3209
|
+
return;
|
|
3210
|
+
}
|
|
3211
|
+
const note = args.slice(2).join(' ').trim();
|
|
3212
|
+
const outcome = sub === 'win' ? 'success' : sub === 'fail' ? 'fail' : 'detected';
|
|
3213
|
+
const updated = recordOffsecOutcome(run.id, actionId, outcome, note);
|
|
3214
|
+
if (!updated) {
|
|
3215
|
+
display.showWarning(`Action ${actionId} not found in run ${run.id}.`);
|
|
3216
|
+
return;
|
|
3217
|
+
}
|
|
3218
|
+
const next = getOffsecNextActions(run.id, 3);
|
|
3219
|
+
display.showSystemMessage(theme.success(`Recorded ${outcome} for ${actionId} in run ${run.id}`));
|
|
3220
|
+
display.showSystemMessage(formatOffsecStatus(updated, next));
|
|
3221
|
+
return;
|
|
3222
|
+
}
|
|
3223
|
+
display.showInfo(usage);
|
|
3224
|
+
}
|
|
2910
3225
|
/**
|
|
2911
3226
|
* Handle /test command for intelligent test flows
|
|
2912
3227
|
*/
|
|
@@ -3222,7 +3537,7 @@ export class InteractiveShell {
|
|
|
3222
3537
|
if (!value) {
|
|
3223
3538
|
// Show current status
|
|
3224
3539
|
display.showInfo(`Auto-continue is ${this.autoContinueEnabled ? 'enabled' : 'disabled'}. ` +
|
|
3225
|
-
`Use /autocontinue on|off or
|
|
3540
|
+
`Use /autocontinue on|off or Ctrl+Shift+C to toggle.`);
|
|
3226
3541
|
return;
|
|
3227
3542
|
}
|
|
3228
3543
|
if (value !== 'on' && value !== 'off') {
|
|
@@ -3367,7 +3682,7 @@ export class InteractiveShell {
|
|
|
3367
3682
|
display.clear();
|
|
3368
3683
|
clearAutosaveSnapshot(this.profile);
|
|
3369
3684
|
display.showInfo('Conversation cleared. Starting fresh.');
|
|
3370
|
-
this.
|
|
3685
|
+
this.renderPromptArea();
|
|
3371
3686
|
}
|
|
3372
3687
|
async handleResumeCommand(input) {
|
|
3373
3688
|
const tokens = input.split(/\s+/).slice(1);
|
|
@@ -3676,7 +3991,7 @@ export class InteractiveShell {
|
|
|
3676
3991
|
if (!providerOptions.length) {
|
|
3677
3992
|
display.showWarning('No providers are available.');
|
|
3678
3993
|
this.pendingInteraction = null;
|
|
3679
|
-
this.
|
|
3994
|
+
this.renderPromptArea();
|
|
3680
3995
|
return;
|
|
3681
3996
|
}
|
|
3682
3997
|
const lines = [
|
|
@@ -3697,7 +4012,7 @@ export class InteractiveShell {
|
|
|
3697
4012
|
catch (error) {
|
|
3698
4013
|
display.showError('Failed to load model list. Try again in a moment.', error);
|
|
3699
4014
|
this.pendingInteraction = null;
|
|
3700
|
-
this.
|
|
4015
|
+
this.renderPromptArea();
|
|
3701
4016
|
}
|
|
3702
4017
|
}
|
|
3703
4018
|
buildProviderOptions() {
|
|
@@ -4242,29 +4557,29 @@ export class InteractiveShell {
|
|
|
4242
4557
|
const trimmed = input.trim();
|
|
4243
4558
|
if (!trimmed) {
|
|
4244
4559
|
display.showWarning('Enter a number or type cancel.');
|
|
4245
|
-
this.
|
|
4560
|
+
this.renderPromptArea();
|
|
4246
4561
|
return;
|
|
4247
4562
|
}
|
|
4248
4563
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
4249
4564
|
this.pendingInteraction = null;
|
|
4250
4565
|
display.showInfo('Model selection cancelled.');
|
|
4251
|
-
this.
|
|
4566
|
+
this.renderPromptArea();
|
|
4252
4567
|
return;
|
|
4253
4568
|
}
|
|
4254
4569
|
const choice = Number.parseInt(trimmed, 10);
|
|
4255
4570
|
if (!Number.isFinite(choice)) {
|
|
4256
4571
|
display.showWarning('Please enter a valid number.');
|
|
4257
|
-
this.
|
|
4572
|
+
this.renderPromptArea();
|
|
4258
4573
|
return;
|
|
4259
4574
|
}
|
|
4260
4575
|
const option = pending.options[choice - 1];
|
|
4261
4576
|
if (!option) {
|
|
4262
4577
|
display.showWarning('That option is not available.');
|
|
4263
|
-
this.
|
|
4578
|
+
this.renderPromptArea();
|
|
4264
4579
|
return;
|
|
4265
4580
|
}
|
|
4266
4581
|
this.showProviderModels(option);
|
|
4267
|
-
this.
|
|
4582
|
+
this.renderPromptArea();
|
|
4268
4583
|
}
|
|
4269
4584
|
async handleModelSelection(input) {
|
|
4270
4585
|
const pending = this.pendingInteraction;
|
|
@@ -4274,35 +4589,35 @@ export class InteractiveShell {
|
|
|
4274
4589
|
const trimmed = input.trim();
|
|
4275
4590
|
if (!trimmed) {
|
|
4276
4591
|
display.showWarning('Enter a number, type "back", or type "cancel".');
|
|
4277
|
-
this.
|
|
4592
|
+
this.renderPromptArea();
|
|
4278
4593
|
return;
|
|
4279
4594
|
}
|
|
4280
4595
|
if (trimmed.toLowerCase() === 'back') {
|
|
4281
4596
|
this.showModelMenu();
|
|
4282
|
-
this.
|
|
4597
|
+
this.renderPromptArea();
|
|
4283
4598
|
return;
|
|
4284
4599
|
}
|
|
4285
4600
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
4286
4601
|
this.pendingInteraction = null;
|
|
4287
4602
|
display.showInfo('Model selection cancelled.');
|
|
4288
|
-
this.
|
|
4603
|
+
this.renderPromptArea();
|
|
4289
4604
|
return;
|
|
4290
4605
|
}
|
|
4291
4606
|
const choice = Number.parseInt(trimmed, 10);
|
|
4292
4607
|
if (!Number.isFinite(choice)) {
|
|
4293
4608
|
display.showWarning('Please enter a valid number.');
|
|
4294
|
-
this.
|
|
4609
|
+
this.renderPromptArea();
|
|
4295
4610
|
return;
|
|
4296
4611
|
}
|
|
4297
4612
|
const preset = pending.options[choice - 1];
|
|
4298
4613
|
if (!preset) {
|
|
4299
4614
|
display.showWarning('That option is not available.');
|
|
4300
|
-
this.
|
|
4615
|
+
this.renderPromptArea();
|
|
4301
4616
|
return;
|
|
4302
4617
|
}
|
|
4303
4618
|
this.pendingInteraction = null;
|
|
4304
4619
|
await this.applyModelPreset(preset);
|
|
4305
|
-
this.
|
|
4620
|
+
this.renderPromptArea();
|
|
4306
4621
|
}
|
|
4307
4622
|
async applyModelPreset(preset) {
|
|
4308
4623
|
try {
|
|
@@ -4335,30 +4650,30 @@ export class InteractiveShell {
|
|
|
4335
4650
|
const trimmed = input.trim();
|
|
4336
4651
|
if (!trimmed) {
|
|
4337
4652
|
display.showWarning('Enter a number or type cancel.');
|
|
4338
|
-
this.
|
|
4653
|
+
this.renderPromptArea();
|
|
4339
4654
|
return;
|
|
4340
4655
|
}
|
|
4341
4656
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
4342
4657
|
this.pendingInteraction = null;
|
|
4343
4658
|
display.showInfo('Secret management cancelled.');
|
|
4344
|
-
this.
|
|
4659
|
+
this.renderPromptArea();
|
|
4345
4660
|
return;
|
|
4346
4661
|
}
|
|
4347
4662
|
const choice = Number.parseInt(trimmed, 10);
|
|
4348
4663
|
if (!Number.isFinite(choice)) {
|
|
4349
4664
|
display.showWarning('Please enter a valid number.');
|
|
4350
|
-
this.
|
|
4665
|
+
this.renderPromptArea();
|
|
4351
4666
|
return;
|
|
4352
4667
|
}
|
|
4353
4668
|
const secret = pending.options[choice - 1];
|
|
4354
4669
|
if (!secret) {
|
|
4355
4670
|
display.showWarning('That option is not available.');
|
|
4356
|
-
this.
|
|
4671
|
+
this.renderPromptArea();
|
|
4357
4672
|
return;
|
|
4358
4673
|
}
|
|
4359
4674
|
display.showSystemMessage(`Enter a new value for ${secret.label} or type "cancel".`);
|
|
4360
4675
|
this.pendingInteraction = { type: 'secret-input', secret };
|
|
4361
|
-
this.
|
|
4676
|
+
this.renderPromptArea();
|
|
4362
4677
|
}
|
|
4363
4678
|
async handleSecretInput(input) {
|
|
4364
4679
|
const pending = this.pendingInteraction;
|
|
@@ -4368,14 +4683,14 @@ export class InteractiveShell {
|
|
|
4368
4683
|
const trimmed = input.trim();
|
|
4369
4684
|
if (!trimmed) {
|
|
4370
4685
|
display.showWarning('Enter a value or type cancel.');
|
|
4371
|
-
this.
|
|
4686
|
+
this.renderPromptArea();
|
|
4372
4687
|
return;
|
|
4373
4688
|
}
|
|
4374
4689
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
4375
4690
|
this.pendingInteraction = null;
|
|
4376
4691
|
this.pendingSecretRetry = null;
|
|
4377
4692
|
display.showInfo('Secret unchanged.');
|
|
4378
|
-
this.
|
|
4693
|
+
this.renderPromptArea();
|
|
4379
4694
|
return;
|
|
4380
4695
|
}
|
|
4381
4696
|
try {
|
|
@@ -4399,11 +4714,11 @@ export class InteractiveShell {
|
|
|
4399
4714
|
this.pendingInteraction = null;
|
|
4400
4715
|
this.pendingSecretRetry = null;
|
|
4401
4716
|
}
|
|
4402
|
-
this.
|
|
4717
|
+
this.renderPromptArea();
|
|
4403
4718
|
}
|
|
4404
|
-
async processRequest(
|
|
4719
|
+
async processRequest(userRequest) {
|
|
4405
4720
|
if (this.isProcessing) {
|
|
4406
|
-
this.enqueueFollowUpAction({ type: 'request', text:
|
|
4721
|
+
this.enqueueFollowUpAction({ type: 'request', text: userRequest });
|
|
4407
4722
|
return;
|
|
4408
4723
|
}
|
|
4409
4724
|
if (!this.agent && !this.rebuildAgent()) {
|
|
@@ -4414,28 +4729,48 @@ export class InteractiveShell {
|
|
|
4414
4729
|
if (!agent) {
|
|
4415
4730
|
return;
|
|
4416
4731
|
}
|
|
4417
|
-
this.
|
|
4732
|
+
const alphaZeroEngaged = this.alphaZeroModeEnabled;
|
|
4733
|
+
const alphaZeroDifficult = alphaZeroEngaged ? this.isDifficultProblem(userRequest) : false;
|
|
4734
|
+
const requestForAgent = alphaZeroEngaged
|
|
4735
|
+
? this.buildAlphaZeroPrompt(userRequest, alphaZeroDifficult)
|
|
4736
|
+
: userRequest;
|
|
4737
|
+
const alphaZeroStatusId = 'alpha-zero';
|
|
4738
|
+
let alphaZeroStatusApplied = false;
|
|
4739
|
+
let alphaZeroTaskStarted = false;
|
|
4740
|
+
let alphaZeroTaskCompleted = false;
|
|
4741
|
+
if (alphaZeroEngaged) {
|
|
4742
|
+
const detail = alphaZeroDifficult ? 'Difficult request detected' : 'Reinforcement loop enabled';
|
|
4743
|
+
this.statusTracker.pushOverride(alphaZeroStatusId, 'AlphaZero RL active', {
|
|
4744
|
+
detail: `${detail} ยท full verification`,
|
|
4745
|
+
tone: 'info',
|
|
4746
|
+
});
|
|
4747
|
+
alphaZeroStatusApplied = true;
|
|
4748
|
+
display.showInfo(`AlphaZero RL mode engaged${alphaZeroDifficult ? ' for a difficult request' : ''}. Duel + self-critique with verification enabled.`);
|
|
4749
|
+
this.alphaZeroMetrics.startAlphaZeroTask(userRequest);
|
|
4750
|
+
alphaZeroTaskStarted = true;
|
|
4751
|
+
}
|
|
4752
|
+
this.logUserPrompt(userRequest);
|
|
4418
4753
|
this.isProcessing = true;
|
|
4419
4754
|
this.uiUpdates.setMode('processing');
|
|
4420
4755
|
this.terminalInput.setStreaming(true);
|
|
4421
4756
|
// Keep the persistent input/control bar active as we transition into streaming.
|
|
4422
|
-
this.
|
|
4757
|
+
this.renderPromptArea(true);
|
|
4423
4758
|
const requestStartTime = Date.now(); // Alpha Zero 2 timing
|
|
4424
4759
|
// Clear previous parallel agents and start fresh for new request
|
|
4425
4760
|
const parallelManager = getParallelAgentManager();
|
|
4426
4761
|
parallelManager.clear();
|
|
4427
4762
|
parallelManager.startBatch();
|
|
4428
4763
|
// AlphaZero: Track task for learning
|
|
4429
|
-
this.lastUserQuery =
|
|
4430
|
-
this.currentTaskType = classifyTaskType(
|
|
4764
|
+
this.lastUserQuery = userRequest;
|
|
4765
|
+
this.currentTaskType = classifyTaskType(userRequest);
|
|
4431
4766
|
this.currentToolCalls = [];
|
|
4432
4767
|
this.uiAdapter.startProcessing('Working on your request');
|
|
4433
4768
|
this.setProcessingStatus();
|
|
4434
4769
|
let responseText = '';
|
|
4435
4770
|
try {
|
|
4436
4771
|
// Start streaming - no header needed, the input area already provides context
|
|
4437
|
-
this.startStreamingHeartbeat('Streaming response');
|
|
4438
|
-
responseText = await agent.send(
|
|
4772
|
+
this.startStreamingHeartbeat(alphaZeroEngaged ? 'AlphaZero RL' : 'Streaming response');
|
|
4773
|
+
responseText = await agent.send(requestForAgent, true);
|
|
4439
4774
|
await this.awaitPendingCleanup();
|
|
4440
4775
|
this.captureHistorySnapshot();
|
|
4441
4776
|
this.autosaveIfEnabled();
|
|
@@ -4456,8 +4791,12 @@ export class InteractiveShell {
|
|
|
4456
4791
|
// AlphaZero: Check for failure in response
|
|
4457
4792
|
const failure = detectFailure(responseText, {
|
|
4458
4793
|
toolCalls: this.currentToolCalls,
|
|
4459
|
-
userMessage:
|
|
4794
|
+
userMessage: userRequest,
|
|
4460
4795
|
});
|
|
4796
|
+
if (alphaZeroEngaged && alphaZeroTaskStarted && !alphaZeroTaskCompleted) {
|
|
4797
|
+
this.alphaZeroMetrics.completeAlphaZeroTask(!failure);
|
|
4798
|
+
alphaZeroTaskCompleted = true;
|
|
4799
|
+
}
|
|
4461
4800
|
if (failure) {
|
|
4462
4801
|
this.lastFailure = failure;
|
|
4463
4802
|
// Check if we have a recovery strategy
|
|
@@ -4484,13 +4823,23 @@ export class InteractiveShell {
|
|
|
4484
4823
|
}
|
|
4485
4824
|
}
|
|
4486
4825
|
catch (error) {
|
|
4487
|
-
const handled = this.handleProviderError(error, () => this.processRequest(
|
|
4826
|
+
const handled = this.handleProviderError(error, () => this.processRequest(userRequest));
|
|
4827
|
+
if (alphaZeroEngaged && alphaZeroTaskStarted && !alphaZeroTaskCompleted) {
|
|
4828
|
+
this.alphaZeroMetrics.completeAlphaZeroTask(false);
|
|
4829
|
+
alphaZeroTaskCompleted = true;
|
|
4830
|
+
}
|
|
4488
4831
|
if (!handled) {
|
|
4489
4832
|
// Pass full error object for enhanced formatting with stack trace
|
|
4490
4833
|
display.showError(error instanceof Error ? error.message : String(error), error);
|
|
4491
4834
|
}
|
|
4492
4835
|
}
|
|
4493
4836
|
finally {
|
|
4837
|
+
if (alphaZeroEngaged && alphaZeroStatusApplied) {
|
|
4838
|
+
this.statusTracker.clearOverride(alphaZeroStatusId);
|
|
4839
|
+
}
|
|
4840
|
+
if (alphaZeroEngaged && alphaZeroTaskStarted && !alphaZeroTaskCompleted) {
|
|
4841
|
+
this.alphaZeroMetrics.completeAlphaZeroTask(false);
|
|
4842
|
+
}
|
|
4494
4843
|
display.stopThinking(false);
|
|
4495
4844
|
this.uiUpdates.setMode('processing');
|
|
4496
4845
|
this.stopStreamingHeartbeat();
|
|
@@ -4504,7 +4853,7 @@ export class InteractiveShell {
|
|
|
4504
4853
|
// CRITICAL: Ensure readline prompt is active for user input
|
|
4505
4854
|
// Claude Code style: New prompt naturally appears at bottom
|
|
4506
4855
|
this.ensureReadlineReady();
|
|
4507
|
-
this.
|
|
4856
|
+
this.renderPromptArea();
|
|
4508
4857
|
this.scheduleQueueProcessing();
|
|
4509
4858
|
this.refreshQueueIndicators();
|
|
4510
4859
|
}
|
|
@@ -4975,6 +5324,8 @@ What's the next action?`;
|
|
|
4975
5324
|
finally {
|
|
4976
5325
|
this.updateStatusMessage(null);
|
|
4977
5326
|
this.autoTestInFlight = false;
|
|
5327
|
+
this.terminalInput.resetContentPosition();
|
|
5328
|
+
this.terminalInput.forceRender();
|
|
4978
5329
|
}
|
|
4979
5330
|
}
|
|
4980
5331
|
isBuildToolCall(entry) {
|
|
@@ -5081,7 +5432,7 @@ What's the next action?`;
|
|
|
5081
5432
|
// Send the error to the agent for fixing
|
|
5082
5433
|
display.showThinking('Analyzing build errors');
|
|
5083
5434
|
this.refreshStatusLine(true);
|
|
5084
|
-
const response = await this.agent.send(prompt, true);
|
|
5435
|
+
const response = await this.withStreamingUi('Fixing build errors', () => this.agent.send(prompt, true));
|
|
5085
5436
|
display.stopThinking();
|
|
5086
5437
|
this.refreshStatusLine(true);
|
|
5087
5438
|
if (response) {
|
|
@@ -5191,19 +5542,19 @@ What's the next action?`;
|
|
|
5191
5542
|
this.updateContextUsage(percentage);
|
|
5192
5543
|
}
|
|
5193
5544
|
// Ensure prompt remains visible at bottom after context messages
|
|
5194
|
-
this.
|
|
5545
|
+
this.renderPromptArea();
|
|
5195
5546
|
},
|
|
5196
5547
|
onContinueAfterRecovery: () => {
|
|
5197
5548
|
// Update UI to show we're continuing after context recovery
|
|
5198
5549
|
display.showSystemMessage(`๐ Continuing after context recovery...`);
|
|
5199
5550
|
this.updateStatusMessage('Retrying with reduced context...');
|
|
5200
|
-
this.
|
|
5551
|
+
this.renderPromptArea();
|
|
5201
5552
|
},
|
|
5202
5553
|
onAutoContinue: (attempt, maxAttempts, _message) => {
|
|
5203
5554
|
// Show auto-continue progress in UI
|
|
5204
5555
|
display.showSystemMessage(`๐ Auto-continue (${attempt}/${maxAttempts}): Model expressed intent, prompting to act...`);
|
|
5205
5556
|
this.updateStatusMessage('Auto-continuing...');
|
|
5206
|
-
this.
|
|
5557
|
+
this.renderPromptArea();
|
|
5207
5558
|
},
|
|
5208
5559
|
onCancelled: () => {
|
|
5209
5560
|
// Update UI to show operation was cancelled
|
|
@@ -5212,7 +5563,7 @@ What's the next action?`;
|
|
|
5212
5563
|
this.stopStreamingHeartbeat();
|
|
5213
5564
|
this.updateStatusMessage(null);
|
|
5214
5565
|
this.terminalInput.setStreaming(false);
|
|
5215
|
-
this.
|
|
5566
|
+
this.renderPromptArea();
|
|
5216
5567
|
},
|
|
5217
5568
|
onVerificationNeeded: () => {
|
|
5218
5569
|
void this.enforceAutoBuild('verification');
|
|
@@ -5250,7 +5601,7 @@ What's the next action?`;
|
|
|
5250
5601
|
resetChatBoxAfterModelSwap() {
|
|
5251
5602
|
this.updateStatusMessage(null);
|
|
5252
5603
|
this.terminalInput.setStreaming(false);
|
|
5253
|
-
this.
|
|
5604
|
+
this.renderPromptArea();
|
|
5254
5605
|
this.ensureReadlineReady();
|
|
5255
5606
|
}
|
|
5256
5607
|
/**
|