bugzero 0.0.33 → 0.0.35
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 +14 -9
- package/demo.svg +81 -0
- package/dist/index.js +50 -9
- package/package.json +1 -1
- package/src/index.ts +6 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> bugzero@0.0.
|
|
2
|
+
> bugzero@0.0.35 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[32m79.68 KB[39m
|
|
11
|
+
[32mCJS[39m ⚡️ Build success in 54ms
|
|
12
12
|
[34mDTS[39m Build start
|
|
13
|
-
[32mDTS[39m ⚡️ Build success in
|
|
13
|
+
[32mDTS[39m ⚡️ Build success in 1265ms
|
|
14
14
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m20.00 B[39m
|
package/README.md
CHANGED
|
@@ -13,11 +13,15 @@
|
|
|
13
13
|
|
|
14
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.
|
|
15
15
|
|
|
16
|
+
<img src="https://raw.githubusercontent.com/Saksham1800t/Bugzero/main/apps/bugzero/demo.svg" alt="Animated terminal demo of bugzero rescue detecting and fixing a TypeScript build error" width="700" />
|
|
17
|
+
|
|
18
|
+
<sub>Illustrative animation of a <code>bugzero rescue</code> run using the tool's real log output format.</sub>
|
|
19
|
+
|
|
16
20
|
</div>
|
|
17
21
|
|
|
18
22
|
---
|
|
19
23
|
|
|
20
|
-
##
|
|
24
|
+
## Quick Start
|
|
21
25
|
|
|
22
26
|
```bash
|
|
23
27
|
npm install -g bugzero
|
|
@@ -33,11 +37,11 @@ That's it — BugZero runs your build, diagnoses the failure, generates a patch,
|
|
|
33
37
|
|
|
34
38
|
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.
|
|
35
39
|
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
40
|
+
- **No more debugging the same TypeScript error twice.** The agent reads the error, finds the file, generates the fix, and verifies it.
|
|
41
|
+
- **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.
|
|
42
|
+
- **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.
|
|
43
|
+
- **Model agnostic.** DeepSeek, Claude, Gemini, GPT-4o, Llama, or any model on OpenRouter.
|
|
44
|
+
- **CI-native.** Run it as a GitHub Action instead of a local CLI, and let it open the fix as a PR.
|
|
41
45
|
|
|
42
46
|
---
|
|
43
47
|
|
|
@@ -84,13 +88,14 @@ bugzero rescue
|
|
|
84
88
|
|
|
85
89
|
---
|
|
86
90
|
|
|
87
|
-
##
|
|
91
|
+
## Key Features
|
|
88
92
|
|
|
89
93
|
| Feature | Description |
|
|
90
94
|
|---|---|
|
|
91
95
|
| Autonomous repair loop | Runs analyze, patch, verify in a stateful LangGraph graph |
|
|
92
96
|
| Multi-model support | DeepSeek, Claude, GPT-4o, Gemini, Llama via OpenRouter |
|
|
93
97
|
| Framework detection | Automatically identifies your project's tooling setup |
|
|
98
|
+
| Package manager detection | Runs build/lint/test with npm, pnpm, yarn, or bun — whichever the target project actually uses |
|
|
94
99
|
| **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
100
|
| **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 |
|
|
96
101
|
| Safe file patching | Every modified file receives a `.opspilot.bak` backup |
|
|
@@ -102,7 +107,7 @@ bugzero rescue
|
|
|
102
107
|
|
|
103
108
|
---
|
|
104
109
|
|
|
105
|
-
##
|
|
110
|
+
## GitHub Action Mode
|
|
106
111
|
|
|
107
112
|
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
113
|
|
|
@@ -260,7 +265,7 @@ BugZero provides clear, actionable output for common failure modes:
|
|
|
260
265
|
---
|
|
261
266
|
|
|
262
267
|
<details>
|
|
263
|
-
<summary><strong
|
|
268
|
+
<summary><strong>Development Setup</strong> (contributing to BugZero itself)</summary>
|
|
264
269
|
|
|
265
270
|
Clone the repository and install dependencies. This project uses a pnpm monorepo managed by Turborepo, with a Vitest test suite and GitHub Actions CI.
|
|
266
271
|
|
package/demo.svg
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<svg viewBox="0 0 700 520" xmlns="http://www.w3.org/2000/svg" font-family="SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace">
|
|
2
|
+
<title>bugzero rescue demo</title>
|
|
3
|
+
<desc>Illustrative animation of "bugzero rescue" fixing a small TypeScript error. Log lines are the tool's real output format; the example error is a stand-in, not a captured recording.</desc>
|
|
4
|
+
|
|
5
|
+
<style>
|
|
6
|
+
text { font-size: 13px; }
|
|
7
|
+
.prompt { fill: #58a6ff; }
|
|
8
|
+
.out { fill: #c9d1d9; }
|
|
9
|
+
.ok { fill: #3fb950; }
|
|
10
|
+
.dim { fill: #8b949e; }
|
|
11
|
+
.dot { }
|
|
12
|
+
.titlebar-label { fill: #8b949e; font-size: 12px; }
|
|
13
|
+
|
|
14
|
+
@keyframes gA { 0% { opacity: 0; } 2% { opacity: 1; } 90% { opacity: 1; } 97% { opacity: 0; } 100% { opacity: 0; } }
|
|
15
|
+
@keyframes gB { 0%, 6% { opacity: 0; } 9% { opacity: 1; } 90% { opacity: 1; } 97% { opacity: 0; } 100% { opacity: 0; } }
|
|
16
|
+
@keyframes gC { 0%, 16% { opacity: 0; } 19% { opacity: 1; } 90% { opacity: 1; } 97% { opacity: 0; } 100% { opacity: 0; } }
|
|
17
|
+
@keyframes gD { 0%, 26% { opacity: 0; } 29% { opacity: 1; } 90% { opacity: 1; } 97% { opacity: 0; } 100% { opacity: 0; } }
|
|
18
|
+
@keyframes gE { 0%, 38% { opacity: 0; } 41% { opacity: 1; } 90% { opacity: 1; } 97% { opacity: 0; } 100% { opacity: 0; } }
|
|
19
|
+
@keyframes gF { 0%, 48% { opacity: 0; } 50% { opacity: 1; } 90% { opacity: 1; } 97% { opacity: 0; } 100% { opacity: 0; } }
|
|
20
|
+
@keyframes gG { 0%, 56% { opacity: 0; } 59% { opacity: 1; } 90% { opacity: 1; } 97% { opacity: 0; } 100% { opacity: 0; } }
|
|
21
|
+
|
|
22
|
+
.groupA { animation: gA 14s ease-in-out infinite; }
|
|
23
|
+
.groupB { animation: gB 14s ease-in-out infinite; }
|
|
24
|
+
.groupC { animation: gC 14s ease-in-out infinite; }
|
|
25
|
+
.groupD { animation: gD 14s ease-in-out infinite; }
|
|
26
|
+
.groupE { animation: gE 14s ease-in-out infinite; }
|
|
27
|
+
.groupF { animation: gF 14s ease-in-out infinite; }
|
|
28
|
+
.groupG { animation: gG 14s ease-in-out infinite; }
|
|
29
|
+
</style>
|
|
30
|
+
|
|
31
|
+
<rect x="0" y="0" width="700" height="520" rx="10" fill="#0d1117" />
|
|
32
|
+
<rect x="0" y="0" width="700" height="34" rx="10" fill="#161b22" />
|
|
33
|
+
<rect x="0" y="24" width="700" height="10" fill="#161b22" />
|
|
34
|
+
|
|
35
|
+
<circle class="dot" cx="20" cy="17" r="6" fill="#ff5f56" />
|
|
36
|
+
<circle class="dot" cx="40" cy="17" r="6" fill="#ffbd2e" />
|
|
37
|
+
<circle class="dot" cx="60" cy="17" r="6" fill="#27c93f" />
|
|
38
|
+
<text class="titlebar-label" x="350" y="21" text-anchor="middle">bugzero rescue</text>
|
|
39
|
+
|
|
40
|
+
<g class="groupA">
|
|
41
|
+
<text class="prompt" x="18" y="54">$ bugzero rescue --path ./demo-project</text>
|
|
42
|
+
</g>
|
|
43
|
+
|
|
44
|
+
<g class="groupB">
|
|
45
|
+
<text class="out" x="18" y="83">🤖 BugZero Fix</text>
|
|
46
|
+
<text class="out" x="18" y="102"> Path: ./demo-project</text>
|
|
47
|
+
<text class="out" x="18" y="121"> Framework: typescript</text>
|
|
48
|
+
<text class="out" x="18" y="140"> Max attempts: 3</text>
|
|
49
|
+
</g>
|
|
50
|
+
|
|
51
|
+
<g class="groupC">
|
|
52
|
+
<text class="out" x="18" y="169">[BugZero] Running validation pipeline in: ./demo-project</text>
|
|
53
|
+
<text class="out" x="18" y="188">[BugZero] Running build...</text>
|
|
54
|
+
<text class="out" x="18" y="207">[BugZero] Detected 1 error(s) (type: typescript)</text>
|
|
55
|
+
</g>
|
|
56
|
+
|
|
57
|
+
<g class="groupD">
|
|
58
|
+
<text class="out" x="18" y="236">[BugZero] Attempt 1/3 — asking AI…</text>
|
|
59
|
+
</g>
|
|
60
|
+
|
|
61
|
+
<g class="groupE">
|
|
62
|
+
<text class="out" x="18" y="265">[BugZero] Patching 1 file: src/sum.ts</text>
|
|
63
|
+
<text class="out" x="18" y="284">[BugZero] Reason: Fixed subtraction typo in the sum() function</text>
|
|
64
|
+
<text class="out" x="18" y="303">[BugZero] Backup saved to: src/sum.ts.opspilot.bak</text>
|
|
65
|
+
<text class="out" x="18" y="322">[BugZero] Re-running validation pipeline to verify fix…</text>
|
|
66
|
+
</g>
|
|
67
|
+
|
|
68
|
+
<g class="groupF">
|
|
69
|
+
<text class="ok" x="18" y="351">[BugZero] ✅ Validation succeeded!</text>
|
|
70
|
+
</g>
|
|
71
|
+
|
|
72
|
+
<g class="groupG">
|
|
73
|
+
<text class="dim" x="18" y="380">──────────────────────────────────────────────</text>
|
|
74
|
+
<text class="ok" x="18" y="399">✅ Build fixed after 1 attempt(s)!</text>
|
|
75
|
+
<text class="out" x="18" y="418"> Model: deepseek/deepseek-chat</text>
|
|
76
|
+
<text class="out" x="18" y="437"> Tokens: Prompt: 812 | Completion: 96 | Total: 908</text>
|
|
77
|
+
<text class="out" x="18" y="456"> File: src/sum.ts</text>
|
|
78
|
+
<text class="out" x="18" y="475"> Reason: Fixed subtraction typo in the sum() function</text>
|
|
79
|
+
<text class="out" x="18" y="494"> Root cause: sum() used the - operator instead of +</text>
|
|
80
|
+
</g>
|
|
81
|
+
</svg>
|
package/dist/index.js
CHANGED
|
@@ -466,6 +466,8 @@ var require_dist2 = __commonJS({
|
|
|
466
466
|
var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
467
467
|
var index_exports = {};
|
|
468
468
|
__export(index_exports, {
|
|
469
|
+
detectPackageManager: () => detectPackageManager3,
|
|
470
|
+
getRunScriptCommand: () => getRunScriptCommand,
|
|
469
471
|
parseErrors: () => parseErrors,
|
|
470
472
|
runBuild: () => runBuild,
|
|
471
473
|
runCommand: () => runCommand,
|
|
@@ -474,6 +476,39 @@ var require_dist2 = __commonJS({
|
|
|
474
476
|
runValidationPipeline: () => runValidationPipeline
|
|
475
477
|
});
|
|
476
478
|
module2.exports = __toCommonJS(index_exports);
|
|
479
|
+
var import_fs = __toESM2(require("fs"));
|
|
480
|
+
var import_path2 = __toESM2(require("path"));
|
|
481
|
+
var VALID_MANAGERS = ["npm", "pnpm", "yarn", "bun"];
|
|
482
|
+
var LOCKFILE_MANAGERS = [
|
|
483
|
+
{ file: "pnpm-workspace.yaml", manager: "pnpm" },
|
|
484
|
+
{ file: "pnpm-lock.yaml", manager: "pnpm" },
|
|
485
|
+
{ file: "yarn.lock", manager: "yarn" },
|
|
486
|
+
{ file: "bun.lockb", manager: "bun" },
|
|
487
|
+
{ file: "bun.lock", manager: "bun" },
|
|
488
|
+
{ file: "package-lock.json", manager: "npm" }
|
|
489
|
+
];
|
|
490
|
+
function detectPackageManager3(cwd = process.cwd()) {
|
|
491
|
+
try {
|
|
492
|
+
const pkgPath = import_path2.default.join(cwd, "package.json");
|
|
493
|
+
if (import_fs.default.existsSync(pkgPath)) {
|
|
494
|
+
const pkg = JSON.parse(import_fs.default.readFileSync(pkgPath, "utf-8"));
|
|
495
|
+
if (typeof pkg.packageManager === "string") {
|
|
496
|
+
const name = pkg.packageManager.split("@")[0].trim();
|
|
497
|
+
if (VALID_MANAGERS.includes(name)) {
|
|
498
|
+
return name;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
} catch {
|
|
503
|
+
}
|
|
504
|
+
for (const { file, manager } of LOCKFILE_MANAGERS) {
|
|
505
|
+
if (import_fs.default.existsSync(import_path2.default.join(cwd, file))) return manager;
|
|
506
|
+
}
|
|
507
|
+
return "npm";
|
|
508
|
+
}
|
|
509
|
+
function getRunScriptCommand(manager, script) {
|
|
510
|
+
return `${manager} run ${script}`;
|
|
511
|
+
}
|
|
477
512
|
async function runCommand(command, cwd) {
|
|
478
513
|
const { execa } = await import("execa");
|
|
479
514
|
try {
|
|
@@ -497,9 +532,9 @@ var require_dist2 = __commonJS({
|
|
|
497
532
|
};
|
|
498
533
|
}
|
|
499
534
|
}
|
|
500
|
-
var runBuild = (cwd) => runCommand("
|
|
501
|
-
var runLint = (cwd) => runCommand("
|
|
502
|
-
var runTests = (cwd) => runCommand("
|
|
535
|
+
var runBuild = (cwd) => runCommand(getRunScriptCommand(detectPackageManager3(cwd), "build"), cwd);
|
|
536
|
+
var runLint = (cwd) => runCommand(getRunScriptCommand(detectPackageManager3(cwd), "lint"), cwd);
|
|
537
|
+
var runTests = (cwd) => runCommand(getRunScriptCommand(detectPackageManager3(cwd), "test"), cwd);
|
|
503
538
|
var TS_ERROR_RE = /^(.+)\((\d+),(\d+)\):\s+error\s+TS\d+:\s+(.+)$/gm;
|
|
504
539
|
var ESLINT_ERROR_RE = /^\s+(\d+):(\d+)\s+error\s+(.+)$/gm;
|
|
505
540
|
var JEST_FAIL_RE = /● (.+)/g;
|
|
@@ -549,15 +584,15 @@ var require_dist2 = __commonJS({
|
|
|
549
584
|
}
|
|
550
585
|
return errors;
|
|
551
586
|
}
|
|
552
|
-
var
|
|
553
|
-
var
|
|
587
|
+
var import_fs2 = __toESM2(require("fs"));
|
|
588
|
+
var import_path22 = __toESM2(require("path"));
|
|
554
589
|
async function runValidationPipeline(cwd) {
|
|
555
590
|
const targetCwd = cwd ?? process.cwd();
|
|
556
591
|
let scripts = [];
|
|
557
592
|
try {
|
|
558
|
-
const pkgPath =
|
|
559
|
-
if (
|
|
560
|
-
const pkg = JSON.parse(
|
|
593
|
+
const pkgPath = import_path22.default.resolve(targetCwd, "package.json");
|
|
594
|
+
if (import_fs2.default.existsSync(pkgPath)) {
|
|
595
|
+
const pkg = JSON.parse(import_fs2.default.readFileSync(pkgPath, "utf-8"));
|
|
561
596
|
scripts = Object.keys(pkg.scripts || {});
|
|
562
597
|
}
|
|
563
598
|
} catch {
|
|
@@ -1375,6 +1410,7 @@ var require_dist7 = __commonJS({
|
|
|
1375
1410
|
var index_exports = {};
|
|
1376
1411
|
__export(index_exports, {
|
|
1377
1412
|
detectFramework: () => detectFramework2,
|
|
1413
|
+
detectPackageManager: () => import_analyzers2.detectPackageManager,
|
|
1378
1414
|
orchestrate: () => orchestrate2,
|
|
1379
1415
|
orchestrateAndFix: () => orchestrateAndFix2
|
|
1380
1416
|
});
|
|
@@ -1707,6 +1743,7 @@ ${rawOutput}
|
|
|
1707
1743
|
console.log("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1708
1744
|
}
|
|
1709
1745
|
}
|
|
1746
|
+
var import_analyzers2 = require_dist2();
|
|
1710
1747
|
}
|
|
1711
1748
|
});
|
|
1712
1749
|
|
|
@@ -1721,10 +1758,12 @@ program.command("hunt").description("Run build, lint, and tests \u2014 report is
|
|
|
1721
1758
|
try {
|
|
1722
1759
|
const cwd = import_path.default.resolve(opts.path);
|
|
1723
1760
|
const framework = (0, import_core.detectFramework)(cwd);
|
|
1761
|
+
const packageManager = (0, import_core.detectPackageManager)(cwd);
|
|
1724
1762
|
console.log(`
|
|
1725
1763
|
\u{1F50D} BugZero \u2014 Analyzing project`);
|
|
1726
1764
|
console.log(` Path: ${cwd}`);
|
|
1727
|
-
console.log(` Framework: ${framework}
|
|
1765
|
+
console.log(` Framework: ${framework}`);
|
|
1766
|
+
console.log(` Package manager: ${packageManager}
|
|
1728
1767
|
`);
|
|
1729
1768
|
const { build, lint, test } = await (0, import_core.orchestrate)({ cwd });
|
|
1730
1769
|
console.log("\u2500\u2500 Pipeline Summary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
@@ -1749,10 +1788,12 @@ program.command("rescue").description("Detect build failures and automatically a
|
|
|
1749
1788
|
const maxAttempts = parseInt(opts.maxAttempts, 10);
|
|
1750
1789
|
const dryRun = opts.dryRun;
|
|
1751
1790
|
const framework = (0, import_core.detectFramework)(cwd);
|
|
1791
|
+
const packageManager = (0, import_core.detectPackageManager)(cwd);
|
|
1752
1792
|
console.log(`
|
|
1753
1793
|
\u{1F916} BugZero Fix`);
|
|
1754
1794
|
console.log(` Path: ${cwd}`);
|
|
1755
1795
|
console.log(` Framework: ${framework}`);
|
|
1796
|
+
console.log(` Package manager: ${packageManager}`);
|
|
1756
1797
|
console.log(` Max attempts: ${maxAttempts}`);
|
|
1757
1798
|
if (dryRun) console.log(` Mode: DRY RUN (no files will be modified)`);
|
|
1758
1799
|
console.log();
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import "@opspilot/config"; // loads .env before anything else
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import path from "path";
|
|
6
|
-
import { orchestrate, orchestrateAndFix, detectFramework } from "@opspilot/core";
|
|
6
|
+
import { orchestrate, orchestrateAndFix, detectFramework, detectPackageManager } from "@opspilot/core";
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
const program = new Command();
|
|
@@ -22,10 +22,12 @@ program
|
|
|
22
22
|
try {
|
|
23
23
|
const cwd = path.resolve(opts.path);
|
|
24
24
|
const framework = detectFramework(cwd);
|
|
25
|
+
const packageManager = detectPackageManager(cwd);
|
|
25
26
|
|
|
26
27
|
console.log(`\n🔍 BugZero — Analyzing project`);
|
|
27
28
|
console.log(` Path: ${cwd}`);
|
|
28
|
-
console.log(` Framework: ${framework}
|
|
29
|
+
console.log(` Framework: ${framework}`);
|
|
30
|
+
console.log(` Package manager: ${packageManager}\n`);
|
|
29
31
|
|
|
30
32
|
const { build, lint, test } = await orchestrate({ cwd });
|
|
31
33
|
|
|
@@ -57,10 +59,12 @@ program
|
|
|
57
59
|
const maxAttempts = parseInt(opts.maxAttempts, 10);
|
|
58
60
|
const dryRun: boolean = opts.dryRun;
|
|
59
61
|
const framework = detectFramework(cwd);
|
|
62
|
+
const packageManager = detectPackageManager(cwd);
|
|
60
63
|
|
|
61
64
|
console.log(`\n🤖 BugZero Fix`);
|
|
62
65
|
console.log(` Path: ${cwd}`);
|
|
63
66
|
console.log(` Framework: ${framework}`);
|
|
67
|
+
console.log(` Package manager: ${packageManager}`);
|
|
64
68
|
console.log(` Max attempts: ${maxAttempts}`);
|
|
65
69
|
if (dryRun) console.log(` Mode: DRY RUN (no files will be modified)`);
|
|
66
70
|
console.log();
|