@vatzzza/botintern 1.0.0

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.
@@ -0,0 +1,33 @@
1
+ # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
+
4
+ name: Node.js Package
5
+
6
+ on:
7
+ push:
8
+ # only trigger on branches, not on tags
9
+ branches: 'main'
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-node@v4
17
+ with:
18
+ node-version: 20
19
+ - run: npm ci
20
+
21
+ publish-npm:
22
+ needs: build
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+ - uses: actions/setup-node@v4
27
+ with:
28
+ node-version: 20
29
+ registry-url: https://registry.npmjs.org/
30
+ - run: npm ci
31
+ - run: npm publish --access=public
32
+ env:
33
+ NODE_AUTH_TOKEN: ${{secrets.npm_token}}
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # botintern
2
+
3
+ To install dependencies:
4
+
5
+ ```bash
6
+ bun install
7
+ ```
8
+
9
+ To run:
10
+
11
+ ```bash
12
+ bun run index.ts
13
+ ```
14
+
15
+ This project was created using `bun init` in bun v1.3.5. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
package/bun.lock ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "configVersion": 1,
4
+ "workspaces": {
5
+ "": {
6
+ "name": "botintern",
7
+ "dependencies": {
8
+ "@google/generative-ai": "^0.24.1",
9
+ "chalk": "^5.6.2",
10
+ "commander": "^14.0.2",
11
+ "dotenv": "^17.2.3",
12
+ "ora": "^9.0.0",
13
+ "playwright": "^1.57.0",
14
+ },
15
+ "devDependencies": {
16
+ "@types/bun": "latest",
17
+ },
18
+ "peerDependencies": {
19
+ "typescript": "^5",
20
+ },
21
+ },
22
+ },
23
+ "packages": {
24
+ "@google/generative-ai": ["@google/generative-ai@0.24.1", "", {}, "sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q=="],
25
+
26
+ "@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="],
27
+
28
+ "@types/node": ["@types/node@25.0.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw=="],
29
+
30
+ "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
31
+
32
+ "bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="],
33
+
34
+ "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
35
+
36
+ "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
37
+
38
+ "cli-spinners": ["cli-spinners@3.4.0", "", {}, "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw=="],
39
+
40
+ "commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="],
41
+
42
+ "dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
43
+
44
+ "fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
45
+
46
+ "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
47
+
48
+ "is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="],
49
+
50
+ "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
51
+
52
+ "log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="],
53
+
54
+ "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
55
+
56
+ "onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
57
+
58
+ "ora": ["ora@9.0.0", "", { "dependencies": { "chalk": "^5.6.2", "cli-cursor": "^5.0.0", "cli-spinners": "^3.2.0", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.1.0", "log-symbols": "^7.0.1", "stdin-discarder": "^0.2.2", "string-width": "^8.1.0", "strip-ansi": "^7.1.2" } }, "sha512-m0pg2zscbYgWbqRR6ABga5c3sZdEon7bSgjnlXC64kxtxLOyjRcbbUkLj7HFyy/FTD+P2xdBWu8snGhYI0jc4A=="],
59
+
60
+ "playwright": ["playwright@1.57.0", "", { "dependencies": { "playwright-core": "1.57.0" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw=="],
61
+
62
+ "playwright-core": ["playwright-core@1.57.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ=="],
63
+
64
+ "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
65
+
66
+ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
67
+
68
+ "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="],
69
+
70
+ "string-width": ["string-width@8.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" } }, "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg=="],
71
+
72
+ "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
73
+
74
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
75
+
76
+ "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
77
+
78
+ "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="],
79
+ }
80
+ }
package/index.js ADDED
@@ -0,0 +1,425 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Use bun run index.js to run this file single time.
4
+ // Use bun run dev to run this file in watch mode.
5
+
6
+ import { Command } from "commander";
7
+ import chalk from "chalk";
8
+ import exec from "child_process";
9
+ import ora from "ora";
10
+ import { fixBuild, generateYaml } from "./lib/ai.js";
11
+ import fs from "fs";
12
+ import { extractErrorFile } from "./utils/errorExtractor.js";
13
+ import path from "path";
14
+ import { getCriticalSourceCode, getProjectStructure } from "./lib/fileTreeParser.js";
15
+ import { runTests } from "./lib/runTests.js";
16
+ import { runPlaywright } from "./lib/runPlaywright.js";
17
+ import { loop } from "./lib/loop.js";
18
+ import { saveApiKey } from "./lib/registerAndFetchKey.js";
19
+ import readline from "readline";
20
+
21
+ const banner = `
22
+ ${chalk.bold.cyan('โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”')}
23
+ ${chalk.cyan('โ”‚')} ${chalk.bold.white('โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—')} ${chalk.cyan('โ”‚')}
24
+ ${chalk.cyan('โ”‚')} ${chalk.cyan('โ•‘')} ${chalk.bold.white('โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–„ โ–„โ–ˆโ–ˆโ–ˆโ–ˆโ–„ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–„ โ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆ ')} ${chalk.cyan('โ•‘')} ${chalk.cyan('โ”‚')}
25
+ ${chalk.cyan('โ”‚')} ${chalk.cyan('โ•‘')} ${chalk.bold.white('โ–ˆโ–ˆโ–„โ–„โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–€โ–„โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆโ–„โ–„ โ–ˆโ–ˆโ–„โ–„โ–ˆโ–ˆโ–„ โ–ˆโ–ˆ โ–€โ–„โ–ˆโ–ˆ ')} ${chalk.cyan('โ•‘')} ${chalk.cyan('โ”‚')}
26
+ ${chalk.cyan('โ”‚')} ${chalk.cyan('โ•‘')} ${chalk.bold.white('โ–ˆโ–ˆโ–„โ–„โ–ˆโ–€ โ–€โ–ˆโ–ˆโ–ˆโ–ˆโ–€ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆโ–„โ–„โ–„โ–„ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆ ')} ${chalk.cyan('โ•‘')} ${chalk.cyan('โ”‚')}
27
+ ${chalk.cyan('โ”‚')} ${chalk.cyan('โ•‘')} ${chalk.gray(' ' + chalk.italic.blue('AI-Powered Code Testing & Validation') + ' ')} ${chalk.cyan('โ•‘')} ${chalk.cyan('โ”‚')}
28
+ ${chalk.cyan('โ”‚')} ${chalk.cyan('โ•‘')} ${chalk.dim(' ' + chalk.yellow('โšก') + ' The intern that fixes more bugs than it creates ' + chalk.yellow('โšก') + ' ')} ${chalk.cyan('โ•‘')} ${chalk.cyan('โ”‚')}
29
+ ${chalk.cyan('โ”‚')} ${chalk.cyan('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•')} ${chalk.cyan('โ”‚')}
30
+ ${chalk.cyan('โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ””')}
31
+
32
+ ${chalk.cyan.bold('๐Ÿš€ Ready to validate your AI-generated code? ๐Ÿš€')}
33
+
34
+ ${chalk.dim('โœจ Scan โ€ข Fix โ€ข Test โ€ข Generate โ€ข Loop')}
35
+ ${chalk.dim('')}
36
+
37
+ `;
38
+
39
+ const program = new Command();
40
+
41
+ program
42
+ .name('botintern')
43
+ .description(chalk.gray('Advanced CLI to validate and fix AI-generated code with intelligent testing.'))
44
+ .version('1.0.0')
45
+ .configureOutput({
46
+ writeErr: (str) => process.stderr.write(chalk.red(str)),
47
+ writeOut: (str) => process.stdout.write(str)
48
+ });
49
+
50
+ program
51
+ .command('login')
52
+ .description('Authenticate BotIntern with your Gemini API Key')
53
+ .action(() => {
54
+ const rl = readline.createInterface({
55
+ input: process.stdin,
56
+ output: process.stdout
57
+ });
58
+
59
+ console.log(chalk.cyan('๐Ÿค– BotIntern Login'));
60
+ console.log(chalk.dim('Get your free key at: https://aistudio.google.com/app/apikey'));
61
+
62
+ rl.question('\n๐Ÿ”‘ Paste your Gemini API Key: ', (key) => {
63
+ if (!key || key.trim().length === 0) {
64
+ console.log(chalk.red('โŒ Invalid key.'));
65
+ rl.close();
66
+ return;
67
+ }
68
+
69
+ saveApiKey(key.trim());
70
+ console.log(chalk.green('\nโœจ Success! Key saved globally. You can now use "botintern test" and "botintern loop" commands.'));
71
+ rl.close();
72
+ });
73
+ });
74
+
75
+ program.command('scan')
76
+ .description('๐Ÿ” Scan a codebase for errors')
77
+ .action(() => {
78
+ console.log(chalk.cyan('โ”Œโ”€ ') + chalk.bold.white('SCAN MODE') + chalk.cyan(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
79
+ console.log(chalk.cyan('โ”‚') + ' ' + chalk.blue('๐Ÿ” Initializing AI code scanner...'));
80
+ console.log(chalk.cyan('โ”‚') + ' ' + chalk.yellow('โšก Analyzing codebase for potential issues...'));
81
+ console.log(chalk.cyan('โ””โ”€') + chalk.cyan('โ”€'.repeat(45)));
82
+
83
+ const spinner = ora({
84
+ text: chalk.yellow('๐Ÿ” Scanning for AI hallucinations...'),
85
+ spinner: 'dots',
86
+ color: 'yellow'
87
+ }).start();
88
+
89
+ exec.exec("npm run build", function (error, stdout, stderr) {
90
+ if (error) {
91
+ spinner.fail({
92
+ text: chalk.red('โŒ BUILD FAILED'),
93
+ symbol: 'โœ–'
94
+ });
95
+ console.log('');
96
+ console.log(chalk.red('โ”Œโ”€ ') + chalk.bold.white('ERROR DETAILS') + chalk.red(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
97
+ console.log(chalk.red('โ”‚') + ' ' + chalk.gray('Build output detected issues:'));
98
+ console.log(chalk.red('โ”‚') + chalk.dim('โ”œโ”€ STDOUT:'));
99
+ console.log(chalk.red('โ”‚') + chalk.dim('โ”‚ ' + stdout.trim()));
100
+ console.log(chalk.red('โ”‚') + chalk.dim('โ”œโ”€ STDERR:'));
101
+ console.log(chalk.red('โ”‚') + chalk.dim('โ”‚ ' + stderr.trim()));
102
+ console.log(chalk.red('โ””โ”€') + chalk.red('โ”€'.repeat(45)));
103
+ } else {
104
+ spinner.succeed({
105
+ text: chalk.green('โœ… BUILD PASSED'),
106
+ symbol: 'โœ”'
107
+ });
108
+ console.log(chalk.green('โ”Œโ”€ ') + chalk.white('SCAN RESULTS') + chalk.green(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
109
+ console.log(chalk.green('โ”‚') + ' ' + chalk.white('โœจ No errors detected! Code looks clean.'));
110
+ console.log(chalk.green('โ”‚') + ' ' + chalk.gray('๐ŸŽฏ AI code quality: EXCELLENT'));
111
+ console.log(chalk.green('โ””โ”€') + chalk.green('โ”€'.repeat(45)));
112
+ }
113
+ })
114
+ });
115
+
116
+
117
+ program.command('fix')
118
+ .description('๐Ÿ”ง Automatically fix errors in a codebase')
119
+ .action(() => {
120
+ console.log(chalk.magenta('โ”Œโ”€ ') + chalk.bold.white('AUTO-FIX MODE') + chalk.magenta(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
121
+ console.log(chalk.magenta('โ”‚') + ' ' + chalk.blue('๐Ÿ”ง Initializing intelligent code repair...'));
122
+ console.log(chalk.magenta('โ”‚') + ' ' + chalk.yellow('โšก AI-powered error fixing enabled...'));
123
+ console.log(chalk.magenta('โ””โ”€') + chalk.magenta('โ”€'.repeat(45)));
124
+
125
+ const spinner = ora({
126
+ text: chalk.yellow('๐Ÿ” Detecting and analyzing build errors...'),
127
+ spinner: 'line',
128
+ color: 'yellow'
129
+ }).start();
130
+
131
+ exec.exec("npm run build", async function (error, stdout, stderr) {
132
+ if (error) {
133
+ spinner.fail({
134
+ text: chalk.red('โŒ BUILD ERRORS FOUND'),
135
+ symbol: 'โœ–'
136
+ });
137
+ console.log('');
138
+ console.log(chalk.red('โ”Œโ”€ ') + chalk.bold.white('ERROR ANALYSIS') + chalk.red(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
139
+ console.log(chalk.red('โ”‚') + ' ' + chalk.gray('๐Ÿ” Processing build output...'));
140
+ console.log(chalk.red('โ”‚') + chalk.dim('โ”œโ”€ BUILD LOGS:'));
141
+ console.log(chalk.red('โ”‚') + chalk.dim('โ”‚ ' + (stdout + stderr).trim()));
142
+
143
+ const combinedLogs = stdout + "\n" + stderr;
144
+ let brokenFilePath = extractErrorFile(combinedLogs);
145
+
146
+ if (!brokenFilePath) {
147
+ console.log(chalk.yellow('โ”‚') + chalk.dim('โ”œโ”€ ') + chalk.yellow('โš ๏ธ No specific file detected, using default: app/page.tsx'));
148
+ brokenFilePath = "app/page.tsx";
149
+ } else {
150
+ console.log(chalk.blue('โ”‚') + chalk.dim('โ”œโ”€ ') + chalk.blue(`๐ŸŽฏ Target identified: ${chalk.bold(brokenFilePath)}`));
151
+ }
152
+
153
+ console.log(chalk.magenta('โ”‚') + chalk.dim('โ””โ”€ ') + chalk.magenta('๐Ÿค– AI attempting fix...'));
154
+ console.log(chalk.magenta('โ””โ”€') + chalk.magenta('โ”€'.repeat(45)));
155
+
156
+ try {
157
+ const absolutePath = path.resolve(process.cwd(), brokenFilePath);
158
+
159
+ if (fs.existsSync(absolutePath)) {
160
+ const fixSpinner = ora({
161
+ text: chalk.cyan('๐Ÿง  AI generating solution...'),
162
+ spinner: 'bouncingBar',
163
+ color: 'cyan'
164
+ }).start();
165
+
166
+ const pageContent = fs.readFileSync(absolutePath, "utf-8");
167
+ const packageContent = fs.readFileSync(path.join(process.cwd(), "package.json"), "utf-8");
168
+
169
+ const finalCode = await fixBuild([combinedLogs, pageContent, packageContent]);
170
+ fixSpinner.succeed({
171
+ text: chalk.green('โœ… SOLUTION GENERATED'),
172
+ symbol: 'โœจ'
173
+ });
174
+
175
+ const applySpinner = ora({
176
+ text: chalk.blue('๐Ÿ“ Applying fixes...'),
177
+ spinner: 'dots',
178
+ color: 'blue'
179
+ }).start();
180
+
181
+ fs.writeFileSync(absolutePath, finalCode);
182
+ applySpinner.succeed({
183
+ text: chalk.green('โœจ FIXES APPLIED SUCCESSFULLY'),
184
+ symbol: 'โœ”'
185
+ });
186
+
187
+ console.log(chalk.green('โ”Œโ”€ ') + chalk.white('FIX SUMMARY') + chalk.green(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
188
+ console.log(chalk.green('โ”‚') + ' ' + chalk.white(`๐Ÿ“ File: ${chalk.gray(brokenFilePath)}`));
189
+ console.log(chalk.green('โ”‚') + ' ' + chalk.white('๐Ÿ”ง Status: ') + chalk.green('FIXED'));
190
+ console.log(chalk.green('โ”‚') + ' ' + chalk.gray('๐Ÿ’ก Run "botintern scan" to verify fixes'));
191
+ console.log(chalk.green('โ””โ”€') + chalk.green('โ”€'.repeat(45)));
192
+ } else {
193
+ console.log(chalk.red(`โŒ File not found: ${brokenFilePath}`));
194
+ }
195
+ } catch (err) {
196
+ console.log(chalk.red(`๐Ÿ’ฅ Fix failed: ${err.message}`));
197
+ }
198
+
199
+ } else {
200
+ spinner.succeed({
201
+ text: chalk.green('โœ… NO ERRORS TO FIX'),
202
+ symbol: 'โœจ'
203
+ });
204
+ console.log(chalk.green('โ”Œโ”€ ') + chalk.white('CODE STATUS') + chalk.green(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
205
+ console.log(chalk.green('โ”‚') + ' ' + chalk.white('๐ŸŽ‰ Codebase is already error-free!'));
206
+ console.log(chalk.green('โ”‚') + ' ' + chalk.gray('๐Ÿ’Ž Quality: PERFECT'));
207
+ console.log(chalk.green('โ””โ”€') + chalk.green('โ”€'.repeat(45)));
208
+ }
209
+ })
210
+ });
211
+
212
+
213
+
214
+ program.command("test")
215
+ .description("๐Ÿงช Run comprehensive playwright tests")
216
+ .action(async () => {
217
+ console.log(chalk.blue('โ”Œโ”€ ') + chalk.bold.white('TEST MODE') + chalk.blue(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
218
+ console.log(chalk.blue('โ”‚') + ' ' + chalk.cyan('๐Ÿงช Initializing test environment...'));
219
+ console.log(chalk.blue('โ”‚') + ' ' + chalk.yellow('โšก Launching browser automation...'));
220
+ console.log(chalk.blue('โ””โ”€') + chalk.blue('โ”€'.repeat(45)));
221
+
222
+ const spinner = ora({
223
+ text: chalk.cyan('๐Ÿš€ Setting up test browser...'),
224
+ spinner: 'toggle',
225
+ color: 'cyan'
226
+ }).start();
227
+
228
+ try {
229
+ const { browser, page } = await runPlaywright();
230
+ spinner.succeed({
231
+ text: chalk.green('๐ŸŒ Browser ready'),
232
+ symbol: 'โœจ'
233
+ });
234
+
235
+ const testSpinner = ora({
236
+ text: chalk.yellow('๐Ÿงช Running automated tests...'),
237
+ spinner: 'dots2',
238
+ color: 'yellow'
239
+ }).start();
240
+
241
+ const testResult = await runTests(page);
242
+ testSpinner.stop();
243
+
244
+ const cleanupSpinner = ora({
245
+ text: chalk.blue('๐Ÿงน Cleaning up...'),
246
+ spinner: 'pipe',
247
+ color: 'blue'
248
+ }).start();
249
+
250
+ await browser.close();
251
+ cleanupSpinner.succeed({
252
+ text: chalk.green('โœจ Test session complete'),
253
+ symbol: 'โœ”'
254
+ });
255
+
256
+ // Display results based on actual test outcome
257
+ if (testResult.success) {
258
+ console.log(chalk.green('โ”Œโ”€ ') + chalk.white('TEST RESULTS') + chalk.green(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
259
+ console.log(chalk.green('โ”‚') + ' ' + chalk.white('๐ŸŽฏ Status: ') + chalk.green('PASSED'));
260
+ console.log(chalk.green('โ”‚') + ' ' + chalk.white('๐Ÿ“Š Tests: ') + chalk.gray(`${testResult.passedTests}/${testResult.totalTests} passed`));
261
+ console.log(chalk.green('โ”‚') + ' ' + chalk.gray('๐Ÿ’ก All checks passed successfully'));
262
+ console.log(chalk.green('โ””โ”€') + chalk.green('โ”€'.repeat(45)));
263
+ } else {
264
+ console.log(chalk.red('โ”Œโ”€ ') + chalk.white('TEST RESULTS') + chalk.red(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
265
+ console.log(chalk.red('โ”‚') + ' ' + chalk.white('๐ŸŽฏ Status: ') + chalk.red('FAILED'));
266
+ if (testResult.totalTests) {
267
+ console.log(chalk.red('โ”‚') + ' ' + chalk.white('๐Ÿ“Š Tests: ') + chalk.yellow(`${testResult.passedTests}/${testResult.totalTests} passed`));
268
+ console.log(chalk.red('โ”‚') + ' ' + chalk.white('โŒ Failures: ') + chalk.red(`${testResult.failures?.length || 0}`));
269
+ } else if (testResult.error) {
270
+ console.log(chalk.red('โ”‚') + ' ' + chalk.white('โŒ Error: ') + chalk.red(testResult.error));
271
+ }
272
+ console.log(chalk.red('โ””โ”€') + chalk.red('โ”€'.repeat(45)));
273
+ process.exit(1);
274
+ }
275
+ } catch (error) {
276
+ spinner.fail({
277
+ text: chalk.red('โŒ Test execution failed'),
278
+ symbol: 'โœ–'
279
+ });
280
+ console.log(chalk.red(`๐Ÿ’ฅ Error: ${error.message}`));
281
+ }
282
+ });
283
+
284
+ program.command("generate-yaml")
285
+ .description("๐Ÿ“ Generate intelligent YAML test cases")
286
+ .action(async () => {
287
+ console.log(chalk.yellow('โ”Œโ”€ ') + chalk.bold.white('YAML GENERATOR') + chalk.yellow(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
288
+ console.log(chalk.yellow('โ”‚') + ' ' + chalk.cyan('๐Ÿ“ Creating intelligent test configurations...'));
289
+ console.log(chalk.yellow('โ”‚') + ' ' + chalk.gray('๐Ÿ” Analyzing codebase structure...'));
290
+ console.log(chalk.yellow('โ””โ”€') + chalk.yellow('โ”€'.repeat(45)));
291
+
292
+ const analyzeSpinner = ora({
293
+ text: chalk.blue('๐Ÿ” Scanning project structure...'),
294
+ spinner: 'dots12',
295
+ color: 'blue'
296
+ }).start();
297
+
298
+ const cwd = process.cwd();
299
+ const fileTree = getProjectStructure(cwd);
300
+ const sourceCode = getCriticalSourceCode(cwd);
301
+
302
+ analyzeSpinner.succeed({
303
+ text: chalk.green('๐Ÿ“Š Analysis complete'),
304
+ symbol: 'โœจ'
305
+ });
306
+
307
+ const yamlSpinner = ora({
308
+ text: chalk.magenta('๐Ÿค– AI generating YAML configurations...'),
309
+ spinner: 'growHorizontal',
310
+ color: 'magenta'
311
+ }).start();
312
+
313
+ const yamlPath = `${cwd}/vibe.yaml`;
314
+ let currentYaml = "";
315
+ if (fs.existsSync(yamlPath)) {
316
+ currentYaml = fs.readFileSync(yamlPath, 'utf-8');
317
+ }
318
+
319
+ const yaml = await generateYaml([fileTree, sourceCode, currentYaml, ""]);
320
+ fs.writeFileSync(yamlPath, yaml);
321
+
322
+ yamlSpinner.succeed({
323
+ text: chalk.green('โœจ YAML test cases generated'),
324
+ symbol: '๐Ÿ“‹'
325
+ });
326
+
327
+ console.log(chalk.green('โ”Œโ”€ ') + chalk.white('GENERATION SUMMARY') + chalk.green(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
328
+ console.log(chalk.green('โ”‚') + ' ' + chalk.white('๐Ÿ“ Output: ') + chalk.gray('vibe.yaml'));
329
+ console.log(chalk.green('โ”‚') + ' ' + chalk.white('๐Ÿงช Test cases: ') + chalk.blue('Generated'));
330
+ console.log(chalk.green('โ”‚') + ' ' + chalk.gray('๐Ÿ’ก Ready for automated testing'));
331
+ console.log(chalk.green('โ””โ”€') + chalk.green('โ”€'.repeat(45)));
332
+ });
333
+
334
+ program.command("loop")
335
+ .description("๐Ÿ”„ AI-powered iterative development loop")
336
+ .argument('<string>', 'Custom prompt for AI generation')
337
+ .option("-p", "Prompt mode")
338
+ .action(async (prompt, options) => {
339
+ console.log(chalk.cyan('โ”Œโ”€ ') + chalk.bold.white('AI LOOP MODE') + chalk.cyan(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
340
+ console.log(chalk.cyan('โ”‚') + ' ' + chalk.blue('๐Ÿ”„ Initializing iterative development...'));
341
+ console.log(chalk.cyan('โ”‚') + ' ' + chalk.yellow('๐Ÿค– AI agent ready for continuous improvement...'));
342
+ console.log(chalk.cyan('โ””โ”€') + chalk.cyan('โ”€'.repeat(45)));
343
+
344
+ if (prompt) {
345
+ console.log(chalk.blue('โ”Œโ”€ ') + chalk.white('CUSTOM PROMPT') + chalk.blue(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
346
+ console.log(chalk.blue('โ”‚') + ' ' + chalk.gray(`๐Ÿ“ ${prompt}`));
347
+ console.log(chalk.blue('โ””โ”€') + chalk.blue('โ”€'.repeat(45)));
348
+ }
349
+
350
+ const setupSpinner = ora({
351
+ text: chalk.cyan('๐Ÿš€ Setting up development environment...'),
352
+ spinner: 'bouncingBall',
353
+ color: 'cyan'
354
+ }).start();
355
+
356
+ try {
357
+ const { browser, page } = await runPlaywright();
358
+ setupSpinner.succeed({
359
+ text: chalk.green('๐ŸŒ Environment ready'),
360
+ symbol: 'โœจ'
361
+ });
362
+
363
+ const testSpinner = ora({
364
+ text: chalk.yellow('๐Ÿงช Running initial tests...'),
365
+ spinner: 'flip',
366
+ color: 'yellow'
367
+ }).start();
368
+
369
+ const testResult = await runTests(page);
370
+ testSpinner.succeed({
371
+ text: testResult.success ? chalk.green('โœ… Tests passed') : chalk.yellow('โš ๏ธ Tests need improvement'),
372
+ symbol: testResult.success ? '๐ŸŽ‰' : '๐Ÿ”„'
373
+ });
374
+
375
+ if (testResult.success && !prompt) {
376
+ console.log(chalk.green('โ”Œโ”€ ') + chalk.white('LOOP STATUS') + chalk.green(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'));
377
+ console.log(chalk.green('โ”‚') + ' ' + chalk.white('๐ŸŽ‰ All tests passed!'));
378
+ console.log(chalk.green('โ”‚') + ' ' + chalk.gray('โœจ No iterations needed'));
379
+ console.log(chalk.green('โ””โ”€') + chalk.green('โ”€'.repeat(45)));
380
+ process.exit(0);
381
+ } else {
382
+ const loopSpinner = ora({
383
+ text: chalk.magenta('๐Ÿค– AI improvement loop starting...'),
384
+ spinner: 'toggle8',
385
+ color: 'magenta'
386
+ }).start();
387
+
388
+ if (prompt) {
389
+ await loop(page, prompt);
390
+ } else {
391
+ await loop(page);
392
+ }
393
+
394
+ loopSpinner.succeed({
395
+ text: chalk.green('๐ŸŽฏ Loop completed'),
396
+ symbol: 'โœจ'
397
+ });
398
+ }
399
+
400
+ await browser.close();
401
+ } catch (error) {
402
+ setupSpinner.fail({
403
+ text: chalk.red('โŒ Loop initialization failed'),
404
+ symbol: 'โœ–'
405
+ });
406
+ console.log(chalk.red(`๐Ÿ’ฅ Error: ${error.message}`));
407
+ }
408
+ });
409
+
410
+ // Show welcome banner and help when no arguments provided
411
+ if (process.argv.length <= 2) {
412
+ console.log(banner);
413
+ console.log(chalk.cyan.bold('๐Ÿ“– Getting Started:'));
414
+ console.log(chalk.gray(' botintern scan') + chalk.dim(' โ€ข Scan codebase for errors'));
415
+ console.log(chalk.gray(' botintern fix') + chalk.dim(' โ€ข Auto-fix detected errors'));
416
+ console.log(chalk.gray(' botintern test') + chalk.dim(' โ€ข Run automated tests'));
417
+ console.log(chalk.gray(' botintern generate-yaml') + chalk.dim(' โ€ข Generate test configurations'));
418
+ console.log(chalk.gray(' botintern loop <prompt>') + chalk.dim(' โ€ข AI-powered iterative improvement'));
419
+ console.log('');
420
+ console.log(chalk.blue.bold('๐Ÿค– Need help?') + chalk.dim(' Run ' + chalk.gray('botintern --help')));
421
+ console.log(chalk.dim('โ”€'.repeat(67)));
422
+ process.exit(0);
423
+ }
424
+
425
+ program.parse();