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.
- package/dist/core/agent.d.ts +6 -0
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +10 -1
- package/dist/core/agent.js.map +1 -1
- package/dist/core/errors/errorUtils.d.ts +87 -0
- package/dist/core/errors/errorUtils.d.ts.map +1 -0
- package/dist/core/errors/errorUtils.js +158 -0
- package/dist/core/errors/errorUtils.js.map +1 -0
- package/dist/core/resultVerification.js.map +1 -1
- package/dist/core/toolValidation.d.ts +117 -0
- package/dist/core/toolValidation.d.ts.map +1 -0
- package/dist/core/toolValidation.js +282 -0
- package/dist/core/toolValidation.js.map +1 -0
- package/dist/core/types/utilityTypes.d.ts +192 -0
- package/dist/core/types/utilityTypes.d.ts.map +1 -0
- package/dist/core/types/utilityTypes.js +272 -0
- package/dist/core/types/utilityTypes.js.map +1 -0
- package/dist/shell/interactiveShell.d.ts +9 -0
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +69 -1
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/systemPrompt.d.ts.map +1 -1
- package/dist/shell/systemPrompt.js +5 -0
- package/dist/shell/systemPrompt.js.map +1 -1
- package/dist/shell/terminalInput.d.ts +1 -0
- package/dist/shell/terminalInput.d.ts.map +1 -1
- package/dist/shell/terminalInput.js +9 -2
- package/dist/shell/terminalInput.js.map +1 -1
- package/dist/shell/terminalInputAdapter.d.ts +4 -0
- package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
- package/dist/shell/terminalInputAdapter.js +6 -0
- package/dist/shell/terminalInputAdapter.js.map +1 -1
- package/dist/tools/planningTools.d.ts +1 -0
- package/dist/tools/planningTools.d.ts.map +1 -1
- package/dist/tools/planningTools.js +48 -0
- package/dist/tools/planningTools.js.map +1 -1
- package/dist/ui/display.d.ts +5 -49
- package/dist/ui/display.d.ts.map +1 -1
- package/dist/ui/display.js +36 -335
- package/dist/ui/display.js.map +1 -1
- package/dist/ui/toolDisplay.d.ts.map +1 -1
- package/dist/ui/toolDisplay.js +17 -0
- package/dist/ui/toolDisplay.js.map +1 -1
- package/dist/utils/planFormatter.d.ts +34 -0
- package/dist/utils/planFormatter.d.ts.map +1 -0
- package/dist/utils/planFormatter.js +140 -0
- package/dist/utils/planFormatter.js.map +1 -0
- package/package.json +2 -2
- package/dist/shell/bracketedPasteManager.d.ts +0 -128
- package/dist/shell/bracketedPasteManager.d.ts.map +0 -1
- package/dist/shell/bracketedPasteManager.enhanced.d.ts +0 -2
- package/dist/shell/bracketedPasteManager.enhanced.d.ts.map +0 -1
- package/dist/shell/bracketedPasteManager.enhanced.js +0 -4
- package/dist/shell/bracketedPasteManager.enhanced.js.map +0 -1
- package/dist/shell/bracketedPasteManager.js +0 -372
- package/dist/shell/bracketedPasteManager.js.map +0 -1
- package/dist/shell/chatBox.d.ts +0 -228
- package/dist/shell/chatBox.d.ts.map +0 -1
- package/dist/shell/chatBox.js +0 -811
- package/dist/shell/chatBox.js.map +0 -1
- package/dist/shell/unifiedChatBox.d.ts +0 -194
- package/dist/shell/unifiedChatBox.d.ts.map +0 -1
- package/dist/shell/unifiedChatBox.js +0 -585
- package/dist/shell/unifiedChatBox.js.map +0 -1
- package/dist/ui/persistentPrompt.d.ts +0 -545
- package/dist/ui/persistentPrompt.d.ts.map +0 -1
- package/dist/ui/persistentPrompt.js +0 -1529
- package/dist/ui/persistentPrompt.js.map +0 -1
package/dist/ui/display.js
CHANGED
|
@@ -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
|
|
5
|
+
import { getTerminalColumns } from './layout.js';
|
|
6
6
|
import { highlightError } from './textHighlighter.js';
|
|
7
|
-
import {
|
|
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(
|
|
618
|
+
this.writeLine(`${theme.error('✗')} ${message}`, this.errorStream);
|
|
626
619
|
if (details) {
|
|
627
|
-
this.writeLine(details
|
|
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(`${
|
|
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(
|
|
633
|
+
this.writeLine(`${theme.info('ℹ')} ${message}`);
|
|
654
634
|
});
|
|
655
635
|
}
|
|
656
636
|
/**
|
|
657
|
-
* Show a success message with
|
|
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(
|
|
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,
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
700
|
+
* Show unified status bar - Claude Code style (minimal)
|
|
763
701
|
*/
|
|
764
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
1147
|
-
|
|
1148
|
-
const
|
|
1149
|
-
|
|
1150
|
-
const
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
1293
|
-
|
|
1294
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
*/
|