@agentuity/cli 0.0.42 → 0.0.44
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 +1 -1
- package/README.md +1 -1
- package/bin/cli.ts +7 -5
- package/dist/api.d.ts +3 -3
- package/dist/api.d.ts.map +1 -1
- package/dist/auth.d.ts +10 -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 +4 -4
- package/dist/cmd/auth/api.d.ts.map +1 -1
- package/dist/cmd/auth/index.d.ts.map +1 -1
- package/dist/cmd/auth/login.d.ts.map +1 -1
- package/dist/cmd/auth/signup.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/add.d.ts +2 -0
- package/dist/cmd/auth/ssh/add.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/api.d.ts +16 -0
- package/dist/cmd/auth/ssh/api.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/delete.d.ts +2 -0
- package/dist/cmd/auth/ssh/delete.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/index.d.ts +3 -0
- package/dist/cmd/auth/ssh/index.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/list.d.ts +2 -0
- package/dist/cmd/auth/ssh/list.d.ts.map +1 -0
- package/dist/cmd/auth/whoami.d.ts +2 -0
- package/dist/cmd/auth/whoami.d.ts.map +1 -0
- package/dist/cmd/bundle/ast.d.ts +14 -3
- package/dist/cmd/bundle/ast.d.ts.map +1 -1
- package/dist/cmd/bundle/ast.test.d.ts +2 -0
- package/dist/cmd/bundle/ast.test.d.ts.map +1 -0
- package/dist/cmd/bundle/bundler.d.ts +6 -1
- package/dist/cmd/bundle/bundler.d.ts.map +1 -1
- package/dist/cmd/bundle/file.d.ts.map +1 -1
- package/dist/cmd/bundle/fix-duplicate-exports.d.ts +2 -0
- package/dist/cmd/bundle/fix-duplicate-exports.d.ts.map +1 -0
- package/dist/cmd/bundle/fix-duplicate-exports.test.d.ts +2 -0
- package/dist/cmd/bundle/fix-duplicate-exports.test.d.ts.map +1 -0
- package/dist/cmd/bundle/index.d.ts +1 -1
- package/dist/cmd/bundle/index.d.ts.map +1 -1
- package/dist/cmd/bundle/plugin.d.ts +2 -0
- package/dist/cmd/bundle/plugin.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -0
- package/dist/cmd/cloud/domain.d.ts +17 -0
- package/dist/cmd/cloud/domain.d.ts.map +1 -0
- package/dist/cmd/cloud/index.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/add.d.ts +2 -0
- package/dist/cmd/cloud/resource/add.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/delete.d.ts +2 -0
- package/dist/cmd/cloud/resource/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/index.d.ts +3 -0
- package/dist/cmd/cloud/resource/index.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/list.d.ts +2 -0
- package/dist/cmd/cloud/resource/list.d.ts.map +1 -0
- package/dist/cmd/cloud/scp/download.d.ts +2 -0
- package/dist/cmd/cloud/scp/download.d.ts.map +1 -0
- package/dist/cmd/cloud/scp/index.d.ts +3 -0
- package/dist/cmd/cloud/scp/index.d.ts.map +1 -0
- package/dist/cmd/cloud/scp/upload.d.ts +2 -0
- package/dist/cmd/cloud/scp/upload.d.ts.map +1 -0
- package/dist/cmd/cloud/ssh.d.ts +2 -0
- package/dist/cmd/cloud/ssh.d.ts.map +1 -0
- package/dist/cmd/dev/api.d.ts +18 -0
- package/dist/cmd/dev/api.d.ts.map +1 -0
- package/dist/cmd/dev/download.d.ts +11 -0
- package/dist/cmd/dev/download.d.ts.map +1 -0
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/templates.d.ts +3 -0
- package/dist/cmd/dev/templates.d.ts.map +1 -0
- package/dist/cmd/env/delete.d.ts +2 -0
- package/dist/cmd/env/delete.d.ts.map +1 -0
- package/dist/cmd/env/get.d.ts +2 -0
- package/dist/cmd/env/get.d.ts.map +1 -0
- package/dist/cmd/env/import.d.ts +2 -0
- package/dist/cmd/env/import.d.ts.map +1 -0
- package/dist/cmd/env/index.d.ts +2 -0
- package/dist/cmd/env/index.d.ts.map +1 -0
- package/dist/cmd/env/list.d.ts.map +1 -0
- package/dist/cmd/env/pull.d.ts +2 -0
- package/dist/cmd/env/pull.d.ts.map +1 -0
- package/dist/cmd/env/push.d.ts +2 -0
- package/dist/cmd/env/push.d.ts.map +1 -0
- package/dist/cmd/env/set.d.ts +2 -0
- package/dist/cmd/env/set.d.ts.map +1 -0
- package/dist/cmd/profile/show.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 +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 +5 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/secret/delete.d.ts +2 -0
- package/dist/cmd/secret/delete.d.ts.map +1 -0
- package/dist/cmd/secret/get.d.ts +2 -0
- package/dist/cmd/secret/get.d.ts.map +1 -0
- package/dist/cmd/secret/import.d.ts +2 -0
- package/dist/cmd/secret/import.d.ts.map +1 -0
- package/dist/cmd/secret/index.d.ts +2 -0
- package/dist/cmd/secret/index.d.ts.map +1 -0
- package/dist/cmd/secret/list.d.ts +2 -0
- package/dist/cmd/secret/list.d.ts.map +1 -0
- package/dist/cmd/secret/pull.d.ts +2 -0
- package/dist/cmd/secret/pull.d.ts.map +1 -0
- package/dist/cmd/secret/push.d.ts +2 -0
- package/dist/cmd/secret/push.d.ts.map +1 -0
- package/dist/cmd/secret/set.d.ts +2 -0
- package/dist/cmd/secret/set.d.ts.map +1 -0
- package/dist/cmd/version/index.d.ts.map +1 -1
- package/dist/config.d.ts +11 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/crypto/box.d.ts +65 -0
- package/dist/crypto/box.d.ts.map +1 -0
- package/dist/crypto/box.test.d.ts +2 -0
- package/dist/crypto/box.test.d.ts.map +1 -0
- package/dist/download.d.ts.map +1 -1
- package/dist/env-util.d.ts +67 -0
- package/dist/env-util.d.ts.map +1 -0
- package/dist/env-util.test.d.ts +2 -0
- package/dist/env-util.test.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/schema-parser.d.ts.map +1 -1
- package/dist/steps.d.ts +4 -1
- package/dist/steps.d.ts.map +1 -1
- package/dist/terminal.d.ts.map +1 -1
- package/dist/tui.d.ts +32 -2
- package/dist/tui.d.ts.map +1 -1
- package/dist/types.d.ts +250 -127
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/detectSubagent.d.ts +15 -0
- package/dist/utils/detectSubagent.d.ts.map +1 -0
- package/dist/utils/zip.d.ts +7 -0
- package/dist/utils/zip.d.ts.map +1 -0
- package/package.json +11 -3
- package/src/api-errors.md +2 -2
- package/src/api.ts +12 -7
- package/src/auth.ts +116 -7
- package/src/banner.ts +13 -6
- package/src/cli.ts +709 -36
- package/src/cmd/auth/api.ts +10 -16
- package/src/cmd/auth/index.ts +3 -1
- package/src/cmd/auth/login.ts +24 -8
- package/src/cmd/auth/signup.ts +15 -11
- package/src/cmd/auth/ssh/add.ts +263 -0
- package/src/cmd/auth/ssh/api.ts +94 -0
- package/src/cmd/auth/ssh/delete.ts +102 -0
- package/src/cmd/auth/ssh/index.ts +10 -0
- package/src/cmd/auth/ssh/list.ts +74 -0
- package/src/cmd/auth/whoami.ts +69 -0
- package/src/cmd/bundle/ast.test.ts +565 -0
- package/src/cmd/bundle/ast.ts +457 -44
- package/src/cmd/bundle/bundler.ts +255 -57
- package/src/cmd/bundle/file.ts +6 -12
- package/src/cmd/bundle/fix-duplicate-exports.test.ts +387 -0
- package/src/cmd/bundle/fix-duplicate-exports.ts +204 -0
- package/src/cmd/bundle/index.ts +11 -11
- package/src/cmd/bundle/patch/aisdk.ts +1 -1
- package/src/cmd/bundle/plugin.ts +373 -53
- package/src/cmd/cloud/deploy.ts +336 -0
- package/src/cmd/cloud/domain.ts +92 -0
- package/src/cmd/cloud/index.ts +11 -0
- package/src/cmd/cloud/resource/add.ts +56 -0
- package/src/cmd/cloud/resource/delete.ts +120 -0
- package/src/cmd/cloud/resource/index.ts +11 -0
- package/src/cmd/cloud/resource/list.ts +69 -0
- package/src/cmd/cloud/scp/download.ts +59 -0
- package/src/cmd/cloud/scp/index.ts +9 -0
- package/src/cmd/cloud/scp/upload.ts +62 -0
- package/src/cmd/cloud/ssh.ts +68 -0
- package/src/cmd/dev/api.ts +46 -0
- package/src/cmd/dev/download.ts +111 -0
- package/src/cmd/dev/index.ts +362 -34
- package/src/cmd/dev/templates.ts +84 -0
- package/src/cmd/env/delete.ts +47 -0
- package/src/cmd/env/get.ts +53 -0
- package/src/cmd/env/import.ts +102 -0
- package/src/cmd/env/index.ts +22 -0
- package/src/cmd/env/list.ts +56 -0
- package/src/cmd/env/pull.ts +80 -0
- package/src/cmd/env/push.ts +37 -0
- package/src/cmd/env/set.ts +71 -0
- package/src/cmd/index.ts +2 -2
- package/src/cmd/profile/show.ts +15 -6
- package/src/cmd/project/create.ts +7 -2
- package/src/cmd/project/delete.ts +75 -18
- package/src/cmd/project/download.ts +3 -3
- package/src/cmd/project/list.ts +8 -8
- package/src/cmd/project/show.ts +3 -7
- package/src/cmd/project/template-flow.ts +186 -48
- package/src/cmd/secret/delete.ts +40 -0
- package/src/cmd/secret/get.ts +54 -0
- package/src/cmd/secret/import.ts +64 -0
- package/src/cmd/secret/index.ts +22 -0
- package/src/cmd/secret/list.ts +56 -0
- package/src/cmd/secret/pull.ts +78 -0
- package/src/cmd/secret/push.ts +37 -0
- package/src/cmd/secret/set.ts +45 -0
- package/src/cmd/version/index.ts +2 -1
- package/src/config.ts +257 -27
- package/src/crypto/box.test.ts +431 -0
- package/src/crypto/box.ts +477 -0
- package/src/download.ts +1 -0
- package/src/env-util.test.ts +194 -0
- package/src/env-util.ts +290 -0
- package/src/index.ts +5 -1
- package/src/schema-parser.ts +2 -3
- package/src/steps.ts +144 -10
- package/src/terminal.ts +24 -23
- package/src/tui.ts +208 -68
- package/src/types.ts +292 -202
- package/src/utils/detectSubagent.ts +31 -0
- package/src/utils/zip.ts +38 -0
- package/dist/cmd/example/create-user.d.ts +0 -2
- package/dist/cmd/example/create-user.d.ts.map +0 -1
- package/dist/cmd/example/create.d.ts +0 -2
- package/dist/cmd/example/create.d.ts.map +0 -1
- package/dist/cmd/example/deploy.d.ts.map +0 -1
- package/dist/cmd/example/index.d.ts.map +0 -1
- package/dist/cmd/example/list.d.ts.map +0 -1
- package/dist/cmd/example/optional-auth.d.ts +0 -3
- package/dist/cmd/example/optional-auth.d.ts.map +0 -1
- package/dist/cmd/example/run-command.d.ts +0 -2
- package/dist/cmd/example/run-command.d.ts.map +0 -1
- package/dist/cmd/example/sound.d.ts +0 -3
- package/dist/cmd/example/sound.d.ts.map +0 -1
- package/dist/cmd/example/spinner.d.ts +0 -2
- package/dist/cmd/example/spinner.d.ts.map +0 -1
- package/dist/cmd/example/steps.d.ts +0 -2
- package/dist/cmd/example/steps.d.ts.map +0 -1
- package/dist/cmd/example/version.d.ts +0 -2
- package/dist/cmd/example/version.d.ts.map +0 -1
- package/dist/logger.d.ts +0 -24
- package/dist/logger.d.ts.map +0 -1
- package/src/cmd/example/create-user.ts +0 -38
- package/src/cmd/example/create.ts +0 -31
- package/src/cmd/example/deploy.ts +0 -36
- package/src/cmd/example/index.ts +0 -29
- package/src/cmd/example/list.ts +0 -32
- package/src/cmd/example/optional-auth.ts +0 -38
- package/src/cmd/example/run-command.ts +0 -45
- package/src/cmd/example/sound.ts +0 -14
- package/src/cmd/example/spinner.ts +0 -44
- package/src/cmd/example/steps.ts +0 -66
- package/src/cmd/example/version.ts +0 -13
- package/src/logger.ts +0 -235
- /package/dist/cmd/{example → cloud}/deploy.d.ts +0 -0
- /package/dist/cmd/{example → cloud}/index.d.ts +0 -0
- /package/dist/cmd/{example → env}/list.d.ts +0 -0
package/src/tui.ts
CHANGED
|
@@ -4,9 +4,12 @@
|
|
|
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
|
+
import { stringWidth } from 'bun';
|
|
7
8
|
import enquirer from 'enquirer';
|
|
8
|
-
import type
|
|
9
|
+
import { type OrganizationList, projectList } from '@agentuity/server';
|
|
9
10
|
import type { ColorScheme } from './terminal';
|
|
11
|
+
import { type APIClient as APIClientType } from './api';
|
|
12
|
+
import * as readline from 'readline';
|
|
10
13
|
|
|
11
14
|
// Icons
|
|
12
15
|
const ICONS = {
|
|
@@ -18,8 +21,13 @@ const ICONS = {
|
|
|
18
21
|
bullet: '•',
|
|
19
22
|
} as const;
|
|
20
23
|
|
|
21
|
-
function shouldUseColors(): boolean {
|
|
22
|
-
return
|
|
24
|
+
export function shouldUseColors(): boolean {
|
|
25
|
+
return (
|
|
26
|
+
!process.env.NO_COLOR &&
|
|
27
|
+
!process.env.CI &&
|
|
28
|
+
process.env.TERM !== 'dumb' &&
|
|
29
|
+
!!process.stdout.isTTY
|
|
30
|
+
);
|
|
23
31
|
}
|
|
24
32
|
|
|
25
33
|
// Color definitions (light/dark adaptive) using Bun.color
|
|
@@ -71,10 +79,15 @@ function getColors() {
|
|
|
71
79
|
} as const;
|
|
72
80
|
}
|
|
73
81
|
|
|
74
|
-
let currentColorScheme: ColorScheme = 'dark';
|
|
82
|
+
let currentColorScheme: ColorScheme = process.env.CI ? 'light' : 'dark';
|
|
75
83
|
|
|
76
84
|
export function setColorScheme(scheme: ColorScheme): void {
|
|
77
85
|
currentColorScheme = scheme;
|
|
86
|
+
process.env.COLOR_SCHEME = scheme;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function isDarkMode(): boolean {
|
|
90
|
+
return currentColorScheme === 'dark';
|
|
78
91
|
}
|
|
79
92
|
|
|
80
93
|
function getColor(colorKey: keyof ReturnType<typeof getColors>): string {
|
|
@@ -141,6 +154,15 @@ export function muted(text: string): string {
|
|
|
141
154
|
return `${color}${text}${reset}`;
|
|
142
155
|
}
|
|
143
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Format text in warn color
|
|
159
|
+
*/
|
|
160
|
+
export function warn(text: string): string {
|
|
161
|
+
const color = getColor('warning');
|
|
162
|
+
const reset = getColor('reset');
|
|
163
|
+
return `${color}${text}${reset}`;
|
|
164
|
+
}
|
|
165
|
+
|
|
144
166
|
/**
|
|
145
167
|
* Format text in bold
|
|
146
168
|
*/
|
|
@@ -153,13 +175,13 @@ export function bold(text: string): string {
|
|
|
153
175
|
/**
|
|
154
176
|
* Format text as a link (blue and underlined)
|
|
155
177
|
*/
|
|
156
|
-
export function link(url: string): string {
|
|
178
|
+
export function link(url: string, title?: string): string {
|
|
157
179
|
const color = getColor('link');
|
|
158
180
|
const reset = getColor('reset');
|
|
159
181
|
|
|
160
|
-
// Check if terminal supports hyperlinks (OSC 8)
|
|
161
|
-
if (supportsHyperlinks()) {
|
|
162
|
-
return `\x1b]8;;${url}\x07${color}${url}${reset}\x1b]8;;\x07`;
|
|
182
|
+
// Check if terminal supports hyperlinks (OSC 8) and colors are enabled
|
|
183
|
+
if (shouldUseColors() && supportsHyperlinks()) {
|
|
184
|
+
return `\x1b]8;;${url}\x07${color}${title ?? url}${reset}\x1b]8;;\x07`;
|
|
163
185
|
}
|
|
164
186
|
|
|
165
187
|
return `${color}${url}${reset}`;
|
|
@@ -207,24 +229,40 @@ export function newline(): void {
|
|
|
207
229
|
console.log('');
|
|
208
230
|
}
|
|
209
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Get the display width of a string, handling ANSI codes and OSC 8 hyperlinks
|
|
234
|
+
*
|
|
235
|
+
* Note: Bun.stringWidth() counts OSC 8 hyperlink escape sequences in the width,
|
|
236
|
+
* which causes incorrect alignment. We strip OSC 8 codes first, then use Bun.stringWidth()
|
|
237
|
+
* to handle regular ANSI codes and unicode characters correctly.
|
|
238
|
+
*/
|
|
239
|
+
function getDisplayWidth(str: string): number {
|
|
240
|
+
// Remove OSC-8 hyperlink sequences using Unicode escapes (\u001b = ESC, \u0007 = BEL) to satisfy linter
|
|
241
|
+
// eslint-disable-next-line no-control-regex
|
|
242
|
+
const withoutOSC8 = str.replace(/\u001b\]8;;[^\u0007]*\u0007/g, '');
|
|
243
|
+
return Bun.stringWidth(withoutOSC8);
|
|
244
|
+
}
|
|
245
|
+
|
|
210
246
|
/**
|
|
211
247
|
* Pad a string to a specific length on the right
|
|
212
248
|
*/
|
|
213
249
|
export function padRight(str: string, length: number, pad = ' '): string {
|
|
214
|
-
|
|
250
|
+
const displayWidth = getDisplayWidth(str);
|
|
251
|
+
if (displayWidth >= length) {
|
|
215
252
|
return str;
|
|
216
253
|
}
|
|
217
|
-
return str + pad.repeat(length -
|
|
254
|
+
return str + pad.repeat(length - displayWidth);
|
|
218
255
|
}
|
|
219
256
|
|
|
220
257
|
/**
|
|
221
258
|
* Pad a string to a specific length on the left
|
|
222
259
|
*/
|
|
223
260
|
export function padLeft(str: string, length: number, pad = ' '): string {
|
|
224
|
-
|
|
261
|
+
const displayWidth = getDisplayWidth(str);
|
|
262
|
+
if (displayWidth >= length) {
|
|
225
263
|
return str;
|
|
226
264
|
}
|
|
227
|
-
return pad.repeat(length -
|
|
265
|
+
return pad.repeat(length - displayWidth) + str;
|
|
228
266
|
}
|
|
229
267
|
|
|
230
268
|
interface BannerOptions {
|
|
@@ -244,11 +282,8 @@ interface BannerOptions {
|
|
|
244
282
|
* Responsive to terminal width - adapts to narrow terminals
|
|
245
283
|
*/
|
|
246
284
|
export function banner(title: string, body: string, options?: BannerOptions): void {
|
|
247
|
-
// Get terminal width, default to
|
|
248
|
-
const termWidth = process.stdout.columns ||
|
|
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;
|
|
285
|
+
// Get terminal width, default to 120 if not available
|
|
286
|
+
const termWidth = process.stdout.columns || 120;
|
|
252
287
|
|
|
253
288
|
const border = {
|
|
254
289
|
topLeft: '╭',
|
|
@@ -259,15 +294,27 @@ export function banner(title: string, body: string, options?: BannerOptions): vo
|
|
|
259
294
|
vertical: '│',
|
|
260
295
|
};
|
|
261
296
|
|
|
262
|
-
//
|
|
263
|
-
const bodyLines = wrapText(body, maxWidth - padding); // -4 for padding and borders
|
|
264
|
-
|
|
265
|
-
// Calculate width based on content
|
|
297
|
+
// Calculate content width first (before wrapping)
|
|
266
298
|
const titleWidth = getDisplayWidth(title);
|
|
267
|
-
const
|
|
268
|
-
const
|
|
269
|
-
const
|
|
270
|
-
|
|
299
|
+
const bodyLines = body.split('\n');
|
|
300
|
+
const maxBodyWidth = Math.max(0, ...bodyLines.map((line) => getDisplayWidth(line)));
|
|
301
|
+
const requiredContentWidth = Math.max(titleWidth, maxBodyWidth);
|
|
302
|
+
|
|
303
|
+
// Box width = content + borders (2) + side spaces (2)
|
|
304
|
+
const boxWidth = Math.min(requiredContentWidth + 4, termWidth);
|
|
305
|
+
|
|
306
|
+
// If required content width exceeds terminal width, skip box and print plain text
|
|
307
|
+
if (requiredContentWidth + 4 > termWidth) {
|
|
308
|
+
console.log('\n' + bold(title));
|
|
309
|
+
console.log(body + '\n');
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Inner width is box width minus borders (2) and side spaces (2)
|
|
314
|
+
const innerWidth = boxWidth - 4;
|
|
315
|
+
|
|
316
|
+
// Wrap text to fit box width
|
|
317
|
+
const wrappedBodyLines = wrapText(body, innerWidth);
|
|
271
318
|
|
|
272
319
|
// Colors
|
|
273
320
|
const borderColor = getColor('muted');
|
|
@@ -293,10 +340,7 @@ export function banner(title: string, body: string, options?: BannerOptions): vo
|
|
|
293
340
|
const titleDisplayWidth = getDisplayWidth(title);
|
|
294
341
|
if (options?.centerTitle === true || options?.centerTitle === undefined) {
|
|
295
342
|
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
|
-
);
|
|
343
|
+
const titleRightPadding = Math.max(0, innerWidth - titlePadding - titleDisplayWidth);
|
|
300
344
|
const titleLine =
|
|
301
345
|
' '.repeat(titlePadding) +
|
|
302
346
|
`${titleColor}${bold(title)}${reset}` +
|
|
@@ -305,7 +349,7 @@ export function banner(title: string, body: string, options?: BannerOptions): vo
|
|
|
305
349
|
`${borderColor}${border.vertical} ${reset}${titleLine}${borderColor} ${border.vertical}${reset}`
|
|
306
350
|
);
|
|
307
351
|
} else {
|
|
308
|
-
const titleRightPadding = Math.max(0,
|
|
352
|
+
const titleRightPadding = Math.max(0, innerWidth - titleDisplayWidth);
|
|
309
353
|
const titleLine = `${titleColor}${bold(title)}${reset}` + ' '.repeat(titleRightPadding);
|
|
310
354
|
lines.push(
|
|
311
355
|
`${borderColor}${border.vertical} ${reset}${titleLine}${borderColor} ${border.vertical}${reset}`
|
|
@@ -320,9 +364,9 @@ export function banner(title: string, body: string, options?: BannerOptions): vo
|
|
|
320
364
|
}
|
|
321
365
|
|
|
322
366
|
// Body lines
|
|
323
|
-
for (const line of
|
|
367
|
+
for (const line of wrappedBodyLines) {
|
|
324
368
|
const lineWidth = getDisplayWidth(line);
|
|
325
|
-
const linePadding = Math.max(0,
|
|
369
|
+
const linePadding = Math.max(0, innerWidth - lineWidth);
|
|
326
370
|
lines.push(
|
|
327
371
|
`${borderColor}${border.vertical} ${reset}${line}${' '.repeat(linePadding)}${borderColor} ${border.vertical}${reset}`
|
|
328
372
|
);
|
|
@@ -464,7 +508,7 @@ export function showSignupBenefits(): void {
|
|
|
464
508
|
];
|
|
465
509
|
|
|
466
510
|
console.log('');
|
|
467
|
-
lines.
|
|
511
|
+
lines.map((line) => console.log(CYAN + line + RESET));
|
|
468
512
|
console.log('');
|
|
469
513
|
}
|
|
470
514
|
|
|
@@ -472,24 +516,32 @@ export function showSignupBenefits(): void {
|
|
|
472
516
|
* Display a message when unauthenticated to let the user know certain capabilities are disabled
|
|
473
517
|
*/
|
|
474
518
|
export function showLoggedOutMessage(): void {
|
|
475
|
-
const
|
|
519
|
+
const YELLOW = Bun.color('yellow', 'ansi-16m');
|
|
476
520
|
const TEXT =
|
|
477
521
|
currentColorScheme === 'dark' ? Bun.color('white', 'ansi') : Bun.color('black', 'ansi');
|
|
478
522
|
const RESET = '\x1b[0m';
|
|
479
523
|
|
|
524
|
+
const signupTitle = 'Sign up / Login';
|
|
525
|
+
const showInline = supportsHyperlinks();
|
|
526
|
+
const signupURL = 'https://app.agentuity.com/sign-up';
|
|
527
|
+
const signupLink = showInline
|
|
528
|
+
? link(signupURL, signupTitle)
|
|
529
|
+
: ' '.repeat(stringWidth(signupTitle));
|
|
530
|
+
const showNewLine = showInline ? '' : `║ ${RESET}${link(signupURL)}${YELLOW} ║`;
|
|
531
|
+
|
|
480
532
|
const lines = [
|
|
481
533
|
'╔══════════════════════════════════════════════╗',
|
|
482
534
|
`║ ⨺ Unauthenticated (local mode) ║`,
|
|
483
535
|
'║ ║',
|
|
484
|
-
`║ ${TEXT}Certain capabilities such as the AI services${
|
|
485
|
-
`║ ${TEXT}and devmode remote are unavailable when${
|
|
486
|
-
`║ ${TEXT}unauthenticated.${
|
|
536
|
+
`║ ${TEXT}Certain capabilities such as the AI services${YELLOW} ║`,
|
|
537
|
+
`║ ${TEXT}and devmode remote are unavailable when${YELLOW} ║`,
|
|
538
|
+
`║ ${TEXT}unauthenticated.${YELLOW} ${signupLink}${YELLOW} ║`,
|
|
539
|
+
showNewLine,
|
|
487
540
|
'╚══════════════════════════════════════════════╝',
|
|
488
541
|
];
|
|
489
542
|
|
|
490
543
|
console.log('');
|
|
491
|
-
lines.
|
|
492
|
-
console.log('');
|
|
544
|
+
lines.filter(Boolean).map((line) => console.log(YELLOW + line + RESET));
|
|
493
545
|
}
|
|
494
546
|
|
|
495
547
|
/**
|
|
@@ -544,20 +596,6 @@ export async function copyToClipboard(text: string): Promise<boolean> {
|
|
|
544
596
|
}
|
|
545
597
|
}
|
|
546
598
|
|
|
547
|
-
/**
|
|
548
|
-
* Get the display width of a string, handling ANSI codes and OSC 8 hyperlinks
|
|
549
|
-
*
|
|
550
|
-
* Note: Bun.stringWidth() counts OSC 8 hyperlink escape sequences in the width,
|
|
551
|
-
* which causes incorrect alignment. We strip OSC 8 codes first, then use Bun.stringWidth()
|
|
552
|
-
* to handle regular ANSI codes and unicode characters correctly.
|
|
553
|
-
*/
|
|
554
|
-
function getDisplayWidth(str: string): number {
|
|
555
|
-
// Strip OSC 8 hyperlink sequences: \x1b]8;;URL\x07...\x1b]8;;\x07
|
|
556
|
-
// eslint-disable-next-line no-control-regex
|
|
557
|
-
const withoutOSC8 = str.replace(/\x1b\]8;;[^\x07]*\x07/g, '');
|
|
558
|
-
return Bun.stringWidth(withoutOSC8);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
599
|
/**
|
|
562
600
|
* Extract ANSI codes from the beginning of a string
|
|
563
601
|
*/
|
|
@@ -667,6 +705,11 @@ export interface SimpleSpinnerOptions<T> {
|
|
|
667
705
|
type?: 'simple';
|
|
668
706
|
message: string;
|
|
669
707
|
callback: (() => Promise<T>) | Promise<T>;
|
|
708
|
+
/**
|
|
709
|
+
* If true, clear the spinner output on success (no icon, no message)
|
|
710
|
+
* Defaults to false
|
|
711
|
+
*/
|
|
712
|
+
clearOnSuccess?: boolean;
|
|
670
713
|
}
|
|
671
714
|
|
|
672
715
|
/**
|
|
@@ -676,6 +719,11 @@ export interface ProgressSpinnerOptions<T> {
|
|
|
676
719
|
type: 'progress';
|
|
677
720
|
message: string;
|
|
678
721
|
callback: (progress: SpinnerProgressCallback) => Promise<T>;
|
|
722
|
+
/**
|
|
723
|
+
* If true, clear the spinner output on success (no icon, no message)
|
|
724
|
+
* Defaults to false
|
|
725
|
+
*/
|
|
726
|
+
clearOnSuccess?: boolean;
|
|
679
727
|
}
|
|
680
728
|
|
|
681
729
|
/**
|
|
@@ -726,7 +774,7 @@ export async function spinner<T>(
|
|
|
726
774
|
const reset = getColor('reset');
|
|
727
775
|
|
|
728
776
|
// If no TTY, just execute the callback without animation
|
|
729
|
-
if (!process.
|
|
777
|
+
if (!process.stderr.isTTY) {
|
|
730
778
|
try {
|
|
731
779
|
const result =
|
|
732
780
|
options.type === 'progress'
|
|
@@ -735,6 +783,12 @@ export async function spinner<T>(
|
|
|
735
783
|
? await options.callback()
|
|
736
784
|
: await options.callback;
|
|
737
785
|
|
|
786
|
+
// If clearOnSuccess is true, don't show success message
|
|
787
|
+
if (!options.clearOnSuccess) {
|
|
788
|
+
const successColor = getColor('success');
|
|
789
|
+
console.error(`${successColor}${ICONS.success} ${message}${reset}`);
|
|
790
|
+
}
|
|
791
|
+
|
|
738
792
|
return result;
|
|
739
793
|
} catch (err) {
|
|
740
794
|
const errorColor = getColor('error');
|
|
@@ -757,7 +811,7 @@ export async function spinner<T>(
|
|
|
757
811
|
let currentProgress: number | undefined;
|
|
758
812
|
|
|
759
813
|
// Hide cursor
|
|
760
|
-
process.
|
|
814
|
+
process.stderr.write('\x1B[?25l');
|
|
761
815
|
|
|
762
816
|
// Start animation
|
|
763
817
|
const interval = setInterval(() => {
|
|
@@ -772,7 +826,7 @@ export async function spinner<T>(
|
|
|
772
826
|
: '';
|
|
773
827
|
|
|
774
828
|
// Clear line and render
|
|
775
|
-
process.
|
|
829
|
+
process.stderr.write('\r\x1B[K' + `${frame} ${message}${progressIndicator}`);
|
|
776
830
|
frameIndex++;
|
|
777
831
|
}, 120);
|
|
778
832
|
|
|
@@ -792,27 +846,30 @@ export async function spinner<T>(
|
|
|
792
846
|
|
|
793
847
|
// Clear interval and line
|
|
794
848
|
clearInterval(interval);
|
|
795
|
-
process.
|
|
849
|
+
process.stderr.write('\r\x1B[K');
|
|
796
850
|
|
|
797
|
-
//
|
|
798
|
-
|
|
799
|
-
|
|
851
|
+
// If clearOnSuccess is false, show success message
|
|
852
|
+
if (!options.clearOnSuccess) {
|
|
853
|
+
// Show success
|
|
854
|
+
const successColor = getColor('success');
|
|
855
|
+
console.error(`${successColor}${ICONS.success} ${message}${reset}`);
|
|
856
|
+
}
|
|
800
857
|
|
|
801
858
|
// Show cursor
|
|
802
|
-
process.
|
|
859
|
+
process.stderr.write('\x1B[?25h');
|
|
803
860
|
|
|
804
861
|
return result;
|
|
805
862
|
} catch (err) {
|
|
806
863
|
// Clear interval and line
|
|
807
864
|
clearInterval(interval);
|
|
808
|
-
process.
|
|
865
|
+
process.stderr.write('\r\x1B[K');
|
|
809
866
|
|
|
810
867
|
// Show error
|
|
811
868
|
const errorColor = getColor('error');
|
|
812
869
|
console.error(`${errorColor}${ICONS.error} ${message}${reset}`);
|
|
813
870
|
|
|
814
871
|
// Show cursor
|
|
815
|
-
process.
|
|
872
|
+
process.stderr.write('\x1B[?25h');
|
|
816
873
|
|
|
817
874
|
throw err;
|
|
818
875
|
}
|
|
@@ -847,12 +904,10 @@ export interface CommandRunnerOptions {
|
|
|
847
904
|
* If true or undefined, will truncate each line of output
|
|
848
905
|
*/
|
|
849
906
|
truncate?: boolean;
|
|
850
|
-
|
|
851
907
|
/**
|
|
852
908
|
* If undefined, will show up to 3 last lines of output while running. Customize the number with this property.
|
|
853
909
|
*/
|
|
854
910
|
maxLinesOutput?: number;
|
|
855
|
-
|
|
856
911
|
/**
|
|
857
912
|
* If undefined, will show up to 10 last lines on failure. Customize the number with this property.
|
|
858
913
|
*/
|
|
@@ -1076,6 +1131,33 @@ export async function runCommand(options: CommandRunnerOptions): Promise<number>
|
|
|
1076
1131
|
}
|
|
1077
1132
|
}
|
|
1078
1133
|
|
|
1134
|
+
/**
|
|
1135
|
+
* Prompt user for text input
|
|
1136
|
+
* Returns the input string
|
|
1137
|
+
*/
|
|
1138
|
+
export async function prompt(message: string): Promise<string> {
|
|
1139
|
+
process.stdout.write(message);
|
|
1140
|
+
|
|
1141
|
+
// Check if we're in a TTY environment
|
|
1142
|
+
if (!process.stdin.isTTY) {
|
|
1143
|
+
console.log('');
|
|
1144
|
+
return '';
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
// Use readline for full line input
|
|
1148
|
+
const rl = readline.createInterface({
|
|
1149
|
+
input: process.stdin,
|
|
1150
|
+
output: process.stdout,
|
|
1151
|
+
});
|
|
1152
|
+
|
|
1153
|
+
return new Promise((resolve) => {
|
|
1154
|
+
rl.question('', (answer: string) => {
|
|
1155
|
+
rl.close();
|
|
1156
|
+
resolve(answer);
|
|
1157
|
+
});
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1079
1161
|
export async function selectOrganization(
|
|
1080
1162
|
orgs: OrganizationList,
|
|
1081
1163
|
initial?: string
|
|
@@ -1087,17 +1169,75 @@ export async function selectOrganization(
|
|
|
1087
1169
|
);
|
|
1088
1170
|
}
|
|
1089
1171
|
|
|
1090
|
-
if (
|
|
1091
|
-
|
|
1172
|
+
if (process.env.AGENTUITY_CLOUD_ORG_ID) {
|
|
1173
|
+
const org = orgs.find((o) => o.id === process.env.AGENTUITY_CLOUD_ORG_ID);
|
|
1174
|
+
if (org) {
|
|
1175
|
+
return org.id;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
if (!process.stdin.isTTY) {
|
|
1180
|
+
if (orgs.length === 1) {
|
|
1181
|
+
return orgs[0].id;
|
|
1182
|
+
}
|
|
1183
|
+
if (initial) {
|
|
1184
|
+
return initial;
|
|
1185
|
+
}
|
|
1186
|
+
fatal(
|
|
1187
|
+
'Organization selection required but cannot prompt in non-interactive environment. Set AGENTUITY_CLOUD_ORG_ID or provide a default organization using --org-id'
|
|
1188
|
+
);
|
|
1092
1189
|
}
|
|
1093
1190
|
|
|
1094
1191
|
const response = await enquirer.prompt<{ action: string }>({
|
|
1095
1192
|
type: 'select',
|
|
1096
1193
|
name: 'action',
|
|
1097
1194
|
message: 'Select an organization',
|
|
1098
|
-
initial,
|
|
1195
|
+
initial: initial || (orgs.length === 1 ? orgs[0].id : undefined),
|
|
1099
1196
|
choices: orgs.map((o) => ({ message: o.name, name: o.id })),
|
|
1100
1197
|
});
|
|
1101
1198
|
|
|
1102
1199
|
return response.action;
|
|
1103
1200
|
}
|
|
1201
|
+
|
|
1202
|
+
/**
|
|
1203
|
+
* show a project list picker
|
|
1204
|
+
*
|
|
1205
|
+
* @param apiClient
|
|
1206
|
+
* @param showDeployment
|
|
1207
|
+
* @returns
|
|
1208
|
+
*/
|
|
1209
|
+
export async function showProjectList(
|
|
1210
|
+
apiClient: APIClientType,
|
|
1211
|
+
showDeploymentId = false
|
|
1212
|
+
): Promise<string> {
|
|
1213
|
+
const projects = await spinner({
|
|
1214
|
+
message: 'Fetching projects',
|
|
1215
|
+
clearOnSuccess: true,
|
|
1216
|
+
callback: () => {
|
|
1217
|
+
return projectList(apiClient, showDeploymentId);
|
|
1218
|
+
},
|
|
1219
|
+
});
|
|
1220
|
+
|
|
1221
|
+
if (projects.length === 0) {
|
|
1222
|
+
return '';
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// TODO: might want to sort by the last org_id we used
|
|
1226
|
+
if (projects) {
|
|
1227
|
+
projects.sort((a, b) => {
|
|
1228
|
+
return a.name.localeCompare(b.name);
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
const response = await enquirer.prompt<{ id: string }>({
|
|
1233
|
+
type: 'select',
|
|
1234
|
+
name: 'id',
|
|
1235
|
+
message: 'Select a project:',
|
|
1236
|
+
choices: projects.map((p) => ({
|
|
1237
|
+
name: p.id,
|
|
1238
|
+
message: `${p.name.padEnd(25, ' ')} ${muted(p.id)} ${showDeploymentId ? muted(p.latestDeploymentId ?? 'no deployment') : ''}`,
|
|
1239
|
+
})),
|
|
1240
|
+
});
|
|
1241
|
+
|
|
1242
|
+
return response.id;
|
|
1243
|
+
}
|