diff --git a/codes/tests/action_parser_test.py b/codes/tests/action_parser_test.py index ca04cdc..25ad8e2 100644 --- a/codes/tests/action_parser_test.py +++ b/codes/tests/action_parser_test.py @@ -32,6 +32,40 @@ def test_parsing_response_to_pyautogui_code(self): code = parsing_response_to_pyautogui_code(responses, 224, 224) self.assertIn('pyautogui.hotkey', code) + def test_type_with_trailing_newline_preserves_content(self): + # After parsing, a real trailing newline becomes the literal "\\n". + # The trailing newline must be stripped (so Enter is pressed + # separately) WITHOUT eating real trailing "n"/"\\" characters from + # the typed text. Regression test for the rstrip("\\n") char-set bug + # that turned "Login\\n" into "Logi" and "Run\\n" into "Ru". + for raw, expected in [ + ("Login\\n", "Login"), + ("Run\\n", "Run"), + ("python\\n", "python"), + ("hello world\\n", "hello world"), + ]: + responses = { + "action_type": "type", + "action_inputs": {"content": raw}, + } + code = parsing_response_to_pyautogui_code( + responses, 1080, 1920, input_swap=False + ) + self.assertIn(f"pyautogui.write('{expected}'", code) + # A trailing newline still triggers a separate Enter press. + self.assertIn("pyautogui.press('enter')", code) + + def test_type_without_newline_is_unchanged(self): + responses = { + "action_type": "type", + "action_inputs": {"content": "Login"}, + } + code = parsing_response_to_pyautogui_code( + responses, 1080, 1920, input_swap=False + ) + self.assertIn("pyautogui.write('Login'", code) + self.assertNotIn("pyautogui.press('enter')", code) + if __name__ == '__main__': unittest.main() diff --git a/codes/ui_tars/action_parser.py b/codes/ui_tars/action_parser.py index 2b722f4..b29661f 100644 --- a/codes/ui_tars/action_parser.py +++ b/codes/ui_tars/action_parser.py @@ -405,8 +405,15 @@ def parsing_response_to_pyautogui_code(responses, content = action_inputs.get("content", "") content = escape_single_quotes(content) stripped_content = content - if content.endswith("\n") or content.endswith("\\n"): - stripped_content = stripped_content.rstrip("\\n").rstrip("\n") + # Strip the trailing newline marker(s) so Enter can be pressed + # separately. Use suffix removal rather than ``str.rstrip("\\n")``, + # because ``rstrip`` treats its argument as a set of characters and + # would also eat real trailing ``n``/``\`` characters from the + # content (e.g. "Login\n" -> "Logi", "Run\n" -> "Ru"). + while stripped_content.endswith("\\n"): + stripped_content = stripped_content[:-2] + while stripped_content.endswith("\n"): + stripped_content = stripped_content[:-1] if content: if input_swap: pyautogui_code += f"\nimport pyperclip"