autoglm-gui 1.5.0__py3-none-any.whl → 1.5.2__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.
- AutoGLM_GUI/__init__.py +1 -1
- AutoGLM_GUI/__main__.py +11 -2
- AutoGLM_GUI/adb_plus/qr_pair.py +3 -3
- AutoGLM_GUI/agents/__init__.py +7 -2
- AutoGLM_GUI/agents/factory.py +46 -6
- AutoGLM_GUI/agents/glm/agent.py +8 -3
- AutoGLM_GUI/agents/glm/async_agent.py +515 -0
- AutoGLM_GUI/agents/glm/parser.py +4 -2
- AutoGLM_GUI/agents/mai/agent.py +3 -0
- AutoGLM_GUI/agents/protocols.py +111 -1
- AutoGLM_GUI/agents/stream_runner.py +11 -7
- AutoGLM_GUI/api/__init__.py +3 -1
- AutoGLM_GUI/api/agents.py +103 -37
- AutoGLM_GUI/api/devices.py +72 -0
- AutoGLM_GUI/api/history.py +27 -1
- AutoGLM_GUI/api/layered_agent.py +9 -8
- AutoGLM_GUI/api/mcp.py +6 -4
- AutoGLM_GUI/config_manager.py +38 -1
- AutoGLM_GUI/device_manager.py +28 -4
- AutoGLM_GUI/device_metadata_manager.py +174 -0
- AutoGLM_GUI/devices/mock_device.py +8 -1
- AutoGLM_GUI/models/history.py +45 -1
- AutoGLM_GUI/phone_agent_manager.py +145 -32
- AutoGLM_GUI/scheduler_manager.py +52 -6
- AutoGLM_GUI/schemas.py +101 -0
- AutoGLM_GUI/scrcpy_stream.py +2 -1
- AutoGLM_GUI/static/assets/{about-BQm96DAl.js → about-D7r9gCvG.js} +1 -1
- AutoGLM_GUI/static/assets/{alert-dialog-B42XxGPR.js → alert-dialog-BKM-yRiQ.js} +1 -1
- AutoGLM_GUI/static/assets/chat-k6TTD7PW.js +129 -0
- AutoGLM_GUI/static/assets/{circle-alert-D4rSJh37.js → circle-alert-sohSDLhl.js} +1 -1
- AutoGLM_GUI/static/assets/{dialog-DZ78cEcj.js → dialog-BgtPh0d5.js} +1 -1
- AutoGLM_GUI/static/assets/eye-DLqKbQmg.js +1 -0
- AutoGLM_GUI/static/assets/history-Bv1lfGUU.js +1 -0
- AutoGLM_GUI/static/assets/index-CV7jGxGm.css +1 -0
- AutoGLM_GUI/static/assets/index-CxWwh1VO.js +1 -0
- AutoGLM_GUI/static/assets/{index-CssG-3TH.js → index-SysdKciY.js} +5 -5
- AutoGLM_GUI/static/assets/label-DTUnzN4B.js +1 -0
- AutoGLM_GUI/static/assets/{logs-eoFxn5of.js → logs-BIhnDizW.js} +1 -1
- AutoGLM_GUI/static/assets/{popover-DLsuV5Sx.js → popover-CikYqu2P.js} +1 -1
- AutoGLM_GUI/static/assets/scheduled-tasks-B-KBsGbl.js +1 -0
- AutoGLM_GUI/static/assets/{textarea-BX6y7uM5.js → textarea-knJZrz77.js} +1 -1
- AutoGLM_GUI/static/assets/workflows-DzcSYwLZ.js +1 -0
- AutoGLM_GUI/static/index.html +2 -2
- {autoglm_gui-1.5.0.dist-info → autoglm_gui-1.5.2.dist-info}/METADATA +58 -7
- autoglm_gui-1.5.2.dist-info/RECORD +119 -0
- AutoGLM_GUI/device_adapter.py +0 -263
- AutoGLM_GUI/static/assets/chat-C0L2gQYG.js +0 -129
- AutoGLM_GUI/static/assets/history-DFBv7TGc.js +0 -1
- AutoGLM_GUI/static/assets/index-Bzyv2yQ2.css +0 -1
- AutoGLM_GUI/static/assets/index-CmZSnDqc.js +0 -1
- AutoGLM_GUI/static/assets/label-BCUzE_nm.js +0 -1
- AutoGLM_GUI/static/assets/scheduled-tasks-MyqGJvy_.js +0 -1
- AutoGLM_GUI/static/assets/square-pen-zGWYrdfj.js +0 -1
- AutoGLM_GUI/static/assets/workflows-CYFs6ssC.js +0 -1
- autoglm_gui-1.5.0.dist-info/RECORD +0 -157
- mai_agent/base.py +0 -137
- mai_agent/mai_grounding_agent.py +0 -263
- mai_agent/mai_naivigation_agent.py +0 -526
- mai_agent/prompt.py +0 -148
- mai_agent/unified_memory.py +0 -67
- mai_agent/utils.py +0 -73
- phone_agent/__init__.py +0 -12
- phone_agent/actions/__init__.py +0 -5
- phone_agent/actions/handler.py +0 -400
- phone_agent/actions/handler_ios.py +0 -278
- phone_agent/adb/__init__.py +0 -51
- phone_agent/adb/connection.py +0 -358
- phone_agent/adb/device.py +0 -253
- phone_agent/adb/input.py +0 -108
- phone_agent/adb/screenshot.py +0 -108
- phone_agent/agent.py +0 -253
- phone_agent/agent_ios.py +0 -277
- phone_agent/config/__init__.py +0 -53
- phone_agent/config/apps.py +0 -227
- phone_agent/config/apps_harmonyos.py +0 -256
- phone_agent/config/apps_ios.py +0 -339
- phone_agent/config/i18n.py +0 -81
- phone_agent/config/prompts.py +0 -80
- phone_agent/config/prompts_en.py +0 -79
- phone_agent/config/prompts_zh.py +0 -82
- phone_agent/config/timing.py +0 -167
- phone_agent/device_factory.py +0 -166
- phone_agent/hdc/__init__.py +0 -53
- phone_agent/hdc/connection.py +0 -384
- phone_agent/hdc/device.py +0 -269
- phone_agent/hdc/input.py +0 -145
- phone_agent/hdc/screenshot.py +0 -127
- phone_agent/model/__init__.py +0 -5
- phone_agent/model/client.py +0 -290
- phone_agent/xctest/__init__.py +0 -47
- phone_agent/xctest/connection.py +0 -379
- phone_agent/xctest/device.py +0 -472
- phone_agent/xctest/input.py +0 -311
- phone_agent/xctest/screenshot.py +0 -226
- {autoglm_gui-1.5.0.dist-info → autoglm_gui-1.5.2.dist-info}/WHEEL +0 -0
- {autoglm_gui-1.5.0.dist-info → autoglm_gui-1.5.2.dist-info}/entry_points.txt +0 -0
- {autoglm_gui-1.5.0.dist-info → autoglm_gui-1.5.2.dist-info}/licenses/LICENSE +0 -0
phone_agent/xctest/connection.py
DELETED
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
"""iOS device connection management via idevice tools and WebDriverAgent."""
|
|
2
|
-
|
|
3
|
-
import subprocess
|
|
4
|
-
from dataclasses import dataclass
|
|
5
|
-
from enum import Enum
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class ConnectionType(Enum):
|
|
9
|
-
"""Type of iOS connection."""
|
|
10
|
-
|
|
11
|
-
USB = "usb"
|
|
12
|
-
NETWORK = "network"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@dataclass
|
|
16
|
-
class DeviceInfo:
|
|
17
|
-
"""Information about a connected iOS device."""
|
|
18
|
-
|
|
19
|
-
device_id: str # UDID
|
|
20
|
-
status: str
|
|
21
|
-
connection_type: ConnectionType
|
|
22
|
-
model: str | None = None
|
|
23
|
-
ios_version: str | None = None
|
|
24
|
-
device_name: str | None = None
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class XCTestConnection:
|
|
28
|
-
"""
|
|
29
|
-
Manages connections to iOS devices via libimobiledevice and WebDriverAgent.
|
|
30
|
-
|
|
31
|
-
Requires:
|
|
32
|
-
- libimobiledevice (idevice_id, ideviceinfo)
|
|
33
|
-
- WebDriverAgent running on the iOS device
|
|
34
|
-
- ios-deploy (optional, for app installation)
|
|
35
|
-
|
|
36
|
-
Example:
|
|
37
|
-
>>> conn = XCTestConnection()
|
|
38
|
-
>>> # List connected devices
|
|
39
|
-
>>> devices = conn.list_devices()
|
|
40
|
-
>>> # Get device info
|
|
41
|
-
>>> info = conn.get_device_info()
|
|
42
|
-
>>> # Check if WDA is running
|
|
43
|
-
>>> is_ready = conn.is_wda_ready()
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
def __init__(self, wda_url: str = "http://localhost:8100"):
|
|
47
|
-
"""
|
|
48
|
-
Initialize iOS connection manager.
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
wda_url: WebDriverAgent URL (default: http://localhost:8100).
|
|
52
|
-
For network devices, use http://<device-ip>:8100
|
|
53
|
-
"""
|
|
54
|
-
self.wda_url = wda_url.rstrip("/")
|
|
55
|
-
|
|
56
|
-
def list_devices(self) -> list[DeviceInfo]:
|
|
57
|
-
"""
|
|
58
|
-
List all connected iOS devices.
|
|
59
|
-
|
|
60
|
-
Returns:
|
|
61
|
-
List of DeviceInfo objects.
|
|
62
|
-
|
|
63
|
-
Note:
|
|
64
|
-
Requires libimobiledevice to be installed.
|
|
65
|
-
Install on macOS: brew install libimobiledevice
|
|
66
|
-
"""
|
|
67
|
-
try:
|
|
68
|
-
# Get list of device UDIDs
|
|
69
|
-
result = subprocess.run(
|
|
70
|
-
["idevice_id", "-ln"],
|
|
71
|
-
capture_output=True,
|
|
72
|
-
text=True,
|
|
73
|
-
timeout=5,
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
devices = []
|
|
77
|
-
for line in result.stdout.strip().split("\n"):
|
|
78
|
-
udid = line.strip()
|
|
79
|
-
if not udid:
|
|
80
|
-
continue
|
|
81
|
-
|
|
82
|
-
# Determine connection type (network devices have specific format)
|
|
83
|
-
conn_type = (
|
|
84
|
-
ConnectionType.NETWORK
|
|
85
|
-
if "-" in udid and len(udid) > 40
|
|
86
|
-
else ConnectionType.USB
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
# Get detailed device info
|
|
90
|
-
device_info = self._get_device_details(udid)
|
|
91
|
-
|
|
92
|
-
devices.append(
|
|
93
|
-
DeviceInfo(
|
|
94
|
-
device_id=udid,
|
|
95
|
-
status="connected",
|
|
96
|
-
connection_type=conn_type,
|
|
97
|
-
model=device_info.get("model"),
|
|
98
|
-
ios_version=device_info.get("ios_version"),
|
|
99
|
-
device_name=device_info.get("name"),
|
|
100
|
-
)
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
return devices
|
|
104
|
-
|
|
105
|
-
except FileNotFoundError:
|
|
106
|
-
print(
|
|
107
|
-
"Error: idevice_id not found. Install libimobiledevice: brew install libimobiledevice"
|
|
108
|
-
)
|
|
109
|
-
return []
|
|
110
|
-
except Exception as e:
|
|
111
|
-
print(f"Error listing devices: {e}")
|
|
112
|
-
return []
|
|
113
|
-
|
|
114
|
-
def _get_device_details(self, udid: str) -> dict[str, str]:
|
|
115
|
-
"""
|
|
116
|
-
Get detailed information about a specific device.
|
|
117
|
-
|
|
118
|
-
Args:
|
|
119
|
-
udid: Device UDID.
|
|
120
|
-
|
|
121
|
-
Returns:
|
|
122
|
-
Dictionary with device details.
|
|
123
|
-
"""
|
|
124
|
-
try:
|
|
125
|
-
result = subprocess.run(
|
|
126
|
-
["ideviceinfo", "-u", udid],
|
|
127
|
-
capture_output=True,
|
|
128
|
-
text=True,
|
|
129
|
-
timeout=5,
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
info = {}
|
|
133
|
-
for line in result.stdout.split("\n"):
|
|
134
|
-
if ": " in line:
|
|
135
|
-
key, value = line.split(": ", 1)
|
|
136
|
-
key = key.strip()
|
|
137
|
-
value = value.strip()
|
|
138
|
-
|
|
139
|
-
if key == "ProductType":
|
|
140
|
-
info["model"] = value
|
|
141
|
-
elif key == "ProductVersion":
|
|
142
|
-
info["ios_version"] = value
|
|
143
|
-
elif key == "DeviceName":
|
|
144
|
-
info["name"] = value
|
|
145
|
-
|
|
146
|
-
return info
|
|
147
|
-
|
|
148
|
-
except Exception:
|
|
149
|
-
return {}
|
|
150
|
-
|
|
151
|
-
def get_device_info(self, device_id: str | None = None) -> DeviceInfo | None:
|
|
152
|
-
"""
|
|
153
|
-
Get detailed information about a device.
|
|
154
|
-
|
|
155
|
-
Args:
|
|
156
|
-
device_id: Device UDID. If None, uses first available device.
|
|
157
|
-
|
|
158
|
-
Returns:
|
|
159
|
-
DeviceInfo or None if not found.
|
|
160
|
-
"""
|
|
161
|
-
devices = self.list_devices()
|
|
162
|
-
|
|
163
|
-
if not devices:
|
|
164
|
-
return None
|
|
165
|
-
|
|
166
|
-
if device_id is None:
|
|
167
|
-
return devices[0]
|
|
168
|
-
|
|
169
|
-
for device in devices:
|
|
170
|
-
if device.device_id == device_id:
|
|
171
|
-
return device
|
|
172
|
-
|
|
173
|
-
return None
|
|
174
|
-
|
|
175
|
-
def is_connected(self, device_id: str | None = None) -> bool:
|
|
176
|
-
"""
|
|
177
|
-
Check if a device is connected.
|
|
178
|
-
|
|
179
|
-
Args:
|
|
180
|
-
device_id: Device UDID to check. If None, checks if any device is connected.
|
|
181
|
-
|
|
182
|
-
Returns:
|
|
183
|
-
True if connected, False otherwise.
|
|
184
|
-
"""
|
|
185
|
-
devices = self.list_devices()
|
|
186
|
-
|
|
187
|
-
if not devices:
|
|
188
|
-
return False
|
|
189
|
-
|
|
190
|
-
if device_id is None:
|
|
191
|
-
return len(devices) > 0
|
|
192
|
-
|
|
193
|
-
return any(d.device_id == device_id for d in devices)
|
|
194
|
-
|
|
195
|
-
def is_wda_ready(self, timeout: int = 2) -> bool:
|
|
196
|
-
"""
|
|
197
|
-
Check if WebDriverAgent is running and accessible.
|
|
198
|
-
|
|
199
|
-
Args:
|
|
200
|
-
timeout: Request timeout in seconds.
|
|
201
|
-
|
|
202
|
-
Returns:
|
|
203
|
-
True if WDA is ready, False otherwise.
|
|
204
|
-
"""
|
|
205
|
-
try:
|
|
206
|
-
import requests
|
|
207
|
-
|
|
208
|
-
response = requests.get(
|
|
209
|
-
f"{self.wda_url}/status", timeout=timeout, verify=False
|
|
210
|
-
)
|
|
211
|
-
return response.status_code == 200
|
|
212
|
-
except ImportError:
|
|
213
|
-
print("Error: requests library not found. Install it: pip install requests")
|
|
214
|
-
return False
|
|
215
|
-
except Exception:
|
|
216
|
-
return False
|
|
217
|
-
|
|
218
|
-
def start_wda_session(self) -> tuple[bool, str]:
|
|
219
|
-
"""
|
|
220
|
-
Start a new WebDriverAgent session.
|
|
221
|
-
|
|
222
|
-
Returns:
|
|
223
|
-
Tuple of (success, session_id or error_message).
|
|
224
|
-
"""
|
|
225
|
-
try:
|
|
226
|
-
import requests
|
|
227
|
-
|
|
228
|
-
response = requests.post(
|
|
229
|
-
f"{self.wda_url}/session",
|
|
230
|
-
json={"capabilities": {}},
|
|
231
|
-
timeout=30,
|
|
232
|
-
verify=False,
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
if response.status_code in (200, 201):
|
|
236
|
-
data = response.json()
|
|
237
|
-
session_id = data.get("sessionId") or data.get("value", {}).get(
|
|
238
|
-
"sessionId"
|
|
239
|
-
)
|
|
240
|
-
return True, session_id or "session_started"
|
|
241
|
-
else:
|
|
242
|
-
return False, f"Failed to start session: {response.text}"
|
|
243
|
-
|
|
244
|
-
except ImportError:
|
|
245
|
-
return (
|
|
246
|
-
False,
|
|
247
|
-
"requests library not found. Install it: pip install requests",
|
|
248
|
-
)
|
|
249
|
-
except Exception as e:
|
|
250
|
-
return False, f"Error starting WDA session: {e}"
|
|
251
|
-
|
|
252
|
-
def get_wda_status(self) -> dict | None:
|
|
253
|
-
"""
|
|
254
|
-
Get WebDriverAgent status information.
|
|
255
|
-
|
|
256
|
-
Returns:
|
|
257
|
-
Status dictionary or None if not available.
|
|
258
|
-
"""
|
|
259
|
-
try:
|
|
260
|
-
import requests
|
|
261
|
-
|
|
262
|
-
response = requests.get(f"{self.wda_url}/status", timeout=5, verify=False)
|
|
263
|
-
|
|
264
|
-
if response.status_code == 200:
|
|
265
|
-
return response.json()
|
|
266
|
-
return None
|
|
267
|
-
|
|
268
|
-
except Exception:
|
|
269
|
-
return None
|
|
270
|
-
|
|
271
|
-
def pair_device(self, device_id: str | None = None) -> tuple[bool, str]:
|
|
272
|
-
"""
|
|
273
|
-
Pair with an iOS device (required for some operations).
|
|
274
|
-
|
|
275
|
-
Args:
|
|
276
|
-
device_id: Device UDID. If None, uses first available device.
|
|
277
|
-
|
|
278
|
-
Returns:
|
|
279
|
-
Tuple of (success, message).
|
|
280
|
-
"""
|
|
281
|
-
try:
|
|
282
|
-
cmd = ["idevicepair"]
|
|
283
|
-
if device_id:
|
|
284
|
-
cmd.extend(["-u", device_id])
|
|
285
|
-
cmd.append("pair")
|
|
286
|
-
|
|
287
|
-
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
|
288
|
-
|
|
289
|
-
output = result.stdout + result.stderr
|
|
290
|
-
|
|
291
|
-
if "SUCCESS" in output or "already paired" in output.lower():
|
|
292
|
-
return True, "Device paired successfully"
|
|
293
|
-
else:
|
|
294
|
-
return False, output.strip()
|
|
295
|
-
|
|
296
|
-
except FileNotFoundError:
|
|
297
|
-
return (
|
|
298
|
-
False,
|
|
299
|
-
"idevicepair not found. Install libimobiledevice: brew install libimobiledevice",
|
|
300
|
-
)
|
|
301
|
-
except Exception as e:
|
|
302
|
-
return False, f"Error pairing device: {e}"
|
|
303
|
-
|
|
304
|
-
def get_device_name(self, device_id: str | None = None) -> str | None:
|
|
305
|
-
"""
|
|
306
|
-
Get the device name.
|
|
307
|
-
|
|
308
|
-
Args:
|
|
309
|
-
device_id: Device UDID. If None, uses first available device.
|
|
310
|
-
|
|
311
|
-
Returns:
|
|
312
|
-
Device name string or None if not found.
|
|
313
|
-
"""
|
|
314
|
-
try:
|
|
315
|
-
cmd = ["ideviceinfo"]
|
|
316
|
-
if device_id:
|
|
317
|
-
cmd.extend(["-u", device_id])
|
|
318
|
-
cmd.extend(["-k", "DeviceName"])
|
|
319
|
-
|
|
320
|
-
result = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
|
|
321
|
-
|
|
322
|
-
return result.stdout.strip() or None
|
|
323
|
-
|
|
324
|
-
except Exception as e:
|
|
325
|
-
print(f"Error getting device name: {e}")
|
|
326
|
-
return None
|
|
327
|
-
|
|
328
|
-
def restart_wda(self) -> tuple[bool, str]:
|
|
329
|
-
"""
|
|
330
|
-
Restart WebDriverAgent (requires manual restart on device).
|
|
331
|
-
|
|
332
|
-
Returns:
|
|
333
|
-
Tuple of (success, message).
|
|
334
|
-
|
|
335
|
-
Note:
|
|
336
|
-
This method only checks if WDA needs restart.
|
|
337
|
-
Actual restart requires re-running WDA on the device via Xcode or other means.
|
|
338
|
-
"""
|
|
339
|
-
if self.is_wda_ready():
|
|
340
|
-
return True, "WDA is already running"
|
|
341
|
-
else:
|
|
342
|
-
return (
|
|
343
|
-
False,
|
|
344
|
-
"WDA is not running. Please start it manually on the device.",
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
def quick_connect(wda_url: str = "http://localhost:8100") -> tuple[bool, str]:
|
|
349
|
-
"""
|
|
350
|
-
Quick helper to check iOS device connection and WDA status.
|
|
351
|
-
|
|
352
|
-
Args:
|
|
353
|
-
wda_url: WebDriverAgent URL.
|
|
354
|
-
|
|
355
|
-
Returns:
|
|
356
|
-
Tuple of (success, message).
|
|
357
|
-
"""
|
|
358
|
-
conn = XCTestConnection(wda_url=wda_url)
|
|
359
|
-
|
|
360
|
-
# Check if device is connected
|
|
361
|
-
if not conn.is_connected():
|
|
362
|
-
return False, "No iOS device connected"
|
|
363
|
-
|
|
364
|
-
# Check if WDA is ready
|
|
365
|
-
if not conn.is_wda_ready():
|
|
366
|
-
return False, "WebDriverAgent is not running"
|
|
367
|
-
|
|
368
|
-
return True, "iOS device connected and WDA ready"
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
def list_devices() -> list[DeviceInfo]:
|
|
372
|
-
"""
|
|
373
|
-
Quick helper to list connected iOS devices.
|
|
374
|
-
|
|
375
|
-
Returns:
|
|
376
|
-
List of DeviceInfo objects.
|
|
377
|
-
"""
|
|
378
|
-
conn = XCTestConnection()
|
|
379
|
-
return conn.list_devices()
|