agex 0.1.2 → 0.2.3
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/assets/assets/cursor.js +106 -2
- package/assets/assets/effects.js +1586 -0
- package/dist/chunk-EN7TTESF.js +6134 -0
- package/dist/cli.d.ts +4 -2
- package/dist/cli.js +546 -341
- package/dist/index.d.ts +5 -3
- package/dist/index.js +11 -4
- package/package.json +10 -7
- package/assets/cursor.js +0 -88
- package/dist/agents-SBEQWA3C.js +0 -10
- package/dist/chunk-2ZRS4JND.js +0 -849
- package/dist/chunk-H3CMLOXO.js +0 -421
package/dist/cli.js
CHANGED
|
@@ -1,223 +1,451 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
AGENT_NAMES,
|
|
4
|
+
APPROVAL_POLICIES,
|
|
5
|
+
OUTPUT_MODES,
|
|
6
|
+
detectDefaultBranch,
|
|
7
|
+
isAgexError,
|
|
8
|
+
prove,
|
|
9
|
+
proveOptionsSchema,
|
|
4
10
|
runAgent,
|
|
5
|
-
runReview
|
|
6
|
-
|
|
7
|
-
|
|
11
|
+
runReview,
|
|
12
|
+
validate,
|
|
13
|
+
viewportStringSchema
|
|
14
|
+
} from "./chunk-EN7TTESF.js";
|
|
8
15
|
|
|
9
|
-
// src/
|
|
10
|
-
|
|
11
|
-
console.log(`
|
|
12
|
-
agex proov - Prove visual assertions with screenshots
|
|
13
|
-
|
|
14
|
-
USAGE:
|
|
15
|
-
agex proov "<assertion>" [options]
|
|
16
|
-
|
|
17
|
-
OPTIONS:
|
|
18
|
-
--agent, -a <name> Agent to use: cursor (default), claude, codex
|
|
19
|
-
--url, -u <url> URL to navigate to
|
|
20
|
-
--output, -o <dir> Output directory (default: ./proov-results)
|
|
21
|
-
--video Enable video recording (default)
|
|
22
|
-
--no-video Disable video recording
|
|
23
|
-
--screenshots Enable screenshots (default)
|
|
24
|
-
--no-screenshots Disable screenshots
|
|
25
|
-
--model, -m <model> Model to use
|
|
26
|
-
--timeout, -t <ms> Timeout in milliseconds
|
|
27
|
-
--viewport <WxH> Viewport size (default: 1920x1080)
|
|
28
|
-
--headless Run headless (default)
|
|
29
|
-
--headed Show browser window
|
|
30
|
-
--help, -h Show this help
|
|
16
|
+
// src/cli.ts
|
|
17
|
+
import { defineCommand as defineCommand6, runMain } from "citty";
|
|
31
18
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
19
|
+
// src/commands/browse.ts
|
|
20
|
+
import { defineCommand } from "citty";
|
|
21
|
+
import { execa } from "execa";
|
|
22
|
+
async function installBrowser() {
|
|
23
|
+
console.log("[agex browse] Browser not found. Installing Chromium...");
|
|
24
|
+
await execa("npx", ["--yes", "playwright", "install", "chromium"], { stdio: "inherit" });
|
|
25
|
+
console.log("[agex browse] Browser installed successfully.");
|
|
36
26
|
}
|
|
37
|
-
function
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
options.video = false;
|
|
52
|
-
} else if (arg === "--model" || arg === "-m") {
|
|
53
|
-
options.model = args[++i];
|
|
54
|
-
} else if (arg === "--timeout" || arg === "-t") {
|
|
55
|
-
options.timeout = parseInt(args[++i], 10);
|
|
56
|
-
} else if (arg === "--viewport") {
|
|
57
|
-
const [width, height] = args[++i].split("x").map(Number);
|
|
58
|
-
options.viewport = { width, height };
|
|
59
|
-
} else if (arg === "--headless") {
|
|
60
|
-
options.headless = true;
|
|
61
|
-
} else if (arg === "--headed") {
|
|
62
|
-
options.headless = false;
|
|
63
|
-
} else if (arg === "--screenshots") {
|
|
64
|
-
options.screenshots = true;
|
|
65
|
-
} else if (arg === "--no-screenshots") {
|
|
66
|
-
options.screenshots = false;
|
|
67
|
-
} else if (arg === "--help" || arg === "-h") {
|
|
68
|
-
printHelp();
|
|
69
|
-
process.exit(0);
|
|
70
|
-
} else if (!arg.startsWith("-")) {
|
|
71
|
-
assertion = assertion ? `${assertion} ${arg}` : arg;
|
|
27
|
+
async function runAgentBrowser(browserArgs) {
|
|
28
|
+
try {
|
|
29
|
+
const result = await execa("npx", ["--yes", "agent-browser", ...browserArgs], {
|
|
30
|
+
stdio: "pipe",
|
|
31
|
+
env: { ...process.env }
|
|
32
|
+
});
|
|
33
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
34
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
35
|
+
return { success: true, needsBrowserInstall: false };
|
|
36
|
+
} catch (error) {
|
|
37
|
+
const execaError = error;
|
|
38
|
+
const output = `${execaError.stdout ?? ""}${execaError.stderr ?? ""}`;
|
|
39
|
+
if (output.includes("Executable doesn't exist") || output.includes("npx playwright install")) {
|
|
40
|
+
return { success: false, needsBrowserInstall: true };
|
|
72
41
|
}
|
|
42
|
+
if (execaError.stdout) process.stdout.write(execaError.stdout);
|
|
43
|
+
if (execaError.stderr) process.stderr.write(execaError.stderr);
|
|
44
|
+
return { success: false, needsBrowserInstall: false };
|
|
73
45
|
}
|
|
74
|
-
return { assertion, options };
|
|
75
|
-
}
|
|
76
|
-
async function runProov(args) {
|
|
77
|
-
const { assertion, options } = parseArgs(args);
|
|
78
|
-
if (!assertion) {
|
|
79
|
-
console.error("Error: No assertion provided");
|
|
80
|
-
printHelp();
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
console.log("========================================");
|
|
84
|
-
console.log("agex proov");
|
|
85
|
-
console.log("========================================");
|
|
86
|
-
console.log(`Agent: ${options.agent ?? "cursor"}`);
|
|
87
|
-
console.log(`Task: ${assertion}`);
|
|
88
|
-
if (options.url) {
|
|
89
|
-
console.log(`URL: ${options.url}`);
|
|
90
|
-
}
|
|
91
|
-
console.log("========================================\n");
|
|
92
|
-
const result = await proov(assertion, options);
|
|
93
|
-
console.log("\n========================================");
|
|
94
|
-
if (result.verdict === "pass") {
|
|
95
|
-
console.log("\u2705 PASS");
|
|
96
|
-
} else if (result.verdict === "fail") {
|
|
97
|
-
console.log("\u274C FAIL");
|
|
98
|
-
} else {
|
|
99
|
-
console.log("\u23ED\uFE0F SKIP");
|
|
100
|
-
}
|
|
101
|
-
console.log(`Reason: ${result.reason}`);
|
|
102
|
-
console.log(`Duration: ${result.durationMs}ms`);
|
|
103
|
-
console.log(`Output: ${result.outputDir}`);
|
|
104
|
-
console.log("========================================");
|
|
105
|
-
process.exit(result.verdict === "pass" ? 0 : 1);
|
|
106
46
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
47
|
+
var browse_default = defineCommand({
|
|
48
|
+
meta: {
|
|
49
|
+
name: "browse",
|
|
50
|
+
description: "Browser automation via agent-browser"
|
|
51
|
+
},
|
|
52
|
+
args: {
|
|
53
|
+
install: {
|
|
54
|
+
type: "boolean",
|
|
55
|
+
description: "Force reinstall browser",
|
|
56
|
+
default: false
|
|
57
|
+
},
|
|
58
|
+
_: {
|
|
59
|
+
type: "positional",
|
|
60
|
+
description: "agent-browser command and arguments",
|
|
61
|
+
required: false
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
async run({ args, rawArgs }) {
|
|
65
|
+
const browserArgs = rawArgs.filter((arg) => arg !== "--install");
|
|
66
|
+
if (browserArgs.length === 0) {
|
|
67
|
+
console.log(`
|
|
68
|
+
agex browse - Browser automation via agent-browser
|
|
112
69
|
|
|
113
70
|
USAGE:
|
|
114
|
-
agex
|
|
71
|
+
agex browse <command> [options]
|
|
72
|
+
|
|
73
|
+
COMMANDS:
|
|
74
|
+
All agent-browser commands are supported. Common ones:
|
|
75
|
+
|
|
76
|
+
open <url> Navigate to URL
|
|
77
|
+
snapshot [-i] Get accessibility tree (use -i for interactive elements)
|
|
78
|
+
click @e1 Click element by ref
|
|
79
|
+
fill @e2 "text" Fill input by ref
|
|
80
|
+
screenshot [path] Take screenshot
|
|
81
|
+
close Close browser
|
|
115
82
|
|
|
116
83
|
OPTIONS:
|
|
117
|
-
--
|
|
118
|
-
--model, -m <model> Model to use
|
|
119
|
-
--prompt, -p <text> Prompt (can also be positional)
|
|
120
|
-
--install Run install command before agent
|
|
121
|
-
--install-command Custom install command
|
|
122
|
-
--require-api-key Require API key
|
|
123
|
-
--no-approve-mcps Don't auto-approve MCPs
|
|
124
|
-
--no-browser Disable browser
|
|
125
|
-
--no-stream Disable streaming output
|
|
126
|
-
--mode <mode> Output mode: text, json, debug
|
|
127
|
-
--approval <policy> Approval policy
|
|
128
|
-
--timeout <ms> Timeout in milliseconds
|
|
129
|
-
--help, -h Show this help
|
|
84
|
+
--install Force reinstall browser
|
|
130
85
|
|
|
131
86
|
EXAMPLES:
|
|
132
|
-
agex
|
|
133
|
-
agex
|
|
87
|
+
agex browse open https://example.com
|
|
88
|
+
agex browse snapshot -i
|
|
89
|
+
agex browse click @e1
|
|
90
|
+
agex browse fill @e2 "hello@example.com"
|
|
91
|
+
agex browse screenshot page.png
|
|
92
|
+
agex browse close
|
|
93
|
+
|
|
94
|
+
For full documentation, run: npx agent-browser --help
|
|
95
|
+
Or visit: https://github.com/vercel-labs/agent-browser
|
|
134
96
|
`);
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
let installCommand;
|
|
142
|
-
let timeoutMs;
|
|
143
|
-
let requireApiKey = false;
|
|
144
|
-
let approveMcps = true;
|
|
145
|
-
let browser = true;
|
|
146
|
-
let streamOutput = true;
|
|
147
|
-
let outputMode = "text";
|
|
148
|
-
let approvalPolicy;
|
|
149
|
-
for (let i = 0; i < args.length; i += 1) {
|
|
150
|
-
const arg = args[i];
|
|
151
|
-
if (arg === "--help" || arg === "-h") {
|
|
152
|
-
printHelp2();
|
|
153
|
-
process.exit(0);
|
|
154
|
-
} else if (arg === "--agent" || arg === "-a") {
|
|
155
|
-
agent = args[i + 1];
|
|
156
|
-
i += 1;
|
|
157
|
-
} else if (arg === "--model" || arg === "-m") {
|
|
158
|
-
model = args[i + 1];
|
|
159
|
-
i += 1;
|
|
160
|
-
} else if (arg === "--prompt" || arg === "-p") {
|
|
161
|
-
prompt = args[i + 1] ?? "";
|
|
162
|
-
i += 1;
|
|
163
|
-
} else if (arg === "--install") {
|
|
164
|
-
install = true;
|
|
165
|
-
} else if (arg === "--install-command") {
|
|
166
|
-
installCommand = args[i + 1];
|
|
167
|
-
i += 1;
|
|
168
|
-
} else if (arg === "--require-api-key") {
|
|
169
|
-
requireApiKey = true;
|
|
170
|
-
} else if (arg === "--no-approve-mcps") {
|
|
171
|
-
approveMcps = false;
|
|
172
|
-
} else if (arg === "--no-browser") {
|
|
173
|
-
browser = false;
|
|
174
|
-
} else if (arg === "--no-stream") {
|
|
175
|
-
streamOutput = false;
|
|
176
|
-
} else if (arg === "--mode") {
|
|
177
|
-
const value = args[i + 1];
|
|
178
|
-
if (value === "json" || value === "text" || value === "debug") {
|
|
179
|
-
outputMode = value;
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (args.install) {
|
|
100
|
+
await installBrowser();
|
|
101
|
+
if (browserArgs.length === 0) {
|
|
102
|
+
return;
|
|
180
103
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
104
|
+
}
|
|
105
|
+
const firstRun = await runAgentBrowser(browserArgs);
|
|
106
|
+
if (firstRun.success) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (firstRun.needsBrowserInstall) {
|
|
110
|
+
await installBrowser();
|
|
111
|
+
try {
|
|
112
|
+
await execa("npx", ["--yes", "agent-browser", ...browserArgs], {
|
|
113
|
+
stdio: "inherit",
|
|
114
|
+
env: { ...process.env }
|
|
115
|
+
});
|
|
116
|
+
} catch (error) {
|
|
117
|
+
const exitCode = error.exitCode ?? 1;
|
|
118
|
+
process.exit(exitCode);
|
|
189
119
|
}
|
|
190
|
-
|
|
191
|
-
} else {
|
|
192
|
-
prompt = prompt ? `${prompt} ${arg}` : arg;
|
|
120
|
+
return;
|
|
193
121
|
}
|
|
122
|
+
process.exit(1);
|
|
194
123
|
}
|
|
195
|
-
|
|
196
|
-
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// src/commands/prove.ts
|
|
127
|
+
import { defineCommand as defineCommand2 } from "citty";
|
|
128
|
+
var prove_default = defineCommand2({
|
|
129
|
+
meta: {
|
|
130
|
+
name: "prove",
|
|
131
|
+
description: "Prove visual assertions with screenshots"
|
|
132
|
+
},
|
|
133
|
+
args: {
|
|
134
|
+
assertion: {
|
|
135
|
+
type: "positional",
|
|
136
|
+
description: "The assertion to prove",
|
|
137
|
+
required: true
|
|
138
|
+
},
|
|
139
|
+
agent: {
|
|
140
|
+
type: "string",
|
|
141
|
+
alias: "a",
|
|
142
|
+
description: "Agent to use: cursor (default), claude, codex",
|
|
143
|
+
default: "cursor"
|
|
144
|
+
},
|
|
145
|
+
url: {
|
|
146
|
+
type: "string",
|
|
147
|
+
alias: "u",
|
|
148
|
+
description: "URL to navigate to"
|
|
149
|
+
},
|
|
150
|
+
output: {
|
|
151
|
+
type: "string",
|
|
152
|
+
alias: "o",
|
|
153
|
+
description: "Output directory",
|
|
154
|
+
default: "./prove-results"
|
|
155
|
+
},
|
|
156
|
+
video: {
|
|
157
|
+
type: "boolean",
|
|
158
|
+
description: "Enable video recording",
|
|
159
|
+
default: true
|
|
160
|
+
},
|
|
161
|
+
screenshots: {
|
|
162
|
+
type: "boolean",
|
|
163
|
+
description: "Enable screenshots",
|
|
164
|
+
default: true
|
|
165
|
+
},
|
|
166
|
+
model: {
|
|
167
|
+
type: "string",
|
|
168
|
+
alias: "m",
|
|
169
|
+
description: "Model to use"
|
|
170
|
+
},
|
|
171
|
+
timeout: {
|
|
172
|
+
type: "string",
|
|
173
|
+
alias: "t",
|
|
174
|
+
description: "Timeout in milliseconds",
|
|
175
|
+
default: "300000"
|
|
176
|
+
},
|
|
177
|
+
viewport: {
|
|
178
|
+
type: "string",
|
|
179
|
+
description: "Viewport size (WxH)",
|
|
180
|
+
default: "1920x1080"
|
|
181
|
+
},
|
|
182
|
+
headless: {
|
|
183
|
+
type: "boolean",
|
|
184
|
+
description: "Run headless",
|
|
185
|
+
default: true
|
|
186
|
+
},
|
|
187
|
+
browser: {
|
|
188
|
+
type: "string",
|
|
189
|
+
alias: "b",
|
|
190
|
+
description: "Browser mode: mcp (default) or cli (agent-browser)",
|
|
191
|
+
default: "mcp"
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
async run({ args }) {
|
|
195
|
+
if (!AGENT_NAMES.includes(args.agent)) {
|
|
196
|
+
console.error(`Invalid agent: "${args.agent}". Must be one of: ${AGENT_NAMES.join(", ")}`);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
const viewportResult = viewportStringSchema.safeParse(args.viewport);
|
|
200
|
+
if (!viewportResult.success) {
|
|
201
|
+
console.error(`Invalid viewport: "${args.viewport}". Use format "WIDTHxHEIGHT" (e.g. "1920x1080")`);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
const options = {
|
|
205
|
+
agent: args.agent,
|
|
206
|
+
url: args.url,
|
|
207
|
+
outputDir: args.output,
|
|
208
|
+
video: args.video,
|
|
209
|
+
screenshots: args.screenshots,
|
|
210
|
+
model: args.model,
|
|
211
|
+
timeout: args.timeout ? parseInt(args.timeout, 10) : void 0,
|
|
212
|
+
viewport: viewportResult.data,
|
|
213
|
+
headless: args.headless
|
|
214
|
+
};
|
|
215
|
+
const validated = validate(proveOptionsSchema, options);
|
|
216
|
+
if (!validated.success) {
|
|
217
|
+
console.error(`Invalid options: ${validated.error}`);
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
console.log("========================================");
|
|
221
|
+
console.log("agex prove");
|
|
222
|
+
console.log("========================================");
|
|
223
|
+
console.log(`Workspace: ${process.cwd()}`);
|
|
224
|
+
console.log(`Agent: ${options.agent}`);
|
|
225
|
+
console.log(`Task: ${args.assertion}`);
|
|
226
|
+
if (options.url) {
|
|
227
|
+
console.log(`URL: ${options.url}`);
|
|
228
|
+
}
|
|
229
|
+
console.log("========================================\n");
|
|
230
|
+
try {
|
|
231
|
+
const result = await prove(args.assertion, options);
|
|
232
|
+
console.log("\n========================================");
|
|
233
|
+
if (result.verdict === "pass") {
|
|
234
|
+
console.log("\u2705 PASS");
|
|
235
|
+
} else if (result.verdict === "fail") {
|
|
236
|
+
console.log("\u274C FAIL");
|
|
237
|
+
} else {
|
|
238
|
+
console.log("\u23ED\uFE0F SKIP");
|
|
239
|
+
}
|
|
240
|
+
console.log(`Reason: ${result.reason}`);
|
|
241
|
+
console.log(`Duration: ${result.durationMs}ms`);
|
|
242
|
+
console.log(`Output: ${result.outputDir}`);
|
|
243
|
+
console.log("========================================");
|
|
244
|
+
process.exit(result.verdict === "pass" ? 0 : 1);
|
|
245
|
+
} catch (err) {
|
|
246
|
+
if (isAgexError(err)) {
|
|
247
|
+
console.error(`Error [${err.code}]: ${err.message}`);
|
|
248
|
+
} else {
|
|
249
|
+
console.error(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);
|
|
250
|
+
}
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
197
253
|
}
|
|
198
|
-
|
|
199
|
-
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// src/commands/prove-pr.ts
|
|
257
|
+
import { defineCommand as defineCommand3 } from "citty";
|
|
258
|
+
import { provePr } from "agex-prove-pr";
|
|
259
|
+
var prove_pr_default = defineCommand3({
|
|
260
|
+
meta: {
|
|
261
|
+
name: "prove-pr",
|
|
262
|
+
description: "Prove PR changes work with screenshots and evidence"
|
|
263
|
+
},
|
|
264
|
+
args: {
|
|
265
|
+
base: {
|
|
266
|
+
type: "string",
|
|
267
|
+
description: "Base branch/commit to compare against (auto-detected if omitted)"
|
|
268
|
+
},
|
|
269
|
+
agent: {
|
|
270
|
+
type: "string",
|
|
271
|
+
alias: "a",
|
|
272
|
+
description: "Agent to use: cursor (default), claude, codex",
|
|
273
|
+
default: "cursor"
|
|
274
|
+
},
|
|
275
|
+
url: {
|
|
276
|
+
type: "string",
|
|
277
|
+
alias: "u",
|
|
278
|
+
description: "Dev server URL for visual testing"
|
|
279
|
+
},
|
|
280
|
+
output: {
|
|
281
|
+
type: "string",
|
|
282
|
+
alias: "o",
|
|
283
|
+
description: "Output directory",
|
|
284
|
+
default: "./prove-pr-results"
|
|
285
|
+
},
|
|
286
|
+
hypotheses: {
|
|
287
|
+
type: "string",
|
|
288
|
+
description: "Number of hypotheses to generate",
|
|
289
|
+
default: "5"
|
|
290
|
+
},
|
|
291
|
+
model: {
|
|
292
|
+
type: "string",
|
|
293
|
+
alias: "m",
|
|
294
|
+
description: "Model to use"
|
|
295
|
+
},
|
|
296
|
+
viewport: {
|
|
297
|
+
type: "string",
|
|
298
|
+
description: "Viewport size (WxH)",
|
|
299
|
+
default: "1920x1080"
|
|
300
|
+
},
|
|
301
|
+
hint: {
|
|
302
|
+
type: "string",
|
|
303
|
+
description: "Additional prompt hint for hypothesis generation"
|
|
304
|
+
},
|
|
305
|
+
timeout: {
|
|
306
|
+
type: "string",
|
|
307
|
+
alias: "t",
|
|
308
|
+
description: "Timeout in milliseconds",
|
|
309
|
+
default: "300000"
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
async run({ args }) {
|
|
313
|
+
if (!AGENT_NAMES.includes(args.agent)) {
|
|
314
|
+
console.error(`Invalid agent: "${args.agent}". Must be one of: ${AGENT_NAMES.join(", ")}`);
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
const viewportResult = viewportStringSchema.safeParse(args.viewport);
|
|
318
|
+
if (!viewportResult.success) {
|
|
319
|
+
console.error(`Invalid viewport: "${args.viewport}". Use format "WIDTHxHEIGHT" (e.g. "1920x1080")`);
|
|
320
|
+
process.exit(1);
|
|
321
|
+
}
|
|
322
|
+
const hypothesesCount = parseInt(args.hypotheses, 10);
|
|
323
|
+
if (isNaN(hypothesesCount) || hypothesesCount <= 0) {
|
|
324
|
+
console.error(`Invalid hypotheses count: "${args.hypotheses}". Must be a positive integer.`);
|
|
325
|
+
process.exit(1);
|
|
326
|
+
}
|
|
327
|
+
const request = {
|
|
328
|
+
baseRef: args.base,
|
|
329
|
+
agent: args.agent,
|
|
330
|
+
url: args.url,
|
|
331
|
+
outputDir: args.output,
|
|
332
|
+
hypothesesCount,
|
|
333
|
+
model: args.model,
|
|
334
|
+
viewport: viewportResult.data,
|
|
335
|
+
hint: args.hint,
|
|
336
|
+
timeoutMs: args.timeout ? parseInt(args.timeout, 10) : void 0
|
|
337
|
+
};
|
|
338
|
+
console.log("========================================");
|
|
339
|
+
console.log("agex prove-pr");
|
|
340
|
+
console.log("========================================");
|
|
341
|
+
console.log(`Base: ${request.baseRef || "(auto-detect)"}`);
|
|
342
|
+
console.log(`Agent: ${request.agent}`);
|
|
343
|
+
console.log(`Hypotheses: ${hypothesesCount}`);
|
|
344
|
+
if (request.url) console.log(`URL: ${request.url}`);
|
|
345
|
+
console.log(`Output: ${request.outputDir}`);
|
|
346
|
+
console.log("========================================\n");
|
|
347
|
+
try {
|
|
348
|
+
const result = await provePr(request);
|
|
349
|
+
console.log("\n========================================");
|
|
350
|
+
console.log("RESULTS");
|
|
351
|
+
console.log("========================================");
|
|
352
|
+
console.log(`\u2705 Passed: ${result.summary.pass}`);
|
|
353
|
+
console.log(`\u274C Failed: ${result.summary.fail}`);
|
|
354
|
+
console.log(`\u23ED\uFE0F Skipped: ${result.summary.skip}`);
|
|
355
|
+
console.log(`Duration: ${(result.durationMs / 1e3).toFixed(1)}s`);
|
|
356
|
+
console.log(`Output: ${result.outputDir}`);
|
|
357
|
+
console.log("========================================");
|
|
358
|
+
process.exit(result.summary.fail === 0 ? 0 : 1);
|
|
359
|
+
} catch (err) {
|
|
360
|
+
if (isAgexError(err)) {
|
|
361
|
+
console.error(`Error [${err.code}]: ${err.message}`);
|
|
362
|
+
} else {
|
|
363
|
+
console.error(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);
|
|
364
|
+
}
|
|
365
|
+
process.exit(1);
|
|
366
|
+
}
|
|
200
367
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// src/commands/review.ts
|
|
371
|
+
import { defineCommand as defineCommand4 } from "citty";
|
|
372
|
+
var review_default = defineCommand4({
|
|
373
|
+
meta: {
|
|
374
|
+
name: "review",
|
|
375
|
+
description: "Review code changes"
|
|
376
|
+
},
|
|
377
|
+
args: {
|
|
378
|
+
base: {
|
|
379
|
+
type: "string",
|
|
380
|
+
description: "Base branch/commit to compare against (auto-detected if omitted)"
|
|
381
|
+
},
|
|
382
|
+
agent: {
|
|
383
|
+
type: "string",
|
|
384
|
+
alias: "a",
|
|
385
|
+
description: "Agent to use: cursor, claude, codex",
|
|
386
|
+
required: true
|
|
387
|
+
},
|
|
388
|
+
model: {
|
|
389
|
+
type: "string",
|
|
390
|
+
alias: "m",
|
|
391
|
+
description: "Model to use"
|
|
392
|
+
},
|
|
393
|
+
worktree: {
|
|
394
|
+
type: "boolean",
|
|
395
|
+
description: "Include worktree changes",
|
|
396
|
+
default: true
|
|
397
|
+
},
|
|
398
|
+
hypotheses: {
|
|
399
|
+
type: "string",
|
|
400
|
+
description: "Number of hypotheses to generate"
|
|
401
|
+
},
|
|
402
|
+
hint: {
|
|
403
|
+
type: "string",
|
|
404
|
+
description: "Additional prompt hint"
|
|
405
|
+
},
|
|
406
|
+
timeout: {
|
|
407
|
+
type: "string",
|
|
408
|
+
alias: "t",
|
|
409
|
+
description: "Timeout in milliseconds",
|
|
410
|
+
default: "300000"
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
async run({ args }) {
|
|
414
|
+
if (!AGENT_NAMES.includes(args.agent)) {
|
|
415
|
+
console.error(`Invalid agent: "${args.agent}". Must be one of: ${AGENT_NAMES.join(", ")}`);
|
|
416
|
+
process.exit(1);
|
|
417
|
+
}
|
|
418
|
+
if (args.hypotheses) {
|
|
419
|
+
const h = parseInt(args.hypotheses, 10);
|
|
420
|
+
if (isNaN(h) || h <= 0) {
|
|
421
|
+
console.error(`Invalid hypotheses count: "${args.hypotheses}". Must be a positive integer.`);
|
|
422
|
+
process.exit(1);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
try {
|
|
426
|
+
const base = args.base || detectDefaultBranch();
|
|
427
|
+
await runReview({
|
|
428
|
+
baseRef: base,
|
|
429
|
+
agent: args.agent,
|
|
430
|
+
model: args.model,
|
|
431
|
+
includeWorktree: args.worktree,
|
|
432
|
+
hypotheses: args.hypotheses ? parseInt(args.hypotheses, 10) : void 0,
|
|
433
|
+
promptHint: args.hint,
|
|
434
|
+
timeoutMs: args.timeout ? parseInt(args.timeout, 10) : void 0
|
|
435
|
+
});
|
|
436
|
+
} catch (err) {
|
|
437
|
+
if (isAgexError(err)) {
|
|
438
|
+
console.error(`Error [${err.code}]: ${err.message}`);
|
|
439
|
+
} else {
|
|
440
|
+
console.error(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);
|
|
441
|
+
}
|
|
442
|
+
process.exit(1);
|
|
443
|
+
}
|
|
204
444
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
install,
|
|
210
|
-
installCommand,
|
|
211
|
-
requireApiKey,
|
|
212
|
-
approveMcps,
|
|
213
|
-
browser,
|
|
214
|
-
streamOutput,
|
|
215
|
-
quietOutput,
|
|
216
|
-
outputMode,
|
|
217
|
-
approvalPolicy,
|
|
218
|
-
timeoutMs
|
|
219
|
-
};
|
|
220
|
-
}
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
// src/commands/run.ts
|
|
448
|
+
import { defineCommand as defineCommand5 } from "citty";
|
|
221
449
|
function formatOutput(result, mode, wasStreamed) {
|
|
222
450
|
switch (mode) {
|
|
223
451
|
case "json":
|
|
@@ -233,155 +461,132 @@ ${JSON.stringify(result.json, null, 2)}`;
|
|
|
233
461
|
return null;
|
|
234
462
|
}
|
|
235
463
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
464
|
+
var run_default = defineCommand5({
|
|
465
|
+
meta: {
|
|
466
|
+
name: "run",
|
|
467
|
+
description: "Execute AI agent tasks"
|
|
468
|
+
},
|
|
469
|
+
args: {
|
|
470
|
+
prompt: {
|
|
471
|
+
type: "positional",
|
|
472
|
+
description: "The prompt to execute",
|
|
473
|
+
required: true
|
|
474
|
+
},
|
|
475
|
+
agent: {
|
|
476
|
+
type: "string",
|
|
477
|
+
alias: "a",
|
|
478
|
+
description: "Agent to use: cursor, claude, codex (auto-detected if not specified)"
|
|
479
|
+
},
|
|
480
|
+
model: {
|
|
481
|
+
type: "string",
|
|
482
|
+
alias: "m",
|
|
483
|
+
description: "Model to use"
|
|
484
|
+
},
|
|
485
|
+
install: {
|
|
486
|
+
type: "boolean",
|
|
487
|
+
description: "Run install command before agent",
|
|
488
|
+
default: false
|
|
489
|
+
},
|
|
490
|
+
installCommand: {
|
|
491
|
+
type: "string",
|
|
492
|
+
description: "Custom install command"
|
|
493
|
+
},
|
|
494
|
+
requireApiKey: {
|
|
495
|
+
type: "boolean",
|
|
496
|
+
description: "Require API key",
|
|
497
|
+
default: false
|
|
498
|
+
},
|
|
499
|
+
approveMcps: {
|
|
500
|
+
type: "boolean",
|
|
501
|
+
description: "Auto-approve MCPs",
|
|
502
|
+
default: true
|
|
503
|
+
},
|
|
504
|
+
browser: {
|
|
505
|
+
type: "boolean",
|
|
506
|
+
description: "Enable browser",
|
|
507
|
+
default: true
|
|
508
|
+
},
|
|
509
|
+
stream: {
|
|
510
|
+
type: "boolean",
|
|
511
|
+
description: "Enable streaming output",
|
|
512
|
+
default: true
|
|
513
|
+
},
|
|
514
|
+
mode: {
|
|
515
|
+
type: "string",
|
|
516
|
+
description: "Output mode: text, json, debug",
|
|
517
|
+
default: "text"
|
|
518
|
+
},
|
|
519
|
+
approval: {
|
|
520
|
+
type: "string",
|
|
521
|
+
description: "Approval policy: never, on-request, on-failure, untrusted"
|
|
522
|
+
},
|
|
523
|
+
timeout: {
|
|
524
|
+
type: "string",
|
|
525
|
+
description: "Timeout in milliseconds",
|
|
526
|
+
default: "300000"
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
async run({ args }) {
|
|
530
|
+
if (args.agent && !AGENT_NAMES.includes(args.agent)) {
|
|
531
|
+
console.error(`Invalid agent: "${args.agent}". Must be one of: ${AGENT_NAMES.join(", ")}`);
|
|
532
|
+
process.exit(1);
|
|
533
|
+
}
|
|
534
|
+
if (!OUTPUT_MODES.includes(args.mode)) {
|
|
535
|
+
console.error(`Invalid mode: "${args.mode}". Must be one of: ${OUTPUT_MODES.join(", ")}`);
|
|
536
|
+
process.exit(1);
|
|
537
|
+
}
|
|
538
|
+
if (args.approval && !APPROVAL_POLICIES.includes(args.approval)) {
|
|
539
|
+
console.error(`Invalid approval policy: "${args.approval}". Must be one of: ${APPROVAL_POLICIES.join(", ")}`);
|
|
540
|
+
process.exit(1);
|
|
541
|
+
}
|
|
542
|
+
const outputMode = args.mode;
|
|
543
|
+
const quietOutput = outputMode === "json";
|
|
544
|
+
const streamOutput = quietOutput ? false : args.stream;
|
|
545
|
+
const request = {
|
|
546
|
+
agent: args.agent,
|
|
547
|
+
prompt: args.prompt,
|
|
548
|
+
model: args.model,
|
|
549
|
+
install: args.install,
|
|
550
|
+
installCommand: args.installCommand,
|
|
551
|
+
requireApiKey: args.requireApiKey,
|
|
552
|
+
approveMcps: args.approveMcps,
|
|
553
|
+
browser: args.browser,
|
|
554
|
+
streamOutput,
|
|
555
|
+
quietOutput,
|
|
556
|
+
approvalPolicy: args.approval,
|
|
557
|
+
timeoutMs: args.timeout ? parseInt(args.timeout, 10) : void 0
|
|
558
|
+
};
|
|
559
|
+
try {
|
|
560
|
+
const result = await runAgent(request);
|
|
561
|
+
const output = formatOutput(result, outputMode, streamOutput);
|
|
562
|
+
if (output !== null) {
|
|
563
|
+
process.stdout.write(`${output}
|
|
266
564
|
`);
|
|
267
|
-
}
|
|
268
|
-
function parseArgs3(args) {
|
|
269
|
-
let baseRef = "";
|
|
270
|
-
let agent;
|
|
271
|
-
let model;
|
|
272
|
-
let includeWorktree = true;
|
|
273
|
-
let hypotheses;
|
|
274
|
-
let promptHint;
|
|
275
|
-
for (let i = 0; i < args.length; i += 1) {
|
|
276
|
-
const arg = args[i];
|
|
277
|
-
if (arg === "--help" || arg === "-h") {
|
|
278
|
-
printHelp3();
|
|
279
|
-
process.exit(0);
|
|
280
|
-
} else if (arg === "--base") {
|
|
281
|
-
baseRef = args[i + 1] ?? "";
|
|
282
|
-
i += 1;
|
|
283
|
-
} else if (arg === "--agent" || arg === "-a") {
|
|
284
|
-
agent = args[i + 1];
|
|
285
|
-
i += 1;
|
|
286
|
-
} else if (arg === "--model" || arg === "-m") {
|
|
287
|
-
model = args[i + 1];
|
|
288
|
-
i += 1;
|
|
289
|
-
} else if (arg === "--no-worktree") {
|
|
290
|
-
includeWorktree = false;
|
|
291
|
-
} else if (arg === "--hypotheses") {
|
|
292
|
-
const value = Number(args[i + 1]);
|
|
293
|
-
if (!Number.isNaN(value)) {
|
|
294
|
-
hypotheses = value;
|
|
295
565
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
566
|
+
} catch (err) {
|
|
567
|
+
if (isAgexError(err)) {
|
|
568
|
+
console.error(`Error [${err.code}]: ${err.message}`);
|
|
569
|
+
} else {
|
|
570
|
+
console.error(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);
|
|
571
|
+
}
|
|
572
|
+
process.exit(1);
|
|
300
573
|
}
|
|
301
574
|
}
|
|
302
|
-
|
|
303
|
-
throw new Error("Missing --base");
|
|
304
|
-
}
|
|
305
|
-
if (!agent) {
|
|
306
|
-
throw new Error("Missing --agent");
|
|
307
|
-
}
|
|
308
|
-
return {
|
|
309
|
-
baseRef,
|
|
310
|
-
agent,
|
|
311
|
-
model,
|
|
312
|
-
includeWorktree,
|
|
313
|
-
hypotheses,
|
|
314
|
-
promptHint
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
async function runReview2(args) {
|
|
318
|
-
const request = parseArgs3(args);
|
|
319
|
-
await runReview(request);
|
|
320
|
-
}
|
|
575
|
+
});
|
|
321
576
|
|
|
322
577
|
// src/cli.ts
|
|
323
|
-
var
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
},
|
|
329
|
-
run: {
|
|
330
|
-
description: "Execute AI agent tasks",
|
|
331
|
-
run: runRun
|
|
578
|
+
var main = defineCommand6({
|
|
579
|
+
meta: {
|
|
580
|
+
name: "agex",
|
|
581
|
+
version: "0.1.2",
|
|
582
|
+
description: "AI-powered automation toolkit"
|
|
332
583
|
},
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
console.log(`
|
|
340
|
-
agex - AI-powered automation toolkit
|
|
341
|
-
|
|
342
|
-
VERSION: ${VERSION}
|
|
343
|
-
|
|
344
|
-
USAGE:
|
|
345
|
-
agex <command> [options]
|
|
346
|
-
|
|
347
|
-
COMMANDS:
|
|
348
|
-
proov ${COMMANDS.proov.description}
|
|
349
|
-
run ${COMMANDS.run.description}
|
|
350
|
-
review ${COMMANDS.review.description}
|
|
351
|
-
|
|
352
|
-
EXAMPLES:
|
|
353
|
-
agex proov "prove google has a logo" --url https://google.com
|
|
354
|
-
agex run --agent cursor "build a landing page"
|
|
355
|
-
agex review --base main --agent cursor
|
|
356
|
-
|
|
357
|
-
Run 'agex <command> --help' for command-specific options.
|
|
358
|
-
`);
|
|
359
|
-
}
|
|
360
|
-
function printVersion() {
|
|
361
|
-
console.log(`agex v${VERSION}`);
|
|
362
|
-
}
|
|
363
|
-
async function main() {
|
|
364
|
-
const args = process.argv.slice(2);
|
|
365
|
-
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
366
|
-
printHelp4();
|
|
367
|
-
process.exit(0);
|
|
368
|
-
}
|
|
369
|
-
if (args[0] === "--version" || args[0] === "-v") {
|
|
370
|
-
printVersion();
|
|
371
|
-
process.exit(0);
|
|
584
|
+
subCommands: {
|
|
585
|
+
browse: browse_default,
|
|
586
|
+
prove: prove_default,
|
|
587
|
+
"prove-pr": prove_pr_default,
|
|
588
|
+
review: review_default,
|
|
589
|
+
run: run_default
|
|
372
590
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if (!(command in COMMANDS)) {
|
|
376
|
-
console.error(`Unknown command: ${command}`);
|
|
377
|
-
console.error(`Run 'agex --help' for available commands.`);
|
|
378
|
-
process.exit(1);
|
|
379
|
-
}
|
|
380
|
-
try {
|
|
381
|
-
await COMMANDS[command].run(commandArgs);
|
|
382
|
-
} catch (error) {
|
|
383
|
-
console.error("Error:", error instanceof Error ? error.message : error);
|
|
384
|
-
process.exit(1);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
main();
|
|
591
|
+
});
|
|
592
|
+
runMain(main);
|