From 4d427bcd31d251861820e5d4726bd0932ad60c61 Mon Sep 17 00:00:00 2001 From: floatingstarZ Date: Mon, 15 Dec 2025 18:10:46 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3issue154=E4=B8=AD=E7=9A=84mod?= =?UTF-8?q?el=5Foutput=E6=9C=89=E6=8D=A2=E8=A1=8C=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E4=BB=A5=E5=8F=8A=E5=A4=9A=E8=A1=8C=E6=96=87=E6=9C=AC?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E3=80=82=E8=A7=A3=E5=86=B3subprocessing?= =?UTF-8?q?=E7=BC=96=E7=A0=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- phone_agent/actions/handler.py | 33 +++++++++++++++++++++++++++++++-- phone_agent/adb/connection.py | 7 ++++--- phone_agent/adb/device.py | 4 +++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/phone_agent/actions/handler.py b/phone_agent/actions/handler.py index b8293f6..da60804 100644 --- a/phone_agent/actions/handler.py +++ b/phone_agent/actions/handler.py @@ -169,8 +169,21 @@ class ActionHandler: clear_text(self.device_id) time.sleep(TIMING_CONFIG.action.text_clear_delay) - type_text(text, self.device_id) - time.sleep(TIMING_CONFIG.action.text_input_delay) + # Handle multiline text by splitting on newlines + if '\n' in text: + lines = text.split('\n') + for i, line in enumerate(lines): + if line: # Only type non-empty lines + type_text(line, self.device_id) + time.sleep(0.01) + + # Send ENTER key between lines (not after the last line) + if i < len(lines) - 1: + self._send_keyevent("KEYCODE_ENTER") + time.sleep(0.01) + else: + type_text(text, self.device_id) + time.sleep(TIMING_CONFIG.action.text_input_delay) # Restore original keyboard restore_keyboard(original_ime, self.device_id) @@ -256,6 +269,16 @@ class ActionHandler: # This action signals that user input is needed return ActionResult(True, False, message="User interaction required") + def _send_keyevent(self, keycode: str) -> None: + """Send a keyevent to the device.""" + import subprocess + adb_prefix = ["adb", "-s", self.device_id] if self.device_id else ["adb"] + subprocess.run( + adb_prefix + ["shell", "input", "keyevent", keycode], + capture_output=True, + text=True, + ) + @staticmethod def _default_confirmation(message: str) -> bool: """Default confirmation callback using console input.""" @@ -281,11 +304,17 @@ def parse_action(response: str) -> dict[str, Any]: Raises: ValueError: If the response cannot be parsed. """ + print(f"Parsing action: {response}") try: response = response.strip() if response.startswith("do"): # Use AST parsing instead of eval for safety try: + # Escape special characters (newlines, tabs, etc.) for valid Python syntax + response = response.replace('\n', '\\n') + response = response.replace('\r', '\\r') + response = response.replace('\t', '\\t') + tree = ast.parse(response, mode="eval") if not isinstance(tree.body, ast.Call): raise ValueError("Expected a function call") diff --git a/phone_agent/adb/connection.py b/phone_agent/adb/connection.py index 480b5a7..b723ca9 100644 --- a/phone_agent/adb/connection.py +++ b/phone_agent/adb/connection.py @@ -109,7 +109,7 @@ class ADBConnection: 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, encoding="utf-8", timeout=5) output = result.stdout + result.stderr return True, output.strip() or "Disconnected" @@ -241,7 +241,7 @@ class ADBConnection: 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, encoding="utf-8", timeout=10) output = result.stdout + result.stderr @@ -270,7 +270,7 @@ class ADBConnection: cmd.extend(["-s", device_id]) cmd.extend(["shell", "ip", "route"]) - result = subprocess.run(cmd, capture_output=True, text=True, timeout=5) + result = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", timeout=5) # Parse IP from route output for line in result.stdout.split("\n"): @@ -286,6 +286,7 @@ class ADBConnection: cmd[:-1] + ["shell", "ip", "addr", "show", "wlan0"], capture_output=True, text=True, + encoding="utf-8", timeout=5, ) diff --git a/phone_agent/adb/device.py b/phone_agent/adb/device.py index 1a081ad..995336a 100644 --- a/phone_agent/adb/device.py +++ b/phone_agent/adb/device.py @@ -22,9 +22,11 @@ def get_current_app(device_id: str | None = None) -> str: adb_prefix = _get_adb_prefix(device_id) result = subprocess.run( - adb_prefix + ["shell", "dumpsys", "window"], capture_output=True, text=True + adb_prefix + ["shell", "dumpsys", "window"], capture_output=True, text=True, encoding="utf-8" ) output = result.stdout + if not output: + raise ValueError("No output from dumpsys window") # Parse window focus info for line in output.split("\n"):