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/dist/cli.js CHANGED
@@ -1,223 +1,451 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- proov,
3
+ AGENT_NAMES,
4
+ APPROVAL_POLICIES,
5
+ OUTPUT_MODES,
6
+ detectDefaultBranch,
7
+ isAgexError,
8
+ prove,
9
+ proveOptionsSchema,
4
10
  runAgent,
5
- runReview
6
- } from "./chunk-H3CMLOXO.js";
7
- import "./chunk-2ZRS4JND.js";
11
+ runReview,
12
+ validate,
13
+ viewportStringSchema
14
+ } from "./chunk-EN7TTESF.js";
8
15
 
9
- // src/commands/proov.ts
10
- function printHelp() {
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
- EXAMPLES:
33
- agex proov "prove the Google logo is on the homepage" --url https://google.com
34
- agex proov "verify login button exists" --agent claude --url https://example.com
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 parseArgs(args) {
38
- const options = {};
39
- let assertion = "";
40
- for (let i = 0; i < args.length; i++) {
41
- const arg = args[i];
42
- if (arg === "--agent" || arg === "-a") {
43
- options.agent = args[++i];
44
- } else if (arg === "--url" || arg === "-u") {
45
- options.url = args[++i];
46
- } else if (arg === "--output" || arg === "-o") {
47
- options.outputDir = args[++i];
48
- } else if (arg === "--video") {
49
- options.video = true;
50
- } else if (arg === "--no-video") {
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
- // src/commands/run.ts
109
- function printHelp2() {
110
- console.log(`
111
- agex run - Execute AI agent tasks
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 run --agent <name> "<prompt>" [options]
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
- --agent, -a <name> Agent to use: cursor, claude, codex (required)
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 run --agent cursor "build a landing page"
133
- agex run --agent claude "refactor this function" --mode json
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
- function parseArgs2(args) {
137
- let agent;
138
- let model;
139
- let prompt = "";
140
- let install = false;
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
- i += 1;
182
- } else if (arg === "--approval") {
183
- approvalPolicy = args[i + 1];
184
- i += 1;
185
- } else if (arg === "--timeout") {
186
- const value = Number(args[i + 1]);
187
- if (!Number.isNaN(value)) {
188
- timeoutMs = value;
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
- i += 1;
191
- } else {
192
- prompt = prompt ? `${prompt} ${arg}` : arg;
120
+ return;
193
121
  }
122
+ process.exit(1);
194
123
  }
195
- if (!agent) {
196
- throw new Error("Missing --agent");
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
- if (!prompt) {
199
- throw new Error("Missing prompt");
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
- const quietOutput = outputMode === "json";
202
- if (quietOutput) {
203
- streamOutput = false;
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
- return {
206
- agent,
207
- model,
208
- prompt,
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
- async function runRun(args) {
237
- const request = parseArgs2(args);
238
- const result = await runAgent(request);
239
- const output = formatOutput(result, request.outputMode, request.streamOutput ?? true);
240
- if (output !== null) {
241
- process.stdout.write(`${output}
242
- `);
243
- }
244
- }
245
-
246
- // src/commands/review.ts
247
- function printHelp3() {
248
- console.log(`
249
- agex review - Review code changes
250
-
251
- USAGE:
252
- agex review --base <ref> --agent <name> [options]
253
-
254
- OPTIONS:
255
- --base <ref> Base branch/commit to compare against (required)
256
- --agent, -a <name> Agent to use: cursor, claude, codex (required)
257
- --model, -m <model> Model to use
258
- --no-worktree Exclude worktree changes
259
- --hypotheses <n> Number of hypotheses to generate
260
- --hint <text> Additional prompt hint
261
- --help, -h Show this help
262
-
263
- EXAMPLES:
264
- agex review --base main --agent cursor
265
- agex review --base HEAD~3 --agent claude --hint "focus on security"
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
- i += 1;
297
- } else if (arg === "--hint") {
298
- promptHint = args[i + 1];
299
- i += 1;
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
- if (!baseRef) {
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 VERSION = "0.1.0";
324
- var COMMANDS = {
325
- proov: {
326
- description: "Prove visual assertions with screenshots",
327
- run: runProov
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
- review: {
334
- description: "Review code changes",
335
- run: runReview2
336
- }
337
- };
338
- function printHelp4() {
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
- const command = args[0];
374
- const commandArgs = args.slice(1);
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);