@agentuity/cli 0.0.35 → 0.0.42
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/AGENTS.md +2 -2
- package/README.md +4 -4
- package/dist/api.d.ts +6 -22
- package/dist/api.d.ts.map +1 -1
- package/dist/auth.d.ts +0 -2
- package/dist/auth.d.ts.map +1 -1
- package/dist/banner.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cmd/auth/api.d.ts.map +1 -1
- package/dist/cmd/auth/login.d.ts +1 -2
- package/dist/cmd/auth/login.d.ts.map +1 -1
- package/dist/cmd/auth/logout.d.ts +1 -2
- package/dist/cmd/auth/logout.d.ts.map +1 -1
- package/dist/cmd/auth/signup.d.ts +1 -2
- package/dist/cmd/auth/signup.d.ts.map +1 -1
- package/dist/cmd/bundle/ast.d.ts +2 -0
- package/dist/cmd/bundle/ast.d.ts.map +1 -1
- package/dist/cmd/bundle/bundler.d.ts +1 -0
- package/dist/cmd/bundle/bundler.d.ts.map +1 -1
- package/dist/cmd/bundle/patch/index.d.ts.map +1 -1
- package/dist/cmd/bundle/patch/llm.d.ts +3 -0
- package/dist/cmd/bundle/patch/llm.d.ts.map +1 -0
- package/dist/cmd/bundle/plugin.d.ts.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/delete.d.ts.map +1 -1
- package/dist/cmd/project/download.d.ts.map +1 -1
- package/dist/cmd/project/list.d.ts.map +1 -1
- package/dist/cmd/project/show.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.d.ts +3 -0
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/config.d.ts +11 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/sound.d.ts.map +1 -1
- package/dist/tui.d.ts +16 -7
- package/dist/tui.d.ts.map +1 -1
- package/dist/types.d.ts +70 -7
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/api.ts +27 -138
- package/src/auth.ts +87 -71
- package/src/banner.ts +7 -2
- package/src/cli.ts +7 -16
- package/src/cmd/auth/api.ts +40 -29
- package/src/cmd/auth/login.ts +7 -20
- package/src/cmd/auth/logout.ts +3 -3
- package/src/cmd/auth/signup.ts +6 -6
- package/src/cmd/bundle/ast.ts +169 -4
- package/src/cmd/bundle/bundler.ts +1 -0
- package/src/cmd/bundle/patch/index.ts +4 -0
- package/src/cmd/bundle/patch/llm.ts +36 -0
- package/src/cmd/bundle/plugin.ts +42 -1
- package/src/cmd/dev/index.ts +100 -1
- package/src/cmd/example/optional-auth.ts +1 -1
- package/src/cmd/index.ts +1 -0
- package/src/cmd/profile/README.md +1 -1
- package/src/cmd/project/create.ts +10 -2
- package/src/cmd/project/delete.ts +43 -2
- package/src/cmd/project/download.ts +17 -0
- package/src/cmd/project/list.ts +33 -2
- package/src/cmd/project/show.ts +35 -3
- package/src/cmd/project/template-flow.ts +60 -5
- package/src/config.ts +77 -5
- package/src/index.ts +2 -2
- package/src/logger.ts +1 -1
- package/src/sound.ts +9 -3
- package/src/tui.ts +234 -104
- package/src/types.ts +97 -34
package/src/tui.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Provides semantic helpers for console output with automatic icons and colors.
|
|
5
5
|
* Uses Bun's built-in color support and ANSI escape codes.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
import enquirer from 'enquirer';
|
|
8
|
+
import type { OrganizationList } from '@agentuity/server';
|
|
8
9
|
import type { ColorScheme } from './terminal';
|
|
9
10
|
|
|
10
11
|
// Icons
|
|
@@ -17,38 +18,58 @@ const ICONS = {
|
|
|
17
18
|
bullet: '•',
|
|
18
19
|
} as const;
|
|
19
20
|
|
|
21
|
+
function shouldUseColors(): boolean {
|
|
22
|
+
return !process.env.NO_COLOR && process.env.TERM !== 'dumb' && !!process.stdout.isTTY;
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
// Color definitions (light/dark adaptive) using Bun.color
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
26
|
+
function getColors() {
|
|
27
|
+
const USE_COLORS = shouldUseColors();
|
|
28
|
+
if (!USE_COLORS) {
|
|
29
|
+
return {
|
|
30
|
+
success: { light: '', dark: '' },
|
|
31
|
+
error: { light: '', dark: '' },
|
|
32
|
+
warning: { light: '', dark: '' },
|
|
33
|
+
info: { light: '', dark: '' },
|
|
34
|
+
muted: { light: '', dark: '' },
|
|
35
|
+
bold: { light: '', dark: '' },
|
|
36
|
+
link: { light: '', dark: '' },
|
|
37
|
+
reset: '',
|
|
38
|
+
} as const;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
success: {
|
|
43
|
+
light: Bun.color('#008000', 'ansi') || '\x1b[32m', // green
|
|
44
|
+
dark: Bun.color('#00FF00', 'ansi') || '\x1b[92m', // bright green
|
|
45
|
+
},
|
|
46
|
+
error: {
|
|
47
|
+
light: Bun.color('#CC0000', 'ansi') || '\x1b[31m', // red
|
|
48
|
+
dark: Bun.color('#FF5555', 'ansi') || '\x1b[91m', // bright red
|
|
49
|
+
},
|
|
50
|
+
warning: {
|
|
51
|
+
light: Bun.color('#B58900', 'ansi') || '\x1b[33m', // yellow
|
|
52
|
+
dark: Bun.color('#FFFF55', 'ansi') || '\x1b[93m', // bright yellow
|
|
53
|
+
},
|
|
54
|
+
info: {
|
|
55
|
+
light: Bun.color('#008B8B', 'ansi') || '\x1b[36m', // dark cyan
|
|
56
|
+
dark: Bun.color('#55FFFF', 'ansi') || '\x1b[96m', // bright cyan
|
|
57
|
+
},
|
|
58
|
+
muted: {
|
|
59
|
+
light: Bun.color('#808080', 'ansi') || '\x1b[90m', // gray
|
|
60
|
+
dark: Bun.color('#888888', 'ansi') || '\x1b[90m', // darker gray
|
|
61
|
+
},
|
|
62
|
+
bold: {
|
|
63
|
+
light: '\x1b[1m',
|
|
64
|
+
dark: '\x1b[1m',
|
|
65
|
+
},
|
|
66
|
+
link: {
|
|
67
|
+
light: '\x1b[34;4m', // blue underline (need ANSI for underline)
|
|
68
|
+
dark: '\x1b[94;4m', // bright blue underline
|
|
69
|
+
},
|
|
70
|
+
reset: '\x1b[0m',
|
|
71
|
+
} as const;
|
|
72
|
+
}
|
|
52
73
|
|
|
53
74
|
let currentColorScheme: ColorScheme = 'dark';
|
|
54
75
|
|
|
@@ -56,7 +77,8 @@ export function setColorScheme(scheme: ColorScheme): void {
|
|
|
56
77
|
currentColorScheme = scheme;
|
|
57
78
|
}
|
|
58
79
|
|
|
59
|
-
function getColor(colorKey: keyof typeof
|
|
80
|
+
function getColor(colorKey: keyof ReturnType<typeof getColors>): string {
|
|
81
|
+
const COLORS = getColors();
|
|
60
82
|
const color = COLORS[colorKey];
|
|
61
83
|
if (typeof color === 'string') {
|
|
62
84
|
return color;
|
|
@@ -69,7 +91,7 @@ function getColor(colorKey: keyof typeof COLORS): string {
|
|
|
69
91
|
*/
|
|
70
92
|
export function success(message: string): void {
|
|
71
93
|
const color = getColor('success');
|
|
72
|
-
const reset =
|
|
94
|
+
const reset = getColor('reset');
|
|
73
95
|
console.log(`${color}${ICONS.success} ${message}${reset}`);
|
|
74
96
|
}
|
|
75
97
|
|
|
@@ -78,7 +100,7 @@ export function success(message: string): void {
|
|
|
78
100
|
*/
|
|
79
101
|
export function error(message: string): void {
|
|
80
102
|
const color = getColor('error');
|
|
81
|
-
const reset =
|
|
103
|
+
const reset = getColor('reset');
|
|
82
104
|
console.error(`${color}${ICONS.error} ${message}${reset}`);
|
|
83
105
|
}
|
|
84
106
|
|
|
@@ -87,7 +109,7 @@ export function error(message: string): void {
|
|
|
87
109
|
*/
|
|
88
110
|
export function fatal(message: string): never {
|
|
89
111
|
const color = getColor('error');
|
|
90
|
-
const reset =
|
|
112
|
+
const reset = getColor('reset');
|
|
91
113
|
console.error(`${color}${ICONS.error} ${message}${reset}`);
|
|
92
114
|
process.exit(1);
|
|
93
115
|
}
|
|
@@ -97,7 +119,7 @@ export function fatal(message: string): never {
|
|
|
97
119
|
*/
|
|
98
120
|
export function warning(message: string, asError = false): void {
|
|
99
121
|
const color = asError ? getColor('error') : getColor('warning');
|
|
100
|
-
const reset =
|
|
122
|
+
const reset = getColor('reset');
|
|
101
123
|
console.log(`${color}${ICONS.warning} ${message}${reset}`);
|
|
102
124
|
}
|
|
103
125
|
|
|
@@ -106,7 +128,7 @@ export function warning(message: string, asError = false): void {
|
|
|
106
128
|
*/
|
|
107
129
|
export function info(message: string): void {
|
|
108
130
|
const color = getColor('info');
|
|
109
|
-
const reset =
|
|
131
|
+
const reset = getColor('reset');
|
|
110
132
|
console.log(`${color}${ICONS.info} ${message}${reset}`);
|
|
111
133
|
}
|
|
112
134
|
|
|
@@ -115,7 +137,7 @@ export function info(message: string): void {
|
|
|
115
137
|
*/
|
|
116
138
|
export function muted(text: string): string {
|
|
117
139
|
const color = getColor('muted');
|
|
118
|
-
const reset =
|
|
140
|
+
const reset = getColor('reset');
|
|
119
141
|
return `${color}${text}${reset}`;
|
|
120
142
|
}
|
|
121
143
|
|
|
@@ -124,7 +146,7 @@ export function muted(text: string): string {
|
|
|
124
146
|
*/
|
|
125
147
|
export function bold(text: string): string {
|
|
126
148
|
const color = getColor('bold');
|
|
127
|
-
const reset =
|
|
149
|
+
const reset = getColor('reset');
|
|
128
150
|
return `${color}${text}${reset}`;
|
|
129
151
|
}
|
|
130
152
|
|
|
@@ -133,7 +155,7 @@ export function bold(text: string): string {
|
|
|
133
155
|
*/
|
|
134
156
|
export function link(url: string): string {
|
|
135
157
|
const color = getColor('link');
|
|
136
|
-
const reset =
|
|
158
|
+
const reset = getColor('reset');
|
|
137
159
|
|
|
138
160
|
// Check if terminal supports hyperlinks (OSC 8)
|
|
139
161
|
if (supportsHyperlinks()) {
|
|
@@ -205,6 +227,15 @@ export function padLeft(str: string, length: number, pad = ' '): string {
|
|
|
205
227
|
return pad.repeat(length - str.length) + str;
|
|
206
228
|
}
|
|
207
229
|
|
|
230
|
+
interface BannerOptions {
|
|
231
|
+
padding?: number;
|
|
232
|
+
minWidth?: number;
|
|
233
|
+
topSpacer?: boolean;
|
|
234
|
+
middleSpacer?: boolean;
|
|
235
|
+
bottomSpacer?: boolean;
|
|
236
|
+
centerTitle?: boolean;
|
|
237
|
+
}
|
|
238
|
+
|
|
208
239
|
/**
|
|
209
240
|
* Display a formatted banner with title and body content
|
|
210
241
|
* Creates a bordered box around the content
|
|
@@ -212,10 +243,12 @@ export function padLeft(str: string, length: number, pad = ' '): string {
|
|
|
212
243
|
* Uses Bun.stringWidth() for accurate width calculation with ANSI codes and unicode
|
|
213
244
|
* Responsive to terminal width - adapts to narrow terminals
|
|
214
245
|
*/
|
|
215
|
-
export function banner(title: string, body: string): void {
|
|
246
|
+
export function banner(title: string, body: string, options?: BannerOptions): void {
|
|
216
247
|
// Get terminal width, default to 80 if not available, minimum 40
|
|
217
248
|
const termWidth = process.stdout.columns || 80;
|
|
218
|
-
const
|
|
249
|
+
const minWidth = options?.minWidth ?? 40;
|
|
250
|
+
const maxWidth = Math.max(minWidth, Math.min(termWidth - 2, 80)); // Between 40 and 80, with 2 char margin
|
|
251
|
+
const padding = options?.padding ?? 4;
|
|
219
252
|
|
|
220
253
|
const border = {
|
|
221
254
|
topLeft: '╭',
|
|
@@ -227,19 +260,19 @@ export function banner(title: string, body: string): void {
|
|
|
227
260
|
};
|
|
228
261
|
|
|
229
262
|
// Split body into lines and wrap if needed
|
|
230
|
-
const bodyLines = wrapText(body, maxWidth -
|
|
263
|
+
const bodyLines = wrapText(body, maxWidth - padding); // -4 for padding and borders
|
|
231
264
|
|
|
232
265
|
// Calculate width based on content
|
|
233
266
|
const titleWidth = getDisplayWidth(title);
|
|
234
267
|
const maxBodyWidth = Math.max(...bodyLines.map((line) => getDisplayWidth(line)));
|
|
235
|
-
const contentWidth = Math.max(titleWidth, maxBodyWidth);
|
|
236
|
-
const boxWidth = Math.min(contentWidth
|
|
237
|
-
const innerWidth = boxWidth -
|
|
268
|
+
const contentWidth = Math.max(minWidth, Math.max(titleWidth, maxBodyWidth) + padding);
|
|
269
|
+
const boxWidth = Math.min(contentWidth, maxWidth); // +N for padding
|
|
270
|
+
const innerWidth = boxWidth - padding;
|
|
238
271
|
|
|
239
272
|
// Colors
|
|
240
273
|
const borderColor = getColor('muted');
|
|
241
274
|
const titleColor = getColor('info');
|
|
242
|
-
const reset =
|
|
275
|
+
const reset = getColor('reset');
|
|
243
276
|
|
|
244
277
|
// Build banner
|
|
245
278
|
const lines: string[] = [];
|
|
@@ -249,41 +282,58 @@ export function banner(title: string, body: string): void {
|
|
|
249
282
|
`${borderColor}${border.topLeft}${border.horizontal.repeat(boxWidth - 2)}${border.topRight}${reset}`
|
|
250
283
|
);
|
|
251
284
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
285
|
+
if (options?.topSpacer === true || options?.topSpacer === undefined) {
|
|
286
|
+
// Empty line
|
|
287
|
+
lines.push(
|
|
288
|
+
`${borderColor}${border.vertical}${' '.repeat(boxWidth - 2)}${border.vertical}${reset}`
|
|
289
|
+
);
|
|
290
|
+
}
|
|
256
291
|
|
|
257
292
|
// Title (centered and bold)
|
|
258
293
|
const titleDisplayWidth = getDisplayWidth(title);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
294
|
+
if (options?.centerTitle === true || options?.centerTitle === undefined) {
|
|
295
|
+
const titlePadding = Math.max(0, Math.floor((innerWidth - titleDisplayWidth) / 2));
|
|
296
|
+
const titleRightPadding = Math.max(
|
|
297
|
+
0,
|
|
298
|
+
Math.max(0, innerWidth - titlePadding - titleDisplayWidth) - padding
|
|
299
|
+
);
|
|
300
|
+
const titleLine =
|
|
301
|
+
' '.repeat(titlePadding) +
|
|
302
|
+
`${titleColor}${bold(title)}${reset}` +
|
|
303
|
+
' '.repeat(titleRightPadding);
|
|
304
|
+
lines.push(
|
|
305
|
+
`${borderColor}${border.vertical} ${reset}${titleLine}${borderColor} ${border.vertical}${reset}`
|
|
306
|
+
);
|
|
307
|
+
} else {
|
|
308
|
+
const titleRightPadding = Math.max(0, Math.max(0, innerWidth - titleDisplayWidth) - padding);
|
|
309
|
+
const titleLine = `${titleColor}${bold(title)}${reset}` + ' '.repeat(titleRightPadding);
|
|
310
|
+
lines.push(
|
|
311
|
+
`${borderColor}${border.vertical} ${reset}${titleLine}${borderColor} ${border.vertical}${reset}`
|
|
312
|
+
);
|
|
313
|
+
}
|
|
268
314
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
315
|
+
if (options?.middleSpacer === true || options?.middleSpacer === undefined) {
|
|
316
|
+
// Empty line
|
|
317
|
+
lines.push(
|
|
318
|
+
`${borderColor}${border.vertical}${' '.repeat(boxWidth - 2)}${border.vertical}${reset}`
|
|
319
|
+
);
|
|
320
|
+
}
|
|
273
321
|
|
|
274
322
|
// Body lines
|
|
275
323
|
for (const line of bodyLines) {
|
|
276
324
|
const lineWidth = getDisplayWidth(line);
|
|
277
|
-
const
|
|
325
|
+
const linePadding = Math.max(0, Math.max(0, innerWidth - lineWidth) - padding);
|
|
278
326
|
lines.push(
|
|
279
|
-
`${borderColor}${border.vertical} ${reset}${line}${' '.repeat(
|
|
327
|
+
`${borderColor}${border.vertical} ${reset}${line}${' '.repeat(linePadding)}${borderColor} ${border.vertical}${reset}`
|
|
280
328
|
);
|
|
281
329
|
}
|
|
282
330
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
331
|
+
if (options?.bottomSpacer === true || options?.bottomSpacer === undefined) {
|
|
332
|
+
// Empty line
|
|
333
|
+
lines.push(
|
|
334
|
+
`${borderColor}${border.vertical}${' '.repeat(boxWidth - 2)}${border.vertical}${reset}`
|
|
335
|
+
);
|
|
336
|
+
}
|
|
287
337
|
|
|
288
338
|
// Bottom border
|
|
289
339
|
lines.push(
|
|
@@ -418,6 +468,30 @@ export function showSignupBenefits(): void {
|
|
|
418
468
|
console.log('');
|
|
419
469
|
}
|
|
420
470
|
|
|
471
|
+
/**
|
|
472
|
+
* Display a message when unauthenticated to let the user know certain capabilities are disabled
|
|
473
|
+
*/
|
|
474
|
+
export function showLoggedOutMessage(): void {
|
|
475
|
+
const CYAN = Bun.color('yellow', 'ansi-16m');
|
|
476
|
+
const TEXT =
|
|
477
|
+
currentColorScheme === 'dark' ? Bun.color('white', 'ansi') : Bun.color('black', 'ansi');
|
|
478
|
+
const RESET = '\x1b[0m';
|
|
479
|
+
|
|
480
|
+
const lines = [
|
|
481
|
+
'╔══════════════════════════════════════════════╗',
|
|
482
|
+
`║ ⨺ Unauthenticated (local mode) ║`,
|
|
483
|
+
'║ ║',
|
|
484
|
+
`║ ${TEXT}Certain capabilities such as the AI services${CYAN} ║`,
|
|
485
|
+
`║ ${TEXT}and devmode remote are unavailable when${CYAN} ║`,
|
|
486
|
+
`║ ${TEXT}unauthenticated.${CYAN} ║`,
|
|
487
|
+
'╚══════════════════════════════════════════════╝',
|
|
488
|
+
];
|
|
489
|
+
|
|
490
|
+
console.log('');
|
|
491
|
+
lines.forEach((line) => console.log(CYAN + line + RESET));
|
|
492
|
+
console.log('');
|
|
493
|
+
}
|
|
494
|
+
|
|
421
495
|
/**
|
|
422
496
|
* Copy text to clipboard
|
|
423
497
|
* Returns true if successful, false otherwise
|
|
@@ -507,7 +581,7 @@ function stripAnsiCodes(str: string): string {
|
|
|
507
581
|
* Check if a string ends with ANSI reset code
|
|
508
582
|
*/
|
|
509
583
|
function endsWithReset(str: string): boolean {
|
|
510
|
-
return str.endsWith('\x1b[0m') || str.endsWith(
|
|
584
|
+
return str.endsWith('\x1b[0m') || str.endsWith(getColor('reset'));
|
|
511
585
|
}
|
|
512
586
|
|
|
513
587
|
/**
|
|
@@ -572,7 +646,7 @@ function wrapText(text: string, maxWidth: number): string[] {
|
|
|
572
646
|
if (leadingCodes && hasReset) {
|
|
573
647
|
for (let i = paragraphStart; i < allLines.length; i++) {
|
|
574
648
|
if (!endsWithReset(allLines[i])) {
|
|
575
|
-
allLines[i] +=
|
|
649
|
+
allLines[i] += getColor('reset');
|
|
576
650
|
}
|
|
577
651
|
}
|
|
578
652
|
}
|
|
@@ -649,6 +723,26 @@ export async function spinner<T>(
|
|
|
649
723
|
}
|
|
650
724
|
|
|
651
725
|
const message = options.message;
|
|
726
|
+
const reset = getColor('reset');
|
|
727
|
+
|
|
728
|
+
// If no TTY, just execute the callback without animation
|
|
729
|
+
if (!process.stdout.isTTY) {
|
|
730
|
+
try {
|
|
731
|
+
const result =
|
|
732
|
+
options.type === 'progress'
|
|
733
|
+
? await options.callback(() => {})
|
|
734
|
+
: typeof options.callback === 'function'
|
|
735
|
+
? await options.callback()
|
|
736
|
+
: await options.callback;
|
|
737
|
+
|
|
738
|
+
return result;
|
|
739
|
+
} catch (err) {
|
|
740
|
+
const errorColor = getColor('error');
|
|
741
|
+
console.error(`${errorColor}${ICONS.error} ${message}${reset}`);
|
|
742
|
+
throw err;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
652
746
|
const frames = ['◐', '◓', '◑', '◒'];
|
|
653
747
|
const spinnerColors = [
|
|
654
748
|
{ light: '\x1b[36m', dark: '\x1b[96m' }, // cyan
|
|
@@ -657,7 +751,6 @@ export async function spinner<T>(
|
|
|
657
751
|
{ light: '\x1b[36m', dark: '\x1b[96m' }, // cyan
|
|
658
752
|
];
|
|
659
753
|
const bold = '\x1b[1m';
|
|
660
|
-
const reset = COLORS.reset;
|
|
661
754
|
const cyanColor = { light: '\x1b[36m', dark: '\x1b[96m' }[currentColorScheme];
|
|
662
755
|
|
|
663
756
|
let frameIndex = 0;
|
|
@@ -812,7 +905,7 @@ export async function runCommand(options: CommandRunnerOptions): Promise<number>
|
|
|
812
905
|
? '\x1b[1m' + (Bun.color('#00008B', 'ansi') || '\x1b[34m')
|
|
813
906
|
: Bun.color('#FFFFFF', 'ansi') || '\x1b[97m'; // bold dark blue / white
|
|
814
907
|
const mutedColor = Bun.color('#808080', 'ansi') || '\x1b[90m';
|
|
815
|
-
const reset =
|
|
908
|
+
const reset = getColor('reset');
|
|
816
909
|
|
|
817
910
|
// Get terminal width
|
|
818
911
|
const termWidth = process.stdout.columns || 80;
|
|
@@ -905,41 +998,52 @@ export async function runCommand(options: CommandRunnerOptions): Promise<number>
|
|
|
905
998
|
// Wait for process to exit
|
|
906
999
|
const exitCode = await proc.exited;
|
|
907
1000
|
|
|
908
|
-
//
|
|
1001
|
+
// If clearOnSuccess is true and command succeeded, clear everything
|
|
1002
|
+
if (clearOnSuccess && exitCode === 0) {
|
|
1003
|
+
if (linesRendered > 0) {
|
|
1004
|
+
// Move up to the command line
|
|
1005
|
+
process.stdout.write(`\x1b[${linesRendered}A`);
|
|
1006
|
+
// Clear each line (entire line) and move cursor back up
|
|
1007
|
+
for (let i = 0; i < linesRendered; i++) {
|
|
1008
|
+
process.stdout.write('\x1b[2K'); // Clear entire line
|
|
1009
|
+
if (i < linesRendered - 1) {
|
|
1010
|
+
process.stdout.write('\x1b[B'); // Move down one line
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
// Move cursor back up to original position
|
|
1014
|
+
process.stdout.write(`\x1b[${linesRendered}A\r`);
|
|
1015
|
+
}
|
|
1016
|
+
return exitCode;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
// Clear all rendered lines completely
|
|
909
1020
|
if (linesRendered > 0) {
|
|
1021
|
+
// Move up to the command line (first line of our output)
|
|
910
1022
|
process.stdout.write(`\x1b[${linesRendered}A`);
|
|
1023
|
+
// Move to beginning of line and clear from cursor to end of screen
|
|
1024
|
+
process.stdout.write('\r\x1b[J');
|
|
911
1025
|
}
|
|
912
1026
|
|
|
913
|
-
//
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
for (let i = 0; i < linesRendered; i++) {
|
|
917
|
-
process.stdout.write('\r\x1b[K\n');
|
|
918
|
-
}
|
|
919
|
-
// Move cursor back up
|
|
920
|
-
process.stdout.write(`\x1b[${linesRendered}A`);
|
|
1027
|
+
// Determine icon based on exit code
|
|
1028
|
+
const icon = exitCode === 0 ? ICONS.success : ICONS.error;
|
|
1029
|
+
const statusColor = exitCode === 0 ? green : red;
|
|
921
1030
|
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
for (const line of finalOutputLines) {
|
|
937
|
-
let displayLine = line;
|
|
938
|
-
if (truncate && getDisplayWidth(displayLine) > maxLineWidth) {
|
|
939
|
-
displayLine = displayLine.slice(0, maxLineWidth - 3) + '...';
|
|
940
|
-
}
|
|
941
|
-
process.stdout.write(`\r\x1b[K${mutedColor}${displayLine}${reset}\n`);
|
|
1031
|
+
// Show final status: icon + command
|
|
1032
|
+
process.stdout.write(
|
|
1033
|
+
`\r\x1b[K${statusColor}${icon}${reset} ${cmdColor}${displayCmd}${reset}\n`
|
|
1034
|
+
);
|
|
1035
|
+
|
|
1036
|
+
// Determine how many lines to show in final output
|
|
1037
|
+
const finalLinesToShow = exitCode === 0 ? maxLinesOutput : maxLinesOnFailure;
|
|
1038
|
+
|
|
1039
|
+
// Show final output lines
|
|
1040
|
+
const finalOutputLines = allOutputLines.slice(-finalLinesToShow);
|
|
1041
|
+
for (const line of finalOutputLines) {
|
|
1042
|
+
let displayLine = line;
|
|
1043
|
+
if (truncate && getDisplayWidth(displayLine) > maxLineWidth) {
|
|
1044
|
+
displayLine = displayLine.slice(0, maxLineWidth - 3) + '...';
|
|
942
1045
|
}
|
|
1046
|
+
process.stdout.write(`\r\x1b[K${mutedColor}${displayLine}${reset}\n`);
|
|
943
1047
|
}
|
|
944
1048
|
|
|
945
1049
|
return exitCode;
|
|
@@ -971,3 +1075,29 @@ export async function runCommand(options: CommandRunnerOptions): Promise<number>
|
|
|
971
1075
|
process.stdout.write('\x1B[?25h');
|
|
972
1076
|
}
|
|
973
1077
|
}
|
|
1078
|
+
|
|
1079
|
+
export async function selectOrganization(
|
|
1080
|
+
orgs: OrganizationList,
|
|
1081
|
+
initial?: string
|
|
1082
|
+
): Promise<string> {
|
|
1083
|
+
if (orgs.length === 0) {
|
|
1084
|
+
fatal(
|
|
1085
|
+
'You do not belong to any organizations.\n' +
|
|
1086
|
+
'Please contact support or create an organization at https://agentuity.com'
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
if (orgs.length === 1) {
|
|
1091
|
+
return orgs[0].id;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
const response = await enquirer.prompt<{ action: string }>({
|
|
1095
|
+
type: 'select',
|
|
1096
|
+
name: 'action',
|
|
1097
|
+
message: 'Select an organization',
|
|
1098
|
+
initial,
|
|
1099
|
+
choices: orgs.map((o) => ({ message: o.name, name: o.id })),
|
|
1100
|
+
});
|
|
1101
|
+
|
|
1102
|
+
return response.action;
|
|
1103
|
+
}
|