@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.
- package/README.md +82 -849
- package/bin/agent-browser.js +2 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +37 -11
- package/dist/orchestrator.js.map +1 -1
- package/package.json +1 -3
- package/README.sdk.md +0 -129
- package/scripts/fast_reset.sh +0 -117
- package/scripts/snapshot_manager.sh +0 -293
- package/scripts/vaccine-run +0 -26
- package/sdk.sh +0 -176
- package/start.sh +0 -109
|
@@ -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
|
package/scripts/vaccine-run
DELETED
|
@@ -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}"
|