@shakecodeslikecray/whiterose 1.0.3 → 1.0.5
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/dist/cli/index.js +211 -45
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.js +64 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2116,11 +2116,25 @@ var CoreScanner = class {
|
|
|
2116
2116
|
executor;
|
|
2117
2117
|
config;
|
|
2118
2118
|
progress;
|
|
2119
|
+
passErrors = [];
|
|
2119
2120
|
constructor(executor, config = {}, progress = {}) {
|
|
2120
2121
|
this.executor = executor;
|
|
2121
2122
|
this.config = { ...DEFAULT_SCANNER_CONFIG, ...config };
|
|
2122
2123
|
this.progress = progress;
|
|
2123
2124
|
}
|
|
2125
|
+
/**
|
|
2126
|
+
* Get errors that occurred during the last scan.
|
|
2127
|
+
* Returns an array of pass names and their error messages.
|
|
2128
|
+
*/
|
|
2129
|
+
getPassErrors() {
|
|
2130
|
+
return this.passErrors;
|
|
2131
|
+
}
|
|
2132
|
+
/**
|
|
2133
|
+
* Check if any passes failed during the last scan.
|
|
2134
|
+
*/
|
|
2135
|
+
hasPassErrors() {
|
|
2136
|
+
return this.passErrors.length > 0;
|
|
2137
|
+
}
|
|
2124
2138
|
/**
|
|
2125
2139
|
* Run a thorough 19-pass scan with findings flowing through pipeline:
|
|
2126
2140
|
*
|
|
@@ -2134,6 +2148,7 @@ var CoreScanner = class {
|
|
|
2134
2148
|
async scan(context) {
|
|
2135
2149
|
const cwd = process.cwd();
|
|
2136
2150
|
const startTime = Date.now();
|
|
2151
|
+
this.passErrors = [];
|
|
2137
2152
|
const pipeline = getFullAnalysisPipeline();
|
|
2138
2153
|
const unitPasses = pipeline[0].passes;
|
|
2139
2154
|
const integrationPasses = pipeline[1].passes;
|
|
@@ -2214,8 +2229,10 @@ var CoreScanner = class {
|
|
|
2214
2229
|
this.report(` \u2713 ${pass.name}: ${bugs.length} bugs`);
|
|
2215
2230
|
return bugs;
|
|
2216
2231
|
} catch (error) {
|
|
2217
|
-
|
|
2218
|
-
this.
|
|
2232
|
+
const errorMsg = error.message || String(error);
|
|
2233
|
+
this.progress.onPassError?.(pass.name, errorMsg);
|
|
2234
|
+
this.report(` \u2717 ${pass.name}: ${errorMsg}`);
|
|
2235
|
+
this.passErrors.push({ passName: pass.name, error: errorMsg });
|
|
2219
2236
|
return [];
|
|
2220
2237
|
}
|
|
2221
2238
|
});
|
|
@@ -3089,7 +3106,7 @@ function extractIntentFromDocs(docs) {
|
|
|
3089
3106
|
}
|
|
3090
3107
|
}
|
|
3091
3108
|
if (docs.readme) {
|
|
3092
|
-
const featuresMatch = docs.readme.match(/##\s*Features?\s*\n([\s\S]*?)(?=\n##|\n
|
|
3109
|
+
const featuresMatch = docs.readme.match(/##\s*Features?\s*\n([\s\S]*?)(?=\n##|\n---|$)/i);
|
|
3093
3110
|
if (featuresMatch) {
|
|
3094
3111
|
const featureLines = featuresMatch[1].split("\n").filter((line) => line.trim().startsWith("-") || line.trim().startsWith("*")).map((line) => line.replace(/^[-*]\s*/, "").trim()).filter((line) => line.length > 0);
|
|
3095
3112
|
intent.features.push(...featureLines.slice(0, 20));
|
|
@@ -4327,6 +4344,9 @@ function loadAccumulatedBugs(cwd) {
|
|
|
4327
4344
|
if (!Array.isArray(stored.bugs)) {
|
|
4328
4345
|
stored.bugs = [];
|
|
4329
4346
|
}
|
|
4347
|
+
if (!stored.fingerprints || typeof stored.fingerprints !== "object") {
|
|
4348
|
+
stored.fingerprints = {};
|
|
4349
|
+
}
|
|
4330
4350
|
stored.bugs = stored.bugs.map((b) => ({ ...b, kind: b.kind || "bug" }));
|
|
4331
4351
|
return stored;
|
|
4332
4352
|
} catch (error) {
|
|
@@ -5875,7 +5895,9 @@ var FixConfirm = ({ bug, dryRun, onConfirm, onCancel, onFixComplete }) => {
|
|
|
5875
5895
|
setStatus("fixing");
|
|
5876
5896
|
setProgressMessage("Starting agentic fix...");
|
|
5877
5897
|
try {
|
|
5878
|
-
const result = await onConfirm()
|
|
5898
|
+
const result = await onConfirm((message) => {
|
|
5899
|
+
setProgressMessage(message);
|
|
5900
|
+
});
|
|
5879
5901
|
if (result.falsePositive) {
|
|
5880
5902
|
setFalsePositiveReason(result.falsePositiveReason || "The AI determined this bug is not real after analyzing the code.");
|
|
5881
5903
|
setStatus("false-positive");
|
|
@@ -6019,11 +6041,11 @@ var App = ({ bugs, config, fixOptions, onFix, onExit }) => {
|
|
|
6019
6041
|
};
|
|
6020
6042
|
const [fixError, setFixError] = useState(null);
|
|
6021
6043
|
const [lastFixedBugId, setLastFixedBugId] = useState(null);
|
|
6022
|
-
const handleConfirmFix = async () => {
|
|
6044
|
+
const handleConfirmFix = async (onProgress) => {
|
|
6023
6045
|
if (selectedBug) {
|
|
6024
6046
|
setFixError(null);
|
|
6025
6047
|
setLastFixedBugId(selectedBug.id);
|
|
6026
|
-
const result = await onFix(selectedBug);
|
|
6048
|
+
const result = await onFix(selectedBug, onProgress);
|
|
6027
6049
|
return result;
|
|
6028
6050
|
}
|
|
6029
6051
|
return { falsePositive: false };
|
|
@@ -6228,6 +6250,67 @@ function markBugAsFixed(bug, commitHash, cwd = process.cwd()) {
|
|
|
6228
6250
|
}
|
|
6229
6251
|
|
|
6230
6252
|
// src/core/fixer.ts
|
|
6253
|
+
var MAX_SARIF_TEXT_LENGTH = 2e3;
|
|
6254
|
+
var PROMPT_INJECTION_PATTERNS = [
|
|
6255
|
+
// Attempts to override or ignore instructions
|
|
6256
|
+
/ignore\s+(previous|all|above)\s+instructions?/i,
|
|
6257
|
+
/disregard\s+(previous|all|above)\s+instructions?/i,
|
|
6258
|
+
/forget\s+(previous|all|above)\s+instructions?/i,
|
|
6259
|
+
// Attempts to define new roles or personas
|
|
6260
|
+
/you\s+are\s+(now|actually)\s+/i,
|
|
6261
|
+
/act\s+as\s+(a|an)\s+/i,
|
|
6262
|
+
/pretend\s+(you|to\s+be)\s+/i,
|
|
6263
|
+
// Attempts to inject system-level commands
|
|
6264
|
+
/\[SYSTEM\]/i,
|
|
6265
|
+
/\[INST\]/i,
|
|
6266
|
+
/<\|system\|>/i,
|
|
6267
|
+
/<\|assistant\|>/i,
|
|
6268
|
+
/<\|user\|>/i,
|
|
6269
|
+
// Attempts to break out with special markers
|
|
6270
|
+
/###\s*(INSTRUCTION|SYSTEM|END|NEW)/i,
|
|
6271
|
+
/```\s*(system|instruction)/i,
|
|
6272
|
+
// Direct file operation injections
|
|
6273
|
+
/delete\s+(all|the)\s+files?/i,
|
|
6274
|
+
/rm\s+-rf\s+/i,
|
|
6275
|
+
/remove\s+(all|every)\s+file/i,
|
|
6276
|
+
// Exfiltration attempts
|
|
6277
|
+
/send\s+(this|the|all)\s+(data|content|file)/i,
|
|
6278
|
+
/upload\s+(to|this)/i,
|
|
6279
|
+
/curl\s+.*\s+-d/i,
|
|
6280
|
+
/fetch\s*\(\s*['"][^'"]*['"]\s*,\s*\{[^}]*method\s*:\s*['"]POST['"]/i
|
|
6281
|
+
];
|
|
6282
|
+
function sanitizeSarifText(text2, fieldName = "field") {
|
|
6283
|
+
if (!text2 || typeof text2 !== "string") {
|
|
6284
|
+
return "";
|
|
6285
|
+
}
|
|
6286
|
+
let sanitized = text2.length > MAX_SARIF_TEXT_LENGTH ? text2.substring(0, MAX_SARIF_TEXT_LENGTH) + `... [truncated ${fieldName}]` : text2;
|
|
6287
|
+
for (const pattern of PROMPT_INJECTION_PATTERNS) {
|
|
6288
|
+
if (pattern.test(sanitized)) {
|
|
6289
|
+
sanitized = sanitized.replace(pattern, "[REDACTED: potential injection]");
|
|
6290
|
+
}
|
|
6291
|
+
}
|
|
6292
|
+
sanitized = sanitized.replace(/```+/g, "`\u200B`\u200B`");
|
|
6293
|
+
sanitized = sanitized.replace(/###/g, "#\u200B#\u200B#");
|
|
6294
|
+
return sanitized;
|
|
6295
|
+
}
|
|
6296
|
+
function sanitizeSarifEvidence(evidence) {
|
|
6297
|
+
if (!Array.isArray(evidence)) {
|
|
6298
|
+
return [];
|
|
6299
|
+
}
|
|
6300
|
+
return evidence.filter((e) => typeof e === "string").slice(0, 10).map((e) => sanitizeSarifText(e, "evidence"));
|
|
6301
|
+
}
|
|
6302
|
+
function sanitizeSarifCodePath(codePath) {
|
|
6303
|
+
if (!Array.isArray(codePath)) {
|
|
6304
|
+
return [];
|
|
6305
|
+
}
|
|
6306
|
+
return codePath.slice(0, 20).map((entry, idx) => ({
|
|
6307
|
+
step: typeof entry?.step === "number" ? entry.step : idx + 1,
|
|
6308
|
+
file: sanitizeSarifText(String(entry?.file || ""), "codePath.file").substring(0, 500),
|
|
6309
|
+
line: typeof entry?.line === "number" ? entry.line : 0,
|
|
6310
|
+
code: sanitizeSarifText(String(entry?.code || ""), "codePath.code"),
|
|
6311
|
+
explanation: sanitizeSarifText(String(entry?.explanation || ""), "codePath.explanation")
|
|
6312
|
+
}));
|
|
6313
|
+
}
|
|
6231
6314
|
function isPathWithinProject(filePath, projectDir) {
|
|
6232
6315
|
const resolvedPath = resolve(projectDir, filePath);
|
|
6233
6316
|
const relativePath = relative(projectDir, resolvedPath);
|
|
@@ -6291,7 +6374,7 @@ In: ${bug.file}:${bug.line}`
|
|
|
6291
6374
|
}
|
|
6292
6375
|
let agenticResult;
|
|
6293
6376
|
try {
|
|
6294
|
-
agenticResult = await runAgenticFix(bug, config, projectDir);
|
|
6377
|
+
agenticResult = await runAgenticFix(bug, config, projectDir, options.onProgress);
|
|
6295
6378
|
} catch (error) {
|
|
6296
6379
|
return {
|
|
6297
6380
|
success: false,
|
|
@@ -6331,7 +6414,7 @@ In: ${bug.file}:${bug.line}`
|
|
|
6331
6414
|
commitHash
|
|
6332
6415
|
};
|
|
6333
6416
|
}
|
|
6334
|
-
async function runAgenticFix(bug, config, projectDir) {
|
|
6417
|
+
async function runAgenticFix(bug, config, projectDir, onProgress) {
|
|
6335
6418
|
const providerCommand = getProviderCommand(config.provider);
|
|
6336
6419
|
const prompt = buildAgenticFixPrompt(bug);
|
|
6337
6420
|
const controller = new AbortController();
|
|
@@ -6385,9 +6468,13 @@ async function runAgenticFix(bug, config, projectDir) {
|
|
|
6385
6468
|
}
|
|
6386
6469
|
}
|
|
6387
6470
|
} else if (config.provider === "claude-code") {
|
|
6388
|
-
const
|
|
6471
|
+
const args = ["--dangerously-skip-permissions", "-p"];
|
|
6472
|
+
if (onProgress) {
|
|
6473
|
+
args.push("--verbose", "--output-format", "stream-json");
|
|
6474
|
+
}
|
|
6475
|
+
const subprocess = execa(
|
|
6389
6476
|
providerCommand,
|
|
6390
|
-
|
|
6477
|
+
args,
|
|
6391
6478
|
{
|
|
6392
6479
|
cwd: projectDir,
|
|
6393
6480
|
input: prompt,
|
|
@@ -6398,6 +6485,43 @@ async function runAgenticFix(bug, config, projectDir) {
|
|
|
6398
6485
|
cancelSignal: controller.signal
|
|
6399
6486
|
}
|
|
6400
6487
|
);
|
|
6488
|
+
if (onProgress && subprocess.stdout) {
|
|
6489
|
+
let lineBuffer = "";
|
|
6490
|
+
subprocess.stdout.on("data", (chunk) => {
|
|
6491
|
+
const text2 = chunk.toString();
|
|
6492
|
+
lineBuffer += text2;
|
|
6493
|
+
const lines = lineBuffer.split("\n");
|
|
6494
|
+
lineBuffer = lines.pop() || "";
|
|
6495
|
+
for (const line of lines) {
|
|
6496
|
+
const trimmed = line.trim();
|
|
6497
|
+
if (trimmed) {
|
|
6498
|
+
try {
|
|
6499
|
+
const event = JSON.parse(trimmed);
|
|
6500
|
+
if (event.type === "assistant" && event.message?.content) {
|
|
6501
|
+
for (const block of event.message.content) {
|
|
6502
|
+
if (block.type === "tool_use") {
|
|
6503
|
+
const toolName = block.name || "tool";
|
|
6504
|
+
const friendlyNames = {
|
|
6505
|
+
"Read": "Reading file",
|
|
6506
|
+
"Edit": "Editing file",
|
|
6507
|
+
"Write": "Writing file",
|
|
6508
|
+
"Bash": "Running command",
|
|
6509
|
+
"Glob": "Searching files",
|
|
6510
|
+
"Grep": "Searching content",
|
|
6511
|
+
"Task": "Running task"
|
|
6512
|
+
};
|
|
6513
|
+
const displayName = friendlyNames[toolName] || `Using ${toolName}`;
|
|
6514
|
+
onProgress(`${displayName}...`);
|
|
6515
|
+
}
|
|
6516
|
+
}
|
|
6517
|
+
}
|
|
6518
|
+
} catch {
|
|
6519
|
+
}
|
|
6520
|
+
}
|
|
6521
|
+
}
|
|
6522
|
+
});
|
|
6523
|
+
}
|
|
6524
|
+
const result = await subprocess;
|
|
6401
6525
|
stdout = result.stdout || "";
|
|
6402
6526
|
stderr = result.stderr || "";
|
|
6403
6527
|
} else if (config.provider === "gemini") {
|
|
@@ -6567,8 +6691,8 @@ function generateSimpleDiff(original, modified, filename) {
|
|
|
6567
6691
|
}
|
|
6568
6692
|
async function startFixTUI(bugs, config, options, cwd) {
|
|
6569
6693
|
return new Promise((resolve6) => {
|
|
6570
|
-
const handleFix = async (bug) => {
|
|
6571
|
-
const result = await applyFix(bug, config, options);
|
|
6694
|
+
const handleFix = async (bug, onProgress) => {
|
|
6695
|
+
const result = await applyFix(bug, config, { ...options, onProgress });
|
|
6572
6696
|
if (result.falsePositive) {
|
|
6573
6697
|
if (cwd) {
|
|
6574
6698
|
removeBugFromAccumulated(cwd, bug.id);
|
|
@@ -6727,39 +6851,67 @@ function loadBugsFromSarif(sarifPath) {
|
|
|
6727
6851
|
} catch (error) {
|
|
6728
6852
|
throw new Error(`Failed to parse SARIF file: ${sarifPath}. File may be corrupted or malformed.`);
|
|
6729
6853
|
}
|
|
6730
|
-
|
|
6854
|
+
if (!sarif || typeof sarif !== "object") {
|
|
6855
|
+
throw new Error(`Invalid SARIF file: ${sarifPath}. Expected a JSON object.`);
|
|
6856
|
+
}
|
|
6857
|
+
const runs = sarif.runs;
|
|
6858
|
+
if (!Array.isArray(runs) || runs.length === 0) {
|
|
6859
|
+
return [];
|
|
6860
|
+
}
|
|
6861
|
+
const results = runs[0]?.results;
|
|
6862
|
+
if (!Array.isArray(results)) {
|
|
6863
|
+
return [];
|
|
6864
|
+
}
|
|
6865
|
+
return results.map((r, i) => {
|
|
6866
|
+
if (!r || typeof r !== "object") {
|
|
6867
|
+
throw new Error(`Invalid SARIF result at index ${i}: expected an object.`);
|
|
6868
|
+
}
|
|
6731
6869
|
const props = r.properties || {};
|
|
6870
|
+
const rawTitle = r.message?.text || "Unknown bug";
|
|
6871
|
+
const rawDescription = r.message?.markdown || r.message?.text || "";
|
|
6872
|
+
const rawCodePath = r.codeFlows?.[0]?.threadFlows?.[0]?.locations?.map((loc, idx) => ({
|
|
6873
|
+
step: idx + 1,
|
|
6874
|
+
file: loc.location?.physicalLocation?.artifactLocation?.uri || "",
|
|
6875
|
+
line: loc.location?.physicalLocation?.region?.startLine || 0,
|
|
6876
|
+
code: "",
|
|
6877
|
+
explanation: loc.message?.text || ""
|
|
6878
|
+
})) || [];
|
|
6879
|
+
const rawFile = r.locations?.[0]?.physicalLocation?.artifactLocation?.uri;
|
|
6880
|
+
const file = typeof rawFile === "string" ? rawFile : "unknown";
|
|
6881
|
+
const rawLine = r.locations?.[0]?.physicalLocation?.region?.startLine;
|
|
6882
|
+
const line = typeof rawLine === "number" && Number.isFinite(rawLine) ? Math.floor(rawLine) : 0;
|
|
6883
|
+
const rawEndLine = r.locations?.[0]?.physicalLocation?.region?.endLine;
|
|
6884
|
+
const endLine = typeof rawEndLine === "number" && Number.isFinite(rawEndLine) ? Math.floor(rawEndLine) : void 0;
|
|
6885
|
+
const rawId = r.ruleId;
|
|
6886
|
+
const id = typeof rawId === "string" ? rawId : `WR-${String(i + 1).padStart(3, "0")}`;
|
|
6887
|
+
const validatedKind = FindingKind.safeParse(props.kind);
|
|
6888
|
+
const validatedCategory = BugCategory.safeParse(props.category);
|
|
6889
|
+
const validatedConfidence = ConfidenceLevel.safeParse(props.confidence);
|
|
6732
6890
|
return {
|
|
6733
|
-
id
|
|
6734
|
-
title:
|
|
6735
|
-
description:
|
|
6736
|
-
file
|
|
6737
|
-
line
|
|
6738
|
-
endLine
|
|
6739
|
-
kind:
|
|
6891
|
+
id,
|
|
6892
|
+
title: sanitizeSarifText(String(rawTitle), "title"),
|
|
6893
|
+
description: sanitizeSarifText(String(rawDescription), "description"),
|
|
6894
|
+
file,
|
|
6895
|
+
line,
|
|
6896
|
+
endLine,
|
|
6897
|
+
kind: validatedKind.success ? validatedKind.data : "bug",
|
|
6740
6898
|
severity: mapSarifLevel(r.level),
|
|
6741
|
-
category:
|
|
6899
|
+
category: validatedCategory.success ? validatedCategory.data : "logic-error",
|
|
6742
6900
|
confidence: {
|
|
6743
|
-
overall:
|
|
6744
|
-
codePathValidity: props.codePathValidity
|
|
6745
|
-
reachability: props.reachability
|
|
6746
|
-
intentViolation: props.intentViolation
|
|
6747
|
-
staticToolSignal: props.staticToolSignal
|
|
6748
|
-
adversarialSurvived: props.adversarialSurvived
|
|
6901
|
+
overall: validatedConfidence.success ? validatedConfidence.data : "medium",
|
|
6902
|
+
codePathValidity: typeof props.codePathValidity === "number" ? props.codePathValidity : 0.8,
|
|
6903
|
+
reachability: typeof props.reachability === "number" ? props.reachability : 0.8,
|
|
6904
|
+
intentViolation: typeof props.intentViolation === "boolean" ? props.intentViolation : false,
|
|
6905
|
+
staticToolSignal: typeof props.staticToolSignal === "boolean" ? props.staticToolSignal : false,
|
|
6906
|
+
adversarialSurvived: typeof props.adversarialSurvived === "boolean" ? props.adversarialSurvived : false
|
|
6749
6907
|
},
|
|
6750
|
-
codePath:
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
line: loc.location?.physicalLocation?.region?.startLine || 0,
|
|
6754
|
-
code: "",
|
|
6755
|
-
explanation: loc.message?.text || ""
|
|
6756
|
-
})) || [],
|
|
6757
|
-
evidence: props.evidence || [],
|
|
6758
|
-
suggestedFix: props.suggestedFix,
|
|
6908
|
+
codePath: sanitizeSarifCodePath(rawCodePath),
|
|
6909
|
+
evidence: sanitizeSarifEvidence(props.evidence),
|
|
6910
|
+
suggestedFix: props.suggestedFix ? sanitizeSarifText(String(props.suggestedFix), "suggestedFix") : void 0,
|
|
6759
6911
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6760
6912
|
status: "open"
|
|
6761
6913
|
};
|
|
6762
|
-
})
|
|
6914
|
+
});
|
|
6763
6915
|
}
|
|
6764
6916
|
async function loadBugFromGitHub(issueUrl, cwd) {
|
|
6765
6917
|
try {
|
|
@@ -6802,10 +6954,12 @@ async function loadBugFromGitHub(issueUrl, cwd) {
|
|
|
6802
6954
|
} else if (labels.some((l) => l.includes("leak") || l.includes("memory"))) {
|
|
6803
6955
|
category = "resource-leak";
|
|
6804
6956
|
}
|
|
6957
|
+
const sanitizedTitle = sanitizeSarifText(String(issue.title || ""), "github.title");
|
|
6958
|
+
const sanitizedBody = sanitizeSarifText(String(issue.body || ""), "github.body");
|
|
6805
6959
|
return {
|
|
6806
6960
|
id: `GH-${issueNumber}`,
|
|
6807
|
-
title:
|
|
6808
|
-
description:
|
|
6961
|
+
title: sanitizedTitle,
|
|
6962
|
+
description: sanitizedBody || sanitizedTitle,
|
|
6809
6963
|
file: fileMatch?.[1] || "",
|
|
6810
6964
|
line: parseInt(lineMatch?.[1] || "1", 10),
|
|
6811
6965
|
kind: "bug",
|
|
@@ -6999,12 +7153,24 @@ async function fixSingleBug(bug, config, options, cwd) {
|
|
|
6999
7153
|
process.exit(0);
|
|
7000
7154
|
}
|
|
7001
7155
|
}
|
|
7002
|
-
|
|
7003
|
-
|
|
7156
|
+
console.log();
|
|
7157
|
+
console.log(chalk3.cyan(" \u25C6 Starting agentic fix..."));
|
|
7158
|
+
console.log();
|
|
7004
7159
|
try {
|
|
7005
|
-
|
|
7160
|
+
let lastMessage = "";
|
|
7161
|
+
const result = await applyFix(bug, config, {
|
|
7162
|
+
...options,
|
|
7163
|
+
onProgress: (message) => {
|
|
7164
|
+
if (message !== lastMessage) {
|
|
7165
|
+
lastMessage = message;
|
|
7166
|
+
const truncated = message.length > 72 ? message.substring(0, 72) + "..." : message;
|
|
7167
|
+
process.stdout.write(`\r\x1B[K ${chalk3.dim("\u203A")} ${chalk3.gray(truncated)}`);
|
|
7168
|
+
}
|
|
7169
|
+
}
|
|
7170
|
+
});
|
|
7171
|
+
process.stdout.write("\r\x1B[K");
|
|
7006
7172
|
if (result.success) {
|
|
7007
|
-
|
|
7173
|
+
console.log(chalk3.green(" \u2713 Fix applied successfully"));
|
|
7008
7174
|
if (result.diff) {
|
|
7009
7175
|
console.log();
|
|
7010
7176
|
console.log(chalk3.dim(" Changes:"));
|
|
@@ -7030,12 +7196,12 @@ async function fixSingleBug(bug, config, options, cwd) {
|
|
|
7030
7196
|
}
|
|
7031
7197
|
p3.outro(chalk3.green("Fix complete!"));
|
|
7032
7198
|
} else {
|
|
7033
|
-
|
|
7199
|
+
console.log(chalk3.red(" \u2717 Fix failed"));
|
|
7034
7200
|
p3.log.error(result.error || "Unknown error");
|
|
7035
7201
|
process.exit(1);
|
|
7036
7202
|
}
|
|
7037
7203
|
} catch (error) {
|
|
7038
|
-
|
|
7204
|
+
console.log(chalk3.red(" \u2717 Fix failed"));
|
|
7039
7205
|
p3.log.error(error.message);
|
|
7040
7206
|
process.exit(1);
|
|
7041
7207
|
}
|