agent-browser 0.1.2 → 0.2.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,409 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Lightweight CLI client for agent-browser
4
+ *
5
+ * This file contains ONLY the client logic (no Playwright imports).
6
+ * It can be compiled with Bun for fast startup times.
7
+ *
8
+ * The actual browser automation runs in a separate daemon process.
9
+ */
10
+ import * as net from 'net';
11
+ import * as fs from 'fs';
12
+ import * as os from 'os';
13
+ import * as path from 'path';
14
+ import { spawn } from 'child_process';
15
+ // ============================================================================
16
+ // Configuration
17
+ // ============================================================================
18
+ const SESSION = process.env.AGENT_BROWSER_SESSION || 'default';
19
+ const SOCKET_PATH = path.join(os.tmpdir(), `agent-browser-${SESSION}.sock`);
20
+ const PID_FILE = path.join(os.tmpdir(), `agent-browser-${SESSION}.pid`);
21
+ // ============================================================================
22
+ // Daemon Management
23
+ // ============================================================================
24
+ function isDaemonRunning() {
25
+ if (!fs.existsSync(PID_FILE))
26
+ return false;
27
+ try {
28
+ const pid = parseInt(fs.readFileSync(PID_FILE, 'utf8').trim(), 10);
29
+ process.kill(pid, 0);
30
+ return true;
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+ async function ensureDaemon() {
37
+ if (isDaemonRunning() && fs.existsSync(SOCKET_PATH)) {
38
+ return;
39
+ }
40
+ // Find the daemon script - look relative to this script
41
+ const scriptDir = path.dirname(process.argv[1]);
42
+ let daemonPath = path.join(scriptDir, 'daemon.js');
43
+ // Fallback paths
44
+ if (!fs.existsSync(daemonPath)) {
45
+ daemonPath = path.join(scriptDir, '../dist/daemon.js');
46
+ }
47
+ if (!fs.existsSync(daemonPath)) {
48
+ daemonPath = path.join(process.cwd(), 'dist/daemon.js');
49
+ }
50
+ if (!fs.existsSync(daemonPath)) {
51
+ throw new Error(`Daemon not found. Looked in: ${daemonPath}`);
52
+ }
53
+ const child = spawn('node', [daemonPath], {
54
+ detached: true,
55
+ stdio: 'ignore',
56
+ env: { ...process.env, AGENT_BROWSER_DAEMON: '1', AGENT_BROWSER_SESSION: SESSION },
57
+ });
58
+ child.unref();
59
+ // Wait for socket
60
+ for (let i = 0; i < 50; i++) {
61
+ if (fs.existsSync(SOCKET_PATH))
62
+ return;
63
+ await new Promise(r => setTimeout(r, 100));
64
+ }
65
+ throw new Error('Failed to start daemon');
66
+ }
67
+ async function sendCommand(cmd) {
68
+ return new Promise((resolve, reject) => {
69
+ let buffer = '';
70
+ let resolved = false;
71
+ const socket = net.createConnection(SOCKET_PATH);
72
+ const cleanup = () => {
73
+ socket.removeAllListeners();
74
+ socket.destroy();
75
+ };
76
+ socket.on('connect', () => {
77
+ socket.write(JSON.stringify(cmd) + '\n');
78
+ });
79
+ socket.on('data', (data) => {
80
+ buffer += data.toString();
81
+ const idx = buffer.indexOf('\n');
82
+ if (idx !== -1 && !resolved) {
83
+ resolved = true;
84
+ try {
85
+ const response = JSON.parse(buffer.substring(0, idx));
86
+ cleanup();
87
+ resolve(response);
88
+ }
89
+ catch {
90
+ cleanup();
91
+ reject(new Error('Invalid JSON response'));
92
+ }
93
+ }
94
+ });
95
+ socket.on('error', (err) => {
96
+ if (!resolved) {
97
+ resolved = true;
98
+ cleanup();
99
+ reject(err);
100
+ }
101
+ });
102
+ socket.on('close', () => {
103
+ if (!resolved && buffer.trim()) {
104
+ resolved = true;
105
+ try {
106
+ resolve(JSON.parse(buffer.trim()));
107
+ }
108
+ catch {
109
+ reject(new Error('Connection closed'));
110
+ }
111
+ }
112
+ });
113
+ setTimeout(() => {
114
+ if (!resolved) {
115
+ resolved = true;
116
+ cleanup();
117
+ reject(new Error('Timeout'));
118
+ }
119
+ }, 30000);
120
+ });
121
+ }
122
+ // ============================================================================
123
+ // Command Parsing
124
+ // ============================================================================
125
+ function parseCommand(parts) {
126
+ if (parts.length === 0)
127
+ return null;
128
+ const command = parts[0];
129
+ const rest = parts.slice(1);
130
+ const id = Math.random().toString(36).slice(2, 10);
131
+ switch (command) {
132
+ case 'open':
133
+ case 'goto':
134
+ case 'navigate':
135
+ return { id, action: 'navigate', url: rest[0]?.startsWith('http') ? rest[0] : `https://${rest[0]}` };
136
+ case 'click':
137
+ return { id, action: 'click', selector: rest[0] };
138
+ case 'fill':
139
+ return { id, action: 'fill', selector: rest[0], value: rest.slice(1).join(' ') };
140
+ case 'type':
141
+ return { id, action: 'type', selector: rest[0], text: rest.slice(1).join(' ') };
142
+ case 'hover':
143
+ return { id, action: 'hover', selector: rest[0] };
144
+ case 'snapshot': {
145
+ const opts = { id, action: 'snapshot' };
146
+ // Parse snapshot options from rest args
147
+ for (let i = 0; i < rest.length; i++) {
148
+ const arg = rest[i];
149
+ if (arg === '-i' || arg === '--interactive') {
150
+ opts.interactive = true;
151
+ }
152
+ else if (arg === '-c' || arg === '--compact') {
153
+ opts.compact = true;
154
+ }
155
+ else if (arg === '--depth' || arg === '-d') {
156
+ opts.maxDepth = parseInt(rest[++i], 10);
157
+ }
158
+ else if (arg === '--selector' || arg === '-s') {
159
+ opts.selector = rest[++i];
160
+ }
161
+ }
162
+ return opts;
163
+ }
164
+ case 'screenshot':
165
+ return { id, action: 'screenshot', path: rest[0] };
166
+ case 'close':
167
+ case 'quit':
168
+ return { id, action: 'close' };
169
+ case 'get':
170
+ if (rest[0] === 'text')
171
+ return { id, action: 'gettext', selector: rest[1] };
172
+ if (rest[0] === 'url')
173
+ return { id, action: 'url' };
174
+ if (rest[0] === 'title')
175
+ return { id, action: 'title' };
176
+ return null;
177
+ case 'press':
178
+ return { id, action: 'press', key: rest[0] };
179
+ case 'wait':
180
+ if (/^\d+$/.test(rest[0])) {
181
+ return { id, action: 'wait', timeout: parseInt(rest[0], 10) };
182
+ }
183
+ return { id, action: 'wait', selector: rest[0] };
184
+ case 'back':
185
+ return { id, action: 'back' };
186
+ case 'forward':
187
+ return { id, action: 'forward' };
188
+ case 'reload':
189
+ return { id, action: 'reload' };
190
+ case 'eval':
191
+ return { id, action: 'evaluate', script: rest.join(' ') };
192
+ default:
193
+ return null;
194
+ }
195
+ }
196
+ function parseBatchCommands(args) {
197
+ const commands = [];
198
+ // Each argument after 'batch' is a command string
199
+ for (const arg of args) {
200
+ // Split the command string into parts
201
+ const parts = arg.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
202
+ const cleanParts = parts.map(p => p.replace(/^"|"$/g, ''));
203
+ const cmd = parseCommand(cleanParts);
204
+ if (cmd) {
205
+ commands.push(cmd);
206
+ }
207
+ }
208
+ return commands;
209
+ }
210
+ // ============================================================================
211
+ // Output Formatting
212
+ // ============================================================================
213
+ function formatResponse(response) {
214
+ if (!response.success) {
215
+ return `\x1b[31m✗ Error:\x1b[0m ${response.error}`;
216
+ }
217
+ const data = response.data;
218
+ if (data?.url && data?.title) {
219
+ return `\x1b[32m✓\x1b[0m \x1b[1m${data.title}\x1b[0m\n\x1b[2m ${data.url}\x1b[0m`;
220
+ }
221
+ else if (data?.snapshot) {
222
+ return String(data.snapshot);
223
+ }
224
+ else if (data?.text !== undefined) {
225
+ return String(data.text);
226
+ }
227
+ else if (data?.url) {
228
+ return String(data.url);
229
+ }
230
+ else if (data?.title) {
231
+ return String(data.title);
232
+ }
233
+ else if (data?.result !== undefined) {
234
+ return typeof data.result === 'object' ? JSON.stringify(data.result, null, 2) : String(data.result);
235
+ }
236
+ else if (data?.closed) {
237
+ return '\x1b[32m✓\x1b[0m Browser closed';
238
+ }
239
+ else {
240
+ return '\x1b[32m✓\x1b[0m Done';
241
+ }
242
+ }
243
+ function printResponse(response, json) {
244
+ if (json) {
245
+ console.log(JSON.stringify(response));
246
+ }
247
+ else {
248
+ console.log(formatResponse(response));
249
+ }
250
+ }
251
+ // ============================================================================
252
+ // Main
253
+ // ============================================================================
254
+ const HELP = `
255
+ agent-browser - fast browser automation CLI
256
+
257
+ Usage:
258
+ agent-browser <command> [args] [--json]
259
+ agent-browser batch <cmd1> <cmd2> ... [--json]
260
+
261
+ Commands:
262
+ open <url> Navigate to URL
263
+ click <sel> Click element (use @ref from snapshot)
264
+ fill <sel> <text> Fill input
265
+ type <sel> <text> Type text
266
+ hover <sel> Hover element
267
+ snapshot [options] Get accessibility tree with refs
268
+ screenshot [path] Take screenshot
269
+ get text <sel> Get text content
270
+ get url Get current URL
271
+ get title Get page title
272
+ press <key> Press keyboard key
273
+ wait <ms|sel> Wait for time or element
274
+ eval <js> Evaluate JavaScript
275
+ close Close browser
276
+
277
+ Snapshot Options:
278
+ -i, --interactive Only show interactive elements (buttons, links, inputs)
279
+ -c, --compact Remove empty structural elements
280
+ -d, --depth <n> Limit tree depth (e.g., --depth 3)
281
+ -s, --selector <sel> Scope snapshot to CSS selector
282
+
283
+ Batch Mode:
284
+ batch <cmd1> <cmd2> ... Execute multiple commands in sequence
285
+ Each command is a quoted string
286
+
287
+ Options:
288
+ --json Output JSON (for AI agents)
289
+
290
+ Examples:
291
+ agent-browser open example.com
292
+ agent-browser snapshot
293
+ agent-browser click @e2
294
+ agent-browser fill @e3 "hello"
295
+
296
+ # Batch mode - execute multiple commands efficiently
297
+ agent-browser batch "open example.com" "snapshot" "click a"
298
+ agent-browser batch "open google.com" "snapshot" "get title" --json
299
+ `;
300
+ async function runBatch(commands, json) {
301
+ const results = [];
302
+ let hasError = false;
303
+ for (const cmd of commands) {
304
+ try {
305
+ const response = await sendCommand(cmd);
306
+ results.push(response);
307
+ if (!json) {
308
+ // Print each result as we go for non-JSON mode
309
+ console.log(`\x1b[36m[${cmd.action}]\x1b[0m`);
310
+ console.log(formatResponse(response));
311
+ console.log();
312
+ }
313
+ if (!response.success) {
314
+ hasError = true;
315
+ break; // Stop on first error
316
+ }
317
+ }
318
+ catch (err) {
319
+ const message = err instanceof Error ? err.message : String(err);
320
+ const errorResponse = {
321
+ id: String(cmd.id),
322
+ success: false,
323
+ error: message,
324
+ };
325
+ results.push(errorResponse);
326
+ hasError = true;
327
+ if (!json) {
328
+ console.log(`\x1b[36m[${cmd.action}]\x1b[0m`);
329
+ console.log(`\x1b[31m✗ Error:\x1b[0m ${message}`);
330
+ }
331
+ break;
332
+ }
333
+ }
334
+ if (json) {
335
+ console.log(JSON.stringify({
336
+ success: !hasError,
337
+ results,
338
+ completed: results.length,
339
+ total: commands.length,
340
+ }));
341
+ }
342
+ else {
343
+ console.log(`\x1b[2m─────────────────────────────────────\x1b[0m`);
344
+ console.log(`Completed ${results.length}/${commands.length} commands`);
345
+ }
346
+ process.exit(hasError ? 1 : 0);
347
+ }
348
+ async function main() {
349
+ const args = process.argv.slice(2);
350
+ const json = args.includes('--json');
351
+ const cleanArgs = args.filter(a => !a.startsWith('--'));
352
+ if (cleanArgs.length === 0 || args.includes('--help') || args.includes('-h')) {
353
+ console.log(HELP);
354
+ process.exit(0);
355
+ }
356
+ // Check for batch mode
357
+ if (cleanArgs[0] === 'batch') {
358
+ const batchArgs = cleanArgs.slice(1);
359
+ if (batchArgs.length === 0) {
360
+ console.error('\x1b[31mBatch mode requires at least one command\x1b[0m');
361
+ console.log('\nExample: agent-browser batch "open example.com" "snapshot"');
362
+ process.exit(1);
363
+ }
364
+ const commands = parseBatchCommands(batchArgs);
365
+ if (commands.length === 0) {
366
+ console.error('\x1b[31mNo valid commands found\x1b[0m');
367
+ process.exit(1);
368
+ }
369
+ try {
370
+ await ensureDaemon();
371
+ await runBatch(commands, json);
372
+ }
373
+ catch (err) {
374
+ const message = err instanceof Error ? err.message : String(err);
375
+ if (json) {
376
+ console.log(JSON.stringify({ success: false, error: message }));
377
+ }
378
+ else {
379
+ console.error('\x1b[31m✗ Error:\x1b[0m', message);
380
+ }
381
+ process.exit(1);
382
+ }
383
+ return;
384
+ }
385
+ // Single command mode
386
+ const cmd = parseCommand(cleanArgs);
387
+ if (!cmd) {
388
+ console.error('\x1b[31mUnknown command:\x1b[0m', cleanArgs[0]);
389
+ process.exit(1);
390
+ }
391
+ try {
392
+ await ensureDaemon();
393
+ const response = await sendCommand(cmd);
394
+ printResponse(response, json);
395
+ process.exit(response.success ? 0 : 1);
396
+ }
397
+ catch (err) {
398
+ const message = err instanceof Error ? err.message : String(err);
399
+ if (json) {
400
+ console.log(JSON.stringify({ success: false, error: message }));
401
+ }
402
+ else {
403
+ console.error('\x1b[31m✗ Error:\x1b[0m', message);
404
+ }
405
+ process.exit(1);
406
+ }
407
+ }
408
+ main();
409
+ //# sourceMappingURL=cli-light.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-light.js","sourceRoot":"","sources":["../src/cli-light.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -214,7 +214,7 @@ ${c('yellow', 'Usage:')} agent-browser <command> [options]
214
214
 
215
215
  ${c('yellow', 'Core Commands:')}
216
216
  ${c('cyan', 'open')} <url> Navigate to URL
217
- ${c('cyan', 'click')} <sel> Click element
217
+ ${c('cyan', 'click')} <sel> Click element (or @ref)
218
218
  ${c('cyan', 'type')} <sel> <text> Type into element
219
219
  ${c('cyan', 'fill')} <sel> <text> Clear and fill
220
220
  ${c('cyan', 'press')} <key> Press key (Enter, Tab, Control+a)
@@ -223,10 +223,16 @@ ${c('yellow', 'Core Commands:')}
223
223
  ${c('cyan', 'scroll')} <dir> [px] Scroll (up/down/left/right)
224
224
  ${c('cyan', 'wait')} <sel|ms> Wait for element or time
225
225
  ${c('cyan', 'screenshot')} [path] Take screenshot
226
- ${c('cyan', 'snapshot')} Accessibility tree (for AI)
226
+ ${c('cyan', 'snapshot')} Accessibility tree with refs (for AI)
227
227
  ${c('cyan', 'eval')} <js> Run JavaScript
228
228
  ${c('cyan', 'close')} Close browser
229
229
 
230
+ ${c('yellow', 'Selectors:')} CSS, XPath, text=, or ${c('green', '@ref')} from snapshot
231
+ ${c('dim', 'CSS:')} "#id", ".class", "button"
232
+ ${c('dim', 'XPath:')} "xpath=//button"
233
+ ${c('dim', 'Text:')} "text=Submit"
234
+ ${c('dim', 'Ref:')} ${c('green', '@e1')}, ${c('green', '@e2')} (from snapshot output)
235
+
230
236
  ${c('yellow', 'Get Info:')} agent-browser get <what> [selector]
231
237
  text, html, value, attr, title, url, count, box
232
238
 
@@ -270,13 +276,12 @@ ${c('yellow', 'Options:')}
270
276
 
271
277
  ${c('yellow', 'Examples:')}
272
278
  agent-browser open example.com
273
- agent-browser click "#submit"
274
- agent-browser fill "#email" "test@example.com"
275
- agent-browser get text "h1"
276
- agent-browser is visible ".modal"
279
+ agent-browser snapshot # Get tree with refs
280
+ agent-browser click @e2 # Click by ref from snapshot
281
+ agent-browser fill @e3 "test@example.com" # Fill by ref
282
+ agent-browser click "#submit" # CSS selector still works
283
+ agent-browser get text @e1 # Get text by ref
277
284
  agent-browser find role button click --name Submit
278
- agent-browser wait 2000
279
- agent-browser wait --load networkidle
280
285
  `);
281
286
  }
282
287
  // ============================================================================