erosolar-cli 1.7.194 → 1.7.196

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.
Files changed (68) hide show
  1. package/dist/core/agent.d.ts +6 -0
  2. package/dist/core/agent.d.ts.map +1 -1
  3. package/dist/core/agent.js +10 -1
  4. package/dist/core/agent.js.map +1 -1
  5. package/dist/core/errors/errorUtils.d.ts +87 -0
  6. package/dist/core/errors/errorUtils.d.ts.map +1 -0
  7. package/dist/core/errors/errorUtils.js +158 -0
  8. package/dist/core/errors/errorUtils.js.map +1 -0
  9. package/dist/core/resultVerification.js.map +1 -1
  10. package/dist/core/toolValidation.d.ts +117 -0
  11. package/dist/core/toolValidation.d.ts.map +1 -0
  12. package/dist/core/toolValidation.js +282 -0
  13. package/dist/core/toolValidation.js.map +1 -0
  14. package/dist/core/types/utilityTypes.d.ts +192 -0
  15. package/dist/core/types/utilityTypes.d.ts.map +1 -0
  16. package/dist/core/types/utilityTypes.js +272 -0
  17. package/dist/core/types/utilityTypes.js.map +1 -0
  18. package/dist/shell/interactiveShell.d.ts +9 -0
  19. package/dist/shell/interactiveShell.d.ts.map +1 -1
  20. package/dist/shell/interactiveShell.js +69 -1
  21. package/dist/shell/interactiveShell.js.map +1 -1
  22. package/dist/shell/systemPrompt.d.ts.map +1 -1
  23. package/dist/shell/systemPrompt.js +5 -0
  24. package/dist/shell/systemPrompt.js.map +1 -1
  25. package/dist/shell/terminalInput.d.ts +1 -0
  26. package/dist/shell/terminalInput.d.ts.map +1 -1
  27. package/dist/shell/terminalInput.js +9 -2
  28. package/dist/shell/terminalInput.js.map +1 -1
  29. package/dist/shell/terminalInputAdapter.d.ts +4 -0
  30. package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
  31. package/dist/shell/terminalInputAdapter.js +6 -0
  32. package/dist/shell/terminalInputAdapter.js.map +1 -1
  33. package/dist/tools/planningTools.d.ts +1 -0
  34. package/dist/tools/planningTools.d.ts.map +1 -1
  35. package/dist/tools/planningTools.js +48 -0
  36. package/dist/tools/planningTools.js.map +1 -1
  37. package/dist/ui/display.d.ts +5 -49
  38. package/dist/ui/display.d.ts.map +1 -1
  39. package/dist/ui/display.js +36 -335
  40. package/dist/ui/display.js.map +1 -1
  41. package/dist/ui/toolDisplay.d.ts.map +1 -1
  42. package/dist/ui/toolDisplay.js +17 -0
  43. package/dist/ui/toolDisplay.js.map +1 -1
  44. package/dist/utils/planFormatter.d.ts +34 -0
  45. package/dist/utils/planFormatter.d.ts.map +1 -0
  46. package/dist/utils/planFormatter.js +140 -0
  47. package/dist/utils/planFormatter.js.map +1 -0
  48. package/package.json +2 -2
  49. package/dist/shell/bracketedPasteManager.d.ts +0 -128
  50. package/dist/shell/bracketedPasteManager.d.ts.map +0 -1
  51. package/dist/shell/bracketedPasteManager.enhanced.d.ts +0 -2
  52. package/dist/shell/bracketedPasteManager.enhanced.d.ts.map +0 -1
  53. package/dist/shell/bracketedPasteManager.enhanced.js +0 -4
  54. package/dist/shell/bracketedPasteManager.enhanced.js.map +0 -1
  55. package/dist/shell/bracketedPasteManager.js +0 -372
  56. package/dist/shell/bracketedPasteManager.js.map +0 -1
  57. package/dist/shell/chatBox.d.ts +0 -228
  58. package/dist/shell/chatBox.d.ts.map +0 -1
  59. package/dist/shell/chatBox.js +0 -811
  60. package/dist/shell/chatBox.js.map +0 -1
  61. package/dist/shell/unifiedChatBox.d.ts +0 -194
  62. package/dist/shell/unifiedChatBox.d.ts.map +0 -1
  63. package/dist/shell/unifiedChatBox.js +0 -585
  64. package/dist/shell/unifiedChatBox.js.map +0 -1
  65. package/dist/ui/persistentPrompt.d.ts +0 -545
  66. package/dist/ui/persistentPrompt.d.ts.map +0 -1
  67. package/dist/ui/persistentPrompt.js +0 -1529
  68. package/dist/ui/persistentPrompt.js.map +0 -1
@@ -2,9 +2,9 @@ import { createSpinner } from 'nanospinner';
2
2
  import { clearScreenDown, cursorTo, moveCursor } from 'node:readline';
3
3
  import { theme, icons } from './theme.js';
4
4
  import { formatRichContent, renderMessagePanel, renderMessageBody } from './richText.js';
5
- import { getTerminalColumns, wrapPreformatted } from './layout.js';
5
+ import { getTerminalColumns } from './layout.js';
6
6
  import { highlightError } from './textHighlighter.js';
7
- import { renderCallout, renderSectionHeading } from './designSystem.js';
7
+ import { renderSectionHeading } from './designSystem.js';
8
8
  import { isPlainOutputMode } from './outputMode.js';
9
9
  /**
10
10
  * Output lock to prevent race conditions during spinner/stream output.
@@ -156,7 +156,6 @@ const DISPLAY_CONSTANTS = {
156
156
  };
157
157
  // Enhanced spinner frames with smooth animation
158
158
  const SPINNER_FRAMES = ['◐', '◓', '◑', '◒', '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
159
- const INDEPENDENT_SECURITY_MANDATE = 'Independent security research CLI for third-party, ethics-reviewed assessments and vulnerability discovery.';
160
159
  /**
161
160
  * Display class manages all terminal UI output for the application.
162
161
  *
@@ -614,64 +613,33 @@ export class Display {
614
613
  }
615
614
  showError(message, error) {
616
615
  this.clearSpinnerIfActive();
617
- const callout = renderCallout(message, {
618
- tone: 'danger',
619
- icon: icons.error,
620
- title: 'Error',
621
- width: this.getBannerWidth(),
622
- });
623
616
  const details = this.formatErrorDetails(error);
624
617
  this.withOutput(() => {
625
- this.writeLine(`\n${callout}`, this.errorStream);
618
+ this.writeLine(`${theme.error('✗')} ${message}`, this.errorStream);
626
619
  if (details) {
627
- this.writeLine(details, this.errorStream);
620
+ this.writeLine(` ${details}`, this.errorStream);
628
621
  }
629
- this.writeLine('', this.errorStream);
630
622
  });
631
623
  }
632
624
  showWarning(message) {
633
625
  this.clearSpinnerIfActive();
634
- const callout = renderCallout(message, {
635
- tone: 'warning',
636
- icon: icons.warning,
637
- title: 'Warning',
638
- width: this.getBannerWidth(),
639
- });
640
626
  this.withOutput(() => {
641
- this.writeLine(`${callout}`, this.errorStream);
627
+ this.writeLine(`${theme.warning('!')} ${message}`, this.errorStream);
642
628
  });
643
629
  }
644
630
  showInfo(message) {
645
631
  this.clearSpinnerIfActive();
646
- const callout = renderCallout(message, {
647
- tone: 'info',
648
- icon: icons.info,
649
- title: 'Info',
650
- width: this.getBannerWidth(),
651
- });
652
632
  this.withOutput(() => {
653
- this.writeLine(callout);
633
+ this.writeLine(`${theme.info('ℹ')} ${message}`);
654
634
  });
655
635
  }
656
636
  /**
657
- * Show a success message with enhanced styling
637
+ * Show a success message with simple styling
658
638
  */
659
639
  showSuccess(message) {
660
640
  this.clearSpinnerIfActive();
661
- const box = { tl: '╭', tr: '╮', bl: '╰', br: '╯', h: '─', v: '│' };
662
- const width = Math.min(this.getColumnWidth() - 4, 60);
663
- const innerWidth = width - 2;
664
- const icon = '✓';
665
- const title = ` ${icon} Success `;
666
- const headerPad = Math.floor((innerWidth - title.length) / 2);
667
641
  this.withOutput(() => {
668
- this.writeLine(theme.success(`${box.tl}${box.h.repeat(headerPad)}${title}${box.h.repeat(innerWidth - headerPad - title.length)}${box.tr}`));
669
- const msgLines = this.wrapLine(message, innerWidth - 2);
670
- for (const line of msgLines) {
671
- const padding = Math.max(0, innerWidth - line.length - 1);
672
- this.writeLine(`${theme.success(box.v)} ${line}${' '.repeat(padding)}${theme.success(box.v)}`);
673
- }
674
- this.writeLine(theme.success(`${box.bl}${box.h.repeat(innerWidth)}${box.br}`));
642
+ this.writeLine(`${theme.success('✓')} ${message}`);
675
643
  });
676
644
  }
677
645
  /**
@@ -691,36 +659,18 @@ export class Display {
691
659
  }
692
660
  });
693
661
  }
694
- showStatusLine(status, elapsedMs, context) {
662
+ showStatusLine(status, elapsedMs, _context) {
695
663
  this.clearSpinnerIfActive();
696
664
  const normalized = status?.trim();
697
665
  if (!normalized) {
698
666
  return;
699
667
  }
700
- const parts = [];
701
- // Show session elapsed time first (Claude Code style: "Session 5m 23s")
702
- if (context?.sessionElapsedMs && context.sessionElapsedMs > 0) {
703
- const sessionElapsed = this.formatElapsedTime(Math.floor(context.sessionElapsedMs / 1000));
704
- parts.push(theme.ui.muted(`Session ${sessionElapsed}`));
705
- }
706
- const contextSummary = this.formatContextSummary(context);
707
- if (contextSummary) {
708
- parts.push(contextSummary);
709
- }
710
668
  const elapsed = this.formatElapsed(elapsedMs);
711
669
  const statusText = elapsed
712
- ? `${theme.success(normalized)} ${theme.ui.muted(`(${elapsed})`)}`
713
- : theme.success(normalized);
714
- parts.push(statusText);
715
- const bulletSep = theme.ui.muted(` ${icons.bullet} `);
670
+ ? `${theme.success('✓')} ${normalized} ${theme.ui.muted(`(${elapsed})`)}`
671
+ : `${theme.success('✓')} ${normalized}`;
716
672
  this.withOutput(() => {
717
- // Claude Code style: show status line then separator
718
- this.writeLine(parts.join(bulletSep));
719
- this.writeLine();
720
- // Add separator line above prompt (Claude Code style)
721
- const cols = getTerminalColumns();
722
- const separatorLine = theme.ui.border('─'.repeat(Math.min(cols - 2, 72)));
723
- this.writeLine(separatorLine);
673
+ this.writeLine(statusText);
724
674
  });
725
675
  }
726
676
  showAvailableTools(_tools) {
@@ -732,12 +682,8 @@ export class Display {
732
682
  * Show ready message with keyboard shortcuts hint (compact)
733
683
  */
734
684
  showReadyWithHints() {
735
- const cols = this.getColumnWidth();
736
- const width = Math.max(32, Math.min(cols - 6, DISPLAY_CONSTANTS.MAX_BANNER_WIDTH - 4));
737
685
  this.withOutput(() => {
738
- const readyLine = `${theme.success('Ready')} ${theme.ui.muted('/help /model')}`;
739
- this.writeLine(this.renderCompactRow(readyLine, width, true));
740
- this.writeLine();
686
+ this.writeLine(`${theme.success('>')} ${theme.ui.muted('/help for commands')}`);
741
687
  });
742
688
  }
743
689
  /**
@@ -748,75 +694,21 @@ export class Display {
748
694
  if (available.length === 0) {
749
695
  return;
750
696
  }
751
- const width = Math.max(32, Math.min(this.getColumnWidth() - 6, DISPLAY_CONSTANTS.MAX_BANNER_WIDTH - 4));
752
- this.withOutput(() => {
753
- const providerList = available
754
- .map(p => `${theme.success('●')} ${p.provider} ${theme.ui.muted(`(${this.truncateModel(p.latestModel)})`)}`)
755
- .join(theme.ui.muted(' │ '));
756
- const line = `${theme.ui.muted('models')} ${providerList}`;
757
- this.writeLine(this.renderCompactRow(line, width));
758
- this.writeLine();
759
- });
697
+ // Claude Code style: don't show providers on startup, keep it minimal
760
698
  }
761
699
  /**
762
- * Truncate model name for compact display
700
+ * Show unified status bar - Claude Code style (minimal)
763
701
  */
764
- truncateModel(model) {
765
- if (model.length <= 20)
766
- return model;
767
- // Extract the meaningful part of model names
768
- const parts = model.split('-');
769
- if (parts.length > 2) {
770
- return `${parts[0]}-${parts[1]}...`;
771
- }
772
- return `${model.slice(0, 17)}...`;
773
- }
774
- /**
775
- * Show unified status bar - Claude Code style
776
- *
777
- * Format:
778
- * ▌ models ● anthropic (claude-opus...) │ ● openai (gpt-5.1-codex)
779
- * ▌ Ready • /help • /model
780
- *
781
- * Called both at startup and after streaming ends to provide consistent UI.
782
- */
783
- showUnifiedStatusBar(providers) {
784
- const cols = this.getColumnWidth();
785
- const width = Math.max(32, Math.min(cols - 6, DISPLAY_CONSTANTS.MAX_BANNER_WIDTH - 4));
702
+ showUnifiedStatusBar(_providers) {
786
703
  this.withOutput(() => {
787
- // Show providers line if available
788
- if (providers && providers.length > 0) {
789
- const available = providers.filter(p => p.available);
790
- if (available.length > 0) {
791
- const providerList = available
792
- .map(p => `${theme.success('●')} ${p.provider} ${theme.ui.muted(`(${this.truncateModel(p.latestModel)})`)}`)
793
- .join(theme.ui.muted(' │ '));
794
- const providerLine = `${theme.ui.muted('models')} ${providerList}`;
795
- this.writeLine(this.renderCompactRow(providerLine, width));
796
- this.writeLine();
797
- }
798
- }
799
- const readyLine = `${theme.success('Ready')} ${theme.ui.muted('• /help • /model')}`;
800
- this.writeLine(this.renderCompactRow(readyLine, width, true));
801
- this.writeLine();
704
+ this.writeLine(`${theme.success('>')} ${theme.ui.muted('/help for commands')}`);
802
705
  });
803
706
  }
804
707
  /**
805
- * Show streaming header - Claude Code style
806
- *
807
- * Displays a unified streaming status bar before AI response starts.
808
- * This provides visual consistency with the startup Ready bar.
809
- *
810
- * Format:
811
- * ▌ ● Responding...
708
+ * Show streaming header - Claude Code style (minimal)
812
709
  */
813
710
  showStreamingHeader() {
814
- const cols = this.getColumnWidth();
815
- const width = Math.max(32, Math.min(cols - 6, DISPLAY_CONSTANTS.MAX_BANNER_WIDTH - 4));
816
- this.withOutput(() => {
817
- const indicator = `${theme.info('●')} ${theme.ui.muted('Responding...')}`;
818
- this.writeLine(this.renderCompactRow(indicator, width, true));
819
- });
711
+ // Claude Code style: no header, just start streaming
820
712
  }
821
713
  /**
822
714
  * Show model commands help
@@ -1020,84 +912,6 @@ export class Display {
1020
912
  const columns = this.getColumnWidth();
1021
913
  return Math.max(DISPLAY_CONSTANTS.MIN_MESSAGE_WIDTH, Math.min(columns - DISPLAY_CONSTANTS.MESSAGE_PADDING, DISPLAY_CONSTANTS.MAX_MESSAGE_WIDTH));
1022
914
  }
1023
- /**
1024
- * Legacy method for appending thought blocks with tree-like formatting.
1025
- * Kept for backwards compatibility but not actively used.
1026
- * @deprecated Use buildClaudeStyleThought instead
1027
- */
1028
- // @ts-expect-error - Legacy method kept for backwards compatibility
1029
- _appendThoughtBlock(block, format, output) {
1030
- const rawLines = block.split('\n');
1031
- const indices = rawLines
1032
- .map((line, index) => (line.trim().length ? index : -1))
1033
- .filter((index) => index >= 0);
1034
- if (!indices.length) {
1035
- return;
1036
- }
1037
- const lastIndex = indices[indices.length - 1];
1038
- let usedFirst = false;
1039
- for (let index = 0; index < rawLines.length; index += 1) {
1040
- const rawLine = rawLines[index] ?? '';
1041
- if (!rawLine.trim()) {
1042
- continue;
1043
- }
1044
- const segments = this.wrapThoughtLine(rawLine, format.available);
1045
- if (!segments.length) {
1046
- continue;
1047
- }
1048
- const isLastLine = index === lastIndex;
1049
- segments.forEach((segment, segmentIndex) => {
1050
- const prefix = this.resolveThoughtPrefix({
1051
- usedFirst,
1052
- segmentIndex,
1053
- isLastLine,
1054
- format,
1055
- });
1056
- output.push(`${prefix}${segment}`);
1057
- });
1058
- usedFirst = true;
1059
- }
1060
- }
1061
- resolveThoughtPrefix(options) {
1062
- if (!options.usedFirst) {
1063
- return options.segmentIndex === 0 ? options.format.bullet : options.format.spacer;
1064
- }
1065
- if (options.segmentIndex === 0) {
1066
- return options.isLastLine ? options.format.last : options.format.branch;
1067
- }
1068
- return options.format.spacer;
1069
- }
1070
- /**
1071
- * Legacy method for generating thought formatting configuration.
1072
- * Kept for backwards compatibility but not actively used.
1073
- * @deprecated Use buildClaudeStyleThought instead
1074
- */
1075
- // @ts-expect-error - Legacy method kept for backwards compatibility
1076
- _getThoughtFormat() {
1077
- const totalWidth = Math.max(DISPLAY_CONSTANTS.MIN_THOUGHT_WIDTH, Math.min(this.getColumnWidth(), DISPLAY_CONSTANTS.MAX_THOUGHT_WIDTH));
1078
- const prefixWidth = Math.max(3, this.visibleLength(`${icons.bullet} `));
1079
- const available = Math.max(DISPLAY_CONSTANTS.MIN_WRAP_WIDTH, totalWidth - prefixWidth);
1080
- return {
1081
- totalWidth,
1082
- prefixWidth,
1083
- available,
1084
- bullet: theme.secondary(this.padPrefix(`${icons.bullet} `, prefixWidth)),
1085
- branch: theme.ui.muted(this.padPrefix('│ ', prefixWidth)),
1086
- last: theme.ui.muted(this.padPrefix('└ ', prefixWidth)),
1087
- spacer: ' '.repeat(prefixWidth),
1088
- };
1089
- }
1090
- wrapThoughtLine(line, width) {
1091
- const preserveIndentation = /^\s/.test(line);
1092
- const normalized = preserveIndentation ? line.replace(/\s+$/, '') : line.trim();
1093
- if (!normalized) {
1094
- return [];
1095
- }
1096
- if (preserveIndentation) {
1097
- return wrapPreformatted(normalized, width);
1098
- }
1099
- return this.wrapLine(normalized, width);
1100
- }
1101
915
  formatTelemetryLine(metadata) {
1102
916
  if (!metadata) {
1103
917
  return '';
@@ -1115,22 +929,6 @@ export class Display {
1115
929
  const separator = theme.ui.muted(' • ');
1116
930
  return ` ${parts.join(separator)}`;
1117
931
  }
1118
- formatContextSummary(context) {
1119
- if (!context) {
1120
- return null;
1121
- }
1122
- const hasPercentage = typeof context.percentage === 'number' && Number.isFinite(context.percentage);
1123
- const hasTokens = typeof context.tokens === 'number' && Number.isFinite(context.tokens);
1124
- if (!hasPercentage && !hasTokens) {
1125
- return null;
1126
- }
1127
- if (hasPercentage) {
1128
- const normalizedPercent = Math.max(0, Math.min(100, Math.round(context.percentage)));
1129
- const tokenDetails = hasTokens ? ` (${context.tokens} tokens)` : '';
1130
- return `${theme.info('Context')} ${theme.ui.muted(`${normalizedPercent}% used${tokenDetails}`)}`;
1131
- }
1132
- return theme.ui.muted(`${context.tokens} tokens`);
1133
- }
1134
932
  formatElapsed(elapsedMs) {
1135
933
  if (typeof elapsedMs !== 'number' || !Number.isFinite(elapsedMs) || elapsedMs < 0) {
1136
934
  return null;
@@ -1143,70 +941,17 @@ export class Display {
1143
941
  }
1144
942
  return `${seconds}s`;
1145
943
  }
1146
- buildClaudeStyleBanner(profileLabel, profileName, model, provider, workingDir, width, version) {
1147
- const effectiveWidth = Math.min(Math.max(width, 52), DISPLAY_CONSTANTS.MAX_BANNER_WIDTH);
1148
- const contentWidth = Math.max(32, effectiveWidth - 6);
1149
- const normalizedProfile = profileName?.trim();
1150
- const agentLabel = profileLabel?.trim() || normalizedProfile || 'Active agent';
1151
- const headerSegments = [
1152
- `${theme.gradient.cool('Erosolar CLI')}${version ? theme.ui.muted(` v${version}`) : ''}`,
1153
- `${theme.success('')} ${this.formatModelLabel(model)}`,
1154
- `${theme.ui.muted('via')} ${provider}`,
1155
- `${theme.ui.muted('agent')} ${agentLabel}`,
1156
- ];
1157
- const detailSegments = [
1158
- `${theme.ui.muted('workspace')} ${this.abbreviatePath(workingDir, contentWidth - 12)}`,
1159
- `${theme.ui.muted('mandate')} ${this.buildMandateSnippet(contentWidth)}`,
1160
- ];
1161
- const rows = [
1162
- ...this.buildSegmentRows(headerSegments, contentWidth),
1163
- ...this.buildSegmentRows(detailSegments, contentWidth),
1164
- ];
1165
- if (!rows.length) {
1166
- return '';
1167
- }
1168
- const renderedRows = rows.map((row, index) => this.renderCompactRow(row, contentWidth, index === 0));
1169
- const availableColumns = Math.max(0, this.getColumnWidth() - 2);
1170
- const dividerWidth = Math.max(0, Math.min(effectiveWidth, availableColumns));
1171
- const divider = !dividerWidth || isPlainOutputMode()
1172
- ? ''
1173
- : theme.ui.border('─'.repeat(Math.max(24, dividerWidth)));
1174
- return divider ? `${renderedRows.join('\n')}\n${divider}` : renderedRows.join('\n');
1175
- }
1176
- buildSegmentRows(segments, width) {
1177
- const separator = theme.ui.muted(' │ ');
1178
- const rows = [];
1179
- let current = '';
1180
- for (const segment of segments) {
1181
- if (!segment?.trim()) {
1182
- continue;
1183
- }
1184
- const candidate = current ? `${current}${separator}${segment}` : segment;
1185
- if (this.visibleLength(candidate) > width && current) {
1186
- rows.push(current);
1187
- current = segment;
1188
- }
1189
- else {
1190
- current = candidate;
1191
- }
1192
- }
1193
- if (current) {
1194
- rows.push(current);
1195
- }
1196
- return rows;
1197
- }
1198
- renderCompactRow(line, width, highlight = false) {
1199
- const padded = this.padLine(line, width);
1200
- if (isPlainOutputMode()) {
1201
- return padded;
1202
- }
1203
- const prefix = highlight ? theme.accent('▌') : theme.ui.border('▌');
1204
- const body = theme.ui.background(theme.ui.text(` ${padded} `));
1205
- return `${prefix}${body}`;
1206
- }
1207
- buildMandateSnippet(width) {
1208
- const maxLen = Math.max(28, width - 20);
1209
- return this.truncateVisible(INDEPENDENT_SECURITY_MANDATE, maxLen);
944
+ buildClaudeStyleBanner(_profileLabel, _profileName, model, provider, workingDir, _width, version) {
945
+ // Claude Code style: simple, compact, no boxes
946
+ const lines = [];
947
+ // Version line
948
+ const versionStr = version ? `v${version}` : '';
949
+ lines.push(`${theme.gradient.cool('Erosolar')} ${theme.ui.muted(versionStr)}`);
950
+ // Model info on one line
951
+ lines.push(`${theme.ui.muted('>')} ${this.formatModelLabel(model)} ${theme.ui.muted(`(${provider})`)}`);
952
+ // Working directory
953
+ lines.push(`${theme.ui.muted('>')} ${this.abbreviatePath(workingDir, 60)}`);
954
+ return lines.join('\n');
1210
955
  }
1211
956
  abbreviatePath(path, maxLen) {
1212
957
  if (path.length <= maxLen)
@@ -1216,14 +961,6 @@ export class Display {
1216
961
  return path;
1217
962
  return `${parts[0]}/.../${parts[parts.length - 1]}`;
1218
963
  }
1219
- padLine(text, width) {
1220
- const visible = this.visibleLength(text);
1221
- if (visible >= width) {
1222
- return this.truncateVisible(text, width);
1223
- }
1224
- const padding = Math.max(0, width - visible);
1225
- return `${text}${' '.repeat(padding)}`;
1226
- }
1227
964
  /**
1228
965
  * Wraps text with a prefix on the first line and optional continuation prefix.
1229
966
  * Handles multi-line text and word wrapping intelligently.
@@ -1279,7 +1016,7 @@ export class Display {
1279
1016
  return colorize(`${icons.action}`);
1280
1017
  }
1281
1018
  buildClaudeStyleThought(content) {
1282
- // Rich thinking block display with box frame
1019
+ // Claude Code style: simple prefix, no boxes
1283
1020
  const thinkingStyle = theme.thinking || {
1284
1021
  icon: theme.info,
1285
1022
  text: theme.ui.muted,
@@ -1287,24 +1024,17 @@ export class Display {
1287
1024
  label: theme.info,
1288
1025
  };
1289
1026
  const width = Math.min(this.getColumnWidth() - 4, 70);
1290
- const innerWidth = width - 2;
1291
1027
  const lines = [];
1292
- // Header with thinking icon
1293
- const header = ' 💭 Thinking ';
1294
- const headerPad = Math.floor((innerWidth - header.length) / 2);
1295
- lines.push(thinkingStyle.border(`╭${'─'.repeat(headerPad)}${thinkingStyle.label(header)}${'─'.repeat(innerWidth - headerPad - header.length)}╮`));
1296
- // Parse and format the thinking content
1028
+ // Simple header
1029
+ lines.push(`${theme.ui.muted('⏺')} ${thinkingStyle.label('Thinking')}`);
1030
+ // Parse and format the thinking content with simple indentation
1297
1031
  const contentLines = content.split('\n').filter(line => line.trim());
1298
1032
  for (const line of contentLines) {
1299
- // Wrap each line to fit
1300
- const wrapped = this.wrapLine(line.trim(), innerWidth - 2);
1033
+ const wrapped = this.wrapLine(line.trim(), width - 4);
1301
1034
  for (const wrappedLine of wrapped) {
1302
- const padding = Math.max(0, innerWidth - wrappedLine.length - 1);
1303
- lines.push(`${thinkingStyle.border('│')} ${thinkingStyle.text(wrappedLine)}${' '.repeat(padding)}${thinkingStyle.border('│')}`);
1035
+ lines.push(` ${thinkingStyle.text(wrappedLine)}`);
1304
1036
  }
1305
1037
  }
1306
- // Bottom border
1307
- lines.push(thinkingStyle.border(`╰${'─'.repeat(innerWidth)}╯`));
1308
1038
  return lines.join('\n');
1309
1039
  }
1310
1040
  /**
@@ -1319,8 +1049,6 @@ export class Display {
1319
1049
  this.writeLine();
1320
1050
  });
1321
1051
  }
1322
- // @ts-ignore - Legacy method kept for compatibility
1323
- // Keep legacy method to avoid breaking changes
1324
1052
  buildSubActionPrefixes(status, isLast) {
1325
1053
  if (isLast) {
1326
1054
  const colorize = this.resolveStatusColor(status);
@@ -1418,33 +1146,6 @@ export class Display {
1418
1146
  }
1419
1147
  return chunks.length > 0 ? chunks : [''];
1420
1148
  }
1421
- /**
1422
- * Pads a prefix string to the specified width with spaces.
1423
- */
1424
- padPrefix(value, width) {
1425
- if (!value || value.length >= width || width <= 0) {
1426
- return value;
1427
- }
1428
- return value.padEnd(width, ' ');
1429
- }
1430
- /**
1431
- * Truncates a string to fit within the specified width,
1432
- * accounting for ANSI color codes and adding ellipsis.
1433
- */
1434
- truncateVisible(value, width) {
1435
- if (width <= 0) {
1436
- return '';
1437
- }
1438
- if (!value) {
1439
- return '';
1440
- }
1441
- const plain = this.stripAnsi(value);
1442
- if (plain.length <= width) {
1443
- return value;
1444
- }
1445
- const slice = plain.slice(0, Math.max(1, width - 1));
1446
- return `${slice}…`;
1447
- }
1448
1149
  /**
1449
1150
  * Returns the visible length of a string, excluding ANSI escape codes.
1450
1151
  */