droidrun 0.3.10.dev6__py3-none-any.whl → 0.3.10.dev8__py3-none-any.whl
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.
- droidrun/agent/codeact/codeact_agent.py +3 -4
- droidrun/agent/context/task_manager.py +0 -1
- droidrun/agent/droid/droid_agent.py +1 -3
- droidrun/agent/droid/events.py +2 -2
- droidrun/agent/manager/__init__.py +1 -1
- droidrun/agent/manager/manager_agent.py +4 -4
- droidrun/agent/utils/executer.py +11 -10
- droidrun/agent/utils/llm_picker.py +1 -1
- droidrun/agent/utils/tools.py +1 -1
- droidrun/app_cards/app_card_provider.py +0 -1
- droidrun/app_cards/providers/__init__.py +1 -1
- droidrun/app_cards/providers/composite_provider.py +4 -4
- droidrun/app_cards/providers/local_provider.py +1 -2
- droidrun/app_cards/providers/server_provider.py +1 -1
- droidrun/cli/logs.py +4 -4
- droidrun/cli/main.py +10 -14
- droidrun/config_manager/config_manager.py +0 -1
- droidrun/macro/cli.py +0 -1
- droidrun/tools/adb.py +23 -365
- droidrun/tools/portal_client.py +434 -0
- {droidrun-0.3.10.dev6.dist-info → droidrun-0.3.10.dev8.dist-info}/METADATA +1 -1
- {droidrun-0.3.10.dev6.dist-info → droidrun-0.3.10.dev8.dist-info}/RECORD +25 -24
- {droidrun-0.3.10.dev6.dist-info → droidrun-0.3.10.dev8.dist-info}/WHEEL +0 -0
- {droidrun-0.3.10.dev6.dist-info → droidrun-0.3.10.dev8.dist-info}/entry_points.txt +0 -0
- {droidrun-0.3.10.dev6.dist-info → droidrun-0.3.10.dev8.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,434 @@
|
|
1
|
+
"""
|
2
|
+
Portal Client - Unified communication layer for DroidRun Portal app.
|
3
|
+
|
4
|
+
This module provides automatic TCP/Content Provider fallback for Portal communication.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import base64
|
8
|
+
import io
|
9
|
+
import json
|
10
|
+
import logging
|
11
|
+
import re
|
12
|
+
from typing import Any, Dict, List, Optional
|
13
|
+
|
14
|
+
import requests
|
15
|
+
from adbutils import AdbDevice
|
16
|
+
|
17
|
+
logger = logging.getLogger("droidrun-tools")
|
18
|
+
|
19
|
+
PORTAL_REMOTE_PORT = 8080 # Port on device where Portal HTTP server runs
|
20
|
+
|
21
|
+
|
22
|
+
class PortalClient:
|
23
|
+
"""
|
24
|
+
Unified client for DroidRun Portal communication.
|
25
|
+
|
26
|
+
Automatically handles TCP vs Content Provider fallback with the following strategy:
|
27
|
+
- On init, checks for existing port forward and reuses it
|
28
|
+
- If no forward exists, creates new one
|
29
|
+
- Tests connection and sets tcp_available flag
|
30
|
+
- All methods auto-select TCP or content provider based on availability
|
31
|
+
- No cleanup needed - forwards persist until device disconnect
|
32
|
+
|
33
|
+
Key features:
|
34
|
+
- Reuses existing port forwards (no cleanup needed)
|
35
|
+
- Automatic fallback to content provider if TCP fails
|
36
|
+
- Zero explicit resource management
|
37
|
+
- Graceful degradation
|
38
|
+
"""
|
39
|
+
|
40
|
+
def __init__(self, device: AdbDevice, prefer_tcp: bool = False):
|
41
|
+
"""
|
42
|
+
Initialize Portal client.
|
43
|
+
|
44
|
+
Args:
|
45
|
+
device: ADB device instance
|
46
|
+
prefer_tcp: Whether to prefer TCP communication (will fallback to content provider if unavailable)
|
47
|
+
"""
|
48
|
+
self.device = device
|
49
|
+
self.tcp_available = False
|
50
|
+
self.tcp_base_url = None
|
51
|
+
self.local_tcp_port = None
|
52
|
+
|
53
|
+
if prefer_tcp:
|
54
|
+
self._try_enable_tcp()
|
55
|
+
|
56
|
+
def _try_enable_tcp(self) -> None:
|
57
|
+
"""
|
58
|
+
Try to enable TCP communication. Fails silently and falls back to content provider.
|
59
|
+
|
60
|
+
Strategy:
|
61
|
+
1. Check if forward already exists → reuse
|
62
|
+
2. If not, create new forward
|
63
|
+
3. Test connection with ping
|
64
|
+
4. Set tcp_available flag
|
65
|
+
"""
|
66
|
+
try:
|
67
|
+
# Step 1: Check for existing forward
|
68
|
+
local_port = self._find_existing_forward()
|
69
|
+
|
70
|
+
# Step 2: If no forward exists, create one
|
71
|
+
if local_port is None:
|
72
|
+
logger.debug(f"No existing forward found, creating new forward for port {PORTAL_REMOTE_PORT}")
|
73
|
+
local_port = self.device.forward_port(PORTAL_REMOTE_PORT)
|
74
|
+
logger.debug(f"Created forward: localhost:{local_port} -> device:{PORTAL_REMOTE_PORT}")
|
75
|
+
else:
|
76
|
+
logger.debug(f"Reusing existing forward: localhost:{local_port} -> device:{PORTAL_REMOTE_PORT}")
|
77
|
+
|
78
|
+
# Store local port
|
79
|
+
self.local_tcp_port = local_port
|
80
|
+
|
81
|
+
# Step 3: Test connection
|
82
|
+
self.tcp_base_url = f"http://localhost:{local_port}"
|
83
|
+
if self._test_connection():
|
84
|
+
self.tcp_available = True
|
85
|
+
logger.info(f"✓ TCP mode enabled: {self.tcp_base_url}")
|
86
|
+
else:
|
87
|
+
logger.warning("TCP connection test failed, falling back to content provider")
|
88
|
+
self.tcp_available = False
|
89
|
+
|
90
|
+
except Exception as e:
|
91
|
+
logger.warning(f"Failed to setup TCP forwarding: {e}. Using content provider fallback.")
|
92
|
+
self.tcp_available = False
|
93
|
+
|
94
|
+
def _find_existing_forward(self) -> Optional[int]:
|
95
|
+
"""
|
96
|
+
Check if a forward already exists for the Portal remote port.
|
97
|
+
|
98
|
+
Returns:
|
99
|
+
Local port number if forward exists, None otherwise
|
100
|
+
"""
|
101
|
+
try:
|
102
|
+
forwards = self.device.forward_list()
|
103
|
+
# Format: ['serial tcp:local_port tcp:remote_port', ...]
|
104
|
+
for forward in forwards:
|
105
|
+
if self.device.serial in forward and f"tcp:{PORTAL_REMOTE_PORT}" in forward:
|
106
|
+
# Extract local port: "serial tcp:12345 tcp:8080"
|
107
|
+
match = re.search(r'tcp:(\d+)\s+tcp:' + str(PORTAL_REMOTE_PORT), forward)
|
108
|
+
if match:
|
109
|
+
local_port = int(match.group(1))
|
110
|
+
logger.debug(f"Found existing forward: localhost:{local_port} -> {PORTAL_REMOTE_PORT}")
|
111
|
+
return local_port
|
112
|
+
except Exception as e:
|
113
|
+
logger.debug(f"Failed to check existing forwards: {e}")
|
114
|
+
|
115
|
+
return None
|
116
|
+
|
117
|
+
def _test_connection(self) -> bool:
|
118
|
+
"""Test if TCP connection to Portal is working."""
|
119
|
+
try:
|
120
|
+
response = requests.get(f"{self.tcp_base_url}/ping", timeout=3)
|
121
|
+
return response.status_code == 200
|
122
|
+
except Exception as e:
|
123
|
+
logger.debug(f"TCP connection test failed: {e}")
|
124
|
+
return False
|
125
|
+
|
126
|
+
def _parse_content_provider_output(self, raw_output: str) -> Optional[Dict[str, Any]]:
|
127
|
+
"""
|
128
|
+
Parse the raw ADB content provider output and extract JSON data.
|
129
|
+
|
130
|
+
Args:
|
131
|
+
raw_output: Raw output from ADB content query command
|
132
|
+
|
133
|
+
Returns:
|
134
|
+
Parsed JSON data or None if parsing failed
|
135
|
+
"""
|
136
|
+
lines = raw_output.strip().split("\n")
|
137
|
+
|
138
|
+
# Try line-by-line parsing
|
139
|
+
for line in lines:
|
140
|
+
line = line.strip()
|
141
|
+
|
142
|
+
# Look for "result=" pattern (common content provider format)
|
143
|
+
if "result=" in line:
|
144
|
+
result_start = line.find("result=") + 7
|
145
|
+
json_str = line[result_start:]
|
146
|
+
try:
|
147
|
+
json_data = json.loads(json_str)
|
148
|
+
# Handle nested "data" field with JSON string
|
149
|
+
if isinstance(json_data, dict) and "data" in json_data:
|
150
|
+
if isinstance(json_data["data"], str):
|
151
|
+
return json.loads(json_data["data"])
|
152
|
+
return json_data
|
153
|
+
except json.JSONDecodeError:
|
154
|
+
continue
|
155
|
+
|
156
|
+
# Fallback: try lines starting with JSON
|
157
|
+
elif line.startswith("{") or line.startswith("["):
|
158
|
+
try:
|
159
|
+
return json.loads(line)
|
160
|
+
except json.JSONDecodeError:
|
161
|
+
continue
|
162
|
+
|
163
|
+
# Last resort: try parsing entire output
|
164
|
+
try:
|
165
|
+
return json.loads(raw_output.strip())
|
166
|
+
except json.JSONDecodeError:
|
167
|
+
return None
|
168
|
+
|
169
|
+
|
170
|
+
def get_state(self) -> Dict[str, Any]:
|
171
|
+
"""
|
172
|
+
Get device state (accessibility tree + phone state).
|
173
|
+
Auto-selects TCP or content provider.
|
174
|
+
|
175
|
+
Returns:
|
176
|
+
Dictionary containing 'a11y_tree' and 'phone_state' keys
|
177
|
+
"""
|
178
|
+
if self.tcp_available:
|
179
|
+
return self._get_state_tcp()
|
180
|
+
return self._get_state_content_provider()
|
181
|
+
|
182
|
+
def _get_state_tcp(self) -> Dict[str, Any]:
|
183
|
+
"""Get state via TCP."""
|
184
|
+
try:
|
185
|
+
response = requests.get(f"{self.tcp_base_url}/state", timeout=10)
|
186
|
+
if response.status_code == 200:
|
187
|
+
data = response.json()
|
188
|
+
|
189
|
+
# Handle nested "data" field
|
190
|
+
if isinstance(data, dict) and "data" in data:
|
191
|
+
if isinstance(data["data"], str):
|
192
|
+
return json.loads(data["data"])
|
193
|
+
return data
|
194
|
+
else:
|
195
|
+
logger.warning(f"TCP get_state failed ({response.status_code}), falling back")
|
196
|
+
return self._get_state_content_provider()
|
197
|
+
except Exception as e:
|
198
|
+
logger.warning(f"TCP get_state error: {e}, falling back")
|
199
|
+
return self._get_state_content_provider()
|
200
|
+
|
201
|
+
def _get_state_content_provider(self) -> Dict[str, Any]:
|
202
|
+
"""Get state via content provider (fallback)."""
|
203
|
+
try:
|
204
|
+
output = self.device.shell("content query --uri content://com.droidrun.portal/state")
|
205
|
+
state_data = self._parse_content_provider_output(output)
|
206
|
+
|
207
|
+
if state_data is None:
|
208
|
+
return {
|
209
|
+
"error": "Parse Error",
|
210
|
+
"message": "Failed to parse state data from ContentProvider"
|
211
|
+
}
|
212
|
+
|
213
|
+
# Handle nested "data" field if present
|
214
|
+
if isinstance(state_data, dict) and "data" in state_data:
|
215
|
+
if isinstance(state_data["data"], str):
|
216
|
+
try:
|
217
|
+
return json.loads(state_data["data"])
|
218
|
+
except json.JSONDecodeError:
|
219
|
+
return {
|
220
|
+
"error": "Parse Error",
|
221
|
+
"message": "Failed to parse nested JSON data"
|
222
|
+
}
|
223
|
+
|
224
|
+
return state_data
|
225
|
+
|
226
|
+
except Exception as e:
|
227
|
+
return {
|
228
|
+
"error": "ContentProvider Error",
|
229
|
+
"message": str(e)
|
230
|
+
}
|
231
|
+
|
232
|
+
|
233
|
+
def input_text(self, text: str, clear: bool = False) -> bool:
|
234
|
+
"""
|
235
|
+
Input text via keyboard.
|
236
|
+
Auto-selects TCP or content provider.
|
237
|
+
|
238
|
+
Args:
|
239
|
+
text: Text to input
|
240
|
+
clear: Whether to clear existing text first
|
241
|
+
|
242
|
+
Returns:
|
243
|
+
True if successful, False otherwise
|
244
|
+
"""
|
245
|
+
if self.tcp_available:
|
246
|
+
return self._input_text_tcp(text, clear)
|
247
|
+
return self._input_text_content_provider(text, clear)
|
248
|
+
|
249
|
+
def _input_text_tcp(self, text: str, clear: bool) -> bool:
|
250
|
+
"""Input text via TCP."""
|
251
|
+
try:
|
252
|
+
encoded = base64.b64encode(text.encode()).decode()
|
253
|
+
payload = {"base64_text": encoded, "clear": clear}
|
254
|
+
response = requests.post(
|
255
|
+
f"{self.tcp_base_url}/keyboard/input",
|
256
|
+
json=payload,
|
257
|
+
headers={"Content-Type": "application/json"},
|
258
|
+
timeout=10
|
259
|
+
)
|
260
|
+
if response.status_code == 200:
|
261
|
+
logger.debug(f"TCP input_text successful")
|
262
|
+
return True
|
263
|
+
else:
|
264
|
+
logger.warning(f"TCP input_text failed ({response.status_code}), falling back")
|
265
|
+
return self._input_text_content_provider(text, clear)
|
266
|
+
except Exception as e:
|
267
|
+
logger.warning(f"TCP input_text error: {e}, falling back")
|
268
|
+
return self._input_text_content_provider(text, clear)
|
269
|
+
|
270
|
+
def _input_text_content_provider(self, text: str, clear: bool) -> bool:
|
271
|
+
"""Input text via content provider (fallback)."""
|
272
|
+
try:
|
273
|
+
encoded = base64.b64encode(text.encode()).decode()
|
274
|
+
clear_str = "true" if clear else "false"
|
275
|
+
cmd = (
|
276
|
+
f'content insert --uri "content://com.droidrun.portal/keyboard/input" '
|
277
|
+
f'--bind base64_text:s:"{encoded}" '
|
278
|
+
f'--bind clear:b:{clear_str}'
|
279
|
+
)
|
280
|
+
self.device.shell(cmd)
|
281
|
+
logger.debug("Content provider input_text successful")
|
282
|
+
return True
|
283
|
+
except Exception as e:
|
284
|
+
logger.error(f"Content provider input_text error: {e}")
|
285
|
+
return False
|
286
|
+
|
287
|
+
|
288
|
+
def take_screenshot(self, hide_overlay: bool = True) -> bytes:
|
289
|
+
"""
|
290
|
+
Take screenshot of device.
|
291
|
+
Auto-selects TCP or ADB screencap.
|
292
|
+
|
293
|
+
Args:
|
294
|
+
hide_overlay: Whether to hide Portal overlay during screenshot
|
295
|
+
|
296
|
+
Returns:
|
297
|
+
Screenshot image bytes (PNG format)
|
298
|
+
"""
|
299
|
+
if self.tcp_available:
|
300
|
+
return self._take_screenshot_tcp(hide_overlay)
|
301
|
+
return self._take_screenshot_adb()
|
302
|
+
|
303
|
+
def _take_screenshot_tcp(self, hide_overlay: bool) -> bytes:
|
304
|
+
"""Take screenshot via TCP."""
|
305
|
+
try:
|
306
|
+
url = f"{self.tcp_base_url}/screenshot"
|
307
|
+
if not hide_overlay:
|
308
|
+
url += "?hideOverlay=false"
|
309
|
+
|
310
|
+
response = requests.get(url, timeout=10)
|
311
|
+
if response.status_code == 200:
|
312
|
+
data = response.json()
|
313
|
+
if data.get("status") == "success" and "data" in data:
|
314
|
+
logger.debug("Screenshot taken via TCP")
|
315
|
+
return base64.b64decode(data["data"])
|
316
|
+
else:
|
317
|
+
logger.warning("TCP screenshot failed (invalid response), falling back")
|
318
|
+
return self._take_screenshot_adb()
|
319
|
+
else:
|
320
|
+
logger.warning(f"TCP screenshot failed ({response.status_code}), falling back")
|
321
|
+
return self._take_screenshot_adb()
|
322
|
+
except Exception as e:
|
323
|
+
logger.warning(f"TCP screenshot error: {e}, falling back")
|
324
|
+
return self._take_screenshot_adb()
|
325
|
+
|
326
|
+
def _take_screenshot_adb(self) -> bytes:
|
327
|
+
"""Take screenshot via ADB screencap (fallback)."""
|
328
|
+
img = self.device.screenshot()
|
329
|
+
buf = io.BytesIO()
|
330
|
+
img.save(buf, format="PNG")
|
331
|
+
logger.debug("Screenshot taken via ADB")
|
332
|
+
return buf.getvalue()
|
333
|
+
|
334
|
+
def get_apps(self, include_system: bool = True) -> List[Dict[str, str]]:
|
335
|
+
"""
|
336
|
+
Get installed apps with package name and label.
|
337
|
+
|
338
|
+
Note: Currently only supports content provider (no TCP endpoint exists yet)
|
339
|
+
|
340
|
+
Args:
|
341
|
+
include_system: Whether to include system apps
|
342
|
+
|
343
|
+
Returns:
|
344
|
+
List of dicts with 'package' and 'label' keys
|
345
|
+
"""
|
346
|
+
try:
|
347
|
+
logger.debug("Getting apps via content provider")
|
348
|
+
|
349
|
+
# Query content provider
|
350
|
+
output = self.device.shell("content query --uri content://com.droidrun.portal/packages")
|
351
|
+
packages_data = self._parse_content_provider_output(output)
|
352
|
+
|
353
|
+
if not packages_data or "packages" not in packages_data:
|
354
|
+
logger.warning("No packages data found in content provider response")
|
355
|
+
return []
|
356
|
+
|
357
|
+
# Filter and format apps
|
358
|
+
apps = []
|
359
|
+
for package_info in packages_data["packages"]:
|
360
|
+
if not include_system and package_info.get("isSystemApp", False):
|
361
|
+
continue
|
362
|
+
|
363
|
+
apps.append({
|
364
|
+
"package": package_info.get("packageName", ""),
|
365
|
+
"label": package_info.get("label", "")
|
366
|
+
})
|
367
|
+
|
368
|
+
logger.debug(f"Found {len(apps)} apps")
|
369
|
+
return apps
|
370
|
+
|
371
|
+
except Exception as e:
|
372
|
+
logger.error(f"Error getting apps: {e}")
|
373
|
+
raise ValueError(f"Error getting apps: {e}") from e
|
374
|
+
|
375
|
+
|
376
|
+
def ping(self) -> Dict[str, Any]:
|
377
|
+
"""
|
378
|
+
Test Portal connection.
|
379
|
+
|
380
|
+
Returns:
|
381
|
+
Dictionary with status and connection details
|
382
|
+
"""
|
383
|
+
if self.tcp_available:
|
384
|
+
try:
|
385
|
+
response = requests.get(f"{self.tcp_base_url}/ping", timeout=5)
|
386
|
+
if response.status_code == 200:
|
387
|
+
try:
|
388
|
+
tcp_response = response.json() if response.content else {}
|
389
|
+
return {
|
390
|
+
"status": "success",
|
391
|
+
"method": "tcp",
|
392
|
+
"url": self.tcp_base_url,
|
393
|
+
"response": tcp_response
|
394
|
+
}
|
395
|
+
except json.JSONDecodeError:
|
396
|
+
return {
|
397
|
+
"status": "success",
|
398
|
+
"method": "tcp",
|
399
|
+
"url": self.tcp_base_url,
|
400
|
+
"response": response.text
|
401
|
+
}
|
402
|
+
else:
|
403
|
+
return {
|
404
|
+
"status": "error",
|
405
|
+
"method": "tcp",
|
406
|
+
"message": f"HTTP {response.status_code}: {response.text}"
|
407
|
+
}
|
408
|
+
except Exception as e:
|
409
|
+
return {
|
410
|
+
"status": "error",
|
411
|
+
"method": "tcp",
|
412
|
+
"message": str(e)
|
413
|
+
}
|
414
|
+
else:
|
415
|
+
# Test content provider
|
416
|
+
try:
|
417
|
+
output = self.device.shell("content query --uri content://com.droidrun.portal/state")
|
418
|
+
if "Row: 0 result=" in output:
|
419
|
+
return {
|
420
|
+
"status": "success",
|
421
|
+
"method": "content_provider"
|
422
|
+
}
|
423
|
+
else:
|
424
|
+
return {
|
425
|
+
"status": "error",
|
426
|
+
"method": "content_provider",
|
427
|
+
"message": "Invalid response"
|
428
|
+
}
|
429
|
+
except Exception as e:
|
430
|
+
return {
|
431
|
+
"status": "error",
|
432
|
+
"method": "content_provider",
|
433
|
+
"message": str(e)
|
434
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: droidrun
|
3
|
-
Version: 0.3.10.
|
3
|
+
Version: 0.3.10.dev8
|
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
|
@@ -4,23 +4,23 @@ droidrun/portal.py,sha256=QCfJecUpuyd9io_76ngJizs1ebKubMzVMmCWXpgC6PM,6737
|
|
4
4
|
droidrun/agent/__init__.py,sha256=91sM0qTmdV5trlXOWE4D_nRhXVPgHKMnYU_9Stc_obQ,209
|
5
5
|
droidrun/agent/usage.py,sha256=6PVeHctNa0EmHmNPTdOUv5e3-EK6AMu6D2Pz5OMqs5c,7145
|
6
6
|
droidrun/agent/codeact/__init__.py,sha256=lagBdrury33kbHN1XEZ-xzJ-RywmpkUUoUidOno9ym8,96
|
7
|
-
droidrun/agent/codeact/codeact_agent.py,sha256=
|
7
|
+
droidrun/agent/codeact/codeact_agent.py,sha256=7EkuazNIpTOX-W1oSG0XmtOwcmNOyaiPddgNxnK10No,20292
|
8
8
|
droidrun/agent/codeact/events.py,sha256=kRKTQPzogPiQwmOCc_fGcg1g1zDXXVeBpDl45GTdpYU,734
|
9
9
|
droidrun/agent/common/constants.py,sha256=q7ywmOXCsJZg8m9ctpzQ-nxvuj5GMn28Pr8z3dMj1Rg,94
|
10
10
|
droidrun/agent/common/events.py,sha256=rbPWdlqNNMdnVjYhJOL2mJcNNORHhjXOkY8XiLPzp7c,1182
|
11
11
|
droidrun/agent/context/__init__.py,sha256=-CiAv66qym_WgFy5vCRfNLxmiprmEbssu6S_2jj0LZw,452
|
12
12
|
droidrun/agent/context/episodic_memory.py,sha256=0WKmOPe_KDWGdxudUXkmNVO1vj7L1g2zpyhAA54E1Lk,308
|
13
|
-
droidrun/agent/context/task_manager.py,sha256=
|
13
|
+
droidrun/agent/context/task_manager.py,sha256=A2COoBMXBOCtrASC4QI8ZdYizNVLOD04e4rzviVIMbk,5013
|
14
14
|
droidrun/agent/droid/__init__.py,sha256=3Kzejs0p2hqKzgMc253W147P-Y84bYnQX7AZ4pybIsU,297
|
15
|
-
droidrun/agent/droid/droid_agent.py,sha256=
|
16
|
-
droidrun/agent/droid/events.py,sha256=
|
15
|
+
droidrun/agent/droid/droid_agent.py,sha256=FRHNsuEyDY7n6jGwxnjoyAAgHhHWRQkbx5-Onen0Zvw,21722
|
16
|
+
droidrun/agent/droid/events.py,sha256=m7FoIpAb4Fd6pcFyoWf9Jx9mYhSV8qMCieHEfYS7Fsg,4059
|
17
17
|
droidrun/agent/executor/__init__.py,sha256=2B531GoY7L1Hs_RJIVu62ARsP9mj86do8MiFl6ejpZ4,456
|
18
18
|
droidrun/agent/executor/events.py,sha256=sYMs24at_VtikPKqSh_yNRYByDt4JpS1jiEob9UjNrs,1377
|
19
19
|
droidrun/agent/executor/executor_agent.py,sha256=mBbL-NfZ59w-8TDz_etuku-fgPzrL9DE4h5vi-STEWM,13923
|
20
20
|
droidrun/agent/executor/prompts.py,sha256=amHWdGV-q-lgFkwg8N8VGeshvUqkEdxTM8GHnt7uTUQ,1182
|
21
|
-
droidrun/agent/manager/__init__.py,sha256=
|
21
|
+
droidrun/agent/manager/__init__.py,sha256=A8esHVpxzHd3Epzkl0j5seNkRQqwNEn1a97eeLmbsww,525
|
22
22
|
droidrun/agent/manager/events.py,sha256=X0tUwCX2mU8I4bGR4JW2NmUqiOrX-Hrb017vGVPVyHw,855
|
23
|
-
droidrun/agent/manager/manager_agent.py,sha256=
|
23
|
+
droidrun/agent/manager/manager_agent.py,sha256=nXftmLlSLDs9LLB3rHE3EzpaCnUKa6v1dNfjFTMV9ys,22256
|
24
24
|
droidrun/agent/manager/prompts.py,sha256=qfDYcSbpWpnUaavAuPE6qY6Df6w25LmtY1mEiBUMti0,2060
|
25
25
|
droidrun/agent/oneflows/app_starter_workflow.py,sha256=MSJ6_jfbiCfSIjnw-qfSDFDuqsUS6rUGLsdKVj43wvY,3525
|
26
26
|
droidrun/agent/oneflows/text_manipulator.py,sha256=mO59DF1uif9poUWy90UehrBmHbNxL9ph4Evtgt1ODbQ,8751
|
@@ -28,38 +28,39 @@ droidrun/agent/utils/__init__.py,sha256=Oro0oyiz1xzRpchWLDA1TZJELJNSwBOb2WdGgknt
|
|
28
28
|
droidrun/agent/utils/async_utils.py,sha256=_JhZ_ZfCkRTfPsufFDhUUds_Vp6z1-TokzUG4H8G7pc,338
|
29
29
|
droidrun/agent/utils/chat_utils.py,sha256=mginY1rbP5t06O3hz2RpJJJNzggaE8VhWjnFid844vw,13797
|
30
30
|
droidrun/agent/utils/device_state_formatter.py,sha256=3MuR3XQulnrsdzmMYfTEegA_XkYTTiETXMRtOtyqoC0,6889
|
31
|
-
droidrun/agent/utils/executer.py,sha256=
|
31
|
+
droidrun/agent/utils/executer.py,sha256=mCq-T9gekgFK9oSHz2H9ctHIyJQFzp9MWQgzuxP0TU0,4191
|
32
32
|
droidrun/agent/utils/inference.py,sha256=dupCtMYXUGuBJz9RqTgSsLYe_MOSB0LEhfHIdtFC8x0,3893
|
33
|
-
droidrun/agent/utils/llm_picker.py,sha256=
|
33
|
+
droidrun/agent/utils/llm_picker.py,sha256=KQzrRcHE38NwujDbNth5F9v5so9HVvHjfkQznMsv-cM,9397
|
34
34
|
droidrun/agent/utils/message_utils.py,sha256=_wngf082gg232y_3pC_yn4fnPhHiyYAxhU4ewT78roo,2309
|
35
|
-
droidrun/agent/utils/tools.py,sha256=
|
35
|
+
droidrun/agent/utils/tools.py,sha256=anc10NAKmZx91JslHFpo6wfnUOZ2pnPXJS-5nMVHC_A,9930
|
36
36
|
droidrun/agent/utils/trajectory.py,sha256=Z6C19Y9hsRxjLZWywqYWTApKU7PelvWM-5Tsl3h7KEw,19718
|
37
|
-
droidrun/app_cards/app_card_provider.py,sha256=
|
38
|
-
droidrun/app_cards/providers/__init__.py,sha256=
|
39
|
-
droidrun/app_cards/providers/composite_provider.py,sha256=
|
40
|
-
droidrun/app_cards/providers/local_provider.py,sha256=
|
41
|
-
droidrun/app_cards/providers/server_provider.py,sha256=
|
37
|
+
droidrun/app_cards/app_card_provider.py,sha256=wy7CGFnBd_EPU58xNdv4ZWUA9F4Plon71N4-5RT5vNg,827
|
38
|
+
droidrun/app_cards/providers/__init__.py,sha256=vN4TvBtsvfdvzgqbIJegIfHhct0aTFZjvJazWFDvdhg,372
|
39
|
+
droidrun/app_cards/providers/composite_provider.py,sha256=oi7dlkv_Hv2rEZMxQlO1jP9fQcTBydr40zCyunCNxQA,3156
|
40
|
+
droidrun/app_cards/providers/local_provider.py,sha256=RRGQ7VR7qHT9uKSOlSvqCTRq_p4W5HzlWue7B6tcbT0,3904
|
41
|
+
droidrun/app_cards/providers/server_provider.py,sha256=rOJyiCE_zTCCK9SAJeee3vLWISytoZrBUiXB6LaJEv8,4148
|
42
42
|
droidrun/cli/__init__.py,sha256=5cO-QBcUl5w35zO18OENj4OShdglQjn8Ne9aqgSh-PM,167
|
43
|
-
droidrun/cli/logs.py,sha256=
|
44
|
-
droidrun/cli/main.py,sha256=
|
43
|
+
droidrun/cli/logs.py,sha256=V8rn6oXgYObExX4dG8MUnQXxUdKOk1QlTkOQtI5e6wo,12686
|
44
|
+
droidrun/cli/main.py,sha256=lzGwWk8SbbxmVeyz2mqkPBT6Xs5SMxnQSxecuK-7L5s,35119
|
45
45
|
droidrun/config_manager/__init__.py,sha256=SeLoEYVU5jMEtXLjx76VE_3rxzZXjCMlVPW7hodU128,460
|
46
|
-
droidrun/config_manager/config_manager.py,sha256=
|
46
|
+
droidrun/config_manager/config_manager.py,sha256=hPETII_5wYvfb11e7sJlfCVk9p3WbA7nHPAV3bQQdmE,19930
|
47
47
|
droidrun/config_manager/path_resolver.py,sha256=vQKT5XmnENtSK3B1D-iItL8CpOQTKzfKZ1wTO4khlTs,3421
|
48
48
|
droidrun/config_manager/prompt_loader.py,sha256=JqGHjT4Ik5iwPfnaXkCc1W1cm4QmIqq2duPuye14jSc,2430
|
49
49
|
droidrun/macro/__init__.py,sha256=TKRNlMJqClV1p1dkfES4eo-Bq1VkSiTC1DDMxMjnUWE,357
|
50
50
|
droidrun/macro/__main__.py,sha256=MWdBvQVhOoeKlC8atDwjVbPSn0-XNt4PDbpCCoeJuUk,193
|
51
|
-
droidrun/macro/cli.py,sha256=
|
51
|
+
droidrun/macro/cli.py,sha256=jQqnnrAnH_KTxuPsYsvIdftPlVcvpb5a5yn5v6A6cCg,9151
|
52
52
|
droidrun/macro/replay.py,sha256=ILhnvN3VYhMK13wkaD5oDwP4wCYTniwcgesUON-9L5o,10721
|
53
53
|
droidrun/telemetry/__init__.py,sha256=2G9PwAuVWsd6qRMKSscssvmL57ILlOK5EV0KezPiF1I,271
|
54
54
|
droidrun/telemetry/events.py,sha256=y-i2d5KiPkikVXrzMQu87osy1LAZTBIx8DlPIWGAXG0,486
|
55
55
|
droidrun/telemetry/phoenix.py,sha256=JHdFdRHXu7cleAb4X4_Y5yn5zPSIApwyKCOxoaj_gf4,7117
|
56
56
|
droidrun/telemetry/tracker.py,sha256=YWOkyLE8XiHainVSB77JE37y-rloOYVYs6j53Aw1J8A,2735
|
57
57
|
droidrun/tools/__init__.py,sha256=BbQFKuPn-5MwGzr-3urMDK8S1ZsP96D96y7WTJYB3AA,271
|
58
|
-
droidrun/tools/adb.py,sha256=
|
58
|
+
droidrun/tools/adb.py,sha256=PRbQS1qhy_HFUVx78LYPwTa4GT4TgMrRTwc7NM4Tf4A,28950
|
59
59
|
droidrun/tools/ios.py,sha256=GMYbiNNBeHLwVQAo4_fEZ7snr4JCHE6sG11rcuPvSpk,21831
|
60
|
+
droidrun/tools/portal_client.py,sha256=BthC-ryHtCxh3czmkTge5aaurinPZfFkV4DgbkD_wbw,16307
|
60
61
|
droidrun/tools/tools.py,sha256=0eAZFTaY10eiiUcJM4AkURmTGX-O1RRXjpQ5MHj2Ydo,5241
|
61
|
-
droidrun-0.3.10.
|
62
|
-
droidrun-0.3.10.
|
63
|
-
droidrun-0.3.10.
|
64
|
-
droidrun-0.3.10.
|
65
|
-
droidrun-0.3.10.
|
62
|
+
droidrun-0.3.10.dev8.dist-info/METADATA,sha256=MWB-CRMnxmQV4il8-OYdsGKn00IclAqvxPNRk_-LLxw,7044
|
63
|
+
droidrun-0.3.10.dev8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
64
|
+
droidrun-0.3.10.dev8.dist-info/entry_points.txt,sha256=o259U66js8TIybQ7zs814Oe_LQ_GpZsp6a9Cr-xm5zE,51
|
65
|
+
droidrun-0.3.10.dev8.dist-info/licenses/LICENSE,sha256=s-uxn9qChu-kFdRXUp6v_0HhsaJ_5OANmfNOFVm2zdk,1069
|
66
|
+
droidrun-0.3.10.dev8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|