erosolar-cli 1.7.429 → 1.7.430
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/enhancedGitCapability.js +3 -3
- package/dist/capabilities/enhancedGitCapability.js.map +1 -1
- package/dist/capabilities/learnCapability.d.ts +1 -1
- package/dist/capabilities/learnCapability.d.ts.map +1 -1
- package/dist/capabilities/learnCapability.js +1 -1
- package/dist/capabilities/learnCapability.js.map +1 -1
- package/dist/core/checkpoint.d.ts +1 -1
- package/dist/core/checkpoint.js +1 -1
- package/dist/core/costTracker.d.ts +1 -1
- package/dist/core/costTracker.js +1 -1
- package/dist/core/hooks.d.ts +1 -1
- package/dist/core/hooks.js +1 -1
- package/dist/core/memorySystem.d.ts +2 -2
- package/dist/core/memorySystem.js +2 -2
- package/dist/core/outputStyles.d.ts +2 -2
- package/dist/core/outputStyles.js +2 -2
- package/dist/core/validationRunner.d.ts +1 -1
- package/dist/core/validationRunner.js +1 -1
- package/dist/shell/interactiveShell.d.ts +5 -1
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +115 -83
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/systemPrompt.d.ts.map +1 -1
- package/dist/shell/systemPrompt.js +13 -34
- package/dist/shell/systemPrompt.js.map +1 -1
- package/dist/shell/terminalInputAdapter.d.ts +75 -83
- package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
- package/dist/shell/terminalInputAdapter.js +159 -220
- package/dist/shell/terminalInputAdapter.js.map +1 -1
- package/dist/shell/vimMode.d.ts +1 -1
- package/dist/shell/vimMode.js +1 -1
- package/dist/tools/buildTools.d.ts +1 -1
- package/dist/tools/buildTools.js +1 -1
- package/dist/tools/diffUtils.d.ts +2 -2
- package/dist/tools/diffUtils.js +2 -2
- package/dist/tools/editTools.js +4 -4
- package/dist/tools/editTools.js.map +1 -1
- package/dist/tools/localExplore.d.ts +3 -3
- package/dist/tools/localExplore.js +3 -3
- package/dist/tools/skillTools.js +2 -2
- package/dist/tools/skillTools.js.map +1 -1
- package/dist/tools/validationTools.js +1 -1
- package/dist/ui/DisplayEventQueue.d.ts +99 -0
- package/dist/ui/DisplayEventQueue.d.ts.map +1 -0
- package/dist/ui/DisplayEventQueue.js +167 -0
- package/dist/ui/DisplayEventQueue.js.map +1 -0
- package/dist/ui/SequentialRenderer.d.ts +69 -0
- package/dist/ui/SequentialRenderer.d.ts.map +1 -0
- package/dist/ui/SequentialRenderer.js +137 -0
- package/dist/ui/SequentialRenderer.js.map +1 -0
- package/dist/ui/ShellUIAdapter.d.ts +18 -6
- package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
- package/dist/ui/ShellUIAdapter.js +65 -14
- package/dist/ui/ShellUIAdapter.js.map +1 -1
- package/dist/ui/UnifiedUIRenderer.d.ts +184 -0
- package/dist/ui/UnifiedUIRenderer.d.ts.map +1 -0
- package/dist/ui/UnifiedUIRenderer.js +567 -0
- package/dist/ui/UnifiedUIRenderer.js.map +1 -0
- package/dist/ui/display.d.ts +100 -173
- package/dist/ui/display.d.ts.map +1 -1
- package/dist/ui/display.js +359 -927
- package/dist/ui/display.js.map +1 -1
- package/dist/ui/errorFormatter.d.ts +1 -1
- package/dist/ui/errorFormatter.js +1 -1
- package/dist/ui/shortcutsHelp.d.ts +6 -6
- package/dist/ui/shortcutsHelp.js +6 -6
- package/dist/ui/streamingFormatter.d.ts +2 -5
- package/dist/ui/streamingFormatter.d.ts.map +1 -1
- package/dist/ui/streamingFormatter.js +9 -33
- package/dist/ui/streamingFormatter.js.map +1 -1
- package/dist/ui/textHighlighter.d.ts +8 -8
- package/dist/ui/textHighlighter.js +9 -9
- package/dist/ui/textHighlighter.js.map +1 -1
- package/dist/ui/theme.d.ts +2 -2
- package/dist/ui/theme.js +4 -4
- package/dist/ui/theme.js.map +1 -1
- package/dist/ui/toolDisplay.d.ts +8 -8
- package/dist/ui/toolDisplay.js +8 -8
- package/package.json +1 -1
- package/dist/shell/terminalInput.d.ts +0 -619
- package/dist/shell/terminalInput.d.ts.map +0 -1
- package/dist/shell/terminalInput.js +0 -2699
- package/dist/shell/terminalInput.js.map +0 -1
|
@@ -4,9 +4,9 @@ import { promisify } from 'node:util';
|
|
|
4
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { display } from '../ui/display.js';
|
|
7
|
-
import { isPlainOutputMode } from '../ui/outputMode.js';
|
|
8
7
|
import { theme } from '../ui/theme.js';
|
|
9
8
|
import { StreamingResponseFormatter } from '../ui/streamingFormatter.js';
|
|
9
|
+
import { UnifiedUIRenderer } from '../ui/UnifiedUIRenderer.js';
|
|
10
10
|
import { getContextWindowTokens } from '../core/contextWindow.js';
|
|
11
11
|
import { ensureSecretForProvider, getSecretDefinitionForProvider, getSecretValue, listSecretDefinitions, maskSecret, setSecretValue, } from '../core/secretStore.js';
|
|
12
12
|
import { saveActiveProfilePreference, saveModelPreference, loadToolSettings, saveToolSettings, clearToolSettings, clearActiveProfilePreference, loadSessionPreferences, saveSessionPreferences, loadFeatureFlags, saveFeatureFlags, toggleFeatureFlag, FEATURE_FLAG_INFO, } from '../core/preferences.js';
|
|
@@ -174,6 +174,8 @@ export class InteractiveShell {
|
|
|
174
174
|
alternateScreenEnabled;
|
|
175
175
|
welcomeShown = false;
|
|
176
176
|
scrollbackRestored = false;
|
|
177
|
+
uiRenderer;
|
|
178
|
+
useUnifiedRenderer;
|
|
177
179
|
constructor(config) {
|
|
178
180
|
this.profile = config.profile;
|
|
179
181
|
this.profileLabel = config.profileLabel;
|
|
@@ -270,6 +272,10 @@ export class InteractiveShell {
|
|
|
270
272
|
onToggleThinking: () => this.cycleThinkingMode(),
|
|
271
273
|
onClearContext: () => this.handleClearContext(),
|
|
272
274
|
});
|
|
275
|
+
const canUseRenderer = output.isTTY;
|
|
276
|
+
this.uiRenderer = canUseRenderer ? new UnifiedUIRenderer(output, input) : null;
|
|
277
|
+
this.useUnifiedRenderer = !!this.uiRenderer;
|
|
278
|
+
display.setRenderer(this.uiRenderer);
|
|
273
279
|
// Initialize Alpha Zero 2 metrics tracking
|
|
274
280
|
this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
|
|
275
281
|
this.setupStatusTracking();
|
|
@@ -292,7 +298,8 @@ export class InteractiveShell {
|
|
|
292
298
|
}
|
|
293
299
|
// Render chat box immediately using the streaming UI lifecycle
|
|
294
300
|
this.refreshControlBar();
|
|
295
|
-
this.
|
|
301
|
+
this.syncRendererInput();
|
|
302
|
+
this.uiRenderer?.render();
|
|
296
303
|
this.rebuildAgent();
|
|
297
304
|
this.setupHandlers();
|
|
298
305
|
this.refreshSessionContext();
|
|
@@ -393,7 +400,7 @@ export class InteractiveShell {
|
|
|
393
400
|
const model = `${this.sessionState.model} @ ${this.providerLabel(this.sessionState.provider)}`;
|
|
394
401
|
const workspace = this.workingDir;
|
|
395
402
|
const lines = [
|
|
396
|
-
'
|
|
403
|
+
'Erosolar-CLI',
|
|
397
404
|
welcome,
|
|
398
405
|
model,
|
|
399
406
|
workspace,
|
|
@@ -401,6 +408,20 @@ export class InteractiveShell {
|
|
|
401
408
|
];
|
|
402
409
|
return lines.join('\n');
|
|
403
410
|
}
|
|
411
|
+
syncRendererInput() {
|
|
412
|
+
// No-op: UnifiedUIRenderer handles its own input state now
|
|
413
|
+
// The new architecture doesn't require separate input syncing
|
|
414
|
+
}
|
|
415
|
+
pushUiEvent(type, content) {
|
|
416
|
+
if (!content) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
if (this.useUnifiedRenderer && this.uiRenderer) {
|
|
420
|
+
this.uiRenderer.addEvent(type, content);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
display.stream(content);
|
|
424
|
+
}
|
|
404
425
|
/**
|
|
405
426
|
* Stream a content block as a single event, isolating it from adjacent output.
|
|
406
427
|
*/
|
|
@@ -409,6 +430,10 @@ export class InteractiveShell {
|
|
|
409
430
|
if (!normalized) {
|
|
410
431
|
return;
|
|
411
432
|
}
|
|
433
|
+
if (this.useUnifiedRenderer && this.uiRenderer) {
|
|
434
|
+
this.uiRenderer.addEvent('banner', normalized);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
412
437
|
const bullet = `${theme.info('⏺')} `;
|
|
413
438
|
const indent = ' ';
|
|
414
439
|
const lines = normalized.split('\n').map(line => line.trimEnd());
|
|
@@ -416,11 +441,18 @@ export class InteractiveShell {
|
|
|
416
441
|
.map((line, index) => (index === 0 ? `${bullet}${line}` : `${indent}${line}`))
|
|
417
442
|
.join('\n');
|
|
418
443
|
const block = `\n${formatted}\n`;
|
|
419
|
-
this.
|
|
444
|
+
this.pushUiEvent('raw', block);
|
|
420
445
|
}
|
|
421
446
|
async start(initialPrompt) {
|
|
422
447
|
// Always use the scroll-region streaming layout from the outset
|
|
423
|
-
this.
|
|
448
|
+
if (this.useUnifiedRenderer && this.uiRenderer) {
|
|
449
|
+
this.uiRenderer.initialize();
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
this.terminalInput.clearScreen();
|
|
453
|
+
this.terminalInput.resetContentPosition();
|
|
454
|
+
}
|
|
455
|
+
this.syncRendererInput();
|
|
424
456
|
this.showWelcomeBanner();
|
|
425
457
|
if (initialPrompt) {
|
|
426
458
|
await this.processInputBlock(initialPrompt);
|
|
@@ -428,7 +460,7 @@ export class InteractiveShell {
|
|
|
428
460
|
}
|
|
429
461
|
this.showLaunchCommandPalette();
|
|
430
462
|
// Ensure the terminal input is visible
|
|
431
|
-
this.
|
|
463
|
+
this.syncRendererInput();
|
|
432
464
|
}
|
|
433
465
|
showLaunchCommandPalette() {
|
|
434
466
|
// Disabled: Quick commands palette takes up too much space
|
|
@@ -547,6 +579,7 @@ export class InteractiveShell {
|
|
|
547
579
|
*/
|
|
548
580
|
handleInputChange(text) {
|
|
549
581
|
this.currentInput = text;
|
|
582
|
+
this.syncRendererInput();
|
|
550
583
|
if (text.length > 0) {
|
|
551
584
|
this.resetCtrlCSequence();
|
|
552
585
|
}
|
|
@@ -568,7 +601,7 @@ export class InteractiveShell {
|
|
|
568
601
|
display.showSystemMessage('✏️ Display edits mode enabled.');
|
|
569
602
|
}
|
|
570
603
|
}
|
|
571
|
-
this.
|
|
604
|
+
this.syncRendererInput();
|
|
572
605
|
}
|
|
573
606
|
toggleVerificationMode() {
|
|
574
607
|
this.setVerificationMode(!this.verificationEnabled, 'shortcut');
|
|
@@ -689,7 +722,7 @@ export class InteractiveShell {
|
|
|
689
722
|
if (['n', 'no', 'cancel', '/cancel'].includes(lower)) {
|
|
690
723
|
this.pendingPermissionInput = null;
|
|
691
724
|
display.showInfo('Request cancelled.');
|
|
692
|
-
this.
|
|
725
|
+
this.syncRendererInput();
|
|
693
726
|
return null;
|
|
694
727
|
}
|
|
695
728
|
// Treat any other input as a replacement request that also needs confirmation
|
|
@@ -707,7 +740,7 @@ export class InteractiveShell {
|
|
|
707
740
|
]
|
|
708
741
|
.filter(Boolean)
|
|
709
742
|
.join('\n'));
|
|
710
|
-
this.
|
|
743
|
+
this.syncRendererInput();
|
|
711
744
|
}
|
|
712
745
|
/**
|
|
713
746
|
* Handle Ctrl+C presses in three stages:
|
|
@@ -772,6 +805,7 @@ export class InteractiveShell {
|
|
|
772
805
|
this.stopStreamingHeartbeat('quit', { quiet: true });
|
|
773
806
|
this.endAiRuntime();
|
|
774
807
|
this.uiUpdates.dispose();
|
|
808
|
+
this.uiRenderer?.cleanup();
|
|
775
809
|
this.clearPromptRefreshTimer();
|
|
776
810
|
this.teardownStatusTracking();
|
|
777
811
|
// Clear global AI enhancer (explore tool will work offline after this)
|
|
@@ -831,26 +865,26 @@ export class InteractiveShell {
|
|
|
831
865
|
const trimmed = input.trim();
|
|
832
866
|
if (!trimmed) {
|
|
833
867
|
display.showWarning('Enter a number, "save", "defaults", or "cancel".');
|
|
834
|
-
this.
|
|
868
|
+
this.syncRendererInput();
|
|
835
869
|
return;
|
|
836
870
|
}
|
|
837
871
|
const normalized = trimmed.toLowerCase();
|
|
838
872
|
if (normalized === 'cancel') {
|
|
839
873
|
this.pendingInteraction = null;
|
|
840
874
|
display.showInfo('Tool selection cancelled.');
|
|
841
|
-
this.
|
|
875
|
+
this.syncRendererInput();
|
|
842
876
|
return;
|
|
843
877
|
}
|
|
844
878
|
if (normalized === 'defaults') {
|
|
845
879
|
pending.selection = buildEnabledToolSet(null);
|
|
846
880
|
this.renderToolMenu(pending);
|
|
847
|
-
this.
|
|
881
|
+
this.syncRendererInput();
|
|
848
882
|
return;
|
|
849
883
|
}
|
|
850
884
|
if (normalized === 'save') {
|
|
851
885
|
await this.persistToolSelection(pending);
|
|
852
886
|
this.pendingInteraction = null;
|
|
853
|
-
this.
|
|
887
|
+
this.syncRendererInput();
|
|
854
888
|
return;
|
|
855
889
|
}
|
|
856
890
|
const choice = Number.parseInt(trimmed, 10);
|
|
@@ -873,11 +907,11 @@ export class InteractiveShell {
|
|
|
873
907
|
}
|
|
874
908
|
this.renderToolMenu(pending);
|
|
875
909
|
}
|
|
876
|
-
this.
|
|
910
|
+
this.syncRendererInput();
|
|
877
911
|
return;
|
|
878
912
|
}
|
|
879
913
|
display.showWarning('Enter a number, "save", "defaults", or "cancel".');
|
|
880
|
-
this.
|
|
914
|
+
this.syncRendererInput();
|
|
881
915
|
}
|
|
882
916
|
async persistToolSelection(interaction) {
|
|
883
917
|
if (setsEqual(interaction.selection, interaction.initialSelection)) {
|
|
@@ -905,36 +939,36 @@ export class InteractiveShell {
|
|
|
905
939
|
if (!this.agentMenu) {
|
|
906
940
|
this.pendingInteraction = null;
|
|
907
941
|
display.showWarning('Agent selection is unavailable in this CLI.');
|
|
908
|
-
this.
|
|
942
|
+
this.syncRendererInput();
|
|
909
943
|
return;
|
|
910
944
|
}
|
|
911
945
|
const trimmed = input.trim();
|
|
912
946
|
if (!trimmed) {
|
|
913
947
|
display.showWarning('Enter a number or type "cancel".');
|
|
914
|
-
this.
|
|
948
|
+
this.syncRendererInput();
|
|
915
949
|
return;
|
|
916
950
|
}
|
|
917
951
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
918
952
|
this.pendingInteraction = null;
|
|
919
953
|
display.showInfo('Agent selection cancelled.');
|
|
920
|
-
this.
|
|
954
|
+
this.syncRendererInput();
|
|
921
955
|
return;
|
|
922
956
|
}
|
|
923
957
|
const choice = Number.parseInt(trimmed, 10);
|
|
924
958
|
if (!Number.isFinite(choice)) {
|
|
925
959
|
display.showWarning('Please enter a valid number.');
|
|
926
|
-
this.
|
|
960
|
+
this.syncRendererInput();
|
|
927
961
|
return;
|
|
928
962
|
}
|
|
929
963
|
const option = pending.options[choice - 1];
|
|
930
964
|
if (!option) {
|
|
931
965
|
display.showWarning('That option is not available.');
|
|
932
|
-
this.
|
|
966
|
+
this.syncRendererInput();
|
|
933
967
|
return;
|
|
934
968
|
}
|
|
935
969
|
await this.persistAgentSelection(option.name);
|
|
936
970
|
this.pendingInteraction = null;
|
|
937
|
-
this.
|
|
971
|
+
this.syncRendererInput();
|
|
938
972
|
}
|
|
939
973
|
async persistAgentSelection(profileName) {
|
|
940
974
|
if (!this.agentMenu) {
|
|
@@ -1007,7 +1041,7 @@ export class InteractiveShell {
|
|
|
1007
1041
|
lines.push(` ${theme.primary('[text]')} Submit your own solution instead`);
|
|
1008
1042
|
lines.push('');
|
|
1009
1043
|
display.showSystemMessage(lines.join('\n'));
|
|
1010
|
-
this.
|
|
1044
|
+
this.syncRendererInput();
|
|
1011
1045
|
}
|
|
1012
1046
|
async handlePlanApprovalInput(input) {
|
|
1013
1047
|
const pending = this.pendingInteraction;
|
|
@@ -1016,7 +1050,7 @@ export class InteractiveShell {
|
|
|
1016
1050
|
const trimmed = input.trim();
|
|
1017
1051
|
if (!trimmed) {
|
|
1018
1052
|
display.showWarning('Enter a command or your own solution.');
|
|
1019
|
-
this.
|
|
1053
|
+
this.syncRendererInput();
|
|
1020
1054
|
return;
|
|
1021
1055
|
}
|
|
1022
1056
|
const lower = trimmed.toLowerCase();
|
|
@@ -1024,7 +1058,7 @@ export class InteractiveShell {
|
|
|
1024
1058
|
if (lower === 'cancel' || lower === 'c') {
|
|
1025
1059
|
this.pendingInteraction = null;
|
|
1026
1060
|
display.showInfo('Plan cancelled. You can continue with a different approach.');
|
|
1027
|
-
this.
|
|
1061
|
+
this.syncRendererInput();
|
|
1028
1062
|
return;
|
|
1029
1063
|
}
|
|
1030
1064
|
// Select all
|
|
@@ -1044,7 +1078,7 @@ export class InteractiveShell {
|
|
|
1044
1078
|
const selectedSteps = pending.steps.filter(s => pending.selectedSteps.has(s.id));
|
|
1045
1079
|
if (selectedSteps.length === 0) {
|
|
1046
1080
|
display.showWarning('No steps selected. Select steps or enter your own solution.');
|
|
1047
|
-
this.
|
|
1081
|
+
this.syncRendererInput();
|
|
1048
1082
|
return;
|
|
1049
1083
|
}
|
|
1050
1084
|
this.pendingInteraction = null;
|
|
@@ -1077,7 +1111,7 @@ export class InteractiveShell {
|
|
|
1077
1111
|
return;
|
|
1078
1112
|
}
|
|
1079
1113
|
display.showWarning('Invalid input. Enter a step number, command (go/cancel/all/none), or your own solution.');
|
|
1080
|
-
this.
|
|
1114
|
+
this.syncRendererInput();
|
|
1081
1115
|
}
|
|
1082
1116
|
setupHandlers() {
|
|
1083
1117
|
// Handle terminal resize
|
|
@@ -1085,7 +1119,7 @@ export class InteractiveShell {
|
|
|
1085
1119
|
this.terminalInput.handleResize();
|
|
1086
1120
|
});
|
|
1087
1121
|
// Show initial input UI
|
|
1088
|
-
this.
|
|
1122
|
+
this.syncRendererInput();
|
|
1089
1123
|
}
|
|
1090
1124
|
/**
|
|
1091
1125
|
* Set up command autocomplete with all available slash commands.
|
|
@@ -1198,7 +1232,7 @@ export class InteractiveShell {
|
|
|
1198
1232
|
thinkingHotkey: 'tab',
|
|
1199
1233
|
});
|
|
1200
1234
|
this.refreshStatusLine();
|
|
1201
|
-
this.
|
|
1235
|
+
this.syncRendererInput();
|
|
1202
1236
|
}
|
|
1203
1237
|
writeLocked(content) {
|
|
1204
1238
|
if (!content) {
|
|
@@ -1236,7 +1270,7 @@ export class InteractiveShell {
|
|
|
1236
1270
|
/**
|
|
1237
1271
|
* Refresh the status line in the persistent input area.
|
|
1238
1272
|
* Uses combined status display: streaming label + override + main status.
|
|
1239
|
-
* All three can be shown simultaneously (
|
|
1273
|
+
* All three can be shown simultaneously (Erosolar-CLI style).
|
|
1240
1274
|
*/
|
|
1241
1275
|
refreshStatusLine(forceRender = false) {
|
|
1242
1276
|
// Set streaming label (spinner + label) - shows during streaming
|
|
@@ -1263,8 +1297,10 @@ export class InteractiveShell {
|
|
|
1263
1297
|
model: this.sessionState.model,
|
|
1264
1298
|
provider: this.providerLabel(this.sessionState.provider),
|
|
1265
1299
|
});
|
|
1300
|
+
this.syncRendererInput();
|
|
1266
1301
|
if (forceRender) {
|
|
1267
|
-
this.
|
|
1302
|
+
this.syncRendererInput();
|
|
1303
|
+
this.uiRenderer?.render();
|
|
1268
1304
|
}
|
|
1269
1305
|
}
|
|
1270
1306
|
/**
|
|
@@ -1323,7 +1359,8 @@ export class InteractiveShell {
|
|
|
1323
1359
|
}
|
|
1324
1360
|
requestPromptRefresh(force = false) {
|
|
1325
1361
|
if (force) {
|
|
1326
|
-
this.
|
|
1362
|
+
this.syncRendererInput();
|
|
1363
|
+
this.uiRenderer?.render();
|
|
1327
1364
|
return;
|
|
1328
1365
|
}
|
|
1329
1366
|
if (this.promptRefreshTimer) {
|
|
@@ -1331,7 +1368,7 @@ export class InteractiveShell {
|
|
|
1331
1368
|
}
|
|
1332
1369
|
this.promptRefreshTimer = setTimeout(() => {
|
|
1333
1370
|
this.promptRefreshTimer = null;
|
|
1334
|
-
this.
|
|
1371
|
+
this.syncRendererInput();
|
|
1335
1372
|
}, 48);
|
|
1336
1373
|
}
|
|
1337
1374
|
clearPromptRefreshTimer() {
|
|
@@ -1345,7 +1382,6 @@ export class InteractiveShell {
|
|
|
1345
1382
|
// Enter global streaming mode - blocks all non-streaming UI output
|
|
1346
1383
|
enterStreamingMode();
|
|
1347
1384
|
// Set up scroll region for streaming content
|
|
1348
|
-
this.terminalInput.enterStreamingScrollRegion();
|
|
1349
1385
|
this.uiUpdates.setMode('streaming');
|
|
1350
1386
|
this.streamingHeartbeatStart = Date.now();
|
|
1351
1387
|
this.streamingHeartbeatFrame = 0;
|
|
@@ -1412,19 +1448,14 @@ export class InteractiveShell {
|
|
|
1412
1448
|
if (!chunk) {
|
|
1413
1449
|
return;
|
|
1414
1450
|
}
|
|
1415
|
-
// Preserve raw output in plain/CI modes or non-TTY environments
|
|
1416
|
-
if (isPlainOutputMode() || !output.isTTY) {
|
|
1417
|
-
this.terminalInput.streamContent(chunk);
|
|
1418
|
-
return;
|
|
1419
|
-
}
|
|
1420
1451
|
if (!this.streamingFormatter) {
|
|
1421
1452
|
this.streamingFormatter = new StreamingResponseFormatter(output.columns ?? undefined);
|
|
1422
|
-
this.
|
|
1453
|
+
this.pushUiEvent('streaming', this.streamingFormatter.header());
|
|
1423
1454
|
}
|
|
1424
1455
|
const formatted = this.streamingFormatter.formatChunk(chunk);
|
|
1425
1456
|
this.captureStreamingThought(chunk);
|
|
1426
1457
|
if (formatted) {
|
|
1427
|
-
this.
|
|
1458
|
+
this.pushUiEvent('streaming', formatted);
|
|
1428
1459
|
}
|
|
1429
1460
|
}
|
|
1430
1461
|
finishStreamingFormatter(note, options) {
|
|
@@ -1436,7 +1467,7 @@ export class InteractiveShell {
|
|
|
1436
1467
|
mode: options?.mode ?? 'complete',
|
|
1437
1468
|
});
|
|
1438
1469
|
if (closing) {
|
|
1439
|
-
this.
|
|
1470
|
+
this.pushUiEvent('streaming', closing);
|
|
1440
1471
|
}
|
|
1441
1472
|
if (this.streamingThoughtBuffer.trim()) {
|
|
1442
1473
|
this.ui.controller.recordAssistantThought(this.streamingThoughtBuffer.trim());
|
|
@@ -1488,7 +1519,7 @@ export class InteractiveShell {
|
|
|
1488
1519
|
else {
|
|
1489
1520
|
this.setIdleStatus();
|
|
1490
1521
|
}
|
|
1491
|
-
this.
|
|
1522
|
+
this.syncRendererInput();
|
|
1492
1523
|
}
|
|
1493
1524
|
enqueueFollowUpAction(action) {
|
|
1494
1525
|
this.followUpQueue.push(action);
|
|
@@ -1507,7 +1538,7 @@ export class InteractiveShell {
|
|
|
1507
1538
|
this.refreshQueueIndicators();
|
|
1508
1539
|
this.scheduleQueueProcessing();
|
|
1509
1540
|
// Re-show the prompt so user can continue typing more follow-ups
|
|
1510
|
-
this.
|
|
1541
|
+
this.syncRendererInput();
|
|
1511
1542
|
}
|
|
1512
1543
|
scheduleQueueProcessing() {
|
|
1513
1544
|
if (!this.followUpQueue.length) {
|
|
@@ -1562,12 +1593,12 @@ export class InteractiveShell {
|
|
|
1562
1593
|
}
|
|
1563
1594
|
if (lower === 'clear') {
|
|
1564
1595
|
display.clear();
|
|
1565
|
-
this.
|
|
1596
|
+
this.syncRendererInput();
|
|
1566
1597
|
return;
|
|
1567
1598
|
}
|
|
1568
1599
|
if (lower === 'help') {
|
|
1569
1600
|
this.showHelp();
|
|
1570
|
-
this.
|
|
1601
|
+
this.syncRendererInput();
|
|
1571
1602
|
return;
|
|
1572
1603
|
}
|
|
1573
1604
|
if (trimmed.startsWith('/')) {
|
|
@@ -1577,12 +1608,12 @@ export class InteractiveShell {
|
|
|
1577
1608
|
// Check for continuous/infinite loop commands
|
|
1578
1609
|
if (this.isContinuousCommand(trimmed)) {
|
|
1579
1610
|
await this.processContinuousRequest(trimmed);
|
|
1580
|
-
this.
|
|
1611
|
+
this.syncRendererInput();
|
|
1581
1612
|
return;
|
|
1582
1613
|
}
|
|
1583
1614
|
// Direct execution for all inputs, including multi-line pastes
|
|
1584
1615
|
await this.processRequest(trimmed);
|
|
1585
|
-
this.
|
|
1616
|
+
this.syncRendererInput();
|
|
1586
1617
|
}
|
|
1587
1618
|
/**
|
|
1588
1619
|
* Check if the command is a continuous/infinite loop command
|
|
@@ -1627,7 +1658,7 @@ export class InteractiveShell {
|
|
|
1627
1658
|
switch (this.pendingInteraction.type) {
|
|
1628
1659
|
case 'model-loading':
|
|
1629
1660
|
display.showInfo('Still fetching model options. Please wait a moment.');
|
|
1630
|
-
this.
|
|
1661
|
+
this.syncRendererInput();
|
|
1631
1662
|
return true;
|
|
1632
1663
|
case 'model-provider':
|
|
1633
1664
|
await this.handleModelProviderSelection(input);
|
|
@@ -1658,7 +1689,7 @@ export class InteractiveShell {
|
|
|
1658
1689
|
const [command] = input.split(/\s+/);
|
|
1659
1690
|
if (!command) {
|
|
1660
1691
|
display.showWarning('Enter a slash command.');
|
|
1661
|
-
this.
|
|
1692
|
+
this.syncRendererInput();
|
|
1662
1693
|
return;
|
|
1663
1694
|
}
|
|
1664
1695
|
switch (command) {
|
|
@@ -1761,7 +1792,7 @@ export class InteractiveShell {
|
|
|
1761
1792
|
case '/discover':
|
|
1762
1793
|
await this.discoverModelsCommand();
|
|
1763
1794
|
break;
|
|
1764
|
-
//
|
|
1795
|
+
// Erosolar-CLI style commands
|
|
1765
1796
|
case '/rewind':
|
|
1766
1797
|
await this.handleRewindCommand(input);
|
|
1767
1798
|
break;
|
|
@@ -1816,7 +1847,7 @@ export class InteractiveShell {
|
|
|
1816
1847
|
}
|
|
1817
1848
|
break;
|
|
1818
1849
|
}
|
|
1819
|
-
this.
|
|
1850
|
+
this.syncRendererInput();
|
|
1820
1851
|
}
|
|
1821
1852
|
async tryCustomSlashCommand(command, fullInput) {
|
|
1822
1853
|
const custom = this.customCommandMap.get(command);
|
|
@@ -2142,7 +2173,7 @@ export class InteractiveShell {
|
|
|
2142
2173
|
display.showSystemMessage(`${headline}\n${theme.ui.muted(descriptions[this.thinkingMode])}`);
|
|
2143
2174
|
}
|
|
2144
2175
|
handleShortcutsCommand() {
|
|
2145
|
-
// Display keyboard shortcuts help (
|
|
2176
|
+
// Display keyboard shortcuts help (Erosolar-CLI style)
|
|
2146
2177
|
display.showSystemMessage(formatShortcutsHelp());
|
|
2147
2178
|
}
|
|
2148
2179
|
showFileChangeSummary() {
|
|
@@ -3465,7 +3496,7 @@ export class InteractiveShell {
|
|
|
3465
3496
|
}
|
|
3466
3497
|
this.setAutoContinueMode(value === 'on', 'command');
|
|
3467
3498
|
}
|
|
3468
|
-
// ====================
|
|
3499
|
+
// ==================== Erosolar-CLI Style Commands ====================
|
|
3469
3500
|
async handleRewindCommand(_input) {
|
|
3470
3501
|
const lines = [];
|
|
3471
3502
|
lines.push(theme.bold('Rewind / Checkpoint System'));
|
|
@@ -3624,7 +3655,7 @@ export class InteractiveShell {
|
|
|
3624
3655
|
display.clear();
|
|
3625
3656
|
clearAutosaveSnapshot(this.profile);
|
|
3626
3657
|
display.showInfo('Conversation cleared. Starting fresh.');
|
|
3627
|
-
this.
|
|
3658
|
+
this.syncRendererInput();
|
|
3628
3659
|
}
|
|
3629
3660
|
async handleResumeCommand(input) {
|
|
3630
3661
|
const tokens = input.split(/\s+/).slice(1);
|
|
@@ -3752,7 +3783,7 @@ export class InteractiveShell {
|
|
|
3752
3783
|
display.showInfo('Compacting conversation context...');
|
|
3753
3784
|
await this.performContextCompaction('Manual /compact request');
|
|
3754
3785
|
}
|
|
3755
|
-
// ==================== End
|
|
3786
|
+
// ==================== End Erosolar-CLI Style Commands ====================
|
|
3756
3787
|
updateActiveSession(summary, remember = false) {
|
|
3757
3788
|
this.activeSessionId = summary?.id ?? null;
|
|
3758
3789
|
this.activeSessionTitle = summary?.title ?? null;
|
|
@@ -3927,7 +3958,7 @@ export class InteractiveShell {
|
|
|
3927
3958
|
if (!providerOptions.length) {
|
|
3928
3959
|
display.showWarning('No providers are available.');
|
|
3929
3960
|
this.pendingInteraction = null;
|
|
3930
|
-
this.
|
|
3961
|
+
this.syncRendererInput();
|
|
3931
3962
|
return;
|
|
3932
3963
|
}
|
|
3933
3964
|
const lines = [
|
|
@@ -3948,7 +3979,7 @@ export class InteractiveShell {
|
|
|
3948
3979
|
catch (error) {
|
|
3949
3980
|
display.showError('Failed to load model list. Try again in a moment.', error);
|
|
3950
3981
|
this.pendingInteraction = null;
|
|
3951
|
-
this.
|
|
3982
|
+
this.syncRendererInput();
|
|
3952
3983
|
}
|
|
3953
3984
|
}
|
|
3954
3985
|
buildProviderOptions() {
|
|
@@ -4503,29 +4534,29 @@ export class InteractiveShell {
|
|
|
4503
4534
|
const trimmed = input.trim();
|
|
4504
4535
|
if (!trimmed) {
|
|
4505
4536
|
display.showWarning('Enter a number or type cancel.');
|
|
4506
|
-
this.
|
|
4537
|
+
this.syncRendererInput();
|
|
4507
4538
|
return;
|
|
4508
4539
|
}
|
|
4509
4540
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
4510
4541
|
this.pendingInteraction = null;
|
|
4511
4542
|
display.showInfo('Model selection cancelled.');
|
|
4512
|
-
this.
|
|
4543
|
+
this.syncRendererInput();
|
|
4513
4544
|
return;
|
|
4514
4545
|
}
|
|
4515
4546
|
const choice = Number.parseInt(trimmed, 10);
|
|
4516
4547
|
if (!Number.isFinite(choice)) {
|
|
4517
4548
|
display.showWarning('Please enter a valid number.');
|
|
4518
|
-
this.
|
|
4549
|
+
this.syncRendererInput();
|
|
4519
4550
|
return;
|
|
4520
4551
|
}
|
|
4521
4552
|
const option = pending.options[choice - 1];
|
|
4522
4553
|
if (!option) {
|
|
4523
4554
|
display.showWarning('That option is not available.');
|
|
4524
|
-
this.
|
|
4555
|
+
this.syncRendererInput();
|
|
4525
4556
|
return;
|
|
4526
4557
|
}
|
|
4527
4558
|
this.showProviderModels(option);
|
|
4528
|
-
this.
|
|
4559
|
+
this.syncRendererInput();
|
|
4529
4560
|
}
|
|
4530
4561
|
async handleModelSelection(input) {
|
|
4531
4562
|
const pending = this.pendingInteraction;
|
|
@@ -4535,35 +4566,35 @@ export class InteractiveShell {
|
|
|
4535
4566
|
const trimmed = input.trim();
|
|
4536
4567
|
if (!trimmed) {
|
|
4537
4568
|
display.showWarning('Enter a number, type "back", or type "cancel".');
|
|
4538
|
-
this.
|
|
4569
|
+
this.syncRendererInput();
|
|
4539
4570
|
return;
|
|
4540
4571
|
}
|
|
4541
4572
|
if (trimmed.toLowerCase() === 'back') {
|
|
4542
4573
|
this.showModelMenu();
|
|
4543
|
-
this.
|
|
4574
|
+
this.syncRendererInput();
|
|
4544
4575
|
return;
|
|
4545
4576
|
}
|
|
4546
4577
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
4547
4578
|
this.pendingInteraction = null;
|
|
4548
4579
|
display.showInfo('Model selection cancelled.');
|
|
4549
|
-
this.
|
|
4580
|
+
this.syncRendererInput();
|
|
4550
4581
|
return;
|
|
4551
4582
|
}
|
|
4552
4583
|
const choice = Number.parseInt(trimmed, 10);
|
|
4553
4584
|
if (!Number.isFinite(choice)) {
|
|
4554
4585
|
display.showWarning('Please enter a valid number.');
|
|
4555
|
-
this.
|
|
4586
|
+
this.syncRendererInput();
|
|
4556
4587
|
return;
|
|
4557
4588
|
}
|
|
4558
4589
|
const preset = pending.options[choice - 1];
|
|
4559
4590
|
if (!preset) {
|
|
4560
4591
|
display.showWarning('That option is not available.');
|
|
4561
|
-
this.
|
|
4592
|
+
this.syncRendererInput();
|
|
4562
4593
|
return;
|
|
4563
4594
|
}
|
|
4564
4595
|
this.pendingInteraction = null;
|
|
4565
4596
|
await this.applyModelPreset(preset);
|
|
4566
|
-
this.
|
|
4597
|
+
this.syncRendererInput();
|
|
4567
4598
|
}
|
|
4568
4599
|
async applyModelPreset(preset) {
|
|
4569
4600
|
try {
|
|
@@ -4596,30 +4627,30 @@ export class InteractiveShell {
|
|
|
4596
4627
|
const trimmed = input.trim();
|
|
4597
4628
|
if (!trimmed) {
|
|
4598
4629
|
display.showWarning('Enter a number or type cancel.');
|
|
4599
|
-
this.
|
|
4630
|
+
this.syncRendererInput();
|
|
4600
4631
|
return;
|
|
4601
4632
|
}
|
|
4602
4633
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
4603
4634
|
this.pendingInteraction = null;
|
|
4604
4635
|
display.showInfo('Secret management cancelled.');
|
|
4605
|
-
this.
|
|
4636
|
+
this.syncRendererInput();
|
|
4606
4637
|
return;
|
|
4607
4638
|
}
|
|
4608
4639
|
const choice = Number.parseInt(trimmed, 10);
|
|
4609
4640
|
if (!Number.isFinite(choice)) {
|
|
4610
4641
|
display.showWarning('Please enter a valid number.');
|
|
4611
|
-
this.
|
|
4642
|
+
this.syncRendererInput();
|
|
4612
4643
|
return;
|
|
4613
4644
|
}
|
|
4614
4645
|
const secret = pending.options[choice - 1];
|
|
4615
4646
|
if (!secret) {
|
|
4616
4647
|
display.showWarning('That option is not available.');
|
|
4617
|
-
this.
|
|
4648
|
+
this.syncRendererInput();
|
|
4618
4649
|
return;
|
|
4619
4650
|
}
|
|
4620
4651
|
display.showSystemMessage(`Enter a new value for ${secret.label} or type "cancel".`);
|
|
4621
4652
|
this.pendingInteraction = { type: 'secret-input', secret };
|
|
4622
|
-
this.
|
|
4653
|
+
this.syncRendererInput();
|
|
4623
4654
|
}
|
|
4624
4655
|
async handleSecretInput(input) {
|
|
4625
4656
|
const pending = this.pendingInteraction;
|
|
@@ -4629,14 +4660,14 @@ export class InteractiveShell {
|
|
|
4629
4660
|
const trimmed = input.trim();
|
|
4630
4661
|
if (!trimmed) {
|
|
4631
4662
|
display.showWarning('Enter a value or type cancel.');
|
|
4632
|
-
this.
|
|
4663
|
+
this.syncRendererInput();
|
|
4633
4664
|
return;
|
|
4634
4665
|
}
|
|
4635
4666
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
4636
4667
|
this.pendingInteraction = null;
|
|
4637
4668
|
this.pendingSecretRetry = null;
|
|
4638
4669
|
display.showInfo('Secret unchanged.');
|
|
4639
|
-
this.
|
|
4670
|
+
this.syncRendererInput();
|
|
4640
4671
|
return;
|
|
4641
4672
|
}
|
|
4642
4673
|
try {
|
|
@@ -4660,7 +4691,7 @@ export class InteractiveShell {
|
|
|
4660
4691
|
this.pendingInteraction = null;
|
|
4661
4692
|
this.pendingSecretRetry = null;
|
|
4662
4693
|
}
|
|
4663
|
-
this.
|
|
4694
|
+
this.syncRendererInput();
|
|
4664
4695
|
}
|
|
4665
4696
|
async processRequest(request) {
|
|
4666
4697
|
if (this.isProcessing) {
|
|
@@ -4680,7 +4711,8 @@ export class InteractiveShell {
|
|
|
4680
4711
|
this.uiUpdates.setMode('processing');
|
|
4681
4712
|
this.terminalInput.setStreaming(true);
|
|
4682
4713
|
// Keep the persistent input/control bar active as we transition into streaming.
|
|
4683
|
-
this.
|
|
4714
|
+
this.syncRendererInput();
|
|
4715
|
+
this.uiRenderer?.render();
|
|
4684
4716
|
const requestStartTime = Date.now(); // Alpha Zero 2 timing
|
|
4685
4717
|
// Clear previous parallel agents and start fresh for new request
|
|
4686
4718
|
const parallelManager = getParallelAgentManager();
|
|
@@ -4766,7 +4798,7 @@ export class InteractiveShell {
|
|
|
4766
4798
|
this.updateStatusMessage(null);
|
|
4767
4799
|
queueMicrotask(() => this.uiUpdates.setMode('idle'));
|
|
4768
4800
|
// CRITICAL: Ensure readline prompt is active for user input
|
|
4769
|
-
//
|
|
4801
|
+
// Erosolar-CLI style: New prompt naturally appears at bottom
|
|
4770
4802
|
this.ensureReadlineReady();
|
|
4771
4803
|
this.scheduleQueueProcessing();
|
|
4772
4804
|
this.refreshQueueIndicators();
|
|
@@ -4996,7 +5028,7 @@ What's the next action?`;
|
|
|
4996
5028
|
this.updateStatusMessage(null);
|
|
4997
5029
|
queueMicrotask(() => this.uiUpdates.setMode('idle'));
|
|
4998
5030
|
// CRITICAL: Ensure readline prompt is active for user input
|
|
4999
|
-
//
|
|
5031
|
+
// Erosolar-CLI style: New prompt naturally appears at bottom
|
|
5000
5032
|
this.ensureReadlineReady();
|
|
5001
5033
|
this.scheduleQueueProcessing();
|
|
5002
5034
|
this.refreshQueueIndicators();
|
|
@@ -5607,7 +5639,7 @@ Return ONLY JSON array:
|
|
|
5607
5639
|
void this.runAutoQualityChecks('final-response', finalContent);
|
|
5608
5640
|
}
|
|
5609
5641
|
else {
|
|
5610
|
-
// Non-final message = narrative text before tool calls (
|
|
5642
|
+
// Non-final message = narrative text before tool calls (Erosolar-CLI style)
|
|
5611
5643
|
// Stop spinner and show the narrative text directly
|
|
5612
5644
|
display.stopThinking();
|
|
5613
5645
|
// Skip display if content was already streamed to avoid double-display
|
|
@@ -5654,19 +5686,19 @@ Return ONLY JSON array:
|
|
|
5654
5686
|
this.updateContextUsage(percentage);
|
|
5655
5687
|
}
|
|
5656
5688
|
// Ensure prompt remains visible at bottom after context messages
|
|
5657
|
-
this.
|
|
5689
|
+
this.syncRendererInput();
|
|
5658
5690
|
},
|
|
5659
5691
|
onContinueAfterRecovery: () => {
|
|
5660
5692
|
// Update UI to show we're continuing after context recovery
|
|
5661
5693
|
display.showSystemMessage(`🔄 Continuing after context recovery...`);
|
|
5662
5694
|
this.updateStatusMessage('Retrying with reduced context...');
|
|
5663
|
-
this.
|
|
5695
|
+
this.syncRendererInput();
|
|
5664
5696
|
},
|
|
5665
5697
|
onAutoContinue: (attempt, maxAttempts, _message) => {
|
|
5666
5698
|
// Show auto-continue progress in UI
|
|
5667
5699
|
display.showSystemMessage(`🔄 Auto-continue (${attempt}/${maxAttempts}): Model expressed intent, prompting to act...`);
|
|
5668
5700
|
this.updateStatusMessage('Auto-continuing...');
|
|
5669
|
-
this.
|
|
5701
|
+
this.syncRendererInput();
|
|
5670
5702
|
},
|
|
5671
5703
|
onCancelled: () => {
|
|
5672
5704
|
// Update UI to show operation was cancelled
|