bugzero 0.0.30 → 0.0.32
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/.turbo/turbo-build.log +4 -4
- package/README.md +2 -0
- package/dist/index.js +241 -63
- package/package.json +1 -1
- package/src/index.ts +2 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> bugzero@0.0.
|
|
2
|
+
> bugzero@0.0.32 build /home/runner/work/Bugzero/Bugzero/apps/bugzero
|
|
3
3
|
> tsup src/index.ts --format cjs --dts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
[34mCLI[39m tsup v8.5.1
|
|
8
8
|
[34mCLI[39m Target: es2022
|
|
9
9
|
[34mCJS[39m Build start
|
|
10
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
11
|
-
[32mCJS[39m ⚡️ Build success in
|
|
10
|
+
[32mCJS[39m [1mdist/index.js [22m[32m77.80 KB[39m
|
|
11
|
+
[32mCJS[39m ⚡️ Build success in 32ms
|
|
12
12
|
[34mDTS[39m Build start
|
|
13
|
-
[32mDTS[39m ⚡️ Build success in
|
|
13
|
+
[32mDTS[39m ⚡️ Build success in 1160ms
|
|
14
14
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m20.00 B[39m
|
package/README.md
CHANGED
|
@@ -74,6 +74,8 @@ bugzero rescue
|
|
|
74
74
|
| Multi-model support | DeepSeek, Claude, GPT-4o, Gemini, Llama via OpenRouter |
|
|
75
75
|
| Framework detection | Automatically identifies your project's tooling setup |
|
|
76
76
|
| Safe file patching | Every modified file receives a `.opspilot.bak` backup |
|
|
77
|
+
| Fuzzy patch matching | Falls back from exact match to whitespace-normalized and similarity-scored matching when the AI's snippet doesn't match the file verbatim |
|
|
78
|
+
| Multi-file patches | A single fix attempt can edit several files at once, applied atomically — if any file's patch fails, every file touched in that attempt is rolled back |
|
|
77
79
|
| Error type parsing | Parses TypeScript, ESLint, and Jest error formats |
|
|
78
80
|
| Dry-run mode | Analyze and report without writing any files |
|
|
79
81
|
| Local model config | Save preferred model to `.bugzerorc` per project |
|
package/dist/index.js
CHANGED
|
@@ -346,9 +346,9 @@ var require_main = __commonJS({
|
|
|
346
346
|
}
|
|
347
347
|
});
|
|
348
348
|
|
|
349
|
-
//
|
|
349
|
+
// ../../packages/config/dist/index.js
|
|
350
350
|
var require_dist = __commonJS({
|
|
351
|
-
"
|
|
351
|
+
"../../packages/config/dist/index.js"(exports2, module2) {
|
|
352
352
|
"use strict";
|
|
353
353
|
var __create2 = Object.create;
|
|
354
354
|
var __defProp2 = Object.defineProperty;
|
|
@@ -433,9 +433,9 @@ var require_dist = __commonJS({
|
|
|
433
433
|
}
|
|
434
434
|
});
|
|
435
435
|
|
|
436
|
-
//
|
|
436
|
+
// ../../packages/analyzers/dist/index.js
|
|
437
437
|
var require_dist2 = __commonJS({
|
|
438
|
-
"
|
|
438
|
+
"../../packages/analyzers/dist/index.js"(exports2, module2) {
|
|
439
439
|
"use strict";
|
|
440
440
|
var __create2 = Object.create;
|
|
441
441
|
var __defProp2 = Object.defineProperty;
|
|
@@ -586,9 +586,9 @@ var require_dist2 = __commonJS({
|
|
|
586
586
|
}
|
|
587
587
|
});
|
|
588
588
|
|
|
589
|
-
//
|
|
589
|
+
// ../../packages/ai-provider/dist/index.js
|
|
590
590
|
var require_dist3 = __commonJS({
|
|
591
|
-
"
|
|
591
|
+
"../../packages/ai-provider/dist/index.js"(exports2, module2) {
|
|
592
592
|
"use strict";
|
|
593
593
|
var __create2 = Object.create;
|
|
594
594
|
var __defProp2 = Object.defineProperty;
|
|
@@ -709,9 +709,9 @@ var require_dist3 = __commonJS({
|
|
|
709
709
|
}
|
|
710
710
|
});
|
|
711
711
|
|
|
712
|
-
//
|
|
712
|
+
// ../../packages/prompts/dist/index.js
|
|
713
713
|
var require_dist4 = __commonJS({
|
|
714
|
-
"
|
|
714
|
+
"../../packages/prompts/dist/index.js"(exports2, module2) {
|
|
715
715
|
"use strict";
|
|
716
716
|
var __create2 = Object.create;
|
|
717
717
|
var __defProp2 = Object.defineProperty;
|
|
@@ -908,29 +908,35 @@ ${compilerLogs}
|
|
|
908
908
|
Your task:
|
|
909
909
|
1. Root Cause: Identify the root cause of the build failure.
|
|
910
910
|
2. Codebase Context: Read the provided file contents and directory listings under "\u{1F4C1} Codebase Context" to locate the correct files, imports, and file paths. Do not guess filenames or contents that are not in the context.
|
|
911
|
-
3. Patch: Provide the minimal, precise fix.
|
|
911
|
+
3. Patch: Provide the minimal, precise fix. If the fix genuinely requires changes in more than one file (for example, a renamed export and every place that imports it), include one patch entry per file \u2014 all patches in your response are applied together, atomically.
|
|
912
912
|
|
|
913
913
|
Reply with ONLY a valid JSON object in this exact shape \u2014 no markdown fences, no extra text:
|
|
914
914
|
{
|
|
915
915
|
"rootCause": "One-sentence explanation of the error",
|
|
916
|
-
"
|
|
917
|
-
"
|
|
918
|
-
|
|
919
|
-
|
|
916
|
+
"explanation": "short explanation of what you changed and why",
|
|
917
|
+
"patches": [
|
|
918
|
+
{
|
|
919
|
+
"filePath": "relative/path/from/project/root/to/file.ts",
|
|
920
|
+
"search": "exact code that currently exists in the file and must be replaced",
|
|
921
|
+
"replace": "the corrected code that replaces the search string"
|
|
922
|
+
}
|
|
923
|
+
]
|
|
920
924
|
}
|
|
921
925
|
|
|
922
926
|
Critical rules:
|
|
923
|
-
- "
|
|
924
|
-
- "
|
|
925
|
-
- "
|
|
927
|
+
- "patches" must contain at least one entry. Only include more than one when the fix truly requires editing multiple files \u2014 most fixes need just one.
|
|
928
|
+
- Each "filePath" must be a relative path from the project root (no leading /).
|
|
929
|
+
- Each "search" must be an EXACT character-for-character substring of that file's current content.
|
|
930
|
+
- Each "replace" must be syntactically valid code.
|
|
931
|
+
- If two patches target the same file, list them in the order they should be applied, and make sure each "search" reflects the file's content *after* the previous patch in this list has been applied to it.
|
|
926
932
|
- Do NOT add backticks, markdown, or any text outside the JSON object.`;
|
|
927
933
|
}
|
|
928
934
|
}
|
|
929
935
|
});
|
|
930
936
|
|
|
931
|
-
//
|
|
937
|
+
// ../../packages/patcher/dist/index.js
|
|
932
938
|
var require_dist5 = __commonJS({
|
|
933
|
-
"
|
|
939
|
+
"../../packages/patcher/dist/index.js"(exports2, module2) {
|
|
934
940
|
"use strict";
|
|
935
941
|
var __create2 = Object.create;
|
|
936
942
|
var __defProp2 = Object.defineProperty;
|
|
@@ -961,11 +967,113 @@ var require_dist5 = __commonJS({
|
|
|
961
967
|
var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
962
968
|
var index_exports = {};
|
|
963
969
|
__export(index_exports, {
|
|
964
|
-
applyPatch: () => applyPatch
|
|
970
|
+
applyPatch: () => applyPatch,
|
|
971
|
+
applyPatches: () => applyPatches,
|
|
972
|
+
findMatch: () => findMatch,
|
|
973
|
+
lineSimilarity: () => lineSimilarity
|
|
965
974
|
});
|
|
966
975
|
module2.exports = __toCommonJS(index_exports);
|
|
967
976
|
var import_fs = __toESM2(require("fs"));
|
|
968
977
|
var import_path2 = __toESM2(require("path"));
|
|
978
|
+
var SIMILARITY_THRESHOLD = 0.85;
|
|
979
|
+
var AMBIGUITY_MARGIN = 0.05;
|
|
980
|
+
var MAX_LINES_FOR_SIMILARITY_PASS = 2e4;
|
|
981
|
+
function splitLinesWithOffsets(text) {
|
|
982
|
+
const lines = [];
|
|
983
|
+
let start = 0;
|
|
984
|
+
for (let i = 0; i < text.length; i++) {
|
|
985
|
+
if (text[i] === "\n") {
|
|
986
|
+
let end = i;
|
|
987
|
+
if (end > start && text[end - 1] === "\r") end -= 1;
|
|
988
|
+
lines.push({ text: text.slice(start, end), start, end });
|
|
989
|
+
start = i + 1;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
lines.push({ text: text.slice(start), start, end: text.length });
|
|
993
|
+
return lines;
|
|
994
|
+
}
|
|
995
|
+
function normalizeLine(line) {
|
|
996
|
+
return line.trim().replace(/\s+/g, " ");
|
|
997
|
+
}
|
|
998
|
+
function levenshtein(a, b) {
|
|
999
|
+
const m = a.length;
|
|
1000
|
+
const n = b.length;
|
|
1001
|
+
if (m === 0) return n;
|
|
1002
|
+
if (n === 0) return m;
|
|
1003
|
+
const dp = new Array(n + 1);
|
|
1004
|
+
for (let j = 0; j <= n; j++) dp[j] = j;
|
|
1005
|
+
for (let i = 1; i <= m; i++) {
|
|
1006
|
+
let prev = dp[0];
|
|
1007
|
+
dp[0] = i;
|
|
1008
|
+
for (let j = 1; j <= n; j++) {
|
|
1009
|
+
const temp = dp[j];
|
|
1010
|
+
dp[j] = a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
|
|
1011
|
+
prev = temp;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return dp[n];
|
|
1015
|
+
}
|
|
1016
|
+
function lineSimilarity(a, b) {
|
|
1017
|
+
const maxLen = Math.max(a.length, b.length);
|
|
1018
|
+
if (maxLen === 0) return 1;
|
|
1019
|
+
return 1 - levenshtein(a, b) / maxLen;
|
|
1020
|
+
}
|
|
1021
|
+
function findWhitespaceNormalizedMatch(content, search) {
|
|
1022
|
+
const searchLines = search.split(/\r\n|\n/).map(normalizeLine);
|
|
1023
|
+
const contentLines = splitLinesWithOffsets(content);
|
|
1024
|
+
if (searchLines.length === 0 || searchLines.length > contentLines.length) return null;
|
|
1025
|
+
const normalizedContentLines = contentLines.map((l) => normalizeLine(l.text));
|
|
1026
|
+
for (let i = 0; i + searchLines.length <= contentLines.length; i++) {
|
|
1027
|
+
let matches = true;
|
|
1028
|
+
for (let j = 0; j < searchLines.length; j++) {
|
|
1029
|
+
if (normalizedContentLines[i + j] !== searchLines[j]) {
|
|
1030
|
+
matches = false;
|
|
1031
|
+
break;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
if (matches) {
|
|
1035
|
+
const firstLine = contentLines[i];
|
|
1036
|
+
const lastLine = contentLines[i + searchLines.length - 1];
|
|
1037
|
+
return { start: firstLine.start, end: lastLine.end, strategy: "whitespace", score: 1 };
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
return null;
|
|
1041
|
+
}
|
|
1042
|
+
function findSimilarityMatch(content, search) {
|
|
1043
|
+
const searchLines = search.split(/\r\n|\n/);
|
|
1044
|
+
const contentLines = splitLinesWithOffsets(content);
|
|
1045
|
+
if (searchLines.length === 0 || searchLines.length > contentLines.length) return null;
|
|
1046
|
+
if (contentLines.length > MAX_LINES_FOR_SIMILARITY_PASS) return null;
|
|
1047
|
+
let bestIndex = -1;
|
|
1048
|
+
let bestScore = -1;
|
|
1049
|
+
let secondBestScore = -1;
|
|
1050
|
+
for (let i = 0; i + searchLines.length <= contentLines.length; i++) {
|
|
1051
|
+
let total = 0;
|
|
1052
|
+
for (let j = 0; j < searchLines.length; j++) {
|
|
1053
|
+
total += lineSimilarity(searchLines[j], contentLines[i + j].text);
|
|
1054
|
+
}
|
|
1055
|
+
const avgScore = total / searchLines.length;
|
|
1056
|
+
if (avgScore > bestScore) {
|
|
1057
|
+
secondBestScore = bestScore;
|
|
1058
|
+
bestScore = avgScore;
|
|
1059
|
+
bestIndex = i;
|
|
1060
|
+
} else if (avgScore > secondBestScore) {
|
|
1061
|
+
secondBestScore = avgScore;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
if (bestIndex === -1 || bestScore < SIMILARITY_THRESHOLD) return null;
|
|
1065
|
+
if (secondBestScore >= 0 && bestScore - secondBestScore < AMBIGUITY_MARGIN) return null;
|
|
1066
|
+
const firstLine = contentLines[bestIndex];
|
|
1067
|
+
const lastLine = contentLines[bestIndex + searchLines.length - 1];
|
|
1068
|
+
return { start: firstLine.start, end: lastLine.end, strategy: "similarity", score: bestScore };
|
|
1069
|
+
}
|
|
1070
|
+
function findMatch(content, search) {
|
|
1071
|
+
const exactIndex = content.indexOf(search);
|
|
1072
|
+
if (exactIndex !== -1) {
|
|
1073
|
+
return { start: exactIndex, end: exactIndex + search.length, strategy: "exact", score: 1 };
|
|
1074
|
+
}
|
|
1075
|
+
return findWhitespaceNormalizedMatch(content, search) ?? findSimilarityMatch(content, search);
|
|
1076
|
+
}
|
|
969
1077
|
function applyPatch(absoluteFilePath, search, replace) {
|
|
970
1078
|
try {
|
|
971
1079
|
if (!import_fs.default.existsSync(absoluteFilePath)) {
|
|
@@ -975,33 +1083,88 @@ var require_dist5 = __commonJS({
|
|
|
975
1083
|
};
|
|
976
1084
|
}
|
|
977
1085
|
const original = import_fs.default.readFileSync(absoluteFilePath, "utf-8");
|
|
978
|
-
|
|
1086
|
+
const match = findMatch(original, search);
|
|
1087
|
+
if (!match) {
|
|
979
1088
|
return {
|
|
980
1089
|
success: false,
|
|
981
|
-
error: `Search string not found in ${import_path2.default.basename(absoluteFilePath)}. The AI's "search" field did not match file content.`
|
|
1090
|
+
error: `Search string not found in ${import_path2.default.basename(absoluteFilePath)} (tried exact, whitespace-normalized, and fuzzy matching). The AI's "search" field did not match file content.`
|
|
982
1091
|
};
|
|
983
1092
|
}
|
|
984
1093
|
const backupPath = absoluteFilePath + ".opspilot.bak";
|
|
985
1094
|
import_fs.default.writeFileSync(backupPath, original, "utf-8");
|
|
986
|
-
const fixed = original.
|
|
1095
|
+
const fixed = original.slice(0, match.start) + replace + original.slice(match.end);
|
|
987
1096
|
import_fs.default.writeFileSync(absoluteFilePath, fixed, "utf-8");
|
|
988
|
-
return { success: true, backupPath };
|
|
1097
|
+
return { success: true, backupPath, matchStrategy: match.strategy };
|
|
989
1098
|
} catch (err) {
|
|
990
1099
|
return { success: false, error: err.message };
|
|
991
1100
|
}
|
|
992
1101
|
}
|
|
1102
|
+
var import_fs2 = __toESM2(require("fs"));
|
|
1103
|
+
var import_path22 = __toESM2(require("path"));
|
|
1104
|
+
function rollback(originalContent, backupPaths) {
|
|
1105
|
+
for (const [absolutePath, content] of originalContent) {
|
|
1106
|
+
try {
|
|
1107
|
+
import_fs2.default.writeFileSync(absolutePath, content, "utf-8");
|
|
1108
|
+
} catch {
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
for (const backupPath of backupPaths) {
|
|
1112
|
+
try {
|
|
1113
|
+
import_fs2.default.unlinkSync(backupPath);
|
|
1114
|
+
} catch {
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
function applyPatches(cwd, patches) {
|
|
1119
|
+
if (patches.length === 0) {
|
|
1120
|
+
return { success: false, error: "No patches to apply.", applied: [] };
|
|
1121
|
+
}
|
|
1122
|
+
const originalContent = /* @__PURE__ */ new Map();
|
|
1123
|
+
const backupPaths = /* @__PURE__ */ new Set();
|
|
1124
|
+
const applied = [];
|
|
1125
|
+
for (const patch of patches) {
|
|
1126
|
+
const absolutePath = import_path22.default.resolve(cwd, patch.filePath);
|
|
1127
|
+
if (!originalContent.has(absolutePath)) {
|
|
1128
|
+
try {
|
|
1129
|
+
originalContent.set(absolutePath, import_fs2.default.readFileSync(absolutePath, "utf-8"));
|
|
1130
|
+
} catch {
|
|
1131
|
+
rollback(originalContent, backupPaths);
|
|
1132
|
+
return {
|
|
1133
|
+
success: false,
|
|
1134
|
+
error: `Failed to patch "${patch.filePath}": File not found: ${absolutePath}`,
|
|
1135
|
+
applied: []
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
const result = applyPatch(absolutePath, patch.search, patch.replace);
|
|
1140
|
+
if (result.backupPath) backupPaths.add(result.backupPath);
|
|
1141
|
+
if (!result.success) {
|
|
1142
|
+
rollback(originalContent, backupPaths);
|
|
1143
|
+
return {
|
|
1144
|
+
success: false,
|
|
1145
|
+
error: `Failed to patch "${patch.filePath}": ${result.error}`,
|
|
1146
|
+
applied: []
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
applied.push({
|
|
1150
|
+
filePath: patch.filePath,
|
|
1151
|
+
absolutePath,
|
|
1152
|
+
backupPath: result.backupPath,
|
|
1153
|
+
matchStrategy: result.matchStrategy
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
return { success: true, applied };
|
|
1157
|
+
}
|
|
993
1158
|
}
|
|
994
1159
|
});
|
|
995
1160
|
|
|
996
|
-
//
|
|
1161
|
+
// ../../packages/agents/dist/index.js
|
|
997
1162
|
var require_dist6 = __commonJS({
|
|
998
|
-
"
|
|
1163
|
+
"../../packages/agents/dist/index.js"(exports2, module2) {
|
|
999
1164
|
"use strict";
|
|
1000
|
-
var __create2 = Object.create;
|
|
1001
1165
|
var __defProp2 = Object.defineProperty;
|
|
1002
1166
|
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
1003
1167
|
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
1004
|
-
var __getProtoOf2 = Object.getPrototypeOf;
|
|
1005
1168
|
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
1006
1169
|
var __export = (target, all) => {
|
|
1007
1170
|
for (var name in all)
|
|
@@ -1015,14 +1178,6 @@ var require_dist6 = __commonJS({
|
|
|
1015
1178
|
}
|
|
1016
1179
|
return to;
|
|
1017
1180
|
};
|
|
1018
|
-
var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps2(
|
|
1019
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
1020
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
1021
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
1022
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
1023
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target,
|
|
1024
|
-
mod
|
|
1025
|
-
));
|
|
1026
1181
|
var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
1027
1182
|
var index_exports = {};
|
|
1028
1183
|
__export(index_exports, {
|
|
@@ -1030,7 +1185,6 @@ var require_dist6 = __commonJS({
|
|
|
1030
1185
|
});
|
|
1031
1186
|
module2.exports = __toCommonJS(index_exports);
|
|
1032
1187
|
var import_langgraph2 = require("@langchain/langgraph");
|
|
1033
|
-
var import_path2 = __toESM2(require("path"));
|
|
1034
1188
|
var import_langgraph = require("@langchain/langgraph");
|
|
1035
1189
|
var GraphState = import_langgraph.Annotation.Root({
|
|
1036
1190
|
/** Absolute path to the project being fixed */
|
|
@@ -1102,7 +1256,12 @@ var require_dist6 = __commonJS({
|
|
|
1102
1256
|
const cleaned = response.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim();
|
|
1103
1257
|
const jsonMatch = cleaned.match(/\{[\s\S]*\}/);
|
|
1104
1258
|
if (jsonMatch) {
|
|
1105
|
-
|
|
1259
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
1260
|
+
if (Array.isArray(parsed.patches) && parsed.patches.length > 0) {
|
|
1261
|
+
fixSuggestion = parsed;
|
|
1262
|
+
} else {
|
|
1263
|
+
console.warn('[BugZero] AI response JSON did not contain a non-empty "patches" array.');
|
|
1264
|
+
}
|
|
1106
1265
|
} else {
|
|
1107
1266
|
console.warn("[BugZero] AI response did not contain a valid JSON object.");
|
|
1108
1267
|
}
|
|
@@ -1123,24 +1282,28 @@ var require_dist6 = __commonJS({
|
|
|
1123
1282
|
console.warn("[BugZero] No fix suggestion available \u2014 skipping patch.");
|
|
1124
1283
|
return {};
|
|
1125
1284
|
}
|
|
1126
|
-
const {
|
|
1127
|
-
const
|
|
1128
|
-
console.log(`[BugZero] Patching: ${
|
|
1285
|
+
const { patches, explanation } = state.fixSuggestion;
|
|
1286
|
+
const fileList = patches.map((p) => p.filePath).join(", ");
|
|
1287
|
+
console.log(`[BugZero] Patching ${patches.length} file${patches.length === 1 ? "" : "s"}: ${fileList}`);
|
|
1129
1288
|
console.log(`[BugZero] Reason: ${explanation}`);
|
|
1130
|
-
const result = (0, import_patcher.
|
|
1289
|
+
const result = (0, import_patcher.applyPatches)(state.cwd, patches);
|
|
1131
1290
|
if (!result.success) {
|
|
1132
1291
|
console.error(`[BugZero] Patch failed: ${result.error}`);
|
|
1133
1292
|
const updatedLogs = `${state.logs}
|
|
1134
1293
|
|
|
1135
|
-
\u26A0\uFE0F [BugZero System Warning] Your previous patch suggestion
|
|
1294
|
+
\u26A0\uFE0F [BugZero System Warning] Your previous patch suggestion failed with the following error:
|
|
1136
1295
|
- ${result.error}
|
|
1137
1296
|
|
|
1138
|
-
Please check if the file path
|
|
1297
|
+
Any other files from that same suggestion were rolled back to keep the change atomic. Please check if the file path(s) are correct relative to the project root and make sure you target the correct file(s) that contain the build error.`;
|
|
1139
1298
|
return {
|
|
1140
1299
|
logs: updatedLogs
|
|
1141
1300
|
};
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1301
|
+
}
|
|
1302
|
+
for (const applied of result.applied) {
|
|
1303
|
+
console.log(`[BugZero] Backup saved to: ${applied.backupPath}`);
|
|
1304
|
+
if (applied.matchStrategy !== "exact") {
|
|
1305
|
+
console.log(`[BugZero] Note: exact match failed for ${applied.filePath} \u2014 patch applied via ${applied.matchStrategy} matching.`);
|
|
1306
|
+
}
|
|
1144
1307
|
}
|
|
1145
1308
|
return {};
|
|
1146
1309
|
}
|
|
@@ -1178,9 +1341,9 @@ Please check if the file path is correct relative to the project root and make s
|
|
|
1178
1341
|
}
|
|
1179
1342
|
});
|
|
1180
1343
|
|
|
1181
|
-
//
|
|
1344
|
+
// ../../packages/core/dist/index.js
|
|
1182
1345
|
var require_dist7 = __commonJS({
|
|
1183
|
-
"
|
|
1346
|
+
"../../packages/core/dist/index.js"(exports2, module2) {
|
|
1184
1347
|
"use strict";
|
|
1185
1348
|
var __create2 = Object.create;
|
|
1186
1349
|
var __defProp2 = Object.defineProperty;
|
|
@@ -1327,6 +1490,30 @@ var require_dist7 = __commonJS({
|
|
|
1327
1490
|
});
|
|
1328
1491
|
return result;
|
|
1329
1492
|
}
|
|
1493
|
+
function formatPatchesForPrompt(appliedFix) {
|
|
1494
|
+
return appliedFix.patches.map(
|
|
1495
|
+
(p, i) => `File ${i + 1}: ${p.filePath}
|
|
1496
|
+
- Search code:
|
|
1497
|
+
${p.search}
|
|
1498
|
+
- Replace code:
|
|
1499
|
+
${p.replace}`
|
|
1500
|
+
).join("\n\n");
|
|
1501
|
+
}
|
|
1502
|
+
function formatPatchesMarkdown(appliedFix) {
|
|
1503
|
+
return appliedFix.patches.map(
|
|
1504
|
+
(p) => `**File:** \`${p.filePath}\`
|
|
1505
|
+
|
|
1506
|
+
**Search (Before):**
|
|
1507
|
+
\`\`\`typescript
|
|
1508
|
+
${p.search}
|
|
1509
|
+
\`\`\`
|
|
1510
|
+
|
|
1511
|
+
**Replace (After):**
|
|
1512
|
+
\`\`\`typescript
|
|
1513
|
+
${p.replace}
|
|
1514
|
+
\`\`\``
|
|
1515
|
+
).join("\n\n---\n\n");
|
|
1516
|
+
}
|
|
1330
1517
|
async function writeReport(cwd, type, data) {
|
|
1331
1518
|
let content = "";
|
|
1332
1519
|
const provider = new import_ai_provider.OpenRouterProvider();
|
|
@@ -1405,14 +1592,12 @@ ${logs}
|
|
|
1405
1592
|
const { success, attempts, maxAttempts, appliedFix, error, rawOutput, modelUsed, promptTokens, completionTokens } = data;
|
|
1406
1593
|
if (success && appliedFix) {
|
|
1407
1594
|
console.log("[BugZero] Calling AI to write solution summary report...");
|
|
1408
|
-
const
|
|
1595
|
+
const patchedFiles = appliedFix.patches.map((p) => p.filePath).join(", ");
|
|
1596
|
+
const prompt = `You are an expert software engineer assistant. An automated AI agent successfully resolved a build/lint/test failure in a project located at "${cwd}" after ${attempts} attempts by applying a patch to: ${patchedFiles}.
|
|
1409
1597
|
Here is the patch details:
|
|
1410
1598
|
- Root Cause: ${appliedFix.rootCause}
|
|
1411
1599
|
- Explanation: ${appliedFix.explanation}
|
|
1412
|
-
|
|
1413
|
-
${appliedFix.search}
|
|
1414
|
-
- Replace code:
|
|
1415
|
-
${appliedFix.replace}
|
|
1600
|
+
${formatPatchesForPrompt(appliedFix)}
|
|
1416
1601
|
|
|
1417
1602
|
Please generate a professional, beautifully formatted Markdown report summarizing:
|
|
1418
1603
|
1. **Repair Summary:** Celebrate the success and explain the fix.
|
|
@@ -1445,20 +1630,12 @@ Generate the Markdown report directly. Do not wrap it in markdown block fences (
|
|
|
1445
1630
|
- **Token Usage:** ${promptTokens !== void 0 && completionTokens !== void 0 ? `Prompt: **${promptTokens}** | Completion: **${completionTokens}** | Total: **${promptTokens + completionTokens}**` : "*N/A*"}
|
|
1446
1631
|
|
|
1447
1632
|
## \u{1F6E0}\uFE0F Applied Solution
|
|
1448
|
-
- **Target File:**
|
|
1633
|
+
- **Target File(s):** ${appliedFix.patches.map((p) => `\`${p.filePath}\``).join(", ")}
|
|
1449
1634
|
- **Root Cause:** ${appliedFix.rootCause}
|
|
1450
1635
|
- **Explanation:** ${appliedFix.explanation}
|
|
1451
1636
|
|
|
1452
1637
|
### \u{1F4DD} Code Changes
|
|
1453
|
-
|
|
1454
|
-
\`\`\`typescript
|
|
1455
|
-
${appliedFix.search}
|
|
1456
|
-
\`\`\`
|
|
1457
|
-
|
|
1458
|
-
**Replace (After):**
|
|
1459
|
-
\`\`\`typescript
|
|
1460
|
-
${appliedFix.replace}
|
|
1461
|
-
\`\`\`
|
|
1638
|
+
${formatPatchesMarkdown(appliedFix)}
|
|
1462
1639
|
`;
|
|
1463
1640
|
}
|
|
1464
1641
|
} else {
|
|
@@ -1588,7 +1765,8 @@ program.command("rescue").description("Detect build failures and automatically a
|
|
|
1588
1765
|
console.log(` Tokens: Prompt: ${result.promptTokens} | Completion: ${result.completionTokens} | Total: ${result.promptTokens + result.completionTokens}`);
|
|
1589
1766
|
}
|
|
1590
1767
|
if (result.appliedFix) {
|
|
1591
|
-
|
|
1768
|
+
const files = result.appliedFix.patches.map((p) => p.filePath).join(", ");
|
|
1769
|
+
console.log(` File${result.appliedFix.patches.length === 1 ? "" : "s"}: ${files}`);
|
|
1592
1770
|
console.log(` Reason: ${result.appliedFix.explanation}`);
|
|
1593
1771
|
console.log(` Root cause: ${result.appliedFix.rootCause}`);
|
|
1594
1772
|
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -75,7 +75,8 @@ program
|
|
|
75
75
|
console.log(` Tokens: Prompt: ${result.promptTokens} | Completion: ${result.completionTokens} | Total: ${result.promptTokens + result.completionTokens}`);
|
|
76
76
|
}
|
|
77
77
|
if (result.appliedFix) {
|
|
78
|
-
|
|
78
|
+
const files = result.appliedFix.patches.map((p) => p.filePath).join(", ");
|
|
79
|
+
console.log(` File${result.appliedFix.patches.length === 1 ? "" : "s"}: ${files}`);
|
|
79
80
|
console.log(` Reason: ${result.appliedFix.explanation}`);
|
|
80
81
|
console.log(` Root cause: ${result.appliedFix.rootCause}`);
|
|
81
82
|
}
|