@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.
- package/CHANGELOG.md +97 -0
- package/MIGRATION.md +239 -0
- package/README.md +34 -16
- package/dist/app/interactive-app.d.ts +101 -0
- package/dist/app/interactive-app.d.ts.map +1 -0
- package/dist/app/interactive-app.js +309 -0
- package/dist/app/layout/canvas.d.ts +23 -0
- package/dist/app/layout/canvas.d.ts.map +1 -0
- package/dist/app/layout/canvas.js +36 -0
- package/dist/app/layout/footer.d.ts +31 -0
- package/dist/app/layout/footer.d.ts.map +1 -0
- package/dist/app/layout/footer.js +41 -0
- package/dist/app/layout/header.d.ts +20 -0
- package/dist/app/layout/header.d.ts.map +1 -0
- package/dist/app/layout/header.js +27 -0
- package/dist/app/menu/categories.d.ts +20 -0
- package/dist/app/menu/categories.d.ts.map +1 -0
- package/dist/app/menu/categories.js +181 -0
- package/dist/app/menu/filter.d.ts +17 -0
- package/dist/app/menu/filter.d.ts.map +1 -0
- package/dist/app/menu/filter.js +33 -0
- package/dist/app/menu/menu-view.d.ts +35 -0
- package/dist/app/menu/menu-view.d.ts.map +1 -0
- package/dist/app/menu/menu-view.js +230 -0
- package/dist/app/menu/recent.d.ts +24 -0
- package/dist/app/menu/recent.d.ts.map +1 -0
- package/dist/app/menu/recent.js +49 -0
- package/dist/app/types.d.ts +43 -0
- package/dist/app/types.d.ts.map +1 -0
- package/dist/app/types.js +7 -0
- package/dist/app/views/command-runner.d.ts +36 -0
- package/dist/app/views/command-runner.d.ts.map +1 -0
- package/dist/app/views/command-runner.js +372 -0
- package/dist/app/views/help-overlay.d.ts +21 -0
- package/dist/app/views/help-overlay.d.ts.map +1 -0
- package/dist/app/views/help-overlay.js +45 -0
- package/dist/auth/ci-token.d.ts +14 -2
- package/dist/auth/ci-token.d.ts.map +1 -1
- package/dist/auth/ci-token.js +15 -30
- package/dist/auth/device-flow.d.ts +2 -1
- package/dist/auth/device-flow.d.ts.map +1 -1
- package/dist/auth/device-flow.js +13 -10
- package/dist/auth/token-store.d.ts.map +1 -1
- package/dist/auth/token-store.js +12 -2
- package/dist/baseline/diff.d.ts +2 -2
- package/dist/baseline/diff.d.ts.map +1 -1
- package/dist/baseline/diff.js +15 -34
- package/dist/commands/a11y.d.ts +9 -0
- package/dist/commands/a11y.d.ts.map +1 -0
- package/dist/commands/a11y.js +76 -0
- package/dist/commands/audit/artifacts.d.ts +27 -0
- package/dist/commands/audit/artifacts.d.ts.map +1 -0
- package/dist/commands/audit/artifacts.js +158 -0
- package/dist/commands/audit/ci-detection.d.ts +18 -0
- package/dist/commands/audit/ci-detection.d.ts.map +1 -0
- package/dist/commands/audit/ci-detection.js +71 -0
- package/dist/commands/audit/explain.d.ts +11 -0
- package/dist/commands/audit/explain.d.ts.map +1 -0
- package/dist/commands/audit/explain.js +45 -0
- package/dist/commands/audit/filters.d.ts +17 -0
- package/dist/commands/audit/filters.d.ts.map +1 -0
- package/dist/commands/audit/filters.js +40 -0
- package/dist/commands/audit/index.d.ts +18 -0
- package/dist/commands/audit/index.d.ts.map +1 -0
- package/dist/commands/audit/index.js +564 -0
- package/dist/commands/audit/output.d.ts +32 -0
- package/dist/commands/audit/output.d.ts.map +1 -0
- package/dist/commands/audit/output.js +130 -0
- package/dist/commands/audit/policy.d.ts +19 -0
- package/dist/commands/audit/policy.d.ts.map +1 -0
- package/dist/commands/audit/policy.js +102 -0
- package/dist/commands/audit/scoring.d.ts +23 -0
- package/dist/commands/audit/scoring.d.ts.map +1 -0
- package/dist/commands/audit/scoring.js +70 -0
- package/dist/commands/audit/types.d.ts +88 -0
- package/dist/commands/audit/types.d.ts.map +1 -0
- package/dist/commands/audit/types.js +8 -0
- package/dist/commands/audit.d.ts +2 -60
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +2 -1038
- package/dist/commands/baseline.d.ts +1 -0
- package/dist/commands/baseline.d.ts.map +1 -1
- package/dist/commands/baseline.js +205 -121
- package/dist/commands/comment.d.ts +22 -0
- package/dist/commands/comment.d.ts.map +1 -1
- package/dist/commands/comment.js +122 -58
- package/dist/commands/compare.d.ts +17 -0
- package/dist/commands/compare.d.ts.map +1 -1
- package/dist/commands/compare.js +287 -180
- package/dist/commands/diff.d.ts +5 -0
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +168 -141
- package/dist/commands/doc.d.ts +10 -0
- package/dist/commands/doc.d.ts.map +1 -1
- package/dist/commands/doc.js +134 -76
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +164 -17
- package/dist/commands/download.d.ts +10 -0
- package/dist/commands/download.d.ts.map +1 -1
- package/dist/commands/download.js +169 -112
- package/dist/commands/explain.d.ts +5 -0
- package/dist/commands/explain.d.ts.map +1 -1
- package/dist/commands/explain.js +241 -155
- package/dist/commands/fix-all.d.ts +25 -0
- package/dist/commands/fix-all.d.ts.map +1 -0
- package/dist/commands/fix-all.js +206 -0
- package/dist/commands/fix-plan.d.ts +9 -0
- package/dist/commands/fix-plan.d.ts.map +1 -1
- package/dist/commands/fix-plan.js +152 -89
- package/dist/commands/fix.d.ts +17 -0
- package/dist/commands/fix.d.ts.map +1 -0
- package/dist/commands/fix.js +111 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +94 -42
- package/dist/commands/login.d.ts +18 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +268 -95
- package/dist/commands/patch-review.d.ts +11 -0
- package/dist/commands/patch-review.d.ts.map +1 -1
- package/dist/commands/patch-review.js +159 -97
- package/dist/commands/policy.d.ts +31 -0
- package/dist/commands/policy.d.ts.map +1 -1
- package/dist/commands/policy.js +269 -124
- package/dist/commands/release-notes.d.ts +10 -0
- package/dist/commands/release-notes.d.ts.map +1 -1
- package/dist/commands/release-notes.js +127 -73
- package/dist/commands/scan.d.ts +13 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +133 -0
- package/dist/commands/status.d.ts +9 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +81 -0
- package/dist/commands/suggest.d.ts +10 -0
- package/dist/commands/suggest.d.ts.map +1 -1
- package/dist/commands/suggest.js +153 -82
- package/dist/commands/triage.d.ts +35 -0
- package/dist/commands/triage.d.ts.map +1 -1
- package/dist/commands/triage.js +206 -81
- package/dist/commands/upload.d.ts +9 -0
- package/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +140 -101
- package/dist/commands/verify.d.ts +13 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +118 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +125 -990
- package/dist/interactive/fix-wizard.d.ts +3 -0
- package/dist/interactive/fix-wizard.d.ts.map +1 -1
- package/dist/interactive/fix-wizard.js +130 -112
- package/dist/interactive/init-wizard.d.ts +3 -1
- package/dist/interactive/init-wizard.d.ts.map +1 -1
- package/dist/interactive/init-wizard.js +207 -138
- package/dist/interactive/prompts.d.ts +7 -3
- package/dist/interactive/prompts.d.ts.map +1 -1
- package/dist/interactive/prompts.js +44 -23
- package/dist/output/envelope.d.ts +2 -0
- package/dist/output/envelope.d.ts.map +1 -1
- package/dist/output/envelope.js +18 -2
- package/dist/output/factory.d.ts +9 -1
- package/dist/output/factory.d.ts.map +1 -1
- package/dist/output/html.d.ts +2 -1
- package/dist/output/html.d.ts.map +1 -1
- package/dist/output/html.js +3 -2
- package/dist/output/human.d.ts +9 -1
- package/dist/output/human.d.ts.map +1 -1
- package/dist/output/human.js +17 -2
- package/dist/output/json.d.ts +2 -1
- package/dist/output/json.d.ts.map +1 -1
- package/dist/output/junit.d.ts +2 -1
- package/dist/output/junit.d.ts.map +1 -1
- package/dist/output/sarif.d.ts +2 -1
- package/dist/output/sarif.d.ts.map +1 -1
- package/dist/types.d.ts +74 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/ui/banner.d.ts +34 -0
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +97 -5
- package/dist/ui/diagnostics.d.ts +9 -4
- package/dist/ui/diagnostics.d.ts.map +1 -1
- package/dist/ui/diagnostics.js +32 -82
- package/dist/ui/strings.d.ts +373 -0
- package/dist/ui/strings.d.ts.map +1 -0
- package/dist/ui/strings.js +499 -0
- package/dist/ui/table.d.ts +0 -2
- package/dist/ui/table.d.ts.map +1 -1
- package/dist/ui/table.js +3 -4
- package/dist/utils/api-client.d.ts +46 -0
- package/dist/utils/api-client.d.ts.map +1 -0
- package/dist/utils/api-client.js +170 -0
- package/dist/utils/client.d.ts +29 -18
- package/dist/utils/client.d.ts.map +1 -1
- package/dist/utils/client.js +102 -12
- package/dist/utils/formatters.d.ts +38 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/formatters.js +277 -0
- package/dist/utils/local-capture.d.ts +25 -0
- package/dist/utils/local-capture.d.ts.map +1 -0
- package/dist/utils/local-capture.js +57 -0
- package/dist/utils/url-classify.d.ts +18 -0
- package/dist/utils/url-classify.d.ts.map +1 -0
- package/dist/utils/url-classify.js +106 -0
- package/node_modules/@vertaaux/tui/dist/index.cjs +713 -20
- package/node_modules/@vertaaux/tui/dist/index.cjs.map +1 -1
- package/node_modules/@vertaaux/tui/dist/index.d.cts +361 -4
- package/node_modules/@vertaaux/tui/dist/index.d.ts +361 -4
- package/node_modules/@vertaaux/tui/dist/index.js +689 -21
- package/node_modules/@vertaaux/tui/dist/index.js.map +1 -1
- package/package.json +13 -5
- package/dist/commands/client.d.ts +0 -14
- package/dist/commands/client.d.ts.map +0 -1
- package/dist/commands/client.js +0 -362
- package/dist/commands/drift.d.ts +0 -15
- package/dist/commands/drift.d.ts.map +0 -1
- package/dist/commands/drift.js +0 -309
- package/dist/commands/protect.d.ts +0 -16
- package/dist/commands/protect.d.ts.map +0 -1
- package/dist/commands/protect.js +0 -323
- package/dist/commands/report.d.ts +0 -15
- package/dist/commands/report.d.ts.map +0 -1
- package/dist/commands/report.js +0 -214
- package/dist/policy/sync.d.ts +0 -67
- package/dist/policy/sync.d.ts.map +0 -1
- package/dist/policy/sync.js +0 -147
|
@@ -12,28 +12,28 @@
|
|
|
12
12
|
* vertaa release-notes --file diff.json
|
|
13
13
|
* vertaa release-notes --job-a abc --job-b def
|
|
14
14
|
*/
|
|
15
|
-
import
|
|
15
|
+
import { bold, dim, boldColor, brand, renderError, createRenderer, runSteps } from "@vertaaux/tui";
|
|
16
16
|
import { ExitCode } from "../utils/exit-codes.js";
|
|
17
17
|
import { resolveApiBase, getApiKey, apiRequest } from "../utils/client.js";
|
|
18
18
|
import { resolveConfig } from "../config/loader.js";
|
|
19
19
|
import { writeJsonOutput, writeOutput } from "../output/envelope.js";
|
|
20
20
|
import { resolveCommandFormat } from "../output/formats.js";
|
|
21
|
-
import { createSpinner, succeedSpinner } from "../ui/spinner.js";
|
|
22
21
|
import { readJsonInput } from "../utils/stdin.js";
|
|
23
|
-
import {
|
|
22
|
+
import { AI_TIMEOUT_MS } from "../utils/ai-error.js";
|
|
23
|
+
import { strings } from "../ui/strings.js";
|
|
24
24
|
// ---------------------------------------------------------------------------
|
|
25
25
|
// Formatters
|
|
26
26
|
// ---------------------------------------------------------------------------
|
|
27
27
|
function formatReleaseNotesHuman(data) {
|
|
28
28
|
const lines = [];
|
|
29
|
-
lines.push(
|
|
29
|
+
lines.push(bold(data.headline));
|
|
30
30
|
lines.push("");
|
|
31
|
-
lines.push(
|
|
32
|
-
lines.push(
|
|
31
|
+
lines.push(boldColor("Developer Notes", brand.teal));
|
|
32
|
+
lines.push(dim("─".repeat(40)));
|
|
33
33
|
lines.push(data.developer_notes);
|
|
34
34
|
lines.push("");
|
|
35
|
-
lines.push(
|
|
36
|
-
lines.push(
|
|
35
|
+
lines.push(boldColor("PM / User-Facing Notes", brand.lime));
|
|
36
|
+
lines.push(dim("─".repeat(40)));
|
|
37
37
|
lines.push(data.pm_notes);
|
|
38
38
|
return lines.join("\n");
|
|
39
39
|
}
|
|
@@ -50,6 +50,111 @@ function formatReleaseNotesMarkdown(data) {
|
|
|
50
50
|
lines.push(data.pm_notes);
|
|
51
51
|
return lines.join("\n");
|
|
52
52
|
}
|
|
53
|
+
export async function handleReleaseNotes(opts) {
|
|
54
|
+
const config = { apiKey: opts.apiKey };
|
|
55
|
+
const format = resolveCommandFormat("release-notes", opts.format, opts.machine || false);
|
|
56
|
+
const renderer = createRenderer("auto");
|
|
57
|
+
const baseState = {
|
|
58
|
+
phase: "release-notes",
|
|
59
|
+
phaseIndex: 1,
|
|
60
|
+
phaseTotal: 2,
|
|
61
|
+
url: "",
|
|
62
|
+
mode: "release-notes",
|
|
63
|
+
progress: {},
|
|
64
|
+
totals: {},
|
|
65
|
+
issueCount: 0,
|
|
66
|
+
scorePreview: null,
|
|
67
|
+
verbose: false,
|
|
68
|
+
elapsed: 0,
|
|
69
|
+
};
|
|
70
|
+
const startTime = Date.now();
|
|
71
|
+
let responseData = null;
|
|
72
|
+
const steps = [
|
|
73
|
+
{
|
|
74
|
+
id: "fetch",
|
|
75
|
+
actionText: strings.releaseNotes.generate.action,
|
|
76
|
+
summaryText: "History loaded",
|
|
77
|
+
run: async () => {
|
|
78
|
+
let diffPayload;
|
|
79
|
+
if (opts.jobA && opts.jobB) {
|
|
80
|
+
const base = resolveApiBase(opts.base);
|
|
81
|
+
const apiKey = getApiKey(config.apiKey);
|
|
82
|
+
const diffResult = await apiRequest(base, `/diff?job_a=${encodeURIComponent(opts.jobA)}&job_b=${encodeURIComponent(opts.jobB)}`, { method: "GET" }, apiKey);
|
|
83
|
+
diffPayload = diffResult.data;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const input = await readJsonInput(opts.file);
|
|
87
|
+
if (!input) {
|
|
88
|
+
throw new Error("No diff data provided.\nUsage:\n vertaa diff --job-a abc --job-b def --json | vertaa release-notes\n vertaa release-notes --file diff.json\n vertaa release-notes --job-a abc --job-b def");
|
|
89
|
+
}
|
|
90
|
+
const data = input;
|
|
91
|
+
const innerData = (data.data && typeof data.data === "object" ? data.data : data);
|
|
92
|
+
if (!Array.isArray(innerData.new) || !Array.isArray(innerData.fixed)) {
|
|
93
|
+
throw new Error("Invalid diff data. Expected { new: [...], fixed: [...], summary: {...} }\nPipe from: vertaa diff --job-a abc --job-b def --json | vertaa release-notes");
|
|
94
|
+
}
|
|
95
|
+
diffPayload = {
|
|
96
|
+
new: innerData.new,
|
|
97
|
+
fixed: innerData.fixed,
|
|
98
|
+
present: innerData.present || null,
|
|
99
|
+
summary: innerData.summary || {
|
|
100
|
+
newCount: innerData.new.length,
|
|
101
|
+
fixedCount: innerData.fixed.length,
|
|
102
|
+
presentCount: Array.isArray(innerData.present) ? innerData.present.length : null,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const base = resolveApiBase(opts.base);
|
|
107
|
+
const apiKey = getApiKey(config.apiKey);
|
|
108
|
+
const response = await Promise.race([
|
|
109
|
+
apiRequest(base, "/cli/ai/release-notes", { method: "POST", body: { diff: diffPayload } }, apiKey),
|
|
110
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("LLM request timed out")), AI_TIMEOUT_MS)),
|
|
111
|
+
]);
|
|
112
|
+
responseData = response.data;
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: "generate",
|
|
117
|
+
actionText: "Generating release notes...",
|
|
118
|
+
summaryText: strings.releaseNotes.generate.done(),
|
|
119
|
+
run: async () => {
|
|
120
|
+
// Notes generated in fetch step via API call
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
];
|
|
124
|
+
const { success, states } = await runSteps(steps, {
|
|
125
|
+
onStateChange: (stepStates) => {
|
|
126
|
+
renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
renderer.finish({
|
|
130
|
+
url: "",
|
|
131
|
+
mode: "release-notes",
|
|
132
|
+
overallScore: success ? 100 : 0,
|
|
133
|
+
scores: {},
|
|
134
|
+
issueCount: 0,
|
|
135
|
+
passed: success,
|
|
136
|
+
elapsed: Date.now() - startTime,
|
|
137
|
+
});
|
|
138
|
+
if (!success) {
|
|
139
|
+
const failed = states.find(s => s.status === "failed");
|
|
140
|
+
process.stderr.write(renderError({
|
|
141
|
+
message: failed?.failReason || "Command failed",
|
|
142
|
+
suggestion: "vertaa doctor",
|
|
143
|
+
}) + "\n");
|
|
144
|
+
process.exitCode = ExitCode.ERROR;
|
|
145
|
+
}
|
|
146
|
+
if (success && responseData) {
|
|
147
|
+
if (format === "json") {
|
|
148
|
+
writeJsonOutput(responseData, "release-notes");
|
|
149
|
+
}
|
|
150
|
+
else if (format === "markdown") {
|
|
151
|
+
writeOutput(formatReleaseNotesMarkdown(responseData));
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
writeOutput(formatReleaseNotesHuman(responseData));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
53
158
|
// ---------------------------------------------------------------------------
|
|
54
159
|
// Command Registration
|
|
55
160
|
// ---------------------------------------------------------------------------
|
|
@@ -72,73 +177,22 @@ Examples:
|
|
|
72
177
|
const globalOpts = command.optsWithGlobals();
|
|
73
178
|
const config = await resolveConfig(globalOpts.config);
|
|
74
179
|
const machineMode = globalOpts.machine || false;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
// Read from stdin or --file
|
|
87
|
-
const input = await readJsonInput(options.file);
|
|
88
|
-
if (!input) {
|
|
89
|
-
console.error("Error: No diff data provided.");
|
|
90
|
-
console.error("Usage:");
|
|
91
|
-
console.error(" vertaa diff --job-a abc --job-b def --json | vertaa release-notes");
|
|
92
|
-
console.error(" vertaa release-notes --file diff.json");
|
|
93
|
-
console.error(" vertaa release-notes --job-a abc --job-b def");
|
|
94
|
-
process.exit(ExitCode.ERROR);
|
|
95
|
-
}
|
|
96
|
-
const data = input;
|
|
97
|
-
const innerData = (data.data && typeof data.data === "object" ? data.data : data);
|
|
98
|
-
// Validate shape
|
|
99
|
-
if (!Array.isArray(innerData.new) || !Array.isArray(innerData.fixed)) {
|
|
100
|
-
console.error("Error: Invalid diff data. Expected { new: [...], fixed: [...], summary: {...} }");
|
|
101
|
-
console.error("Pipe from: vertaa diff --job-a abc --job-b def --json | vertaa release-notes");
|
|
102
|
-
process.exit(ExitCode.ERROR);
|
|
103
|
-
}
|
|
104
|
-
diffPayload = {
|
|
105
|
-
new: innerData.new,
|
|
106
|
-
fixed: innerData.fixed,
|
|
107
|
-
present: innerData.present || null,
|
|
108
|
-
summary: innerData.summary || {
|
|
109
|
-
newCount: innerData.new.length,
|
|
110
|
-
fixedCount: innerData.fixed.length,
|
|
111
|
-
presentCount: Array.isArray(innerData.present) ? innerData.present.length : null,
|
|
112
|
-
},
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
// Auth check
|
|
116
|
-
const base = resolveApiBase(globalOpts.base);
|
|
117
|
-
const apiKey = getApiKey(config.apiKey);
|
|
118
|
-
// Call LLM release-notes API
|
|
119
|
-
const spinner = createSpinner("Generating release notes...");
|
|
120
|
-
try {
|
|
121
|
-
const response = await Promise.race([
|
|
122
|
-
apiRequest(base, "/cli/ai/release-notes", { method: "POST", body: { diff: diffPayload } }, apiKey),
|
|
123
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error("LLM request timed out")), AI_TIMEOUT_MS)),
|
|
124
|
-
]);
|
|
125
|
-
succeedSpinner(spinner, "Notes ready");
|
|
126
|
-
if (format === "json") {
|
|
127
|
-
writeJsonOutput(response.data, "release-notes");
|
|
128
|
-
}
|
|
129
|
-
else if (format === "markdown") {
|
|
130
|
-
writeOutput(formatReleaseNotesMarkdown(response.data));
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
writeOutput(formatReleaseNotesHuman(response.data));
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
catch (error) {
|
|
137
|
-
handleAiCommandError(error, "release-notes", spinner);
|
|
138
|
-
}
|
|
180
|
+
await handleReleaseNotes({
|
|
181
|
+
file: options.file,
|
|
182
|
+
jobA: options.jobA,
|
|
183
|
+
jobB: options.jobB,
|
|
184
|
+
format: options.format,
|
|
185
|
+
base: globalOpts.base,
|
|
186
|
+
machine: machineMode,
|
|
187
|
+
apiKey: config.apiKey,
|
|
188
|
+
});
|
|
139
189
|
}
|
|
140
190
|
catch (error) {
|
|
141
|
-
|
|
191
|
+
process.stderr.write(renderError({
|
|
192
|
+
message: error instanceof Error ? error.message : String(error),
|
|
193
|
+
suggestion: "vertaa audit <url>",
|
|
194
|
+
exitCode: ExitCode.ERROR,
|
|
195
|
+
}) + "\n");
|
|
142
196
|
process.exit(ExitCode.ERROR);
|
|
143
197
|
}
|
|
144
198
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy scan command handler + shared runAuditCommand implementation.
|
|
3
|
+
* Provides the `scan` alias for audit and the shared audit runner for a11y/scan commands.
|
|
4
|
+
*/
|
|
5
|
+
import type { Command } from "commander";
|
|
6
|
+
import type { Flags } from "../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Shared audit runner used by a11y, scan, and related legacy commands.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runAuditCommand(base: string, url: string, flags: Flags, label: "audit" | "scan" | "a11y"): Promise<void>;
|
|
11
|
+
export declare function handleScan(rawUrl: string, cmdOptions: Flags): Promise<void>;
|
|
12
|
+
export declare function registerScanCommand(program: Command): void;
|
|
13
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBzC,OAAO,KAAK,EAAE,KAAK,EAAiB,MAAM,aAAa,CAAC;AAExD;;GAEG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,iBA8DjC;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDjF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuB1D"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy scan command handler + shared runAuditCommand implementation.
|
|
3
|
+
* Provides the `scan` alias for audit and the shared audit runner for a11y/scan commands.
|
|
4
|
+
*/
|
|
5
|
+
import { renderError, runSteps, createRenderer } from "@vertaaux/tui";
|
|
6
|
+
import { ExitCode } from "../utils/exit-codes.js";
|
|
7
|
+
import { parseMode, parseTimeout, parseInterval, parseScore } from "../utils/validators.js";
|
|
8
|
+
import { resolveApiBase, getString, getBool, getNumber, resolveFormat, createClient, } from "../utils/api-client.js";
|
|
9
|
+
import { waitForAudit } from "../utils/client.js";
|
|
10
|
+
import { normalizeIssues, getCategoryScore, getOverallScore, formatA11yMarkdown, formatAuditMarkdown, printOutput, } from "../utils/formatters.js";
|
|
11
|
+
/**
|
|
12
|
+
* Shared audit runner used by a11y, scan, and related legacy commands.
|
|
13
|
+
*/
|
|
14
|
+
export async function runAuditCommand(base, url, flags, label) {
|
|
15
|
+
const mode = getString(flags, "mode") || "basic";
|
|
16
|
+
const timeout = getNumber(flags, "timeout");
|
|
17
|
+
const userAgent = getString(flags, "user-agent");
|
|
18
|
+
const engineVersion = getString(flags, "engine-version");
|
|
19
|
+
const failOnScore = getNumber(flags, "fail-on-score");
|
|
20
|
+
// Use SDK typed client for audit creation
|
|
21
|
+
const sdkClient = createClient({ base: getString(flags, "base") });
|
|
22
|
+
const created = await sdkClient.audits.create({
|
|
23
|
+
url,
|
|
24
|
+
mode: mode,
|
|
25
|
+
timeout,
|
|
26
|
+
user_agent: userAgent,
|
|
27
|
+
engine_version: engineVersion,
|
|
28
|
+
fail_on_score: failOnScore,
|
|
29
|
+
});
|
|
30
|
+
const format = resolveFormat(flags);
|
|
31
|
+
if (!getBool(flags, "wait")) {
|
|
32
|
+
const markdown = `## Audit queued\n- Job ID: ${created.job_id}\n- URL: ${created.url}\n- Mode: ${created.mode}`;
|
|
33
|
+
printOutput(format, created, markdown);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!created.job_id) {
|
|
37
|
+
throw new Error("Audit response missing job_id");
|
|
38
|
+
}
|
|
39
|
+
const waitTimeout = getNumber(flags, "timeout") || 60000;
|
|
40
|
+
const interval = getNumber(flags, "interval") || 5000;
|
|
41
|
+
const result = await waitForAudit(sdkClient, created.job_id, waitTimeout, interval);
|
|
42
|
+
if (label === "a11y") {
|
|
43
|
+
const a11yScore = getCategoryScore(result.scores, "accessibility");
|
|
44
|
+
if (failOnScore !== undefined && a11yScore !== null && a11yScore < failOnScore) {
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
}
|
|
47
|
+
const issues = normalizeIssues(result.issues).filter((issue) => {
|
|
48
|
+
const category = (issue.category || "").toLowerCase();
|
|
49
|
+
return (category.includes("accessibility") ||
|
|
50
|
+
category.includes("a11y") ||
|
|
51
|
+
category.includes("wcag"));
|
|
52
|
+
});
|
|
53
|
+
const payload = {
|
|
54
|
+
...result,
|
|
55
|
+
accessibility_score: a11yScore,
|
|
56
|
+
accessibility_issues: issues,
|
|
57
|
+
};
|
|
58
|
+
printOutput(format, payload, formatA11yMarkdown(result));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const overall = getOverallScore(result.scores);
|
|
62
|
+
if (failOnScore !== undefined && overall !== null && overall < failOnScore) {
|
|
63
|
+
process.exitCode = 1;
|
|
64
|
+
}
|
|
65
|
+
printOutput(format, result, formatAuditMarkdown(result));
|
|
66
|
+
}
|
|
67
|
+
export async function handleScan(rawUrl, cmdOptions) {
|
|
68
|
+
const url = /^https?:\/\//i.test(rawUrl) ? rawUrl : `https://${rawUrl}`;
|
|
69
|
+
const renderer = createRenderer("auto");
|
|
70
|
+
const baseState = {
|
|
71
|
+
phase: "scan",
|
|
72
|
+
phaseIndex: 1,
|
|
73
|
+
phaseTotal: 1,
|
|
74
|
+
url,
|
|
75
|
+
mode: "scan",
|
|
76
|
+
progress: {},
|
|
77
|
+
totals: {},
|
|
78
|
+
issueCount: 0,
|
|
79
|
+
scorePreview: null,
|
|
80
|
+
verbose: false,
|
|
81
|
+
elapsed: 0,
|
|
82
|
+
};
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
const steps = [
|
|
85
|
+
{
|
|
86
|
+
id: "scan",
|
|
87
|
+
actionText: "Running UX scan...",
|
|
88
|
+
summaryText: "Scan complete",
|
|
89
|
+
run: async () => {
|
|
90
|
+
const base = resolveApiBase(cmdOptions);
|
|
91
|
+
await runAuditCommand(base, url, { ...cmdOptions, wait: cmdOptions.wait ?? true }, "scan");
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
const { success, states } = await runSteps(steps, {
|
|
96
|
+
failFast: true,
|
|
97
|
+
onStateChange: (stepStates) => {
|
|
98
|
+
renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
renderer.finish({ url, mode: "scan", overallScore: 0, scores: {}, issueCount: 0, passed: success, elapsed: Date.now() - startTime });
|
|
102
|
+
if (!success) {
|
|
103
|
+
const failed = states.find(s => s.status === "failed");
|
|
104
|
+
process.stderr.write(renderError({
|
|
105
|
+
message: failed?.failReason || "Command failed",
|
|
106
|
+
suggestion: "vertaa doctor",
|
|
107
|
+
}) + "\n");
|
|
108
|
+
process.exitCode = ExitCode.ERROR;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export function registerScanCommand(program) {
|
|
112
|
+
program
|
|
113
|
+
.command("scan <url>")
|
|
114
|
+
.description("Run UX scan (alias for audit)")
|
|
115
|
+
.option("--mode <mode>", "Audit depth: basic|standard|deep", parseMode, "basic")
|
|
116
|
+
.option("--wait", "Wait for audit completion")
|
|
117
|
+
.option("--timeout <ms>", "Wait timeout in milliseconds (1-300000)", parseTimeout, 60000)
|
|
118
|
+
.option("--interval <ms>", "Poll interval in milliseconds (1-300000)", parseInterval, 5000)
|
|
119
|
+
.option("--fail-on-score <n>", "Exit non-zero if score below n (0-100)", parseScore)
|
|
120
|
+
.action(async (url, cmdOptions) => {
|
|
121
|
+
try {
|
|
122
|
+
await handleScan(url, cmdOptions);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
process.stderr.write(renderError({
|
|
126
|
+
message: error instanceof Error ? error.message : String(error),
|
|
127
|
+
suggestion: "vertaa audit <url>",
|
|
128
|
+
exitCode: ExitCode.ERROR,
|
|
129
|
+
}) + "\n");
|
|
130
|
+
process.exit(ExitCode.ERROR);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy status command handler.
|
|
3
|
+
* Gets the status of an audit job.
|
|
4
|
+
*/
|
|
5
|
+
import type { Command } from "commander";
|
|
6
|
+
import type { Flags } from "../types.js";
|
|
7
|
+
export declare function handleStatus(jobId: string, cmdOptions: Flags): Promise<void>;
|
|
8
|
+
export declare function registerStatusCommand(program: Command): void;
|
|
9
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDlF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmB5D"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy status command handler.
|
|
3
|
+
* Gets the status of an audit job.
|
|
4
|
+
*/
|
|
5
|
+
import { renderError, runSteps, createRenderer } from "@vertaaux/tui";
|
|
6
|
+
import { ExitCode } from "../utils/exit-codes.js";
|
|
7
|
+
import { parseScore } from "../utils/validators.js";
|
|
8
|
+
import { resolveApiBase, resolveFormat, getNumber, createClient, } from "../utils/api-client.js";
|
|
9
|
+
import { getOverallScore, formatAuditMarkdown, printOutput, } from "../utils/formatters.js";
|
|
10
|
+
export async function handleStatus(jobId, cmdOptions) {
|
|
11
|
+
const renderer = createRenderer("auto");
|
|
12
|
+
const baseState = {
|
|
13
|
+
phase: "status",
|
|
14
|
+
phaseIndex: 1,
|
|
15
|
+
phaseTotal: 1,
|
|
16
|
+
url: "",
|
|
17
|
+
mode: "status",
|
|
18
|
+
progress: {},
|
|
19
|
+
totals: {},
|
|
20
|
+
issueCount: 0,
|
|
21
|
+
scorePreview: null,
|
|
22
|
+
verbose: false,
|
|
23
|
+
elapsed: 0,
|
|
24
|
+
};
|
|
25
|
+
const startTime = Date.now();
|
|
26
|
+
const steps = [
|
|
27
|
+
{
|
|
28
|
+
id: "fetch",
|
|
29
|
+
actionText: "Fetching audit status...",
|
|
30
|
+
summaryText: "Audit status retrieved",
|
|
31
|
+
run: async () => {
|
|
32
|
+
const base = resolveApiBase(cmdOptions);
|
|
33
|
+
const client = createClient({ base: base });
|
|
34
|
+
const result = await client.audits.retrieve(jobId);
|
|
35
|
+
const format = resolveFormat(cmdOptions);
|
|
36
|
+
const overall = getOverallScore(result.scores);
|
|
37
|
+
const payload = { ...result, overall_score: overall };
|
|
38
|
+
const markdown = formatAuditMarkdown(result);
|
|
39
|
+
const failOnScore = getNumber(cmdOptions, "fail-on-score");
|
|
40
|
+
if (failOnScore !== undefined && overall !== null && overall < failOnScore) {
|
|
41
|
+
process.exitCode = 1;
|
|
42
|
+
}
|
|
43
|
+
printOutput(format, payload, markdown);
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
const { success, states } = await runSteps(steps, {
|
|
48
|
+
failFast: true,
|
|
49
|
+
onStateChange: (stepStates) => {
|
|
50
|
+
renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
renderer.finish({ url: "", mode: "status", overallScore: 0, scores: {}, issueCount: 0, passed: success, elapsed: Date.now() - startTime });
|
|
54
|
+
if (!success) {
|
|
55
|
+
const failed = states.find(s => s.status === "failed");
|
|
56
|
+
process.stderr.write(renderError({
|
|
57
|
+
message: failed?.failReason || "Command failed",
|
|
58
|
+
suggestion: "vertaa doctor",
|
|
59
|
+
}) + "\n");
|
|
60
|
+
process.exitCode = ExitCode.ERROR;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function registerStatusCommand(program) {
|
|
64
|
+
program
|
|
65
|
+
.command("status <jobId>")
|
|
66
|
+
.description("Get status of an audit job")
|
|
67
|
+
.option("--fail-on-score <n>", "Exit non-zero if score below n (0-100)", parseScore)
|
|
68
|
+
.action(async (jobId, cmdOptions) => {
|
|
69
|
+
try {
|
|
70
|
+
await handleStatus(jobId, cmdOptions);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
process.stderr.write(renderError({
|
|
74
|
+
message: error instanceof Error ? error.message : String(error),
|
|
75
|
+
suggestion: "vertaa doctor",
|
|
76
|
+
exitCode: ExitCode.ERROR,
|
|
77
|
+
}) + "\n");
|
|
78
|
+
process.exit(ExitCode.ERROR);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
@@ -11,6 +11,16 @@
|
|
|
11
11
|
* vertaa suggest "set up CI quality gate"
|
|
12
12
|
*/
|
|
13
13
|
import { Command } from "commander";
|
|
14
|
+
export interface SuggestCommandOptions {
|
|
15
|
+
intent: string;
|
|
16
|
+
format?: string;
|
|
17
|
+
strict?: boolean;
|
|
18
|
+
continueOnError?: boolean;
|
|
19
|
+
machine?: boolean;
|
|
20
|
+
base?: string;
|
|
21
|
+
apiKey?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function handleSuggest(opts: SuggestCommandOptions): Promise<void>;
|
|
14
24
|
/**
|
|
15
25
|
* Register the suggest command with the Commander program.
|
|
16
26
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../src/commands/suggest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../src/commands/suggest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwDpC,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiJ9E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2C7D"}
|