Stop mutating message_history with stale device state and screenshots.
Instead, deepcopy the history before each LLM call and inject current
+ previous device state and screenshot into the disposable copy.
- FastAgent/CodeActAgent: add state rotation, deepcopy, and 2-state
injection matching the manager's pattern
- ManagerAgent: rename previous state tag to <previous_device_state>
Add DROIDRUN_STREAM_SCREENSHOTS env var (disabled by default) to enable
ScreenshotEvent emission without trajectory disk I/O. Screenshots can
now be streamed via the event system independently of TrajectoryWriter
serialization, PNG writes, and GIF generation.
- Wrap response.read() in screenshot() to catch SDK disconnect errors
that occur after the initial request succeeds but during body read
- Remove try/except around get_date() in start_handler — if the device
can't respond at startup, fail immediately instead of silently degrading
Add DeviceDisconnectedError to the driver layer so cloud device
disconnects (409/timeout/connection errors) propagate cleanly instead
of crashing the workflow or being silently swallowed.
- CloudDriver: add max_retries=4 (~7.5s backoff), wrap all SDK calls
via _call() helper that translates ConflictError/APIConnectionError/
APITimeoutError into DeviceDisconnectedError, remove 7 silent
try/except blocks that returned fake values on failure
- StateProvider: let DeviceDisconnectedError bypass retry loop; fix
pre-existing bug where `from last_error` used str instead of exception
- DroidAgent: catch DeviceDisconnectedError in run_manager and
execute_task, finalize with success=False and clear reason
- FastAgent/CodeActAgent: re-raise DeviceDisconnectedError from
screenshot and get_state try/except blocks
- ManagerAgent/StatelessManagerAgent: re-raise DeviceDisconnectedError
from screenshot; use shared_state.device_date (fetched once at
startup) instead of calling get_date() every step
Allow custom UIState subclasses to be injected via ui_cls param,
enabling external stealth implementations without subclassing
the provider. Bump version to 0.5.0.dev4.
Replaces the old per-action event classes (TapActionEvent, SwipeActionEvent,
etc.) with a single generic ToolExecutionEvent streamed via llama-index
workflow Context after each tool execution.
- Add StealthDriver (curved Bezier swipes via motionevent, word-by-word typing)
- Add StealthUIState (randomized tap coords within element safe zone)
- Add stealth flag to AndroidStateProvider and ToolsConfig
- Wire stealth mode in DroidAgent.start_handler
- Delete old StealthAdbTools (depended on deleted AdbTools base class)
- Move mobilerun-sdk from optional extra to core dependencies
- Move `from mobilerun import AsyncMobilerun` to top of cloud.py
- Export CloudDriver from driver __init__
- Set requires-python to >=3.11,<3.14
- Add IOSDriver (httpx-based async HTTP REST driver)
- Add IOSStateProvider (parses iOS a11y tree into UIState)
- Branch DroidAgent.start_handler on config.device.platform
- Update exports in driver/, ui/, and ios/ __init__ files
Known TODOs (pre-existing iOS limitations, not regressions):
- input_text clear param ignored
- press_key only maps HOME (no BACK/ENTER on iOS)
- get_date not available
- drag not implemented
- Screen dimensions inferred from element bounds
- bundle_identifiers not configurable from config yet
- Move imports to top of file in droid_agent, tools_agent, manager_agent,
state, app_starter_workflow
- Fix Manager agent to exclude standard atomic actions from custom_tools_descriptions
(was redundantly listing click, swipe, etc. alongside actual custom tools)
- Fix focused_text undefined reference in both manager agents
- Fix unused variable in codeact_agent
- Add circular import guard comment in android driver
- Fix undefined `focused_text` variable in both manager agents (should be
`self.shared_state.focused_text`)
- Remove unused `goal` variable in CodeActAgent
- Reject whitespace-only strings in `DroidAgentState.remember()`
- Fix `raise` without `from` in AndroidStateProvider
- Clean up import sorting and unused import
Remove Tools/AdbTools/StealthAdbTools/IOSTools classes, MacroEvent
hierarchy, and legacy helper functions now replaced by DeviceDriver,
ToolRegistry, and RecordingDriver. Macro data flows from
RecordingDriver.log through trajectory writer as plain dicts.
Phases 1-3 of the tooling refactor:
- Add DeviceDriver, AndroidDriver, RecordingDriver for clean device I/O
- Add UIState, StateProvider for element resolution and state fetching
- Add ActionContext, ActionResult, ToolRegistry for tool dispatch
- Refactor all action functions to use ctx: ActionContext
- Update DroidAgent start_handler to create driver/registry/action_ctx
- Update executor, FastAgent, CodeActAgent to use registry.execute()
- Update manager agents to use action_ctx/state_provider
- Rename DroidAgentState fields: memory→manager_memory, manager_answer→answer
- Add fast_memory, finished, success fields to DroidAgentState
- Delete legacy v1 and v2 docs
- Create v5 docs as new latest version
- Configure Mintlify navigation.versions for v3/v4/v5 switcher
- Replace all CodeAct references with FastAgent (XML tool-calling)
- Update internal event types to match FastAgent implementation
- Fix all cross-references to point to /v5/
- Remove v3→v4 migration guide from v5
- Update SKILL.md and gen-docs-sdk-ref.sh to target v5