erosolar-cli 2.1.63 → 2.1.65

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.
@@ -53,16 +53,22 @@ export declare class UnifiedUIRenderer extends EventEmitter {
53
53
  private statusMessage;
54
54
  private statusOverride;
55
55
  private statusStreaming;
56
+ private streamingSpinner;
57
+ private thinkingIndicator;
58
+ private contextMeter;
59
+ private spinnerFrame;
60
+ private spinnerInterval;
61
+ private compactingStatusMessage;
62
+ private compactingStatusFrame;
63
+ private compactingStatusInterval;
64
+ private readonly compactingSpinnerFrames;
56
65
  private statusMeta;
57
66
  private toggleState;
58
67
  private formatHotkey;
59
68
  private lastPromptEvent;
60
69
  private promptHeight;
61
70
  private lastOverlayHeight;
62
- private lastPromptIndex;
63
- private readonly overlayBottomPadding;
64
71
  private inlinePanel;
65
- private overlayInvalidated;
66
72
  private hasConversationContent;
67
73
  private isPromptActive;
68
74
  private inputRenderOffset;
@@ -83,7 +89,6 @@ export declare class UnifiedUIRenderer extends EventEmitter {
83
89
  private hasRenderedPrompt;
84
90
  private hasEverRenderedOverlay;
85
91
  private lastOverlay;
86
- private contentRowCount;
87
92
  private allowPromptRender;
88
93
  private inputCapture;
89
94
  constructor(output?: NodeJS.WriteStream, input?: NodeJS.ReadStream, options?: UnifiedUIRendererOptions);
@@ -132,6 +137,14 @@ export declare class UnifiedUIRenderer extends EventEmitter {
132
137
  */
133
138
  addCompactBlock(content: string, label?: string): void;
134
139
  setMode(mode: 'idle' | 'streaming'): void;
140
+ /**
141
+ * Start the animated spinner for streaming status
142
+ */
143
+ private startSpinnerAnimation;
144
+ /**
145
+ * Stop the animated spinner
146
+ */
147
+ private stopSpinnerAnimation;
135
148
  getMode(): 'idle' | 'streaming';
136
149
  updateStatus(message: string | null): void;
137
150
  updateStatusBundle(status: {
@@ -187,12 +200,20 @@ export declare class UnifiedUIRenderer extends EventEmitter {
187
200
  private visibleLength;
188
201
  private stripAnsi;
189
202
  private truncateLine;
190
- private clearOverlayRows;
191
203
  getBuffer(): string;
192
204
  getCursor(): number;
193
205
  setBuffer(text: string, cursorPos?: number): void;
194
206
  clearBuffer(): void;
195
207
  setModeStatus(status: string | null): void;
208
+ /**
209
+ * Show a compacting status with animated spinner (Claude Code style)
210
+ * Uses ✻ character with animation to indicate context compaction in progress
211
+ */
212
+ showCompactingStatus(message: string): void;
213
+ /**
214
+ * Hide the compacting status and stop spinner animation
215
+ */
216
+ hideCompactingStatus(): void;
196
217
  emitPrompt(content: string): void;
197
218
  /**
198
219
  * Display user prompt immediately in scrollback (Claude Code style)
@@ -1 +1 @@
1
- {"version":3,"file":"UnifiedUIRenderer.d.ts","sourceRoot":"","sources":["../../src/ui/UnifiedUIRenderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"UnifiedUIRenderer.d.ts","sourceRoot":"","sources":["../../src/ui/UnifiedUIRenderer.ts"],"names":[],"mappings":"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"}
@@ -11,9 +11,9 @@
11
11
  import * as readline from 'node:readline';
12
12
  import { EventEmitter } from 'node:events';
13
13
  import { homedir } from 'node:os';
14
- import { theme } from './theme.js';
14
+ import { theme, spinnerFrames } from './theme.js';
15
15
  import { isPlainOutputMode } from './outputMode.js';
16
- import { renderDivider } from './unified/layout.js';
16
+ import { ContextMeter, disposeAnimations } from './animatedStatus.js';
17
17
  const ESC = {
18
18
  HIDE_CURSOR: '\x1b[?25l',
19
19
  SHOW_CURSOR: '\x1b[?25h',
@@ -54,6 +54,17 @@ export class UnifiedUIRenderer extends EventEmitter {
54
54
  statusMessage = null;
55
55
  statusOverride = null;
56
56
  statusStreaming = null;
57
+ // Animated UI components
58
+ streamingSpinner = null;
59
+ thinkingIndicator = null;
60
+ contextMeter;
61
+ spinnerFrame = 0;
62
+ spinnerInterval = null;
63
+ // Compacting status animation
64
+ compactingStatusMessage = '';
65
+ compactingStatusFrame = 0;
66
+ compactingStatusInterval = null;
67
+ compactingSpinnerFrames = ['✻', '✼', '✻', '✺'];
57
68
  statusMeta = {};
58
69
  toggleState = {
59
70
  verificationEnabled: false,
@@ -69,10 +80,7 @@ export class UnifiedUIRenderer extends EventEmitter {
69
80
  lastPromptEvent = null;
70
81
  promptHeight = 0;
71
82
  lastOverlayHeight = 0;
72
- lastPromptIndex = 0;
73
- overlayBottomPadding = 1;
74
83
  inlinePanel = [];
75
- overlayInvalidated = false;
76
84
  hasConversationContent = false;
77
85
  isPromptActive = false;
78
86
  inputRenderOffset = 0;
@@ -91,9 +99,8 @@ export class UnifiedUIRenderer extends EventEmitter {
91
99
  lastRenderedEventKey = null;
92
100
  lastOutputEndedWithNewline = true;
93
101
  hasRenderedPrompt = false;
94
- hasEverRenderedOverlay = false; // Track if we've ever rendered to prevent first-render scrollback pollution
102
+ hasEverRenderedOverlay = false; // Track if we've ever rendered for inline clearing
95
103
  lastOverlay = null;
96
- contentRowCount = 0; // Track how many rows of content have been written (for flow-based positioning)
97
104
  allowPromptRender = true;
98
105
  inputCapture = null;
99
106
  constructor(output = process.stdout, input = process.stdin, options) {
@@ -102,6 +109,8 @@ export class UnifiedUIRenderer extends EventEmitter {
102
109
  this.input = input;
103
110
  this.interactive = Boolean(this.output.isTTY && this.input.isTTY && !process.env['CI']);
104
111
  this.plainMode = isPlainOutputMode() || !this.interactive;
112
+ // Initialize animated components
113
+ this.contextMeter = new ContextMeter();
105
114
  this.rl = readline.createInterface({
106
115
  input: this.input,
107
116
  output: this.output,
@@ -148,6 +157,21 @@ export class UnifiedUIRenderer extends EventEmitter {
148
157
  cleanup() {
149
158
  this.cancelInputCapture(new Error('Renderer disposed'));
150
159
  this.cancelPlainPasteCapture();
160
+ // Stop any running animations
161
+ if (this.spinnerInterval) {
162
+ clearInterval(this.spinnerInterval);
163
+ this.spinnerInterval = null;
164
+ }
165
+ if (this.streamingSpinner) {
166
+ this.streamingSpinner.stop();
167
+ this.streamingSpinner = null;
168
+ }
169
+ if (this.thinkingIndicator) {
170
+ this.thinkingIndicator.stop();
171
+ this.thinkingIndicator = null;
172
+ }
173
+ this.contextMeter.dispose();
174
+ disposeAnimations();
151
175
  if (!this.interactive) {
152
176
  this.rl.close();
153
177
  return;
@@ -801,11 +825,6 @@ export class UnifiedUIRenderer extends EventEmitter {
801
825
  }
802
826
  this.output.write(formatted);
803
827
  this.lastOutputEndedWithNewline = formatted.endsWith('\n');
804
- // Track content row count for flow-based overlay positioning
805
- const newlines = (formatted.match(/\n/g) || []).length;
806
- this.contentRowCount += newlines + (this.lastOutputEndedWithNewline ? 0 : 1);
807
- // Overlay must be re-anchored after new scrollback is written
808
- this.overlayInvalidated = true;
809
828
  // Don't re-render prompt after every event - wait for queue to finish
810
829
  // This prevents premature prompt rendering that cuts off responses
811
830
  }
@@ -851,10 +870,19 @@ export class UnifiedUIRenderer extends EventEmitter {
851
870
  case 'prompt':
852
871
  return `\n> ${event.content}\n`; // Plain > like Claude Code
853
872
  case 'thought': {
854
- // Claude Code style: first line, then indented continuation
873
+ // Enhanced thought display with animated thinking indicator style
874
+ // Uses ◐ symbol for thinking with muted styling to distinguish from content
875
+ const thinkingIcon = theme.thinking?.icon ? theme.thinking.icon('◐') : theme.ui.muted('◐');
876
+ const thinkingLabel = theme.thinking?.label ? theme.thinking.label('Thinking') : theme.ui.muted('Thinking');
855
877
  const lines = event.content.split('\n');
878
+ // Show thinking header with first line, then indent continuation
856
879
  const formatted = lines
857
- .map((line, i) => (i === 0 ? `${bullet} ${line}` : ` ${line}`))
880
+ .map((line, i) => {
881
+ if (i === 0) {
882
+ return `${thinkingIcon} ${thinkingLabel}: ${theme.ui.muted(line)}`;
883
+ }
884
+ return ` ${theme.ui.muted(line)}`;
885
+ })
858
886
  .join('\n');
859
887
  return `\n${formatted}\n`;
860
888
  }
@@ -912,6 +940,13 @@ export class UnifiedUIRenderer extends EventEmitter {
912
940
  setMode(mode) {
913
941
  const wasStreaming = this.mode === 'streaming';
914
942
  this.mode = mode;
943
+ // Start/stop spinner animation based on streaming state
944
+ if (mode === 'streaming' && !wasStreaming) {
945
+ this.startSpinnerAnimation();
946
+ }
947
+ else if (mode === 'idle' && wasStreaming) {
948
+ this.stopSpinnerAnimation();
949
+ }
915
950
  if (wasStreaming && mode === 'idle' && !this.lastOutputEndedWithNewline) {
916
951
  // Finish streaming on a fresh line so the next prompt/event doesn't collide
917
952
  this.write('\n');
@@ -922,6 +957,31 @@ export class UnifiedUIRenderer extends EventEmitter {
922
957
  this.renderPrompt();
923
958
  }
924
959
  }
960
+ /**
961
+ * Start the animated spinner for streaming status
962
+ */
963
+ startSpinnerAnimation() {
964
+ if (this.spinnerInterval)
965
+ return; // Already running
966
+ this.spinnerFrame = 0;
967
+ this.spinnerInterval = setInterval(() => {
968
+ this.spinnerFrame = (this.spinnerFrame + 1) % spinnerFrames.braille.length;
969
+ // Re-render to show updated spinner frame
970
+ if (!this.plainMode && this.mode === 'streaming') {
971
+ this.renderPrompt();
972
+ }
973
+ }, 80); // ~12 FPS for smooth spinner animation
974
+ }
975
+ /**
976
+ * Stop the animated spinner
977
+ */
978
+ stopSpinnerAnimation() {
979
+ if (this.spinnerInterval) {
980
+ clearInterval(this.spinnerInterval);
981
+ this.spinnerInterval = null;
982
+ }
983
+ this.spinnerFrame = 0;
984
+ }
925
985
  getMode() {
926
986
  return this.mode;
927
987
  }
@@ -1017,13 +1077,9 @@ export class UnifiedUIRenderer extends EventEmitter {
1017
1077
  if (!this.allowPromptRender) {
1018
1078
  return;
1019
1079
  }
1020
- // Rich mode: inline overlay anchored to current scrollback (no full-screen clear)
1080
+ // Rich mode: inline rendering (no full-screen overlay)
1021
1081
  this.updateTerminalSize();
1022
1082
  const maxWidth = this.safeWidth();
1023
- if (this.lastRenderWidth !== null && maxWidth !== this.lastRenderWidth) {
1024
- // Terminal resized; force a clean anchor so the overlay doesn't jitter.
1025
- this.overlayInvalidated = true;
1026
- }
1027
1083
  this.lastRenderWidth = maxWidth;
1028
1084
  const overlay = this.buildOverlayLines();
1029
1085
  if (!overlay.lines.length) {
@@ -1035,53 +1091,39 @@ export class UnifiedUIRenderer extends EventEmitter {
1035
1091
  }
1036
1092
  let promptIndex = Math.max(0, Math.min(overlay.promptIndex, renderedLines.length - 1));
1037
1093
  let height = renderedLines.length;
1038
- // Keep at least one free line below the overlay so typing always has breathing room
1039
- const bottomPadding = this.overlayBottomPadding;
1040
1094
  const totalRows = this.rows || 24;
1041
- const availableRows = Math.max(1, totalRows - bottomPadding);
1042
- if (height > availableRows) {
1043
- renderedLines.splice(availableRows);
1044
- height = renderedLines.length;
1045
- promptIndex = Math.max(0, Math.min(promptIndex, height - 1));
1046
- }
1047
- // Position overlay immediately after content (flow-based) rather than pinned to bottom
1048
- // Only pin to bottom if content + overlay would exceed screen height
1049
- const contentEndRow = Math.min(this.contentRowCount + 1, totalRows);
1050
- const flowBasedStartRow = contentEndRow;
1051
- const bottomPinnedStartRow = Math.max(1, availableRows - height + 1);
1052
- // Use flow-based positioning when content is small, bottom-pinned when content fills screen
1053
- const startRow = (flowBasedStartRow + height <= availableRows)
1054
- ? flowBasedStartRow
1055
- : bottomPinnedStartRow;
1056
- const promptRow = startRow + promptIndex;
1057
- const promptCol = Math.min(Math.max(1, 3 + this.cursor), this.cols || 80);
1058
- // Clear any previous overlay footprint (status, prompt, controls) to avoid leaking into scrollback
1059
- this.clearOverlayRows(height, startRow);
1060
- if (bottomPadding > 0 && startRow + height <= totalRows) {
1061
- this.write(ESC.TO(startRow + height, 1));
1062
- this.write(ESC.CLEAR_LINE);
1095
+ // PURE INLINE MODE: Always render the prompt area inline, flowing naturally.
1096
+ // No overlay mode - content flows like Claude Code.
1097
+ // Clear any previous inline render by moving up and clearing
1098
+ if (this.hasEverRenderedOverlay && this.lastOverlayHeight > 0) {
1099
+ // Move to start of previous prompt and clear it
1100
+ const linesToClear = this.lastOverlayHeight;
1101
+ for (let i = 0; i < linesToClear; i++) {
1102
+ this.write('\x1b[A'); // Move up
1103
+ this.write(ESC.CLEAR_LINE);
1104
+ }
1063
1105
  }
1064
- // Render overlay lines in place without pushing scrollback
1065
- for (let idx = 0; idx < height; idx++) {
1066
- const row = startRow + idx;
1067
- const line = renderedLines[idx] ?? '';
1068
- this.write(ESC.TO(row, 1));
1106
+ // Write prompt lines directly to scrollback (no absolute positioning)
1107
+ for (const line of renderedLines) {
1069
1108
  this.write(ESC.CLEAR_LINE);
1070
- if (line) {
1071
- this.write(line);
1072
- }
1109
+ this.write(line);
1110
+ this.write('\n');
1073
1111
  }
1074
- // Position cursor at prompt row/col
1075
- this.write(ESC.TO(promptRow, promptCol));
1112
+ // Position cursor at prompt input position
1113
+ const promptCol = Math.min(Math.max(1, 3 + this.cursor), this.cols || 80);
1114
+ // Move up to the prompt line and position cursor
1115
+ const linesToMoveUp = height - promptIndex - 1;
1116
+ if (linesToMoveUp > 0) {
1117
+ this.write(`\x1b[${linesToMoveUp}A`); // Move cursor up
1118
+ }
1119
+ this.write(`\x1b[${promptCol}G`); // Move to column
1076
1120
  this.cursorVisibleColumn = promptCol;
1077
1121
  this.hasRenderedPrompt = true;
1078
- this.hasEverRenderedOverlay = true; // Mark that we've rendered at least once
1122
+ this.hasEverRenderedOverlay = true;
1079
1123
  this.isPromptActive = true;
1080
1124
  this.lastOverlayHeight = height;
1081
- this.lastPromptIndex = promptIndex;
1082
1125
  this.lastOverlay = { lines: renderedLines, promptIndex };
1083
- this.overlayInvalidated = false;
1084
- this.lastOutputEndedWithNewline = true;
1126
+ this.lastOutputEndedWithNewline = false;
1085
1127
  this.promptHeight = height;
1086
1128
  }
1087
1129
  buildOverlayLines() {
@@ -1091,7 +1133,9 @@ export class UnifiedUIRenderer extends EventEmitter {
1091
1133
  for (const line of chromeLines) {
1092
1134
  lines.push(this.truncateLine(line, maxWidth));
1093
1135
  }
1094
- const divider = renderDivider(Math.min(maxWidth, 96), 'prompt');
1136
+ // Simple divider without label (Claude Code style)
1137
+ const dividerWidth = Math.min(maxWidth, 48);
1138
+ const divider = theme.ui.muted('─'.repeat(dividerWidth));
1095
1139
  lines.push(this.truncateLine(divider, maxWidth));
1096
1140
  const promptIndex = lines.length;
1097
1141
  lines.push(this.truncateLine(this.buildInputLine(), maxWidth));
@@ -1099,10 +1143,11 @@ export class UnifiedUIRenderer extends EventEmitter {
1099
1143
  for (let index = 0; index < this.suggestions.length; index++) {
1100
1144
  const suggestion = this.suggestions[index];
1101
1145
  const isActive = index === this.suggestionIndex;
1102
- const marker = isActive ? theme.primary('›') : theme.ui.muted('›');
1146
+ // Use simple arrow marker like Claude Code
1147
+ const marker = isActive ? theme.primary('>') : theme.ui.muted(' ');
1103
1148
  const cmdText = isActive ? theme.primary(suggestion.command) : theme.ui.muted(suggestion.command);
1104
1149
  const descText = isActive ? suggestion.description : theme.ui.muted(suggestion.description);
1105
- lines.push(this.truncateLine(`${marker} ${cmdText} — ${descText}`, maxWidth));
1150
+ lines.push(this.truncateLine(` ${marker} ${cmdText} — ${descText}`, maxWidth));
1106
1151
  }
1107
1152
  }
1108
1153
  if (this.inlinePanel.length > 0) {
@@ -1135,15 +1180,22 @@ export class UnifiedUIRenderer extends EventEmitter {
1135
1180
  return [];
1136
1181
  }
1137
1182
  const segments = [];
1138
- segments.push(`${theme.ui.muted('status')} ${this.applyTone(statusLabel.text, statusLabel.tone)}`);
1183
+ // Add animated spinner when streaming for dynamic visual feedback
1184
+ if (this.mode === 'streaming') {
1185
+ const spinnerChars = spinnerFrames.braille;
1186
+ const spinnerChar = spinnerChars[this.spinnerFrame % spinnerChars.length] ?? '⠋';
1187
+ segments.push(`${theme.info(spinnerChar)} ${this.applyTone(statusLabel.text, statusLabel.tone)}`);
1188
+ }
1189
+ else {
1190
+ segments.push(`${theme.ui.muted('status')} ${this.applyTone(statusLabel.text, statusLabel.tone)}`);
1191
+ }
1139
1192
  if (this.statusMeta.sessionTime) {
1140
1193
  segments.push(`${theme.ui.muted('runtime')} ${theme.ui.muted(this.statusMeta.sessionTime)}`);
1141
1194
  }
1142
1195
  if (this.statusMeta.contextPercent !== undefined) {
1143
- const ctx = this.statusMeta.contextPercent;
1144
- const tone = ctx > 90 ? 'error' : ctx > 70 ? 'warn' : 'muted';
1145
- const color = tone === 'error' ? theme.error : tone === 'warn' ? theme.warning : theme.ui.muted;
1146
- segments.push(`${theme.ui.muted('ctx')} ${color(`${ctx}%`)}`);
1196
+ // Use animated context meter for smooth color transitions
1197
+ this.contextMeter.update(this.statusMeta.contextPercent);
1198
+ segments.push(this.contextMeter.render());
1147
1199
  }
1148
1200
  return this.wrapSegments(segments, maxWidth);
1149
1201
  }
@@ -1313,9 +1365,10 @@ export class UnifiedUIRenderer extends EventEmitter {
1313
1365
  buildInputLine() {
1314
1366
  if (this.collapsedPaste) {
1315
1367
  const summary = `[pasted ${this.collapsedPaste.lines} lines, ${this.collapsedPaste.chars} chars] (Ctrl+L insert, Backspace discard)`;
1316
- return this.truncateLine(`${theme.primary(' ')}${theme.ui.muted(summary)}`, this.safeWidth());
1368
+ return this.truncateLine(`${theme.primary('> ')}${theme.ui.muted(summary)}`, this.safeWidth());
1317
1369
  }
1318
- const prompt = theme.primary(' ');
1370
+ // Claude Code uses simple '>' prompt
1371
+ const prompt = theme.primary('> ');
1319
1372
  const promptWidth = this.visibleLength(prompt);
1320
1373
  const maxWidth = this.safeWidth();
1321
1374
  const available = Math.max(1, maxWidth - promptWidth);
@@ -1452,17 +1505,6 @@ export class UnifiedUIRenderer extends EventEmitter {
1452
1505
  }
1453
1506
  return result;
1454
1507
  }
1455
- clearOverlayRows(rows, startRow) {
1456
- const totalRows = this.rows || 24;
1457
- const limit = Math.max(0, Math.min(rows, totalRows));
1458
- for (let idx = 0; idx < limit; idx++) {
1459
- const row = startRow + idx;
1460
- if (row < 1 || row > totalRows)
1461
- continue;
1462
- this.write(ESC.TO(row, 1));
1463
- this.write(ESC.CLEAR_LINE);
1464
- }
1465
- }
1466
1508
  getBuffer() {
1467
1509
  return this.buffer;
1468
1510
  }
@@ -1490,6 +1532,31 @@ export class UnifiedUIRenderer extends EventEmitter {
1490
1532
  setModeStatus(status) {
1491
1533
  this.updateStatus(status);
1492
1534
  }
1535
+ /**
1536
+ * Show a compacting status with animated spinner (Claude Code style)
1537
+ * Uses ✻ character with animation to indicate context compaction in progress
1538
+ */
1539
+ showCompactingStatus(message) {
1540
+ this.statusMessage = message;
1541
+ if (!this.spinnerInterval) {
1542
+ this.spinnerInterval = setInterval(() => {
1543
+ this.spinnerFrame++;
1544
+ this.renderPrompt();
1545
+ }, 80);
1546
+ }
1547
+ this.renderPrompt();
1548
+ }
1549
+ /**
1550
+ * Hide the compacting status and stop spinner animation
1551
+ */
1552
+ hideCompactingStatus() {
1553
+ if (this.spinnerInterval) {
1554
+ clearInterval(this.spinnerInterval);
1555
+ this.spinnerInterval = null;
1556
+ }
1557
+ this.statusMessage = null;
1558
+ this.renderPrompt();
1559
+ }
1493
1560
  emitPrompt(content) {
1494
1561
  this.pushPromptEvent(content);
1495
1562
  }
@@ -1533,31 +1600,15 @@ export class UnifiedUIRenderer extends EventEmitter {
1533
1600
  const height = this.lastOverlay?.lines.length ?? this.promptHeight ?? 0;
1534
1601
  if (height === 0)
1535
1602
  return;
1536
- this.updateTerminalSize();
1537
- const totalRows = this.rows || 24;
1538
- const bottomPadding = this.overlayBottomPadding;
1539
- const availableRows = Math.max(1, totalRows - bottomPadding);
1540
- // Use same flow-based positioning logic as renderPrompt for consistency
1541
- const contentEndRow = Math.min(this.contentRowCount + 1, totalRows);
1542
- const flowBasedStartRow = contentEndRow;
1543
- const bottomPinnedStartRow = Math.max(1, availableRows - height + 1);
1544
- const startRow = (flowBasedStartRow + height <= availableRows)
1545
- ? flowBasedStartRow
1546
- : bottomPinnedStartRow;
1547
- this.clearOverlayRows(height, startRow);
1548
- // Keep the padding row clean as well
1549
- const paddingRow = startRow + height;
1550
- if (this.overlayBottomPadding > 0 && paddingRow <= totalRows) {
1551
- this.write(ESC.TO(paddingRow, 1));
1603
+ // Pure inline mode: clear by moving up and clearing lines
1604
+ for (let i = 0; i < height; i++) {
1605
+ this.write('\x1b[A'); // Move up
1552
1606
  this.write(ESC.CLEAR_LINE);
1553
1607
  }
1554
- // Move cursor to the bottom ready for new scrollback output
1555
- this.write(ESC.TO(totalRows, 1));
1556
- this.lastOverlayHeight = height;
1557
- this.lastPromptIndex = this.lastOverlay?.promptIndex ?? this.lastPromptIndex;
1558
1608
  this.lastOverlay = null;
1559
- this.overlayInvalidated = true;
1560
1609
  this.promptHeight = 0;
1610
+ this.lastOverlayHeight = 0;
1611
+ this.isPromptActive = false;
1561
1612
  }
1562
1613
  updateTerminalSize() {
1563
1614
  if (this.output.isTTY) {