1003 Commits

Author SHA1 Message Date
johnmalek312 fdf580d5b6 fix(external): harden external agent loading and add docs
- Allow agents with no config section (use DEFAULT_CONFIG or env vars)
- Validate run() is async, reject sync functions with clear error
- Wrap list_agents() at CLI import to prevent crashes on scan failure
- Simplify migration to only remove example entries
- Add README.md with full contract, AdbDevice API, and setup guide
2026-03-25 22:09:46 +11:00
johnmalek312 eb047e7c38 refactor!: redesign external agent system to use raw ADB access
External agents now receive a raw async_adbutils.AdbDevice instead of
internal DroidRun tools. This makes them fully self-contained — zero
imports from droidrun, just copy-paste a file or folder and it works.

- Remove mai_ui and autoglm agents (depended on internals)
- Pass raw AdbDevice directly, skip Portal/driver/registry setup
- Add --agent CLI flag with dynamic discovery from external/ dir
- Add list_agents() for runtime agent enumeration
- Add config migration v005 to clean up legacy agent entries
- Update config_example.yaml to remove old agent references

BREAKING CHANGE: external agent run() signature changed from
(tools, instruction, config, max_steps) to
(device, instruction, config, max_steps) where device is an
async_adbutils.AdbDevice
2026-03-25 21:42:28 +11:00
johnmalek312 e3cc1ec154 chore: update default model to gemini-3.1-flash-lite-preview
Replace all gemini-2.5-pro and gemini-2.5-flash defaults with
gemini-3.1-flash-lite-preview and drop the models/ prefix from
model names.
2026-03-23 17:52:49 +11:00
johnmalek312 1fee3be384 refactor!: remove CodeActAgent, ScripterAgent, and TextManipulatorAgent
Remove three deprecated agents and all associated dead code:
- CodeActAgent (Python code-gen + exec)
- ScripterAgent (off-device Python execution)
- TextManipulatorAgent (text field editing via code-gen)

Only FastAgent (XML tool-calling) remains as the direct-execution
agent. Rename agent/codeact/ to agent/fast_agent/ and
config/prompts/codeact/ to config/prompts/fast_agent/.

Also removes: SimpleCodeExecutor, SafeExecutionConfig,
extract_code_and_thought, code_checker, and all related config
fields (codeact, scripter, text_manipulator LLM profiles).

Adds v004 config migration to strip removed keys and update
prompt paths in existing user configs.

BREAKING CHANGE: `ScripterConfig`, `SafeExecutionConfig`, and
`codeact` config field are removed. The `text_manipulator` and
`scripter` LLM profiles are no longer used. Users with custom
imports of these classes or configs referencing removed fields
will need to update their code.
2026-03-23 17:49:54 +11:00
johnmalek312 98b762d06a chore: sync uv lockfile for v0.5.1 2026-03-13 04:27:11 +11:00
johnmalek312 5c9de16d8f chore: bump version to 0.5.1 v0.5.1 2026-03-13 04:26:10 +11:00
johnmalek312 baa19dfe60 Merge pull request #289 from droidrun/reliablity
fix(state): improve state retrieval reliability with retries and a11y recovery
2026-03-13 04:24:38 +11:00
johnmalek312 7d1f03979c fix(state): correct recovery timing, consistent typing, and cleaner logging
- Set _RECOVERY_AFTER_ATTEMPT to 5 so recovery fires after ~11s as intended
- Use Optional[List[float]] consistently instead of mixing old/new style hints
- Simplify nested f-string in retry warning log
- Update docstring to reflect actual fallback behavior for short delay lists
2026-03-13 04:24:04 +11:00
johnmalek312 98290d23cb Merge pull request #288 from droidrun/feat/stealth-passthrough
Add stealth passthrough to CloudDriver
2026-03-13 04:19:15 +11:00
johnmalek312 534cd451d5 fix(state): add TCP server recovery to state retrieval retry logic
Restart Portal's TCP socket server alongside the accessibility service
during mid-retry recovery. This handles the case where the TCP server
crashes mid-run, causing state requests to fail on both TCP and content
provider paths.
2026-03-13 04:17:50 +11:00
johnmalek312 f53bb933f8 fix(state): improve state retrieval reliability with retries and a11y recovery
Extract retry logic into fetch_state_with_retry() helper with 7 attempts,
increasing backoff (1-10s, ~29s total), and mid-retry accessibility service
restart after ~11s of failures. Fixes intermittent "Portal returned error:
Unknown error" by logging the full Portal response dict.
2026-03-13 04:13:05 +11:00
johnmalek312 d57b004336 feat(cloud): add stealth flag to CloudDriver for devices-api passthrough
CloudDriver.__init__ accepts stealth=True which passes
{"stealth": true} via extra_body on tap, swipe, and input_text
calls to devices-api. No stealth logic added — purely passthrough.
2026-03-13 02:19:27 +11:00
sleynsol e32bf1a9fc updated README 2026-03-11 14:55:37 +01:00
johnmalek312 4f1a39f548 chore: bump version to 0.5.1.dev3 v0.5.1.dev3 2026-03-11 05:02:06 +11:00
johnmalek312 f8db6f9324 feat(driver): add stealth and wpm params to input_text for cloud devices 2026-03-11 04:58:06 +11:00
johnmalek312 290d7b12ab chore: bump version to 0.5.1.dev2 v0.5.1.dev2 2026-03-11 03:41:56 +11:00
johnmalek312 f3df299547 fix: consistent Screenshot → UI state emission order across all agents
- Manager and StatelessManager now emit ScreenshotEvent before
  RecordUIStateEvent, matching FastAgent/CodeAct ordering
- DroidAgent finalize step now emits RecordUIStateEvent after the
  final screenshot so every screenshot has a paired UI state
2026-03-11 03:39:38 +11:00
johnmalek312 d6d59761a6 chore: bump version to 0.5.1.dev1 in pyproject.toml v0.5.1.dev1 2026-03-10 14:48:11 +11:00
johnmalek312 2aa0d4e303 Merge pull request #283 from droidrun/feat/external-user-message-injection
Feat/external user message injection
2026-03-10 01:12:27 +11:00
johnmalek312 6899d31bf3 fix: validate empty messages and clean up QueuedUserMessage import 2026-03-10 00:27:07 +11:00
johnmalek312 c5bc5e70f9 Merge pull request #279 from hanxi/fix/circular-import
fix: resolve circular import conflict with external mcp package
2026-03-10 00:08:14 +11:00
johnmalek312 8d0eea0349 fix: per-message XML tags and remove dead event classes 2026-03-09 21:16:15 +11:00
johnmalek312 21e594673f fix: unify external_user_message tag format across agents 2026-03-09 19:21:26 +11:00
johnmalek312 1f9998752c chore: remove verbose comments and delete test_external_message.py 2026-03-09 18:56:57 +11:00
johnmalek312 cac887c8fd fix: replace workflow step with direct method for message injection
WorkflowValidationError: llama-index validates that all consumed events
are produced by some step. ExternalUserMessageEvent is external-only,
so the @step approach fails validation.

Replace with DroidAgent.send_user_message(text) -> QueuedUserMessage.
Directly queues on shared state, no event routing needed. Drain points
in FastAgent and Manager still emit Applied/Dropped stream events.
2026-03-09 18:41:14 +11:00
johnmalek312 5aeae4789e feat: add message IDs, completion guards, and dropped message handling
- QueuedUserMessage dataclass with uuid4 ID and queued_at_step
- Events now carry message IDs for end-to-end tracking
- ExternalUserMessageDroppedEvent for max-steps scenario
- FastAgent complete() with pending messages: reset and continue loop
  so LLM sees its own complete() result alongside the user's message
- Manager request_accomplished with pending messages: loop back to
  ManagerInputEvent instead of finalizing
- Max steps: drain queue, emit DroppedEvent, finalize as normal
- workflow_completed flag on shared state, guarding queue_user_message
- Fix device-state injection bug: merge external messages into tool
  results user message instead of appending separate ChatMessages
2026-03-09 18:09:19 +11:00
johnmalek312 039b76965b feat: add mid-run external user message injection
Allow callers to inject user messages into a running DroidAgent via
handler.send_event(ExternalUserMessageEvent(message="...")).

Messages are queued in shared state and drained at safe checkpoints:
- FastAgent: after tool results, before next LLM call
- ManagerAgent: merged into synthesized user turn in prepare_context

Adds ExternalUserMessageEvent, QueuedEvent, and AppliedEvent for
observability. Updates FastAgent and Manager system prompts to
instruct the LLM to honor mid-execution user corrections.
2026-03-09 17:45:29 +11:00
涵曦 d0fb29c73f fix: resolve circular import conflict with external mcp package 2026-03-05 20:08:06 +08:00
johnmalek312 3260801767 chore: black formatter 2026-03-05 02:45:50 +11:00
johnmalek312 91d4217f1c Merge pull request #272 from akhilkedia/bugfix_switch
Bugfix for adding checked stated to Formatted a11y tree
2026-03-05 02:41:21 +11:00
sleynsol 7aa647a755 updated README 2026-03-03 10:55:20 +01:00
johnmalek312 8c53a5682a docs: make v5 the default docs version 2026-03-02 14:34:16 +11:00
johnmalek312 1e4f544b7e chore: bump version to 0.5.0 v0.5.0 2026-03-02 13:08:04 +11:00
johnmalek312 ed92367599 docs: fix inconsistencies across v4/v5 documentation 2026-03-02 13:07:25 +11:00
johnmalek312 434c6927e4 feat: auto-setup Portal APK before each run 2026-02-28 11:04:09 +11:00
johnmalek312 7319b63a8d chore: bump version to 0.5.0.dev7 v0.5.0.dev7 2026-02-27 18:21:15 +11:00
johnmalek312 bc4a818cac Merge pull request #273 from droidrun/thinking
Preserve thinking tokens & ephemeral state injection
2026-02-27 18:19:56 +11:00
johnmalek312 fe71359e73 feat: ephemeral 2-state injection via deepcopy for all agents
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>
2026-02-27 17:49:23 +11:00
johnmalek312 23a29d12b0 feat: preserve thinking tokens 2026-02-27 17:27:50 +11:00
Akhil Kedia 497c4145e8 Bugfix for adding checked stated to Formatted a11y tree
Currently the formatted tree removed all information about the checked/enabled state of switches/buttons/toggles.
This causes droidrun (without vision) to incorrectly toggle switches as it cannot know if they are already checked.

This PR adds an isChecked=True/False field for checkable nodes.

Signed-off-by: Akhil Kedia <16665267+akhilkedia@users.noreply.github.com>
2026-02-27 10:41:16 +09:00
johnmalek312 0fa696abdd chore: bump version to 0.5.0.dev6 v0.5.0.dev6 2026-02-20 23:22:58 +11:00
johnmalek312 89df59aa18 feat: decouple screenshot streaming from trajectory persistence
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.
2026-02-20 23:22:17 +11:00
johnmalek312 e1eb4f7103 chore: bump version to 0.5.0.dev5 v0.5.0.dev5 2026-02-20 20:05:07 +11:00
johnmalek312 e7ec67e38f Merge pull request #271 from droidrun/error_handling
feat: graceful device disconnect handling with DeviceDisconnectedError
2026-02-20 18:59:29 +11:00
johnmalek312 634bb403d0 fix: reuse _call() for screenshot response.read() instead of inline catch 2026-02-20 18:58:27 +11:00
johnmalek312 c205ec49f4 fix: cover screenshot response.read() disconnect and crash on get_date failure
- 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
2026-02-20 18:45:55 +11:00
johnmalek312 edb55c99c3 feat: graceful device disconnect handling with DeviceDisconnectedError
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
2026-02-20 18:22:35 +11:00
sleynsol 5bf65650ea docs: updated logo 2026-02-19 12:03:24 +01:00
johnmalek312 0cd2e3a692 feat: add ui_cls parameter to AndroidStateProvider
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.
v0.5.0.dev4
2026-02-17 17:55:56 +11:00
johnmalek312 6047db18bb chore: increment project version to 0.5.0.dev3 v0.5.0.dev3 2026-02-17 15:53:21 +11:00