erosolar-cli 2.1.62 → 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;
@@ -131,6 +137,14 @@ export declare class UnifiedUIRenderer extends EventEmitter {
131
137
  */
132
138
  addCompactBlock(content: string, label?: string): void;
133
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;
134
148
  getMode(): 'idle' | 'streaming';
135
149
  updateStatus(message: string | null): void;
136
150
  updateStatusBundle(status: {
@@ -186,12 +200,20 @@ export declare class UnifiedUIRenderer extends EventEmitter {
186
200
  private visibleLength;
187
201
  private stripAnsi;
188
202
  private truncateLine;
189
- private clearOverlayRows;
190
203
  getBuffer(): string;
191
204
  getCursor(): number;
192
205
  setBuffer(text: string, cursorPos?: number): void;
193
206
  clearBuffer(): void;
194
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;
195
217
  emitPrompt(content: string): void;
196
218
  /**
197
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,7 +99,7 @@ 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
104
  allowPromptRender = true;
97
105
  inputCapture = null;
@@ -101,6 +109,8 @@ export class UnifiedUIRenderer extends EventEmitter {
101
109
  this.input = input;
102
110
  this.interactive = Boolean(this.output.isTTY && this.input.isTTY && !process.env['CI']);
103
111
  this.plainMode = isPlainOutputMode() || !this.interactive;
112
+ // Initialize animated components
113
+ this.contextMeter = new ContextMeter();
104
114
  this.rl = readline.createInterface({
105
115
  input: this.input,
106
116
  output: this.output,
@@ -147,6 +157,21 @@ export class UnifiedUIRenderer extends EventEmitter {
147
157
  cleanup() {
148
158
  this.cancelInputCapture(new Error('Renderer disposed'));
149
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();
150
175
  if (!this.interactive) {
151
176
  this.rl.close();
152
177
  return;
@@ -800,8 +825,6 @@ export class UnifiedUIRenderer extends EventEmitter {
800
825
  }
801
826
  this.output.write(formatted);
802
827
  this.lastOutputEndedWithNewline = formatted.endsWith('\n');
803
- // Overlay must be re-anchored after new scrollback is written
804
- this.overlayInvalidated = true;
805
828
  // Don't re-render prompt after every event - wait for queue to finish
806
829
  // This prevents premature prompt rendering that cuts off responses
807
830
  }
@@ -847,10 +870,19 @@ export class UnifiedUIRenderer extends EventEmitter {
847
870
  case 'prompt':
848
871
  return `\n> ${event.content}\n`; // Plain > like Claude Code
849
872
  case 'thought': {
850
- // 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');
851
877
  const lines = event.content.split('\n');
878
+ // Show thinking header with first line, then indent continuation
852
879
  const formatted = lines
853
- .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
+ })
854
886
  .join('\n');
855
887
  return `\n${formatted}\n`;
856
888
  }
@@ -908,6 +940,13 @@ export class UnifiedUIRenderer extends EventEmitter {
908
940
  setMode(mode) {
909
941
  const wasStreaming = this.mode === 'streaming';
910
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
+ }
911
950
  if (wasStreaming && mode === 'idle' && !this.lastOutputEndedWithNewline) {
912
951
  // Finish streaming on a fresh line so the next prompt/event doesn't collide
913
952
  this.write('\n');
@@ -918,6 +957,31 @@ export class UnifiedUIRenderer extends EventEmitter {
918
957
  this.renderPrompt();
919
958
  }
920
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
+ }
921
985
  getMode() {
922
986
  return this.mode;
923
987
  }
@@ -1013,13 +1077,9 @@ export class UnifiedUIRenderer extends EventEmitter {
1013
1077
  if (!this.allowPromptRender) {
1014
1078
  return;
1015
1079
  }
1016
- // Rich mode: inline overlay anchored to current scrollback (no full-screen clear)
1080
+ // Rich mode: inline rendering (no full-screen overlay)
1017
1081
  this.updateTerminalSize();
1018
1082
  const maxWidth = this.safeWidth();
1019
- if (this.lastRenderWidth !== null && maxWidth !== this.lastRenderWidth) {
1020
- // Terminal resized; force a clean anchor so the overlay doesn't jitter.
1021
- this.overlayInvalidated = true;
1022
- }
1023
1083
  this.lastRenderWidth = maxWidth;
1024
1084
  const overlay = this.buildOverlayLines();
1025
1085
  if (!overlay.lines.length) {
@@ -1031,45 +1091,39 @@ export class UnifiedUIRenderer extends EventEmitter {
1031
1091
  }
1032
1092
  let promptIndex = Math.max(0, Math.min(overlay.promptIndex, renderedLines.length - 1));
1033
1093
  let height = renderedLines.length;
1034
- // Keep at least one free line below the overlay so typing always has breathing room
1035
- const bottomPadding = this.overlayBottomPadding;
1036
1094
  const totalRows = this.rows || 24;
1037
- const availableRows = Math.max(1, totalRows - bottomPadding);
1038
- if (height > availableRows) {
1039
- renderedLines.splice(availableRows);
1040
- height = renderedLines.length;
1041
- promptIndex = Math.max(0, Math.min(promptIndex, height - 1));
1042
- }
1043
- const startRow = Math.max(1, availableRows - height + 1);
1044
- const promptRow = startRow + promptIndex;
1045
- const promptCol = Math.min(Math.max(1, 3 + this.cursor), this.cols || 80);
1046
- // Clear any previous overlay footprint (status, prompt, controls) to avoid leaking into scrollback
1047
- this.clearOverlayRows(height, startRow);
1048
- if (bottomPadding > 0 && startRow + height <= totalRows) {
1049
- this.write(ESC.TO(startRow + height, 1));
1050
- 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
+ }
1051
1105
  }
1052
- // Render overlay lines in place without pushing scrollback
1053
- for (let idx = 0; idx < height; idx++) {
1054
- const row = startRow + idx;
1055
- const line = renderedLines[idx] ?? '';
1056
- this.write(ESC.TO(row, 1));
1106
+ // Write prompt lines directly to scrollback (no absolute positioning)
1107
+ for (const line of renderedLines) {
1057
1108
  this.write(ESC.CLEAR_LINE);
1058
- if (line) {
1059
- this.write(line);
1060
- }
1109
+ this.write(line);
1110
+ this.write('\n');
1061
1111
  }
1062
- // Position cursor at prompt row/col
1063
- 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
1064
1120
  this.cursorVisibleColumn = promptCol;
1065
1121
  this.hasRenderedPrompt = true;
1066
- this.hasEverRenderedOverlay = true; // Mark that we've rendered at least once
1122
+ this.hasEverRenderedOverlay = true;
1067
1123
  this.isPromptActive = true;
1068
1124
  this.lastOverlayHeight = height;
1069
- this.lastPromptIndex = promptIndex;
1070
1125
  this.lastOverlay = { lines: renderedLines, promptIndex };
1071
- this.overlayInvalidated = false;
1072
- this.lastOutputEndedWithNewline = true;
1126
+ this.lastOutputEndedWithNewline = false;
1073
1127
  this.promptHeight = height;
1074
1128
  }
1075
1129
  buildOverlayLines() {
@@ -1079,7 +1133,9 @@ export class UnifiedUIRenderer extends EventEmitter {
1079
1133
  for (const line of chromeLines) {
1080
1134
  lines.push(this.truncateLine(line, maxWidth));
1081
1135
  }
1082
- 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));
1083
1139
  lines.push(this.truncateLine(divider, maxWidth));
1084
1140
  const promptIndex = lines.length;
1085
1141
  lines.push(this.truncateLine(this.buildInputLine(), maxWidth));
@@ -1087,10 +1143,11 @@ export class UnifiedUIRenderer extends EventEmitter {
1087
1143
  for (let index = 0; index < this.suggestions.length; index++) {
1088
1144
  const suggestion = this.suggestions[index];
1089
1145
  const isActive = index === this.suggestionIndex;
1090
- 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(' ');
1091
1148
  const cmdText = isActive ? theme.primary(suggestion.command) : theme.ui.muted(suggestion.command);
1092
1149
  const descText = isActive ? suggestion.description : theme.ui.muted(suggestion.description);
1093
- lines.push(this.truncateLine(`${marker} ${cmdText} — ${descText}`, maxWidth));
1150
+ lines.push(this.truncateLine(` ${marker} ${cmdText} — ${descText}`, maxWidth));
1094
1151
  }
1095
1152
  }
1096
1153
  if (this.inlinePanel.length > 0) {
@@ -1123,15 +1180,22 @@ export class UnifiedUIRenderer extends EventEmitter {
1123
1180
  return [];
1124
1181
  }
1125
1182
  const segments = [];
1126
- 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
+ }
1127
1192
  if (this.statusMeta.sessionTime) {
1128
1193
  segments.push(`${theme.ui.muted('runtime')} ${theme.ui.muted(this.statusMeta.sessionTime)}`);
1129
1194
  }
1130
1195
  if (this.statusMeta.contextPercent !== undefined) {
1131
- const ctx = this.statusMeta.contextPercent;
1132
- const tone = ctx > 90 ? 'error' : ctx > 70 ? 'warn' : 'muted';
1133
- const color = tone === 'error' ? theme.error : tone === 'warn' ? theme.warning : theme.ui.muted;
1134
- 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());
1135
1199
  }
1136
1200
  return this.wrapSegments(segments, maxWidth);
1137
1201
  }
@@ -1301,9 +1365,10 @@ export class UnifiedUIRenderer extends EventEmitter {
1301
1365
  buildInputLine() {
1302
1366
  if (this.collapsedPaste) {
1303
1367
  const summary = `[pasted ${this.collapsedPaste.lines} lines, ${this.collapsedPaste.chars} chars] (Ctrl+L insert, Backspace discard)`;
1304
- return this.truncateLine(`${theme.primary(' ')}${theme.ui.muted(summary)}`, this.safeWidth());
1368
+ return this.truncateLine(`${theme.primary('> ')}${theme.ui.muted(summary)}`, this.safeWidth());
1305
1369
  }
1306
- const prompt = theme.primary(' ');
1370
+ // Claude Code uses simple '>' prompt
1371
+ const prompt = theme.primary('> ');
1307
1372
  const promptWidth = this.visibleLength(prompt);
1308
1373
  const maxWidth = this.safeWidth();
1309
1374
  const available = Math.max(1, maxWidth - promptWidth);
@@ -1440,17 +1505,6 @@ export class UnifiedUIRenderer extends EventEmitter {
1440
1505
  }
1441
1506
  return result;
1442
1507
  }
1443
- clearOverlayRows(rows, startRow) {
1444
- const totalRows = this.rows || 24;
1445
- const limit = Math.max(0, Math.min(rows, totalRows));
1446
- for (let idx = 0; idx < limit; idx++) {
1447
- const row = startRow + idx;
1448
- if (row < 1 || row > totalRows)
1449
- continue;
1450
- this.write(ESC.TO(row, 1));
1451
- this.write(ESC.CLEAR_LINE);
1452
- }
1453
- }
1454
1508
  getBuffer() {
1455
1509
  return this.buffer;
1456
1510
  }
@@ -1478,6 +1532,31 @@ export class UnifiedUIRenderer extends EventEmitter {
1478
1532
  setModeStatus(status) {
1479
1533
  this.updateStatus(status);
1480
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
+ }
1481
1560
  emitPrompt(content) {
1482
1561
  this.pushPromptEvent(content);
1483
1562
  }
@@ -1521,23 +1600,15 @@ export class UnifiedUIRenderer extends EventEmitter {
1521
1600
  const height = this.lastOverlay?.lines.length ?? this.promptHeight ?? 0;
1522
1601
  if (height === 0)
1523
1602
  return;
1524
- this.updateTerminalSize();
1525
- const totalRows = this.rows || 24;
1526
- const startRow = Math.max(1, Math.max(1, totalRows - this.overlayBottomPadding) - height + 1);
1527
- this.clearOverlayRows(height, startRow);
1528
- // Keep the padding row clean as well
1529
- const paddingRow = startRow + height;
1530
- if (this.overlayBottomPadding > 0 && paddingRow <= totalRows) {
1531
- 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
1532
1606
  this.write(ESC.CLEAR_LINE);
1533
1607
  }
1534
- // Move cursor to the bottom ready for new scrollback output
1535
- this.write(ESC.TO(totalRows, 1));
1536
- this.lastOverlayHeight = height;
1537
- this.lastPromptIndex = this.lastOverlay?.promptIndex ?? this.lastPromptIndex;
1538
1608
  this.lastOverlay = null;
1539
- this.overlayInvalidated = true;
1540
1609
  this.promptHeight = 0;
1610
+ this.lastOverlayHeight = 0;
1611
+ this.isPromptActive = false;
1541
1612
  }
1542
1613
  updateTerminalSize() {
1543
1614
  if (this.output.isTTY) {