erosolar-cli 1.7.429 → 1.7.431
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/preferences.d.ts +3 -1
- package/dist/core/preferences.d.ts.map +1 -1
- package/dist/core/preferences.js +4 -2
- package/dist/core/preferences.js.map +1 -1
- 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 +120 -88
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/systemPrompt.d.ts.map +1 -1
- package/dist/shell/systemPrompt.js +14 -34
- package/dist/shell/systemPrompt.js.map +1 -1
- package/dist/shell/terminalInputAdapter.d.ts +77 -85
- package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
- package/dist/shell/terminalInputAdapter.js +163 -223
- 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 +188 -0
- package/dist/ui/UnifiedUIRenderer.d.ts.map +1 -0
- package/dist/ui/UnifiedUIRenderer.js +581 -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 +364 -926
- 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;
|
|
@@ -257,7 +259,12 @@ export class InteractiveShell {
|
|
|
257
259
|
for (const definition of createSkillTools({ repository: this.skillRepository })) {
|
|
258
260
|
this.skillToolHandlers.set(definition.name, definition.handler);
|
|
259
261
|
}
|
|
260
|
-
//
|
|
262
|
+
// Create unified UI renderer first (single instance shared by all components)
|
|
263
|
+
const canUseRenderer = output.isTTY;
|
|
264
|
+
this.uiRenderer = canUseRenderer ? new UnifiedUIRenderer(output, input) : null;
|
|
265
|
+
this.useUnifiedRenderer = !!this.uiRenderer;
|
|
266
|
+
display.setRenderer(this.uiRenderer);
|
|
267
|
+
// Initialize unified terminal input handler with shared renderer
|
|
261
268
|
this.terminalInput = new TerminalInputAdapter(input, output, {
|
|
262
269
|
onSubmit: (text) => this.processInput(text),
|
|
263
270
|
onQueue: (text) => this.handleQueuedInput(text),
|
|
@@ -269,7 +276,7 @@ export class InteractiveShell {
|
|
|
269
276
|
onToggleAutoContinue: () => this.toggleAutoContinueMode(),
|
|
270
277
|
onToggleThinking: () => this.cycleThinkingMode(),
|
|
271
278
|
onClearContext: () => this.handleClearContext(),
|
|
272
|
-
});
|
|
279
|
+
}, this.uiRenderer ?? undefined);
|
|
273
280
|
// Initialize Alpha Zero 2 metrics tracking
|
|
274
281
|
this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
|
|
275
282
|
this.setupStatusTracking();
|
|
@@ -292,7 +299,8 @@ export class InteractiveShell {
|
|
|
292
299
|
}
|
|
293
300
|
// Render chat box immediately using the streaming UI lifecycle
|
|
294
301
|
this.refreshControlBar();
|
|
295
|
-
this.
|
|
302
|
+
this.syncRendererInput();
|
|
303
|
+
this.uiRenderer?.render();
|
|
296
304
|
this.rebuildAgent();
|
|
297
305
|
this.setupHandlers();
|
|
298
306
|
this.refreshSessionContext();
|
|
@@ -393,7 +401,7 @@ export class InteractiveShell {
|
|
|
393
401
|
const model = `${this.sessionState.model} @ ${this.providerLabel(this.sessionState.provider)}`;
|
|
394
402
|
const workspace = this.workingDir;
|
|
395
403
|
const lines = [
|
|
396
|
-
'
|
|
404
|
+
'Erosolar-CLI',
|
|
397
405
|
welcome,
|
|
398
406
|
model,
|
|
399
407
|
workspace,
|
|
@@ -401,6 +409,20 @@ export class InteractiveShell {
|
|
|
401
409
|
];
|
|
402
410
|
return lines.join('\n');
|
|
403
411
|
}
|
|
412
|
+
syncRendererInput() {
|
|
413
|
+
// No-op: UnifiedUIRenderer handles its own input state now
|
|
414
|
+
// The new architecture doesn't require separate input syncing
|
|
415
|
+
}
|
|
416
|
+
pushUiEvent(type, content) {
|
|
417
|
+
if (!content) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
if (this.useUnifiedRenderer && this.uiRenderer) {
|
|
421
|
+
this.uiRenderer.addEvent(type, content);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
display.stream(content);
|
|
425
|
+
}
|
|
404
426
|
/**
|
|
405
427
|
* Stream a content block as a single event, isolating it from adjacent output.
|
|
406
428
|
*/
|
|
@@ -409,6 +431,10 @@ export class InteractiveShell {
|
|
|
409
431
|
if (!normalized) {
|
|
410
432
|
return;
|
|
411
433
|
}
|
|
434
|
+
if (this.useUnifiedRenderer && this.uiRenderer) {
|
|
435
|
+
this.uiRenderer.addEvent('banner', normalized);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
412
438
|
const bullet = `${theme.info('⏺')} `;
|
|
413
439
|
const indent = ' ';
|
|
414
440
|
const lines = normalized.split('\n').map(line => line.trimEnd());
|
|
@@ -416,11 +442,18 @@ export class InteractiveShell {
|
|
|
416
442
|
.map((line, index) => (index === 0 ? `${bullet}${line}` : `${indent}${line}`))
|
|
417
443
|
.join('\n');
|
|
418
444
|
const block = `\n${formatted}\n`;
|
|
419
|
-
this.
|
|
445
|
+
this.pushUiEvent('raw', block);
|
|
420
446
|
}
|
|
421
447
|
async start(initialPrompt) {
|
|
422
448
|
// Always use the scroll-region streaming layout from the outset
|
|
423
|
-
this.
|
|
449
|
+
if (this.useUnifiedRenderer && this.uiRenderer) {
|
|
450
|
+
this.uiRenderer.initialize();
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
this.terminalInput.clearScreen();
|
|
454
|
+
this.terminalInput.resetContentPosition();
|
|
455
|
+
}
|
|
456
|
+
this.syncRendererInput();
|
|
424
457
|
this.showWelcomeBanner();
|
|
425
458
|
if (initialPrompt) {
|
|
426
459
|
await this.processInputBlock(initialPrompt);
|
|
@@ -428,7 +461,7 @@ export class InteractiveShell {
|
|
|
428
461
|
}
|
|
429
462
|
this.showLaunchCommandPalette();
|
|
430
463
|
// Ensure the terminal input is visible
|
|
431
|
-
this.
|
|
464
|
+
this.syncRendererInput();
|
|
432
465
|
}
|
|
433
466
|
showLaunchCommandPalette() {
|
|
434
467
|
// Disabled: Quick commands palette takes up too much space
|
|
@@ -547,6 +580,7 @@ export class InteractiveShell {
|
|
|
547
580
|
*/
|
|
548
581
|
handleInputChange(text) {
|
|
549
582
|
this.currentInput = text;
|
|
583
|
+
this.syncRendererInput();
|
|
550
584
|
if (text.length > 0) {
|
|
551
585
|
this.resetCtrlCSequence();
|
|
552
586
|
}
|
|
@@ -568,7 +602,7 @@ export class InteractiveShell {
|
|
|
568
602
|
display.showSystemMessage('✏️ Display edits mode enabled.');
|
|
569
603
|
}
|
|
570
604
|
}
|
|
571
|
-
this.
|
|
605
|
+
this.syncRendererInput();
|
|
572
606
|
}
|
|
573
607
|
toggleVerificationMode() {
|
|
574
608
|
this.setVerificationMode(!this.verificationEnabled, 'shortcut');
|
|
@@ -689,7 +723,7 @@ export class InteractiveShell {
|
|
|
689
723
|
if (['n', 'no', 'cancel', '/cancel'].includes(lower)) {
|
|
690
724
|
this.pendingPermissionInput = null;
|
|
691
725
|
display.showInfo('Request cancelled.');
|
|
692
|
-
this.
|
|
726
|
+
this.syncRendererInput();
|
|
693
727
|
return null;
|
|
694
728
|
}
|
|
695
729
|
// Treat any other input as a replacement request that also needs confirmation
|
|
@@ -707,7 +741,7 @@ export class InteractiveShell {
|
|
|
707
741
|
]
|
|
708
742
|
.filter(Boolean)
|
|
709
743
|
.join('\n'));
|
|
710
|
-
this.
|
|
744
|
+
this.syncRendererInput();
|
|
711
745
|
}
|
|
712
746
|
/**
|
|
713
747
|
* Handle Ctrl+C presses in three stages:
|
|
@@ -772,6 +806,7 @@ export class InteractiveShell {
|
|
|
772
806
|
this.stopStreamingHeartbeat('quit', { quiet: true });
|
|
773
807
|
this.endAiRuntime();
|
|
774
808
|
this.uiUpdates.dispose();
|
|
809
|
+
this.uiRenderer?.cleanup();
|
|
775
810
|
this.clearPromptRefreshTimer();
|
|
776
811
|
this.teardownStatusTracking();
|
|
777
812
|
// Clear global AI enhancer (explore tool will work offline after this)
|
|
@@ -831,26 +866,26 @@ export class InteractiveShell {
|
|
|
831
866
|
const trimmed = input.trim();
|
|
832
867
|
if (!trimmed) {
|
|
833
868
|
display.showWarning('Enter a number, "save", "defaults", or "cancel".');
|
|
834
|
-
this.
|
|
869
|
+
this.syncRendererInput();
|
|
835
870
|
return;
|
|
836
871
|
}
|
|
837
872
|
const normalized = trimmed.toLowerCase();
|
|
838
873
|
if (normalized === 'cancel') {
|
|
839
874
|
this.pendingInteraction = null;
|
|
840
875
|
display.showInfo('Tool selection cancelled.');
|
|
841
|
-
this.
|
|
876
|
+
this.syncRendererInput();
|
|
842
877
|
return;
|
|
843
878
|
}
|
|
844
879
|
if (normalized === 'defaults') {
|
|
845
880
|
pending.selection = buildEnabledToolSet(null);
|
|
846
881
|
this.renderToolMenu(pending);
|
|
847
|
-
this.
|
|
882
|
+
this.syncRendererInput();
|
|
848
883
|
return;
|
|
849
884
|
}
|
|
850
885
|
if (normalized === 'save') {
|
|
851
886
|
await this.persistToolSelection(pending);
|
|
852
887
|
this.pendingInteraction = null;
|
|
853
|
-
this.
|
|
888
|
+
this.syncRendererInput();
|
|
854
889
|
return;
|
|
855
890
|
}
|
|
856
891
|
const choice = Number.parseInt(trimmed, 10);
|
|
@@ -873,11 +908,11 @@ export class InteractiveShell {
|
|
|
873
908
|
}
|
|
874
909
|
this.renderToolMenu(pending);
|
|
875
910
|
}
|
|
876
|
-
this.
|
|
911
|
+
this.syncRendererInput();
|
|
877
912
|
return;
|
|
878
913
|
}
|
|
879
914
|
display.showWarning('Enter a number, "save", "defaults", or "cancel".');
|
|
880
|
-
this.
|
|
915
|
+
this.syncRendererInput();
|
|
881
916
|
}
|
|
882
917
|
async persistToolSelection(interaction) {
|
|
883
918
|
if (setsEqual(interaction.selection, interaction.initialSelection)) {
|
|
@@ -905,36 +940,36 @@ export class InteractiveShell {
|
|
|
905
940
|
if (!this.agentMenu) {
|
|
906
941
|
this.pendingInteraction = null;
|
|
907
942
|
display.showWarning('Agent selection is unavailable in this CLI.');
|
|
908
|
-
this.
|
|
943
|
+
this.syncRendererInput();
|
|
909
944
|
return;
|
|
910
945
|
}
|
|
911
946
|
const trimmed = input.trim();
|
|
912
947
|
if (!trimmed) {
|
|
913
948
|
display.showWarning('Enter a number or type "cancel".');
|
|
914
|
-
this.
|
|
949
|
+
this.syncRendererInput();
|
|
915
950
|
return;
|
|
916
951
|
}
|
|
917
952
|
if (trimmed.toLowerCase() === 'cancel') {
|
|
918
953
|
this.pendingInteraction = null;
|
|
919
954
|
display.showInfo('Agent selection cancelled.');
|
|
920
|
-
this.
|
|
955
|
+
this.syncRendererInput();
|
|
921
956
|
return;
|
|
922
957
|
}
|
|
923
958
|
const choice = Number.parseInt(trimmed, 10);
|
|
924
959
|
if (!Number.isFinite(choice)) {
|
|
925
960
|
display.showWarning('Please enter a valid number.');
|
|
926
|
-
this.
|
|
961
|
+
this.syncRendererInput();
|
|
927
962
|
return;
|
|
928
963
|
}
|
|
929
964
|
const option = pending.options[choice - 1];
|
|
930
965
|
if (!option) {
|
|
931
966
|
display.showWarning('That option is not available.');
|
|
932
|
-
this.
|
|
967
|
+
this.syncRendererInput();
|
|
933
968
|
return;
|
|
934
969
|
}
|
|
935
970
|
await this.persistAgentSelection(option.name);
|
|
936
971
|
this.pendingInteraction = null;
|
|
937
|
-
this.
|
|
972
|
+
this.syncRendererInput();
|
|
938
973
|
}
|
|
939
974
|
async persistAgentSelection(profileName) {
|
|
940
975
|
if (!this.agentMenu) {
|
|
@@ -1007,7 +1042,7 @@ export class InteractiveShell {
|
|
|
1007
1042
|
lines.push(` ${theme.primary('[text]')} Submit your own solution instead`);
|
|
1008
1043
|
lines.push('');
|
|
1009
1044
|
display.showSystemMessage(lines.join('\n'));
|
|
1010
|
-
this.
|
|
1045
|
+
this.syncRendererInput();
|
|
1011
1046
|
}
|
|
1012
1047
|
async handlePlanApprovalInput(input) {
|
|
1013
1048
|
const pending = this.pendingInteraction;
|
|
@@ -1016,7 +1051,7 @@ export class InteractiveShell {
|
|
|
1016
1051
|
const trimmed = input.trim();
|
|
1017
1052
|
if (!trimmed) {
|
|
1018
1053
|
display.showWarning('Enter a command or your own solution.');
|
|
1019
|
-
this.
|
|
1054
|
+
this.syncRendererInput();
|
|
1020
1055
|
return;
|
|
1021
1056
|
}
|
|
1022
1057
|
const lower = trimmed.toLowerCase();
|
|
@@ -1024,7 +1059,7 @@ export class InteractiveShell {
|
|
|
1024
1059
|
if (lower === 'cancel' || lower === 'c') {
|
|
1025
1060
|
this.pendingInteraction = null;
|
|
1026
1061
|
display.showInfo('Plan cancelled. You can continue with a different approach.');
|
|
1027
|
-
this.
|
|
1062
|
+
this.syncRendererInput();
|
|
1028
1063
|
return;
|
|
1029
1064
|
}
|
|
1030
1065
|
// Select all
|
|
@@ -1044,7 +1079,7 @@ export class InteractiveShell {
|
|
|
1044
1079
|
const selectedSteps = pending.steps.filter(s => pending.selectedSteps.has(s.id));
|
|
1045
1080
|
if (selectedSteps.length === 0) {
|
|
1046
1081
|
display.showWarning('No steps selected. Select steps or enter your own solution.');
|
|
1047
|
-
this.
|
|
1082
|
+
this.syncRendererInput();
|
|
1048
1083
|
return;
|
|
1049
1084
|
}
|
|
1050
1085
|
this.pendingInteraction = null;
|
|
@@ -1077,7 +1112,7 @@ export class InteractiveShell {
|
|
|
1077
1112
|
return;
|
|
1078
1113
|
}
|
|
1079
1114
|
display.showWarning('Invalid input. Enter a step number, command (go/cancel/all/none), or your own solution.');
|
|
1080
|
-
this.
|
|
1115
|
+
this.syncRendererInput();
|
|
1081
1116
|
}
|
|
1082
1117
|
setupHandlers() {
|
|
1083
1118
|
// Handle terminal resize
|
|
@@ -1085,7 +1120,7 @@ export class InteractiveShell {
|
|
|
1085
1120
|
this.terminalInput.handleResize();
|
|
1086
1121
|
});
|
|
1087
1122
|
// Show initial input UI
|
|
1088
|
-
this.
|
|
1123
|
+
this.syncRendererInput();
|
|
1089
1124
|
}
|
|
1090
1125
|
/**
|
|
1091
1126
|
* Set up command autocomplete with all available slash commands.
|
|
@@ -1198,7 +1233,7 @@ export class InteractiveShell {
|
|
|
1198
1233
|
thinkingHotkey: 'tab',
|
|
1199
1234
|
});
|
|
1200
1235
|
this.refreshStatusLine();
|
|
1201
|
-
this.
|
|
1236
|
+
this.syncRendererInput();
|
|
1202
1237
|
}
|
|
1203
1238
|
writeLocked(content) {
|
|
1204
1239
|
if (!content) {
|
|
@@ -1236,7 +1271,7 @@ export class InteractiveShell {
|
|
|
1236
1271
|
/**
|
|
1237
1272
|
* Refresh the status line in the persistent input area.
|
|
1238
1273
|
* Uses combined status display: streaming label + override + main status.
|
|
1239
|
-
* All three can be shown simultaneously (
|
|
1274
|
+
* All three can be shown simultaneously (Erosolar-CLI style).
|
|
1240
1275
|
*/
|
|
1241
1276
|
refreshStatusLine(forceRender = false) {
|
|
1242
1277
|
// Set streaming label (spinner + label) - shows during streaming
|
|
@@ -1263,8 +1298,10 @@ export class InteractiveShell {
|
|
|
1263
1298
|
model: this.sessionState.model,
|
|
1264
1299
|
provider: this.providerLabel(this.sessionState.provider),
|
|
1265
1300
|
});
|
|
1301
|
+
this.syncRendererInput();
|
|
1266
1302
|
if (forceRender) {
|
|
1267
|
-
this.
|
|
1303
|
+
this.syncRendererInput();
|
|
1304
|
+
this.uiRenderer?.render();
|
|
1268
1305
|
}
|
|
1269
1306
|
}
|
|
1270
1307
|
/**
|
|
@@ -1317,13 +1354,13 @@ export class InteractiveShell {
|
|
|
1317
1354
|
}
|
|
1318
1355
|
this.lastLoggedPrompt = normalized;
|
|
1319
1356
|
this.lastLoggedPromptAt = now;
|
|
1320
|
-
//
|
|
1321
|
-
|
|
1322
|
-
this.streamEventBlock(formatted);
|
|
1357
|
+
// Note: User prompt display is now handled by UnifiedUIRenderer.displayUserPrompt()
|
|
1358
|
+
// This method just tracks the last prompt for deduplication purposes
|
|
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
|