@claude-flow/cli 3.6.30 → 3.7.0-alpha.3
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/src/commands/daemon.d.ts.map +1 -1
- package/dist/src/commands/daemon.js +19 -3
- package/dist/src/commands/daemon.js.map +1 -1
- package/dist/src/mcp-tools/types.d.ts +4 -33
- package/dist/src/mcp-tools/types.d.ts.map +1 -1
- package/dist/src/mcp-tools/types.js +4 -14
- package/dist/src/mcp-tools/types.js.map +1 -1
- package/dist/src/mcp-tools/validate-input.d.ts +5 -57
- package/dist/src/mcp-tools/validate-input.d.ts.map +1 -1
- package/dist/src/mcp-tools/validate-input.js +5 -233
- package/dist/src/mcp-tools/validate-input.js.map +1 -1
- package/dist/src/output.d.ts +6 -130
- package/dist/src/output.d.ts.map +1 -1
- package/dist/src/output.js +6 -511
- package/dist/src/output.js.map +1 -1
- package/dist/src/types.d.ts +10 -195
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +10 -35
- package/dist/src/types.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
package/dist/src/output.d.ts
CHANGED
|
@@ -1,133 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* V3 CLI Output Formatter
|
|
3
|
-
*
|
|
2
|
+
* V3 CLI Output Formatter — re-export shim (ADR-100, alpha.5).
|
|
3
|
+
*
|
|
4
|
+
* Authoritative source: @claude-flow/cli-core/output. Was a byte-identical
|
|
5
|
+
* 640-line copy. The OutputFormatter class and `output` instance plus all
|
|
6
|
+
* helper exports flow through unchanged. Edit cli-core for behavior changes.
|
|
4
7
|
*/
|
|
5
|
-
|
|
6
|
-
declare const COLORS: {
|
|
7
|
-
readonly reset: "\u001B[0m";
|
|
8
|
-
readonly bold: "\u001B[1m";
|
|
9
|
-
readonly dim: "\u001B[2m";
|
|
10
|
-
readonly italic: "\u001B[3m";
|
|
11
|
-
readonly underline: "\u001B[4m";
|
|
12
|
-
readonly black: "\u001B[30m";
|
|
13
|
-
readonly red: "\u001B[31m";
|
|
14
|
-
readonly green: "\u001B[32m";
|
|
15
|
-
readonly yellow: "\u001B[33m";
|
|
16
|
-
readonly blue: "\u001B[34m";
|
|
17
|
-
readonly magenta: "\u001B[35m";
|
|
18
|
-
readonly cyan: "\u001B[36m";
|
|
19
|
-
readonly white: "\u001B[37m";
|
|
20
|
-
readonly gray: "\u001B[90m";
|
|
21
|
-
readonly brightRed: "\u001B[91m";
|
|
22
|
-
readonly brightGreen: "\u001B[92m";
|
|
23
|
-
readonly brightYellow: "\u001B[93m";
|
|
24
|
-
readonly brightBlue: "\u001B[94m";
|
|
25
|
-
readonly brightMagenta: "\u001B[95m";
|
|
26
|
-
readonly brightCyan: "\u001B[96m";
|
|
27
|
-
readonly brightWhite: "\u001B[97m";
|
|
28
|
-
readonly bgBlack: "\u001B[40m";
|
|
29
|
-
readonly bgRed: "\u001B[41m";
|
|
30
|
-
readonly bgGreen: "\u001B[42m";
|
|
31
|
-
readonly bgYellow: "\u001B[43m";
|
|
32
|
-
readonly bgBlue: "\u001B[44m";
|
|
33
|
-
readonly bgMagenta: "\u001B[45m";
|
|
34
|
-
readonly bgCyan: "\u001B[46m";
|
|
35
|
-
readonly bgWhite: "\u001B[47m";
|
|
36
|
-
};
|
|
37
|
-
type ColorName = keyof typeof COLORS;
|
|
38
|
-
export type VerbosityLevel = 'quiet' | 'normal' | 'verbose' | 'debug';
|
|
39
|
-
export declare class OutputFormatter {
|
|
40
|
-
private colorEnabled;
|
|
41
|
-
private outputStream;
|
|
42
|
-
private errorStream;
|
|
43
|
-
private verbosity;
|
|
44
|
-
constructor(options?: {
|
|
45
|
-
color?: boolean;
|
|
46
|
-
verbosity?: VerbosityLevel;
|
|
47
|
-
});
|
|
48
|
-
/**
|
|
49
|
-
* Set verbosity level
|
|
50
|
-
* - quiet: Only errors and direct results
|
|
51
|
-
* - normal: Errors, warnings, info, and results
|
|
52
|
-
* - verbose: All of normal + debug messages
|
|
53
|
-
* - debug: All output including trace
|
|
54
|
-
*/
|
|
55
|
-
setVerbosity(level: VerbosityLevel): void;
|
|
56
|
-
getVerbosity(): VerbosityLevel;
|
|
57
|
-
isQuiet(): boolean;
|
|
58
|
-
isVerbose(): boolean;
|
|
59
|
-
isDebug(): boolean;
|
|
60
|
-
private supportsColor;
|
|
61
|
-
color(text: string, ...colors: ColorName[]): string;
|
|
62
|
-
bold(text: string): string;
|
|
63
|
-
dim(text: string): string;
|
|
64
|
-
success(text: string): string;
|
|
65
|
-
error(text: string): string;
|
|
66
|
-
warning(text: string): string;
|
|
67
|
-
info(text: string): string;
|
|
68
|
-
highlight(text: string): string;
|
|
69
|
-
write(text: string): void;
|
|
70
|
-
writeln(text?: string): void;
|
|
71
|
-
writeError(text: string): void;
|
|
72
|
-
writeErrorln(text?: string): void;
|
|
73
|
-
printSuccess(message: string): void;
|
|
74
|
-
printError(message: string, details?: string): void;
|
|
75
|
-
printWarning(message: string): void;
|
|
76
|
-
printInfo(message: string): void;
|
|
77
|
-
printDebug(message: string): void;
|
|
78
|
-
printTrace(message: string): void;
|
|
79
|
-
table(options: TableOptions): string;
|
|
80
|
-
printTable(options: TableOptions): void;
|
|
81
|
-
private calculateColumnWidths;
|
|
82
|
-
private createBorderLine;
|
|
83
|
-
private alignText;
|
|
84
|
-
private truncate;
|
|
85
|
-
private stripAnsi;
|
|
86
|
-
createProgress(options: ProgressOptions): Progress;
|
|
87
|
-
progressBar(current: number, total: number, width?: number): string;
|
|
88
|
-
createSpinner(options: SpinnerOptions): Spinner;
|
|
89
|
-
json(data: unknown, pretty?: boolean): string;
|
|
90
|
-
printJson(data: unknown, pretty?: boolean): void;
|
|
91
|
-
list(items: string[], bullet?: string): string;
|
|
92
|
-
printList(items: string[], bullet?: string): void;
|
|
93
|
-
numberedList(items: string[]): string;
|
|
94
|
-
printNumberedList(items: string[]): void;
|
|
95
|
-
box(content: string, title?: string): string;
|
|
96
|
-
printBox(content: string, title?: string): void;
|
|
97
|
-
setColorEnabled(enabled: boolean): void;
|
|
98
|
-
isColorEnabled(): boolean;
|
|
99
|
-
}
|
|
100
|
-
export declare class Progress {
|
|
101
|
-
private current;
|
|
102
|
-
private total;
|
|
103
|
-
private width;
|
|
104
|
-
private startTime;
|
|
105
|
-
private formatter;
|
|
106
|
-
private showPercentage;
|
|
107
|
-
private showETA;
|
|
108
|
-
private lastRender;
|
|
109
|
-
constructor(formatter: OutputFormatter, options: ProgressOptions);
|
|
110
|
-
update(current: number): void;
|
|
111
|
-
increment(amount?: number): void;
|
|
112
|
-
render(): void;
|
|
113
|
-
finish(): void;
|
|
114
|
-
private formatTime;
|
|
115
|
-
}
|
|
116
|
-
export declare class Spinner {
|
|
117
|
-
private formatter;
|
|
118
|
-
private text;
|
|
119
|
-
private frames;
|
|
120
|
-
private interval;
|
|
121
|
-
private frameIndex;
|
|
122
|
-
private static readonly SPINNERS;
|
|
123
|
-
constructor(formatter: OutputFormatter, options: SpinnerOptions);
|
|
124
|
-
start(): void;
|
|
125
|
-
stop(message?: string): void;
|
|
126
|
-
succeed(message?: string): void;
|
|
127
|
-
fail(message?: string): void;
|
|
128
|
-
private render;
|
|
129
|
-
setText(text: string): void;
|
|
130
|
-
}
|
|
131
|
-
export declare const output: OutputFormatter;
|
|
132
|
-
export {};
|
|
8
|
+
export * from '@claude-flow/cli-core/output';
|
|
133
9
|
//# sourceMappingURL=output.d.ts.map
|
package/dist/src/output.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/output.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/output.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,8BAA8B,CAAC"}
|
package/dist/src/output.js
CHANGED
|
@@ -1,514 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* V3 CLI Output Formatter
|
|
3
|
-
*
|
|
2
|
+
* V3 CLI Output Formatter — re-export shim (ADR-100, alpha.5).
|
|
3
|
+
*
|
|
4
|
+
* Authoritative source: @claude-flow/cli-core/output. Was a byte-identical
|
|
5
|
+
* 640-line copy. The OutputFormatter class and `output` instance plus all
|
|
6
|
+
* helper exports flow through unchanged. Edit cli-core for behavior changes.
|
|
4
7
|
*/
|
|
5
|
-
|
|
6
|
-
// Color Support
|
|
7
|
-
// ============================================
|
|
8
|
-
const COLORS = {
|
|
9
|
-
// Standard colors
|
|
10
|
-
reset: '\x1b[0m',
|
|
11
|
-
bold: '\x1b[1m',
|
|
12
|
-
dim: '\x1b[2m',
|
|
13
|
-
italic: '\x1b[3m',
|
|
14
|
-
underline: '\x1b[4m',
|
|
15
|
-
// Foreground colors
|
|
16
|
-
black: '\x1b[30m',
|
|
17
|
-
red: '\x1b[31m',
|
|
18
|
-
green: '\x1b[32m',
|
|
19
|
-
yellow: '\x1b[33m',
|
|
20
|
-
blue: '\x1b[34m',
|
|
21
|
-
magenta: '\x1b[35m',
|
|
22
|
-
cyan: '\x1b[36m',
|
|
23
|
-
white: '\x1b[37m',
|
|
24
|
-
gray: '\x1b[90m',
|
|
25
|
-
// Bright foreground colors
|
|
26
|
-
brightRed: '\x1b[91m',
|
|
27
|
-
brightGreen: '\x1b[92m',
|
|
28
|
-
brightYellow: '\x1b[93m',
|
|
29
|
-
brightBlue: '\x1b[94m',
|
|
30
|
-
brightMagenta: '\x1b[95m',
|
|
31
|
-
brightCyan: '\x1b[96m',
|
|
32
|
-
brightWhite: '\x1b[97m',
|
|
33
|
-
// Background colors
|
|
34
|
-
bgBlack: '\x1b[40m',
|
|
35
|
-
bgRed: '\x1b[41m',
|
|
36
|
-
bgGreen: '\x1b[42m',
|
|
37
|
-
bgYellow: '\x1b[43m',
|
|
38
|
-
bgBlue: '\x1b[44m',
|
|
39
|
-
bgMagenta: '\x1b[45m',
|
|
40
|
-
bgCyan: '\x1b[46m',
|
|
41
|
-
bgWhite: '\x1b[47m'
|
|
42
|
-
};
|
|
43
|
-
export class OutputFormatter {
|
|
44
|
-
colorEnabled;
|
|
45
|
-
outputStream;
|
|
46
|
-
errorStream;
|
|
47
|
-
verbosity;
|
|
48
|
-
constructor(options = {}) {
|
|
49
|
-
this.colorEnabled = options.color ?? this.supportsColor();
|
|
50
|
-
this.outputStream = process.stdout;
|
|
51
|
-
this.errorStream = process.stderr;
|
|
52
|
-
this.verbosity = options.verbosity ?? 'normal';
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Set verbosity level
|
|
56
|
-
* - quiet: Only errors and direct results
|
|
57
|
-
* - normal: Errors, warnings, info, and results
|
|
58
|
-
* - verbose: All of normal + debug messages
|
|
59
|
-
* - debug: All output including trace
|
|
60
|
-
*/
|
|
61
|
-
setVerbosity(level) {
|
|
62
|
-
this.verbosity = level;
|
|
63
|
-
}
|
|
64
|
-
getVerbosity() {
|
|
65
|
-
return this.verbosity;
|
|
66
|
-
}
|
|
67
|
-
isQuiet() {
|
|
68
|
-
return this.verbosity === 'quiet';
|
|
69
|
-
}
|
|
70
|
-
isVerbose() {
|
|
71
|
-
return this.verbosity === 'verbose' || this.verbosity === 'debug';
|
|
72
|
-
}
|
|
73
|
-
isDebug() {
|
|
74
|
-
return this.verbosity === 'debug';
|
|
75
|
-
}
|
|
76
|
-
supportsColor() {
|
|
77
|
-
// Check for NO_COLOR environment variable
|
|
78
|
-
if (process.env.NO_COLOR !== undefined)
|
|
79
|
-
return false;
|
|
80
|
-
// Check for FORCE_COLOR environment variable
|
|
81
|
-
if (process.env.FORCE_COLOR !== undefined)
|
|
82
|
-
return true;
|
|
83
|
-
// Check if stdout is a TTY
|
|
84
|
-
return process.stdout.isTTY ?? false;
|
|
85
|
-
}
|
|
86
|
-
// ============================================
|
|
87
|
-
// Color Methods
|
|
88
|
-
// ============================================
|
|
89
|
-
color(text, ...colors) {
|
|
90
|
-
if (!this.colorEnabled)
|
|
91
|
-
return text;
|
|
92
|
-
const codes = colors.map(c => COLORS[c]).join('');
|
|
93
|
-
return `${codes}${text}${COLORS.reset}`;
|
|
94
|
-
}
|
|
95
|
-
bold(text) {
|
|
96
|
-
return this.color(text, 'bold');
|
|
97
|
-
}
|
|
98
|
-
dim(text) {
|
|
99
|
-
return this.color(text, 'dim');
|
|
100
|
-
}
|
|
101
|
-
success(text) {
|
|
102
|
-
return this.color(text, 'green');
|
|
103
|
-
}
|
|
104
|
-
error(text) {
|
|
105
|
-
return this.color(text, 'red');
|
|
106
|
-
}
|
|
107
|
-
warning(text) {
|
|
108
|
-
return this.color(text, 'yellow');
|
|
109
|
-
}
|
|
110
|
-
info(text) {
|
|
111
|
-
return this.color(text, 'blue');
|
|
112
|
-
}
|
|
113
|
-
highlight(text) {
|
|
114
|
-
return this.color(text, 'cyan', 'bold');
|
|
115
|
-
}
|
|
116
|
-
// ============================================
|
|
117
|
-
// Output Methods
|
|
118
|
-
// ============================================
|
|
119
|
-
write(text) {
|
|
120
|
-
this.outputStream.write(text);
|
|
121
|
-
}
|
|
122
|
-
writeln(text = '') {
|
|
123
|
-
this.outputStream.write(text + '\n');
|
|
124
|
-
}
|
|
125
|
-
writeError(text) {
|
|
126
|
-
this.errorStream.write(text);
|
|
127
|
-
}
|
|
128
|
-
writeErrorln(text = '') {
|
|
129
|
-
this.errorStream.write(text + '\n');
|
|
130
|
-
}
|
|
131
|
-
// ============================================
|
|
132
|
-
// Formatted Output Methods
|
|
133
|
-
// ============================================
|
|
134
|
-
printSuccess(message) {
|
|
135
|
-
// Success always shows (result output)
|
|
136
|
-
const icon = this.color('[OK]', 'green', 'bold');
|
|
137
|
-
this.writeln(`${icon} ${message}`);
|
|
138
|
-
}
|
|
139
|
-
printError(message, details) {
|
|
140
|
-
// Errors always show
|
|
141
|
-
const icon = this.color('[ERROR]', 'red', 'bold');
|
|
142
|
-
this.writeErrorln(`${icon} ${message}`);
|
|
143
|
-
if (details) {
|
|
144
|
-
this.writeErrorln(this.dim(` ${details}`));
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
printWarning(message) {
|
|
148
|
-
// Warnings suppressed in quiet mode
|
|
149
|
-
if (this.verbosity === 'quiet')
|
|
150
|
-
return;
|
|
151
|
-
const icon = this.color('[WARN]', 'yellow', 'bold');
|
|
152
|
-
this.writeln(`${icon} ${message}`);
|
|
153
|
-
}
|
|
154
|
-
printInfo(message) {
|
|
155
|
-
// Info suppressed in quiet mode
|
|
156
|
-
if (this.verbosity === 'quiet')
|
|
157
|
-
return;
|
|
158
|
-
const icon = this.color('[INFO]', 'blue', 'bold');
|
|
159
|
-
this.writeln(`${icon} ${message}`);
|
|
160
|
-
}
|
|
161
|
-
printDebug(message) {
|
|
162
|
-
// Debug only shows in verbose/debug mode
|
|
163
|
-
if (this.verbosity !== 'verbose' && this.verbosity !== 'debug')
|
|
164
|
-
return;
|
|
165
|
-
const icon = this.color('[DEBUG]', 'gray');
|
|
166
|
-
this.writeln(`${icon} ${this.dim(message)}`);
|
|
167
|
-
}
|
|
168
|
-
printTrace(message) {
|
|
169
|
-
// Trace only shows in debug mode
|
|
170
|
-
if (this.verbosity !== 'debug')
|
|
171
|
-
return;
|
|
172
|
-
const icon = this.color('[TRACE]', 'gray', 'dim');
|
|
173
|
-
this.writeln(`${icon} ${this.dim(message)}`);
|
|
174
|
-
}
|
|
175
|
-
// ============================================
|
|
176
|
-
// Table Formatting
|
|
177
|
-
// ============================================
|
|
178
|
-
table(options) {
|
|
179
|
-
const { columns, data, border = true, header = true, padding = 1, maxWidth } = options;
|
|
180
|
-
// Calculate column widths
|
|
181
|
-
const widths = this.calculateColumnWidths(columns, data, maxWidth);
|
|
182
|
-
const lines = [];
|
|
183
|
-
const pad = ' '.repeat(padding);
|
|
184
|
-
// Border characters
|
|
185
|
-
const borderChars = border ? {
|
|
186
|
-
topLeft: '+', topRight: '+', bottomLeft: '+', bottomRight: '+',
|
|
187
|
-
horizontal: '-', vertical: '|',
|
|
188
|
-
leftT: '+', rightT: '+', topT: '+', bottomT: '+', cross: '+'
|
|
189
|
-
} : {
|
|
190
|
-
topLeft: '', topRight: '', bottomLeft: '', bottomRight: '',
|
|
191
|
-
horizontal: '', vertical: ' ',
|
|
192
|
-
leftT: '', rightT: '', topT: '', bottomT: '', cross: ''
|
|
193
|
-
};
|
|
194
|
-
// Top border
|
|
195
|
-
if (border) {
|
|
196
|
-
lines.push(this.createBorderLine(widths, borderChars, 'top', padding));
|
|
197
|
-
}
|
|
198
|
-
// Header row
|
|
199
|
-
if (header) {
|
|
200
|
-
const headerRow = columns.map((col, i) => {
|
|
201
|
-
const text = this.truncate(col.header, widths[i]);
|
|
202
|
-
return pad + this.alignText(this.bold(text), widths[i], col.align) + pad;
|
|
203
|
-
}).join(borderChars.vertical);
|
|
204
|
-
lines.push(`${borderChars.vertical}${headerRow}${borderChars.vertical}`);
|
|
205
|
-
// Header separator
|
|
206
|
-
if (border) {
|
|
207
|
-
lines.push(this.createBorderLine(widths, borderChars, 'middle', padding));
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
// Data rows
|
|
211
|
-
for (const row of data) {
|
|
212
|
-
const rowCells = columns.map((col, i) => {
|
|
213
|
-
let value = row[col.key];
|
|
214
|
-
// Apply formatter if provided
|
|
215
|
-
if (col.format) {
|
|
216
|
-
value = col.format(value);
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
value = String(value ?? '');
|
|
220
|
-
}
|
|
221
|
-
const text = this.truncate(String(value), widths[i]);
|
|
222
|
-
return pad + this.alignText(text, widths[i], col.align) + pad;
|
|
223
|
-
}).join(borderChars.vertical);
|
|
224
|
-
lines.push(`${borderChars.vertical}${rowCells}${borderChars.vertical}`);
|
|
225
|
-
}
|
|
226
|
-
// Bottom border
|
|
227
|
-
if (border) {
|
|
228
|
-
lines.push(this.createBorderLine(widths, borderChars, 'bottom', padding));
|
|
229
|
-
}
|
|
230
|
-
return lines.join('\n');
|
|
231
|
-
}
|
|
232
|
-
printTable(options) {
|
|
233
|
-
this.writeln(this.table(options));
|
|
234
|
-
}
|
|
235
|
-
calculateColumnWidths(columns, data, maxWidth) {
|
|
236
|
-
const widths = columns.map((col, i) => {
|
|
237
|
-
// Start with header width
|
|
238
|
-
let width = col.header.length;
|
|
239
|
-
// Check all data values
|
|
240
|
-
for (const row of data) {
|
|
241
|
-
let value = row[col.key];
|
|
242
|
-
if (col.format) {
|
|
243
|
-
value = col.format(value);
|
|
244
|
-
}
|
|
245
|
-
const len = this.stripAnsi(String(value ?? '')).length;
|
|
246
|
-
width = Math.max(width, len);
|
|
247
|
-
}
|
|
248
|
-
// Apply column-specific width limit
|
|
249
|
-
if (col.width) {
|
|
250
|
-
width = Math.min(width, col.width);
|
|
251
|
-
}
|
|
252
|
-
return width;
|
|
253
|
-
});
|
|
254
|
-
// Apply max width constraint
|
|
255
|
-
if (maxWidth) {
|
|
256
|
-
const totalWidth = widths.reduce((a, b) => a + b, 0) + (columns.length * 3) + 1;
|
|
257
|
-
if (totalWidth > maxWidth) {
|
|
258
|
-
const reduction = (totalWidth - maxWidth) / columns.length;
|
|
259
|
-
return widths.map(w => Math.max(3, Math.floor(w - reduction)));
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
return widths;
|
|
263
|
-
}
|
|
264
|
-
createBorderLine(widths, chars, position, padding) {
|
|
265
|
-
const cellWidth = (w) => chars.horizontal.repeat(w + (padding * 2));
|
|
266
|
-
const cells = widths.map(cellWidth).join(position === 'top' ? chars.topT :
|
|
267
|
-
position === 'bottom' ? chars.bottomT :
|
|
268
|
-
chars.cross);
|
|
269
|
-
const left = position === 'top' ? chars.topLeft : position === 'bottom' ? chars.bottomLeft : chars.leftT;
|
|
270
|
-
const right = position === 'top' ? chars.topRight : position === 'bottom' ? chars.bottomRight : chars.rightT;
|
|
271
|
-
return `${left}${cells}${right}`;
|
|
272
|
-
}
|
|
273
|
-
alignText(text, width, align = 'left') {
|
|
274
|
-
const len = this.stripAnsi(text).length;
|
|
275
|
-
const padding = width - len;
|
|
276
|
-
if (padding <= 0)
|
|
277
|
-
return text;
|
|
278
|
-
switch (align) {
|
|
279
|
-
case 'right':
|
|
280
|
-
return ' '.repeat(padding) + text;
|
|
281
|
-
case 'center':
|
|
282
|
-
const left = Math.floor(padding / 2);
|
|
283
|
-
const right = padding - left;
|
|
284
|
-
return ' '.repeat(left) + text + ' '.repeat(right);
|
|
285
|
-
default:
|
|
286
|
-
return text + ' '.repeat(padding);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
truncate(text, maxLength) {
|
|
290
|
-
const stripped = this.stripAnsi(text);
|
|
291
|
-
if (stripped.length <= maxLength)
|
|
292
|
-
return text;
|
|
293
|
-
return stripped.slice(0, maxLength - 3) + '...';
|
|
294
|
-
}
|
|
295
|
-
stripAnsi(text) {
|
|
296
|
-
return text.replace(/\x1b\[[0-9;]*m/g, '');
|
|
297
|
-
}
|
|
298
|
-
// ============================================
|
|
299
|
-
// Progress Bar
|
|
300
|
-
// ============================================
|
|
301
|
-
createProgress(options) {
|
|
302
|
-
return new Progress(this, options);
|
|
303
|
-
}
|
|
304
|
-
progressBar(current, total, width = 40) {
|
|
305
|
-
const percent = Math.min(100, Math.max(0, (current / total) * 100));
|
|
306
|
-
const filled = Math.round((width * percent) / 100);
|
|
307
|
-
const empty = width - filled;
|
|
308
|
-
const bar = this.color('#'.repeat(filled), 'green') +
|
|
309
|
-
this.dim('-'.repeat(empty));
|
|
310
|
-
return `[${bar}] ${percent.toFixed(1)}%`;
|
|
311
|
-
}
|
|
312
|
-
// ============================================
|
|
313
|
-
// Spinner
|
|
314
|
-
// ============================================
|
|
315
|
-
createSpinner(options) {
|
|
316
|
-
return new Spinner(this, options);
|
|
317
|
-
}
|
|
318
|
-
// ============================================
|
|
319
|
-
// JSON Output
|
|
320
|
-
// ============================================
|
|
321
|
-
json(data, pretty = true) {
|
|
322
|
-
return pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
|
|
323
|
-
}
|
|
324
|
-
printJson(data, pretty = true) {
|
|
325
|
-
this.writeln(this.json(data, pretty));
|
|
326
|
-
}
|
|
327
|
-
// ============================================
|
|
328
|
-
// List Output
|
|
329
|
-
// ============================================
|
|
330
|
-
list(items, bullet = '-') {
|
|
331
|
-
return items.map(item => ` ${bullet} ${item}`).join('\n');
|
|
332
|
-
}
|
|
333
|
-
printList(items, bullet = '-') {
|
|
334
|
-
this.writeln(this.list(items, bullet));
|
|
335
|
-
}
|
|
336
|
-
numberedList(items) {
|
|
337
|
-
return items.map((item, i) => ` ${i + 1}. ${item}`).join('\n');
|
|
338
|
-
}
|
|
339
|
-
printNumberedList(items) {
|
|
340
|
-
this.writeln(this.numberedList(items));
|
|
341
|
-
}
|
|
342
|
-
// ============================================
|
|
343
|
-
// Box Output
|
|
344
|
-
// ============================================
|
|
345
|
-
box(content, title) {
|
|
346
|
-
const lines = content.split('\n');
|
|
347
|
-
const maxLen = Math.max(...lines.map(l => this.stripAnsi(l).length), title?.length ?? 0);
|
|
348
|
-
const width = maxLen + 4;
|
|
349
|
-
const border = {
|
|
350
|
-
topLeft: '+', topRight: '+',
|
|
351
|
-
bottomLeft: '+', bottomRight: '+',
|
|
352
|
-
horizontal: '-', vertical: '|'
|
|
353
|
-
};
|
|
354
|
-
const result = [];
|
|
355
|
-
// Top border with optional title
|
|
356
|
-
if (title) {
|
|
357
|
-
const titleText = ` ${title} `;
|
|
358
|
-
const leftPad = Math.floor((width - titleText.length - 2) / 2);
|
|
359
|
-
const rightPad = width - titleText.length - leftPad - 2;
|
|
360
|
-
result.push(border.topLeft +
|
|
361
|
-
border.horizontal.repeat(leftPad) +
|
|
362
|
-
this.bold(titleText) +
|
|
363
|
-
border.horizontal.repeat(rightPad) +
|
|
364
|
-
border.topRight);
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
result.push(border.topLeft + border.horizontal.repeat(width - 2) + border.topRight);
|
|
368
|
-
}
|
|
369
|
-
// Content lines
|
|
370
|
-
for (const line of lines) {
|
|
371
|
-
const stripped = this.stripAnsi(line);
|
|
372
|
-
const padding = maxLen - stripped.length;
|
|
373
|
-
result.push(`${border.vertical} ${line}${' '.repeat(padding)} ${border.vertical}`);
|
|
374
|
-
}
|
|
375
|
-
// Bottom border
|
|
376
|
-
result.push(border.bottomLeft + border.horizontal.repeat(width - 2) + border.bottomRight);
|
|
377
|
-
return result.join('\n');
|
|
378
|
-
}
|
|
379
|
-
printBox(content, title) {
|
|
380
|
-
this.writeln(this.box(content, title));
|
|
381
|
-
}
|
|
382
|
-
setColorEnabled(enabled) {
|
|
383
|
-
this.colorEnabled = enabled;
|
|
384
|
-
}
|
|
385
|
-
isColorEnabled() {
|
|
386
|
-
return this.colorEnabled;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
// ============================================
|
|
390
|
-
// Progress Class
|
|
391
|
-
// ============================================
|
|
392
|
-
export class Progress {
|
|
393
|
-
current;
|
|
394
|
-
total;
|
|
395
|
-
width;
|
|
396
|
-
startTime;
|
|
397
|
-
formatter;
|
|
398
|
-
showPercentage;
|
|
399
|
-
showETA;
|
|
400
|
-
lastRender = '';
|
|
401
|
-
constructor(formatter, options) {
|
|
402
|
-
this.formatter = formatter;
|
|
403
|
-
this.current = options.current ?? 0;
|
|
404
|
-
this.total = options.total;
|
|
405
|
-
this.width = options.width ?? 40;
|
|
406
|
-
this.showPercentage = options.showPercentage ?? true;
|
|
407
|
-
this.showETA = options.showETA ?? true;
|
|
408
|
-
this.startTime = Date.now();
|
|
409
|
-
}
|
|
410
|
-
update(current) {
|
|
411
|
-
this.current = current;
|
|
412
|
-
this.render();
|
|
413
|
-
}
|
|
414
|
-
increment(amount = 1) {
|
|
415
|
-
this.update(this.current + amount);
|
|
416
|
-
}
|
|
417
|
-
render() {
|
|
418
|
-
const bar = this.formatter.progressBar(this.current, this.total, this.width);
|
|
419
|
-
let output = bar;
|
|
420
|
-
if (this.showETA && this.current > 0) {
|
|
421
|
-
const elapsed = Date.now() - this.startTime;
|
|
422
|
-
const rate = this.current / elapsed;
|
|
423
|
-
const remaining = this.total - this.current;
|
|
424
|
-
const eta = remaining / rate;
|
|
425
|
-
if (isFinite(eta)) {
|
|
426
|
-
output += ` ETA: ${this.formatTime(eta)}`;
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
// Clear previous line and write new
|
|
430
|
-
if (this.lastRender) {
|
|
431
|
-
process.stdout.write('\r' + ' '.repeat(this.lastRender.length) + '\r');
|
|
432
|
-
}
|
|
433
|
-
process.stdout.write(output);
|
|
434
|
-
this.lastRender = output;
|
|
435
|
-
}
|
|
436
|
-
finish() {
|
|
437
|
-
this.current = this.total;
|
|
438
|
-
this.render();
|
|
439
|
-
process.stdout.write('\n');
|
|
440
|
-
}
|
|
441
|
-
formatTime(ms) {
|
|
442
|
-
const seconds = Math.floor(ms / 1000);
|
|
443
|
-
const minutes = Math.floor(seconds / 60);
|
|
444
|
-
const hours = Math.floor(minutes / 60);
|
|
445
|
-
if (hours > 0) {
|
|
446
|
-
return `${hours}h ${minutes % 60}m`;
|
|
447
|
-
}
|
|
448
|
-
else if (minutes > 0) {
|
|
449
|
-
return `${minutes}m ${seconds % 60}s`;
|
|
450
|
-
}
|
|
451
|
-
else {
|
|
452
|
-
return `${seconds}s`;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
// ============================================
|
|
457
|
-
// Spinner Class
|
|
458
|
-
// ============================================
|
|
459
|
-
export class Spinner {
|
|
460
|
-
formatter;
|
|
461
|
-
text;
|
|
462
|
-
frames;
|
|
463
|
-
interval = null;
|
|
464
|
-
frameIndex = 0;
|
|
465
|
-
static SPINNERS = {
|
|
466
|
-
dots: ['...', '..:', '.::', ':::', '::.', ':..',],
|
|
467
|
-
line: ['-', '\\', '|', '/'],
|
|
468
|
-
arc: ['◜', '◠', '◝', '◞', '◡', '◟'],
|
|
469
|
-
circle: ['◐', '◓', '◑', '◒'],
|
|
470
|
-
arrows: ['←', '↖', '↑', '↗', '→', '↘', '↓', '↙']
|
|
471
|
-
};
|
|
472
|
-
constructor(formatter, options) {
|
|
473
|
-
this.formatter = formatter;
|
|
474
|
-
this.text = options.text;
|
|
475
|
-
this.frames = Spinner.SPINNERS[options.spinner ?? 'dots'];
|
|
476
|
-
}
|
|
477
|
-
start() {
|
|
478
|
-
if (this.interval)
|
|
479
|
-
return;
|
|
480
|
-
this.interval = setInterval(() => {
|
|
481
|
-
this.render();
|
|
482
|
-
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
483
|
-
}, 100);
|
|
484
|
-
this.interval.unref();
|
|
485
|
-
this.render();
|
|
486
|
-
}
|
|
487
|
-
stop(message) {
|
|
488
|
-
if (this.interval) {
|
|
489
|
-
clearInterval(this.interval);
|
|
490
|
-
this.interval = null;
|
|
491
|
-
}
|
|
492
|
-
// Clear the line
|
|
493
|
-
process.stdout.write('\r' + ' '.repeat(this.text.length + 10) + '\r');
|
|
494
|
-
if (message) {
|
|
495
|
-
this.formatter.writeln(message);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
succeed(message) {
|
|
499
|
-
this.stop(this.formatter.success(message ?? this.text));
|
|
500
|
-
}
|
|
501
|
-
fail(message) {
|
|
502
|
-
this.stop(this.formatter.error(message ?? this.text));
|
|
503
|
-
}
|
|
504
|
-
render() {
|
|
505
|
-
const frame = this.formatter.info(this.frames[this.frameIndex]);
|
|
506
|
-
process.stdout.write(`\r${frame} ${this.text}`);
|
|
507
|
-
}
|
|
508
|
-
setText(text) {
|
|
509
|
-
this.text = text;
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
// Export singleton instance
|
|
513
|
-
export const output = new OutputFormatter();
|
|
8
|
+
export * from '@claude-flow/cli-core/output';
|
|
514
9
|
//# sourceMappingURL=output.js.map
|