droidrun 0.3.4__tar.gz → 0.3.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. {droidrun-0.3.4 → droidrun-0.3.6}/.github/workflows/bounty.yml +2 -2
  2. {droidrun-0.3.4 → droidrun-0.3.6}/PKG-INFO +17 -23
  3. {droidrun-0.3.4 → droidrun-0.3.6}/docs/docs.json +1 -1
  4. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/quickstart.mdx +3 -2
  5. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/sdk/droid-agent.mdx +1 -1
  6. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/codeact/codeact_agent.py +16 -3
  7. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/codeact/events.py +3 -0
  8. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/common/events.py +5 -1
  9. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/task_manager.py +10 -0
  10. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/droid/droid_agent.py +137 -84
  11. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/planner/events.py +2 -0
  12. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/planner/planner_agent.py +18 -7
  13. droidrun-0.3.6/droidrun/agent/usage.py +213 -0
  14. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/utils/chat_utils.py +24 -22
  15. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/utils/executer.py +1 -1
  16. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/utils/llm_picker.py +91 -54
  17. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/utils/trajectory.py +256 -154
  18. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/cli/logs.py +4 -1
  19. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/cli/main.py +3 -1
  20. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/portal.py +20 -7
  21. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/telemetry/events.py +1 -1
  22. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/tools/adb.py +99 -167
  23. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/tools/tools.py +0 -1
  24. {droidrun-0.3.4 → droidrun-0.3.6}/pyproject.toml +27 -23
  25. {droidrun-0.3.4 → droidrun-0.3.6}/.github/workflows/publish.yml +0 -0
  26. {droidrun-0.3.4 → droidrun-0.3.6}/.gitignore +0 -0
  27. {droidrun-0.3.4 → droidrun-0.3.6}/CHANGELOG.md +0 -0
  28. {droidrun-0.3.4 → droidrun-0.3.6}/CONTRIBUTING.md +0 -0
  29. {droidrun-0.3.4 → droidrun-0.3.6}/LICENSE +0 -0
  30. {droidrun-0.3.4 → droidrun-0.3.6}/MANIFEST.in +0 -0
  31. {droidrun-0.3.4 → droidrun-0.3.6}/README.md +0 -0
  32. {droidrun-0.3.4 → droidrun-0.3.6}/docs/.generated-files.txt +0 -0
  33. {droidrun-0.3.4 → droidrun-0.3.6}/docs/favicon.png +0 -0
  34. {droidrun-0.3.4 → droidrun-0.3.6}/docs/logo/dark.svg +0 -0
  35. {droidrun-0.3.4 → droidrun-0.3.6}/docs/logo/light.svg +0 -0
  36. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v1/concepts/agent.mdx +0 -0
  37. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v1/concepts/android-control.mdx +0 -0
  38. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v1/concepts/portal-app.mdx +0 -0
  39. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v1/overview.mdx +0 -0
  40. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v1/quickstart.mdx +0 -0
  41. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v2/concepts/agent.mdx +0 -0
  42. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v2/concepts/android-control.mdx +0 -0
  43. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v2/concepts/planning.mdx +0 -0
  44. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v2/concepts/portal-app.mdx +0 -0
  45. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v2/concepts/tracing.mdx +0 -0
  46. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v2/overview.mdx +0 -0
  47. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v2/quickstart.mdx +0 -0
  48. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/concepts/agent.mdx +0 -0
  49. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/concepts/android-tools.mdx +0 -0
  50. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/concepts/models.mdx +0 -0
  51. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/concepts/portal-app.mdx +0 -0
  52. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/guides/cli.mdx +0 -0
  53. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/guides/gemini.mdx +0 -0
  54. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/guides/ollama.mdx +0 -0
  55. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/guides/openailike.mdx +0 -0
  56. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/guides/overview.mdx +0 -0
  57. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/guides/telemetry.mdx +0 -0
  58. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/images/portal_apk.png +0 -0
  59. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/overview.mdx +0 -0
  60. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/sdk/adb-tools.mdx +0 -0
  61. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/sdk/base-tools.mdx +0 -0
  62. {droidrun-0.3.4 → droidrun-0.3.6}/docs/v3/sdk/ios-tools.mdx +0 -0
  63. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/__init__.py +0 -0
  64. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/__main__.py +0 -0
  65. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/__init__.py +0 -0
  66. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/codeact/__init__.py +0 -0
  67. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/codeact/prompts.py +0 -0
  68. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/common/default.py +0 -0
  69. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/__init__.py +0 -0
  70. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/agent_persona.py +0 -0
  71. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/context_injection_manager.py +0 -0
  72. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/episodic_memory.py +0 -0
  73. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/personas/__init__.py +0 -0
  74. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/personas/app_starter.py +0 -0
  75. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/personas/big_agent.py +0 -0
  76. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/personas/default.py +0 -0
  77. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/personas/ui_expert.py +0 -0
  78. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/context/reflection.py +0 -0
  79. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/droid/__init__.py +0 -0
  80. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/droid/events.py +0 -0
  81. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/oneflows/reflector.py +0 -0
  82. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/planner/__init__.py +0 -0
  83. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/planner/prompts.py +0 -0
  84. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/utils/__init__.py +0 -0
  85. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/agent/utils/async_utils.py +0 -0
  86. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/cli/__init__.py +0 -0
  87. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/macro/__init__.py +0 -0
  88. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/macro/__main__.py +0 -0
  89. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/macro/cli.py +0 -0
  90. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/macro/replay.py +0 -0
  91. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/telemetry/__init__.py +0 -0
  92. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/telemetry/tracker.py +0 -0
  93. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/tools/__init__.py +0 -0
  94. {droidrun-0.3.4 → droidrun-0.3.6}/droidrun/tools/ios.py +0 -0
  95. {droidrun-0.3.4 → droidrun-0.3.6}/gen-docs-sdk-ref.sh +0 -0
  96. {droidrun-0.3.4 → droidrun-0.3.6}/setup.py +0 -0
  97. {droidrun-0.3.4 → droidrun-0.3.6}/static/droidrun-dark.png +0 -0
  98. {droidrun-0.3.4 → droidrun-0.3.6}/static/droidrun.png +0 -0
@@ -64,7 +64,7 @@ jobs:
64
64
  eligible) OPT_NAME="📝 Eligible" ;;
65
65
  bounty-official) OPT_NAME="💰 Bounty" ;;
66
66
  claimed) OPT_NAME="🛠️ In Progress" ;;
67
- *) echo "No matching status for $LABEL"; exit 0 ;;
67
+ *) echo "No matching status for $LABEL"; exit 78 ;;
68
68
  esac
69
69
 
70
70
  # extract from JSON map
@@ -131,4 +131,4 @@ jobs:
131
131
  -f proj="${PROJECT_ID}" \
132
132
  -f item="${ITEM_ID}" \
133
133
  -f field="${STATUS_FIELD_ID}" \
134
- -f opt="${OPTION_ID}"
134
+ -f opt="${OPTION_ID}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: droidrun
3
- Version: 0.3.4
3
+ Version: 0.3.6
4
4
  Summary: A framework for controlling Android devices through LLM agents
5
5
  Project-URL: Homepage, https://github.com/droidrun/droidrun
6
6
  Project-URL: Bug Tracker, https://github.com/droidrun/droidrun/issues
@@ -26,32 +26,26 @@ Classifier: Topic :: Software Development :: Testing :: Acceptance
26
26
  Classifier: Topic :: System :: Emulators
27
27
  Classifier: Topic :: Utilities
28
28
  Requires-Python: >=3.11
29
- Requires-Dist: adbutils==2.10.0
30
- Requires-Dist: aiofiles>=23.0.0
31
- Requires-Dist: anthropic>=0.7.0
29
+ Requires-Dist: adbutils>=2.10.2
30
+ Requires-Dist: anthropic>=0.67.0
32
31
  Requires-Dist: apkutils==2.0.0
33
- Requires-Dist: arize-phoenix
34
- Requires-Dist: click>=8.1.0
35
- Requires-Dist: llama-index
36
- Requires-Dist: llama-index-callbacks-arize-phoenix
37
- Requires-Dist: llama-index-llms-anthropic
38
- Requires-Dist: llama-index-llms-deepseek
39
- Requires-Dist: llama-index-llms-google-genai
40
- Requires-Dist: llama-index-llms-ollama
41
- Requires-Dist: llama-index-llms-openai
42
- Requires-Dist: llama-index-llms-openai-like
43
- Requires-Dist: openai>=1.0.0
44
- Requires-Dist: pillow>=10.0.0
45
- Requires-Dist: posthog==6.0.2
46
- Requires-Dist: pydantic>=2.0.0
47
- Requires-Dist: python-dotenv>=1.0.0
48
- Requires-Dist: rich>=13.0.0
32
+ Requires-Dist: llama-index-llms-anthropic>=0.8.6
33
+ Requires-Dist: llama-index-llms-deepseek>=0.2.1
34
+ Requires-Dist: llama-index-llms-google-genai>=0.3.1
35
+ Requires-Dist: llama-index-llms-ollama>=0.7.2
36
+ Requires-Dist: llama-index-llms-openai-like>=0.5.1
37
+ Requires-Dist: llama-index-llms-openai>=0.5.6
38
+ Requires-Dist: llama-index>=0.14.0
39
+ Requires-Dist: openai>=1.107.1
40
+ Requires-Dist: posthog>=6.7.4
41
+ Requires-Dist: pydantic>=2.11.7
42
+ Requires-Dist: rich>=14.1.0
49
43
  Provides-Extra: dev
50
- Requires-Dist: bandit>=1.7.0; extra == 'dev'
44
+ Requires-Dist: bandit>=1.8.6; extra == 'dev'
51
45
  Requires-Dist: black>=23.0.0; extra == 'dev'
52
46
  Requires-Dist: mypy>=1.0.0; extra == 'dev'
53
- Requires-Dist: ruff>=0.1.0; extra == 'dev'
54
- Requires-Dist: safety>=2.0.0; extra == 'dev'
47
+ Requires-Dist: ruff>=0.13.0; extra == 'dev'
48
+ Requires-Dist: safety>=3.2.11; extra == 'dev'
55
49
  Description-Content-Type: text/markdown
56
50
 
57
51
  <picture>
@@ -14,7 +14,7 @@
14
14
  "tab": "Framework",
15
15
  "versions": [
16
16
  {
17
- "version": "0.3.3",
17
+ "version": "0.3.6",
18
18
  "groups": [
19
19
  {
20
20
  "group": "Introduction",
@@ -26,8 +26,9 @@ Before installing DroidRun, ensure you have:
26
26
  - Connected via USB or on the same network (for wireless debugging)
27
27
 
28
28
  ### Install from PyPI
29
+ Use [`uv`](https://docs.astral.sh/uv/getting-started/installation/)
29
30
  ```bash
30
- pip install droidrun
31
+ uv pip install droidrun
31
32
  ```
32
33
 
33
34
  ### Setup the Portal APK
@@ -91,4 +92,4 @@ Now that you've got DroidRun running, you can:
91
92
  - Learn about the [Agent](/v3/concepts/agent)
92
93
  - See supported [LLM providers](/v3/concepts/models)
93
94
  - Discover [Android interactions](/v3/concepts/android-control)
94
- - Learn about the [Portal App](/v3/concepts/portal-app)
95
+ - Learn about the [Portal App](/v3/concepts/portal-app)
@@ -33,7 +33,7 @@ def __init__(
33
33
  reflection: bool = False,
34
34
  enable_tracing: bool = False,
35
35
  debug: bool = False,
36
- save_trajectories: str = "none",
36
+ save_trajectories: str = "none",
37
37
  excluded_tools: List[str] = None,
38
38
  *args,
39
39
  **kwargs
@@ -18,7 +18,8 @@ from droidrun.agent.codeact.events import (
18
18
  TaskThinkingEvent,
19
19
  EpisodicMemoryEvent,
20
20
  )
21
- from droidrun.agent.common.events import ScreenshotEvent
21
+ from droidrun.agent.common.events import ScreenshotEvent, RecordUIStateEvent
22
+ from droidrun.agent.usage import get_usage_from_response
22
23
  from droidrun.agent.utils import chat_utils
23
24
  from droidrun.agent.utils.executer import SimpleCodeExecutor
24
25
  from droidrun.agent.codeact.prompts import (
@@ -182,6 +183,7 @@ class CodeActAgent(Workflow):
182
183
  try:
183
184
  state = self.tools.get_state()
184
185
  await ctx.set("ui_state", state["a11y_tree"])
186
+ ctx.write_event_to_stream(RecordUIStateEvent(ui_state=state["a11y_tree"]))
185
187
  chat_history = await chat_utils.add_ui_text_block(
186
188
  state["a11y_tree"], chat_history
187
189
  )
@@ -202,11 +204,17 @@ class CodeActAgent(Workflow):
202
204
  success=False, reason="LLM response is None. This is a critical error."
203
205
  )
204
206
 
207
+ try:
208
+ usage = get_usage_from_response(self.llm.class_name(), response)
209
+ except Exception as e:
210
+ logger.warning(f"Could not get llm usage from response: {e}")
211
+ usage = None
212
+
205
213
  await self.chat_memory.aput(response.message)
206
214
 
207
215
  code, thoughts = chat_utils.extract_code_and_thought(response.message.content)
208
216
 
209
- event = TaskThinkingEvent(thoughts=thoughts, code=code)
217
+ event = TaskThinkingEvent(thoughts=thoughts, code=code, usage=usage)
210
218
  ctx.write_event_to_stream(event)
211
219
  return event
212
220
 
@@ -255,6 +263,10 @@ class CodeActAgent(Workflow):
255
263
  for screenshot in screenshots[:-1]: # the last screenshot will be captured by next step
256
264
  ctx.write_event_to_stream(ScreenshotEvent(screenshot=screenshot))
257
265
 
266
+ ui_states = result['ui_states']
267
+ for ui_state in ui_states[:-1]:
268
+ ctx.write_event_to_stream(RecordUIStateEvent(ui_state=ui_state['a11y_tree']))
269
+
258
270
  if self.tools.finished == True:
259
271
  logger.debug(" - Task completed.")
260
272
  event = TaskEndEvent(
@@ -311,7 +323,8 @@ class CodeActAgent(Workflow):
311
323
  await ctx.set("chat_memory", self.chat_memory)
312
324
 
313
325
  # Add final state observation to episodic memory
314
- await self._add_final_state_observation(ctx)
326
+ if self.vision:
327
+ await self._add_final_state_observation(ctx)
315
328
 
316
329
  result = {}
317
330
  result.update(
@@ -1,6 +1,8 @@
1
1
  from llama_index.core.llms import ChatMessage
2
2
  from llama_index.core.workflow import Event
3
3
  from typing import Optional
4
+
5
+ from droidrun.agent.usage import UsageResult
4
6
  from ..context.episodic_memory import EpisodicMemory
5
7
 
6
8
  class TaskInputEvent(Event):
@@ -11,6 +13,7 @@ class TaskInputEvent(Event):
11
13
  class TaskThinkingEvent(Event):
12
14
  thoughts: Optional[str] = None
13
15
  code: Optional[str] = None
16
+ usage: Optional[UsageResult] = None
14
17
 
15
18
  class TaskExecutionEvent(Event):
16
19
  code: str
@@ -1,4 +1,5 @@
1
1
  from llama_index.core.workflow import Event
2
+ from typing import Dict, Any
2
3
 
3
4
  class ScreenshotEvent(Event):
4
5
  screenshot: bytes
@@ -44,4 +45,7 @@ class KeyPressActionEvent(MacroEvent):
44
45
  class StartAppEvent(MacroEvent):
45
46
  """"Event for starting an app"""
46
47
  package: str
47
- activity: str = None
48
+ activity: str = None
49
+
50
+ class RecordUIStateEvent(Event):
51
+ ui_state: list[Dict[str, Any]]
@@ -43,6 +43,13 @@ class TaskManager:
43
43
  def get_task_history(self):
44
44
  return self.task_history
45
45
 
46
+ def get_current_task(self) -> Optional[Task]:
47
+ """Return the first task with status "pending" from the task list."""
48
+ for task in self.tasks:
49
+ if task.status == self.STATUS_PENDING:
50
+ return task
51
+ return None
52
+
46
53
  def complete_task(self, task: Task, message: Optional[str] = None):
47
54
  task = copy.deepcopy(task)
48
55
  task.status = self.STATUS_COMPLETED
@@ -60,6 +67,9 @@ class TaskManager:
60
67
 
61
68
  def get_failed_tasks(self) -> list[dict]:
62
69
  return [task for task in self.task_history if task.status == self.STATUS_FAILED]
70
+
71
+ def get_task_history(self) -> list[dict]:
72
+ return self.task_history
63
73
 
64
74
 
65
75
  def save_to_file(self):