@agentuity/cli 0.0.70 → 0.0.72
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/cmd/auth/api.d.ts.map +1 -1
- package/dist/cmd/auth/api.js +1 -1
- package/dist/cmd/auth/api.js.map +1 -1
- package/dist/cmd/build/bundler.d.ts +4 -3
- package/dist/cmd/build/bundler.d.ts.map +1 -1
- package/dist/cmd/build/bundler.js +104 -10
- package/dist/cmd/build/bundler.js.map +1 -1
- package/dist/cmd/build/index.d.ts.map +1 -1
- package/dist/cmd/build/index.js +1 -0
- package/dist/cmd/build/index.js.map +1 -1
- package/dist/cmd/cloud/db/create.js +2 -2
- package/dist/cmd/cloud/db/create.js.map +1 -1
- package/dist/cmd/cloud/db/delete.js +2 -2
- package/dist/cmd/cloud/db/delete.js.map +1 -1
- package/dist/cmd/cloud/db/get.js +2 -2
- package/dist/cmd/cloud/db/get.js.map +1 -1
- package/dist/cmd/cloud/db/list.js +2 -2
- package/dist/cmd/cloud/db/list.js.map +1 -1
- package/dist/cmd/cloud/db/logs.js +2 -2
- package/dist/cmd/cloud/db/logs.js.map +1 -1
- package/dist/cmd/cloud/db/sql.js +2 -2
- package/dist/cmd/cloud/db/sql.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +164 -24
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/session/get.js +2 -2
- package/dist/cmd/cloud/session/get.js.map +1 -1
- package/dist/cmd/cloud/session/list.js +2 -2
- package/dist/cmd/cloud/session/list.js.map +1 -1
- package/dist/cmd/cloud/storage/create.js +2 -2
- package/dist/cmd/cloud/storage/create.js.map +1 -1
- package/dist/cmd/cloud/storage/delete.js +2 -2
- package/dist/cmd/cloud/storage/delete.js.map +1 -1
- package/dist/cmd/cloud/storage/download.js +2 -2
- package/dist/cmd/cloud/storage/download.js.map +1 -1
- package/dist/cmd/cloud/storage/get.js +2 -2
- package/dist/cmd/cloud/storage/get.js.map +1 -1
- package/dist/cmd/cloud/storage/list.js +2 -2
- package/dist/cmd/cloud/storage/list.js.map +1 -1
- package/dist/cmd/cloud/storage/upload.js +2 -2
- package/dist/cmd/cloud/storage/upload.js.map +1 -1
- package/dist/cmd/cloud/thread/delete.js +2 -2
- package/dist/cmd/cloud/thread/delete.js.map +1 -1
- package/dist/cmd/cloud/thread/get.js +2 -2
- package/dist/cmd/cloud/thread/get.js.map +1 -1
- package/dist/cmd/cloud/thread/list.js +2 -2
- package/dist/cmd/cloud/thread/list.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +1 -0
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -1
- package/dist/config.js.map +1 -1
- package/dist/env-util.d.ts.map +1 -1
- package/dist/env-util.js +0 -3
- package/dist/env-util.js.map +1 -1
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +5 -1
- package/dist/output.js.map +1 -1
- package/dist/tui.d.ts +27 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +140 -33
- package/dist/tui.js.map +1 -1
- package/package.json +3 -3
- package/src/cmd/auth/api.ts +1 -5
- package/src/cmd/build/bundler.ts +138 -13
- package/src/cmd/build/index.ts +1 -0
- package/src/cmd/cloud/db/create.ts +2 -2
- package/src/cmd/cloud/db/delete.ts +2 -2
- package/src/cmd/cloud/db/get.ts +2 -2
- package/src/cmd/cloud/db/list.ts +2 -2
- package/src/cmd/cloud/db/logs.ts +2 -2
- package/src/cmd/cloud/db/sql.ts +2 -2
- package/src/cmd/cloud/deploy.ts +188 -24
- package/src/cmd/cloud/session/get.ts +2 -2
- package/src/cmd/cloud/session/list.ts +2 -2
- package/src/cmd/cloud/storage/create.ts +2 -2
- package/src/cmd/cloud/storage/delete.ts +2 -2
- package/src/cmd/cloud/storage/download.ts +2 -2
- package/src/cmd/cloud/storage/get.ts +2 -2
- package/src/cmd/cloud/storage/list.ts +2 -2
- package/src/cmd/cloud/storage/upload.ts +2 -2
- package/src/cmd/cloud/thread/delete.ts +2 -2
- package/src/cmd/cloud/thread/get.ts +2 -2
- package/src/cmd/cloud/thread/list.ts +2 -2
- package/src/cmd/dev/index.ts +1 -0
- package/src/config.ts +9 -6
- package/src/env-util.ts +0 -3
- package/src/output.ts +7 -1
- package/src/tui.ts +192 -34
|
@@ -74,9 +74,9 @@ export const listSubcommand = createSubcommand({
|
|
|
74
74
|
},
|
|
75
75
|
|
|
76
76
|
async handler(ctx) {
|
|
77
|
-
const { logger, args, opts, options, orgId, region,
|
|
77
|
+
const { logger, args, opts, options, orgId, region, auth } = ctx;
|
|
78
78
|
|
|
79
|
-
const catalystClient = getCatalystAPIClient(
|
|
79
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
80
80
|
|
|
81
81
|
const resources = await tui.spinner({
|
|
82
82
|
message: `Fetching storage for ${orgId} in ${region}`,
|
|
@@ -49,9 +49,9 @@ export const uploadSubcommand = createSubcommand({
|
|
|
49
49
|
},
|
|
50
50
|
|
|
51
51
|
async handler(ctx) {
|
|
52
|
-
const { logger, args, opts, options, orgId, region,
|
|
52
|
+
const { logger, args, opts, options, orgId, region, auth } = ctx;
|
|
53
53
|
|
|
54
|
-
const catalystClient = getCatalystAPIClient(
|
|
54
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
55
55
|
|
|
56
56
|
// Fetch bucket credentials
|
|
57
57
|
const resources = await tui.spinner({
|
|
@@ -24,8 +24,8 @@ export const deleteSubcommand = createSubcommand({
|
|
|
24
24
|
}),
|
|
25
25
|
},
|
|
26
26
|
async handler(ctx) {
|
|
27
|
-
const {
|
|
28
|
-
const catalystClient = getCatalystAPIClient(
|
|
27
|
+
const { logger, auth, args, region } = ctx;
|
|
28
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
29
29
|
|
|
30
30
|
try {
|
|
31
31
|
await threadDelete(catalystClient, { id: args.thread_id });
|
|
@@ -37,8 +37,8 @@ export const getSubcommand = createSubcommand({
|
|
|
37
37
|
response: ThreadGetResponseSchema,
|
|
38
38
|
},
|
|
39
39
|
async handler(ctx) {
|
|
40
|
-
const {
|
|
41
|
-
const catalystClient = getCatalystAPIClient(
|
|
40
|
+
const { logger, auth, args, options, region } = ctx;
|
|
41
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
42
42
|
|
|
43
43
|
try {
|
|
44
44
|
const thread = await threadGet(catalystClient, { id: args.thread_id });
|
|
@@ -62,8 +62,8 @@ export const listSubcommand = createSubcommand({
|
|
|
62
62
|
response: ThreadListResponseSchema,
|
|
63
63
|
},
|
|
64
64
|
async handler(ctx) {
|
|
65
|
-
const {
|
|
66
|
-
const catalystClient = getCatalystAPIClient(
|
|
65
|
+
const { logger, auth, project, opts, options, region } = ctx;
|
|
66
|
+
const catalystClient = getCatalystAPIClient(logger, auth, region);
|
|
67
67
|
|
|
68
68
|
const projectId = opts.projectId || project?.projectId;
|
|
69
69
|
const orgId = opts.orgId;
|
package/src/cmd/dev/index.ts
CHANGED
package/src/config.ts
CHANGED
|
@@ -727,12 +727,7 @@ export async function loadProjectSDKKey(
|
|
|
727
727
|
logger.trace(`[SDK_KEY] AGENTUITY_SDK_KEY not found in any file`);
|
|
728
728
|
}
|
|
729
729
|
|
|
730
|
-
export function getCatalystAPIClient(
|
|
731
|
-
config: Config | null,
|
|
732
|
-
logger: Logger,
|
|
733
|
-
auth: AuthData,
|
|
734
|
-
region: string
|
|
735
|
-
) {
|
|
730
|
+
export function getCatalystAPIClient(logger: Logger, auth: AuthData, region: string) {
|
|
736
731
|
const serviceUrls = getServiceUrls(region);
|
|
737
732
|
const catalystUrl = serviceUrls.catalyst;
|
|
738
733
|
return new ServerAPIClient(catalystUrl, logger, auth.apiKey);
|
|
@@ -745,3 +740,11 @@ export function getIONHost(config: Config | null) {
|
|
|
745
740
|
const url = new URL(config?.overrides?.ion_url ?? 'https://ion.agentuity.cloud');
|
|
746
741
|
return url.hostname;
|
|
747
742
|
}
|
|
743
|
+
|
|
744
|
+
export function getStreamURL(region: string, config: Config | null) {
|
|
745
|
+
if (config?.name === 'local') {
|
|
746
|
+
return 'https://streams.agentuity.io';
|
|
747
|
+
}
|
|
748
|
+
const serviceUrls = getServiceUrls(region);
|
|
749
|
+
return serviceUrls.stream;
|
|
750
|
+
}
|
package/src/env-util.ts
CHANGED
|
@@ -70,7 +70,6 @@ export async function readEnvFile(path: string): Promise<EnvVars> {
|
|
|
70
70
|
const file = Bun.file(path);
|
|
71
71
|
|
|
72
72
|
if (!(await file.exists())) {
|
|
73
|
-
console.log(`[ENV] File does not exist: ${path}`);
|
|
74
73
|
return {};
|
|
75
74
|
}
|
|
76
75
|
|
|
@@ -85,8 +84,6 @@ export async function readEnvFile(path: string): Promise<EnvVars> {
|
|
|
85
84
|
}
|
|
86
85
|
}
|
|
87
86
|
|
|
88
|
-
console.log(`[ENV] Read ${Object.keys(env).length} variables from: ${path}`);
|
|
89
|
-
console.log(`[ENV] Variables: ${Object.keys(env).join(', ')}`);
|
|
90
87
|
return env;
|
|
91
88
|
}
|
|
92
89
|
|
package/src/output.ts
CHANGED
|
@@ -39,7 +39,13 @@ export function isQuietMode(options: GlobalOptions): boolean {
|
|
|
39
39
|
* Check if progress indicators should be disabled
|
|
40
40
|
*/
|
|
41
41
|
export function shouldDisableProgress(options: GlobalOptions): boolean {
|
|
42
|
-
return
|
|
42
|
+
return (
|
|
43
|
+
options.noProgress === true ||
|
|
44
|
+
options.json === true ||
|
|
45
|
+
options.quiet === true ||
|
|
46
|
+
options.logLevel === 'debug' ||
|
|
47
|
+
options.logLevel === 'trace'
|
|
48
|
+
);
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
/**
|
package/src/tui.ts
CHANGED
|
@@ -341,6 +341,85 @@ function getDisplayWidth(str: string): number {
|
|
|
341
341
|
return Bun.stringWidth(withoutOSC8);
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
+
/**
|
|
345
|
+
* Strip all ANSI escape sequences from a string
|
|
346
|
+
*/
|
|
347
|
+
function stripAnsi(str: string): string {
|
|
348
|
+
// eslint-disable-next-line no-control-regex
|
|
349
|
+
return str.replace(/\u001b\[[0-9;]*m/g, '').replace(/\u001b\]8;;[^\u0007]*\u0007/g, '');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Truncate a string to a maximum display width, handling ANSI codes and Unicode correctly
|
|
354
|
+
* Preserves ANSI escape sequences and doesn't break multi-byte characters or grapheme clusters
|
|
355
|
+
*/
|
|
356
|
+
function truncateToWidth(str: string, maxWidth: number, ellipsis = '...'): string {
|
|
357
|
+
const totalWidth = getDisplayWidth(str);
|
|
358
|
+
if (totalWidth <= maxWidth) {
|
|
359
|
+
return str;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Strip ANSI to get visible text
|
|
363
|
+
const visible = stripAnsi(str);
|
|
364
|
+
|
|
365
|
+
// Use Intl.Segmenter for grapheme-aware iteration
|
|
366
|
+
const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
|
|
367
|
+
const segments = Array.from(segmenter.segment(visible));
|
|
368
|
+
|
|
369
|
+
// Find the cutoff point by accumulating display width
|
|
370
|
+
let currentWidth = 0;
|
|
371
|
+
let cutIndex = 0;
|
|
372
|
+
const targetWidth = maxWidth - ellipsis.length;
|
|
373
|
+
|
|
374
|
+
for (let i = 0; i < segments.length; i++) {
|
|
375
|
+
const segment = segments[i].segment;
|
|
376
|
+
const segmentWidth = Bun.stringWidth(segment);
|
|
377
|
+
|
|
378
|
+
if (currentWidth + segmentWidth > targetWidth) {
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
currentWidth += segmentWidth;
|
|
383
|
+
cutIndex = segments[i].index + segment.length;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Now reconstruct with ANSI codes preserved
|
|
387
|
+
// Walk through original string and copy characters + ANSI codes until we hit cutIndex in visible content
|
|
388
|
+
let result = '';
|
|
389
|
+
let visibleIndex = 0;
|
|
390
|
+
let i = 0;
|
|
391
|
+
|
|
392
|
+
while (i < str.length && visibleIndex < cutIndex) {
|
|
393
|
+
// Check for ANSI escape sequence
|
|
394
|
+
if (str[i] === '\u001b') {
|
|
395
|
+
// Copy entire ANSI sequence
|
|
396
|
+
// eslint-disable-next-line no-control-regex
|
|
397
|
+
const match = str.slice(i).match(/^\u001b\[[0-9;]*m/);
|
|
398
|
+
if (match) {
|
|
399
|
+
result += match[0];
|
|
400
|
+
i += match[0].length;
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// Check for OSC 8 hyperlink
|
|
405
|
+
// eslint-disable-next-line no-control-regex
|
|
406
|
+
const oscMatch = str.slice(i).match(/^\u001b\]8;;[^\u0007]*\u0007/);
|
|
407
|
+
if (oscMatch) {
|
|
408
|
+
result += oscMatch[0];
|
|
409
|
+
i += oscMatch[0].length;
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Copy visible character
|
|
415
|
+
result += str[i];
|
|
416
|
+
visibleIndex++;
|
|
417
|
+
i++;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return result + ellipsis;
|
|
421
|
+
}
|
|
422
|
+
|
|
344
423
|
/**
|
|
345
424
|
* Pad a string to a specific length on the right
|
|
346
425
|
*/
|
|
@@ -796,6 +875,11 @@ function wrapText(text: string, maxWidth: number): string[] {
|
|
|
796
875
|
*/
|
|
797
876
|
export type SpinnerProgressCallback = (progress: number) => void;
|
|
798
877
|
|
|
878
|
+
/**
|
|
879
|
+
* Log callback for spinner
|
|
880
|
+
*/
|
|
881
|
+
export type SpinnerLogCallback = (message: string) => void;
|
|
882
|
+
|
|
799
883
|
/**
|
|
800
884
|
* Spinner options (simple without progress)
|
|
801
885
|
*/
|
|
@@ -824,10 +908,32 @@ export interface ProgressSpinnerOptions<T> {
|
|
|
824
908
|
clearOnSuccess?: boolean;
|
|
825
909
|
}
|
|
826
910
|
|
|
911
|
+
/**
|
|
912
|
+
* Spinner options (with logger streaming)
|
|
913
|
+
*/
|
|
914
|
+
export interface LoggerSpinnerOptions<T> {
|
|
915
|
+
type: 'logger';
|
|
916
|
+
message: string;
|
|
917
|
+
callback: (log: SpinnerLogCallback) => Promise<T>;
|
|
918
|
+
/**
|
|
919
|
+
* If true, clear the spinner output on success (no icon, no message)
|
|
920
|
+
* Defaults to false
|
|
921
|
+
*/
|
|
922
|
+
clearOnSuccess?: boolean;
|
|
923
|
+
/**
|
|
924
|
+
* Maximum number of log lines to show while running
|
|
925
|
+
* If < 0, shows all lines. Defaults to 3.
|
|
926
|
+
*/
|
|
927
|
+
maxLines?: number;
|
|
928
|
+
}
|
|
929
|
+
|
|
827
930
|
/**
|
|
828
931
|
* Spinner options (discriminated union)
|
|
829
932
|
*/
|
|
830
|
-
export type SpinnerOptions<T> =
|
|
933
|
+
export type SpinnerOptions<T> =
|
|
934
|
+
| SimpleSpinnerOptions<T>
|
|
935
|
+
| ProgressSpinnerOptions<T>
|
|
936
|
+
| LoggerSpinnerOptions<T>;
|
|
831
937
|
|
|
832
938
|
/**
|
|
833
939
|
* Run a callback with an animated spinner (simple overload)
|
|
@@ -882,9 +988,14 @@ export async function spinner<T>(
|
|
|
882
988
|
const result =
|
|
883
989
|
options.type === 'progress'
|
|
884
990
|
? await options.callback(() => {})
|
|
885
|
-
:
|
|
886
|
-
? await options.callback()
|
|
887
|
-
|
|
991
|
+
: options.type === 'logger'
|
|
992
|
+
? await options.callback((logMessage: string) => {
|
|
993
|
+
// In non-TTY mode, just write logs directly to stdout
|
|
994
|
+
process.stdout.write(logMessage + '\n');
|
|
995
|
+
})
|
|
996
|
+
: typeof options.callback === 'function'
|
|
997
|
+
? await options.callback()
|
|
998
|
+
: await options.callback;
|
|
888
999
|
|
|
889
1000
|
// If clearOnSuccess is true, don't show success message
|
|
890
1001
|
// Also skip success message in JSON mode
|
|
@@ -914,12 +1025,22 @@ export async function spinner<T>(
|
|
|
914
1025
|
|
|
915
1026
|
let frameIndex = 0;
|
|
916
1027
|
let currentProgress: number | undefined;
|
|
1028
|
+
const logLines: string[] = [];
|
|
1029
|
+
const maxLines = options.type === 'logger' ? (options.maxLines ?? 3) : 0;
|
|
1030
|
+
const mutedColor = getColor('muted');
|
|
1031
|
+
let linesRendered = 0;
|
|
917
1032
|
|
|
918
|
-
//
|
|
919
|
-
process.stderr.
|
|
1033
|
+
// Get terminal width for truncation
|
|
1034
|
+
const termWidth = process.stderr.columns || 80;
|
|
1035
|
+
const maxLineWidth = Math.min(80, termWidth);
|
|
1036
|
+
|
|
1037
|
+
// Function to render spinner with optional log lines
|
|
1038
|
+
const renderSpinner = () => {
|
|
1039
|
+
// Move cursor up to start of our output area if we've rendered before
|
|
1040
|
+
if (linesRendered > 0) {
|
|
1041
|
+
process.stderr.write(`\x1b[${linesRendered}A`);
|
|
1042
|
+
}
|
|
920
1043
|
|
|
921
|
-
// Start animation
|
|
922
|
-
const interval = setInterval(() => {
|
|
923
1044
|
const colorDef = spinnerColors[frameIndex % spinnerColors.length];
|
|
924
1045
|
const color = colorDef[currentColorScheme];
|
|
925
1046
|
const frame = `${color}${bold}${frames[frameIndex % frames.length]}${reset}`;
|
|
@@ -930,31 +1051,64 @@ export async function spinner<T>(
|
|
|
930
1051
|
? ` ${cyanColor}${Math.floor(currentProgress)}%${reset}`
|
|
931
1052
|
: '';
|
|
932
1053
|
|
|
933
|
-
//
|
|
934
|
-
process.stderr.write(
|
|
1054
|
+
// Render spinner line
|
|
1055
|
+
process.stderr.write(`\r\x1b[K${frame} ${message}${progressIndicator}\n`);
|
|
1056
|
+
|
|
1057
|
+
// Render log lines if in logger mode
|
|
1058
|
+
if (options.type === 'logger') {
|
|
1059
|
+
const displayLines = maxLines < 0 ? logLines : logLines.slice(-maxLines);
|
|
1060
|
+
for (const line of displayLines) {
|
|
1061
|
+
const displayLine =
|
|
1062
|
+
getDisplayWidth(line) > maxLineWidth ? truncateToWidth(line, maxLineWidth) : line;
|
|
1063
|
+
process.stderr.write(`\r\x1b[K${mutedColor}${displayLine}${reset}\n`);
|
|
1064
|
+
}
|
|
1065
|
+
linesRendered = 1 + displayLines.length;
|
|
1066
|
+
} else {
|
|
1067
|
+
linesRendered = 1;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
935
1070
|
frameIndex++;
|
|
936
|
-
}
|
|
1071
|
+
};
|
|
1072
|
+
|
|
1073
|
+
// Save cursor position and hide cursor
|
|
1074
|
+
process.stderr.write('\x1B[s\x1B[?25l');
|
|
1075
|
+
|
|
1076
|
+
// Initial render
|
|
1077
|
+
renderSpinner();
|
|
1078
|
+
|
|
1079
|
+
// Start animation
|
|
1080
|
+
const interval = setInterval(renderSpinner, 120);
|
|
937
1081
|
|
|
938
1082
|
// Progress callback
|
|
939
1083
|
const progressCallback: SpinnerProgressCallback = (progress: number) => {
|
|
940
1084
|
currentProgress = Math.min(100, Math.max(0, progress));
|
|
941
1085
|
};
|
|
942
1086
|
|
|
1087
|
+
// Log callback
|
|
1088
|
+
const logCallback: SpinnerLogCallback = (logMessage: string) => {
|
|
1089
|
+
logLines.push(logMessage);
|
|
1090
|
+
};
|
|
1091
|
+
|
|
943
1092
|
try {
|
|
944
1093
|
// Execute callback
|
|
945
1094
|
const result =
|
|
946
1095
|
options.type === 'progress'
|
|
947
1096
|
? await options.callback(progressCallback)
|
|
948
|
-
:
|
|
949
|
-
? await options.callback()
|
|
950
|
-
:
|
|
1097
|
+
: options.type === 'logger'
|
|
1098
|
+
? await options.callback(logCallback)
|
|
1099
|
+
: typeof options.callback === 'function'
|
|
1100
|
+
? await options.callback()
|
|
1101
|
+
: await options.callback;
|
|
951
1102
|
|
|
952
1103
|
// Stop animation first
|
|
953
1104
|
clearInterval(interval);
|
|
954
1105
|
|
|
955
|
-
//
|
|
956
|
-
|
|
957
|
-
|
|
1106
|
+
// Move cursor to start of output, clear all lines
|
|
1107
|
+
if (linesRendered > 0) {
|
|
1108
|
+
process.stderr.write(`\x1b[${linesRendered}A`);
|
|
1109
|
+
}
|
|
1110
|
+
process.stderr.write('\x1b[J'); // Clear from cursor to end of screen
|
|
1111
|
+
process.stderr.write('\x1B[?25h'); // Show cursor
|
|
958
1112
|
|
|
959
1113
|
// If clearOnSuccess is false, show success message
|
|
960
1114
|
if (!options.clearOnSuccess) {
|
|
@@ -968,17 +1122,27 @@ export async function spinner<T>(
|
|
|
968
1122
|
// Stop animation first
|
|
969
1123
|
clearInterval(interval);
|
|
970
1124
|
|
|
971
|
-
//
|
|
972
|
-
|
|
1125
|
+
// Move cursor to start of output, clear all lines
|
|
1126
|
+
if (linesRendered > 0) {
|
|
1127
|
+
process.stderr.write(`\x1b[${linesRendered}A`);
|
|
1128
|
+
}
|
|
1129
|
+
process.stderr.write('\x1b[J'); // Clear from cursor to end of screen
|
|
1130
|
+
process.stderr.write('\x1B[?25h'); // Show cursor
|
|
973
1131
|
|
|
974
1132
|
// Show error
|
|
975
1133
|
const errorColor = getColor('error');
|
|
976
|
-
|
|
1134
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1135
|
+
console.error(`${errorColor}${ICONS.error} ${message}: ${errorMessage}${reset}`);
|
|
977
1136
|
|
|
978
1137
|
throw err;
|
|
979
1138
|
}
|
|
980
1139
|
}
|
|
981
1140
|
|
|
1141
|
+
/**
|
|
1142
|
+
* Alias for spinner function (for better semantics when using progress/logger types)
|
|
1143
|
+
*/
|
|
1144
|
+
export const progress = spinner;
|
|
1145
|
+
|
|
982
1146
|
/**
|
|
983
1147
|
* Options for running a command with streaming output
|
|
984
1148
|
*/
|
|
@@ -1072,11 +1236,8 @@ export async function runCommand(options: CommandRunnerOptions): Promise<number>
|
|
|
1072
1236
|
const maxLineWidth = Math.min(80, termWidth);
|
|
1073
1237
|
|
|
1074
1238
|
// Truncate command if needed
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
// Simple truncation for now - could be smarter about this
|
|
1078
|
-
displayCmd = displayCmd.slice(0, maxCmdWidth - 3) + '...';
|
|
1079
|
-
}
|
|
1239
|
+
const displayCmd =
|
|
1240
|
+
getDisplayWidth(command) > maxCmdWidth ? truncateToWidth(command, maxCmdWidth) : command;
|
|
1080
1241
|
|
|
1081
1242
|
// Store all output lines, display subset based on context
|
|
1082
1243
|
const allOutputLines: string[] = [];
|
|
@@ -1100,11 +1261,8 @@ export async function runCommand(options: CommandRunnerOptions): Promise<number>
|
|
|
1100
1261
|
|
|
1101
1262
|
// Render output lines
|
|
1102
1263
|
for (const line of displayLines) {
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
if (getDisplayWidth(displayLine) > maxLineWidth) {
|
|
1106
|
-
displayLine = displayLine.slice(0, maxLineWidth - 3) + '...';
|
|
1107
|
-
}
|
|
1264
|
+
const displayLine =
|
|
1265
|
+
getDisplayWidth(line) > maxLineWidth ? truncateToWidth(line, maxLineWidth) : line;
|
|
1108
1266
|
process.stdout.write(`\r\x1b[K${mutedColor}${displayLine}${reset}\n`);
|
|
1109
1267
|
}
|
|
1110
1268
|
|
|
@@ -1198,10 +1356,10 @@ export async function runCommand(options: CommandRunnerOptions): Promise<number>
|
|
|
1198
1356
|
// Show final output lines
|
|
1199
1357
|
const finalOutputLines = allOutputLines.slice(-finalLinesToShow);
|
|
1200
1358
|
for (const line of finalOutputLines) {
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1359
|
+
const displayLine =
|
|
1360
|
+
truncate && getDisplayWidth(line) > maxLineWidth
|
|
1361
|
+
? truncateToWidth(line, maxLineWidth)
|
|
1362
|
+
: line;
|
|
1205
1363
|
process.stdout.write(`\r\x1b[K${mutedColor}${displayLine}${reset}\n`);
|
|
1206
1364
|
}
|
|
1207
1365
|
|