bugzero 0.0.43 → 0.0.44
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/README.md +16 -1
- package/dist/index.js +98 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -114,6 +114,7 @@ bugzero rescue
|
|
|
114
114
|
### Integrations and output
|
|
115
115
|
|
|
116
116
|
- **Markdown reports.** Every `hunt` and `rescue` run writes `bugzero-report.md` to the target project: a pass/fail summary of build, lint, and tests, the full error logs, the model used, token usage, and before/after diffs for every file patched. The terminal prints a clickable link straight to it.
|
|
117
|
+
- **JSON output.** Add `--json` to `hunt` or `rescue` to print the result as a single JSON document on stdout, with all human-readable logs moved to stderr and the exit code unchanged (0 on success, 1 otherwise), so scripts and CI can parse it. See [Scripting and CI](#scripting-and-ci).
|
|
117
118
|
- **GitHub Action mode.** Run the same repair loop in CI. Instead of patching a local checkout, the Action commits every changed file in one atomic commit through the GitHub API and opens a pull request — see [GitHub Action Mode](#github-action-mode) below.
|
|
118
119
|
|
|
119
120
|
---
|
|
@@ -191,7 +192,7 @@ OPENROUTER_API_KEY=your_openrouter_api_key_here
|
|
|
191
192
|
## Commands
|
|
192
193
|
|
|
193
194
|
### `bugzero hunt`
|
|
194
|
-
Run build, lint, and test checks. Reports all failures without modifying any files. Accepts `--timeout <seconds
|
|
195
|
+
Run build, lint, and test checks. Reports all failures without modifying any files. Accepts `--timeout <seconds>` and `--json`, like `rescue`.
|
|
195
196
|
|
|
196
197
|
```bash
|
|
197
198
|
bugzero hunt --path /path/to/your/project
|
|
@@ -213,6 +214,7 @@ bugzero rescue --path /path/to/your/project
|
|
|
213
214
|
| `--max-attempts <n>` | `-n` | `3` | Maximum AI fix iterations before giving up |
|
|
214
215
|
| `--timeout <seconds>` | `-t` | none | Stop any build, lint, or test command that runs longer than this many seconds |
|
|
215
216
|
| `--dry-run` | | `false` | Analyze only — no files will be written |
|
|
217
|
+
| `--json` | | `false` | Print the result as one JSON document on stdout (logs go to stderr) |
|
|
216
218
|
|
|
217
219
|
</details>
|
|
218
220
|
|
|
@@ -236,6 +238,19 @@ bugzero vibe
|
|
|
236
238
|
|
|
237
239
|
---
|
|
238
240
|
|
|
241
|
+
## Scripting and CI
|
|
242
|
+
|
|
243
|
+
`hunt` and `rescue` accept `--json`. Stdout then contains exactly one JSON document and every human-readable log line goes to stderr, so the output is safe to pipe. Exit codes don't change: `0` when everything passes or is fixed, `1` otherwise.
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
bugzero hunt --json | jq '.steps'
|
|
247
|
+
bugzero rescue --json --dry-run | jq -r '.outcome'
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
`hunt` reports each step (`build`, `lint`, `test`) as `passed`, `failed`, or `skipped`; failed steps include the command's output and whether it timed out. `rescue` reports an `outcome` of `already-passing`, `fixed`, `failed`, or `dry-run`, along with the model, token usage, and the files and root cause of any fix. Both include the path to the generated report. If a run can't start at all (for example, because of an invalid option), stdout is `{ "success": false, "error": "..." }`.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
239
254
|
## Configuration
|
|
240
255
|
|
|
241
256
|
BugZero reads a `.bugzerorc` JSON file in your target project directory to pick up model preferences:
|
package/dist/index.js
CHANGED
|
@@ -393,7 +393,7 @@ var require_dist = __commonJS({
|
|
|
393
393
|
while (true) {
|
|
394
394
|
const envPath = import_path2.default.join(dir, ".env");
|
|
395
395
|
if (import_fs2.default.existsSync(envPath)) {
|
|
396
|
-
import_dotenv.default.config({ path: envPath });
|
|
396
|
+
import_dotenv.default.config({ path: envPath, quiet: true });
|
|
397
397
|
return;
|
|
398
398
|
}
|
|
399
399
|
const parent = import_path2.default.dirname(dir);
|
|
@@ -402,7 +402,7 @@ var require_dist = __commonJS({
|
|
|
402
402
|
}
|
|
403
403
|
dir = parent;
|
|
404
404
|
}
|
|
405
|
-
import_dotenv.default.config();
|
|
405
|
+
import_dotenv.default.config({ quiet: true });
|
|
406
406
|
}
|
|
407
407
|
loadEnv();
|
|
408
408
|
var env = {
|
|
@@ -1517,6 +1517,7 @@ var require_dist7 = __commonJS({
|
|
|
1517
1517
|
var index_exports = {};
|
|
1518
1518
|
__export(index_exports, {
|
|
1519
1519
|
DEFAULT_MAX_ATTEMPTS: () => DEFAULT_MAX_ATTEMPTS,
|
|
1520
|
+
REPORT_FILENAME: () => REPORT_FILENAME2,
|
|
1520
1521
|
detectFramework: () => detectFramework2,
|
|
1521
1522
|
detectPackageManager: () => import_analyzers2.detectPackageManager,
|
|
1522
1523
|
orchestrate: () => orchestrate2,
|
|
@@ -1625,6 +1626,7 @@ Re-run without \`--dry-run\` to let BugZero attempt a fix.
|
|
|
1625
1626
|
}
|
|
1626
1627
|
}
|
|
1627
1628
|
var import_ai_provider = require_dist3();
|
|
1629
|
+
var REPORT_FILENAME2 = "bugzero-report.md";
|
|
1628
1630
|
function statusLabel(result) {
|
|
1629
1631
|
if (result.skipped) return "\u23ED\uFE0F Skipped (no script defined)";
|
|
1630
1632
|
return result.success ? "\u2705 Passed" : "\u274C Failed";
|
|
@@ -1923,7 +1925,7 @@ ${rawOutput}
|
|
|
1923
1925
|
|
|
1924
1926
|
---
|
|
1925
1927
|
*Report generated by **BugZero** on ${(/* @__PURE__ */ new Date()).toLocaleString()}*`;
|
|
1926
|
-
const reportPath = import_path3.default.resolve(cwd,
|
|
1928
|
+
const reportPath = import_path3.default.resolve(cwd, REPORT_FILENAME2);
|
|
1927
1929
|
try {
|
|
1928
1930
|
import_fs3.default.writeFileSync(reportPath, content, "utf-8");
|
|
1929
1931
|
const clickableUrl = (0, import_url.pathToFileURL)(reportPath).toString();
|
|
@@ -1952,6 +1954,62 @@ var import_fs = __toESM(require("fs"));
|
|
|
1952
1954
|
var import_path = __toESM(require("path"));
|
|
1953
1955
|
var import_core = __toESM(require_dist7());
|
|
1954
1956
|
|
|
1957
|
+
// src/json-output.ts
|
|
1958
|
+
function stepStatus(step) {
|
|
1959
|
+
if (step.skipped) return "skipped";
|
|
1960
|
+
return step.success ? "passed" : "failed";
|
|
1961
|
+
}
|
|
1962
|
+
function stepJson(step) {
|
|
1963
|
+
const status = stepStatus(step);
|
|
1964
|
+
if (status !== "failed") return { status };
|
|
1965
|
+
return { status, timedOut: step.timedOut === true, output: step.output ?? "" };
|
|
1966
|
+
}
|
|
1967
|
+
function buildHuntJson(info, steps) {
|
|
1968
|
+
return {
|
|
1969
|
+
command: "hunt",
|
|
1970
|
+
success: steps.build.success && steps.lint.success && steps.test.success,
|
|
1971
|
+
path: info.path,
|
|
1972
|
+
framework: info.framework,
|
|
1973
|
+
packageManager: info.packageManager,
|
|
1974
|
+
steps: { build: stepJson(steps.build), lint: stepJson(steps.lint), test: stepJson(steps.test) },
|
|
1975
|
+
reportPath: info.reportPath
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
1978
|
+
function buildRescueJson(result, info) {
|
|
1979
|
+
let outcome;
|
|
1980
|
+
if (result.success && result.attempts === 0) outcome = "already-passing";
|
|
1981
|
+
else if (result.success) outcome = "fixed";
|
|
1982
|
+
else if (info.dryRun) outcome = "dry-run";
|
|
1983
|
+
else outcome = "failed";
|
|
1984
|
+
const tokens = result.promptTokens !== void 0 && result.completionTokens !== void 0 ? {
|
|
1985
|
+
prompt: result.promptTokens,
|
|
1986
|
+
completion: result.completionTokens,
|
|
1987
|
+
total: result.promptTokens + result.completionTokens
|
|
1988
|
+
} : null;
|
|
1989
|
+
return {
|
|
1990
|
+
command: "rescue",
|
|
1991
|
+
outcome,
|
|
1992
|
+
success: result.success,
|
|
1993
|
+
dryRun: info.dryRun,
|
|
1994
|
+
path: info.path,
|
|
1995
|
+
framework: info.framework,
|
|
1996
|
+
packageManager: info.packageManager,
|
|
1997
|
+
attempts: result.attempts,
|
|
1998
|
+
model: result.modelUsed || null,
|
|
1999
|
+
tokens,
|
|
2000
|
+
fix: result.appliedFix ? {
|
|
2001
|
+
rootCause: result.appliedFix.rootCause,
|
|
2002
|
+
explanation: result.appliedFix.explanation,
|
|
2003
|
+
files: result.appliedFix.patches.map((p) => p.filePath)
|
|
2004
|
+
} : null,
|
|
2005
|
+
error: result.error ?? null,
|
|
2006
|
+
reportPath: info.reportPath
|
|
2007
|
+
};
|
|
2008
|
+
}
|
|
2009
|
+
function buildErrorJson(message) {
|
|
2010
|
+
return { success: false, error: message };
|
|
2011
|
+
}
|
|
2012
|
+
|
|
1955
2013
|
// src/summary.ts
|
|
1956
2014
|
function tokenLines(result) {
|
|
1957
2015
|
if (result.promptTokens === void 0 || result.completionTokens === void 0) return [];
|
|
@@ -2011,9 +2069,23 @@ function parseTimeout(raw) {
|
|
|
2011
2069
|
(0, import_core.resolveTimeoutMs)(seconds);
|
|
2012
2070
|
return seconds;
|
|
2013
2071
|
}
|
|
2072
|
+
var JSON_DESCRIPTION = "Print the result as one JSON document on stdout (human-readable logs go to stderr)";
|
|
2073
|
+
function routeLogsToStderr() {
|
|
2074
|
+
const toStderr = (...args) => console.error(...args);
|
|
2075
|
+
console.log = toStderr;
|
|
2076
|
+
console.info = toStderr;
|
|
2077
|
+
console.debug = toStderr;
|
|
2078
|
+
}
|
|
2079
|
+
function finish(exitCode, json) {
|
|
2080
|
+
if (json === void 0) process.exit(exitCode);
|
|
2081
|
+
process.stdout.write(`${JSON.stringify(json, null, 2)}
|
|
2082
|
+
`, () => process.exit(exitCode));
|
|
2083
|
+
}
|
|
2014
2084
|
var program = new import_commander.Command();
|
|
2015
2085
|
program.name("bugzero").description("AI-powered build issue fixer \u2014 detects and repairs build errors automatically").version(version);
|
|
2016
|
-
program.command("hunt").description("Run build, lint, and tests \u2014 report issues without modifying files").option("-p, --path <dir>", "Path to the target project", ".").option("-t, --timeout <seconds>", TIMEOUT_DESCRIPTION).action(async (opts) => {
|
|
2086
|
+
program.command("hunt").description("Run build, lint, and tests \u2014 report issues without modifying files").option("-p, --path <dir>", "Path to the target project", ".").option("-t, --timeout <seconds>", TIMEOUT_DESCRIPTION).option("--json", JSON_DESCRIPTION).action(async (opts) => {
|
|
2087
|
+
const json = opts.json === true;
|
|
2088
|
+
if (json) routeLogsToStderr();
|
|
2017
2089
|
try {
|
|
2018
2090
|
const cwd = import_path.default.resolve(opts.path);
|
|
2019
2091
|
const timeoutSeconds = parseTimeout(opts.timeout);
|
|
@@ -2037,14 +2109,22 @@ program.command("hunt").description("Run build, lint, and tests \u2014 report is
|
|
|
2037
2109
|
console.log(`
|
|
2038
2110
|
${allPassed ? "\u2705 All checks passed" : "\u274C Issues found \u2014 run 'bugzero rescue' to repair"}
|
|
2039
2111
|
`);
|
|
2040
|
-
|
|
2112
|
+
finish(
|
|
2113
|
+
allPassed ? 0 : 1,
|
|
2114
|
+
json ? buildHuntJson(
|
|
2115
|
+
{ path: cwd, framework, packageManager, reportPath: import_path.default.resolve(cwd, import_core.REPORT_FILENAME) },
|
|
2116
|
+
{ build, lint, test }
|
|
2117
|
+
) : void 0
|
|
2118
|
+
);
|
|
2041
2119
|
} catch (error) {
|
|
2042
2120
|
console.error(`
|
|
2043
2121
|
\u274C [BugZero] Execution failed: ${error.message || error}`);
|
|
2044
|
-
|
|
2122
|
+
finish(1, json ? buildErrorJson(String(error.message || error)) : void 0);
|
|
2045
2123
|
}
|
|
2046
2124
|
});
|
|
2047
|
-
program.command("rescue").description("Detect build failures and automatically apply AI-generated fixes").option("-p, --path <dir>", "Path to the target project", ".").option("-n, --max-attempts <number>", "Maximum AI fix attempts", "3").option("-t, --timeout <seconds>", TIMEOUT_DESCRIPTION).option("--dry-run", "Analyse only \u2014 print what would be fixed without writing files", false).action(async (opts) => {
|
|
2125
|
+
program.command("rescue").description("Detect build failures and automatically apply AI-generated fixes").option("-p, --path <dir>", "Path to the target project", ".").option("-n, --max-attempts <number>", "Maximum AI fix attempts", "3").option("-t, --timeout <seconds>", TIMEOUT_DESCRIPTION).option("--dry-run", "Analyse only \u2014 print what would be fixed without writing files", false).option("--json", JSON_DESCRIPTION).action(async (opts) => {
|
|
2126
|
+
const json = opts.json === true;
|
|
2127
|
+
if (json) routeLogsToStderr();
|
|
2048
2128
|
try {
|
|
2049
2129
|
const cwd = import_path.default.resolve(opts.path);
|
|
2050
2130
|
const maxAttempts = (0, import_core.resolveMaxAttempts)(Number(opts.maxAttempts));
|
|
@@ -2066,11 +2146,20 @@ program.command("rescue").description("Detect build failures and automatically a
|
|
|
2066
2146
|
const summary = buildRescueSummary(result, { dryRun });
|
|
2067
2147
|
for (const line of summary.lines) console.log(line);
|
|
2068
2148
|
console.log();
|
|
2069
|
-
|
|
2149
|
+
finish(
|
|
2150
|
+
summary.exitCode,
|
|
2151
|
+
json ? buildRescueJson(result, {
|
|
2152
|
+
path: cwd,
|
|
2153
|
+
framework,
|
|
2154
|
+
packageManager,
|
|
2155
|
+
dryRun,
|
|
2156
|
+
reportPath: import_path.default.resolve(cwd, import_core.REPORT_FILENAME)
|
|
2157
|
+
}) : void 0
|
|
2158
|
+
);
|
|
2070
2159
|
} catch (error) {
|
|
2071
2160
|
console.error(`
|
|
2072
2161
|
\u274C [BugZero] Execution failed: ${error.message || error}`);
|
|
2073
|
-
|
|
2162
|
+
finish(1, json ? buildErrorJson(String(error.message || error)) : void 0);
|
|
2074
2163
|
}
|
|
2075
2164
|
});
|
|
2076
2165
|
program.command("protect").description("[Deprecated] Use 'hunt' instead").action(async () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bugzero",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.44",
|
|
4
4
|
"description": "Autonomous AI-powered CLI and GitHub Action that detects build, lint, and test failures, generates multi-file patches, applies them atomically with fuzzy matching, and re-verifies until your project is green.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Saksham Agarwal (https://github.com/Saksham1800t)",
|