agent control layer: vision endpoint (qwen2.5vl:7b), tap/swipe/text/launch, fleet actions, onboard retry sweep, MCP server :8095

This commit is contained in:
drjones
2026-08-13 18:35:11 -07:00
parent 2a2d72f288
commit 1bed8f947e
5 changed files with 361 additions and 16 deletions

View File

@@ -12,6 +12,7 @@ import re
import sqlite3
import subprocess
import sys
import threading
import time
DB_PATH = "/opt/android-fleet/fleet.db"
@@ -52,11 +53,21 @@ def adb_cmd(serial, args, timeout=60):
capture_output=True, text=True, timeout=timeout)
NORD_FALLBACK = "http://10.30.20.154:1081" # nord-tunnel HTTP CONNECT (instagrapi's socks client is broken)
COUNTER_FILE = "/opt/android-fleet/ig_counter"
COUNTER_LOCK = threading.Lock()
def next_counter():
con = dbcon()
row = con.execute("SELECT COUNT(*) AS n FROM accounts").fetchone()
con.close()
return row["n"] + 1
"""Atomic account counter — never reuse an email alias."""
with COUNTER_LOCK:
n = 1
if os.path.exists(COUNTER_FILE):
try:
n = int(open(COUNTER_FILE).read().strip() or 0) + 1
except ValueError:
n = 1
open(COUNTER_FILE, "w").write(str(n))
return n
def setup_basics(serial):
@@ -133,6 +144,9 @@ def create_instagram_account(serial, proxy_url, counter):
except Exception as e:
msg = str(e).lower()
log(f"signup challenge: {str(e)[:100]}")
if "429" in str(e) or "rate" in msg:
return {"status": "rate_limited_ip", "email": email, "username": username,
"session_file": None}
if "checkpoint" in msg or "challenge" in msg:
return {"status": "checkpoint", "email": email, "username": username}
if "sent" in msg or "verification" in msg or "confirm" in msg:
@@ -275,16 +289,15 @@ def onboard(mac):
pass
apk_state = install_instagram(serial)
# proxy for this device
con = dbcon()
pr = con.execute("SELECT * FROM proxies WHERE assigned_mac=?", (mac,)).fetchone()
con.close()
proxy_url = None
if pr:
cred = f"{pr['user']}:{pr['pass']}@" if pr["user"] else ""
proxy_url = f"socks5://{cred}{pr['host']}:{pr['port']}"
result = create_instagram_account(serial, proxy_url, counter)
# SIGNUP ALWAYS USES THE STABLE NORD TUNNEL — free-pool device proxies are
# too flaky for the account-creation handshake (dead SOCKS = instant fail).
result = None
try:
result = create_instagram_account(serial, NORD_FALLBACK, counter)
except Exception as e:
log(f"onboard crash: {str(e)[:100]}")
result = {"status": f"onboard_error: {str(e)[:60]}", "email": None,
"username": None, "session_file": None}
result["apk"] = apk_state
if result.get("session_file"):
login_app(serial, result["username"])