bugzero 0.0.31 → 0.0.33
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 +136 -70
- package/dist/index.js +119 -46
- 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.33 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 33ms
|
|
12
12
|
[34mDTS[39m Build start
|
|
13
|
-
[32mDTS[39m ⚡️ Build success in
|
|
13
|
+
[32mDTS[39m ⚡️ Build success in 784ms
|
|
14
14
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m20.00 B[39m
|
package/README.md
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# 🐛 BugZero
|
|
4
|
+
|
|
5
|
+
### Your build breaks. BugZero fixes it. Automatically.
|
|
2
6
|
|
|
3
7
|
[](https://www.npmjs.com/package/bugzero)
|
|
8
|
+
[](https://www.npmjs.com/package/bugzero)
|
|
9
|
+
[](https://github.com/Saksham1800t/Bugzero/actions/workflows/ci.yml)
|
|
4
10
|
[](https://opensource.org/licenses/MIT)
|
|
5
11
|
[](https://nodejs.org)
|
|
6
12
|
[](https://pnpm.io/)
|
|
7
|
-
[](https://github.com/Saksham1800t)
|
|
8
13
|
|
|
9
|
-
**BugZero** is an autonomous, AI-powered CLI
|
|
14
|
+
**BugZero** is an autonomous, AI-powered CLI that detects and repairs build, lint, and test failures — locally or as a GitHub Action that opens the fix as a pull request.
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## ⚡ Quick Start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g bugzero
|
|
24
|
+
export OPENROUTER_API_KEY="your_openrouter_api_key_here"
|
|
25
|
+
bugzero rescue --path /path/to/your/project
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
That's it — BugZero runs your build, diagnoses the failure, generates a patch, applies it, and re-verifies, looping until it's green or it runs out of attempts.
|
|
12
29
|
|
|
13
30
|
---
|
|
14
31
|
|
|
@@ -16,75 +33,117 @@ Built for developers who want zero-downtime repair cycles, automated CI/CD recov
|
|
|
16
33
|
|
|
17
34
|
Modern applications fail at build and deployment time for reasons that are repetitive, predictable, and ultimately fixable by a knowledgeable agent. BugZero bridges the gap between raw compiler output and working code — automatically.
|
|
18
35
|
|
|
19
|
-
- **No more debugging the same TypeScript error twice.** The agent reads the
|
|
20
|
-
- **Safe by design.** Every file
|
|
21
|
-
- **
|
|
22
|
-
- **
|
|
36
|
+
- 🔁 **No more debugging the same TypeScript error twice.** The agent reads the error, finds the file, generates the fix, and verifies it.
|
|
37
|
+
- 🛡️ **Safe by design.** Every modified file gets a `.opspilot.bak` backup, and a multi-file fix is applied and rolled back as one atomic unit.
|
|
38
|
+
- 🎯 **Forgiving, not brittle.** If the AI's suggested patch doesn't match the file byte-for-byte, BugZero falls back to whitespace-normalized and similarity-scored matching before giving up.
|
|
39
|
+
- 🧠 **Model agnostic.** DeepSeek, Claude, Gemini, GPT-4o, Llama, or any model on OpenRouter.
|
|
40
|
+
- 🤖 **CI-native.** Run it as a GitHub Action instead of a local CLI, and let it open the fix as a PR.
|
|
23
41
|
|
|
24
42
|
---
|
|
25
43
|
|
|
26
|
-
## How
|
|
44
|
+
## How It Works
|
|
27
45
|
|
|
28
46
|
```
|
|
29
47
|
bugzero rescue
|
|
30
|
-
|
|
31
|
-
|
|
48
|
+
│
|
|
49
|
+
▼
|
|
32
50
|
Run Build + Lint + Tests
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Any failures?
|
|
36
|
-
|
|
51
|
+
│
|
|
52
|
+
▼
|
|
53
|
+
Any failures? ── No ──▶ Build already passing. Exit cleanly.
|
|
54
|
+
│
|
|
37
55
|
Yes
|
|
38
|
-
|
|
39
|
-
|
|
56
|
+
│
|
|
57
|
+
▼
|
|
40
58
|
Capture and parse error logs
|
|
41
|
-
|
|
42
|
-
|
|
59
|
+
│
|
|
60
|
+
▼
|
|
43
61
|
Prompt selected LLM via LangGraph Agent
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Parse structured fix suggestion (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Apply
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
│
|
|
63
|
+
▼
|
|
64
|
+
Parse structured fix suggestion (one or more file patches)
|
|
65
|
+
│
|
|
66
|
+
▼
|
|
67
|
+
Apply patches atomically (exact → whitespace → similarity match, with .bak backups)
|
|
68
|
+
│
|
|
69
|
+
▼
|
|
52
70
|
Re-run build to verify the fix
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Build fixed?
|
|
56
|
-
|
|
71
|
+
│
|
|
72
|
+
▼
|
|
73
|
+
Build fixed? ── Yes ──▶ Print fix details. Exit success.
|
|
74
|
+
│
|
|
57
75
|
No
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
Max attempts reached?
|
|
61
|
-
|
|
76
|
+
│
|
|
77
|
+
▼
|
|
78
|
+
Max attempts reached? ── Yes ──▶ Exit with failure logs.
|
|
79
|
+
│
|
|
62
80
|
No
|
|
63
|
-
|
|
64
|
-
|
|
81
|
+
│
|
|
82
|
+
└──────────────────▶ Prompt LLM again (next attempt)
|
|
65
83
|
```
|
|
66
84
|
|
|
67
85
|
---
|
|
68
86
|
|
|
69
|
-
## Key Features
|
|
87
|
+
## ✨ Key Features
|
|
70
88
|
|
|
71
89
|
| Feature | Description |
|
|
72
90
|
|---|---|
|
|
73
91
|
| Autonomous repair loop | Runs analyze, patch, verify in a stateful LangGraph graph |
|
|
74
92
|
| Multi-model support | DeepSeek, Claude, GPT-4o, Gemini, Llama via OpenRouter |
|
|
75
93
|
| Framework detection | Automatically identifies your project's tooling setup |
|
|
94
|
+
| **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 |
|
|
95
|
+
| **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 |
|
|
76
96
|
| 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
97
|
| Error type parsing | Parses TypeScript, ESLint, and Jest error formats |
|
|
79
98
|
| Dry-run mode | Analyze and report without writing any files |
|
|
80
99
|
| Local model config | Save preferred model to `.bugzerorc` per project |
|
|
81
|
-
| Markdown Reports |
|
|
100
|
+
| Markdown Reports | Auto-generates a detailed `bugzero-report.md` with error logs, model name, token usage, and code diffs — plus a clickable link straight to your terminal |
|
|
101
|
+
| **GitHub Action mode** | Run the same repair loop in CI and open a pull request with the fix instead of patching a local checkout — see below |
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 🤖 GitHub Action Mode
|
|
106
|
+
|
|
107
|
+
Instead of running BugZero on your machine, run it in CI: when a check fails, it opens a pull request with the fix instead of patching your local checkout.
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
name: BugZero Auto-Fix
|
|
111
|
+
|
|
112
|
+
on:
|
|
113
|
+
workflow_run:
|
|
114
|
+
workflows: ["CI"]
|
|
115
|
+
types: [completed]
|
|
116
|
+
|
|
117
|
+
jobs:
|
|
118
|
+
fix:
|
|
119
|
+
if: github.event.workflow_run.conclusion == 'failure'
|
|
120
|
+
runs-on: ubuntu-latest
|
|
121
|
+
permissions:
|
|
122
|
+
contents: write
|
|
123
|
+
pull-requests: write
|
|
124
|
+
steps:
|
|
125
|
+
- uses: actions/checkout@v4
|
|
126
|
+
with:
|
|
127
|
+
ref: ${{ github.event.workflow_run.head_branch }}
|
|
128
|
+
|
|
129
|
+
- uses: pnpm/action-setup@v4 # or npm/yarn — whatever installs your project's deps
|
|
130
|
+
- run: pnpm install
|
|
131
|
+
|
|
132
|
+
- uses: Saksham1800t/Bugzero@v1
|
|
133
|
+
with:
|
|
134
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
135
|
+
base-branch: ${{ github.event.workflow_run.head_branch }}
|
|
136
|
+
env:
|
|
137
|
+
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
It commits every changed file as a single atomic commit via the GitHub API — no local git push needed — then opens the PR. Full input/output reference: [`apps/github-action`](https://github.com/Saksham1800t/Bugzero/tree/main/apps/github-action).
|
|
82
141
|
|
|
83
142
|
---
|
|
84
143
|
|
|
85
144
|
## Installation
|
|
86
145
|
|
|
87
|
-
Install globally from the
|
|
146
|
+
Install globally from the npm registry:
|
|
88
147
|
|
|
89
148
|
```bash
|
|
90
149
|
npm install -g bugzero
|
|
@@ -129,7 +188,8 @@ Run the full AI-powered repair loop. Detects build failures, generates precise c
|
|
|
129
188
|
bugzero rescue --path /path/to/your/project
|
|
130
189
|
```
|
|
131
190
|
|
|
132
|
-
|
|
191
|
+
<details>
|
|
192
|
+
<summary><strong>Options for <code>rescue</code></strong></summary>
|
|
133
193
|
|
|
134
194
|
| Flag | Short | Default | Description |
|
|
135
195
|
|---|---|---|---|
|
|
@@ -137,6 +197,8 @@ Options:
|
|
|
137
197
|
| `--max-attempts <n>` | `-n` | `3` | Maximum AI fix iterations before giving up |
|
|
138
198
|
| `--dry-run` | | `false` | Analyze only — no files will be written |
|
|
139
199
|
|
|
200
|
+
</details>
|
|
201
|
+
|
|
140
202
|
### `bugzero vibe`
|
|
141
203
|
Interactively select which AI model to use. Fetches the current model list from OpenRouter, lets you pick one, and saves the selection to a local `.bugzerorc` config file.
|
|
142
204
|
|
|
@@ -144,13 +206,17 @@ Interactively select which AI model to use. Fetches the current model list from
|
|
|
144
206
|
bugzero vibe
|
|
145
207
|
```
|
|
146
208
|
|
|
147
|
-
|
|
209
|
+
<details>
|
|
210
|
+
<summary><strong>Supported models</strong> (curated list, plus custom entry)</summary>
|
|
211
|
+
|
|
148
212
|
- DeepSeek V3 / DeepSeek R1
|
|
149
213
|
- Anthropic Claude 3.5 Sonnet
|
|
150
214
|
- Google Gemini 2.5 Pro / Flash
|
|
151
215
|
- OpenAI GPT-4o
|
|
152
216
|
- Meta Llama 3.3 Instruct
|
|
153
217
|
|
|
218
|
+
</details>
|
|
219
|
+
|
|
154
220
|
---
|
|
155
221
|
|
|
156
222
|
## Configuration
|
|
@@ -169,33 +235,45 @@ This file is created automatically when you run `bugzero vibe`.
|
|
|
169
235
|
|
|
170
236
|
## Reports
|
|
171
237
|
|
|
172
|
-
Every time you run `bugzero hunt` or `bugzero rescue`, a detailed Markdown report is generated at `bugzero-report.md` in the target project directory. The tool prints a clickable absolute file URL and path directly to your terminal.
|
|
238
|
+
Every time you run `bugzero hunt` or `bugzero rescue`, a detailed Markdown report is generated at `bugzero-report.md` in the target project directory. The tool prints a clickable absolute file URL and path directly to your terminal.
|
|
239
|
+
|
|
173
240
|
- **Pipeline Summary:** Clear status checklist of your project's Build, Lint, and Test suites.
|
|
174
241
|
- **Detailed Error Outputs:** Full error logs from any failing checks.
|
|
175
242
|
- **AI Brain Details:** The exact OpenRouter model used.
|
|
176
243
|
- **Token Usage:** Accumulated prompt and completion tokens used for the run.
|
|
177
|
-
- **Applied Fixes (for rescue):** The root cause, explanation, and before/after
|
|
244
|
+
- **Applied Fixes (for rescue):** The root cause, explanation, and before/after diffs for every file patched.
|
|
178
245
|
|
|
179
246
|
---
|
|
180
247
|
|
|
181
|
-
##
|
|
248
|
+
## Error Handling
|
|
182
249
|
|
|
183
|
-
|
|
250
|
+
BugZero provides clear, actionable output for common failure modes:
|
|
251
|
+
|
|
252
|
+
| Error | Message |
|
|
253
|
+
|---|---|
|
|
254
|
+
| Invalid API key (401) | Prompts you to check your `OPENROUTER_API_KEY` |
|
|
255
|
+
| Rate limit exceeded (429) | Prompts you to check your OpenRouter credit balance |
|
|
256
|
+
| Model not found | Displays the invalid model ID and suggests running `bugzero vibe` |
|
|
257
|
+
| Patch not applied | Reports exact mismatch between AI suggestion and file content, after exhausting exact, whitespace, and fuzzy matching |
|
|
258
|
+
| Max attempts reached | Exits cleanly with the last error log for manual review |
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
<details>
|
|
263
|
+
<summary><strong>🛠️ Development Setup</strong> (contributing to BugZero itself)</summary>
|
|
264
|
+
|
|
265
|
+
Clone the repository and install dependencies. This project uses a pnpm monorepo managed by Turborepo, with a Vitest test suite and GitHub Actions CI.
|
|
184
266
|
|
|
185
267
|
### Prerequisites
|
|
186
268
|
- Node.js 18 or later
|
|
187
269
|
- pnpm
|
|
188
270
|
|
|
189
|
-
### Install
|
|
271
|
+
### Install & build
|
|
190
272
|
|
|
191
273
|
```bash
|
|
192
274
|
pnpm install
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### Build all packages
|
|
196
|
-
|
|
197
|
-
```bash
|
|
198
275
|
pnpm build
|
|
276
|
+
pnpm test
|
|
199
277
|
```
|
|
200
278
|
|
|
201
279
|
### Run commands locally without installing globally
|
|
@@ -206,33 +284,22 @@ pnpm rescue --path ./demo-project
|
|
|
206
284
|
pnpm vibe
|
|
207
285
|
```
|
|
208
286
|
|
|
209
|
-
### Monorepo
|
|
287
|
+
### Monorepo structure
|
|
210
288
|
|
|
211
289
|
| Package | Role |
|
|
212
290
|
|---|---|
|
|
213
|
-
| `
|
|
291
|
+
| `apps/bugzero` | CLI entrypoint (Commander) — the package published to npm |
|
|
292
|
+
| `apps/github-action` | GitHub Action wrapper — runs the repair loop in CI and opens a fix PR |
|
|
214
293
|
| `packages/core` | Orchestrates build and fix flow |
|
|
215
294
|
| `packages/agents` | LangGraph state machine (analyze, patch, verify) |
|
|
216
295
|
| `packages/ai-provider` | OpenRouter HTTP client |
|
|
217
296
|
| `packages/analyzers` | Runs build/lint/test and parses output |
|
|
218
|
-
| `packages/patcher` | Applies search-and-replace patches with
|
|
297
|
+
| `packages/patcher` | Applies search-and-replace patches — with atomic multi-file support and fuzzy-match fallback |
|
|
219
298
|
| `packages/prompts` | LLM prompt templates |
|
|
220
299
|
| `packages/config` | Env loading and local `.bugzerorc` config store |
|
|
221
300
|
| `packages/shared` | Shared TypeScript types |
|
|
222
301
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
## Error Handling
|
|
226
|
-
|
|
227
|
-
BugZero provides clear, actionable output for common failure modes:
|
|
228
|
-
|
|
229
|
-
| Error | Message |
|
|
230
|
-
|---|---|
|
|
231
|
-
| Invalid API key (401) | Prompts you to check your `OPENROUTER_API_KEY` |
|
|
232
|
-
| Rate limit exceeded (429) | Prompts you to check your OpenRouter credit balance |
|
|
233
|
-
| Model not found | Displays the invalid model ID and suggests running `bugzero vibe` |
|
|
234
|
-
| Patch not applied | Reports exact mismatch between AI suggestion and file content |
|
|
235
|
-
| Max attempts reached | Exits cleanly with the last error log for manual review |
|
|
302
|
+
</details>
|
|
236
303
|
|
|
237
304
|
---
|
|
238
305
|
|
|
@@ -251,4 +318,3 @@ BugZero provides clear, actionable output for common failure modes:
|
|
|
251
318
|
If BugZero saved you debugging hours in production or deployment pipelines, consider buying the author a coffee.
|
|
252
319
|
|
|
253
320
|
[](https://www.buymeacoffee.com/saksham_)
|
|
254
|
-
|
package/dist/index.js
CHANGED
|
@@ -908,21 +908,27 @@ ${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
|
}
|
|
@@ -962,6 +968,7 @@ var require_dist5 = __commonJS({
|
|
|
962
968
|
var index_exports = {};
|
|
963
969
|
__export(index_exports, {
|
|
964
970
|
applyPatch: () => applyPatch,
|
|
971
|
+
applyPatches: () => applyPatches,
|
|
965
972
|
findMatch: () => findMatch,
|
|
966
973
|
lineSimilarity: () => lineSimilarity
|
|
967
974
|
});
|
|
@@ -1092,6 +1099,62 @@ var require_dist5 = __commonJS({
|
|
|
1092
1099
|
return { success: false, error: err.message };
|
|
1093
1100
|
}
|
|
1094
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
|
+
}
|
|
1095
1158
|
}
|
|
1096
1159
|
});
|
|
1097
1160
|
|
|
@@ -1099,11 +1162,9 @@ var require_dist5 = __commonJS({
|
|
|
1099
1162
|
var require_dist6 = __commonJS({
|
|
1100
1163
|
"../../packages/agents/dist/index.js"(exports2, module2) {
|
|
1101
1164
|
"use strict";
|
|
1102
|
-
var __create2 = Object.create;
|
|
1103
1165
|
var __defProp2 = Object.defineProperty;
|
|
1104
1166
|
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
1105
1167
|
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
1106
|
-
var __getProtoOf2 = Object.getPrototypeOf;
|
|
1107
1168
|
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
1108
1169
|
var __export = (target, all) => {
|
|
1109
1170
|
for (var name in all)
|
|
@@ -1117,14 +1178,6 @@ var require_dist6 = __commonJS({
|
|
|
1117
1178
|
}
|
|
1118
1179
|
return to;
|
|
1119
1180
|
};
|
|
1120
|
-
var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps2(
|
|
1121
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
1122
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
1123
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
1124
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
1125
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target,
|
|
1126
|
-
mod
|
|
1127
|
-
));
|
|
1128
1181
|
var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
1129
1182
|
var index_exports = {};
|
|
1130
1183
|
__export(index_exports, {
|
|
@@ -1132,7 +1185,6 @@ var require_dist6 = __commonJS({
|
|
|
1132
1185
|
});
|
|
1133
1186
|
module2.exports = __toCommonJS(index_exports);
|
|
1134
1187
|
var import_langgraph2 = require("@langchain/langgraph");
|
|
1135
|
-
var import_path2 = __toESM2(require("path"));
|
|
1136
1188
|
var import_langgraph = require("@langchain/langgraph");
|
|
1137
1189
|
var GraphState = import_langgraph.Annotation.Root({
|
|
1138
1190
|
/** Absolute path to the project being fixed */
|
|
@@ -1204,7 +1256,12 @@ var require_dist6 = __commonJS({
|
|
|
1204
1256
|
const cleaned = response.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim();
|
|
1205
1257
|
const jsonMatch = cleaned.match(/\{[\s\S]*\}/);
|
|
1206
1258
|
if (jsonMatch) {
|
|
1207
|
-
|
|
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
|
+
}
|
|
1208
1265
|
} else {
|
|
1209
1266
|
console.warn("[BugZero] AI response did not contain a valid JSON object.");
|
|
1210
1267
|
}
|
|
@@ -1225,26 +1282,27 @@ var require_dist6 = __commonJS({
|
|
|
1225
1282
|
console.warn("[BugZero] No fix suggestion available \u2014 skipping patch.");
|
|
1226
1283
|
return {};
|
|
1227
1284
|
}
|
|
1228
|
-
const {
|
|
1229
|
-
const
|
|
1230
|
-
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}`);
|
|
1231
1288
|
console.log(`[BugZero] Reason: ${explanation}`);
|
|
1232
|
-
const result = (0, import_patcher.
|
|
1289
|
+
const result = (0, import_patcher.applyPatches)(state.cwd, patches);
|
|
1233
1290
|
if (!result.success) {
|
|
1234
1291
|
console.error(`[BugZero] Patch failed: ${result.error}`);
|
|
1235
1292
|
const updatedLogs = `${state.logs}
|
|
1236
1293
|
|
|
1237
|
-
\u26A0\uFE0F [BugZero System Warning] Your previous patch suggestion
|
|
1294
|
+
\u26A0\uFE0F [BugZero System Warning] Your previous patch suggestion failed with the following error:
|
|
1238
1295
|
- ${result.error}
|
|
1239
1296
|
|
|
1240
|
-
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.`;
|
|
1241
1298
|
return {
|
|
1242
1299
|
logs: updatedLogs
|
|
1243
1300
|
};
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
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.`);
|
|
1248
1306
|
}
|
|
1249
1307
|
}
|
|
1250
1308
|
return {};
|
|
@@ -1432,6 +1490,30 @@ var require_dist7 = __commonJS({
|
|
|
1432
1490
|
});
|
|
1433
1491
|
return result;
|
|
1434
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
|
+
}
|
|
1435
1517
|
async function writeReport(cwd, type, data) {
|
|
1436
1518
|
let content = "";
|
|
1437
1519
|
const provider = new import_ai_provider.OpenRouterProvider();
|
|
@@ -1510,14 +1592,12 @@ ${logs}
|
|
|
1510
1592
|
const { success, attempts, maxAttempts, appliedFix, error, rawOutput, modelUsed, promptTokens, completionTokens } = data;
|
|
1511
1593
|
if (success && appliedFix) {
|
|
1512
1594
|
console.log("[BugZero] Calling AI to write solution summary report...");
|
|
1513
|
-
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}.
|
|
1514
1597
|
Here is the patch details:
|
|
1515
1598
|
- Root Cause: ${appliedFix.rootCause}
|
|
1516
1599
|
- Explanation: ${appliedFix.explanation}
|
|
1517
|
-
|
|
1518
|
-
${appliedFix.search}
|
|
1519
|
-
- Replace code:
|
|
1520
|
-
${appliedFix.replace}
|
|
1600
|
+
${formatPatchesForPrompt(appliedFix)}
|
|
1521
1601
|
|
|
1522
1602
|
Please generate a professional, beautifully formatted Markdown report summarizing:
|
|
1523
1603
|
1. **Repair Summary:** Celebrate the success and explain the fix.
|
|
@@ -1550,20 +1630,12 @@ Generate the Markdown report directly. Do not wrap it in markdown block fences (
|
|
|
1550
1630
|
- **Token Usage:** ${promptTokens !== void 0 && completionTokens !== void 0 ? `Prompt: **${promptTokens}** | Completion: **${completionTokens}** | Total: **${promptTokens + completionTokens}**` : "*N/A*"}
|
|
1551
1631
|
|
|
1552
1632
|
## \u{1F6E0}\uFE0F Applied Solution
|
|
1553
|
-
- **Target File:**
|
|
1633
|
+
- **Target File(s):** ${appliedFix.patches.map((p) => `\`${p.filePath}\``).join(", ")}
|
|
1554
1634
|
- **Root Cause:** ${appliedFix.rootCause}
|
|
1555
1635
|
- **Explanation:** ${appliedFix.explanation}
|
|
1556
1636
|
|
|
1557
1637
|
### \u{1F4DD} Code Changes
|
|
1558
|
-
|
|
1559
|
-
\`\`\`typescript
|
|
1560
|
-
${appliedFix.search}
|
|
1561
|
-
\`\`\`
|
|
1562
|
-
|
|
1563
|
-
**Replace (After):**
|
|
1564
|
-
\`\`\`typescript
|
|
1565
|
-
${appliedFix.replace}
|
|
1566
|
-
\`\`\`
|
|
1638
|
+
${formatPatchesMarkdown(appliedFix)}
|
|
1567
1639
|
`;
|
|
1568
1640
|
}
|
|
1569
1641
|
} else {
|
|
@@ -1693,7 +1765,8 @@ program.command("rescue").description("Detect build failures and automatically a
|
|
|
1693
1765
|
console.log(` Tokens: Prompt: ${result.promptTokens} | Completion: ${result.completionTokens} | Total: ${result.promptTokens + result.completionTokens}`);
|
|
1694
1766
|
}
|
|
1695
1767
|
if (result.appliedFix) {
|
|
1696
|
-
|
|
1768
|
+
const files = result.appliedFix.patches.map((p) => p.filePath).join(", ");
|
|
1769
|
+
console.log(` File${result.appliedFix.patches.length === 1 ? "" : "s"}: ${files}`);
|
|
1697
1770
|
console.log(` Reason: ${result.appliedFix.explanation}`);
|
|
1698
1771
|
console.log(` Root cause: ${result.appliedFix.rootCause}`);
|
|
1699
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
|
}
|