@kritchoff/agent-browser 0.9.52 โ†’ 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -57,7 +57,8 @@ async function main() {
57
57
  default:
58
58
  // Pass through arbitrary commands to the agent daemon
59
59
  // e.g. "agent-browser open https://google.com"
60
- await agent.command(...filteredArgs);
60
+ const result = await agent.command(...filteredArgs);
61
+ console.log(result);
61
62
  break;
62
63
  }
63
64
  } catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kritchoff/agent-browser",
3
- "version": "0.9.52",
3
+ "version": "1.0.0",
4
4
  "description": "Headless browser automation CLI for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -10,8 +10,6 @@
10
10
  "bin",
11
11
  "scripts",
12
12
  "skills",
13
- "sdk.sh",
14
- "start.sh",
15
13
  "docker-compose.sdk.yml"
16
14
  ],
17
15
  "bin": {
package/README.sdk.md DELETED
@@ -1,129 +0,0 @@
1
- # @wootzapp/agent-browser SDK
2
-
3
- The official Node.js SDK for controlling the WootzApp Agent Browser environment.
4
-
5
- This SDK provides a **Real Android Browser** (WootzApp) wrapped in a Docker container, controlled by a high-speed Playwright daemon. It is specifically designed for AI Agents to navigate the mobile web, bypassing bot detection, and generating LLM-friendly semantic trees (AXTree).
6
-
7
- ## Features
8
-
9
- - **Real Mobile Environment**: Full Android 14 OS with Touch Events and Mobile Viewports.
10
- - **Zero-Config Setup**: The SDK automatically downloads and orchestrates the required Docker containers.
11
- - **Hyper-Speed Warm Boots**: Uses advanced VDI Volume Mounting to boot the environment in **< 5 seconds** after the first run.
12
- - **Fast Resets**: Cleans the browser state via Android userspace reboot in **~15 seconds**.
13
- - **Playwright Parity**: Control the mobile browser using standard Playwright commands (`click`, `type`, `waitForSelector`).
14
- - **Semantic AXTree**: Built-in `snapshot()` method generates a clean, text-based UI tree optimized for LLM reasoning.
15
-
16
- ---
17
-
18
- ## Prerequisites
19
-
20
- 1. **Docker Engine**: Must be installed and running.
21
- - *Linux Users*: Ensure your user is in the `docker` group (`sudo usermod -aG docker $USER`).
22
- 2. **Node.js**: v18+ is required.
23
-
24
- ---
25
-
26
- ## Installation
27
-
28
- Install the SDK in your project:
29
-
30
- ```bash
31
- npm install @kritchoff/agent-browser
32
- ```
33
-
34
- *(Optional but recommended)* Install `tsx` to run TypeScript files natively:
35
- ```bash
36
- npm install -D tsx
37
- ```
38
-
39
- ---
40
-
41
- ## Quick Start Guide
42
-
43
- Create a file named `agent.ts`:
44
-
45
- ```typescript
46
- import { WootzAgent } from '@kritchoff/agent-browser';
47
-
48
- async function main() {
49
- // 1. Initialize the controller
50
- const agent = new WootzAgent();
51
-
52
- console.log('๐Ÿš€ Booting Environment...');
53
- // First run: Downloads 3GB image and cold boots (~90s).
54
- // Next run: Instant Hyper-Speed Warm Boot (~5s).
55
- await agent.start();
56
-
57
- console.log('๐ŸŒ Navigating to Google...');
58
- await agent.navigate('https://google.com');
59
-
60
- console.log('๐Ÿ“ธ Capturing Semantic Tree for LLM...');
61
- const uiTree = await agent.snapshot();
62
- console.log(uiTree);
63
-
64
- console.log('โŒจ๏ธ Typing and Searching...');
65
- await agent.type('textarea[name="q"]', 'WootzApp AI');
66
- await agent.press('Enter');
67
-
68
- console.log('๐Ÿงน Fast Reset for next task...');
69
- // Wipes all tabs, cookies, and cache in ~15s
70
- await agent.reset();
71
-
72
- console.log('๐Ÿ›‘ Shutting down...');
73
- // Completely destroys containers and releases ports
74
- await agent.stop();
75
- }
76
-
77
- main().catch(console.error);
78
- ```
79
-
80
- Run your agent:
81
- ```bash
82
- npx tsx agent.ts
83
- ```
84
-
85
- ---
86
-
87
- ## CLI Usage (Global Install)
88
-
89
- You can also use the SDK directly from your terminal to debug or control the browser manually.
90
-
91
- ```bash
92
- npm install -g @kritchoff/agent-browser
93
-
94
- # Start the environment
95
- agent-browser start
96
-
97
- # Run commands
98
- agent-browser navigate https://news.ycombinator.com
99
- agent-browser click ".titleline a"
100
- agent-browser snapshot
101
-
102
- # Clean the browser
103
- agent-browser reset
104
-
105
- # Stop
106
- agent-browser stop
107
- ```
108
-
109
- ---
110
-
111
- ## Troubleshooting
112
-
113
- ### `Error: Failed to connect to agent daemon (ECONNREFUSED)`
114
- - **Cause**: The container failed to bind port `32001` to your host machine.
115
- - **Fix**: Run `agent.stop()` or `docker rm -f $(docker ps -aq)` to clear old/stuck containers, then run `agent.start()` again. The SDK has built-in self-healing, but a manual hard reset always works.
116
-
117
- ### `net::ERR_NAME_NOT_RESOLVED`
118
- - **Cause**: The Android Emulator temporarily lost its internet connection after a Warm Boot.
119
- - **Fix**: The SDK automatically toggles Airplane Mode to fix this, but if it persists, ensure your host machine has a stable internet connection before starting the agent.
120
-
121
- ### `Selector "..." matched X elements (Strict Mode Violation)`
122
- - **Cause**: Playwright requires selectors to point to exactly one element.
123
- - **Fix**: Use more specific selectors, or use Playwright's `>> nth=0` pseudo-selector to pick the first match (e.g., `agent.click('a >> nth=0')`).
124
-
125
- ---
126
-
127
- ## Next Steps
128
-
129
- For a complete list of all available commands (clicking, typing, tabbing, network interception), please read the [COMMANDS.md](./COMMANDS.md) file.
@@ -1,117 +0,0 @@
1
- #!/bin/bash
2
- # Fast Android environment reset using userspace reboot.
3
- #
4
- # This script resets the Android emulator state much faster (~15s) than
5
- # a full container restart (~60s). It uses 'adb reboot userspace' to
6
- # restart the Android framework while keeping the kernel running.
7
- #
8
- # Usage:
9
- # ./scripts/fast_reset.sh
10
-
11
- set -e
12
-
13
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14
- PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
15
-
16
- cd "$PROJECT_DIR"
17
-
18
- # Colors for output
19
- RED='\033[0;31m'
20
- GREEN='\033[0;32m'
21
- YELLOW='\033[1;33m'
22
- BLUE='\033[0;34m'
23
- NC='\033[0m' # No Color
24
-
25
- log_info() {
26
- echo -e "${BLUE}[INFO]${NC} $1"
27
- }
28
-
29
- log_success() {
30
- echo -e "${GREEN}[OK]${NC} $1"
31
- }
32
-
33
- log_warn() {
34
- echo -e "${YELLOW}[WARN]${NC} $1"
35
- }
36
-
37
- log_error() {
38
- echo -e "${RED}[ERROR]${NC} $1"
39
- }
40
-
41
- # Respect COMPOSE_FILE from environment, or auto-detect
42
- if [ -z "$COMPOSE_FILE" ]; then
43
- if [ -f "$PROJECT_DIR/docker-compose.sdk.yml" ]; then
44
- COMPOSE_FILE="$PROJECT_DIR/docker-compose.sdk.yml"
45
- else
46
- COMPOSE_FILE="$PROJECT_DIR/docker-compose.prod.yml"
47
- fi
48
- fi
49
-
50
- # Detect container
51
- CONTAINER=$(docker compose -f "$COMPOSE_FILE" ps -q android-service)
52
- if [ -z "$CONTAINER" ]; then
53
- log_error "android-service container not running."
54
- exit 1
55
- fi
56
-
57
- ADB_CMD="docker exec $CONTAINER adb"
58
-
59
- log_info "Initiating fast reset (userspace reboot)..."
60
-
61
- # 1. Trigger userspace reboot
62
- # This command returns immediately and the device goes offline
63
- $ADB_CMD shell reboot userspace || true
64
-
65
- # 2. Wait for device to come back online
66
- log_info "Waiting for device to come online..."
67
- start_time=$(date +%s)
68
- timeout=30
69
-
70
- while true; do
71
- current_time=$(date +%s)
72
- elapsed=$((current_time - start_time))
73
-
74
- if [ $elapsed -gt $timeout ]; then
75
- log_error "Timeout waiting for device after ${timeout}s"
76
- exit 1
77
- fi
78
-
79
- # Check if device is visible to ADB and state is 'device'
80
- if $ADB_CMD get-state 2>/dev/null | grep -q "device"; then
81
- # Verify shell is responsive
82
- if $ADB_CMD shell echo ok 2>/dev/null | grep -q "ok"; then
83
- break
84
- fi
85
- fi
86
-
87
- sleep 1
88
- done
89
-
90
- log_success "Device online (${elapsed}s)"
91
-
92
- # 3. Wait for CDP (Chrome DevTools Protocol)
93
- log_info "Waiting for browser CDP..."
94
- cdp_timeout=30
95
- cdp_start_time=$(date +%s)
96
-
97
- while true; do
98
- current_time=$(date +%s)
99
- elapsed=$((current_time - cdp_start_time))
100
-
101
- if [ $elapsed -gt $cdp_timeout ]; then
102
- log_warn "Timeout waiting for CDP. Browser might not have autostarted."
103
- log_info "Attempting to start browser manually..."
104
- $ADB_CMD shell am start -n com.wootzapp.web/com.aspect.chromium.ChromiumMain -a android.intent.action.VIEW -d 'about:blank'
105
- sleep 2
106
- fi
107
-
108
- # Check CDP version endpoint
109
- if docker exec $CONTAINER curl -s --connect-timeout 2 http://localhost:9224/json/version >/dev/null; then
110
- break
111
- fi
112
-
113
- sleep 1
114
- done
115
-
116
- log_success "Browser CDP ready"
117
- log_success "Fast reset complete!"
@@ -1,293 +0,0 @@
1
- #!/bin/bash
2
- # Emulator snapshot import/export utility
3
- #
4
- # Manages Android emulator snapshots for agent-browser.
5
- # Snapshots are stored in the emulator's AVD directory and can be
6
- # exported as compressed tar.gz files for sharing or backup.
7
- #
8
- # Usage:
9
- # ./scripts/snapshot_manager.sh export <name> <output.tar.gz>
10
- # ./scripts/snapshot_manager.sh import <input.tar.gz> [name]
11
- # ./scripts/snapshot_manager.sh list
12
- # ./scripts/snapshot_manager.sh validate <name>
13
- #
14
- # Examples:
15
- # # Export current snapshot for sharing
16
- # ./scripts/snapshot_manager.sh export w8rl_clean ./my_snapshot.tar.gz
17
- #
18
- # # Import a snapshot from a file
19
- # ./scripts/snapshot_manager.sh import ./my_snapshot.tar.gz
20
- #
21
- # # Import with a different name
22
- # ./scripts/snapshot_manager.sh import ./my_snapshot.tar.gz imported_snapshot
23
- #
24
- # # List all available snapshots
25
- # ./scripts/snapshot_manager.sh list
26
- #
27
- # # Validate a snapshot is not corrupt
28
- # ./scripts/snapshot_manager.sh validate w8rl_clean
29
-
30
- set -euo pipefail
31
-
32
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
33
- PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
34
-
35
- cd "$PROJECT_DIR"
36
-
37
- # Respect COMPOSE_FILE from environment
38
- COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.prod.yml}"
39
-
40
- # Detect container name using docker compose
41
- CONTAINER=$(docker compose -f "$COMPOSE_FILE" ps -q android-service)
42
- if [ -z "$CONTAINER" ]; then
43
- echo "Error: android-service container not running."
44
- exit 1
45
- fi
46
-
47
- AVD_NAME="${EMULATOR_NAME:-Pixel_6_API_34}"
48
- SNAPSHOT_BASE="/root/.android/avd/${AVD_NAME}.avd/snapshots"
49
-
50
- # Colors for output
51
- RED='\033[0;31m'
52
- GREEN='\033[0;32m'
53
- YELLOW='\033[1;33m'
54
- BLUE='\033[0;34m'
55
- NC='\033[0m' # No Color
56
-
57
- log_info() {
58
- echo -e "${BLUE}[INFO]${NC} $1"
59
- }
60
-
61
- log_success() {
62
- echo -e "${GREEN}[OK]${NC} $1"
63
- }
64
-
65
- log_warn() {
66
- echo -e "${YELLOW}[WARN]${NC} $1"
67
- }
68
-
69
- log_error() {
70
- echo -e "${RED}[ERROR]${NC} $1"
71
- }
72
-
73
- # Check if container is running
74
- check_container() {
75
- # Use docker inspect for reliable status check (avoids SIGPIPE with grep -q)
76
- if [ "$(docker inspect -f '{{.State.Running}}' "$CONTAINER" 2>/dev/null)" != "true" ]; then
77
- log_error "Container '${CONTAINER}' is not running"
78
- log_info "Start it with: docker compose -f ${COMPOSE_FILE} up -d android-service"
79
- exit 1
80
- fi
81
- }
82
-
83
- # Validate a snapshot has all required files and is not corrupt
84
- validate_snapshot_internal() {
85
- local name="$1"
86
- local snapshot_dir="${SNAPSHOT_BASE}/${name}"
87
- local valid=true
88
-
89
- log_info "Validating snapshot '${name}'..."
90
-
91
- for file in ram.bin snapshot.pb hardware.ini; do
92
- if docker exec "$CONTAINER" test -f "${snapshot_dir}/${file}"; then
93
- local size
94
- size=$(docker exec "$CONTAINER" stat -c%s "${snapshot_dir}/${file}")
95
- echo -e " ${GREEN}โœ“${NC} ${file}: ${size} bytes"
96
- else
97
- echo -e " ${RED}โœ—${NC} ${file}: MISSING"
98
- valid=false
99
- fi
100
- done
101
-
102
- # Check ram.bin size (must be >= 1MB)
103
- if docker exec "$CONTAINER" test -f "${snapshot_dir}/ram.bin"; then
104
- local ram_size
105
- ram_size=$(docker exec "$CONTAINER" stat -c%s "${snapshot_dir}/ram.bin")
106
- if [ "$ram_size" -lt 1000000 ]; then
107
- echo -e " ${RED}โœ—${NC} ram.bin too small (${ram_size} bytes, expected >= 1MB)"
108
- valid=false
109
- fi
110
- fi
111
-
112
- if [ "$valid" = true ]; then
113
- log_success "Snapshot validation passed"
114
- return 0
115
- else
116
- log_error "Snapshot validation failed"
117
- return 1
118
- fi
119
- }
120
-
121
- # Export a snapshot to a tar.gz file
122
- cmd_export() {
123
- local name="${1:?Usage: $0 export <name> <output.tar.gz>}"
124
- local output="${2:?Usage: $0 export <name> <output.tar.gz>}"
125
-
126
- check_container
127
-
128
- # Validate snapshot exists
129
- if ! docker exec "$CONTAINER" test -d "${SNAPSHOT_BASE}/${name}"; then
130
- log_error "Snapshot '${name}' does not exist"
131
- exit 1
132
- fi
133
-
134
- log_info "Exporting snapshot '${name}' to ${output}..."
135
-
136
- # Validate before export
137
- if ! validate_snapshot_internal "$name"; then
138
- log_error "Cannot export invalid snapshot"
139
- exit 1
140
- fi
141
-
142
- # Create tar.gz from snapshot directory
143
- docker exec "$CONTAINER" tar -czf - -C "$SNAPSHOT_BASE" "$name" > "$output"
144
-
145
- local size
146
- size=$(ls -lh "$output" | awk '{print $5}')
147
- log_success "Exported: ${output} (${size})"
148
- }
149
-
150
- # Import a snapshot from a tar.gz file
151
- cmd_import() {
152
- local input="${1:?Usage: $0 import <input.tar.gz> [name]}"
153
-
154
- # Extract original name from tar
155
- # Disable pipefail to avoid SIGPIPE from tar | head
156
- set +o pipefail
157
- local original_name
158
- original_name=$(tar -tzf "$input" 2>/dev/null | head -1 | cut -d'/' -f1)
159
- set -o pipefail
160
-
161
- local name="${2:-$original_name}"
162
-
163
- if [ -z "$name" ]; then
164
- log_error "Could not determine snapshot name from archive"
165
- exit 1
166
- fi
167
-
168
- check_container
169
-
170
- log_info "Importing snapshot from ${input} as '${name}'..."
171
-
172
- # Ensure snapshot directory exists
173
- docker exec "$CONTAINER" mkdir -p "$SNAPSHOT_BASE"
174
-
175
- # Remove existing snapshot if present
176
- if docker exec "$CONTAINER" test -d "${SNAPSHOT_BASE}/${name}"; then
177
- log_warn "Removing existing snapshot '${name}'..."
178
- docker exec "$CONTAINER" rm -rf "${SNAPSHOT_BASE}/${name}"
179
- fi
180
-
181
- # Extract snapshot into container
182
- # Use 'docker cp' to avoid stdin pipe issues
183
- log_info "Copying archive to container..."
184
- docker cp "$input" "$CONTAINER:/tmp/import_snapshot.tar.gz"
185
-
186
- log_info "Extracting archive..."
187
- if ! docker exec "$CONTAINER" tar -xzf /tmp/import_snapshot.tar.gz -C "$SNAPSHOT_BASE"; then
188
- log_error "Failed to extract snapshot archive"
189
- docker exec "$CONTAINER" rm -f /tmp/import_snapshot.tar.gz
190
- exit 1
191
- fi
192
-
193
- # Clean up
194
- docker exec "$CONTAINER" rm -f /tmp/import_snapshot.tar.gz
195
-
196
- # If renaming, move the extracted directory
197
- if [ "$name" != "$original_name" ]; then
198
- docker exec "$CONTAINER" mv "${SNAPSHOT_BASE}/${original_name}" "${SNAPSHOT_BASE}/${name}"
199
- fi
200
-
201
- # Validate after import
202
- if validate_snapshot_internal "$name"; then
203
- log_success "Import completed successfully"
204
- docker exec "$CONTAINER" ls -lh "${SNAPSHOT_BASE}/${name}/"
205
- else
206
- log_error "Import failed - snapshot validation failed"
207
- exit 1
208
- fi
209
- }
210
-
211
- # List all snapshots
212
- cmd_list() {
213
- check_container
214
-
215
- log_info "Available snapshots in ${CONTAINER}:"
216
- echo ""
217
-
218
- if docker exec "$CONTAINER" test -d "$SNAPSHOT_BASE"; then
219
- docker exec "$CONTAINER" ls -la "$SNAPSHOT_BASE" 2>/dev/null | tail -n +2 || echo " (none)"
220
-
221
- echo ""
222
- log_info "Snapshot details:"
223
- for snapshot in $(docker exec "$CONTAINER" ls "$SNAPSHOT_BASE" 2>/dev/null); do
224
- local snapshot_dir="${SNAPSHOT_BASE}/${snapshot}"
225
- if docker exec "$CONTAINER" test -d "$snapshot_dir"; then
226
- local ram_size
227
- ram_size=$(docker exec "$CONTAINER" stat -c%s "${snapshot_dir}/ram.bin" 2>/dev/null || echo "0")
228
- local ram_mb=$((ram_size / 1024 / 1024))
229
- echo " ${snapshot}: ${ram_mb}MB RAM"
230
- fi
231
- done
232
- else
233
- echo " No snapshots found (snapshot directory does not exist)"
234
- fi
235
- }
236
-
237
- # Validate a snapshot
238
- cmd_validate() {
239
- local name="${1:?Usage: $0 validate <name>}"
240
-
241
- check_container
242
-
243
- if ! docker exec "$CONTAINER" test -d "${SNAPSHOT_BASE}/${name}"; then
244
- log_error "Snapshot '${name}' does not exist"
245
- exit 1
246
- fi
247
-
248
- validate_snapshot_internal "$name"
249
- }
250
-
251
- # Show usage
252
- usage() {
253
- echo "Usage: $0 {export|import|list|validate} [args...]"
254
- echo ""
255
- echo "Commands:"
256
- echo " export <name> <output.tar.gz> Export a snapshot to a file"
257
- echo " import <input.tar.gz> [name] Import a snapshot from a file"
258
- echo " list List all available snapshots"
259
- echo " validate <name> Validate a snapshot is not corrupt"
260
- echo ""
261
- echo "Examples:"
262
- echo " $0 export w8rl_clean ./my_snapshot.tar.gz"
263
- echo " $0 import ./my_snapshot.tar.gz"
264
- echo " $0 import ./my_snapshot.tar.gz custom_name"
265
- echo " $0 list"
266
- echo " $0 validate w8rl_clean"
267
- }
268
-
269
- # Main command dispatch
270
- case "${1:-}" in
271
- export)
272
- shift
273
- cmd_export "$@"
274
- ;;
275
- import)
276
- shift
277
- cmd_import "$@"
278
- ;;
279
- list)
280
- cmd_list
281
- ;;
282
- validate)
283
- shift
284
- cmd_validate "$@"
285
- ;;
286
- -h|--help|help)
287
- usage
288
- ;;
289
- *)
290
- usage
291
- exit 1
292
- ;;
293
- esac
@@ -1,26 +0,0 @@
1
- #!/bin/bash
2
- exec 2>&1
3
-
4
- echo "[vaccine] Waiting for emulator..."
5
- adb wait-for-device
6
-
7
- echo "[vaccine] Waiting for boot completion..."
8
- while [[ -z $(adb shell getprop sys.boot_completed) ]]; do sleep 1; done
9
-
10
- echo "[vaccine] Waiting for Package Manager..."
11
- while ! adb shell pm list packages > /dev/null 2>&1; do sleep 1; done
12
-
13
- echo "[vaccine] Applying permissions to org.chromium.chrome (WootzApp)..."
14
- adb shell pm grant org.chromium.chrome android.permission.ACCESS_FINE_LOCATION || true
15
- adb shell pm grant org.chromium.chrome android.permission.CAMERA || true
16
- adb shell pm grant org.chromium.chrome android.permission.RECORD_AUDIO || true
17
-
18
- # Fallback for standard Chrome if present
19
- adb shell pm grant com.android.chrome android.permission.ACCESS_FINE_LOCATION || true
20
- adb shell pm grant com.android.chrome android.permission.CAMERA || true
21
- adb shell pm grant com.android.chrome android.permission.RECORD_AUDIO || true
22
-
23
- echo "[vaccine] Permissions granted."
24
-
25
- # Prevent restart
26
- touch /etc/services.d/vaccine/down