@vertaaux/cli 0.2.3 → 0.3.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.
- package/LICENSE +21 -0
- package/README.md +58 -2
- package/dist/auth/device-flow.js +6 -8
- package/dist/commands/audit.d.ts +2 -0
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +165 -6
- package/dist/commands/compare.d.ts +20 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +335 -0
- package/dist/commands/doc.d.ts +18 -0
- package/dist/commands/doc.d.ts.map +1 -0
- package/dist/commands/doc.js +161 -0
- package/dist/commands/download.d.ts.map +1 -1
- package/dist/commands/download.js +9 -8
- package/dist/commands/explain.d.ts +14 -33
- package/dist/commands/explain.d.ts.map +1 -1
- package/dist/commands/explain.js +277 -179
- package/dist/commands/fix-plan.d.ts +15 -0
- package/dist/commands/fix-plan.d.ts.map +1 -0
- package/dist/commands/fix-plan.js +182 -0
- package/dist/commands/patch-review.d.ts +14 -0
- package/dist/commands/patch-review.d.ts.map +1 -0
- package/dist/commands/patch-review.js +200 -0
- package/dist/commands/release-notes.d.ts +17 -0
- package/dist/commands/release-notes.d.ts.map +1 -0
- package/dist/commands/release-notes.js +145 -0
- package/dist/commands/suggest.d.ts +18 -0
- package/dist/commands/suggest.d.ts.map +1 -0
- package/dist/commands/suggest.js +152 -0
- package/dist/commands/triage.d.ts +17 -0
- package/dist/commands/triage.d.ts.map +1 -0
- package/dist/commands/triage.js +205 -0
- package/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +8 -7
- package/dist/index.js +62 -25
- package/dist/output/formats.d.ts.map +1 -1
- package/dist/output/formats.js +14 -0
- package/dist/output/human.d.ts +1 -10
- package/dist/output/human.d.ts.map +1 -1
- package/dist/output/human.js +26 -98
- package/dist/prompts/command-catalog.d.ts +46 -0
- package/dist/prompts/command-catalog.d.ts.map +1 -0
- package/dist/prompts/command-catalog.js +187 -0
- package/dist/ui/spinner.d.ts +10 -35
- package/dist/ui/spinner.d.ts.map +1 -1
- package/dist/ui/spinner.js +11 -58
- package/dist/ui/table.d.ts +1 -18
- package/dist/ui/table.d.ts.map +1 -1
- package/dist/ui/table.js +56 -163
- package/dist/utils/ai-error.d.ts +48 -0
- package/dist/utils/ai-error.d.ts.map +1 -0
- package/dist/utils/ai-error.js +190 -0
- package/dist/utils/detect-env.d.ts +6 -8
- package/dist/utils/detect-env.d.ts.map +1 -1
- package/dist/utils/detect-env.js +6 -25
- package/dist/utils/stdin.d.ts +50 -0
- package/dist/utils/stdin.d.ts.map +1 -0
- package/dist/utils/stdin.js +93 -0
- package/package.json +9 -5
package/dist/output/human.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Human-readable output formatter for CLI.
|
|
3
3
|
*
|
|
4
4
|
* Outputs audit results as colorful, formatted text for terminal display.
|
|
5
|
-
*
|
|
5
|
+
* Delegates to @vertaaux/tui for consistent rendering.
|
|
6
6
|
*/
|
|
7
7
|
import { type FormatTableOptions } from "../ui/table.js";
|
|
8
8
|
export interface AuditResult {
|
|
@@ -19,23 +19,14 @@ export interface AuditResult {
|
|
|
19
19
|
error?: string;
|
|
20
20
|
}
|
|
21
21
|
export interface FormatHumanOptions {
|
|
22
|
-
/** How to group issues: severity (default), category, route */
|
|
23
22
|
groupBy?: "severity" | "category" | "route";
|
|
24
|
-
/** Whether to show detailed scores table */
|
|
25
23
|
showScores?: boolean;
|
|
26
|
-
/** Whether to show the summary at the end */
|
|
27
24
|
showSummary?: boolean;
|
|
28
|
-
/** Maximum issues to display per group */
|
|
29
25
|
maxIssuesPerGroup?: number;
|
|
30
|
-
/** Table formatting options */
|
|
31
26
|
tableOptions?: FormatTableOptions;
|
|
32
27
|
}
|
|
33
28
|
/**
|
|
34
29
|
* Format audit result as human-readable string.
|
|
35
|
-
*
|
|
36
|
-
* @param result - Audit result object
|
|
37
|
-
* @param options - Formatting options
|
|
38
|
-
* @returns Formatted string for terminal display
|
|
39
30
|
*/
|
|
40
31
|
export declare function formatAuditHuman(result: AuditResult, options?: FormatHumanOptions): string;
|
|
41
32
|
//# sourceMappingURL=human.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"human.d.ts","sourceRoot":"","sources":["../../src/output/human.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"human.d.ts","sourceRoot":"","sources":["../../src/output/human.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,EAOL,KAAK,kBAAkB,EACxB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;IAC5C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC;AAuND;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CAuCR"}
|
package/dist/output/human.js
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
* Human-readable output formatter for CLI.
|
|
3
3
|
*
|
|
4
4
|
* Outputs audit results as colorful, formatted text for terminal display.
|
|
5
|
-
*
|
|
5
|
+
* Delegates to @vertaaux/tui for consistent rendering.
|
|
6
6
|
*/
|
|
7
|
-
import
|
|
7
|
+
import { text, getTerminalWidth, scoreColor, boldColor, } from "@vertaaux/tui";
|
|
8
8
|
import { formatIssuesTable, formatScoresTable, formatIssueSummary, groupBySeverity, groupByCategory, } from "../ui/table.js";
|
|
9
|
-
import { shouldUseColor, getTerminalWidth } from "../utils/detect-env.js";
|
|
10
9
|
/**
|
|
11
10
|
* Normalize issues from various API response formats.
|
|
12
11
|
*/
|
|
@@ -34,41 +33,22 @@ function getOverallScore(scores) {
|
|
|
34
33
|
return null;
|
|
35
34
|
return Math.round(numeric.reduce((a, b) => a + b, 0) / numeric.length);
|
|
36
35
|
}
|
|
37
|
-
/**
|
|
38
|
-
* Format a horizontal rule.
|
|
39
|
-
*/
|
|
40
|
-
function hr() {
|
|
41
|
-
const width = Math.min(getTerminalWidth(), 80);
|
|
42
|
-
return shouldUseColor()
|
|
43
|
-
? chalk.dim("-".repeat(width))
|
|
44
|
-
: "-".repeat(width);
|
|
45
|
-
}
|
|
46
36
|
/**
|
|
47
37
|
* Format the header section.
|
|
48
38
|
*/
|
|
49
39
|
function formatHeader(result) {
|
|
50
|
-
const useColor = shouldUseColor();
|
|
51
40
|
const lines = [];
|
|
52
|
-
|
|
53
|
-
const title = useColor
|
|
54
|
-
? chalk.bold.cyan("Audit Complete")
|
|
55
|
-
: "AUDIT COMPLETE";
|
|
56
|
-
lines.push(title);
|
|
57
|
-
// URL
|
|
41
|
+
lines.push(text.heading("Audit Complete"));
|
|
58
42
|
if (result.url) {
|
|
59
|
-
|
|
60
|
-
? chalk.dim("URL: ") + chalk.white(result.url)
|
|
61
|
-
: `URL: ${result.url}`;
|
|
62
|
-
lines.push(urlLine);
|
|
43
|
+
lines.push(`${text.dim("URL:")} ${text.link(result.url)}`);
|
|
63
44
|
}
|
|
64
|
-
// Mode and Job ID
|
|
65
45
|
const meta = [];
|
|
66
46
|
if (result.mode)
|
|
67
47
|
meta.push(`Mode: ${result.mode}`);
|
|
68
48
|
if (result.job_id)
|
|
69
49
|
meta.push(`Job: ${result.job_id}`);
|
|
70
50
|
if (meta.length) {
|
|
71
|
-
lines.push(
|
|
51
|
+
lines.push(text.dim(meta.join(" | ")));
|
|
72
52
|
}
|
|
73
53
|
return lines.join("\n");
|
|
74
54
|
}
|
|
@@ -76,34 +56,20 @@ function formatHeader(result) {
|
|
|
76
56
|
* Format the scores section.
|
|
77
57
|
*/
|
|
78
58
|
function formatScoresSection(scores) {
|
|
79
|
-
const useColor = shouldUseColor();
|
|
80
59
|
const lines = [];
|
|
81
60
|
lines.push("");
|
|
82
|
-
lines.push(
|
|
83
|
-
lines.push(hr());
|
|
61
|
+
lines.push(text.bold("Scores"));
|
|
62
|
+
lines.push(text.hr(Math.min(getTerminalWidth(), 80)));
|
|
84
63
|
if (!scores || Object.keys(scores).length === 0) {
|
|
85
|
-
lines.push(
|
|
64
|
+
lines.push(text.dim("No scores available."));
|
|
86
65
|
return lines.join("\n");
|
|
87
66
|
}
|
|
88
|
-
// Overall score with color coding
|
|
89
67
|
const overall = getOverallScore(scores);
|
|
90
68
|
if (overall !== null) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (overall >= 90) {
|
|
94
|
-
scoreDisplay = chalk.green.bold(scoreDisplay);
|
|
95
|
-
}
|
|
96
|
-
else if (overall >= 70) {
|
|
97
|
-
scoreDisplay = chalk.yellow.bold(scoreDisplay);
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
scoreDisplay = chalk.red.bold(scoreDisplay);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
lines.push(`Overall: ${scoreDisplay}/100`);
|
|
69
|
+
const scoreStr = boldColor(String(overall), scoreColor(overall));
|
|
70
|
+
lines.push(`Overall: ${scoreStr}/100`);
|
|
104
71
|
lines.push("");
|
|
105
72
|
}
|
|
106
|
-
// Detailed scores table
|
|
107
73
|
const numericScores = {};
|
|
108
74
|
for (const [key, value] of Object.entries(scores)) {
|
|
109
75
|
if (typeof value === "number" && key !== "overall") {
|
|
@@ -119,40 +85,29 @@ function formatScoresSection(scores) {
|
|
|
119
85
|
* Format issues section grouped by severity.
|
|
120
86
|
*/
|
|
121
87
|
function formatIssuesBySeverity(issues, maxPerGroup, tableOptions) {
|
|
122
|
-
const useColor = shouldUseColor();
|
|
123
88
|
const lines = [];
|
|
124
89
|
lines.push("");
|
|
125
|
-
lines.push(
|
|
126
|
-
lines.push(hr());
|
|
90
|
+
lines.push(text.bold("Issues"));
|
|
91
|
+
lines.push(text.hr(Math.min(getTerminalWidth(), 80)));
|
|
127
92
|
if (issues.length === 0) {
|
|
128
|
-
lines.push(
|
|
93
|
+
lines.push(text.success("No issues found!"));
|
|
129
94
|
return lines.join("\n");
|
|
130
95
|
}
|
|
131
|
-
// Group by severity
|
|
132
96
|
const groups = groupBySeverity(issues);
|
|
133
|
-
const
|
|
134
|
-
for (const
|
|
135
|
-
const groupIssues = groups.get(
|
|
97
|
+
const order = ["critical", "error", "serious", "warning", "minor", "moderate", "info"];
|
|
98
|
+
for (const sev of order) {
|
|
99
|
+
const groupIssues = groups.get(sev);
|
|
136
100
|
if (!groupIssues || groupIssues.length === 0)
|
|
137
101
|
continue;
|
|
138
102
|
const displayIssues = maxPerGroup
|
|
139
103
|
? groupIssues.slice(0, maxPerGroup)
|
|
140
104
|
: groupIssues;
|
|
141
|
-
// Section header
|
|
142
|
-
const label = severity.toUpperCase();
|
|
143
|
-
const count = groupIssues.length;
|
|
144
|
-
const header = useColor
|
|
145
|
-
? chalk.bold(`${label} (${count})`)
|
|
146
|
-
: `${label} (${count})`;
|
|
147
105
|
lines.push("");
|
|
148
|
-
lines.push(
|
|
149
|
-
// Issues table for this severity
|
|
106
|
+
lines.push(text.bold(`${text.severityBadge(sev)} (${groupIssues.length})`));
|
|
150
107
|
lines.push(formatIssuesTable(displayIssues, tableOptions));
|
|
151
|
-
// Show truncation message if needed
|
|
152
108
|
if (maxPerGroup && groupIssues.length > maxPerGroup) {
|
|
153
109
|
const remaining = groupIssues.length - maxPerGroup;
|
|
154
|
-
|
|
155
|
-
lines.push(useColor ? chalk.dim(msg) : msg);
|
|
110
|
+
lines.push(text.dim(`...and ${remaining} more ${sev} issues`));
|
|
156
111
|
}
|
|
157
112
|
}
|
|
158
113
|
return lines.join("\n");
|
|
@@ -161,34 +116,25 @@ function formatIssuesBySeverity(issues, maxPerGroup, tableOptions) {
|
|
|
161
116
|
* Format issues section grouped by category.
|
|
162
117
|
*/
|
|
163
118
|
function formatIssuesByCategory(issues, maxPerGroup, tableOptions) {
|
|
164
|
-
const useColor = shouldUseColor();
|
|
165
119
|
const lines = [];
|
|
166
120
|
lines.push("");
|
|
167
|
-
lines.push(
|
|
168
|
-
lines.push(hr());
|
|
121
|
+
lines.push(text.bold("Issues by Category"));
|
|
122
|
+
lines.push(text.hr(Math.min(getTerminalWidth(), 80)));
|
|
169
123
|
if (issues.length === 0) {
|
|
170
|
-
lines.push(
|
|
124
|
+
lines.push(text.success("No issues found!"));
|
|
171
125
|
return lines.join("\n");
|
|
172
126
|
}
|
|
173
|
-
// Group by category
|
|
174
127
|
const groups = groupByCategory(issues);
|
|
175
128
|
for (const [category, groupIssues] of groups) {
|
|
176
129
|
const displayIssues = maxPerGroup
|
|
177
130
|
? groupIssues.slice(0, maxPerGroup)
|
|
178
131
|
: groupIssues;
|
|
179
|
-
// Section header
|
|
180
|
-
const header = useColor
|
|
181
|
-
? chalk.bold(`${category} (${groupIssues.length})`)
|
|
182
|
-
: `${category} (${groupIssues.length})`;
|
|
183
132
|
lines.push("");
|
|
184
|
-
lines.push(
|
|
185
|
-
// Issues table for this category
|
|
133
|
+
lines.push(text.bold(`${category} (${groupIssues.length})`));
|
|
186
134
|
lines.push(formatIssuesTable(displayIssues, tableOptions));
|
|
187
|
-
// Show truncation message if needed
|
|
188
135
|
if (maxPerGroup && groupIssues.length > maxPerGroup) {
|
|
189
136
|
const remaining = groupIssues.length - maxPerGroup;
|
|
190
|
-
|
|
191
|
-
lines.push(useColor ? chalk.dim(msg) : msg);
|
|
137
|
+
lines.push(text.dim(`...and ${remaining} more issues`));
|
|
192
138
|
}
|
|
193
139
|
}
|
|
194
140
|
return lines.join("\n");
|
|
@@ -197,14 +143,11 @@ function formatIssuesByCategory(issues, maxPerGroup, tableOptions) {
|
|
|
197
143
|
* Format the summary section.
|
|
198
144
|
*/
|
|
199
145
|
function formatSummary(issues, scores, threshold) {
|
|
200
|
-
const useColor = shouldUseColor();
|
|
201
146
|
const lines = [];
|
|
202
147
|
lines.push("");
|
|
203
|
-
lines.push(hr());
|
|
204
|
-
// Summary line
|
|
148
|
+
lines.push(text.hr(Math.min(getTerminalWidth(), 80)));
|
|
205
149
|
const summary = formatIssueSummary(issues);
|
|
206
150
|
lines.push(summary);
|
|
207
|
-
// Pass/fail status
|
|
208
151
|
const overall = getOverallScore(scores);
|
|
209
152
|
const hasErrors = issues.some((i) => i.severity?.toLowerCase() === "critical" || i.severity?.toLowerCase() === "error");
|
|
210
153
|
let status;
|
|
@@ -223,50 +166,35 @@ function formatSummary(issues, scores, threshold) {
|
|
|
223
166
|
passed = !hasErrors;
|
|
224
167
|
status = passed ? "PASSED" : "FAILED";
|
|
225
168
|
}
|
|
226
|
-
|
|
227
|
-
status = passed ? chalk.green.bold(status) : chalk.red.bold(status);
|
|
228
|
-
}
|
|
169
|
+
status = passed ? text.success(status) : text.error(status);
|
|
229
170
|
lines.push(status);
|
|
230
171
|
return lines.join("\n");
|
|
231
172
|
}
|
|
232
173
|
/**
|
|
233
174
|
* Format audit result as human-readable string.
|
|
234
|
-
*
|
|
235
|
-
* @param result - Audit result object
|
|
236
|
-
* @param options - Formatting options
|
|
237
|
-
* @returns Formatted string for terminal display
|
|
238
175
|
*/
|
|
239
176
|
export function formatAuditHuman(result, options = {}) {
|
|
240
177
|
const { groupBy = "severity", showScores = true, showSummary = true, maxIssuesPerGroup = 10, tableOptions, } = options;
|
|
241
178
|
const sections = [];
|
|
242
|
-
// Header
|
|
243
179
|
sections.push(formatHeader(result));
|
|
244
|
-
// Handle non-completed audits
|
|
245
180
|
if (result.status !== "completed") {
|
|
246
|
-
const useColor = shouldUseColor();
|
|
247
181
|
sections.push("");
|
|
248
|
-
sections.push(
|
|
249
|
-
? chalk.yellow(`Status: ${result.status || "unknown"}`)
|
|
250
|
-
: `Status: ${result.status || "unknown"}`);
|
|
182
|
+
sections.push(text.warning(`Status: ${result.status || "unknown"}`));
|
|
251
183
|
if (typeof result.progress === "number") {
|
|
252
184
|
sections.push(`Progress: ${result.progress}%`);
|
|
253
185
|
}
|
|
254
186
|
return sections.join("\n");
|
|
255
187
|
}
|
|
256
|
-
// Scores section
|
|
257
188
|
if (showScores) {
|
|
258
189
|
sections.push(formatScoresSection(result.scores));
|
|
259
190
|
}
|
|
260
|
-
// Issues section
|
|
261
191
|
const issues = normalizeIssues(result.issues);
|
|
262
192
|
if (groupBy === "category") {
|
|
263
193
|
sections.push(formatIssuesByCategory(issues, maxIssuesPerGroup, tableOptions));
|
|
264
194
|
}
|
|
265
195
|
else {
|
|
266
|
-
// Default: group by severity
|
|
267
196
|
sections.push(formatIssuesBySeverity(issues, maxIssuesPerGroup, tableOptions));
|
|
268
197
|
}
|
|
269
|
-
// Summary
|
|
270
198
|
if (showSummary) {
|
|
271
199
|
sections.push(formatSummary(issues, result.scores));
|
|
272
200
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command catalog for the `suggest` command.
|
|
3
|
+
*
|
|
4
|
+
* Maps natural-language intents to exact CLI commands.
|
|
5
|
+
* Used for local fuzzy matching before falling back to LLM API.
|
|
6
|
+
*/
|
|
7
|
+
export interface CatalogEntry {
|
|
8
|
+
/** Exact CLI command to run */
|
|
9
|
+
command: string;
|
|
10
|
+
/** Short explanation of what the command does */
|
|
11
|
+
description: string;
|
|
12
|
+
/** Keywords that trigger this entry */
|
|
13
|
+
keywords: string[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Full command catalog for VertaaUX CLI.
|
|
17
|
+
*
|
|
18
|
+
* Each entry has keywords that are matched against user intent
|
|
19
|
+
* using simple substring/word-overlap scoring.
|
|
20
|
+
*/
|
|
21
|
+
export declare const COMMAND_CATALOG: CatalogEntry[];
|
|
22
|
+
/**
|
|
23
|
+
* Score a catalog entry against user intent.
|
|
24
|
+
*
|
|
25
|
+
* Uses a combined scoring approach:
|
|
26
|
+
* - Each exact keyword match earns 1 point (multi-word keywords earn 2)
|
|
27
|
+
* - Partial word overlap earns fractional points
|
|
28
|
+
* - Final score = matchPoints / max(totalWeight, 3) to avoid penalizing
|
|
29
|
+
* entries with many keywords when only a few match.
|
|
30
|
+
*
|
|
31
|
+
* Returns a number between 0 and 1 where higher = better match.
|
|
32
|
+
*/
|
|
33
|
+
export declare function scoreMatch(intent: string, entry: CatalogEntry): number;
|
|
34
|
+
/**
|
|
35
|
+
* Find the best matching command(s) for a user intent.
|
|
36
|
+
*
|
|
37
|
+
* @param intent - Natural language intent from the user
|
|
38
|
+
* @param threshold - Minimum score to include (0-1)
|
|
39
|
+
* @param maxResults - Maximum number of results to return
|
|
40
|
+
* @returns Sorted matches with scores
|
|
41
|
+
*/
|
|
42
|
+
export declare function findMatches(intent: string, threshold?: number, maxResults?: number): Array<{
|
|
43
|
+
entry: CatalogEntry;
|
|
44
|
+
score: number;
|
|
45
|
+
}>;
|
|
46
|
+
//# sourceMappingURL=command-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-catalog.d.ts","sourceRoot":"","sources":["../../src/prompts/command-catalog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,YAAY;IAC3B,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,YAAY,EAwIzC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAuBtE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,SAAS,SAAM,EACf,UAAU,SAAI,GACb,KAAK,CAAC;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAU/C"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command catalog for the `suggest` command.
|
|
3
|
+
*
|
|
4
|
+
* Maps natural-language intents to exact CLI commands.
|
|
5
|
+
* Used for local fuzzy matching before falling back to LLM API.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Full command catalog for VertaaUX CLI.
|
|
9
|
+
*
|
|
10
|
+
* Each entry has keywords that are matched against user intent
|
|
11
|
+
* using simple substring/word-overlap scoring.
|
|
12
|
+
*/
|
|
13
|
+
export const COMMAND_CATALOG = [
|
|
14
|
+
// --- Audit Commands ---
|
|
15
|
+
{
|
|
16
|
+
command: "vertaa audit <url> --wait",
|
|
17
|
+
description: "Run a UX audit on a URL and wait for results",
|
|
18
|
+
keywords: ["audit", "scan", "check", "test", "run", "url", "website", "page", "site"],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
command: "vertaa audit <url> --mode standard --wait",
|
|
22
|
+
description: "Run a standard-depth audit (more thorough than basic)",
|
|
23
|
+
keywords: ["standard", "thorough", "detailed", "full", "deep scan"],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
command: "vertaa audit <url> --mode deep --wait",
|
|
27
|
+
description: "Run a deep audit with maximum coverage",
|
|
28
|
+
keywords: ["deep", "comprehensive", "maximum", "everything", "all checks"],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
command: "vertaa audit <url> --wait --json",
|
|
32
|
+
description: "Run an audit and output JSON for piping to other commands",
|
|
33
|
+
keywords: ["json", "pipe", "machine", "ci", "scripting", "output json", "structured"],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
command: "vertaa audit <url> --wait --fail-on-score 80",
|
|
37
|
+
description: "Run audit and fail CI if score is below 80",
|
|
38
|
+
keywords: ["ci", "gate", "fail", "threshold", "score", "pipeline", "quality gate"],
|
|
39
|
+
},
|
|
40
|
+
// --- Accessibility ---
|
|
41
|
+
{
|
|
42
|
+
command: "vertaa a11y <url> --wait",
|
|
43
|
+
description: "Run accessibility-focused audit",
|
|
44
|
+
keywords: ["accessibility", "a11y", "wcag", "aria", "screen reader", "accessible"],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
command: "vertaa audit <url> --wait --json | vertaa explain",
|
|
48
|
+
description: "Audit a site and get an AI explanation of findings",
|
|
49
|
+
keywords: ["explain", "understand", "what", "why", "summary", "meaning"],
|
|
50
|
+
},
|
|
51
|
+
// --- Contrast & Color ---
|
|
52
|
+
{
|
|
53
|
+
command: "vertaa audit <url> --wait --json | vertaa triage",
|
|
54
|
+
description: "Audit and prioritize findings by severity",
|
|
55
|
+
keywords: ["contrast", "color", "triage", "prioritize", "priority", "important", "critical", "p0"],
|
|
56
|
+
},
|
|
57
|
+
// --- Compare ---
|
|
58
|
+
{
|
|
59
|
+
command: "vertaa compare <urlA> <urlB> --wait",
|
|
60
|
+
description: "Compare UX audits of two URLs",
|
|
61
|
+
keywords: ["compare", "diff", "versus", "vs", "difference", "before after", "regression"],
|
|
62
|
+
},
|
|
63
|
+
// --- Explain ---
|
|
64
|
+
{
|
|
65
|
+
command: "vertaa explain <finding-id> --job <job-id>",
|
|
66
|
+
description: "Show detailed evidence for a specific finding",
|
|
67
|
+
keywords: ["explain", "finding", "evidence", "detail", "issue", "specific"],
|
|
68
|
+
},
|
|
69
|
+
// --- Triage ---
|
|
70
|
+
{
|
|
71
|
+
command: "vertaa audit <url> --wait --json | vertaa triage",
|
|
72
|
+
description: "Prioritize audit findings into P0/P1/P2 buckets with effort estimates",
|
|
73
|
+
keywords: ["triage", "prioritize", "priority", "bucket", "effort", "plan", "what first"],
|
|
74
|
+
},
|
|
75
|
+
// --- Fix ---
|
|
76
|
+
{
|
|
77
|
+
command: "vertaa fix <jobId> --issue <id> --file-content \"...\"",
|
|
78
|
+
description: "Generate an auto-fix patch for a specific issue",
|
|
79
|
+
keywords: ["fix", "patch", "auto-fix", "repair", "resolve", "remediate"],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
command: "vertaa fix-all <jobId> --file-content \"...\"",
|
|
83
|
+
description: "Generate fix patches for all issues in an audit",
|
|
84
|
+
keywords: ["fix all", "batch", "all issues", "bulk fix"],
|
|
85
|
+
},
|
|
86
|
+
// --- Diff ---
|
|
87
|
+
{
|
|
88
|
+
command: "vertaa diff --job-a <id> --job-b <id>",
|
|
89
|
+
description: "Compare two audit jobs to see what changed",
|
|
90
|
+
keywords: ["diff", "delta", "change", "compare jobs", "what changed"],
|
|
91
|
+
},
|
|
92
|
+
// --- Baseline ---
|
|
93
|
+
{
|
|
94
|
+
command: "vertaa baseline save",
|
|
95
|
+
description: "Save current audit results as a baseline for future comparison",
|
|
96
|
+
keywords: ["baseline", "save", "snapshot", "reference", "lock"],
|
|
97
|
+
},
|
|
98
|
+
// --- Policy ---
|
|
99
|
+
{
|
|
100
|
+
command: "vertaa policy show",
|
|
101
|
+
description: "Show the current audit policy configuration",
|
|
102
|
+
keywords: ["policy", "rules", "config", "configuration", "show policy"],
|
|
103
|
+
},
|
|
104
|
+
// --- Init & Setup ---
|
|
105
|
+
{
|
|
106
|
+
command: "vertaa init",
|
|
107
|
+
description: "Initialize a new VertaaUX project with configuration file",
|
|
108
|
+
keywords: ["init", "setup", "start", "new", "configure", "initialize", "create config"],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
command: "vertaa login",
|
|
112
|
+
description: "Authenticate with VertaaUX API",
|
|
113
|
+
keywords: ["login", "auth", "authenticate", "sign in", "connect", "api key"],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
command: "vertaa doctor",
|
|
117
|
+
description: "Run diagnostics on CLI configuration and connectivity",
|
|
118
|
+
keywords: ["doctor", "diagnostic", "health", "check", "debug", "troubleshoot", "problem"],
|
|
119
|
+
},
|
|
120
|
+
// --- Comment ---
|
|
121
|
+
{
|
|
122
|
+
command: "vertaa comment --job <id> --github-pr <number>",
|
|
123
|
+
description: "Post audit results as a GitHub PR comment",
|
|
124
|
+
keywords: ["comment", "pr", "pull request", "github", "gitlab", "post"],
|
|
125
|
+
},
|
|
126
|
+
// --- Upload/Download ---
|
|
127
|
+
{
|
|
128
|
+
command: "vertaa upload --file baseline.json",
|
|
129
|
+
description: "Upload a baseline file to the VertaaUX API",
|
|
130
|
+
keywords: ["upload", "push", "send"],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
command: "vertaa download --job <id> --output results.json",
|
|
134
|
+
description: "Download audit results to a local file",
|
|
135
|
+
keywords: ["download", "pull", "fetch", "get", "save results"],
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
/**
|
|
139
|
+
* Score a catalog entry against user intent.
|
|
140
|
+
*
|
|
141
|
+
* Uses a combined scoring approach:
|
|
142
|
+
* - Each exact keyword match earns 1 point (multi-word keywords earn 2)
|
|
143
|
+
* - Partial word overlap earns fractional points
|
|
144
|
+
* - Final score = matchPoints / max(totalWeight, 3) to avoid penalizing
|
|
145
|
+
* entries with many keywords when only a few match.
|
|
146
|
+
*
|
|
147
|
+
* Returns a number between 0 and 1 where higher = better match.
|
|
148
|
+
*/
|
|
149
|
+
export function scoreMatch(intent, entry) {
|
|
150
|
+
const lower = intent.toLowerCase();
|
|
151
|
+
const words = lower.split(/\s+/).filter(Boolean);
|
|
152
|
+
let matchPoints = 0;
|
|
153
|
+
for (const keyword of entry.keywords) {
|
|
154
|
+
const kw = keyword.toLowerCase();
|
|
155
|
+
const weight = kw.includes(" ") ? 2 : 1;
|
|
156
|
+
if (lower.includes(kw)) {
|
|
157
|
+
matchPoints += weight;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// Partial word overlap
|
|
161
|
+
const kwWords = kw.split(/\s+/);
|
|
162
|
+
const overlap = kwWords.filter((w) => words.includes(w)).length / kwWords.length;
|
|
163
|
+
matchPoints += weight * overlap * 0.5;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Normalize: divide by a minimum of 3 so that 1 exact match = 0.33 (above threshold)
|
|
167
|
+
const normalizer = Math.max(entry.keywords.length, 3);
|
|
168
|
+
return normalizer > 0 ? Math.min(matchPoints / normalizer, 1) : 0;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Find the best matching command(s) for a user intent.
|
|
172
|
+
*
|
|
173
|
+
* @param intent - Natural language intent from the user
|
|
174
|
+
* @param threshold - Minimum score to include (0-1)
|
|
175
|
+
* @param maxResults - Maximum number of results to return
|
|
176
|
+
* @returns Sorted matches with scores
|
|
177
|
+
*/
|
|
178
|
+
export function findMatches(intent, threshold = 0.1, maxResults = 3) {
|
|
179
|
+
const scored = COMMAND_CATALOG.map((entry) => ({
|
|
180
|
+
entry,
|
|
181
|
+
score: scoreMatch(intent, entry),
|
|
182
|
+
}));
|
|
183
|
+
return scored
|
|
184
|
+
.filter((m) => m.score >= threshold)
|
|
185
|
+
.sort((a, b) => b.score - a.score)
|
|
186
|
+
.slice(0, maxResults);
|
|
187
|
+
}
|
package/dist/ui/spinner.d.ts
CHANGED
|
@@ -1,61 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Progress spinner wrapper for CLI.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Delegates to @vertaaux/tui for consistent terminal rendering.
|
|
5
|
+
* Writes ONLY to stderr — never pollutes stdout.
|
|
6
6
|
*/
|
|
7
|
-
import { type
|
|
8
|
-
export
|
|
9
|
-
/** Initial text to display */
|
|
10
|
-
text: string;
|
|
11
|
-
/** Color for the spinner (default: brand lime) */
|
|
12
|
-
color?: string;
|
|
13
|
-
}
|
|
7
|
+
import { type SpinnerInstance } from "@vertaaux/tui";
|
|
8
|
+
export type { SpinnerInstance };
|
|
14
9
|
/**
|
|
15
10
|
* Create a new spinner instance.
|
|
16
11
|
*
|
|
17
12
|
* Spinner only displays in TTY mode. In non-TTY environments,
|
|
18
13
|
* returns a no-op spinner that still tracks state.
|
|
19
|
-
*
|
|
20
|
-
* @param text - Initial text to display next to spinner
|
|
21
|
-
* @returns An ora spinner instance
|
|
22
14
|
*/
|
|
23
|
-
export declare function createSpinner(text: string):
|
|
15
|
+
export declare function createSpinner(text: string): SpinnerInstance;
|
|
24
16
|
/**
|
|
25
17
|
* Update spinner text with optional progress indicator.
|
|
26
|
-
*
|
|
27
|
-
* @param spinner - The spinner instance to update
|
|
28
|
-
* @param text - New text to display
|
|
29
|
-
* @param current - Current progress count (optional)
|
|
30
|
-
* @param total - Total items count (optional)
|
|
31
18
|
*/
|
|
32
|
-
export declare function updateSpinner(spinner:
|
|
19
|
+
export declare function updateSpinner(spinner: SpinnerInstance, text: string, current?: number, total?: number): void;
|
|
33
20
|
/**
|
|
34
21
|
* Complete spinner with success state.
|
|
35
|
-
*
|
|
36
|
-
* @param spinner - The spinner instance
|
|
37
|
-
* @param text - Success message to display
|
|
38
22
|
*/
|
|
39
|
-
export declare function succeedSpinner(spinner:
|
|
23
|
+
export declare function succeedSpinner(spinner: SpinnerInstance, text: string): void;
|
|
40
24
|
/**
|
|
41
25
|
* Complete spinner with failure state.
|
|
42
|
-
*
|
|
43
|
-
* @param spinner - The spinner instance
|
|
44
|
-
* @param text - Failure message to display
|
|
45
26
|
*/
|
|
46
|
-
export declare function failSpinner(spinner:
|
|
27
|
+
export declare function failSpinner(spinner: SpinnerInstance, text: string): void;
|
|
47
28
|
/**
|
|
48
29
|
* Complete spinner with warning state.
|
|
49
|
-
*
|
|
50
|
-
* @param spinner - The spinner instance
|
|
51
|
-
* @param text - Warning message to display
|
|
52
30
|
*/
|
|
53
|
-
export declare function warnSpinner(spinner:
|
|
31
|
+
export declare function warnSpinner(spinner: SpinnerInstance, text: string): void;
|
|
54
32
|
/**
|
|
55
33
|
* Complete spinner with info state.
|
|
56
|
-
*
|
|
57
|
-
* @param spinner - The spinner instance
|
|
58
|
-
* @param text - Info message to display
|
|
59
34
|
*/
|
|
60
|
-
export declare function infoSpinner(spinner:
|
|
35
|
+
export declare function infoSpinner(spinner: SpinnerInstance, text: string): void;
|
|
61
36
|
//# sourceMappingURL=spinner.d.ts.map
|
package/dist/ui/spinner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAE3D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CAQN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE3E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAExE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAExE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAExE"}
|