@vertaaux/cli 0.3.3 → 0.5.0

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.
Files changed (227) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/MIGRATION.md +239 -0
  3. package/README.md +34 -16
  4. package/dist/app/interactive-app.d.ts +101 -0
  5. package/dist/app/interactive-app.d.ts.map +1 -0
  6. package/dist/app/interactive-app.js +309 -0
  7. package/dist/app/layout/canvas.d.ts +23 -0
  8. package/dist/app/layout/canvas.d.ts.map +1 -0
  9. package/dist/app/layout/canvas.js +36 -0
  10. package/dist/app/layout/footer.d.ts +31 -0
  11. package/dist/app/layout/footer.d.ts.map +1 -0
  12. package/dist/app/layout/footer.js +41 -0
  13. package/dist/app/layout/header.d.ts +20 -0
  14. package/dist/app/layout/header.d.ts.map +1 -0
  15. package/dist/app/layout/header.js +27 -0
  16. package/dist/app/menu/categories.d.ts +20 -0
  17. package/dist/app/menu/categories.d.ts.map +1 -0
  18. package/dist/app/menu/categories.js +181 -0
  19. package/dist/app/menu/filter.d.ts +17 -0
  20. package/dist/app/menu/filter.d.ts.map +1 -0
  21. package/dist/app/menu/filter.js +33 -0
  22. package/dist/app/menu/menu-view.d.ts +35 -0
  23. package/dist/app/menu/menu-view.d.ts.map +1 -0
  24. package/dist/app/menu/menu-view.js +230 -0
  25. package/dist/app/menu/recent.d.ts +24 -0
  26. package/dist/app/menu/recent.d.ts.map +1 -0
  27. package/dist/app/menu/recent.js +49 -0
  28. package/dist/app/types.d.ts +43 -0
  29. package/dist/app/types.d.ts.map +1 -0
  30. package/dist/app/types.js +7 -0
  31. package/dist/app/views/command-runner.d.ts +36 -0
  32. package/dist/app/views/command-runner.d.ts.map +1 -0
  33. package/dist/app/views/command-runner.js +372 -0
  34. package/dist/app/views/help-overlay.d.ts +21 -0
  35. package/dist/app/views/help-overlay.d.ts.map +1 -0
  36. package/dist/app/views/help-overlay.js +45 -0
  37. package/dist/auth/ci-token.d.ts +14 -2
  38. package/dist/auth/ci-token.d.ts.map +1 -1
  39. package/dist/auth/ci-token.js +15 -30
  40. package/dist/auth/device-flow.d.ts +2 -1
  41. package/dist/auth/device-flow.d.ts.map +1 -1
  42. package/dist/auth/device-flow.js +13 -10
  43. package/dist/auth/token-store.d.ts.map +1 -1
  44. package/dist/auth/token-store.js +12 -2
  45. package/dist/baseline/diff.d.ts +2 -2
  46. package/dist/baseline/diff.d.ts.map +1 -1
  47. package/dist/baseline/diff.js +15 -34
  48. package/dist/commands/a11y.d.ts +9 -0
  49. package/dist/commands/a11y.d.ts.map +1 -0
  50. package/dist/commands/a11y.js +76 -0
  51. package/dist/commands/audit/artifacts.d.ts +27 -0
  52. package/dist/commands/audit/artifacts.d.ts.map +1 -0
  53. package/dist/commands/audit/artifacts.js +158 -0
  54. package/dist/commands/audit/ci-detection.d.ts +18 -0
  55. package/dist/commands/audit/ci-detection.d.ts.map +1 -0
  56. package/dist/commands/audit/ci-detection.js +71 -0
  57. package/dist/commands/audit/explain.d.ts +11 -0
  58. package/dist/commands/audit/explain.d.ts.map +1 -0
  59. package/dist/commands/audit/explain.js +45 -0
  60. package/dist/commands/audit/filters.d.ts +17 -0
  61. package/dist/commands/audit/filters.d.ts.map +1 -0
  62. package/dist/commands/audit/filters.js +40 -0
  63. package/dist/commands/audit/index.d.ts +18 -0
  64. package/dist/commands/audit/index.d.ts.map +1 -0
  65. package/dist/commands/audit/index.js +564 -0
  66. package/dist/commands/audit/output.d.ts +32 -0
  67. package/dist/commands/audit/output.d.ts.map +1 -0
  68. package/dist/commands/audit/output.js +130 -0
  69. package/dist/commands/audit/policy.d.ts +19 -0
  70. package/dist/commands/audit/policy.d.ts.map +1 -0
  71. package/dist/commands/audit/policy.js +102 -0
  72. package/dist/commands/audit/scoring.d.ts +23 -0
  73. package/dist/commands/audit/scoring.d.ts.map +1 -0
  74. package/dist/commands/audit/scoring.js +70 -0
  75. package/dist/commands/audit/types.d.ts +88 -0
  76. package/dist/commands/audit/types.d.ts.map +1 -0
  77. package/dist/commands/audit/types.js +8 -0
  78. package/dist/commands/audit.d.ts +2 -60
  79. package/dist/commands/audit.d.ts.map +1 -1
  80. package/dist/commands/audit.js +2 -1038
  81. package/dist/commands/baseline.d.ts +1 -0
  82. package/dist/commands/baseline.d.ts.map +1 -1
  83. package/dist/commands/baseline.js +205 -121
  84. package/dist/commands/comment.d.ts +22 -0
  85. package/dist/commands/comment.d.ts.map +1 -1
  86. package/dist/commands/comment.js +122 -58
  87. package/dist/commands/compare.d.ts +17 -0
  88. package/dist/commands/compare.d.ts.map +1 -1
  89. package/dist/commands/compare.js +287 -180
  90. package/dist/commands/diff.d.ts +5 -0
  91. package/dist/commands/diff.d.ts.map +1 -1
  92. package/dist/commands/diff.js +168 -141
  93. package/dist/commands/doc.d.ts +10 -0
  94. package/dist/commands/doc.d.ts.map +1 -1
  95. package/dist/commands/doc.js +134 -76
  96. package/dist/commands/doctor.d.ts +2 -0
  97. package/dist/commands/doctor.d.ts.map +1 -1
  98. package/dist/commands/doctor.js +164 -17
  99. package/dist/commands/download.d.ts +10 -0
  100. package/dist/commands/download.d.ts.map +1 -1
  101. package/dist/commands/download.js +169 -112
  102. package/dist/commands/explain.d.ts +5 -0
  103. package/dist/commands/explain.d.ts.map +1 -1
  104. package/dist/commands/explain.js +241 -155
  105. package/dist/commands/fix-all.d.ts +25 -0
  106. package/dist/commands/fix-all.d.ts.map +1 -0
  107. package/dist/commands/fix-all.js +206 -0
  108. package/dist/commands/fix-plan.d.ts +9 -0
  109. package/dist/commands/fix-plan.d.ts.map +1 -1
  110. package/dist/commands/fix-plan.js +152 -89
  111. package/dist/commands/fix.d.ts +17 -0
  112. package/dist/commands/fix.d.ts.map +1 -0
  113. package/dist/commands/fix.js +111 -0
  114. package/dist/commands/init.d.ts +11 -0
  115. package/dist/commands/init.d.ts.map +1 -1
  116. package/dist/commands/init.js +94 -42
  117. package/dist/commands/login.d.ts +18 -0
  118. package/dist/commands/login.d.ts.map +1 -1
  119. package/dist/commands/login.js +268 -95
  120. package/dist/commands/patch-review.d.ts +11 -0
  121. package/dist/commands/patch-review.d.ts.map +1 -1
  122. package/dist/commands/patch-review.js +159 -97
  123. package/dist/commands/policy.d.ts +31 -0
  124. package/dist/commands/policy.d.ts.map +1 -1
  125. package/dist/commands/policy.js +269 -124
  126. package/dist/commands/release-notes.d.ts +10 -0
  127. package/dist/commands/release-notes.d.ts.map +1 -1
  128. package/dist/commands/release-notes.js +127 -73
  129. package/dist/commands/scan.d.ts +13 -0
  130. package/dist/commands/scan.d.ts.map +1 -0
  131. package/dist/commands/scan.js +133 -0
  132. package/dist/commands/status.d.ts +9 -0
  133. package/dist/commands/status.d.ts.map +1 -0
  134. package/dist/commands/status.js +81 -0
  135. package/dist/commands/suggest.d.ts +10 -0
  136. package/dist/commands/suggest.d.ts.map +1 -1
  137. package/dist/commands/suggest.js +153 -82
  138. package/dist/commands/triage.d.ts +35 -0
  139. package/dist/commands/triage.d.ts.map +1 -1
  140. package/dist/commands/triage.js +206 -81
  141. package/dist/commands/upload.d.ts +9 -0
  142. package/dist/commands/upload.d.ts.map +1 -1
  143. package/dist/commands/upload.js +140 -101
  144. package/dist/commands/verify.d.ts +13 -0
  145. package/dist/commands/verify.d.ts.map +1 -0
  146. package/dist/commands/verify.js +118 -0
  147. package/dist/index.d.ts +3 -2
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +125 -990
  150. package/dist/interactive/fix-wizard.d.ts +3 -0
  151. package/dist/interactive/fix-wizard.d.ts.map +1 -1
  152. package/dist/interactive/fix-wizard.js +130 -112
  153. package/dist/interactive/init-wizard.d.ts +3 -1
  154. package/dist/interactive/init-wizard.d.ts.map +1 -1
  155. package/dist/interactive/init-wizard.js +207 -138
  156. package/dist/interactive/prompts.d.ts +7 -3
  157. package/dist/interactive/prompts.d.ts.map +1 -1
  158. package/dist/interactive/prompts.js +44 -23
  159. package/dist/output/envelope.d.ts +2 -0
  160. package/dist/output/envelope.d.ts.map +1 -1
  161. package/dist/output/envelope.js +18 -2
  162. package/dist/output/factory.d.ts +9 -1
  163. package/dist/output/factory.d.ts.map +1 -1
  164. package/dist/output/html.d.ts +2 -1
  165. package/dist/output/html.d.ts.map +1 -1
  166. package/dist/output/html.js +3 -2
  167. package/dist/output/human.d.ts +9 -1
  168. package/dist/output/human.d.ts.map +1 -1
  169. package/dist/output/human.js +17 -2
  170. package/dist/output/json.d.ts +2 -1
  171. package/dist/output/json.d.ts.map +1 -1
  172. package/dist/output/junit.d.ts +2 -1
  173. package/dist/output/junit.d.ts.map +1 -1
  174. package/dist/output/sarif.d.ts +2 -1
  175. package/dist/output/sarif.d.ts.map +1 -1
  176. package/dist/types.d.ts +74 -0
  177. package/dist/types.d.ts.map +1 -0
  178. package/dist/types.js +5 -0
  179. package/dist/ui/banner.d.ts +34 -0
  180. package/dist/ui/banner.d.ts.map +1 -1
  181. package/dist/ui/banner.js +97 -5
  182. package/dist/ui/diagnostics.d.ts +9 -4
  183. package/dist/ui/diagnostics.d.ts.map +1 -1
  184. package/dist/ui/diagnostics.js +32 -82
  185. package/dist/ui/strings.d.ts +373 -0
  186. package/dist/ui/strings.d.ts.map +1 -0
  187. package/dist/ui/strings.js +499 -0
  188. package/dist/ui/table.d.ts +0 -2
  189. package/dist/ui/table.d.ts.map +1 -1
  190. package/dist/ui/table.js +3 -4
  191. package/dist/utils/api-client.d.ts +46 -0
  192. package/dist/utils/api-client.d.ts.map +1 -0
  193. package/dist/utils/api-client.js +170 -0
  194. package/dist/utils/client.d.ts +29 -18
  195. package/dist/utils/client.d.ts.map +1 -1
  196. package/dist/utils/client.js +102 -12
  197. package/dist/utils/formatters.d.ts +38 -0
  198. package/dist/utils/formatters.d.ts.map +1 -0
  199. package/dist/utils/formatters.js +277 -0
  200. package/dist/utils/local-capture.d.ts +25 -0
  201. package/dist/utils/local-capture.d.ts.map +1 -0
  202. package/dist/utils/local-capture.js +57 -0
  203. package/dist/utils/url-classify.d.ts +18 -0
  204. package/dist/utils/url-classify.d.ts.map +1 -0
  205. package/dist/utils/url-classify.js +106 -0
  206. package/node_modules/@vertaaux/tui/dist/index.cjs +713 -20
  207. package/node_modules/@vertaaux/tui/dist/index.cjs.map +1 -1
  208. package/node_modules/@vertaaux/tui/dist/index.d.cts +361 -4
  209. package/node_modules/@vertaaux/tui/dist/index.d.ts +361 -4
  210. package/node_modules/@vertaaux/tui/dist/index.js +689 -21
  211. package/node_modules/@vertaaux/tui/dist/index.js.map +1 -1
  212. package/package.json +13 -5
  213. package/dist/commands/client.d.ts +0 -14
  214. package/dist/commands/client.d.ts.map +0 -1
  215. package/dist/commands/client.js +0 -362
  216. package/dist/commands/drift.d.ts +0 -15
  217. package/dist/commands/drift.d.ts.map +0 -1
  218. package/dist/commands/drift.js +0 -309
  219. package/dist/commands/protect.d.ts +0 -16
  220. package/dist/commands/protect.d.ts.map +0 -1
  221. package/dist/commands/protect.js +0 -323
  222. package/dist/commands/report.d.ts +0 -15
  223. package/dist/commands/report.d.ts.map +0 -1
  224. package/dist/commands/report.js +0 -214
  225. package/dist/policy/sync.d.ts +0 -67
  226. package/dist/policy/sync.d.ts.map +0 -1
  227. package/dist/policy/sync.js +0 -147
@@ -6,12 +6,14 @@
6
6
  * - vertaa logout: Clear stored credentials
7
7
  * - vertaa whoami: Show current authentication status
8
8
  */
9
- import chalk from "chalk";
9
+ import { colorize, bold, brand, severity as severityPalette, renderError, renderWarning, runSteps, createRenderer } from "@vertaaux/tui";
10
10
  import { saveToken, loadToken, clearToken, isTokenExpired, } from "../auth/token-store.js";
11
11
  import { startDeviceFlow } from "../auth/device-flow.js";
12
12
  import { validateCIToken, getCIToken, getTokenInfo } from "../auth/ci-token.js";
13
13
  import { isInteractive } from "../interactive/prompts.js";
14
14
  import { ExitCode } from "../utils/exit-codes.js";
15
+ import { writeOutput } from "../output/envelope.js";
16
+ import { strings } from "../ui/strings.js";
15
17
  /**
16
18
  * OAuth client ID for the CLI.
17
19
  * This is a public client ID, not a secret.
@@ -40,145 +42,285 @@ function getApiBase() {
40
42
  /**
41
43
  * Handle the login command.
42
44
  */
43
- async function handleLogin(options) {
45
+ export async function handleLogin(options) {
44
46
  // Check for SSO placeholder
45
47
  if (options.sso) {
46
- console.error("SSO login is not yet implemented.");
47
- console.error("Use --token for CI/API token authentication or omit flags for device code flow.");
48
+ process.stderr.write(renderWarning({
49
+ message: strings.login.ssoNotImplemented,
50
+ suggestion: "vertaa login",
51
+ }) + "\n");
48
52
  process.exit(ExitCode.ERROR);
49
53
  }
54
+ const renderer = createRenderer("auto");
55
+ const baseState = {
56
+ phase: "login",
57
+ phaseIndex: 1,
58
+ phaseTotal: 1,
59
+ url: "",
60
+ mode: "login",
61
+ progress: {},
62
+ totals: {},
63
+ issueCount: 0,
64
+ scorePreview: null,
65
+ verbose: false,
66
+ elapsed: 0,
67
+ };
68
+ const startTime = Date.now();
50
69
  // Option 1: Direct token authentication (CI mode)
51
70
  if (options.token) {
52
- console.error("Validating token...");
53
- const apiBase = options.base || getApiBase();
54
- const isValid = await validateCIToken(options.token, apiBase);
55
- if (!isValid) {
56
- console.error(chalk.red("Error: Invalid token. Please check your token and try again."));
57
- process.exit(ExitCode.ERROR);
58
- }
59
- // Save the CI token
60
- const tokenData = {
61
- accessToken: options.token,
62
- type: "ci",
63
- savedAt: new Date().toISOString(),
64
- };
65
- await saveToken(tokenData);
66
- console.error(chalk.green("Authentication successful!"));
67
- console.error("Token saved to ~/.vertaaux/credentials.json");
71
+ const steps = [
72
+ {
73
+ id: "validate",
74
+ actionText: strings.login.validatingToken,
75
+ summaryText: "Token validated",
76
+ run: async () => {
77
+ const apiBase = options.base || getApiBase();
78
+ const isValid = await validateCIToken(options.token, apiBase);
79
+ if (!isValid) {
80
+ throw new Error(strings.login.errors.invalidToken);
81
+ }
82
+ },
83
+ },
84
+ {
85
+ id: "save",
86
+ actionText: "Saving credentials...",
87
+ summaryText: "Credentials saved",
88
+ run: async () => {
89
+ const tokenData = {
90
+ accessToken: options.token,
91
+ type: "ci",
92
+ savedAt: new Date().toISOString(),
93
+ };
94
+ await saveToken(tokenData);
95
+ },
96
+ },
97
+ ];
98
+ await runSteps(steps, {
99
+ failFast: true,
100
+ onStateChange: (stepStates) => {
101
+ renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
102
+ },
103
+ });
104
+ renderer.finish({ url: "", mode: "login", overallScore: 0, scores: {}, issueCount: 0, passed: true, elapsed: Date.now() - startTime });
105
+ writeOutput(colorize(strings.login.success, brand.lime) + "\n" + strings.login.tokenSaved);
68
106
  return;
69
107
  }
70
108
  // Option 2: Check for CI token in environment
71
109
  const envToken = getCIToken();
72
110
  if (envToken && !isInteractive()) {
73
- console.error("Found token in environment, validating...");
74
- const apiBase = options.base || getApiBase();
75
- const isValid = await validateCIToken(envToken, apiBase);
76
- if (!isValid) {
77
- console.error(chalk.red("Error: Environment token is invalid."));
78
- process.exit(ExitCode.ERROR);
79
- }
80
- const tokenData = {
81
- accessToken: envToken,
82
- type: "ci",
83
- savedAt: new Date().toISOString(),
84
- };
85
- await saveToken(tokenData);
86
- console.error(chalk.green("Authentication successful!"));
87
- console.error("Token from environment saved to ~/.vertaaux/credentials.json");
111
+ const steps = [
112
+ {
113
+ id: "validate",
114
+ actionText: strings.login.envTokenFound,
115
+ summaryText: "Environment token validated",
116
+ run: async () => {
117
+ const apiBase = options.base || getApiBase();
118
+ const isValid = await validateCIToken(envToken, apiBase);
119
+ if (!isValid) {
120
+ throw new Error(strings.login.errors.envTokenInvalid);
121
+ }
122
+ },
123
+ },
124
+ {
125
+ id: "save",
126
+ actionText: "Saving credentials...",
127
+ summaryText: "Credentials saved",
128
+ run: async () => {
129
+ const tokenData = {
130
+ accessToken: envToken,
131
+ type: "ci",
132
+ savedAt: new Date().toISOString(),
133
+ };
134
+ await saveToken(tokenData);
135
+ },
136
+ },
137
+ ];
138
+ await runSteps(steps, {
139
+ failFast: true,
140
+ onStateChange: (stepStates) => {
141
+ renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
142
+ },
143
+ });
144
+ renderer.finish({ url: "", mode: "login", overallScore: 0, scores: {}, issueCount: 0, passed: true, elapsed: Date.now() - startTime });
145
+ writeOutput(colorize(strings.login.success, brand.lime) + "\n" + strings.login.envTokenSaved);
88
146
  return;
89
147
  }
90
148
  // Option 3: Interactive device code flow (requires TTY)
91
149
  if (!isInteractive()) {
92
- console.error(chalk.red("Error: Interactive login requires a terminal."));
93
- console.error("Use --token <token> for non-interactive authentication,");
94
- console.error("or set VERTAAUX_TOKEN environment variable.");
150
+ process.stderr.write(renderError({
151
+ message: strings.login.errors.requiresTerminal,
152
+ suggestion: "vertaa login --token <api-key>",
153
+ exitCode: ExitCode.ERROR,
154
+ }) + "\n");
95
155
  process.exit(ExitCode.ERROR);
96
156
  }
97
157
  // Start device code flow
98
- console.error("Starting authentication...");
99
- try {
100
- const authBase = options.base ? options.base.replace("/v1", "") : getAuthBase();
101
- const result = await startDeviceFlow(CLI_CLIENT_ID, authBase);
102
- // Calculate expiration time
103
- const expiresAt = new Date(Date.now() + result.expiresIn * 1000).toISOString();
104
- // Save token
105
- const tokenData = {
106
- accessToken: result.accessToken,
107
- refreshToken: result.refreshToken,
108
- expiresAt,
109
- type: "device",
110
- savedAt: new Date().toISOString(),
111
- };
112
- await saveToken(tokenData);
113
- console.error(chalk.green("\nAuthentication successful!"));
114
- console.error("Token saved to ~/.vertaaux/credentials.json");
115
- }
116
- catch (error) {
117
- console.error(chalk.red("\nError:"), error instanceof Error ? error.message : String(error));
118
- process.exit(ExitCode.ERROR);
119
- }
158
+ const steps = [
159
+ {
160
+ id: "auth",
161
+ actionText: strings.login.startingAuth,
162
+ summaryText: "Authenticated",
163
+ run: async () => {
164
+ const authBase = options.base ? options.base.replace("/v1", "") : getAuthBase();
165
+ const result = await startDeviceFlow(CLI_CLIENT_ID, authBase);
166
+ // Calculate expiration time
167
+ const expiresAt = new Date(Date.now() + result.expiresIn * 1000).toISOString();
168
+ // Save token
169
+ const tokenData = {
170
+ accessToken: result.accessToken,
171
+ refreshToken: result.refreshToken,
172
+ expiresAt,
173
+ type: "device",
174
+ savedAt: new Date().toISOString(),
175
+ };
176
+ await saveToken(tokenData);
177
+ },
178
+ },
179
+ ];
180
+ await runSteps(steps, {
181
+ failFast: true,
182
+ onStateChange: (stepStates) => {
183
+ renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
184
+ },
185
+ });
186
+ renderer.finish({ url: "", mode: "login", overallScore: 0, scores: {}, issueCount: 0, passed: true, elapsed: Date.now() - startTime });
187
+ writeOutput(colorize(strings.login.success, brand.lime) + "\n" + strings.login.tokenSaved);
120
188
  }
121
189
  /**
122
190
  * Handle the logout command.
123
191
  */
124
- async function handleLogout() {
192
+ export async function handleLogout() {
193
+ const renderer = createRenderer("auto");
194
+ const baseState = {
195
+ phase: "logout",
196
+ phaseIndex: 1,
197
+ phaseTotal: 1,
198
+ url: "",
199
+ mode: "logout",
200
+ progress: {},
201
+ totals: {},
202
+ issueCount: 0,
203
+ scorePreview: null,
204
+ verbose: false,
205
+ elapsed: 0,
206
+ };
207
+ const startTime = Date.now();
208
+ const steps = [
209
+ {
210
+ id: "clear",
211
+ actionText: "Clearing credentials...",
212
+ summaryText: "Credentials cleared",
213
+ run: async () => {
214
+ const existingToken = await loadToken();
215
+ if (!existingToken) {
216
+ // Not an error — just nothing to clear
217
+ return;
218
+ }
219
+ await clearToken();
220
+ },
221
+ },
222
+ ];
223
+ // Check if already logged out before step-list
125
224
  const existingToken = await loadToken();
126
225
  if (!existingToken) {
127
- console.error("No stored credentials found.");
226
+ writeOutput(strings.login.noStoredCredentials);
128
227
  return;
129
228
  }
130
- await clearToken();
131
- console.error(chalk.green("Logged out successfully."));
132
- console.error("Credentials removed from ~/.vertaaux/credentials.json");
229
+ await runSteps(steps, {
230
+ failFast: true,
231
+ onStateChange: (stepStates) => {
232
+ renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
233
+ },
234
+ });
235
+ renderer.finish({ url: "", mode: "logout", overallScore: 0, scores: {}, issueCount: 0, passed: true, elapsed: Date.now() - startTime });
236
+ writeOutput(colorize(strings.login.logoutSuccess, brand.lime) + "\n" + strings.login.credentialsRemoved);
133
237
  }
134
238
  /**
135
239
  * Handle the whoami command.
136
240
  */
137
- async function handleWhoami(options) {
241
+ export async function handleWhoami(options) {
242
+ const renderer = createRenderer("auto");
243
+ const baseState = {
244
+ phase: "whoami",
245
+ phaseIndex: 1,
246
+ phaseTotal: 1,
247
+ url: "",
248
+ mode: "whoami",
249
+ progress: {},
250
+ totals: {},
251
+ issueCount: 0,
252
+ scorePreview: null,
253
+ verbose: false,
254
+ elapsed: 0,
255
+ };
256
+ const startTime = Date.now();
138
257
  // Check for token in credentials file
139
258
  const storedToken = await loadToken();
140
259
  // Check for token in environment
141
260
  const envToken = getCIToken();
142
261
  if (!storedToken && !envToken) {
143
- console.error(chalk.yellow("Not authenticated."));
144
- console.error("\nRun `vertaa login` to authenticate.");
262
+ writeOutput(colorize(strings.login.notAuthenticated, severityPalette.warning) +
263
+ "\n" + strings.login.runLoginHint);
145
264
  return;
146
265
  }
147
266
  // Use stored token or env token
148
267
  const token = storedToken?.accessToken || envToken;
149
- const tokenSource = storedToken ? "stored" : "environment";
150
268
  if (!token) {
151
- console.error(chalk.yellow("Not authenticated."));
152
- console.error("\nRun `vertaa login` to authenticate.");
269
+ writeOutput(colorize(strings.login.notAuthenticated, severityPalette.warning) +
270
+ "\n" + strings.login.runLoginHint);
153
271
  return;
154
272
  }
155
273
  // Check expiration for stored device tokens
156
274
  if (storedToken && storedToken.type === "device" && isTokenExpired(storedToken)) {
157
- console.error(chalk.yellow("Token expired."));
158
- console.error("\nRun `vertaa login` to re-authenticate.");
275
+ writeOutput(colorize(strings.login.tokenExpired, severityPalette.warning) +
276
+ "\n" + strings.login.runLoginRefreshHint);
159
277
  return;
160
278
  }
161
- // Get token info from API
162
- const apiBase = options.base || getApiBase();
163
- const info = await getTokenInfo(token, apiBase);
164
- if (!info || !info.valid) {
165
- console.error(chalk.yellow("Token invalid or expired."));
166
- console.error("\nRun `vertaa login` to re-authenticate.");
279
+ let whoamiResult = null;
280
+ const steps = [
281
+ {
282
+ id: "check",
283
+ actionText: "Checking identity...",
284
+ summaryText: "Identity verified",
285
+ run: async () => {
286
+ const apiBase = options.base || getApiBase();
287
+ whoamiResult = await getTokenInfo(token, apiBase);
288
+ if (!whoamiResult || !whoamiResult.valid) {
289
+ throw new Error(strings.login.tokenInvalidOrExpired);
290
+ }
291
+ },
292
+ },
293
+ ];
294
+ await runSteps(steps, {
295
+ failFast: true,
296
+ onStateChange: (stepStates) => {
297
+ renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
298
+ },
299
+ });
300
+ renderer.finish({ url: "", mode: "whoami", overallScore: 0, scores: {}, issueCount: 0, passed: true, elapsed: Date.now() - startTime });
301
+ if (!whoamiResult || !whoamiResult.valid) {
302
+ writeOutput(colorize(strings.login.tokenInvalidOrExpired, severityPalette.warning) +
303
+ "\n" + strings.login.runLoginRefreshHint);
167
304
  return;
168
305
  }
169
- // Display auth status
170
- console.error(chalk.green("Authenticated"));
171
- console.error("");
172
- console.error(` Source: ${tokenSource}`);
173
- console.error(` Type: ${storedToken?.type || "ci"}`);
174
- if (info.organization) {
175
- console.error(` Organization: ${info.organization}`);
306
+ const info = whoamiResult;
307
+ // Display auth status via writeOutput
308
+ const displayName = info.name || info.email || info.user_id || "Unknown";
309
+ const lines = [
310
+ colorize(strings.login.successWithName(bold(displayName)), brand.lime),
311
+ "",
312
+ ];
313
+ if (info.email) {
314
+ lines.push(` Email: ${info.email}`);
176
315
  }
177
- if (info.user_id) {
178
- console.error(` User ID: ${info.user_id}`);
316
+ if (info.tier) {
317
+ lines.push(` Plan: ${info.tier.charAt(0).toUpperCase() + info.tier.slice(1)}`);
318
+ }
319
+ if (info.organization) {
320
+ lines.push(` Organization: ${info.organization}`);
179
321
  }
180
322
  if (info.scopes && info.scopes.length > 0) {
181
- console.error(` Scopes: ${info.scopes.join(", ")}`);
323
+ lines.push(` Scopes: ${info.scopes.join(", ")}`);
182
324
  }
183
325
  if (storedToken?.expiresAt) {
184
326
  const expiresAt = new Date(storedToken.expiresAt);
@@ -186,9 +328,10 @@ async function handleWhoami(options) {
186
328
  const diffMs = expiresAt.getTime() - now.getTime();
187
329
  const diffHours = Math.round(diffMs / (1000 * 60 * 60));
188
330
  if (diffHours > 0) {
189
- console.error(` Expires: in ${diffHours} hour${diffHours === 1 ? "" : "s"}`);
331
+ lines.push(` Expires: in ${diffHours} hour${diffHours === 1 ? "" : "s"}`);
190
332
  }
191
333
  }
334
+ writeOutput(lines.join("\n"));
192
335
  }
193
336
  /**
194
337
  * Register authentication commands with the Commander program.
@@ -197,19 +340,39 @@ export function registerLoginCommand(program) {
197
340
  // Login command
198
341
  program
199
342
  .command("login")
200
- .description("Authenticate with VertaaUX")
201
- .option("--token <token>", "Use API token directly (for CI/non-interactive use)")
343
+ .description("Authenticate with VertaaUX (stores SDK credentials in ~/.vertaaux/credentials.json)")
344
+ .option("--token <token>", "Use API token directly (stored as SDK default credentials)")
202
345
  .option("--sso", "Use SSO login (not yet implemented)")
203
346
  .option("-b, --base <url>", "API base URL")
204
347
  .action(async (options) => {
205
- await handleLogin(options);
348
+ try {
349
+ await handleLogin(options);
350
+ }
351
+ catch (error) {
352
+ process.stderr.write(renderError({
353
+ message: error instanceof Error ? error.message : String(error),
354
+ suggestion: "vertaa login",
355
+ exitCode: ExitCode.ERROR,
356
+ }) + "\n");
357
+ process.exit(ExitCode.ERROR);
358
+ }
206
359
  });
207
360
  // Logout command
208
361
  program
209
362
  .command("logout")
210
363
  .description("Clear stored credentials")
211
364
  .action(async () => {
212
- await handleLogout();
365
+ try {
366
+ await handleLogout();
367
+ }
368
+ catch (error) {
369
+ process.stderr.write(renderError({
370
+ message: error instanceof Error ? error.message : String(error),
371
+ suggestion: "vertaa login",
372
+ exitCode: ExitCode.ERROR,
373
+ }) + "\n");
374
+ process.exit(ExitCode.ERROR);
375
+ }
213
376
  });
214
377
  // Whoami command
215
378
  program
@@ -217,6 +380,16 @@ export function registerLoginCommand(program) {
217
380
  .description("Show current authentication status")
218
381
  .option("-b, --base <url>", "API base URL")
219
382
  .action(async (options) => {
220
- await handleWhoami(options);
383
+ try {
384
+ await handleWhoami(options);
385
+ }
386
+ catch (error) {
387
+ process.stderr.write(renderError({
388
+ message: error instanceof Error ? error.message : String(error),
389
+ suggestion: "vertaa whoami",
390
+ exitCode: ExitCode.ERROR,
391
+ }) + "\n");
392
+ process.exit(ExitCode.ERROR);
393
+ }
221
394
  });
222
395
  }
@@ -10,5 +10,16 @@
10
10
  * cat fix.patch | vertaa patch-review --findings findings.json
11
11
  */
12
12
  import { Command } from "commander";
13
+ export interface PatchReviewCommandOptions {
14
+ job?: string;
15
+ findings?: string;
16
+ diffFile?: string;
17
+ format?: string;
18
+ base?: string;
19
+ machine?: boolean;
20
+ dryRun?: boolean;
21
+ apiKey?: string;
22
+ }
23
+ export declare function handlePatchReview(opts: PatchReviewCommandOptions): Promise<void>;
13
24
  export declare function registerPatchReviewCommand(program: Command): void;
14
25
  //# sourceMappingURL=patch-review.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"patch-review.d.ts","sourceRoot":"","sources":["../../src/commands/patch-review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmIpC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2HjE"}
1
+ {"version":3,"file":"patch-review.d.ts","sourceRoot":"","sources":["../../src/commands/patch-review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmIpC,MAAM,WAAW,yBAAyB;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkJtF;AAMD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6CjE"}