@kritchoff/agent-browser 0.9.51 → 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.
@@ -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
package/sdk.sh DELETED
@@ -1,176 +0,0 @@
1
- #!/bin/bash
2
- # Agent Browser SDK Wrapper
3
- #
4
- # A user-friendly entry point for AI Agents to interact with the Android Browser Environment.
5
- # Handles "Hyper-Speed Snapshot" logic for instant startups.
6
- #
7
- # Usage:
8
- # ./sdk.sh start - Start the environment (Cold boot 1st time, Warm boot after)
9
- # ./sdk.sh stop - Stop the environment
10
- # ./sdk.sh reset - Fast Reset the browser (15s)
11
- # ./sdk.sh agent ... - Run agent commands (e.g. ./sdk.sh agent open google.com)
12
- #
13
-
14
- set -e
15
-
16
- # Set high timeouts for large image downloads
17
- export COMPOSE_HTTP_TIMEOUT=900
18
- export DOCKER_CLIENT_TIMEOUT=900
19
-
20
- SDK_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
- CACHE_DIR="$SDK_ROOT/cache"
22
- SNAPSHOT_DIR="$CACHE_DIR/snapshots/quickboot"
23
-
24
- # Default to production/local build unless --dist is used
25
- COMPOSE_FILE="$SDK_ROOT/docker-compose.prod.yml"
26
-
27
- # Colors
28
- GREEN='\033[0;32m'
29
- BLUE='\033[0;34m'
30
- YELLOW='\033[1;33m'
31
- RED='\033[0;31m'
32
- NC='\033[0m' # No Color
33
-
34
- # Parse global options
35
- while [[ $# -gt 0 ]]; do
36
- case $1 in
37
- --dist)
38
- COMPOSE_FILE="$SDK_ROOT/docker-compose.sdk.yml"
39
- shift
40
- ;;
41
- *)
42
- break
43
- ;;
44
- esac
45
- done
46
-
47
- # Ensure cache dir exists
48
- mkdir -p "$CACHE_DIR/snapshots"
49
-
50
- log_info() { echo -e "${BLUE}[SDK]${NC} $1"; }
51
- log_success() { echo -e "${GREEN}[SDK]${NC} $1"; }
52
- log_warn() { echo -e "${YELLOW}[SDK]${NC} $1"; }
53
- log_error() { echo -e "${RED}[SDK]${NC} $1"; }
54
-
55
- pull_images_with_retry() {
56
- if [[ "$COMPOSE_FILE" != *"docker-compose.sdk.yml" ]]; then
57
- return 0
58
- fi
59
-
60
- local max_retries=10
61
- local count=0
62
-
63
- log_info "Please wait while we get things ready..."
64
-
65
- while [ $count -lt $max_retries ]; do
66
- if docker compose -f "$COMPOSE_FILE" pull; then
67
- return 0
68
- fi
69
-
70
- count=$((count + 1))
71
- log_warn "Download failed/interrupted. Retrying ($count/$max_retries) in 10s..."
72
- sleep 10
73
- done
74
-
75
- log_error "Failed to download images after $max_retries attempts. Please check your internet connection."
76
- exit 1
77
- }
78
-
79
- cmd_start() {
80
- log_info "Initializing Agent Environment (using $COMPOSE_FILE)..."
81
- export COMPOSE_FILE="$COMPOSE_FILE"
82
- pull_images_with_retry
83
-
84
- log_info "Cleaning up previous container state..."
85
- docker compose -f "$COMPOSE_FILE" down -v --remove-orphans >/dev/null 2>&1 || true
86
-
87
- if [ -d "$SNAPSHOT_DIR" ]; then
88
- # === WARM START ===
89
- log_success "Found cached baseline snapshot. Performing HYPER-SPEED WARM BOOT..."
90
- export EMULATOR_SNAPSHOT_NAME="quickboot"
91
- "$SDK_ROOT/start.sh"
92
- else
93
- # === COLD START & FREEZE ===
94
- log_warn "No baseline found. Performing FIRST RUN SETUP (Cold Boot)..."
95
- log_warn "This will take ~60-90 seconds, but only once."
96
-
97
- export EMULATOR_SNAPSHOT_NAME=""
98
-
99
- "$SDK_ROOT/start.sh" &
100
- START_PID=$!
101
- wait $START_PID
102
-
103
- if [ $? -ne 0 ]; then
104
- log_error "Startup failed."
105
- exit 1
106
- fi
107
-
108
- cd "$SDK_ROOT"
109
- CONTAINER=$(docker compose ps -q android-service)
110
-
111
- if [ -z "$CONTAINER" ]; then
112
- log_error "Error: Android container not found."
113
- exit 1
114
- fi
115
-
116
- log_info "Saving emulator state (quickboot)..."
117
- if docker exec "$CONTAINER" adb emu avd snapshot save quickboot; then
118
- log_success "Snapshot saved to host volume."
119
- log_success "Setup Complete! Future runs will launch instantly."
120
- else
121
- log_error "Failed to save snapshot inside emulator."
122
- exit 1
123
- fi
124
- fi
125
- }
126
-
127
- cmd_stop() {
128
- log_info "Stopping environment (using $COMPOSE_FILE)..."
129
- cd "$SDK_ROOT"
130
- docker compose -f "$COMPOSE_FILE" stop
131
- log_success "Stopped."
132
- }
133
-
134
- cmd_clean() {
135
- log_info "Tearing down environment and releasing ports (using $COMPOSE_FILE)..."
136
- cd "$SDK_ROOT"
137
- docker compose -f "$COMPOSE_FILE" down -v --remove-orphans
138
- log_success "Environment cleaned."
139
- }
140
-
141
- cmd_reset() {
142
- log_info "Performing Fast Browser Reset..."
143
- export COMPOSE_FILE="$COMPOSE_FILE"
144
- "$SDK_ROOT/scripts/fast_reset.sh"
145
- }
146
-
147
- cmd_agent() {
148
- if [ -f "$SDK_ROOT/agent" ]; then
149
- "$SDK_ROOT/agent" "$@"
150
- else
151
- node "$SDK_ROOT/bin/agent-browser.js" "$@"
152
- fi
153
- }
154
-
155
- case "$1" in
156
- start)
157
- cmd_start
158
- ;;
159
- stop)
160
- cmd_stop
161
- ;;
162
- clean)
163
- cmd_clean
164
- ;;
165
- reset)
166
- cmd_reset
167
- ;;
168
- agent)
169
- shift
170
- cmd_agent "$@"
171
- ;;
172
- *)
173
- echo "Usage: $0 {start|stop|clean|reset|agent}"
174
- exit 1
175
- ;;
176
- esac
package/start.sh DELETED
@@ -1,109 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
-
4
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
-
6
- # Colors
7
- GREEN='\033[0;32m'
8
- BLUE='\033[0;34m'
9
- YELLOW='\033[1;33m'
10
- RED='\033[0;31m'
11
- NC='\033[0m' # No Color
12
-
13
- echo -e "${BLUE}=================================================${NC}"
14
- echo -e "${BLUE} Agent Browser - Android Environment Setup ${NC}"
15
- echo -e "${BLUE}=================================================${NC}"
16
-
17
- SNAPSHOT_PATH=""
18
- while [[ $# -gt 0 ]]; do
19
- case $1 in
20
- --snapshot)
21
- SNAPSHOT_PATH="$2"
22
- shift 2
23
- ;;
24
- *)
25
- echo "Unknown option: $1"
26
- exit 1
27
- ;;
28
- esac
29
- done
30
-
31
- # 1. Pre-flight Checks
32
- echo -e "\n${YELLOW}[1/4] Checking System Requirements...${NC}"
33
-
34
- if ! command -v docker &> /dev/null; then
35
- echo -e "${RED}Error: Docker is not installed.${NC}"
36
- exit 1
37
- fi
38
-
39
- if [[ "$OSTYPE" == "linux-gnu"* ]]; then
40
- if [ -e /dev/kvm ]; then
41
- echo -e "${GREEN}✓ KVM Acceleration detected (/dev/kvm)${NC}"
42
- else
43
- echo -e "${YELLOW}⚠ Warning: No KVM detected. Emulator will be slow.${NC}"
44
- fi
45
- fi
46
-
47
- # 2. Start Services
48
- echo -e "\n${YELLOW}[2/4] Starting Docker Stack...${NC}"
49
- echo " (First run may take a few minutes to download images)"
50
-
51
- docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" up -d --build --remove-orphans
52
-
53
- # Find actual container names
54
- ANDROID_CONTAINER=$(docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" ps -q android-service)
55
- AGENT_CONTAINER=$(docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" ps -q agent-service)
56
-
57
- # 3. Wait for Readiness
58
- echo -e "\n${YELLOW}[3/4] Waiting for Initialization...${NC}"
59
-
60
- wait_for_log() {
61
- local container=$1
62
- local pattern=$2
63
- local label=$3
64
-
65
- echo -n " Waiting for $label... "
66
- until docker logs "$container" 2>&1 | grep -q "$pattern"; do
67
- sleep 1 # Faster polling
68
- done
69
- echo -e "${GREEN}Done!${NC}"
70
- }
71
-
72
- if [ -z "$SNAPSHOT_PATH" ] && [ -z "$EMULATOR_SNAPSHOT_NAME" ]; then
73
- # --- COLD BOOT PATH (Wait for everything) ---
74
- wait_for_log "$ANDROID_CONTAINER" "Emulator boot complete" "Android Emulator Boot"
75
- wait_for_log "$ANDROID_CONTAINER" "APK installation complete" "WootzApp Installation"
76
- wait_for_log "$ANDROID_CONTAINER" "CDP Bridge ready" "CDP Bridge"
77
- else
78
- # --- WARM BOOT PATH (Hyper-Speed) ---
79
- # We skip Boot and APK installation because they are inside the snapshot.
80
- # We only wait for the Daemon to reconnect to the resumed emulator.
81
- echo -e "${GREEN} Snapshot detected. Skipping OS boot and APK install waits.${NC}"
82
- fi
83
-
84
- # We always wait for the Daemon because it's the final bridge to the SDK
85
- wait_for_log "$AGENT_CONTAINER" "Daemon listening on TCP" "Agent Daemon Connection"
86
-
87
- # 3.5 Network Rehydration (Warm Boot Only)
88
- if [ -n "$SNAPSHOT_PATH" ] || [ -n "$EMULATOR_SNAPSHOT_NAME" ]; then
89
- echo " Rehydrating Android network connection..."
90
- # Toggle airplane mode to force DHCP lease renewal
91
- docker exec "$ANDROID_CONTAINER" adb shell cmd connectivity airplane-mode enable
92
- sleep 2
93
- docker exec "$ANDROID_CONTAINER" adb shell cmd connectivity airplane-mode disable
94
- # Wait for internet to come back
95
- sleep 3
96
- fi
97
-
98
- # 4. Success
99
- echo -e "\n${GREEN}[4/4] Environment Ready!${NC}"
100
- echo -e "${BLUE}=================================================${NC}"
101
- echo -e "You can now control the Android browser."
102
- echo -e ""
103
- echo -e "Try these commands:"
104
- echo -e " ${GREEN}./agent open https://google.com${NC}"
105
- echo -e " ${GREEN}./agent snapshot${NC}"
106
- echo -e " ${GREEN}./agent click @e1${NC}"
107
- echo -e ""
108
- echo -e "See COMMANDS.md for full reference."
109
- echo -e "${BLUE}=================================================${NC}"