bugzero 0.0.30 → 0.0.31

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > bugzero@0.0.30 build /home/runner/work/Bugzero/Bugzero/packages/cli
2
+ > bugzero@0.0.31 build /home/runner/work/Bugzero/Bugzero/apps/bugzero
3
3
  > tsup src/index.ts --format cjs --dts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -7,8 +7,8 @@
7
7
  CLI tsup v8.5.1
8
8
  CLI Target: es2022
9
9
  CJS Build start
10
- CJS dist/index.js 70.42 KB
10
+ CJS dist/index.js 74.91 KB
11
11
  CJS ⚡️ Build success in 34ms
12
12
  DTS Build start
13
- DTS ⚡️ Build success in 1230ms
13
+ DTS ⚡️ Build success in 1100ms
14
14
  DTS dist/index.d.ts 20.00 B
package/README.md CHANGED
@@ -74,6 +74,7 @@ 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 |
77
78
  | Error type parsing | Parses TypeScript, ESLint, and Jest error formats |
78
79
  | Dry-run mode | Analyze and report without writing any files |
79
80
  | 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
- // ../config/dist/index.js
349
+ // ../../packages/config/dist/index.js
350
350
  var require_dist = __commonJS({
351
- "../config/dist/index.js"(exports2, module2) {
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
- // ../analyzers/dist/index.js
436
+ // ../../packages/analyzers/dist/index.js
437
437
  var require_dist2 = __commonJS({
438
- "../analyzers/dist/index.js"(exports2, module2) {
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
- // ../ai-provider/dist/index.js
589
+ // ../../packages/ai-provider/dist/index.js
590
590
  var require_dist3 = __commonJS({
591
- "../ai-provider/dist/index.js"(exports2, module2) {
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
- // ../prompts/dist/index.js
712
+ // ../../packages/prompts/dist/index.js
713
713
  var require_dist4 = __commonJS({
714
- "../prompts/dist/index.js"(exports2, module2) {
714
+ "../../packages/prompts/dist/index.js"(exports2, module2) {
715
715
  "use strict";
716
716
  var __create2 = Object.create;
717
717
  var __defProp2 = Object.defineProperty;
@@ -928,9 +928,9 @@ Critical rules:
928
928
  }
929
929
  });
930
930
 
931
- // ../patcher/dist/index.js
931
+ // ../../packages/patcher/dist/index.js
932
932
  var require_dist5 = __commonJS({
933
- "../patcher/dist/index.js"(exports2, module2) {
933
+ "../../packages/patcher/dist/index.js"(exports2, module2) {
934
934
  "use strict";
935
935
  var __create2 = Object.create;
936
936
  var __defProp2 = Object.defineProperty;
@@ -961,11 +961,112 @@ var require_dist5 = __commonJS({
961
961
  var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
962
962
  var index_exports = {};
963
963
  __export(index_exports, {
964
- applyPatch: () => applyPatch
964
+ applyPatch: () => applyPatch,
965
+ findMatch: () => findMatch,
966
+ lineSimilarity: () => lineSimilarity
965
967
  });
966
968
  module2.exports = __toCommonJS(index_exports);
967
969
  var import_fs = __toESM2(require("fs"));
968
970
  var import_path2 = __toESM2(require("path"));
971
+ var SIMILARITY_THRESHOLD = 0.85;
972
+ var AMBIGUITY_MARGIN = 0.05;
973
+ var MAX_LINES_FOR_SIMILARITY_PASS = 2e4;
974
+ function splitLinesWithOffsets(text) {
975
+ const lines = [];
976
+ let start = 0;
977
+ for (let i = 0; i < text.length; i++) {
978
+ if (text[i] === "\n") {
979
+ let end = i;
980
+ if (end > start && text[end - 1] === "\r") end -= 1;
981
+ lines.push({ text: text.slice(start, end), start, end });
982
+ start = i + 1;
983
+ }
984
+ }
985
+ lines.push({ text: text.slice(start), start, end: text.length });
986
+ return lines;
987
+ }
988
+ function normalizeLine(line) {
989
+ return line.trim().replace(/\s+/g, " ");
990
+ }
991
+ function levenshtein(a, b) {
992
+ const m = a.length;
993
+ const n = b.length;
994
+ if (m === 0) return n;
995
+ if (n === 0) return m;
996
+ const dp = new Array(n + 1);
997
+ for (let j = 0; j <= n; j++) dp[j] = j;
998
+ for (let i = 1; i <= m; i++) {
999
+ let prev = dp[0];
1000
+ dp[0] = i;
1001
+ for (let j = 1; j <= n; j++) {
1002
+ const temp = dp[j];
1003
+ dp[j] = a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
1004
+ prev = temp;
1005
+ }
1006
+ }
1007
+ return dp[n];
1008
+ }
1009
+ function lineSimilarity(a, b) {
1010
+ const maxLen = Math.max(a.length, b.length);
1011
+ if (maxLen === 0) return 1;
1012
+ return 1 - levenshtein(a, b) / maxLen;
1013
+ }
1014
+ function findWhitespaceNormalizedMatch(content, search) {
1015
+ const searchLines = search.split(/\r\n|\n/).map(normalizeLine);
1016
+ const contentLines = splitLinesWithOffsets(content);
1017
+ if (searchLines.length === 0 || searchLines.length > contentLines.length) return null;
1018
+ const normalizedContentLines = contentLines.map((l) => normalizeLine(l.text));
1019
+ for (let i = 0; i + searchLines.length <= contentLines.length; i++) {
1020
+ let matches = true;
1021
+ for (let j = 0; j < searchLines.length; j++) {
1022
+ if (normalizedContentLines[i + j] !== searchLines[j]) {
1023
+ matches = false;
1024
+ break;
1025
+ }
1026
+ }
1027
+ if (matches) {
1028
+ const firstLine = contentLines[i];
1029
+ const lastLine = contentLines[i + searchLines.length - 1];
1030
+ return { start: firstLine.start, end: lastLine.end, strategy: "whitespace", score: 1 };
1031
+ }
1032
+ }
1033
+ return null;
1034
+ }
1035
+ function findSimilarityMatch(content, search) {
1036
+ const searchLines = search.split(/\r\n|\n/);
1037
+ const contentLines = splitLinesWithOffsets(content);
1038
+ if (searchLines.length === 0 || searchLines.length > contentLines.length) return null;
1039
+ if (contentLines.length > MAX_LINES_FOR_SIMILARITY_PASS) return null;
1040
+ let bestIndex = -1;
1041
+ let bestScore = -1;
1042
+ let secondBestScore = -1;
1043
+ for (let i = 0; i + searchLines.length <= contentLines.length; i++) {
1044
+ let total = 0;
1045
+ for (let j = 0; j < searchLines.length; j++) {
1046
+ total += lineSimilarity(searchLines[j], contentLines[i + j].text);
1047
+ }
1048
+ const avgScore = total / searchLines.length;
1049
+ if (avgScore > bestScore) {
1050
+ secondBestScore = bestScore;
1051
+ bestScore = avgScore;
1052
+ bestIndex = i;
1053
+ } else if (avgScore > secondBestScore) {
1054
+ secondBestScore = avgScore;
1055
+ }
1056
+ }
1057
+ if (bestIndex === -1 || bestScore < SIMILARITY_THRESHOLD) return null;
1058
+ if (secondBestScore >= 0 && bestScore - secondBestScore < AMBIGUITY_MARGIN) return null;
1059
+ const firstLine = contentLines[bestIndex];
1060
+ const lastLine = contentLines[bestIndex + searchLines.length - 1];
1061
+ return { start: firstLine.start, end: lastLine.end, strategy: "similarity", score: bestScore };
1062
+ }
1063
+ function findMatch(content, search) {
1064
+ const exactIndex = content.indexOf(search);
1065
+ if (exactIndex !== -1) {
1066
+ return { start: exactIndex, end: exactIndex + search.length, strategy: "exact", score: 1 };
1067
+ }
1068
+ return findWhitespaceNormalizedMatch(content, search) ?? findSimilarityMatch(content, search);
1069
+ }
969
1070
  function applyPatch(absoluteFilePath, search, replace) {
970
1071
  try {
971
1072
  if (!import_fs.default.existsSync(absoluteFilePath)) {
@@ -975,17 +1076,18 @@ var require_dist5 = __commonJS({
975
1076
  };
976
1077
  }
977
1078
  const original = import_fs.default.readFileSync(absoluteFilePath, "utf-8");
978
- if (!original.includes(search)) {
1079
+ const match = findMatch(original, search);
1080
+ if (!match) {
979
1081
  return {
980
1082
  success: false,
981
- error: `Search string not found in ${import_path2.default.basename(absoluteFilePath)}. The AI's "search" field did not match file content.`
1083
+ 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
1084
  };
983
1085
  }
984
1086
  const backupPath = absoluteFilePath + ".opspilot.bak";
985
1087
  import_fs.default.writeFileSync(backupPath, original, "utf-8");
986
- const fixed = original.replace(search, replace);
1088
+ const fixed = original.slice(0, match.start) + replace + original.slice(match.end);
987
1089
  import_fs.default.writeFileSync(absoluteFilePath, fixed, "utf-8");
988
- return { success: true, backupPath };
1090
+ return { success: true, backupPath, matchStrategy: match.strategy };
989
1091
  } catch (err) {
990
1092
  return { success: false, error: err.message };
991
1093
  }
@@ -993,9 +1095,9 @@ var require_dist5 = __commonJS({
993
1095
  }
994
1096
  });
995
1097
 
996
- // ../agents/dist/index.js
1098
+ // ../../packages/agents/dist/index.js
997
1099
  var require_dist6 = __commonJS({
998
- "../agents/dist/index.js"(exports2, module2) {
1100
+ "../../packages/agents/dist/index.js"(exports2, module2) {
999
1101
  "use strict";
1000
1102
  var __create2 = Object.create;
1001
1103
  var __defProp2 = Object.defineProperty;
@@ -1141,6 +1243,9 @@ Please check if the file path is correct relative to the project root and make s
1141
1243
  };
1142
1244
  } else {
1143
1245
  console.log(`[BugZero] Backup saved to: ${result.backupPath}`);
1246
+ if (result.matchStrategy && result.matchStrategy !== "exact") {
1247
+ console.log(`[BugZero] Note: exact match failed \u2014 patch applied via ${result.matchStrategy} matching.`);
1248
+ }
1144
1249
  }
1145
1250
  return {};
1146
1251
  }
@@ -1178,9 +1283,9 @@ Please check if the file path is correct relative to the project root and make s
1178
1283
  }
1179
1284
  });
1180
1285
 
1181
- // ../core/dist/index.js
1286
+ // ../../packages/core/dist/index.js
1182
1287
  var require_dist7 = __commonJS({
1183
- "../core/dist/index.js"(exports2, module2) {
1288
+ "../../packages/core/dist/index.js"(exports2, module2) {
1184
1289
  "use strict";
1185
1290
  var __create2 = Object.create;
1186
1291
  var __defProp2 = Object.defineProperty;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bugzero",
3
- "version": "0.0.30",
3
+ "version": "0.0.31",
4
4
  "description": "An autonomous, AI-powered CLI tool for automatic build error detection and repair.",
5
5
  "license": "MIT",
6
6
  "bin": {