@shakecodeslikecray/whiterose 1.0.2 → 1.0.4
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 +288 -94
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +134 -57
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -4327,9 +4327,23 @@ function loadAccumulatedBugs(cwd) {
|
|
|
4327
4327
|
if (!Array.isArray(stored.bugs)) {
|
|
4328
4328
|
stored.bugs = [];
|
|
4329
4329
|
}
|
|
4330
|
+
if (!stored.fingerprints || typeof stored.fingerprints !== "object") {
|
|
4331
|
+
stored.fingerprints = {};
|
|
4332
|
+
}
|
|
4330
4333
|
stored.bugs = stored.bugs.map((b) => ({ ...b, kind: b.kind || "bug" }));
|
|
4331
4334
|
return stored;
|
|
4332
|
-
} catch {
|
|
4335
|
+
} catch (error) {
|
|
4336
|
+
const backupPath = `${bugsPath}.corrupted.${Date.now()}`;
|
|
4337
|
+
try {
|
|
4338
|
+
const corruptedContent = readFileSync(bugsPath, "utf-8");
|
|
4339
|
+
writeFileSync(backupPath, corruptedContent);
|
|
4340
|
+
console.warn(`Warning: ${BUGS_FILENAME} is corrupted and could not be parsed.`);
|
|
4341
|
+
console.warn(`Corrupted file backed up to: ${backupPath}`);
|
|
4342
|
+
console.warn("Bug history has been reset. Previous bugs will appear as new.");
|
|
4343
|
+
} catch {
|
|
4344
|
+
console.warn(`Warning: ${BUGS_FILENAME} is corrupted and could not be parsed.`);
|
|
4345
|
+
console.warn("Bug history has been reset. Previous bugs will appear as new.");
|
|
4346
|
+
}
|
|
4333
4347
|
return {
|
|
4334
4348
|
version: STORAGE_VERSION,
|
|
4335
4349
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -5864,7 +5878,9 @@ var FixConfirm = ({ bug, dryRun, onConfirm, onCancel, onFixComplete }) => {
|
|
|
5864
5878
|
setStatus("fixing");
|
|
5865
5879
|
setProgressMessage("Starting agentic fix...");
|
|
5866
5880
|
try {
|
|
5867
|
-
const result = await onConfirm()
|
|
5881
|
+
const result = await onConfirm((message) => {
|
|
5882
|
+
setProgressMessage(message);
|
|
5883
|
+
});
|
|
5868
5884
|
if (result.falsePositive) {
|
|
5869
5885
|
setFalsePositiveReason(result.falsePositiveReason || "The AI determined this bug is not real after analyzing the code.");
|
|
5870
5886
|
setStatus("false-positive");
|
|
@@ -6008,11 +6024,11 @@ var App = ({ bugs, config, fixOptions, onFix, onExit }) => {
|
|
|
6008
6024
|
};
|
|
6009
6025
|
const [fixError, setFixError] = useState(null);
|
|
6010
6026
|
const [lastFixedBugId, setLastFixedBugId] = useState(null);
|
|
6011
|
-
const handleConfirmFix = async () => {
|
|
6027
|
+
const handleConfirmFix = async (onProgress) => {
|
|
6012
6028
|
if (selectedBug) {
|
|
6013
6029
|
setFixError(null);
|
|
6014
6030
|
setLastFixedBugId(selectedBug.id);
|
|
6015
|
-
const result = await onFix(selectedBug);
|
|
6031
|
+
const result = await onFix(selectedBug, onProgress);
|
|
6016
6032
|
return result;
|
|
6017
6033
|
}
|
|
6018
6034
|
return { falsePositive: false };
|
|
@@ -6217,6 +6233,67 @@ function markBugAsFixed(bug, commitHash, cwd = process.cwd()) {
|
|
|
6217
6233
|
}
|
|
6218
6234
|
|
|
6219
6235
|
// src/core/fixer.ts
|
|
6236
|
+
var MAX_SARIF_TEXT_LENGTH = 2e3;
|
|
6237
|
+
var PROMPT_INJECTION_PATTERNS = [
|
|
6238
|
+
// Attempts to override or ignore instructions
|
|
6239
|
+
/ignore\s+(previous|all|above)\s+instructions?/i,
|
|
6240
|
+
/disregard\s+(previous|all|above)\s+instructions?/i,
|
|
6241
|
+
/forget\s+(previous|all|above)\s+instructions?/i,
|
|
6242
|
+
// Attempts to define new roles or personas
|
|
6243
|
+
/you\s+are\s+(now|actually)\s+/i,
|
|
6244
|
+
/act\s+as\s+(a|an)\s+/i,
|
|
6245
|
+
/pretend\s+(you|to\s+be)\s+/i,
|
|
6246
|
+
// Attempts to inject system-level commands
|
|
6247
|
+
/\[SYSTEM\]/i,
|
|
6248
|
+
/\[INST\]/i,
|
|
6249
|
+
/<\|system\|>/i,
|
|
6250
|
+
/<\|assistant\|>/i,
|
|
6251
|
+
/<\|user\|>/i,
|
|
6252
|
+
// Attempts to break out with special markers
|
|
6253
|
+
/###\s*(INSTRUCTION|SYSTEM|END|NEW)/i,
|
|
6254
|
+
/```\s*(system|instruction)/i,
|
|
6255
|
+
// Direct file operation injections
|
|
6256
|
+
/delete\s+(all|the)\s+files?/i,
|
|
6257
|
+
/rm\s+-rf\s+/i,
|
|
6258
|
+
/remove\s+(all|every)\s+file/i,
|
|
6259
|
+
// Exfiltration attempts
|
|
6260
|
+
/send\s+(this|the|all)\s+(data|content|file)/i,
|
|
6261
|
+
/upload\s+(to|this)/i,
|
|
6262
|
+
/curl\s+.*\s+-d/i,
|
|
6263
|
+
/fetch\s*\(\s*['"][^'"]*['"]\s*,\s*\{[^}]*method\s*:\s*['"]POST['"]/i
|
|
6264
|
+
];
|
|
6265
|
+
function sanitizeSarifText(text2, fieldName = "field") {
|
|
6266
|
+
if (!text2 || typeof text2 !== "string") {
|
|
6267
|
+
return "";
|
|
6268
|
+
}
|
|
6269
|
+
let sanitized = text2.length > MAX_SARIF_TEXT_LENGTH ? text2.substring(0, MAX_SARIF_TEXT_LENGTH) + `... [truncated ${fieldName}]` : text2;
|
|
6270
|
+
for (const pattern of PROMPT_INJECTION_PATTERNS) {
|
|
6271
|
+
if (pattern.test(sanitized)) {
|
|
6272
|
+
sanitized = sanitized.replace(pattern, "[REDACTED: potential injection]");
|
|
6273
|
+
}
|
|
6274
|
+
}
|
|
6275
|
+
sanitized = sanitized.replace(/```+/g, "`\u200B`\u200B`");
|
|
6276
|
+
sanitized = sanitized.replace(/###/g, "#\u200B#\u200B#");
|
|
6277
|
+
return sanitized;
|
|
6278
|
+
}
|
|
6279
|
+
function sanitizeSarifEvidence(evidence) {
|
|
6280
|
+
if (!Array.isArray(evidence)) {
|
|
6281
|
+
return [];
|
|
6282
|
+
}
|
|
6283
|
+
return evidence.filter((e) => typeof e === "string").slice(0, 10).map((e) => sanitizeSarifText(e, "evidence"));
|
|
6284
|
+
}
|
|
6285
|
+
function sanitizeSarifCodePath(codePath) {
|
|
6286
|
+
if (!Array.isArray(codePath)) {
|
|
6287
|
+
return [];
|
|
6288
|
+
}
|
|
6289
|
+
return codePath.slice(0, 20).map((entry, idx) => ({
|
|
6290
|
+
step: typeof entry?.step === "number" ? entry.step : idx + 1,
|
|
6291
|
+
file: sanitizeSarifText(String(entry?.file || ""), "codePath.file").substring(0, 500),
|
|
6292
|
+
line: typeof entry?.line === "number" ? entry.line : 0,
|
|
6293
|
+
code: sanitizeSarifText(String(entry?.code || ""), "codePath.code"),
|
|
6294
|
+
explanation: sanitizeSarifText(String(entry?.explanation || ""), "codePath.explanation")
|
|
6295
|
+
}));
|
|
6296
|
+
}
|
|
6220
6297
|
function isPathWithinProject(filePath, projectDir) {
|
|
6221
6298
|
const resolvedPath = resolve(projectDir, filePath);
|
|
6222
6299
|
const relativePath = relative(projectDir, resolvedPath);
|
|
@@ -6280,7 +6357,7 @@ In: ${bug.file}:${bug.line}`
|
|
|
6280
6357
|
}
|
|
6281
6358
|
let agenticResult;
|
|
6282
6359
|
try {
|
|
6283
|
-
agenticResult = await runAgenticFix(bug, config, projectDir);
|
|
6360
|
+
agenticResult = await runAgenticFix(bug, config, projectDir, options.onProgress);
|
|
6284
6361
|
} catch (error) {
|
|
6285
6362
|
return {
|
|
6286
6363
|
success: false,
|
|
@@ -6320,76 +6397,153 @@ In: ${bug.file}:${bug.line}`
|
|
|
6320
6397
|
commitHash
|
|
6321
6398
|
};
|
|
6322
6399
|
}
|
|
6323
|
-
async function runAgenticFix(bug, config, projectDir) {
|
|
6400
|
+
async function runAgenticFix(bug, config, projectDir, onProgress) {
|
|
6324
6401
|
const providerCommand = getProviderCommand(config.provider);
|
|
6325
6402
|
const prompt = buildAgenticFixPrompt(bug);
|
|
6326
|
-
const
|
|
6327
|
-
|
|
6328
|
-
args.push("-p", prompt, "--dangerously-skip-permissions");
|
|
6329
|
-
} else if (config.provider === "gemini") {
|
|
6330
|
-
args.push("-p", prompt);
|
|
6331
|
-
} else if (config.provider === "aider") {
|
|
6332
|
-
args.push("--message", prompt, bug.file);
|
|
6333
|
-
} else if (config.provider === "codex") ; else {
|
|
6334
|
-
args.push("-p", prompt);
|
|
6335
|
-
}
|
|
6403
|
+
const controller = new AbortController();
|
|
6404
|
+
const timeoutId = setTimeout(() => controller.abort(), 3e5);
|
|
6336
6405
|
let stdout = "";
|
|
6337
6406
|
let stderr = "";
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6407
|
+
try {
|
|
6408
|
+
if (config.provider === "codex") {
|
|
6409
|
+
const tempDir = mkdtempSync(join(tmpdir(), "whiterose-fix-"));
|
|
6410
|
+
const outputFile = join(tempDir, "output.txt");
|
|
6411
|
+
try {
|
|
6412
|
+
const result = await execa(
|
|
6413
|
+
providerCommand,
|
|
6414
|
+
[
|
|
6415
|
+
"exec",
|
|
6416
|
+
"--full-auto",
|
|
6417
|
+
// Allow workspace writes without approval prompts
|
|
6418
|
+
"--skip-git-repo-check",
|
|
6419
|
+
"-C",
|
|
6420
|
+
projectDir,
|
|
6421
|
+
// Set working directory for codex
|
|
6422
|
+
"-o",
|
|
6423
|
+
outputFile,
|
|
6424
|
+
"-"
|
|
6425
|
+
// Read prompt from stdin
|
|
6426
|
+
],
|
|
6427
|
+
{
|
|
6428
|
+
cwd: projectDir,
|
|
6429
|
+
input: prompt,
|
|
6430
|
+
// Pass prompt via stdin
|
|
6431
|
+
timeout: 3e5,
|
|
6432
|
+
env: { ...process.env, NO_COLOR: "1" },
|
|
6433
|
+
reject: false,
|
|
6434
|
+
cancelSignal: controller.signal
|
|
6435
|
+
}
|
|
6436
|
+
);
|
|
6437
|
+
stderr = result.stderr || "";
|
|
6438
|
+
if (existsSync(outputFile)) {
|
|
6439
|
+
try {
|
|
6440
|
+
stdout = readFileSync(outputFile, "utf-8");
|
|
6441
|
+
} catch {
|
|
6442
|
+
stdout = result.stdout || "";
|
|
6443
|
+
}
|
|
6444
|
+
} else {
|
|
6445
|
+
stdout = result.stdout || "";
|
|
6446
|
+
}
|
|
6447
|
+
} finally {
|
|
6448
|
+
try {
|
|
6449
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
6450
|
+
} catch {
|
|
6451
|
+
}
|
|
6452
|
+
}
|
|
6453
|
+
} else if (config.provider === "claude-code") {
|
|
6454
|
+
const args = ["--dangerously-skip-permissions", "-p"];
|
|
6455
|
+
if (onProgress) {
|
|
6456
|
+
args.push("--verbose", "--output-format", "stream-json");
|
|
6457
|
+
}
|
|
6458
|
+
const subprocess = execa(
|
|
6343
6459
|
providerCommand,
|
|
6344
|
-
|
|
6345
|
-
"exec",
|
|
6346
|
-
"--full-auto",
|
|
6347
|
-
// Allow workspace writes without approval prompts
|
|
6348
|
-
"--skip-git-repo-check",
|
|
6349
|
-
"-C",
|
|
6350
|
-
projectDir,
|
|
6351
|
-
// Set working directory for codex
|
|
6352
|
-
"-o",
|
|
6353
|
-
outputFile,
|
|
6354
|
-
"-"
|
|
6355
|
-
// Read prompt from stdin
|
|
6356
|
-
],
|
|
6460
|
+
args,
|
|
6357
6461
|
{
|
|
6358
6462
|
cwd: projectDir,
|
|
6359
6463
|
input: prompt,
|
|
6360
|
-
// Pass prompt via stdin
|
|
6464
|
+
// Pass prompt via stdin (Claude reads from stdin when no prompt arg provided)
|
|
6361
6465
|
timeout: 3e5,
|
|
6362
6466
|
env: { ...process.env, NO_COLOR: "1" },
|
|
6363
|
-
reject: false
|
|
6467
|
+
reject: false,
|
|
6468
|
+
cancelSignal: controller.signal
|
|
6364
6469
|
}
|
|
6365
6470
|
);
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6471
|
+
if (onProgress && subprocess.stdout) {
|
|
6472
|
+
let lineBuffer = "";
|
|
6473
|
+
subprocess.stdout.on("data", (chunk) => {
|
|
6474
|
+
const text2 = chunk.toString();
|
|
6475
|
+
lineBuffer += text2;
|
|
6476
|
+
const lines = lineBuffer.split("\n");
|
|
6477
|
+
lineBuffer = lines.pop() || "";
|
|
6478
|
+
for (const line of lines) {
|
|
6479
|
+
const trimmed = line.trim();
|
|
6480
|
+
if (trimmed) {
|
|
6481
|
+
try {
|
|
6482
|
+
const event = JSON.parse(trimmed);
|
|
6483
|
+
if (event.type === "assistant" && event.message?.content) {
|
|
6484
|
+
for (const block of event.message.content) {
|
|
6485
|
+
if (block.type === "tool_use") {
|
|
6486
|
+
const toolName = block.name || "tool";
|
|
6487
|
+
onProgress(`Using ${toolName}...`);
|
|
6488
|
+
} else if (block.type === "text" && block.text) {
|
|
6489
|
+
const preview = block.text.substring(0, 80).replace(/\n/g, " ").trim();
|
|
6490
|
+
if (preview) {
|
|
6491
|
+
onProgress(preview + (block.text.length > 80 ? "..." : ""));
|
|
6492
|
+
}
|
|
6493
|
+
}
|
|
6494
|
+
}
|
|
6495
|
+
}
|
|
6496
|
+
} catch {
|
|
6497
|
+
if (trimmed.length > 3 && trimmed.length < 100) {
|
|
6498
|
+
onProgress(trimmed);
|
|
6499
|
+
}
|
|
6500
|
+
}
|
|
6501
|
+
}
|
|
6502
|
+
}
|
|
6503
|
+
});
|
|
6380
6504
|
}
|
|
6505
|
+
const result = await subprocess;
|
|
6506
|
+
stdout = result.stdout || "";
|
|
6507
|
+
stderr = result.stderr || "";
|
|
6508
|
+
} else if (config.provider === "gemini") {
|
|
6509
|
+
const result = await execa(providerCommand, ["-p", prompt], {
|
|
6510
|
+
cwd: projectDir,
|
|
6511
|
+
timeout: 3e5,
|
|
6512
|
+
env: { ...process.env, NO_COLOR: "1" },
|
|
6513
|
+
reject: false,
|
|
6514
|
+
stdin: "ignore",
|
|
6515
|
+
// Prevent stdin hangs
|
|
6516
|
+
cancelSignal: controller.signal
|
|
6517
|
+
});
|
|
6518
|
+
stdout = result.stdout || "";
|
|
6519
|
+
stderr = result.stderr || "";
|
|
6520
|
+
} else if (config.provider === "aider") {
|
|
6521
|
+
const result = await execa(providerCommand, ["--message", prompt, bug.file], {
|
|
6522
|
+
cwd: projectDir,
|
|
6523
|
+
timeout: 3e5,
|
|
6524
|
+
env: { ...process.env, NO_COLOR: "1" },
|
|
6525
|
+
reject: false,
|
|
6526
|
+
stdin: "ignore",
|
|
6527
|
+
// Prevent stdin hangs
|
|
6528
|
+
cancelSignal: controller.signal
|
|
6529
|
+
});
|
|
6530
|
+
stdout = result.stdout || "";
|
|
6531
|
+
stderr = result.stderr || "";
|
|
6532
|
+
} else {
|
|
6533
|
+
const result = await execa(providerCommand, ["-p", prompt], {
|
|
6534
|
+
cwd: projectDir,
|
|
6535
|
+
timeout: 3e5,
|
|
6536
|
+
env: { ...process.env, NO_COLOR: "1" },
|
|
6537
|
+
reject: false,
|
|
6538
|
+
stdin: "ignore",
|
|
6539
|
+
// Prevent stdin hangs
|
|
6540
|
+
cancelSignal: controller.signal
|
|
6541
|
+
});
|
|
6542
|
+
stdout = result.stdout || "";
|
|
6543
|
+
stderr = result.stderr || "";
|
|
6381
6544
|
}
|
|
6382
|
-
}
|
|
6383
|
-
|
|
6384
|
-
cwd: projectDir,
|
|
6385
|
-
timeout: 3e5,
|
|
6386
|
-
// 5 minute timeout for agentic operations
|
|
6387
|
-
env: { ...process.env, NO_COLOR: "1" },
|
|
6388
|
-
reject: false
|
|
6389
|
-
// Don't throw on non-zero exit
|
|
6390
|
-
});
|
|
6391
|
-
stdout = result.stdout || "";
|
|
6392
|
-
stderr = result.stderr || "";
|
|
6545
|
+
} finally {
|
|
6546
|
+
clearTimeout(timeoutId);
|
|
6393
6547
|
}
|
|
6394
6548
|
if (stderr) {
|
|
6395
6549
|
const lowerStderr = stderr.toLowerCase();
|
|
@@ -6518,8 +6672,8 @@ function generateSimpleDiff(original, modified, filename) {
|
|
|
6518
6672
|
}
|
|
6519
6673
|
async function startFixTUI(bugs, config, options, cwd) {
|
|
6520
6674
|
return new Promise((resolve6) => {
|
|
6521
|
-
const handleFix = async (bug) => {
|
|
6522
|
-
const result = await applyFix(bug, config, options);
|
|
6675
|
+
const handleFix = async (bug, onProgress) => {
|
|
6676
|
+
const result = await applyFix(bug, config, { ...options, onProgress });
|
|
6523
6677
|
if (result.falsePositive) {
|
|
6524
6678
|
if (cwd) {
|
|
6525
6679
|
removeBugFromAccumulated(cwd, bug.id);
|
|
@@ -6678,39 +6832,67 @@ function loadBugsFromSarif(sarifPath) {
|
|
|
6678
6832
|
} catch (error) {
|
|
6679
6833
|
throw new Error(`Failed to parse SARIF file: ${sarifPath}. File may be corrupted or malformed.`);
|
|
6680
6834
|
}
|
|
6681
|
-
|
|
6835
|
+
if (!sarif || typeof sarif !== "object") {
|
|
6836
|
+
throw new Error(`Invalid SARIF file: ${sarifPath}. Expected a JSON object.`);
|
|
6837
|
+
}
|
|
6838
|
+
const runs = sarif.runs;
|
|
6839
|
+
if (!Array.isArray(runs) || runs.length === 0) {
|
|
6840
|
+
return [];
|
|
6841
|
+
}
|
|
6842
|
+
const results = runs[0]?.results;
|
|
6843
|
+
if (!Array.isArray(results)) {
|
|
6844
|
+
return [];
|
|
6845
|
+
}
|
|
6846
|
+
return results.map((r, i) => {
|
|
6847
|
+
if (!r || typeof r !== "object") {
|
|
6848
|
+
throw new Error(`Invalid SARIF result at index ${i}: expected an object.`);
|
|
6849
|
+
}
|
|
6682
6850
|
const props = r.properties || {};
|
|
6851
|
+
const rawTitle = r.message?.text || "Unknown bug";
|
|
6852
|
+
const rawDescription = r.message?.markdown || r.message?.text || "";
|
|
6853
|
+
const rawCodePath = r.codeFlows?.[0]?.threadFlows?.[0]?.locations?.map((loc, idx) => ({
|
|
6854
|
+
step: idx + 1,
|
|
6855
|
+
file: loc.location?.physicalLocation?.artifactLocation?.uri || "",
|
|
6856
|
+
line: loc.location?.physicalLocation?.region?.startLine || 0,
|
|
6857
|
+
code: "",
|
|
6858
|
+
explanation: loc.message?.text || ""
|
|
6859
|
+
})) || [];
|
|
6860
|
+
const rawFile = r.locations?.[0]?.physicalLocation?.artifactLocation?.uri;
|
|
6861
|
+
const file = typeof rawFile === "string" ? rawFile : "unknown";
|
|
6862
|
+
const rawLine = r.locations?.[0]?.physicalLocation?.region?.startLine;
|
|
6863
|
+
const line = typeof rawLine === "number" && Number.isFinite(rawLine) ? Math.floor(rawLine) : 0;
|
|
6864
|
+
const rawEndLine = r.locations?.[0]?.physicalLocation?.region?.endLine;
|
|
6865
|
+
const endLine = typeof rawEndLine === "number" && Number.isFinite(rawEndLine) ? Math.floor(rawEndLine) : void 0;
|
|
6866
|
+
const rawId = r.ruleId;
|
|
6867
|
+
const id = typeof rawId === "string" ? rawId : `WR-${String(i + 1).padStart(3, "0")}`;
|
|
6868
|
+
const validatedKind = FindingKind.safeParse(props.kind);
|
|
6869
|
+
const validatedCategory = BugCategory.safeParse(props.category);
|
|
6870
|
+
const validatedConfidence = ConfidenceLevel.safeParse(props.confidence);
|
|
6683
6871
|
return {
|
|
6684
|
-
id
|
|
6685
|
-
title:
|
|
6686
|
-
description:
|
|
6687
|
-
file
|
|
6688
|
-
line
|
|
6689
|
-
endLine
|
|
6690
|
-
kind:
|
|
6872
|
+
id,
|
|
6873
|
+
title: sanitizeSarifText(String(rawTitle), "title"),
|
|
6874
|
+
description: sanitizeSarifText(String(rawDescription), "description"),
|
|
6875
|
+
file,
|
|
6876
|
+
line,
|
|
6877
|
+
endLine,
|
|
6878
|
+
kind: validatedKind.success ? validatedKind.data : "bug",
|
|
6691
6879
|
severity: mapSarifLevel(r.level),
|
|
6692
|
-
category:
|
|
6880
|
+
category: validatedCategory.success ? validatedCategory.data : "logic-error",
|
|
6693
6881
|
confidence: {
|
|
6694
|
-
overall:
|
|
6695
|
-
codePathValidity: props.codePathValidity
|
|
6696
|
-
reachability: props.reachability
|
|
6697
|
-
intentViolation: props.intentViolation
|
|
6698
|
-
staticToolSignal: props.staticToolSignal
|
|
6699
|
-
adversarialSurvived: props.adversarialSurvived
|
|
6882
|
+
overall: validatedConfidence.success ? validatedConfidence.data : "medium",
|
|
6883
|
+
codePathValidity: typeof props.codePathValidity === "number" ? props.codePathValidity : 0.8,
|
|
6884
|
+
reachability: typeof props.reachability === "number" ? props.reachability : 0.8,
|
|
6885
|
+
intentViolation: typeof props.intentViolation === "boolean" ? props.intentViolation : false,
|
|
6886
|
+
staticToolSignal: typeof props.staticToolSignal === "boolean" ? props.staticToolSignal : false,
|
|
6887
|
+
adversarialSurvived: typeof props.adversarialSurvived === "boolean" ? props.adversarialSurvived : false
|
|
6700
6888
|
},
|
|
6701
|
-
codePath:
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
line: loc.location?.physicalLocation?.region?.startLine || 0,
|
|
6705
|
-
code: "",
|
|
6706
|
-
explanation: loc.message?.text || ""
|
|
6707
|
-
})) || [],
|
|
6708
|
-
evidence: props.evidence || [],
|
|
6709
|
-
suggestedFix: props.suggestedFix,
|
|
6889
|
+
codePath: sanitizeSarifCodePath(rawCodePath),
|
|
6890
|
+
evidence: sanitizeSarifEvidence(props.evidence),
|
|
6891
|
+
suggestedFix: props.suggestedFix ? sanitizeSarifText(String(props.suggestedFix), "suggestedFix") : void 0,
|
|
6710
6892
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6711
6893
|
status: "open"
|
|
6712
6894
|
};
|
|
6713
|
-
})
|
|
6895
|
+
});
|
|
6714
6896
|
}
|
|
6715
6897
|
async function loadBugFromGitHub(issueUrl, cwd) {
|
|
6716
6898
|
try {
|
|
@@ -6950,12 +7132,24 @@ async function fixSingleBug(bug, config, options, cwd) {
|
|
|
6950
7132
|
process.exit(0);
|
|
6951
7133
|
}
|
|
6952
7134
|
}
|
|
6953
|
-
|
|
6954
|
-
|
|
7135
|
+
console.log();
|
|
7136
|
+
console.log(chalk3.cyan(" \u25C6 Starting agentic fix..."));
|
|
7137
|
+
console.log();
|
|
6955
7138
|
try {
|
|
6956
|
-
|
|
7139
|
+
let lastMessage = "";
|
|
7140
|
+
const result = await applyFix(bug, config, {
|
|
7141
|
+
...options,
|
|
7142
|
+
onProgress: (message) => {
|
|
7143
|
+
if (message !== lastMessage) {
|
|
7144
|
+
lastMessage = message;
|
|
7145
|
+
const truncated = message.length > 72 ? message.substring(0, 72) + "..." : message;
|
|
7146
|
+
process.stdout.write(`\r\x1B[K ${chalk3.dim("\u203A")} ${chalk3.gray(truncated)}`);
|
|
7147
|
+
}
|
|
7148
|
+
}
|
|
7149
|
+
});
|
|
7150
|
+
process.stdout.write("\r\x1B[K");
|
|
6957
7151
|
if (result.success) {
|
|
6958
|
-
|
|
7152
|
+
console.log(chalk3.green(" \u2713 Fix applied successfully"));
|
|
6959
7153
|
if (result.diff) {
|
|
6960
7154
|
console.log();
|
|
6961
7155
|
console.log(chalk3.dim(" Changes:"));
|
|
@@ -6981,12 +7175,12 @@ async function fixSingleBug(bug, config, options, cwd) {
|
|
|
6981
7175
|
}
|
|
6982
7176
|
p3.outro(chalk3.green("Fix complete!"));
|
|
6983
7177
|
} else {
|
|
6984
|
-
|
|
7178
|
+
console.log(chalk3.red(" \u2717 Fix failed"));
|
|
6985
7179
|
p3.log.error(result.error || "Unknown error");
|
|
6986
7180
|
process.exit(1);
|
|
6987
7181
|
}
|
|
6988
7182
|
} catch (error) {
|
|
6989
|
-
|
|
7183
|
+
console.log(chalk3.red(" \u2717 Fix failed"));
|
|
6990
7184
|
p3.log.error(error.message);
|
|
6991
7185
|
process.exit(1);
|
|
6992
7186
|
}
|