Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
897 changes: 93 additions & 804 deletions README.md

Large diffs are not rendered by default.

430 changes: 0 additions & 430 deletions README_coding_agent.md

This file was deleted.

795 changes: 0 additions & 795 deletions README_en.md

This file was deleted.

48 changes: 48 additions & 0 deletions REMOTE_SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Remote Control Setup Guide (Tailscale + ADB)

This guide explains how to control your Android phone using Open-AutoGLM even when the phone is on a mobile network (4G/5G) and not on the same Wi-Fi as your PC.

## 1. Prerequisites (Tailscale VPN)

Since ADB (Android Debug Bridge) does not work over the public internet securely, we use **Tailscale** to create a private, secure link between your devices.

### Step 1: Install Tailscale
1. **On PC**: Download and install [Tailscale for Windows](https://tailscale.com/download/windows).
2. **On Phone**: Install the **Tailscale** app from the Google Play Store.

### Step 2: Configure Network
1. Open Tailscale on **both** devices.
2. Log in with the **same account** (e.g., your Google account) on both.
3. Ensure Tailscale is **Active** (Connected) on both.
4. On the phone app, find the **IP Address** assigned to your phone (it starts with `100.x.x.x`).

## 2. Connect ADB Remotely

To connect your PC to the phone securely over this new network:

1. **Open Terminal** in the `Open-AutoGLM` directory.
2. Run the connect command using the local `platform-tools`:

```powershell
.\platform-tools\adb.exe connect <PHONE_TAILSCALE_IP>:5555
```
*(Replace `<PHONE_TAILSCALE_IP>` with the address you found in Step 1, e.g., `100.76.226.33`)*

3. **Verify Connection**:
```powershell
.\platform-tools\adb.exe devices
```
You should see your device IP listed as `device`.

## 3. Troubleshooting

**"Target machine actively refused it"**
* This means ADB is not listening on port 5555 on the phone.
* **Fix**: You must enable TCP/IP mode *once* via USB.
1. Plug phone into PC via USB.
2. Run: `.\platform-tools\adb.exe tcpip 5555`
3. Unplug phone.
4. Try connecting again via Tailscale IP.

**"Command not found"**
* PowerShell doesn't know where `adb` is. Always use `.\platform-tools\adb.exe` instead of just `adb`.
56 changes: 48 additions & 8 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from phone_agent.model import ModelConfig


def check_system_requirements() -> bool:
def check_system_requirements(device_id: str | None = None) -> bool:
"""
Check system requirements before running the agent.

Expand Down Expand Up @@ -90,7 +90,7 @@ def check_system_requirements() -> bool:
print("2. Checking connected devices...", end=" ")
try:
result = subprocess.run(
["adb", "devices"], capture_output=True, text=True, timeout=10
["adb", "devices"], capture_output=True, text=True, timeout=30
)
lines = result.stdout.strip().split("\n")
# Filter out header and empty lines, look for 'device' status
Expand Down Expand Up @@ -125,11 +125,16 @@ def check_system_requirements() -> bool:
# Check 3: ADB Keyboard installed
print("3. Checking ADB Keyboard...", end=" ")
try:
cmd = ["adb"]
if device_id:
cmd.extend(["-s", device_id])
cmd.extend(["shell", "ime", "list", "-s"])

result = subprocess.run(
["adb", "shell", "ime", "list", "-s"],
cmd,
capture_output=True,
text=True,
timeout=10,
timeout=30,
)
ime_list = result.stdout.strip()

Expand Down Expand Up @@ -368,9 +373,21 @@ def parse_args() -> argparse.Namespace:
help="Language for system prompt (cn or en, default: cn)",
)

parser.add_argument(
"--auto-confirm",
action="store_true",
help="Automatically confirm sensitive operations and suppress interactive prompts"
)

parser.add_argument(
"--skip-checks",
action="store_true",
help="Skip system requirements check",
)

parser.add_argument(
"task",
nargs="?",
nargs="*",
type=str,
help="Task to execute (interactive mode if not provided)",
)
Expand Down Expand Up @@ -464,7 +481,7 @@ def main():
return

# Run system requirements check before proceeding
if not check_system_requirements():
if not args.skip_checks and not check_system_requirements(args.device_id):
sys.exit(1)

# Check model API connectivity and model availability
Expand All @@ -485,10 +502,27 @@ def main():
lang=args.lang,
)

# Define callbacks based on auto-confirm
confirmation_callback = None
takeover_callback = None

if args.auto_confirm:
def auto_confirmation(msg):
print(f"⚠️ Auto-confirming sensitive operation: {msg}")
return True

def auto_takeover(msg):
print(f"⚠️ Auto-takeover suppressed: {msg}")

confirmation_callback = auto_confirmation
takeover_callback = auto_takeover

# Create agent
agent = PhoneAgent(
model_config=model_config,
agent_config=agent_config,
confirmation_callback=confirmation_callback,
takeover_callback=takeover_callback,
)

# Print header
Expand All @@ -511,8 +545,14 @@ def main():

# Run with provided task or enter interactive mode
if args.task:
print(f"\nTask: {args.task}\n")
result = agent.run(args.task)
# Join task arguments into a single string if it's a list
if isinstance(args.task, list):
task_str = " ".join(args.task)
else:
task_str = args.task

print(f"\nTask: {task_str}\n")
result = agent.run(task_str)
print(f"\nResult: {result}")
else:
# Interactive mode
Expand Down
8 changes: 4 additions & 4 deletions phone_agent/adb/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def __init__(self, adb_path: str = "adb"):
"""
self.adb_path = adb_path

def connect(self, address: str, timeout: int = 10) -> tuple[bool, str]:
def connect(self, address: str, timeout: int = 30) -> tuple[bool, str]:
"""
Connect to a remote device via TCP/IP.

Expand Down Expand Up @@ -107,7 +107,7 @@ def disconnect(self, address: str | None = None) -> tuple[bool, str]:
if address:
cmd.append(address)

result = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)

output = result.stdout + result.stderr
return True, output.strip() or "Disconnected"
Expand All @@ -127,7 +127,7 @@ def list_devices(self) -> list[DeviceInfo]:
[self.adb_path, "devices", "-l"],
capture_output=True,
text=True,
timeout=5,
timeout=15,
)

devices = []
Expand Down Expand Up @@ -239,7 +239,7 @@ def enable_tcpip(
cmd.extend(["-s", device_id])
cmd.extend(["tcpip", str(port)])

result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)

output = result.stdout + result.stderr

Expand Down
4 changes: 2 additions & 2 deletions phone_agent/adb/screenshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Screenshot:
is_sensitive: bool = False


def get_screenshot(device_id: str | None = None, timeout: int = 10) -> Screenshot:
def get_screenshot(device_id: str | None = None, timeout: int = 30) -> Screenshot:
"""
Capture a screenshot from the connected Android device.

Expand Down Expand Up @@ -59,7 +59,7 @@ def get_screenshot(device_id: str | None = None, timeout: int = 10) -> Screensho
adb_prefix + ["pull", "/sdcard/tmp.png", temp_path],
capture_output=True,
text=True,
timeout=5,
timeout=30,
)

if not os.path.exists(temp_path):
Expand Down
Binary file added platform-tools/AdbWinApi.dll
Binary file not shown.
Binary file added platform-tools/AdbWinUsbApi.dll
Binary file not shown.
Loading