@kritchoff/agent-browser 0.9.43 → 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.
@@ -3,7 +3,7 @@ services:
3
3
  # Android Emulator Service (The "Body")
4
4
  # ---------------------------------------------------------------------------
5
5
  android-service:
6
- image: kritchoff/agent-android:v1.0.7
6
+ image: kritchoff/agent-android:v1.0.8
7
7
  platform: linux/amd64
8
8
  privileged: true # Required for KVM
9
9
  restart: always # Auto-restart on crash
@@ -19,18 +19,21 @@ services:
19
19
  - /dev/kvm:/dev/kvm
20
20
  volumes:
21
21
  - avd-data:/root/.android
22
+ - ./cache/snapshots:/root/.android/avd/Pixel_6_API_34.avd/snapshots
22
23
  healthcheck:
23
24
  test: ["CMD", "curl", "-f", "http://localhost:9224/json/version"]
24
25
  interval: 10s
25
26
  timeout: 5s
26
27
  retries: 60
27
28
  start_period: 60s
29
+ networks:
30
+ - agent-network
28
31
 
29
32
  # ---------------------------------------------------------------------------
30
33
  # Agent Browser Service (The "Brain")
31
34
  # ---------------------------------------------------------------------------
32
35
  agent-service:
33
- image: kritchoff/agent-daemon:v1.0.7
36
+ image: kritchoff/agent-daemon:v1.0.8
34
37
  platform: linux/amd64
35
38
  restart: always
36
39
  depends_on:
@@ -40,8 +43,12 @@ services:
40
43
  environment:
41
44
  - AGENT_DEBUG=false
42
45
  - AGENT_BROWSER_SOCKET_DIR=/tmp/agent-browser
43
- links:
44
- - android-service
46
+ networks:
47
+ - agent-network
45
48
 
46
49
  volumes:
47
50
  avd-data:
51
+
52
+ networks:
53
+ agent-network:
54
+ driver: bridge
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kritchoff/agent-browser",
3
- "version": "0.9.43",
3
+ "version": "0.9.46",
4
4
  "description": "Headless browser automation CLI for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -6,19 +6,18 @@ mkdir -p $AGENT_BROWSER_SOCKET_DIR
6
6
 
7
7
  echo "[Agent] Starting Agent Browser Service"
8
8
 
9
- # Resolve IP of android-service to avoid Chrome Host header security block
10
- echo "[Agent] Resolving android-service IP..."
9
+ # Resolve IP of android-service via Docker's built-in DNS
10
+ echo "[Agent] Resolving android-service IP via DNS..."
11
11
  ANDROID_IP=""
12
12
  until [ -n "$ANDROID_IP" ]; do
13
- # Try /etc/hosts (Fastest, reliable with Docker links)
14
- ANDROID_IP=$(grep "android-service" /etc/hosts | awk '{print $1}' | head -n 1)
13
+ ANDROID_IP=$(node -e 'require("dns").lookup("android-service", (err, addr) => { if(!err) console.log(addr) })' 2>/dev/null)
15
14
 
16
15
  if [ -z "$ANDROID_IP" ]; then
17
- echo "[Agent] Waiting for DNS resolution..."
16
+ echo "[Agent] Waiting for Docker DNS resolution of 'android-service'..."
18
17
  sleep 2
19
18
  fi
20
19
  done
21
- echo "[Agent] Android IP: $ANDROID_IP"
20
+ echo "[Agent] Resolved Android IP: $ANDROID_IP"
22
21
 
23
22
  # Wait for CDP Bridge (Port 9224)
24
23
  echo "[Agent] Waiting for Android CDP at http://$ANDROID_IP:9224..."
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 "Lazy Snapshot" logic for instant startups.
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 (Production robustness)
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
- SNAPSHOT_FILE="$CACHE_DIR/baseline.tar.gz"
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=5
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 5
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 [ -f "$SNAPSHOT_FILE" ]; then
87
+ if [ -d "$SNAPSHOT_DIR" ]; then
97
88
  # === WARM START ===
98
- log_success "Found cached baseline snapshot. Performing WARM BOOT..."
99
- "$SDK_ROOT/start.sh" --snapshot "$SNAPSHOT_FILE"
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
- # Verify port mapping for warm start too
102
- cd "$SDK_ROOT"
103
- AGENT_CONT=$(docker compose ps -q agent-service)
104
- if [ -n "$AGENT_CONT" ] && ! docker port "$AGENT_CONT" 3000 >/dev/null 2>&1; then
105
- log_warn "Port 3000 (Host 32001) is not mapped! Container config is stale."
106
- log_info "Forcing full restart to apply network settings..."
107
- docker compose -f "$COMPOSE_FILE" down -v --remove-orphans
108
-
109
- log_info "Waiting for ports to release..."
110
- sleep 5
111
-
112
- "$SDK_ROOT/start.sh" --snapshot "$SNAPSHOT_FILE"
113
- fi
114
- else
115
- # === COLD START & FREEZE ===
116
- log_warn "No baseline found. Performing FIRST RUN SETUP (Cold Boot)..."
117
- log_warn "This will take ~60-90 seconds, but only once."
118
-
119
- # Start in background to wait for it
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
- # We need to find the container ID to send the adb command
131
- # We use docker compose to find it reliably
132
- cd "$SDK_ROOT"
133
- CONTAINER=$(docker compose ps -q android-service)
134
- AGENT_CONT=$(docker compose ps -q agent-service)
135
-
136
- if [ -z "$CONTAINER" ]; then
137
- log_error "Error: Android container not found."
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
- # SELF-HEAL: Verify port 3000 is actually mapped
142
- if ! docker port "$AGENT_CONT" 3000 >/dev/null 2>&1; then
143
- log_warn "Port 3000 (Host 32001) is not mapped! Container config is stale."
144
- log_info "Forcing full restart to apply network settings..."
145
- docker compose -f "$COMPOSE_FILE" down -v --remove-orphans
146
-
147
- log_info "Waiting for ports to release..."
148
- sleep 5
149
-
150
- "$SDK_ROOT/start.sh"
151
-
152
- # Re-fetch container ID after restart
153
- CONTAINER=$(docker compose ps -q android-service)
154
- fi
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 inside emulator."
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}"