bangonit 0.2.2 → 0.3.1
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 +80 -59
- package/app/desktopapp/dist/main/index.js +10 -161
- package/app/desktopapp/dist/main/ipc.js +0 -20
- package/app/desktopapp/dist/main/preload.js +0 -2
- package/app/desktopapp/dist/main/tabs.js +0 -10
- package/app/desktopapp/dist/shared/args.js +21 -0
- package/app/desktopapp/package.json +1 -1
- package/app/replay/dist/replay.css +1 -1
- package/app/replay/dist/replay.js +20 -20
- package/app/webapp/.next/BUILD_ID +1 -1
- package/app/webapp/.next/app-build-manifest.json +7 -7
- package/app/webapp/.next/app-path-routes-manifest.json +1 -1
- package/app/webapp/.next/build-manifest.json +2 -2
- package/app/webapp/.next/next-minimal-server.js.nft.json +1 -1
- package/app/webapp/.next/next-server.js.nft.json +1 -1
- package/app/webapp/.next/prerender-manifest.json +1 -1
- package/app/webapp/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/webapp/.next/server/app/_not-found.html +1 -1
- package/app/webapp/.next/server/app/_not-found.rsc +1 -1
- package/app/webapp/.next/server/app/app/page.js +3 -7
- package/app/webapp/.next/server/app/app/page_client-reference-manifest.js +1 -1
- package/app/webapp/.next/server/app/app.html +1 -1
- package/app/webapp/.next/server/app/app.rsc +2 -2
- package/app/webapp/.next/server/app/index.html +1 -1
- package/app/webapp/.next/server/app/index.rsc +1 -1
- package/app/webapp/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/webapp/.next/server/app-paths-manifest.json +3 -3
- package/app/webapp/.next/server/chunks/708.js +1 -1
- package/app/webapp/.next/server/functions-config-manifest.json +1 -1
- package/app/webapp/.next/server/pages/404.html +1 -1
- package/app/webapp/.next/server/pages/500.html +1 -1
- package/app/webapp/.next/server/pages-manifest.json +1 -1
- package/app/webapp/.next/server/server-reference-manifest.json +1 -1
- package/app/webapp/.next/static/chunks/app/app/page-0e096497dcb81dae.js +1 -0
- package/app/webapp/.next/static/css/{869d3ff23c36c4b5.css → 38219627f55424f2.css} +1 -1
- package/app/webapp/.next/trace +2 -2
- package/app/webapp/package.json +7 -2
- package/app/webapp/src/shared/api/chat.ts +2 -11
- package/app/webapp/src/shared/components/AppShell.tsx +21 -1
- package/app/webapp/src/shared/components/SessionView.tsx +37 -65
- package/app/webapp/src/shared/lib/browser/mouse.ts +1 -1
- package/app/webapp/src/shared/lib/browser/recorder.ts +3 -3
- package/app/webapp/src/shared/types/global.d.ts +0 -3
- package/bin/app/desktopapp/src/shared/args.js +21 -0
- package/bin/bangonit.js +334 -283
- package/bin/src/cli/bangonit.js +767 -0
- package/package.json +11 -3
- package/app/webapp/.next/static/chunks/app/app/page-d38c1e48d37def82.js +0 -1
- /package/app/webapp/.next/static/{VAxJ7wm0K-fSKpsIoB9lY → Qq0OvlQijtcR84Dg9Dgp0}/_buildManifest.js +0 -0
- /package/app/webapp/.next/static/{VAxJ7wm0K-fSKpsIoB9lY → Qq0OvlQijtcR84Dg9Dgp0}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
# Bang On It!
|
|
2
2
|
|
|
3
|
-
Bang On It! bangs on your apps so you don't have to.
|
|
3
|
+
Bang On It! bangs on your apps so you don't have to.
|
|
4
|
+
|
|
5
|
+
Bang On It! replaces annoying manual QA and flakey end-to-end tests with a CLI-friendly AI agent that launches a real browser, reads your test plan, and executes it autonomously — clicking, typing, navigating, and verifying everything works.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
|
|
11
|
+
# Run a single test
|
|
12
|
+
npx bangonit run \
|
|
13
|
+
--plan "Go to localhost:3000, login as test@test.com (password: 12345), \
|
|
14
|
+
and click all the buttons in the dashboard and make sure they work"
|
|
15
|
+
|
|
16
|
+
# Run a suite of test plans
|
|
17
|
+
npx bangonit run testplans/*.md --concurrency 3
|
|
18
|
+
|
|
19
|
+
# Record a video of your test run in the recordings/ directory
|
|
20
|
+
npx bangonit run testplans/*.md --record
|
|
21
|
+
|
|
22
|
+
# Initialize your project with full CI integration and S3 video recording storage
|
|
23
|
+
npx bangonit init
|
|
24
|
+
```
|
|
4
25
|
|
|
5
26
|
## Why This Matters
|
|
6
27
|
|
|
@@ -36,7 +57,7 @@ npm install -g bangonit
|
|
|
36
57
|
|
|
37
58
|
The package provides three aliases: `bangonit`, `bang-on-it`, and `boi`.
|
|
38
59
|
|
|
39
|
-
##
|
|
60
|
+
## Getting started
|
|
40
61
|
|
|
41
62
|
```bash
|
|
42
63
|
# Launch the interactive UI
|
|
@@ -47,20 +68,20 @@ boi run testplans/checkout-flow.md
|
|
|
47
68
|
|
|
48
69
|
# Run an inline test
|
|
49
70
|
boi run --plan "Go to my-app.com, sign up with a test account, and verify the dashboard loads"
|
|
50
|
-
|
|
51
|
-
# Auto-generate tests from your git changes
|
|
52
|
-
boi run --auto
|
|
53
71
|
```
|
|
54
72
|
|
|
55
|
-
###
|
|
73
|
+
### Set up a project
|
|
56
74
|
|
|
57
75
|
```bash
|
|
58
|
-
#
|
|
76
|
+
# Creates config, test plan directories, and optionally GitHub Actions CI
|
|
59
77
|
boi init
|
|
60
78
|
|
|
61
|
-
# Run all test plans
|
|
79
|
+
# Run all test plans
|
|
62
80
|
boi run
|
|
63
81
|
|
|
82
|
+
# Run just the smoke tests
|
|
83
|
+
boi run testplans/smoke/
|
|
84
|
+
|
|
64
85
|
# Filter test plans by name
|
|
65
86
|
boi run -t checkout
|
|
66
87
|
```
|
|
@@ -71,9 +92,10 @@ Run `boi init` to create a `.bangonit/config.toml` in your project root:
|
|
|
71
92
|
|
|
72
93
|
```toml
|
|
73
94
|
testplans = "testplans"
|
|
74
|
-
|
|
95
|
+
# recordings_dir = "recordings" # default
|
|
96
|
+
# anthropic_api_key = "${ANTHROPIC_API_KEY}"
|
|
75
97
|
|
|
76
|
-
#
|
|
98
|
+
# Optional: upload recordings to S3 (or any S3-compatible provider)
|
|
77
99
|
[s3]
|
|
78
100
|
bucket = "my-recordings"
|
|
79
101
|
region = "us-east-1"
|
|
@@ -83,11 +105,13 @@ prefix = "bangonit"
|
|
|
83
105
|
# secret_key = "${AWS_SECRET_ACCESS_KEY}"
|
|
84
106
|
```
|
|
85
107
|
|
|
86
|
-
All fields are optional. The config is loaded from `.bangonit/config.toml` in the current directory by default, or from a custom path with `--config <path>`.
|
|
108
|
+
All fields are optional. The config is loaded from `.bangonit/config.toml` in the current directory (or any parent up to the repo root) by default, or from a custom path with `--config <path>`.
|
|
87
109
|
|
|
88
|
-
Any string value supports `${ENV_VAR}` interpolation, so you can reference environment variables without committing secrets.
|
|
110
|
+
Any string value supports `${ENV_VAR}` interpolation, so you can reference environment variables without committing secrets.
|
|
89
111
|
|
|
90
|
-
|
|
112
|
+
- **`testplans`** — directory of `.md` test plan files. When set, `boi run` auto-discovers plans. Without it, `boi run` launches the interactive UI.
|
|
113
|
+
- **`recordings_dir`** — where session recordings are written (default: `recordings`).
|
|
114
|
+
- **`[s3]`** — optional S3 upload for recordings. Works with any S3-compatible provider — set `endpoint` for DigitalOcean Spaces, Backblaze B2, MinIO, etc.
|
|
91
115
|
|
|
92
116
|
## How It Works
|
|
93
117
|
|
|
@@ -103,7 +127,25 @@ No selectors. No page objects. No flaky waits. Just describe what to test and le
|
|
|
103
127
|
|
|
104
128
|
## Test Plans
|
|
105
129
|
|
|
106
|
-
Test plans are Markdown files.
|
|
130
|
+
Test plans are Markdown files. `boi init` creates a recommended two-tier structure:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
testplans/
|
|
134
|
+
smoke/ # is the app alive? — run on every push/PR
|
|
135
|
+
homepage.md
|
|
136
|
+
login.md
|
|
137
|
+
acceptance/ # does the app do what it should? — core user journeys
|
|
138
|
+
checkout.md
|
|
139
|
+
onboarding.md
|
|
140
|
+
regression/ # did we break something? — bug fixes, edge cases
|
|
141
|
+
issue-123.md
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
- **Smoke** tests should be quick and focused — verify critical paths still work.
|
|
145
|
+
- **Acceptance** tests cover core user journeys and happy paths.
|
|
146
|
+
- **Regression** tests lock down bug fixes and edge cases so they don't recur.
|
|
147
|
+
|
|
148
|
+
Smoke tests run on every commit. The daily full run discovers everything recursively (smoke + acceptance + regression). Run `boi run testplans/smoke/` to run just the smoke tests.
|
|
107
149
|
|
|
108
150
|
```markdown
|
|
109
151
|
---
|
|
@@ -111,17 +153,15 @@ name: Add Todos
|
|
|
111
153
|
retries: 1
|
|
112
154
|
---
|
|
113
155
|
|
|
114
|
-
##
|
|
115
|
-
Navigate to http://localhost:3000
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
3. Verify the todo appears in the list
|
|
121
|
-
4. Verify the footer shows "1 item left"
|
|
156
|
+
## Steps
|
|
157
|
+
1. Navigate to http://localhost:3000
|
|
158
|
+
2. Verify the page loads with a heading and input field
|
|
159
|
+
3. Type "Buy groceries" and press Enter
|
|
160
|
+
4. Verify the todo appears in the list
|
|
161
|
+
5. Verify the footer shows "1 item left"
|
|
122
162
|
```
|
|
123
163
|
|
|
124
|
-
The `---` frontmatter is optional. `name` sets the display name, `retries` enables auto-retry on failure.
|
|
164
|
+
The `---` frontmatter is optional. `name` sets the display name, `retries` enables auto-retry on failure. You can also set retries for all tests via `--retries N` on the CLI (frontmatter takes precedence).
|
|
125
165
|
|
|
126
166
|
## Filtering Tests
|
|
127
167
|
|
|
@@ -139,24 +179,16 @@ boi run --filter checkout
|
|
|
139
179
|
|
|
140
180
|
You can customize the AI agent's behavior per-project by creating a `.bangonit/system_prompt.md` file in your project root. This content is prepended to the agent's system prompt for all test runs in that directory.
|
|
141
181
|
|
|
142
|
-
##
|
|
143
|
-
|
|
144
|
-
Record test runs for debugging and CI artifacts:
|
|
182
|
+
## Claude Code Skills
|
|
145
183
|
|
|
146
|
-
|
|
147
|
-
boi run testplans/checkout.md --record
|
|
148
|
-
```
|
|
184
|
+
`boi init` installs two [Claude Code](https://claude.com/claude-code) skills into your project:
|
|
149
185
|
|
|
150
|
-
|
|
151
|
-
-
|
|
152
|
-
- **`clips/`** — WebM video clips of browser interactions with cursor composited in
|
|
153
|
-
- **`data.json`** — timeline events, messages, console logs
|
|
186
|
+
- **`/test`** — Run tests locally. Pass file paths, directories, or a filter (e.g. `/test testplans/smoke/`, `/test -t login`).
|
|
187
|
+
- **`/create-test`** — Generate a new test plan from a description (e.g. `/create-test user can reset their password`). Reads your codebase to write accurate steps and places the file in the right directory.
|
|
154
188
|
|
|
155
|
-
|
|
189
|
+
## Session Recordings
|
|
156
190
|
|
|
157
|
-
|
|
158
|
-
boi run --record --s3-bucket my-bucket
|
|
159
|
-
```
|
|
191
|
+
Record test runs with `--record`. Each recording produces a self-contained HTML replay viewer. Configure where they're saved with `recordings_dir` in your config, and optionally upload to S3 via the `[s3]` config section.
|
|
160
192
|
|
|
161
193
|
## CLI Reference
|
|
162
194
|
|
|
@@ -165,19 +197,18 @@ Usage: boi <command> [options]
|
|
|
165
197
|
|
|
166
198
|
Commands:
|
|
167
199
|
run [files...] [options] Run test plans (or launch interactive UI)
|
|
168
|
-
init
|
|
169
|
-
init-ci Generate a GitHub Actions workflow
|
|
200
|
+
init Set up config, test plans, and optionally CI
|
|
170
201
|
|
|
171
202
|
Run options:
|
|
172
203
|
-t, --filter <text> Filter test plans by name substring
|
|
173
204
|
--config <path> Path to config file (default: .bangonit/config.toml)
|
|
174
205
|
--plan <text> Inline test plan (instead of file)
|
|
175
|
-
|
|
206
|
+
|
|
176
207
|
--prompt <text> Additional instructions appended to test plan
|
|
177
|
-
--record Record session replay
|
|
178
|
-
--
|
|
208
|
+
--record Record session replay
|
|
209
|
+
--retries <n> Retry failed tests N times
|
|
179
210
|
--headless Run without showing the browser window
|
|
180
|
-
--exit Exit immediately after tests complete
|
|
211
|
+
--exit Exit immediately after tests complete
|
|
181
212
|
--json Stream NDJSON events to stdout
|
|
182
213
|
--console Forward browser console logs to stdout
|
|
183
214
|
--output <file> Write JSON results to file
|
|
@@ -186,26 +217,16 @@ Run options:
|
|
|
186
217
|
--help Show this help message
|
|
187
218
|
```
|
|
188
219
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
Generate a GitHub Actions workflow:
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
boi init-ci
|
|
195
|
-
```
|
|
220
|
+
In CI environments, `--headless` and `--exit` default to `true` automatically.
|
|
196
221
|
|
|
197
|
-
|
|
222
|
+
## CI Usage
|
|
198
223
|
|
|
199
|
-
|
|
200
|
-
# Headless mode with timeout, exit on completion
|
|
201
|
-
boi run --headless --exit --timeout 120
|
|
224
|
+
`boi init` optionally generates two GitHub Actions workflows:
|
|
202
225
|
|
|
203
|
-
|
|
204
|
-
|
|
226
|
+
- **Smoke tests** (`bangonit-smoke.yml`) — runs `testplans/smoke/` on every push and PR
|
|
227
|
+
- **Full tests** (`bangonit-full.yml`) — runs all test plans daily at 6pm local time
|
|
205
228
|
|
|
206
|
-
|
|
207
|
-
boi run --headless --exit --record
|
|
208
|
-
```
|
|
229
|
+
In CI, `--headless` and `--exit` are enabled automatically.
|
|
209
230
|
|
|
210
231
|
## Multiple Tests
|
|
211
232
|
|
|
@@ -43,154 +43,16 @@ const path = __importStar(require("path"));
|
|
|
43
43
|
const fs = __importStar(require("fs"));
|
|
44
44
|
const ipc_1 = require("./ipc");
|
|
45
45
|
const tabs_1 = require("./tabs");
|
|
46
|
+
const args_1 = require("../shared/args");
|
|
46
47
|
let mainWindow = null;
|
|
48
|
+
// --- Parse args from env (set by CLI) ---
|
|
47
49
|
function parseArgs() {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
exit: false,
|
|
53
|
-
json: false,
|
|
54
|
-
console: false,
|
|
55
|
-
record: false,
|
|
56
|
-
auto: false,
|
|
57
|
-
output: null,
|
|
58
|
-
plan: null,
|
|
59
|
-
prompt: null,
|
|
60
|
-
concurrency: 1,
|
|
61
|
-
timeout: 0,
|
|
62
|
-
cwd: process.cwd(),
|
|
63
|
-
};
|
|
64
|
-
if (args.includes("--help") || args.includes("-h")) {
|
|
65
|
-
console.log(`Usage: boi run [test-plan-files...] [options]
|
|
66
|
-
|
|
67
|
-
Options:
|
|
68
|
-
--plan <text> Inline test plan (instead of file)
|
|
69
|
-
--auto Auto-generate test plan from git state
|
|
70
|
-
--prompt <text> Additional instructions appended to test plan
|
|
71
|
-
--record Record session replay to recordings/ directory
|
|
72
|
-
--headless Run without showing the browser window
|
|
73
|
-
--exit Exit immediately after tests complete (for CI)
|
|
74
|
-
--json Stream NDJSON events to stdout
|
|
75
|
-
--console Forward browser console logs to stdout
|
|
76
|
-
--output <file> Write JSON results to file
|
|
77
|
-
--concurrency <n> Number of parallel agents (default: 1)
|
|
78
|
-
--timeout <seconds> Test timeout in seconds (0 = none)
|
|
79
|
-
--cwd <dir> Working directory (default: current)
|
|
80
|
-
--help Show this help message`);
|
|
81
|
-
process.exit(0);
|
|
82
|
-
}
|
|
83
|
-
let i = 0;
|
|
84
|
-
// Skip "run" subcommand if present
|
|
85
|
-
if (args[i] === "run")
|
|
86
|
-
i++;
|
|
87
|
-
while (i < args.length) {
|
|
88
|
-
const arg = args[i];
|
|
89
|
-
if (arg === "--headless") {
|
|
90
|
-
result.headless = true;
|
|
91
|
-
}
|
|
92
|
-
else if (arg === "--exit") {
|
|
93
|
-
result.exit = true;
|
|
94
|
-
}
|
|
95
|
-
else if (arg === "--json") {
|
|
96
|
-
result.json = true;
|
|
97
|
-
}
|
|
98
|
-
else if (arg === "--console") {
|
|
99
|
-
result.console = true;
|
|
100
|
-
}
|
|
101
|
-
else if (arg === "--record") {
|
|
102
|
-
result.record = true;
|
|
103
|
-
}
|
|
104
|
-
else if (arg === "--auto") {
|
|
105
|
-
result.auto = true;
|
|
106
|
-
}
|
|
107
|
-
else if (arg === "--output" && i + 1 < args.length) {
|
|
108
|
-
result.output = args[++i];
|
|
109
|
-
}
|
|
110
|
-
else if (arg === "--plan" && i + 1 < args.length) {
|
|
111
|
-
result.plan = args[++i];
|
|
112
|
-
}
|
|
113
|
-
else if (arg === "--prompt" && i + 1 < args.length) {
|
|
114
|
-
result.prompt = args[++i];
|
|
115
|
-
}
|
|
116
|
-
else if (arg === "--concurrency" && i + 1 < args.length) {
|
|
117
|
-
result.concurrency = Math.max(1, parseInt(args[++i], 10) || 1);
|
|
118
|
-
}
|
|
119
|
-
else if (arg === "--timeout" && i + 1 < args.length) {
|
|
120
|
-
result.timeout = Math.max(0, parseInt(args[++i], 10) || 0);
|
|
121
|
-
}
|
|
122
|
-
else if (arg === "--cwd" && i + 1 < args.length) {
|
|
123
|
-
result.cwd = args[++i];
|
|
124
|
-
}
|
|
125
|
-
else if (!arg.startsWith("-")) {
|
|
126
|
-
result.testPlanFiles.push(arg);
|
|
127
|
-
}
|
|
128
|
-
i++;
|
|
50
|
+
const raw = process.env[args_1.ELECTRON_ARGS_ENV];
|
|
51
|
+
if (!raw) {
|
|
52
|
+
console.error("Error: BANGONIT_ARGS environment variable not set. Run via the boi CLI.");
|
|
53
|
+
process.exit(1);
|
|
129
54
|
}
|
|
130
|
-
return
|
|
131
|
-
}
|
|
132
|
-
// --- Auto-generate test plan from git state ---
|
|
133
|
-
async function generateTestPlan(cwd) {
|
|
134
|
-
const { execSync } = require("child_process");
|
|
135
|
-
const exec = (cmd) => {
|
|
136
|
-
try {
|
|
137
|
-
return execSync(cmd, { cwd, encoding: "utf-8", timeout: 10000 }).trim();
|
|
138
|
-
}
|
|
139
|
-
catch {
|
|
140
|
-
return "";
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
const diff = exec("git diff") + "\n" + exec("git diff --cached");
|
|
144
|
-
const status = exec("git status --short");
|
|
145
|
-
if (diff.trim() || status.trim()) {
|
|
146
|
-
return `## Auto-generated test plan from uncommitted changes
|
|
147
|
-
|
|
148
|
-
Analyze the following git changes and generate a comprehensive test plan. Then execute each test step.
|
|
149
|
-
|
|
150
|
-
### Git Status
|
|
151
|
-
\`\`\`
|
|
152
|
-
${status}
|
|
153
|
-
\`\`\`
|
|
154
|
-
|
|
155
|
-
### Git Diff
|
|
156
|
-
\`\`\`
|
|
157
|
-
${diff.slice(0, 8000)}
|
|
158
|
-
\`\`\`
|
|
159
|
-
|
|
160
|
-
Generate test steps that verify the changes work correctly, then execute them.`;
|
|
161
|
-
}
|
|
162
|
-
const logDiff = exec("git log master..HEAD --oneline");
|
|
163
|
-
const codeDiff = exec("git diff master...HEAD");
|
|
164
|
-
if (logDiff || codeDiff) {
|
|
165
|
-
return `## Auto-generated test plan from branch divergence
|
|
166
|
-
|
|
167
|
-
Analyze the following commits diverging from master and generate a comprehensive test plan. Then execute each test step.
|
|
168
|
-
|
|
169
|
-
### Commits
|
|
170
|
-
\`\`\`
|
|
171
|
-
${logDiff}
|
|
172
|
-
\`\`\`
|
|
173
|
-
|
|
174
|
-
### Diff from master
|
|
175
|
-
\`\`\`
|
|
176
|
-
${codeDiff.slice(0, 8000)}
|
|
177
|
-
\`\`\`
|
|
178
|
-
|
|
179
|
-
Generate test steps that verify these changes work correctly, then execute them.`;
|
|
180
|
-
}
|
|
181
|
-
const lastCommit = exec("git log -1 --format='%H %s'");
|
|
182
|
-
const lastDiff = exec("git show HEAD --stat");
|
|
183
|
-
return `## Auto-generated test plan from latest commit
|
|
184
|
-
|
|
185
|
-
No test plan provided and no changes unmerged to master. Generating test plan from latest commit.
|
|
186
|
-
|
|
187
|
-
### Latest Commit
|
|
188
|
-
\`\`\`
|
|
189
|
-
${lastCommit}
|
|
190
|
-
${lastDiff}
|
|
191
|
-
\`\`\`
|
|
192
|
-
|
|
193
|
-
Generate test steps that verify this commit works correctly, then execute them.`;
|
|
55
|
+
return args_1.electronArgsSchema.parse(JSON.parse(raw));
|
|
194
56
|
}
|
|
195
57
|
const cliArgs = parseArgs();
|
|
196
58
|
function parseFrontmatter(content) {
|
|
@@ -321,7 +183,8 @@ async function createWindow() {
|
|
|
321
183
|
// Create recordings directory if --record
|
|
322
184
|
if (cliArgs.record) {
|
|
323
185
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
324
|
-
const
|
|
186
|
+
const baseDir = cliArgs.recordingsDir || path.join(cliArgs.cwd, "recordings");
|
|
187
|
+
const recordDir = path.join(baseDir, timestamp);
|
|
325
188
|
fs.mkdirSync(recordDir, { recursive: true });
|
|
326
189
|
(0, ipc_1.setRunDir)(recordDir);
|
|
327
190
|
if (!cliArgs.json)
|
|
@@ -361,26 +224,12 @@ async function createWindow() {
|
|
|
361
224
|
agentIndex: i,
|
|
362
225
|
testPlan: parsed[i].body,
|
|
363
226
|
name: parsed[i].frontmatter.name || names[i],
|
|
364
|
-
retries: parsed[i].frontmatter.retries
|
|
227
|
+
retries: parsed[i].frontmatter.retries ?? cliArgs.retries,
|
|
365
228
|
extraPrompt: cliArgs.prompt || undefined,
|
|
366
229
|
record: cliArgs.record || undefined,
|
|
367
230
|
});
|
|
368
231
|
}
|
|
369
232
|
}
|
|
370
|
-
else if (cliArgs.auto) {
|
|
371
|
-
// Auto-generate from git state
|
|
372
|
-
const generated = await generateTestPlan(cliArgs.cwd);
|
|
373
|
-
const fullPlan = cliArgs.prompt
|
|
374
|
-
? `${generated}\n\n## Additional Instructions\n${cliArgs.prompt}`
|
|
375
|
-
: generated;
|
|
376
|
-
expectedResults = 1;
|
|
377
|
-
mainWindow.webContents.send("test-plan", {
|
|
378
|
-
agentIndex: 0,
|
|
379
|
-
testPlan: fullPlan,
|
|
380
|
-
name: "auto-generated",
|
|
381
|
-
record: cliArgs.record || undefined,
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
233
|
// No test plans provided — interactive UI will show the prompt screen
|
|
385
234
|
// Start timeout if specified
|
|
386
235
|
if (cliArgs.timeout > 0) {
|
|
@@ -206,26 +206,6 @@ function registerIpcHandlers() {
|
|
|
206
206
|
store.delete(`agentSessions.${agentId}`);
|
|
207
207
|
(0, tabs_1.destroyContext)(agentId);
|
|
208
208
|
});
|
|
209
|
-
// --- Bash (per-agent) ---
|
|
210
|
-
electron_1.ipcMain.handle("bash-exec", async (_, { agentId, command }) => {
|
|
211
|
-
const ctx = (0, tabs_1.getOrCreateContext)(agentId);
|
|
212
|
-
if (!ctx.bashInstance) {
|
|
213
|
-
const { Bash, OverlayFs } = await Promise.resolve().then(() => __importStar(require("just-bash")));
|
|
214
|
-
const overlay = new OverlayFs({ root: bangerCwd });
|
|
215
|
-
const cwd = overlay.getMountPoint();
|
|
216
|
-
ctx.bashInstance = new Bash({ fs: overlay, cwd });
|
|
217
|
-
try {
|
|
218
|
-
ctx.bashInstance.fs.mkdirSync("/home/user/downloads");
|
|
219
|
-
}
|
|
220
|
-
catch { }
|
|
221
|
-
ctx.bashFs = ctx.bashInstance.fs;
|
|
222
|
-
ctx.bashCwd = cwd;
|
|
223
|
-
}
|
|
224
|
-
const result = await ctx.bashInstance.exec(command, { cwd: ctx.bashCwd });
|
|
225
|
-
return [result.stdout, result.stderr ? `stderr: ${result.stderr}` : "", `exit code: ${result.exitCode}`]
|
|
226
|
-
.filter(Boolean)
|
|
227
|
-
.join("\n");
|
|
228
|
-
});
|
|
229
209
|
electron_1.ipcMain.handle("clear-partition", async (_, agentId) => {
|
|
230
210
|
const partitionName = `persist:agent-${agentId}`;
|
|
231
211
|
const ses = electron_1.session.fromPartition(partitionName);
|
|
@@ -14,8 +14,6 @@ contextBridge.exposeInMainWorld("bangonit", {
|
|
|
14
14
|
getAgentSession: (agentId) => ipcRenderer.invoke("get-agent-session", agentId),
|
|
15
15
|
setAgentSession: (agentId, session) => ipcRenderer.invoke("set-agent-session", { agentId, session }),
|
|
16
16
|
deleteAgentSession: (agentId) => ipcRenderer.invoke("delete-agent-session", agentId),
|
|
17
|
-
// Bash (per-agent)
|
|
18
|
-
bashExec: (agentId, command) => ipcRenderer.invoke("bash-exec", { agentId, command }),
|
|
19
17
|
// --- Low-level browser primitives ---
|
|
20
18
|
// CDP: send a raw CDP command to the active tab
|
|
21
19
|
cdpSend: (agentId, method, params) => ipcRenderer.invoke("cdp-send", { agentId, method, params }),
|
|
@@ -53,12 +53,9 @@ function getOrCreateContext(agentId) {
|
|
|
53
53
|
const ctx = {
|
|
54
54
|
tabs: new Map(),
|
|
55
55
|
activeTabId: null,
|
|
56
|
-
bashInstance: null,
|
|
57
|
-
bashCwd: null,
|
|
58
56
|
nextPopupId: 10000,
|
|
59
57
|
downloadsDir: null,
|
|
60
58
|
downloadSessionsSetup: new WeakSet(),
|
|
61
|
-
bashFs: null,
|
|
62
59
|
};
|
|
63
60
|
agentContexts.set(agentId, ctx);
|
|
64
61
|
return ctx;
|
|
@@ -126,13 +123,6 @@ function setupDownloads(ctx, wc) {
|
|
|
126
123
|
item.on("done", (_, state) => {
|
|
127
124
|
entry.bytes = item.getReceivedBytes();
|
|
128
125
|
entry.state = state === "completed" ? "completed" : "failed";
|
|
129
|
-
if (state === "completed" && ctx.bashFs) {
|
|
130
|
-
try {
|
|
131
|
-
const data = fs.readFileSync(savePath);
|
|
132
|
-
ctx.bashFs.writeFileSync(`/home/user/downloads/${filename}`, data);
|
|
133
|
-
}
|
|
134
|
-
catch { }
|
|
135
|
-
}
|
|
136
126
|
});
|
|
137
127
|
});
|
|
138
128
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ELECTRON_ARGS_ENV = exports.electronArgsSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
exports.electronArgsSchema = zod_1.z.object({
|
|
6
|
+
testPlanFiles: zod_1.z.array(zod_1.z.string()),
|
|
7
|
+
headless: zod_1.z.boolean(),
|
|
8
|
+
exit: zod_1.z.boolean(),
|
|
9
|
+
json: zod_1.z.boolean(),
|
|
10
|
+
console: zod_1.z.boolean(),
|
|
11
|
+
record: zod_1.z.boolean(),
|
|
12
|
+
retries: zod_1.z.number(),
|
|
13
|
+
output: zod_1.z.string().nullable(),
|
|
14
|
+
plan: zod_1.z.string().nullable(),
|
|
15
|
+
prompt: zod_1.z.string().nullable(),
|
|
16
|
+
concurrency: zod_1.z.number(),
|
|
17
|
+
timeout: zod_1.z.number(),
|
|
18
|
+
cwd: zod_1.z.string(),
|
|
19
|
+
recordingsDir: zod_1.z.string().nullable(),
|
|
20
|
+
});
|
|
21
|
+
exports.ELECTRON_ARGS_ENV = "BANGONIT_ARGS";
|