Skip to content

DRO-722: implement mobileruntools#238

Merged
sleynsol merged 12 commits intomainfrom
timo/dro-722-implement-mobileruntools
Dec 17, 2025
Merged

DRO-722: implement mobileruntools#238
sleynsol merged 12 commits intomainfrom
timo/dro-722-implement-mobileruntools

Conversation

@Timo972
Copy link
Copy Markdown
Collaborator

@Timo972 Timo972 commented Dec 17, 2025

No description provided.

@Timo972 Timo972 requested a review from sleynsol December 17, 2025 10:45
@claude
Copy link
Copy Markdown

claude Bot commented Dec 17, 2025

PR Review: DRO-722 - Implement MobileRunTools

Overview

This PR introduces MobileRunTools, a new cloud-based device interaction tool that integrates with the MobileRun API. The implementation follows the existing Tools abstract base class pattern and adds proper exports.


Code Quality and Best Practices

✅ Strengths

  1. Good code structure: The implementation follows the existing patterns from AdbTools and IOSTools closely
  2. Proper abstraction: Correctly implements the Tools interface
  3. Comprehensive docstrings: Methods like remember() and _extract_element_coordinates_by_index() have excellent documentation
  4. Consistent error handling pattern: Uses try-except blocks consistently across methods
  5. Good use of caching: Implements proper caching for UI elements and tree data
  6. Proper exports: Updates to __init__.py files ensure the new class is properly exported

⚠️ Areas for Improvement

1. Error Handling & Logging Inconsistency

Issue: The code uses print() statements instead of the already imported logger in multiple places.

Lines with print() instead of logger:

  • droidrun/tools/cloud.py:86, 98, 117, 125, 141, 147, 152, 167, 182, 195, 208

Recommendation: Replace all print(f"Error: {str(e)}") with logger.error(f"Error: {str(e)}") for consistency.

2. Inconsistent Return Types

Issue: Several methods have inconsistent return types that don't match their type hints.

Examples:

  • tap_by_index() (line 91): Returns str per type hint but returns bool (True/False)
  • input_text() (line 129): Returns str per type hint but returns bool

3. Unused Import

Issue: Line 2 imports uuid but it's never used in the code.

4. Debug Logging in Production Code

Issue: app_starter_workflow.py:97 contains a debug log statement that should be removed:

logger.info(self.tools.__class__.__class__)

Potential Bugs or Issues

🐛 Critical Issue: Incomplete API Implementation

Lines 125-126, 147-148, 152-153: Three required abstract methods are not implemented:

  • drag() - Returns False with error message
  • back() - Returns error string
  • press_key() - Returns error string

Impact: These incomplete implementations violate the Tools interface contract and could cause runtime issues.

Recommendation: Either implement these methods properly, document why they can't be implemented, or consider making them optional in the base class.

🔍 Type Safety Issue

Issue: The get_state() method (line 57) returns a 4-tuple, but the base class signature expects Dict[str, Any].


Performance Considerations

✅ Good Practices

  1. Proper caching: UI elements, raw tree, and filtered tree are all cached
  2. Reasonable timeout: 10-second timeout on AsyncMobilerun client
  3. Memory management: The remember() method limits memory to 10 items

Security Concerns

⚠️ Moderate Issues

1. API Key Handling

Issue: The API key is stored in plain text as an instance variable (line 29).

Recommendation: Consider integrating with the credential_manager pattern used in AdbTools.

2. SSH Git Dependency

Issue: pyproject.toml:178 uses an SSH git URL for the mobilerun-sdk dependency on the "next" branch.

Concerns:

  • Requires SSH keys for installation
  • Using "next" branch creates reproducibility issues
  • Private repository may cause issues for users without access

3. Broad Exception Catching

Issue: All exception handlers use except Exception as e: which catches too broadly.


Test Coverage

❌ Critical Gap

Issue: No tests found for the new MobileRunTools class.

Recommendation: Add comprehensive tests covering unit tests, integration tests, error handling, and edge cases.


Summary

This is a solid first implementation that follows existing patterns well. The main concerns are:

Must Fix:

  • Remove debug logging line (app_starter_workflow.py:97)
  • Replace print() with logger.error() throughout
  • Fix return type inconsistencies or update type hints
  • Remove unused uuid import

Should Fix:

  • Add comprehensive test coverage
  • Implement or properly document the incomplete methods
  • Fix get_state() return type mismatch
  • Consider security recommendations for API key handling

Overall Assessment: Good implementation quality, but needs tests and some cleanup before merging.

@claude
Copy link
Copy Markdown

claude Bot commented Dec 17, 2025

PR Review: DRO-722 - MobileRunTools Implementation

Summary

This PR adds a new MobileRunTools class to provide cloud-based device control through the MobileRun API. Overall, the implementation is solid and follows the existing codebase patterns well. However, there are several areas that need attention before merging.


Critical Issues

1. Inconsistent Error Handling 🔴

Location: droidrun/tools/cloud.py throughout

The error handling is inconsistent with the rest of the codebase:

  • Using print() instead of logger: Lines 92, 104, 123, 131, 147, 153, 158, 173, 188, 201, 214
  • Catching bare Exception: This is too broad and can mask programming errors
  • Recommendation: Follow the pattern used in adb.py and ios.py where logger.error() or logger.warning() is used

2. Type Inconsistencies in Return Values 🔴

Location: droidrun/tools/cloud.py:97, 135, 152, 157

Methods have incorrect return type annotations - tap_by_index() and input_text() are annotated as returning str but return bool. back() and press_key() return strings instead of bool.

Impact: This breaks the contract defined in the Tools abstract base class and can cause type checking failures.

3. Unimplemented Methods Returning Inconsistent Values 🟡

Location: droidrun/tools/cloud.py:128-132, 152-159

drag() returns False (bool) but back() and press_key() return error strings. Should raise NotImplementedError for clarity.


Security Concerns

4. API Key Handling 🟡

Location: droidrun/tools/cloud.py:29-34

  • When user_id is provided, api_key is set to empty string - is this intentional?
  • No validation that api_key is provided when user_id is not set
  • The commit message mentions "auto load api key from MOBILERUN_CLOUD_API_KEY if not provided" but this logic is missing

Recommendation: Add environment variable fallback


Code Quality Issues

5. Debug Logging Left in Code 🟡

Location: droidrun/agent/oneflows/app_starter_workflow.py:96-97

logger.info(self.tools.__class__.__class__) appears to be debug code and should be removed.

6. Missing Docstrings 🟡

Several important methods lack docstrings: get_state(), get_date(), tap_by_index(), swipe(), input_text(), take_screenshot(), list_packages(), get_apps()

7. Unsafe Generic Exception Handling 🟡

Using except Exception as e: throughout catches too much. Consider catching specific exceptions like httpx.HTTPError, httpx.TimeoutException.


Performance Considerations

8. Hardcoded Timeout 🟡

Location: droidrun/tools/cloud.py:30, 33

Timeout is hardcoded to 10 seconds. Make timeout configurable via constructor parameter with 10.0 as default.


Test Coverage

9. Missing Tests 🔴

This PR adds 349 lines of new code without any tests. Recommendations:

  • Add unit tests for MobileRunTools class
  • Mock the AsyncMobilerun client to test error handling
  • Test coordinate extraction logic

Documentation

10. Missing Documentation Page Configuration 🟡

While IOSTools and AdbTools have documentation page configurations in pyproject.toml, MobileRunTools is missing.


Positive Aspects ✅

  1. Good code structure - Follows existing patterns in AdbTools and IOSTools
  2. Proper use of abstract base class - Implements Tools interface correctly
  3. Memory functionality - Nice addition for context retention
  4. Comprehensive element extraction - Good error messages with available indices
  5. Cache management - Proper caching of tree data and UI elements
  6. Type hints - Good use of type annotations (except for noted inconsistencies)

Recommendations Summary

Must Fix Before Merge:

  1. Replace all print() statements with logger.error() or logger.warning()
  2. Fix return type annotations to match actual return values
  3. Handle unimplemented methods consistently (raise NotImplementedError)
  4. Remove debug logging
  5. Add API key environment variable fallback

Should Fix:
6. Add docstrings to public methods
7. Make timeout configurable
8. Add unit tests
9. Catch specific exceptions rather than bare Exception
10. Add documentation page configuration


Conclusion

The implementation is functionally solid and well-structured, but needs polish in error handling, type consistency, and testing before merge. The main concerns are around production-readiness (proper logging, error handling) and maintainability (tests, documentation).

Estimated effort to address: 2-4 hours

Please address the critical issues before merging. Happy to re-review once updated!

@claude
Copy link
Copy Markdown

claude Bot commented Dec 17, 2025

Pull Request Review: DRO-722 - Implement MobileRunTools

Summary

This PR introduces MobileRunTools, a new cloud-based tools implementation for mobile device interaction via the MobileRun API. Overall, the implementation is solid and follows the existing patterns in the codebase. However, there are several areas that need attention before merging.


🔴 Critical Issues

1. Debug Logging Left in Production Code (droidrun/agent/oneflows/app_starter_workflow.py:96-97)

logger.info(f"Starting app {package_name}")
logger.info(self.tools.__class__.__class__)  # ← This appears to be debug code

Issue: self.tools.__class__.__class__ looks like a debugging statement and should be removed or fixed.

Recommendation: Remove line 97 entirely. If you need to log the class type, use logger.debug(f"Tools type: {self.tools.__class__.__name__}").

2. Inconsistent Package Name Field (droidrun/agent/oneflows/app_starter_workflow.py:61)

f"- {app['label']} (package: {app['package_name'] if 'package_name' in app else app['package']})"

Issue: This suggests inconsistency in the API response structure between AdbTools (uses package) and MobileRunTools (uses package_name).

Recommendation: Normalize the field name in MobileRunTools.get_apps() to use package to match the existing interface, or update the Tools abstract class to document this difference.

3. Security Concern: API Key vs User ID Authentication (droidrun/tools/cloud.py:29-33)

if not user_id:
    self.mobilerun = AsyncMobilerun(api_key=api_key, base_url=base_url, timeout=10.0)
else:
    self.mobilerun = AsyncMobilerun(
        api_key="", base_url=base_url, timeout=10.0, default_headers={"X-User-ID": user_id}
    )

Issue: Using an empty API key with just a User-ID header is potentially insecure and unclear.

Recommendation: Document this authentication pattern clearly or consider using a more secure approach. If this is for testing/development, add a comment explaining the use case.


⚠️ Major Issues

4. Error Handling with print() Instead of Logging (droidrun/tools/cloud.py:Multiple locations)

Throughout the file, errors are printed but the function continues:

except Exception as e:
    print(f"Error: {str(e)}")
    return False

Issue: This pattern is inconsistent with AdbTools which uses logging and raises exceptions or returns descriptive error messages.

Recommendation: Use the logger consistently:

except Exception as e:
    logger.error(f"Error in tap_by_index: {str(e)}")
    return f"Error: {str(e)}"

5. Incomplete Implementation Markers (droidrun/tools/cloud.py:129, 151, 153)

async def drag(...) -> bool:
    print("Error: Drag is not implemented yet")
    return False

async def back(self) -> str:
    print("Error: Back is not implemented yet")
    return "Error: Back is not implemented yet"

Issue: These unimplemented methods return success indicators (False/str) but don't actually raise NotImplementedError.

Recommendation: Either implement these methods or raise NotImplementedError consistently like in AdbTools:

raise NotImplementedError("Drag is not implemented for cloud devices yet")

6. Type Hint Inconsistency (droidrun/tools/cloud.py:22-23)

tree_filter: TreeFilter = None,
tree_formatter: TreeFormatter = None,

Issue: Using None as default but not marking the type as Optional[TreeFilter].

Recommendation: Follow PEP 484:

tree_filter: TreeFilter | None = None,
tree_formatter: TreeFormatter | None = None,

7. Missing Dependency Version Pinning (pyproject.toml:82)

mobilerun = [
    "mobilerun-sdk",
]

Issue: The SDK is pulled from a git branch without version pinning, which could lead to breaking changes.

Recommendation: Either:

  • Use a specific commit hash
  • Use a tagged version when available
  • Document this is for development/testing only

🟡 Minor Issues / Improvements

8. Duplicate Code in Element Coordinate Extraction (droidrun/tools/cloud.py:286-348)

The _extract_element_coordinates_by_index method has ~70 lines of duplicated logic from AdbTools.

Recommendation: Consider extracting this to a shared utility function in the Tools base class to reduce duplication and improve maintainability.

9. Inconsistent Return Types (droidrun/tools/cloud.py:105, 124, 147)

Some methods return bool, some return str, for similar operations.

Recommendation: Standardize return types to match the Tools interface. Most tools in AdbTools return descriptive strings rather than booleans.

10. Magic Numbers (droidrun/tools/cloud.py:27)

timeout=10.0

Recommendation: Extract to a constant:

MOBILERUN_DEFAULT_TIMEOUT = 10.0

11. Missing Docstrings (droidrun/tools/cloud.py:Various methods)

Several methods lack docstrings (e.g., get_state, get_date, get_apps).

Recommendation: Add comprehensive docstrings following the pattern in AdbTools.py.

12. Import Order (droidrun/init.py:5-32)

The imports were reorganized alphabetically within sections, which is good practice.

Note: This is a positive change and improves code organization.


✅ Positive Aspects

  1. Good Architecture: The implementation correctly extends the Tools abstract class
  2. Async/Await: Properly implements async patterns throughout
  3. Caching: Implements element caching similar to existing tools
  4. Memory System: Includes the remember() and get_memory() methods for context management
  5. Error Messages: Good use of descriptive error messages in coordinate extraction
  6. Type Hints: Generally good use of type annotations

📋 Test Coverage

Critical: No tests were added for the new MobileRunTools class.

Recommendation: Add unit tests covering:

  • Authentication (api_key vs user_id modes)
  • Element coordinate extraction edge cases
  • API error handling
  • State retrieval and caching
  • Screenshot functionality

🔒 Security Considerations

  1. API Key Handling: Ensure API keys are not logged or exposed in error messages
  2. Input Validation: The input_text method should validate/sanitize text input
  3. URL Validation: The base_url parameter should be validated to prevent SSRF

📚 Documentation Needs

  1. Add docstring to MobileRunTools class explaining when to use it vs AdbTools
  2. Document the authentication modes (api_key vs user_id)
  3. Add example usage in README or docs
  4. Document which methods are not yet implemented

Recommended Actions Before Merge

Must Fix:

  1. Remove/fix the debug logging at line 97 in app_starter_workflow.py
  2. Normalize the package_name vs package field inconsistency
  3. Replace print() statements with proper logging
  4. Use NotImplementedError for unimplemented methods
  5. Fix type hints to use Optional or | None

Should Fix:
6. Add comprehensive docstrings
7. Add test coverage
8. Document authentication patterns
9. Consider extracting duplicate coordinate extraction logic

Nice to Have:
10. Extract magic numbers to constants
11. Standardize return types across methods


Overall Assessment

This is a solid foundation for cloud-based device control. The implementation follows good patterns from the existing codebase, but needs polish before merging. Focus on the "Must Fix" items and at least basic test coverage.

Estimated effort to address: 2-4 hours

Let me know if you need clarification on any of these points!

@claude
Copy link
Copy Markdown

claude Bot commented Dec 17, 2025

PR Review: DRO-722 - Implement MobileRunTools

Summary

This PR introduces MobileRunTools, a new cloud-based implementation of the Tools abstract class that uses the MobileRun API to control mobile devices remotely. The implementation adds 349 lines of new code with supporting changes to exports and dependencies.

Code Quality & Best Practices

Strengths

  • Well-structured class hierarchy: Properly extends the Tools abstract class
  • Good error handling: Most methods use try-except blocks to handle exceptions gracefully
  • Comprehensive functionality: Implements all required abstract methods from the base class
  • Good documentation: Methods have clear docstrings explaining parameters and return values
  • Consistent patterns: Follows the same patterns as AdbTools (filters, formatters, caches)

Issues Found

1. Inconsistent Error Handling (Medium Priority)

Location: Multiple methods in droidrun/tools/cloud.py

Methods use print() for error logging instead of the logger (lines 92, 104, 123, 131, 147, 153, 158, 173, 188, 201, 214)

Recommendation: Use logger.error() consistently for better log management

2. Type Inconsistencies (Medium Priority)

Location: droidrun/tools/cloud.py

Several methods have incorrect return type annotations:

  • tap_by_index() (line 97): Returns bool but annotated as -> str
  • input_text() (line 135): Returns bool but annotated as -> str
  • back() (line 152): Returns str but should return bool
  • press_key() (line 157): Returns str but should return bool

3. Incomplete Abstract Methods (High Priority)

Location: droidrun/tools/cloud.py:127-132, 152-159

Three methods return hardcoded error messages instead of actual implementations:

  • drag() - Line 131
  • back() - Line 153
  • press_key() - Line 158

Recommendation: Either implement these methods or raise NotImplementedError to make it explicit

4. Debug Code Left In (Low Priority)

Location: droidrun/agent/oneflows/app_starter_workflow.py:97

Line 97 contains debug code that should be removed: logger.info(self.tools.class.class)

5. Inconsistent API Key Handling (Medium Priority - Security)

Location: droidrun/tools/cloud.py:29-34

Concerns:

  • When user_id is provided, the API key is set to an empty string
  • The logic suggests mutual exclusion between api_key and user_id but this isn't validated or documented
  • No validation that at least one authentication method is provided

Recommendation:

  • Add validation to ensure either api_key or user_id is provided
  • Document the authentication strategy in the docstring

6. Package Name Field Inconsistency (Medium Priority)

Location: droidrun/agent/oneflows/app_starter_workflow.py:61

The code handles both package_name and package fields, suggesting API inconsistency. Investigate and standardize.

Test Coverage

Critical Gap: No tests were added for the new MobileRunTools class.

Recommendation: Add unit tests covering:

  • Initialization with different auth methods
  • Each public method
  • Error handling paths
  • Element coordinate extraction logic

Recommendations Summary

High Priority (Must Fix)

  1. Implement or properly handle unimplemented methods
  2. Fix return type annotations
  3. Add unit tests

Medium Priority (Should Fix)

  1. Replace print() with logger.error()
  2. Add authentication validation
  3. Fix package name field inconsistency
  4. Document authentication strategy

Low Priority (Nice to Have)

  1. Remove debug logging
  2. Organize imports per PEP 8
  3. Fix get_memory() async/sync mismatch

Conclusion

This is a solid implementation that follows existing patterns well. The main concerns are incomplete method implementations, type annotation mismatches, and lack of tests. Once these are addressed, this will be a valuable addition to the project.

Overall Assessment: Needs revision before merging.

@sleynsol sleynsol merged commit 9057f17 into main Dec 17, 2025
6 of 8 checks passed
@claude
Copy link
Copy Markdown

claude Bot commented Dec 17, 2025

Pull Request Review: DRO-722 - Implement MobileRunTools

Overview

This PR adds a new MobileRunTools class that provides cloud-based device interaction through the MobileRun SDK. Overall, the implementation follows the existing patterns in the codebase, but there are several areas that need attention.


🔴 Critical Issues

1. Debug Logging Left in Production Code

Location: droidrun/agent/oneflows/app_starter_workflow.py:96-97

logger.info(f"Starting app {package_name}")
logger.info(self.tools.__class__.__class__)

Issue: The second log statement appears to be debug code that was left in by mistake. __class__.__class__ is unusual and likely incorrect.

Recommendation: Remove the second line or fix it to log the intended information.


2. Inconsistent Error Handling

Location: Multiple methods in droidrun/tools/cloud.py

Issue: Error handling is inconsistent:

  • Some methods print to stdout and return False: swipe(), drag(), input_text()
  • Some methods print and return empty values: take_screenshot(), list_packages(), get_apps()
  • Some methods print and return error strings: back(), press_key()

Recommendation:

  • Use consistent error handling across all methods
  • Prefer raising exceptions or logging errors rather than printing to stdout
  • Follow the pattern established in AdbTools and IOSTools

Example:

# Current (inconsistent)
except Exception as e:
    print(f"Error: {str(e)}")
    return False

# Better approach
except Exception as e:
    logger.error(f"Failed to perform swipe: {str(e)}")
    return False

3. Unimplemented Methods Return Error Strings

Location: cloud.py:130, 155, 157

Issue: back() and press_key() return error message strings instead of following the method signature that expects boolean or action results.

Recommendation:

  • Either implement these methods or raise NotImplementedError
  • Keep return types consistent with the abstract base class
async def back(self) -> str:
    raise NotImplementedError("Back navigation not yet supported in MobileRunTools")

async def press_key(self, keycode: int) -> str:
    raise NotImplementedError("Key press not yet supported in MobileRunTools")

⚠️ Important Issues

4. Missing Type Hints in Return Signature

Location: cloud.py:84

async def get_state(self) -> Tuple[str, str, List[Dict[str, Any]], Dict[str, Any]]:

Issue: The base class Tools.get_state() returns Dict[str, Any], but MobileRunTools.get_state() returns a tuple. This violates the Liskov Substitution Principle.

Recommendation: Either:

  1. Update the base class to accommodate both return types
  2. Return a dict matching the base class signature
  3. Rename this method to avoid confusion

5. Security Concern: API Key Handling

Location: cloud.py:30-33

if not user_id:
    self.mobilerun = AsyncMobilerun(api_key=api_key, base_url=base_url, timeout=10.0)
else:
    self.mobilerun = AsyncMobilerun(
        api_key="", base_url=base_url, timeout=10.0, default_headers={"X-User-ID": user_id}
    )

Issue: The authentication logic is unclear. When user_id is provided, the API key is set to an empty string, which may cause issues.

Recommendation:

  • Document the authentication modes more clearly
  • Consider if empty API key is intentional or if validation is needed
  • Add parameter documentation explaining when to use api_key vs user_id

6. Inconsistent Package Field Access

Location: droidrun/agent/oneflows/app_starter_workflow.py:61

f"- {app[\"label\"]} (package: {app[\"package_name\"] if \"package_name\" in app else app[\"package\"]})"

Issue: This change suggests inconsistency in the data structure returned by different Tools implementations. The conditional check is a code smell.

Recommendation:

  • Standardize the field names across all Tools implementations
  • Consider adding a normalization method in the base class
  • Document which field name should be used

💡 Code Quality Improvements

7. Magic Numbers

Location: cloud.py:237

max_memory_items = 10

Recommendation: Extract to a class constant:

MAX_MEMORY_ITEMS = 10

8. Inconsistent Async Method

Location: cloud.py:152, 243

Issue: get_memory() is declared as async but does not await anything. In the base class (tools.py:152), it is also async, but in cloud.py it could be synchronous.

Recommendation: If the method does not need to be async, make it synchronous for better performance. However, keep it async if maintaining consistency with the base class is more important.


9. Missing Docstring Details

Location: Multiple methods in cloud.py

Issue: Some methods lack comprehensive docstrings, especially regarding:

  • What exceptions they might raise
  • Return value meanings (especially False vs error messages)
  • Parameter validation requirements

Recommendation: Add comprehensive docstrings following the pattern in AdbTools


✅ Positive Aspects

  1. Good code reuse: The implementation correctly inherits from Tools and follows established patterns
  2. Comprehensive element coordinate extraction: The _extract_element_coordinates_by_index() method includes good error messages
  3. Memory management: The memory feature includes size limiting to prevent context overflow
  4. Proper caching: UI elements are cached appropriately for performance
  5. Optional dependency handling: The try/except import pattern in __init__.py is good practice

🧪 Test Coverage

Issue: No tests were added for the new MobileRunTools class.

Recommendation: Add unit tests covering:

  • Element coordinate extraction (including error cases)
  • Authentication modes (api_key vs user_id)
  • Error handling in all methods
  • Memory management (add, retrieve, size limiting)
  • State retrieval and caching

📋 Summary

Must Fix Before Merge:

  1. Remove debug logging in app_starter_workflow.py:97
  2. Standardize error handling across all methods
  3. Fix unimplemented method return types

Should Fix:

  1. Resolve get_state() return type inconsistency
  2. Document authentication mechanism
  3. Standardize package field naming

Nice to Have:

  1. Add comprehensive test coverage
  2. Improve docstrings
  3. Extract magic numbers to constants

Overall Assessment

The implementation is functional and follows most of the project's conventions, but needs attention to error handling consistency and some cleanup before merging. The core logic appears sound, and the integration with the existing Tools architecture is well done.

@claude
Copy link
Copy Markdown

claude Bot commented Dec 17, 2025

PR Review: DRO-722 - Implement MobileRunTools

Thank you for this contribution! I've reviewed the implementation of MobileRunTools and related changes. Here's my detailed feedback:


Strengths

  1. Good architectural consistency - The MobileRunTools class properly extends the Tools abstract base and follows the same patterns as AdbTools
  2. Proper optional dependency handling - The try/except import pattern in init.py files is well-implemented, allowing the package to work without the mobilerun SDK installed
  3. Code duplication minimized - The _extract_element_coordinates_by_index helper is reused correctly across methods
  4. Good error messaging - Error messages provide context (e.g., available indices when an element isn't found)

Bugs and Issues

Critical Issues

  1. Inconsistent error handling and return types (droidrun/tools/cloud.py:86-175)

    • Methods mixing print() for errors with returning False or unknown
    • tap_by_index, swipe, input_text, start_app return bool but type hints say str
    • Fix: Use proper logging with logger.error() instead of print(), and make return types consistent
  2. Unimplemented stub methods (droidrun/tools/cloud.py:152-159)

    • back() and press_key() print error messages but are decorated with @Tools.ui_action
    • Fix: Either implement these methods or raise NotImplementedError if they're not supported yet
  3. Debug logging left in production code (droidrun/agent/oneflows/app_starter_workflow.py:97)

    • Line 97 has logger.info(self.tools.class.class) which appears to be debug code
    • Fix: Remove this line
  4. API key security concern (droidrun/tools/cloud.py:29-34)

    • When user_id is provided, api_key is hardcoded to empty string
    • If the API requires authentication, this could expose security issues

Medium Priority Issues

  1. Missing auto-load of API key from environment (droidrun/tools/cloud.py:20)

    • Commit message mentions auto load api key from MOBILERUN_CLOUD_API_KEY but implementation doesn't show this
    • Fix: Add environment variable fallback: api_key = api_key or os.getenv('MOBILERUN_CLOUD_API_KEY')
  2. Generic exception handling (multiple locations)

    • Catching bare Exception in multiple methods hides specific errors
    • Fix: Catch specific exceptions where possible
  3. Inconsistent activity parameter handling (droidrun/tools/cloud.py:165-168)

    • Empty string check if activity == "" is less Pythonic
    • Fix: Use truthiness: act = activity or None

Security Concerns

  1. No input validation - Methods like input_text() don't validate/sanitize the text parameter before sending to API
  2. Timeout hardcoded - 10-second timeout may be too short for some operations, consider making it configurable
  3. No rate limiting - Multiple rapid API calls could hit rate limits without backoff strategy

Performance Considerations

  1. Cache invalidation - clickable_elements_cache is populated in get_state() but never explicitly invalidated. Consider documenting when cache should be refreshed
  2. Redundant API call in input_text - If index != -1, makes two API calls (tap + write). Consider if this is necessary or can be optimized

Test Coverage

Missing tests: No test files were added for the new MobileRunTools class. Recommend adding:

  • Unit tests for _extract_element_coordinates_by_index
  • Integration tests for API interactions (with mocking)
  • Tests for error cases (invalid indices, missing elements, API failures)

Code Quality & Best Practices

  1. Type hints are good - Modern union syntax int | None is used consistently
  2. Docstrings present - Methods like remember() and complete() have good documentation
  3. Missing docstrings - get_state(), get_date(), and several other methods lack docstrings
  4. Inconsistent with base class - Check that return types match the abstract methods in Tools base class

Recommendations

  1. Add environment variable handling as mentioned in commit f4b5f11
  2. Standardize error handling - Use logger instead of print, consistent return types
  3. Add comprehensive tests - At minimum, unit tests for the new class
  4. Document the user_id parameter - When/why should it be used vs api_key?
  5. Consider dependency injection for better testability
  6. Fix the app_starter_workflow.py compatibility - Remove debug logging

Priority Action Items

Before merging, please address:

  1. Fix return type inconsistencies (bool vs str)
  2. Replace print() with logger.error() for error handling
  3. Remove debug logging from app_starter_workflow.py:97
  4. Implement environment variable loading for API key (as mentioned in commit)
  5. Fix unimplemented methods (back(), press_key()) to raise NotImplementedError
  6. Add docstrings to public methods
  7. Consider adding basic tests

Dependency Management

The pyproject.toml changes look good:

  • Optional dependency group for mobilerun
  • Git source properly configured
  • Updated to public SDK repo (commit cbdef6a)

Overall Assessment: This is a solid foundation for MobileRunTools, but needs refinement in error handling, type consistency, and test coverage before merging. The architectural decisions are sound and consistent with the existing codebase.

rejigtian pushed a commit to rejigtian/droidrun that referenced this pull request Apr 14, 2026
…mobileruntools

DRO-722: implement mobileruntools
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants