-
Notifications
You must be signed in to change notification settings - Fork 966
Mobile Agent #265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mobile Agent #265
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request introduces Mobile Agent, a comprehensive Android device automation framework for UFO³. The implementation adds support for mobile devices as a third platform alongside Windows and Linux, enabling cross-platform automation workflows through ADB (Android Debug Bridge) integration.
Key Changes:
- Added MobileAgent with 3-state FSM and 4-phase processing pipeline for Android device automation
- Implemented dual MCP servers (data collection and action) for device interaction via ADB
- Extended platform support from 2 to 3 platforms (Windows, Linux, Mobile)
- Added comprehensive documentation including tutorials, strategies, and command references
Reviewed Changes
Copilot reviewed 52 out of 52 changed files in this pull request and generated 23 comments.
Show a summary per file
| File | Description |
|---|---|
ufo/server/ws/handler.py |
Fixed emoji display issues in WebSocket logs |
ufo/server/services/session_manager.py |
Extended platform support to include 'mobile' |
ufo/server/app.py |
Added 'mobile' to platform choices |
ufo/prompts/third_party/mobile_agent*.yaml |
Added prompt templates and examples for MobileAgent |
ufo/prompter/customized/mobile_agent_prompter.py |
Implemented prompter for mobile-specific prompts |
ufo/module/sessions/platform_session.py |
Added MobileBaseSession class |
ufo/module/sessions/mobile_session.py |
Implemented mobile session management |
ufo/module/session_pool.py |
Extended session pool for mobile sessions |
ufo/client/websocket.py |
Improved WebSocket error handling and logging |
ufo/client/ufo_client.py |
Updated platform documentation |
ufo/client/mcp/http_servers/mobile_mcp_server.py |
Implemented dual MCP servers for Android |
ufo/client/client.py |
Extended platform detection |
ufo/agents/states/mobile_agent_state.py |
Implemented 3-state FSM for MobileAgent |
ufo/agents/processors/strategies/mobile_agent_strategy.py |
Implemented 4-phase processing strategies |
ufo/agents/processors/schemas/target.py |
Fixed rect comment format documentation |
ufo/agents/processors/customized/*.py |
Added MobileAgentProcessor |
ufo/agents/agent/customized_agent.py |
Implemented MobileAgent class |
tests/integration/*.py |
Added integration tests and verification scripts |
tests/aip/test_binary_transfer.py |
Added unit tests for binary transfer |
documents/**/*.md |
Added comprehensive documentation |
galaxy/README*.md |
Updated feature lists for mobile support |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| stdout=asyncio.subprocess.PIPE, | ||
| stderr=asyncio.subprocess.PIPE, | ||
| ) | ||
| stdout, stderr = await proc.communicate() |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable stdout is not used.
| stdout=asyncio.subprocess.PIPE, | ||
| stderr=asyncio.subprocess.PIPE, | ||
| ) | ||
| stdout, stderr = await proc.communicate() |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable stderr is not used.
| """Integration tests for Mobile MCP Servers""" | ||
|
|
||
| @pytest.fixture(scope="class") | ||
| def check_adb_connection(self): |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mixing implicit and explicit returns may indicate an error, as implicit returns always return None.
| def get_prompter( | ||
| self, is_visual: bool, main_prompt: str, example_prompt: str | ||
| ) -> MobileAgentPrompter: |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method requires 4 positional arguments, whereas overridden BasicAgent.get_prompter requires 1.
| def message_constructor( | ||
| self, | ||
| dynamic_examples: List[str], | ||
| dynamic_knowledge: str, | ||
| plan: List[str], | ||
| request: str, | ||
| installed_apps: List[Dict[str, Any]], | ||
| current_controls: List[Dict[str, Any]], | ||
| screenshot_url: str = None, | ||
| annotated_screenshot_url: str = None, | ||
| blackboard_prompt: List[Dict[str, str]] = None, | ||
| last_success_actions: List[Dict[str, Any]] = None, | ||
| ) -> List[Dict[str, Union[str, List[Dict[str, str]]]]]: |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method requires at most 11 positional arguments, whereas overridden AppAgent.message_constructor requires 14.
This method requires at least 7 positional arguments, whereas overridden BasicAgent.message_constructor requires 1.
| ) | ||
| if result.returncode == 0: | ||
| return result.stdout.strip().split("\n")[0] | ||
| except: |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
| ) | ||
| if result.returncode == 0: | ||
| return result.stdout.strip().split("\n")[0] | ||
| except: |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
| ) | ||
| if result.returncode == 0: | ||
| return result.stdout.strip().split("\n")[0] | ||
| except: |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
| """ | ||
| # Implement evaluation logic specific to Mobile sessions | ||
| self.logger.warning("Evaluation not yet implemented for Mobile sessions.") | ||
| pass |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary 'pass' statement.
| """ | ||
| # Implement markdown logging specific to Mobile sessions | ||
| self.logger.warning("Markdown logging not yet implemented for Mobile sessions.") | ||
| pass |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary 'pass' statement.
No description provided.