@kritchoff/agent-browser 0.9.44 → 0.9.46
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/docker-compose.sdk.yml +1 -0
- package/package.json +1 -1
- package/sdk.sh +55 -89
- package/start.sh +11 -32
package/docker-compose.sdk.yml
CHANGED
package/package.json
CHANGED
package/sdk.sh
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Agent Browser SDK Wrapper
|
|
3
3
|
#
|
|
4
4
|
# A user-friendly entry point for AI Agents to interact with the Android Browser Environment.
|
|
5
|
-
# Handles "
|
|
5
|
+
# Handles "Hyper-Speed Snapshot" logic for instant startups.
|
|
6
6
|
#
|
|
7
7
|
# Usage:
|
|
8
8
|
# ./sdk.sh start - Start the environment (Cold boot 1st time, Warm boot after)
|
|
@@ -13,14 +13,13 @@
|
|
|
13
13
|
|
|
14
14
|
set -e
|
|
15
15
|
|
|
16
|
-
# Set high timeouts for large image downloads
|
|
17
|
-
# This helps prevent 'TLS handshake timeout' on slow connections
|
|
16
|
+
# Set high timeouts for large image downloads
|
|
18
17
|
export COMPOSE_HTTP_TIMEOUT=900
|
|
19
18
|
export DOCKER_CLIENT_TIMEOUT=900
|
|
20
19
|
|
|
21
20
|
SDK_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
22
21
|
CACHE_DIR="$SDK_ROOT/cache"
|
|
23
|
-
|
|
22
|
+
SNAPSHOT_DIR="$CACHE_DIR/snapshots/quickboot"
|
|
24
23
|
|
|
25
24
|
# Default to production/local build unless --dist is used
|
|
26
25
|
COMPOSE_FILE="$SDK_ROOT/docker-compose.prod.yml"
|
|
@@ -46,7 +45,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
46
45
|
done
|
|
47
46
|
|
|
48
47
|
# Ensure cache dir exists
|
|
49
|
-
mkdir -p "$CACHE_DIR"
|
|
48
|
+
mkdir -p "$CACHE_DIR/snapshots"
|
|
50
49
|
|
|
51
50
|
log_info() { echo -e "${BLUE}[SDK]${NC} $1"; }
|
|
52
51
|
log_success() { echo -e "${GREEN}[SDK]${NC} $1"; }
|
|
@@ -54,12 +53,11 @@ log_warn() { echo -e "${YELLOW}[SDK]${NC} $1"; }
|
|
|
54
53
|
log_error() { echo -e "${RED}[SDK]${NC} $1"; }
|
|
55
54
|
|
|
56
55
|
pull_images_with_retry() {
|
|
57
|
-
# Only pull if we are using the distribution compose file (which uses images)
|
|
58
56
|
if [[ "$COMPOSE_FILE" != *"docker-compose.sdk.yml" ]]; then
|
|
59
57
|
return 0
|
|
60
58
|
fi
|
|
61
59
|
|
|
62
|
-
local max_retries=
|
|
60
|
+
local max_retries=10
|
|
63
61
|
local count=0
|
|
64
62
|
|
|
65
63
|
log_info "Please wait while we get things ready..."
|
|
@@ -70,8 +68,8 @@ pull_images_with_retry() {
|
|
|
70
68
|
fi
|
|
71
69
|
|
|
72
70
|
count=$((count + 1))
|
|
73
|
-
log_warn "Download failed/interrupted. Retrying ($count/$max_retries)..."
|
|
74
|
-
sleep
|
|
71
|
+
log_warn "Download failed/interrupted. Retrying ($count/$max_retries) in 10s..."
|
|
72
|
+
sleep 10
|
|
75
73
|
done
|
|
76
74
|
|
|
77
75
|
log_error "Failed to download images after $max_retries attempts. Please check your internet connection."
|
|
@@ -80,97 +78,69 @@ pull_images_with_retry() {
|
|
|
80
78
|
|
|
81
79
|
cmd_start() {
|
|
82
80
|
log_info "Initializing Agent Environment (using $COMPOSE_FILE)..."
|
|
83
|
-
|
|
84
|
-
# Export COMPOSE_FILE so start.sh (which might call docker compose) uses it
|
|
85
|
-
# Note: start.sh needs to be updated to respect COMPOSE_FILE if it doesn't already
|
|
86
81
|
export COMPOSE_FILE="$COMPOSE_FILE"
|
|
87
|
-
|
|
88
|
-
# Ensure images are present (Production robustness)
|
|
89
82
|
pull_images_with_retry
|
|
90
83
|
|
|
91
|
-
# --- ALWAYS CLEAN UP PREVIOUS STATE ---
|
|
92
|
-
# This prevents network namespace corruption and port binding failures on warm boots
|
|
93
84
|
log_info "Cleaning up previous container state..."
|
|
94
85
|
docker compose -f "$COMPOSE_FILE" down -v --remove-orphans >/dev/null 2>&1 || true
|
|
95
86
|
|
|
96
|
-
if [ -
|
|
87
|
+
if [ -d "$SNAPSHOT_DIR" ]; then
|
|
97
88
|
# === WARM START ===
|
|
98
|
-
log_success "Found cached baseline snapshot. Performing WARM BOOT..."
|
|
99
|
-
|
|
89
|
+
log_success "Found cached baseline snapshot. Performing HYPER-SPEED WARM BOOT..."
|
|
90
|
+
export EMULATOR_SNAPSHOT_NAME="quickboot"
|
|
91
|
+
"$SDK_ROOT/start.sh"
|
|
100
92
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
"$SDK_ROOT/start.sh" &
|
|
121
|
-
START_PID=$!
|
|
122
|
-
wait $START_PID
|
|
123
|
-
|
|
124
|
-
# Check if start was successful
|
|
125
|
-
if [ $? -ne 0 ]; then
|
|
126
|
-
log_error "Startup failed."
|
|
127
|
-
exit 1
|
|
128
|
-
fi
|
|
93
|
+
cd "$SDK_ROOT"
|
|
94
|
+
AGENT_CONT=$(docker compose ps -q agent-service)
|
|
95
|
+
if [ -n "$AGENT_CONT" ] && ! docker port "$AGENT_CONT" 3000 >/dev/null 2>&1; then
|
|
96
|
+
log_warn "Port 3000 (Host 32001) is not mapped! Container config is stale."
|
|
97
|
+
log_info "Forcing full restart to apply network settings..."
|
|
98
|
+
docker compose -f "$COMPOSE_FILE" down -v --remove-orphans
|
|
99
|
+
sleep 5
|
|
100
|
+
"$SDK_ROOT/start.sh"
|
|
101
|
+
fi
|
|
102
|
+
else
|
|
103
|
+
# === COLD START & FREEZE ===
|
|
104
|
+
log_warn "No baseline found. Performing FIRST RUN SETUP (Cold Boot)..."
|
|
105
|
+
log_warn "This will take ~60-90 seconds, but only once."
|
|
106
|
+
|
|
107
|
+
export EMULATOR_SNAPSHOT_NAME=""
|
|
108
|
+
|
|
109
|
+
"$SDK_ROOT/start.sh" &
|
|
110
|
+
START_PID=$!
|
|
111
|
+
wait $START_PID
|
|
129
112
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
exit 1
|
|
139
|
-
fi
|
|
113
|
+
if [ $? -ne 0 ]; then
|
|
114
|
+
log_error "Startup failed."
|
|
115
|
+
exit 1
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
cd "$SDK_ROOT"
|
|
119
|
+
CONTAINER=$(docker compose ps -q android-service)
|
|
120
|
+
AGENT_CONT=$(docker compose ps -q agent-service)
|
|
140
121
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
# 1. Save snapshot inside emulator
|
|
122
|
+
if [ -z "$CONTAINER" ]; then
|
|
123
|
+
log_error "Error: Android container not found."
|
|
124
|
+
exit 1
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
if ! docker port "$AGENT_CONT" 3000 >/dev/null 2>&1; then
|
|
128
|
+
log_warn "Port 3000 (Host 32001) is not mapped! Container config is stale."
|
|
129
|
+
log_info "Forcing full restart to apply network settings..."
|
|
130
|
+
docker compose -f "$COMPOSE_FILE" down -v --remove-orphans
|
|
131
|
+
sleep 5
|
|
132
|
+
"$SDK_ROOT/start.sh"
|
|
133
|
+
CONTAINER=$(docker compose ps -q android-service)
|
|
134
|
+
fi
|
|
135
|
+
|
|
157
136
|
log_info "Saving emulator state (quickboot)..."
|
|
158
137
|
if docker exec "$CONTAINER" adb emu avd snapshot save quickboot; then
|
|
159
|
-
log_success "Snapshot saved
|
|
138
|
+
log_success "Snapshot saved to host volume."
|
|
139
|
+
log_success "Setup Complete! Future runs will launch instantly."
|
|
160
140
|
else
|
|
161
141
|
log_error "Failed to save snapshot inside emulator."
|
|
162
142
|
exit 1
|
|
163
143
|
fi
|
|
164
|
-
|
|
165
|
-
# 2. Export to host
|
|
166
|
-
log_info "Exporting to cache..."
|
|
167
|
-
if "$SDK_ROOT/scripts/snapshot_manager.sh" export quickboot "$SNAPSHOT_FILE"; then
|
|
168
|
-
log_success "Snapshot exported to $SNAPSHOT_FILE"
|
|
169
|
-
log_success "Setup Complete! Future runs will launch in ~20 seconds."
|
|
170
|
-
else
|
|
171
|
-
log_error "Failed to export snapshot."
|
|
172
|
-
# Don't exit, environment is still running
|
|
173
|
-
fi
|
|
174
144
|
fi
|
|
175
145
|
}
|
|
176
146
|
|
|
@@ -195,17 +165,13 @@ cmd_reset() {
|
|
|
195
165
|
}
|
|
196
166
|
|
|
197
167
|
cmd_agent() {
|
|
198
|
-
# Forward commands to the native agent binary or script
|
|
199
|
-
# Assuming 'agent' binary is in $SDK_ROOT/agent or bin/agent-browser
|
|
200
168
|
if [ -f "$SDK_ROOT/agent" ]; then
|
|
201
169
|
"$SDK_ROOT/agent" "$@"
|
|
202
170
|
else
|
|
203
|
-
# Fallback to bin/agent-browser.js if binary not built/linked
|
|
204
171
|
node "$SDK_ROOT/bin/agent-browser.js" "$@"
|
|
205
172
|
fi
|
|
206
173
|
}
|
|
207
174
|
|
|
208
|
-
# Main Dispatch
|
|
209
175
|
case "$1" in
|
|
210
176
|
start)
|
|
211
177
|
cmd_start
|
|
@@ -224,7 +190,7 @@ case "$1" in
|
|
|
224
190
|
cmd_agent "$@"
|
|
225
191
|
;;
|
|
226
192
|
*)
|
|
227
|
-
echo "Usage: $0 {start|stop|reset|agent}"
|
|
193
|
+
echo "Usage: $0 {start|stop|clean|reset|agent}"
|
|
228
194
|
exit 1
|
|
229
195
|
;;
|
|
230
196
|
esac
|
package/start.sh
CHANGED
|
@@ -54,38 +54,6 @@ docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" up -d --build --rem
|
|
|
54
54
|
ANDROID_CONTAINER=$(docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" ps -q android-service)
|
|
55
55
|
AGENT_CONTAINER=$(docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" ps -q agent-service)
|
|
56
56
|
|
|
57
|
-
# 2b. Import Snapshot (if requested)
|
|
58
|
-
if [ -n "$SNAPSHOT_PATH" ]; then
|
|
59
|
-
echo -e "\n${YELLOW}[2.5/4] Importing Snapshot: $SNAPSHOT_PATH...${NC}"
|
|
60
|
-
|
|
61
|
-
# Wait for container to be responsive
|
|
62
|
-
echo -n " Waiting for container to be ready for import... "
|
|
63
|
-
until docker exec "$ANDROID_CONTAINER" echo "ready" &>/dev/null; do
|
|
64
|
-
sleep 1
|
|
65
|
-
done
|
|
66
|
-
echo -e "${GREEN}OK${NC}"
|
|
67
|
-
|
|
68
|
-
# Import
|
|
69
|
-
if "$SCRIPT_DIR/scripts/snapshot_manager.sh" import "$SNAPSHOT_PATH" "w8rl_imported"; then
|
|
70
|
-
echo -e "${GREEN} Snapshot imported successfully.${NC}"
|
|
71
|
-
|
|
72
|
-
# Configure emulator to load this snapshot
|
|
73
|
-
# We set the env var in the container for the next boot
|
|
74
|
-
# (This assumes the entrypoint script respects EMULATOR_SNAPSHOT_NAME)
|
|
75
|
-
# For now, we'll rely on the default behavior or standard AVD loading
|
|
76
|
-
|
|
77
|
-
echo " Restarting services to load snapshot..."
|
|
78
|
-
docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" restart android-service agent-service
|
|
79
|
-
|
|
80
|
-
# Update container IDs after restart
|
|
81
|
-
ANDROID_CONTAINER=$(docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" ps -q android-service)
|
|
82
|
-
AGENT_CONTAINER=$(docker compose -f "${COMPOSE_FILE:-docker-compose.prod.yml}" ps -q agent-service)
|
|
83
|
-
else
|
|
84
|
-
echo -e "${RED}Error: Failed to import snapshot.${NC}"
|
|
85
|
-
exit 1
|
|
86
|
-
fi
|
|
87
|
-
fi
|
|
88
|
-
|
|
89
57
|
# 3. Wait for Readiness
|
|
90
58
|
echo -e "\n${YELLOW}[3/4] Waiting for Initialization...${NC}"
|
|
91
59
|
|
|
@@ -107,6 +75,17 @@ wait_for_log "$ANDROID_CONTAINER" "CDP Bridge ready" "CDP Bridge"
|
|
|
107
75
|
# Daemon logs "Daemon listening on TCP 0.0.0.0:3000" in direct mode
|
|
108
76
|
wait_for_log "$AGENT_CONTAINER" "Daemon listening on TCP" "Agent Daemon Connection"
|
|
109
77
|
|
|
78
|
+
# 3.5 Network Rehydration (Warm Boot Only)
|
|
79
|
+
if [ -n "$SNAPSHOT_PATH" ]; then
|
|
80
|
+
echo " Rehydrating Android network connection..."
|
|
81
|
+
# Toggle airplane mode to force DHCP lease renewal
|
|
82
|
+
docker exec "$ANDROID_CONTAINER" adb shell cmd connectivity airplane-mode enable
|
|
83
|
+
sleep 2
|
|
84
|
+
docker exec "$ANDROID_CONTAINER" adb shell cmd connectivity airplane-mode disable
|
|
85
|
+
# Wait for internet to come back
|
|
86
|
+
sleep 3
|
|
87
|
+
fi
|
|
88
|
+
|
|
110
89
|
# 4. Success
|
|
111
90
|
echo -e "\n${GREEN}[4/4] Environment Ready!${NC}"
|
|
112
91
|
echo -e "${BLUE}=================================================${NC}"
|