@vertaaux/cli 0.4.0 → 0.5.1
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 +116 -0
- package/MIGRATION.md +239 -0
- package/README.md +62 -17
- package/dist/app/interactive-app.d.ts +103 -0
- package/dist/app/interactive-app.d.ts.map +1 -0
- package/dist/app/interactive-app.js +328 -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 +166 -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 +415 -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 +46 -0
- package/dist/auth/ci-token.d.ts +8 -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 +11 -0
- package/dist/commands/a11y.d.ts.map +1 -0
- package/dist/commands/a11y.js +149 -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 +589 -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 +129 -0
- package/dist/commands/audit/policy.d.ts +27 -0
- package/dist/commands/audit/policy.d.ts.map +1 -0
- package/dist/commands/audit/policy.js +147 -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 +89 -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 -1097
- package/dist/commands/baseline.d.ts +2 -0
- package/dist/commands/baseline.d.ts.map +1 -1
- package/dist/commands/baseline.js +221 -123
- package/dist/commands/comment.d.ts +22 -0
- package/dist/commands/comment.d.ts.map +1 -1
- package/dist/commands/comment.js +127 -62
- package/dist/commands/compare.d.ts +17 -0
- package/dist/commands/compare.d.ts.map +1 -1
- package/dist/commands/compare.js +288 -181
- package/dist/commands/diff.d.ts +7 -0
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +181 -143
- package/dist/commands/doc.d.ts +10 -0
- package/dist/commands/doc.d.ts.map +1 -1
- package/dist/commands/doc.js +135 -77
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +166 -19
- 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 +242 -156
- 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 +154 -90
- 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 +263 -92
- 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 +160 -98
- package/dist/commands/policy.d.ts +31 -0
- package/dist/commands/policy.d.ts.map +1 -1
- package/dist/commands/policy.js +270 -125
- 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 +128 -74
- 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 +180 -83
- package/dist/commands/triage.d.ts +35 -0
- package/dist/commands/triage.d.ts.map +1 -1
- package/dist/commands/triage.js +207 -82
- 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/config/schema.d.ts +4 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +127 -991
- 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 +9 -0
- package/dist/output/envelope.d.ts.map +1 -1
- package/dist/output/envelope.js +37 -3
- package/dist/output/factory.d.ts +2 -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 +2 -1
- package/dist/output/human.d.ts.map +1 -1
- package/dist/output/human.js +3 -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/policy/schema.d.ts +137 -0
- package/dist/policy/schema.d.ts.map +1 -1
- package/dist/policy/schema.js +107 -0
- package/dist/prompts/command-catalog.js +9 -9
- 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 +104 -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/root-args.d.ts +12 -0
- package/dist/utils/root-args.d.ts.map +1 -0
- package/dist/utils/root-args.js +44 -0
- package/dist/utils/stdin.d.ts +7 -0
- package/dist/utils/stdin.d.ts.map +1 -1
- package/dist/utils/stdin.js +32 -2
- package/dist/utils/url-classify.d.ts.map +1 -1
- package/dist/utils/url-classify.js +24 -3
- package/node_modules/@vertaaux/tui/dist/index.cjs +1216 -27
- 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 +1189 -27
- package/node_modules/@vertaaux/tui/dist/index.js.map +1 -1
- package/node_modules/@vertaaux/tui/package.json +2 -3
- package/node_modules/chalk/license +9 -0
- package/node_modules/chalk/package.json +83 -0
- package/node_modules/chalk/readme.md +297 -0
- package/node_modules/chalk/source/index.d.ts +325 -0
- package/node_modules/chalk/source/index.js +225 -0
- package/node_modules/chalk/source/utilities.js +33 -0
- package/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +236 -0
- package/node_modules/chalk/source/vendor/ansi-styles/index.js +223 -0
- package/node_modules/chalk/source/vendor/supports-color/browser.d.ts +1 -0
- package/node_modules/chalk/source/vendor/supports-color/browser.js +34 -0
- package/node_modules/chalk/source/vendor/supports-color/index.d.ts +55 -0
- package/node_modules/chalk/source/vendor/supports-color/index.js +190 -0
- package/package.json +20 -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
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy fix-all command handler.
|
|
3
|
+
* Generates fix patches for all issues in an audit.
|
|
4
|
+
*/
|
|
5
|
+
import { renderError, createRenderer, runSteps } from "@vertaaux/tui";
|
|
6
|
+
import { ExitCode } from "../utils/exit-codes.js";
|
|
7
|
+
import { resolveApiBase, resolveFormat, getString, getBool, createClient, } from "../utils/api-client.js";
|
|
8
|
+
import { normalizeIssues, isAutoFixable, formatBatchMarkdown, } from "../utils/formatters.js";
|
|
9
|
+
import { writeDataOutput, writeJsonOutput, writeOutput } from "../output/envelope.js";
|
|
10
|
+
import { strings } from "../ui/strings.js";
|
|
11
|
+
const BATCH_LIMIT = 10;
|
|
12
|
+
export async function handleFixAll(opts) {
|
|
13
|
+
const { jobId } = opts;
|
|
14
|
+
const autoFixOnly = opts.autoFixOnly || false;
|
|
15
|
+
const format = opts.format || "md";
|
|
16
|
+
if (!opts.fileContent) {
|
|
17
|
+
throw new Error(strings.fixAll.errors.missingArgs);
|
|
18
|
+
}
|
|
19
|
+
const renderer = createRenderer("auto");
|
|
20
|
+
const baseState = {
|
|
21
|
+
phase: "fix-all",
|
|
22
|
+
phaseIndex: 1,
|
|
23
|
+
phaseTotal: 2,
|
|
24
|
+
url: "",
|
|
25
|
+
mode: "fix-all",
|
|
26
|
+
progress: {},
|
|
27
|
+
totals: {},
|
|
28
|
+
issueCount: 0,
|
|
29
|
+
scorePreview: null,
|
|
30
|
+
verbose: false,
|
|
31
|
+
elapsed: 0,
|
|
32
|
+
};
|
|
33
|
+
const startTime = Date.now();
|
|
34
|
+
const client = createClient({ base: opts.base });
|
|
35
|
+
const ctx = { results: null };
|
|
36
|
+
const steps = [
|
|
37
|
+
{
|
|
38
|
+
id: "analyze",
|
|
39
|
+
actionText: "Analyzing fixable issues...",
|
|
40
|
+
summaryText: "Issues identified",
|
|
41
|
+
run: async () => {
|
|
42
|
+
const audit = await client.audits.retrieve(jobId);
|
|
43
|
+
if (audit.status !== "completed") {
|
|
44
|
+
throw new Error(`Audit ${jobId} is not completed (status: ${audit.status})`);
|
|
45
|
+
}
|
|
46
|
+
// Normalize and filter issues
|
|
47
|
+
let issues = normalizeIssues(audit.issues);
|
|
48
|
+
const totalRequested = issues.length;
|
|
49
|
+
if (autoFixOnly) {
|
|
50
|
+
issues = issues.filter((issue) => {
|
|
51
|
+
const typeId = issue.id || "";
|
|
52
|
+
return isAutoFixable(typeId);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
// Respect batch limit
|
|
56
|
+
const totalSkipped = Math.max(0, issues.length - BATCH_LIMIT);
|
|
57
|
+
ctx.results = {
|
|
58
|
+
successes: [],
|
|
59
|
+
failures: [],
|
|
60
|
+
totalRequested,
|
|
61
|
+
totalSkipped,
|
|
62
|
+
};
|
|
63
|
+
// --dry-run: show what would be processed and exit
|
|
64
|
+
if (opts.dryRun) {
|
|
65
|
+
const issuesToShow = issues.slice(0, BATCH_LIMIT);
|
|
66
|
+
const lines = [];
|
|
67
|
+
lines.push(`[dry-run] Would generate patches for ${issuesToShow.length} issues:`);
|
|
68
|
+
for (const issue of issuesToShow) {
|
|
69
|
+
lines.push(` - ${issue.id || "unknown"}: ${issue.title || issue.description || "(no title)"}`);
|
|
70
|
+
}
|
|
71
|
+
if (totalSkipped > 0) {
|
|
72
|
+
lines.push(` (${totalSkipped} additional issues skipped — batch limit ${BATCH_LIMIT})`);
|
|
73
|
+
}
|
|
74
|
+
lines.push("\nNo patches generated. Remove --dry-run to execute.");
|
|
75
|
+
writeOutput(lines.join("\n"));
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: "fix",
|
|
81
|
+
actionText: "Applying fixes...",
|
|
82
|
+
summaryText: "Fixes applied",
|
|
83
|
+
run: async () => {
|
|
84
|
+
if (opts.dryRun || !ctx.results)
|
|
85
|
+
return;
|
|
86
|
+
const audit = await client.audits.retrieve(jobId);
|
|
87
|
+
let issues = normalizeIssues(audit.issues);
|
|
88
|
+
if (autoFixOnly) {
|
|
89
|
+
issues = issues.filter((issue) => {
|
|
90
|
+
const typeId = issue.id || "";
|
|
91
|
+
return isAutoFixable(typeId);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const issuesToProcess = issues.slice(0, BATCH_LIMIT);
|
|
95
|
+
for (let i = 0; i < issuesToProcess.length; i++) {
|
|
96
|
+
const issue = issuesToProcess[i];
|
|
97
|
+
const curIssueId = issue.id || `issue-${i}`;
|
|
98
|
+
try {
|
|
99
|
+
const patchResult = await client.patches.generate({
|
|
100
|
+
job_id: jobId,
|
|
101
|
+
issue_id: curIssueId,
|
|
102
|
+
file_content: opts.fileContent,
|
|
103
|
+
});
|
|
104
|
+
if (patchResult.success && patchResult.patch) {
|
|
105
|
+
ctx.results.successes.push({
|
|
106
|
+
issueId: curIssueId,
|
|
107
|
+
patch: patchResult.patch,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
ctx.results.failures.push({
|
|
112
|
+
issueId: curIssueId,
|
|
113
|
+
reason: patchResult.error?.code || "PATCH_FAILED",
|
|
114
|
+
details: patchResult.error?.message,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
ctx.results.failures.push({
|
|
120
|
+
issueId: curIssueId,
|
|
121
|
+
reason: "REQUEST_ERROR",
|
|
122
|
+
details: err instanceof Error ? err.message : String(err),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
const { success, states } = await runSteps(steps, {
|
|
130
|
+
onStateChange: (stepStates) => {
|
|
131
|
+
renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
renderer.finish({
|
|
135
|
+
url: "",
|
|
136
|
+
mode: "fix-all",
|
|
137
|
+
overallScore: success ? 100 : 0,
|
|
138
|
+
scores: {},
|
|
139
|
+
issueCount: 0,
|
|
140
|
+
passed: success,
|
|
141
|
+
elapsed: Date.now() - startTime,
|
|
142
|
+
});
|
|
143
|
+
if (!success) {
|
|
144
|
+
const failed = states.find(s => s.status === "failed");
|
|
145
|
+
process.stderr.write(renderError({
|
|
146
|
+
message: failed?.failReason || "Command failed",
|
|
147
|
+
suggestion: "vertaa doctor",
|
|
148
|
+
}) + "\n");
|
|
149
|
+
process.exitCode = ExitCode.ERROR;
|
|
150
|
+
}
|
|
151
|
+
const finalResults = ctx.results;
|
|
152
|
+
if (!opts.dryRun && finalResults !== null) {
|
|
153
|
+
// Exit code 1 if any failures
|
|
154
|
+
if (finalResults.failures.length > 0) {
|
|
155
|
+
process.exitCode = 1;
|
|
156
|
+
}
|
|
157
|
+
if (format === "json") {
|
|
158
|
+
writeJsonOutput(finalResults, "fix-all");
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
writeDataOutput(formatBatchMarkdown(finalResults));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Shared fix-all runner used by the fix-all command (legacy wrapper for backward compat).
|
|
167
|
+
*/
|
|
168
|
+
export async function runFixAllCommand(base, jobId, flags, globalFlags = {}) {
|
|
169
|
+
const fileContent = getString(flags, "file-content");
|
|
170
|
+
const autoFixOnly = getBool(flags, "auto-fix-only");
|
|
171
|
+
const format = resolveFormat(flags);
|
|
172
|
+
if (!fileContent) {
|
|
173
|
+
throw new Error(strings.fixAll.errors.missingArgs);
|
|
174
|
+
}
|
|
175
|
+
await handleFixAll({
|
|
176
|
+
base,
|
|
177
|
+
jobId,
|
|
178
|
+
fileContent,
|
|
179
|
+
autoFixOnly,
|
|
180
|
+
format,
|
|
181
|
+
dryRun: globalFlags.dryRun,
|
|
182
|
+
yes: globalFlags.yes,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
export function registerFixAllCommand(program) {
|
|
186
|
+
program
|
|
187
|
+
.command("fix-all <jobId>")
|
|
188
|
+
.description("Generate fix patches for all issues in an audit")
|
|
189
|
+
.requiredOption("--file-content <code>", "Source code content")
|
|
190
|
+
.option("--auto-fix-only", "Only process auto-fixable issues")
|
|
191
|
+
.action(async (jobId, cmdOptions, command) => {
|
|
192
|
+
try {
|
|
193
|
+
const globalOpts = command.optsWithGlobals();
|
|
194
|
+
const base = resolveApiBase(cmdOptions);
|
|
195
|
+
await runFixAllCommand(base, jobId, cmdOptions, { dryRun: !!globalOpts.dryRun, yes: !!globalOpts.yes });
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
process.stderr.write(renderError({
|
|
199
|
+
message: error instanceof Error ? error.message : String(error),
|
|
200
|
+
suggestion: "vertaa explain <id>",
|
|
201
|
+
exitCode: ExitCode.ERROR,
|
|
202
|
+
}) + "\n");
|
|
203
|
+
process.exit(ExitCode.ERROR);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
@@ -11,5 +11,14 @@
|
|
|
11
11
|
* vertaa fix-plan --file audit.json --json
|
|
12
12
|
*/
|
|
13
13
|
import { Command } from "commander";
|
|
14
|
+
export interface FixPlanCommandOptions {
|
|
15
|
+
job?: string;
|
|
16
|
+
file?: string;
|
|
17
|
+
format?: string;
|
|
18
|
+
base?: string;
|
|
19
|
+
machine?: boolean;
|
|
20
|
+
apiKey?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function handleFixPlan(opts: FixPlanCommandOptions): Promise<void>;
|
|
14
23
|
export declare function registerFixPlanCommand(program: Command): void;
|
|
15
24
|
//# sourceMappingURL=fix-plan.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fix-plan.d.ts","sourceRoot":"","sources":["../../src/commands/fix-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"fix-plan.d.ts","sourceRoot":"","sources":["../../src/commands/fix-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8IpC,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiI9E;AAMD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2C7D"}
|
|
@@ -10,15 +10,15 @@
|
|
|
10
10
|
* vertaa fix-plan --job abc123
|
|
11
11
|
* vertaa fix-plan --file audit.json --json
|
|
12
12
|
*/
|
|
13
|
-
import
|
|
13
|
+
import { bold, dim, colorize, boldColor, brand, severity as severityPalette, renderError, createRenderer, runSteps } from "@vertaaux/tui";
|
|
14
14
|
import { ExitCode } from "../utils/exit-codes.js";
|
|
15
|
-
import { resolveApiBase, getApiKey, apiRequest } from "../utils/client.js";
|
|
15
|
+
import { resolveApiBase, getApiKey, apiRequest, createClient } from "../utils/client.js";
|
|
16
16
|
import { resolveConfig } from "../config/loader.js";
|
|
17
|
-
import {
|
|
17
|
+
import { writeDataOutput, writeJsonOutput } from "../output/envelope.js";
|
|
18
18
|
import { resolveCommandFormat } from "../output/formats.js";
|
|
19
|
-
import { createSpinner, succeedSpinner } from "../ui/spinner.js";
|
|
20
19
|
import { readJsonInput } from "../utils/stdin.js";
|
|
21
|
-
import {
|
|
20
|
+
import { AI_TIMEOUT_MS } from "../utils/ai-error.js";
|
|
21
|
+
import { strings } from "../ui/strings.js";
|
|
22
22
|
// ---------------------------------------------------------------------------
|
|
23
23
|
// Helpers
|
|
24
24
|
// ---------------------------------------------------------------------------
|
|
@@ -50,46 +50,158 @@ function normalizeIssues(issues) {
|
|
|
50
50
|
// ---------------------------------------------------------------------------
|
|
51
51
|
// Formatters
|
|
52
52
|
// ---------------------------------------------------------------------------
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
function severityColor(sev, text) {
|
|
54
|
+
switch (sev) {
|
|
55
|
+
case "critical":
|
|
56
|
+
return boldColor(text, severityPalette.critical);
|
|
57
|
+
case "high":
|
|
58
|
+
return colorize(text, severityPalette.error);
|
|
59
|
+
case "medium":
|
|
60
|
+
return colorize(text, severityPalette.warning);
|
|
61
|
+
case "low":
|
|
62
|
+
return colorize(text, brand.cyan);
|
|
63
|
+
default:
|
|
64
|
+
return dim(text);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
59
67
|
const EFFORT_LABELS = {
|
|
60
|
-
trivial:
|
|
61
|
-
small:
|
|
62
|
-
medium:
|
|
63
|
-
large:
|
|
68
|
+
trivial: colorize("trivial", brand.lime),
|
|
69
|
+
small: colorize("small", brand.lime),
|
|
70
|
+
medium: colorize("medium", severityPalette.warning),
|
|
71
|
+
large: colorize("large", severityPalette.error),
|
|
64
72
|
};
|
|
65
73
|
const FIX_TYPE_LABELS = {
|
|
66
|
-
code:
|
|
67
|
-
config:
|
|
68
|
-
content:
|
|
69
|
-
design:
|
|
74
|
+
code: colorize("code", brand.teal),
|
|
75
|
+
config: colorize("config", brand.tealLight),
|
|
76
|
+
content: colorize("content", brand.cyan),
|
|
77
|
+
design: colorize("design", severityPalette.warning),
|
|
70
78
|
};
|
|
71
79
|
function formatFixPlanHuman(data) {
|
|
72
80
|
const lines = [];
|
|
73
|
-
lines.push(
|
|
74
|
-
lines.push(
|
|
81
|
+
lines.push(bold(`Remediation Plan (${data.items.length} items)`));
|
|
82
|
+
lines.push(dim(`Estimated total effort: ${data.estimated_total_effort}`));
|
|
75
83
|
lines.push("");
|
|
76
84
|
for (let idx = 0; idx < data.items.length; idx++) {
|
|
77
85
|
const item = data.items[idx];
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
lines.push(
|
|
82
|
-
lines.push(` Effort: ${effort} Type: ${fixType}${item.id ? chalk.dim(` (${item.id})`) : ""}`);
|
|
86
|
+
const effort = EFFORT_LABELS[item.effort] || dim(item.effort);
|
|
87
|
+
const fixType = FIX_TYPE_LABELS[item.fix_type] || dim(item.fix_type);
|
|
88
|
+
lines.push(`${bold(`${idx + 1}.`)} ${severityColor(item.severity, `[${item.severity}]`)} ${bold(item.title)}`);
|
|
89
|
+
lines.push(` Effort: ${effort} Type: ${fixType}${item.id ? dim(` (${item.id})`) : ""}`);
|
|
83
90
|
for (let s = 0; s < item.steps.length; s++) {
|
|
84
|
-
lines.push(` ${
|
|
91
|
+
lines.push(` ${dim(`${s + 1})`)} ${item.steps[s]}`);
|
|
85
92
|
}
|
|
86
93
|
if (item.code_hint) {
|
|
87
|
-
lines.push(` ${
|
|
94
|
+
lines.push(` ${dim("Hint:")} ${item.code_hint}`);
|
|
88
95
|
}
|
|
89
96
|
lines.push("");
|
|
90
97
|
}
|
|
91
98
|
return lines.join("\n");
|
|
92
99
|
}
|
|
100
|
+
export async function handleFixPlan(opts) {
|
|
101
|
+
const config = { apiKey: opts.apiKey };
|
|
102
|
+
const format = resolveCommandFormat("fix-plan", opts.format, opts.machine || false);
|
|
103
|
+
const renderer = createRenderer("auto");
|
|
104
|
+
const baseState = {
|
|
105
|
+
phase: "fix-plan",
|
|
106
|
+
phaseIndex: 1,
|
|
107
|
+
phaseTotal: 2,
|
|
108
|
+
url: "",
|
|
109
|
+
mode: "fix-plan",
|
|
110
|
+
progress: {},
|
|
111
|
+
totals: {},
|
|
112
|
+
issueCount: 0,
|
|
113
|
+
scorePreview: null,
|
|
114
|
+
verbose: false,
|
|
115
|
+
elapsed: 0,
|
|
116
|
+
};
|
|
117
|
+
const startTime = Date.now();
|
|
118
|
+
let responseData = null;
|
|
119
|
+
const steps = [
|
|
120
|
+
{
|
|
121
|
+
id: "analyze",
|
|
122
|
+
actionText: strings.fixPlan.generate.action,
|
|
123
|
+
summaryText: "Issues analyzed",
|
|
124
|
+
run: async () => {
|
|
125
|
+
let auditPayload;
|
|
126
|
+
if (opts.job) {
|
|
127
|
+
const sdkClient = createClient({ base: opts.base, apiKey: config.apiKey });
|
|
128
|
+
const result = await sdkClient.audits.retrieve(opts.job);
|
|
129
|
+
const issues = normalizeIssues(result.issues);
|
|
130
|
+
auditPayload = {
|
|
131
|
+
job_id: result.job_id || opts.job,
|
|
132
|
+
url: result.url || null,
|
|
133
|
+
scores: result.scores || null,
|
|
134
|
+
issues,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const input = await readJsonInput(opts.file);
|
|
139
|
+
if (!input) {
|
|
140
|
+
throw new Error("No audit data provided.\nUsage:\n vertaa audit https://example.com --json | vertaa fix-plan\n vertaa fix-plan --job <job-id>\n vertaa fix-plan --file audit.json");
|
|
141
|
+
}
|
|
142
|
+
const data = input;
|
|
143
|
+
const innerData = (data.data && typeof data.data === "object" ? data.data : data);
|
|
144
|
+
const issues = normalizeIssues(innerData.issues);
|
|
145
|
+
auditPayload = {
|
|
146
|
+
job_id: innerData.job_id || null,
|
|
147
|
+
url: innerData.url || null,
|
|
148
|
+
scores: innerData.scores || null,
|
|
149
|
+
issues,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
if (!Array.isArray(auditPayload.issues) ||
|
|
153
|
+
auditPayload.issues.length === 0) {
|
|
154
|
+
throw new Error("No issues found in audit data.");
|
|
155
|
+
}
|
|
156
|
+
const base = resolveApiBase(opts.base);
|
|
157
|
+
const apiKey = getApiKey(config.apiKey);
|
|
158
|
+
const response = await Promise.race([
|
|
159
|
+
apiRequest(base, "/cli/ai/fix-plan", { method: "POST", body: { audit: auditPayload } }, apiKey),
|
|
160
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("LLM request timed out")), AI_TIMEOUT_MS)),
|
|
161
|
+
]);
|
|
162
|
+
responseData = response.data;
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: "plan",
|
|
167
|
+
actionText: "Generating fix plan...",
|
|
168
|
+
summaryText: responseData ? strings.fixPlan.generate.done(responseData.items.length) : "Fix plan generated",
|
|
169
|
+
run: async () => {
|
|
170
|
+
// Fix plan generated in analyze step via API call
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
];
|
|
174
|
+
const { success, states } = await runSteps(steps, {
|
|
175
|
+
onStateChange: (stepStates) => {
|
|
176
|
+
renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
renderer.finish({
|
|
180
|
+
url: "",
|
|
181
|
+
mode: "fix-plan",
|
|
182
|
+
overallScore: success ? 100 : 0,
|
|
183
|
+
scores: {},
|
|
184
|
+
issueCount: 0,
|
|
185
|
+
passed: success,
|
|
186
|
+
elapsed: Date.now() - startTime,
|
|
187
|
+
});
|
|
188
|
+
if (!success) {
|
|
189
|
+
const failed = states.find(s => s.status === "failed");
|
|
190
|
+
process.stderr.write(renderError({
|
|
191
|
+
message: failed?.failReason || "Command failed",
|
|
192
|
+
suggestion: "vertaa doctor",
|
|
193
|
+
}) + "\n");
|
|
194
|
+
process.exitCode = ExitCode.ERROR;
|
|
195
|
+
}
|
|
196
|
+
if (success && responseData) {
|
|
197
|
+
if (format === "json") {
|
|
198
|
+
writeJsonOutput(responseData, "fix-plan");
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
writeDataOutput(formatFixPlanHuman(responseData));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
93
205
|
// ---------------------------------------------------------------------------
|
|
94
206
|
// Command Registration
|
|
95
207
|
// ---------------------------------------------------------------------------
|
|
@@ -100,6 +212,7 @@ export function registerFixPlanCommand(program) {
|
|
|
100
212
|
.option("--job <job-id>", "Fetch audit data from a job ID")
|
|
101
213
|
.option("--file <path>", "Load audit JSON from file")
|
|
102
214
|
.option("-f, --format <format>", "Output format: json | human")
|
|
215
|
+
.option("--json", "Alias for --format json")
|
|
103
216
|
.addHelpText("after", `
|
|
104
217
|
Examples:
|
|
105
218
|
vertaa audit https://example.com --json | vertaa fix-plan
|
|
@@ -112,70 +225,21 @@ Examples:
|
|
|
112
225
|
const globalOpts = command.optsWithGlobals();
|
|
113
226
|
const config = await resolveConfig(globalOpts.config);
|
|
114
227
|
const machineMode = globalOpts.machine || false;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
auditPayload = {
|
|
124
|
-
job_id: result.job_id || options.job,
|
|
125
|
-
url: result.url || null,
|
|
126
|
-
scores: result.scores || null,
|
|
127
|
-
issues,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
const input = await readJsonInput(options.file);
|
|
132
|
-
if (!input) {
|
|
133
|
-
console.error("Error: No audit data provided.");
|
|
134
|
-
console.error("Usage:");
|
|
135
|
-
console.error(" vertaa audit https://example.com --json | vertaa fix-plan");
|
|
136
|
-
console.error(" vertaa fix-plan --job <job-id>");
|
|
137
|
-
console.error(" vertaa fix-plan --file audit.json");
|
|
138
|
-
process.exit(ExitCode.ERROR);
|
|
139
|
-
}
|
|
140
|
-
const data = input;
|
|
141
|
-
const innerData = (data.data && typeof data.data === "object" ? data.data : data);
|
|
142
|
-
const issues = normalizeIssues(innerData.issues);
|
|
143
|
-
auditPayload = {
|
|
144
|
-
job_id: innerData.job_id || null,
|
|
145
|
-
url: innerData.url || null,
|
|
146
|
-
scores: innerData.scores || null,
|
|
147
|
-
issues,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
if (!Array.isArray(auditPayload.issues) ||
|
|
151
|
-
auditPayload.issues.length === 0) {
|
|
152
|
-
console.error("Error: No issues found in audit data.");
|
|
153
|
-
process.exit(ExitCode.ERROR);
|
|
154
|
-
}
|
|
155
|
-
// Auth check
|
|
156
|
-
const base = resolveApiBase(globalOpts.base);
|
|
157
|
-
const apiKey = getApiKey(config.apiKey);
|
|
158
|
-
// Call LLM fix-plan API
|
|
159
|
-
const spinner = createSpinner("Generating remediation plan...");
|
|
160
|
-
try {
|
|
161
|
-
const response = await Promise.race([
|
|
162
|
-
apiRequest(base, "/cli/ai/fix-plan", { method: "POST", body: { audit: auditPayload } }, apiKey),
|
|
163
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error("LLM request timed out")), AI_TIMEOUT_MS)),
|
|
164
|
-
]);
|
|
165
|
-
succeedSpinner(spinner, "Plan ready");
|
|
166
|
-
if (format === "json") {
|
|
167
|
-
writeJsonOutput(response.data, "fix-plan");
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
writeOutput(formatFixPlanHuman(response.data));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
catch (error) {
|
|
174
|
-
handleAiCommandError(error, "fix-plan", spinner);
|
|
175
|
-
}
|
|
228
|
+
await handleFixPlan({
|
|
229
|
+
job: options.job,
|
|
230
|
+
file: options.file,
|
|
231
|
+
format: options.json ? "json" : options.format,
|
|
232
|
+
base: globalOpts.base,
|
|
233
|
+
machine: machineMode,
|
|
234
|
+
apiKey: config.apiKey,
|
|
235
|
+
});
|
|
176
236
|
}
|
|
177
237
|
catch (error) {
|
|
178
|
-
|
|
238
|
+
process.stderr.write(renderError({
|
|
239
|
+
message: error instanceof Error ? error.message : String(error),
|
|
240
|
+
suggestion: "vertaa explain <id>",
|
|
241
|
+
exitCode: ExitCode.ERROR,
|
|
242
|
+
}) + "\n");
|
|
179
243
|
process.exit(ExitCode.ERROR);
|
|
180
244
|
}
|
|
181
245
|
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy fix command handler.
|
|
3
|
+
* Generates a fix patch for an issue.
|
|
4
|
+
*/
|
|
5
|
+
import type { Command } from "commander";
|
|
6
|
+
import type { Flags } from "../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Shared fix runner used by the fix command.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runFixCommand(base: string, jobId: string, issueId: string, flags: Flags, globalFlags?: {
|
|
11
|
+
dryRun?: boolean;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
export declare function handleFix(jobId: string, cmdOptions: Flags, globalFlags?: {
|
|
14
|
+
dryRun?: boolean;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
export declare function registerFixCommand(program: Command): void;
|
|
17
|
+
//# sourceMappingURL=fix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix.d.ts","sourceRoot":"","sources":["../../src/commands/fix.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAczC,OAAO,KAAK,EAAE,KAAK,EAAiB,MAAM,aAAa,CAAC;AAGxD;;GAEG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,KAAK,EACZ,WAAW,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,iBAiCvC;AAED,wBAAsB,SAAS,CAC7B,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,KAAK,EACjB,WAAW,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACrC,OAAO,CAAC,IAAI,CAAC,CAiDf;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqBzD"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy fix command handler.
|
|
3
|
+
* Generates a fix patch for an issue.
|
|
4
|
+
*/
|
|
5
|
+
import { renderError, runSteps, createRenderer } from "@vertaaux/tui";
|
|
6
|
+
import { ExitCode } from "../utils/exit-codes.js";
|
|
7
|
+
import { resolveApiBase, resolveFormat, getString, createClient, } from "../utils/api-client.js";
|
|
8
|
+
import { formatPatchMarkdown, } from "../utils/formatters.js";
|
|
9
|
+
import { writeDataOutput, writeJsonOutput } from "../output/envelope.js";
|
|
10
|
+
import { strings } from "../ui/strings.js";
|
|
11
|
+
/**
|
|
12
|
+
* Shared fix runner used by the fix command.
|
|
13
|
+
*/
|
|
14
|
+
export async function runFixCommand(base, jobId, issueId, flags, globalFlags = {}) {
|
|
15
|
+
const fileContent = getString(flags, "file-content");
|
|
16
|
+
const format = resolveFormat(flags);
|
|
17
|
+
if (!fileContent) {
|
|
18
|
+
throw new Error(strings.fix.errors.missingArgs);
|
|
19
|
+
}
|
|
20
|
+
const client = createClient({ base });
|
|
21
|
+
const result = await client.patches.generate({
|
|
22
|
+
job_id: jobId,
|
|
23
|
+
issue_id: issueId,
|
|
24
|
+
file_content: fileContent,
|
|
25
|
+
});
|
|
26
|
+
if (!result.success) {
|
|
27
|
+
process.exitCode = 1;
|
|
28
|
+
}
|
|
29
|
+
if (format === "json") {
|
|
30
|
+
const output = globalFlags.dryRun ? { ...result, dry_run: true } : result;
|
|
31
|
+
writeJsonOutput(output, "fix");
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (globalFlags.dryRun) {
|
|
35
|
+
writeDataOutput(strings.fix.dryRun);
|
|
36
|
+
}
|
|
37
|
+
if (result.success && result.patch) {
|
|
38
|
+
writeDataOutput(formatPatchMarkdown(result.patch));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
writeDataOutput(`## Patch Generation Failed\n\n${result.error?.message || "Unknown error"}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function handleFix(jobId, cmdOptions, globalFlags = {}) {
|
|
46
|
+
const renderer = createRenderer("auto");
|
|
47
|
+
const baseState = {
|
|
48
|
+
phase: "fix",
|
|
49
|
+
phaseIndex: 1,
|
|
50
|
+
phaseTotal: 1,
|
|
51
|
+
url: "",
|
|
52
|
+
mode: "fix",
|
|
53
|
+
progress: {},
|
|
54
|
+
totals: {},
|
|
55
|
+
issueCount: 0,
|
|
56
|
+
scorePreview: null,
|
|
57
|
+
verbose: false,
|
|
58
|
+
elapsed: 0,
|
|
59
|
+
};
|
|
60
|
+
const startTime = Date.now();
|
|
61
|
+
const steps = [
|
|
62
|
+
{
|
|
63
|
+
id: "generate",
|
|
64
|
+
actionText: "Generating patch...",
|
|
65
|
+
summaryText: "Patch generated",
|
|
66
|
+
run: async () => {
|
|
67
|
+
const base = resolveApiBase(cmdOptions);
|
|
68
|
+
const issueId = getString(cmdOptions, "issue");
|
|
69
|
+
if (!issueId)
|
|
70
|
+
throw new Error("--issue is required");
|
|
71
|
+
await runFixCommand(base, jobId, issueId, cmdOptions, globalFlags);
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
const { success, states } = await runSteps(steps, {
|
|
76
|
+
failFast: true,
|
|
77
|
+
onStateChange: (stepStates) => {
|
|
78
|
+
renderer.update({ ...baseState, stepStates, elapsed: Date.now() - startTime });
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
renderer.finish({ url: "", mode: "fix", overallScore: 0, scores: {}, issueCount: 0, passed: success, elapsed: Date.now() - startTime });
|
|
82
|
+
if (!success) {
|
|
83
|
+
const failed = states.find(s => s.status === "failed");
|
|
84
|
+
process.stderr.write(renderError({
|
|
85
|
+
message: failed?.failReason || "Command failed",
|
|
86
|
+
suggestion: "vertaa doctor",
|
|
87
|
+
}) + "\n");
|
|
88
|
+
process.exitCode = ExitCode.ERROR;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export function registerFixCommand(program) {
|
|
92
|
+
program
|
|
93
|
+
.command("fix <jobId>")
|
|
94
|
+
.description("Generate a fix patch for an issue")
|
|
95
|
+
.requiredOption("--issue <id>", "Issue ID to fix")
|
|
96
|
+
.requiredOption("--file-content <code>", "Source code content")
|
|
97
|
+
.action(async (jobId, cmdOptions, command) => {
|
|
98
|
+
try {
|
|
99
|
+
const globalOpts = command.optsWithGlobals();
|
|
100
|
+
await handleFix(jobId, cmdOptions, { dryRun: !!globalOpts.dryRun });
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
process.stderr.write(renderError({
|
|
104
|
+
message: error instanceof Error ? error.message : String(error),
|
|
105
|
+
suggestion: "vertaa explain <id>",
|
|
106
|
+
exitCode: ExitCode.ERROR,
|
|
107
|
+
}) + "\n");
|
|
108
|
+
process.exit(ExitCode.ERROR);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -5,6 +5,17 @@
|
|
|
5
5
|
* Generates CI templates for popular platforms.
|
|
6
6
|
*/
|
|
7
7
|
import type { Command } from "commander";
|
|
8
|
+
import type { CITemplate, FailOnSeverity } from "../config/schema.js";
|
|
9
|
+
/**
|
|
10
|
+
* Handle the init command.
|
|
11
|
+
*/
|
|
12
|
+
export declare function handleInit(options: {
|
|
13
|
+
yes?: boolean;
|
|
14
|
+
ci?: CITemplate;
|
|
15
|
+
failOn?: FailOnSeverity;
|
|
16
|
+
threshold?: number;
|
|
17
|
+
force?: boolean;
|
|
18
|
+
}): Promise<void>;
|
|
8
19
|
/**
|
|
9
20
|
* Register the init command with the Commander program.
|
|
10
21
|
*/
|