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.
Files changed (97) hide show
  1. AutoGLM_GUI/__init__.py +1 -1
  2. AutoGLM_GUI/__main__.py +11 -2
  3. AutoGLM_GUI/adb_plus/qr_pair.py +3 -3
  4. AutoGLM_GUI/agents/__init__.py +7 -2
  5. AutoGLM_GUI/agents/factory.py +46 -6
  6. AutoGLM_GUI/agents/glm/agent.py +8 -3
  7. AutoGLM_GUI/agents/glm/async_agent.py +515 -0
  8. AutoGLM_GUI/agents/glm/parser.py +4 -2
  9. AutoGLM_GUI/agents/mai/agent.py +3 -0
  10. AutoGLM_GUI/agents/protocols.py +111 -1
  11. AutoGLM_GUI/agents/stream_runner.py +11 -7
  12. AutoGLM_GUI/api/__init__.py +3 -1
  13. AutoGLM_GUI/api/agents.py +103 -37
  14. AutoGLM_GUI/api/devices.py +72 -0
  15. AutoGLM_GUI/api/history.py +27 -1
  16. AutoGLM_GUI/api/layered_agent.py +9 -8
  17. AutoGLM_GUI/api/mcp.py +6 -4
  18. AutoGLM_GUI/config_manager.py +38 -1
  19. AutoGLM_GUI/device_manager.py +28 -4
  20. AutoGLM_GUI/device_metadata_manager.py +174 -0
  21. AutoGLM_GUI/devices/mock_device.py +8 -1
  22. AutoGLM_GUI/models/history.py +45 -1
  23. AutoGLM_GUI/phone_agent_manager.py +145 -32
  24. AutoGLM_GUI/scheduler_manager.py +52 -6
  25. AutoGLM_GUI/schemas.py +101 -0
  26. AutoGLM_GUI/scrcpy_stream.py +2 -1
  27. AutoGLM_GUI/static/assets/{about-BQm96DAl.js → about-D7r9gCvG.js} +1 -1
  28. AutoGLM_GUI/static/assets/{alert-dialog-B42XxGPR.js → alert-dialog-BKM-yRiQ.js} +1 -1
  29. AutoGLM_GUI/static/assets/chat-k6TTD7PW.js +129 -0
  30. AutoGLM_GUI/static/assets/{circle-alert-D4rSJh37.js → circle-alert-sohSDLhl.js} +1 -1
  31. AutoGLM_GUI/static/assets/{dialog-DZ78cEcj.js → dialog-BgtPh0d5.js} +1 -1
  32. AutoGLM_GUI/static/assets/eye-DLqKbQmg.js +1 -0
  33. AutoGLM_GUI/static/assets/history-Bv1lfGUU.js +1 -0
  34. AutoGLM_GUI/static/assets/index-CV7jGxGm.css +1 -0
  35. AutoGLM_GUI/static/assets/index-CxWwh1VO.js +1 -0
  36. AutoGLM_GUI/static/assets/{index-CssG-3TH.js → index-SysdKciY.js} +5 -5
  37. AutoGLM_GUI/static/assets/label-DTUnzN4B.js +1 -0
  38. AutoGLM_GUI/static/assets/{logs-eoFxn5of.js → logs-BIhnDizW.js} +1 -1
  39. AutoGLM_GUI/static/assets/{popover-DLsuV5Sx.js → popover-CikYqu2P.js} +1 -1
  40. AutoGLM_GUI/static/assets/scheduled-tasks-B-KBsGbl.js +1 -0
  41. AutoGLM_GUI/static/assets/{textarea-BX6y7uM5.js → textarea-knJZrz77.js} +1 -1
  42. AutoGLM_GUI/static/assets/workflows-DzcSYwLZ.js +1 -0
  43. AutoGLM_GUI/static/index.html +2 -2
  44. {autoglm_gui-1.5.0.dist-info → autoglm_gui-1.5.2.dist-info}/METADATA +58 -7
  45. autoglm_gui-1.5.2.dist-info/RECORD +119 -0
  46. AutoGLM_GUI/device_adapter.py +0 -263
  47. AutoGLM_GUI/static/assets/chat-C0L2gQYG.js +0 -129
  48. AutoGLM_GUI/static/assets/history-DFBv7TGc.js +0 -1
  49. AutoGLM_GUI/static/assets/index-Bzyv2yQ2.css +0 -1
  50. AutoGLM_GUI/static/assets/index-CmZSnDqc.js +0 -1
  51. AutoGLM_GUI/static/assets/label-BCUzE_nm.js +0 -1
  52. AutoGLM_GUI/static/assets/scheduled-tasks-MyqGJvy_.js +0 -1
  53. AutoGLM_GUI/static/assets/square-pen-zGWYrdfj.js +0 -1
  54. AutoGLM_GUI/static/assets/workflows-CYFs6ssC.js +0 -1
  55. autoglm_gui-1.5.0.dist-info/RECORD +0 -157
  56. mai_agent/base.py +0 -137
  57. mai_agent/mai_grounding_agent.py +0 -263
  58. mai_agent/mai_naivigation_agent.py +0 -526
  59. mai_agent/prompt.py +0 -148
  60. mai_agent/unified_memory.py +0 -67
  61. mai_agent/utils.py +0 -73
  62. phone_agent/__init__.py +0 -12
  63. phone_agent/actions/__init__.py +0 -5
  64. phone_agent/actions/handler.py +0 -400
  65. phone_agent/actions/handler_ios.py +0 -278
  66. phone_agent/adb/__init__.py +0 -51
  67. phone_agent/adb/connection.py +0 -358
  68. phone_agent/adb/device.py +0 -253
  69. phone_agent/adb/input.py +0 -108
  70. phone_agent/adb/screenshot.py +0 -108
  71. phone_agent/agent.py +0 -253
  72. phone_agent/agent_ios.py +0 -277
  73. phone_agent/config/__init__.py +0 -53
  74. phone_agent/config/apps.py +0 -227
  75. phone_agent/config/apps_harmonyos.py +0 -256
  76. phone_agent/config/apps_ios.py +0 -339
  77. phone_agent/config/i18n.py +0 -81
  78. phone_agent/config/prompts.py +0 -80
  79. phone_agent/config/prompts_en.py +0 -79
  80. phone_agent/config/prompts_zh.py +0 -82
  81. phone_agent/config/timing.py +0 -167
  82. phone_agent/device_factory.py +0 -166
  83. phone_agent/hdc/__init__.py +0 -53
  84. phone_agent/hdc/connection.py +0 -384
  85. phone_agent/hdc/device.py +0 -269
  86. phone_agent/hdc/input.py +0 -145
  87. phone_agent/hdc/screenshot.py +0 -127
  88. phone_agent/model/__init__.py +0 -5
  89. phone_agent/model/client.py +0 -290
  90. phone_agent/xctest/__init__.py +0 -47
  91. phone_agent/xctest/connection.py +0 -379
  92. phone_agent/xctest/device.py +0 -472
  93. phone_agent/xctest/input.py +0 -311
  94. phone_agent/xctest/screenshot.py +0 -226
  95. {autoglm_gui-1.5.0.dist-info → autoglm_gui-1.5.2.dist-info}/WHEEL +0 -0
  96. {autoglm_gui-1.5.0.dist-info → autoglm_gui-1.5.2.dist-info}/entry_points.txt +0 -0
  97. {autoglm_gui-1.5.0.dist-info → autoglm_gui-1.5.2.dist-info}/licenses/LICENSE +0 -0
phone_agent/adb/device.py DELETED
@@ -1,253 +0,0 @@
1
- """Device control utilities for Android automation."""
2
-
3
- import subprocess
4
- import time
5
-
6
- from phone_agent.config.apps import APP_PACKAGES
7
- from phone_agent.config.timing import TIMING_CONFIG
8
-
9
-
10
- def get_current_app(device_id: str | None = None) -> str:
11
- """
12
- Get the currently focused app name.
13
-
14
- Args:
15
- device_id: Optional ADB device ID for multi-device setups.
16
-
17
- Returns:
18
- The app name if recognized, otherwise "System Home".
19
- """
20
- adb_prefix = _get_adb_prefix(device_id)
21
-
22
- result = subprocess.run(
23
- adb_prefix + ["shell", "dumpsys", "window"],
24
- capture_output=True,
25
- text=True,
26
- encoding="utf-8",
27
- )
28
- output = result.stdout
29
- if not output:
30
- raise ValueError("No output from dumpsys window")
31
-
32
- # Parse window focus info
33
- for line in output.split("\n"):
34
- if "mCurrentFocus" in line or "mFocusedApp" in line:
35
- for app_name, package in APP_PACKAGES.items():
36
- if package in line:
37
- return app_name
38
-
39
- return "System Home"
40
-
41
-
42
- def tap(
43
- x: int, y: int, device_id: str | None = None, delay: float | None = None
44
- ) -> None:
45
- """
46
- Tap at the specified coordinates.
47
-
48
- Args:
49
- x: X coordinate.
50
- y: Y coordinate.
51
- device_id: Optional ADB device ID.
52
- delay: Delay in seconds after tap. If None, uses configured default.
53
- """
54
- if delay is None:
55
- delay = TIMING_CONFIG.device.default_tap_delay
56
-
57
- adb_prefix = _get_adb_prefix(device_id)
58
-
59
- subprocess.run(
60
- adb_prefix + ["shell", "input", "tap", str(x), str(y)], capture_output=True
61
- )
62
- time.sleep(delay)
63
-
64
-
65
- def double_tap(
66
- x: int, y: int, device_id: str | None = None, delay: float | None = None
67
- ) -> None:
68
- """
69
- Double tap at the specified coordinates.
70
-
71
- Args:
72
- x: X coordinate.
73
- y: Y coordinate.
74
- device_id: Optional ADB device ID.
75
- delay: Delay in seconds after double tap. If None, uses configured default.
76
- """
77
- if delay is None:
78
- delay = TIMING_CONFIG.device.default_double_tap_delay
79
-
80
- adb_prefix = _get_adb_prefix(device_id)
81
-
82
- subprocess.run(
83
- adb_prefix + ["shell", "input", "tap", str(x), str(y)], capture_output=True
84
- )
85
- time.sleep(TIMING_CONFIG.device.double_tap_interval)
86
- subprocess.run(
87
- adb_prefix + ["shell", "input", "tap", str(x), str(y)], capture_output=True
88
- )
89
- time.sleep(delay)
90
-
91
-
92
- def long_press(
93
- x: int,
94
- y: int,
95
- duration_ms: int = 3000,
96
- device_id: str | None = None,
97
- delay: float | None = None,
98
- ) -> None:
99
- """
100
- Long press at the specified coordinates.
101
-
102
- Args:
103
- x: X coordinate.
104
- y: Y coordinate.
105
- duration_ms: Duration of press in milliseconds.
106
- device_id: Optional ADB device ID.
107
- delay: Delay in seconds after long press. If None, uses configured default.
108
- """
109
- if delay is None:
110
- delay = TIMING_CONFIG.device.default_long_press_delay
111
-
112
- adb_prefix = _get_adb_prefix(device_id)
113
-
114
- subprocess.run(
115
- adb_prefix
116
- + ["shell", "input", "swipe", str(x), str(y), str(x), str(y), str(duration_ms)],
117
- capture_output=True,
118
- )
119
- time.sleep(delay)
120
-
121
-
122
- def swipe(
123
- start_x: int,
124
- start_y: int,
125
- end_x: int,
126
- end_y: int,
127
- duration_ms: int | None = None,
128
- device_id: str | None = None,
129
- delay: float | None = None,
130
- ) -> None:
131
- """
132
- Swipe from start to end coordinates.
133
-
134
- Args:
135
- start_x: Starting X coordinate.
136
- start_y: Starting Y coordinate.
137
- end_x: Ending X coordinate.
138
- end_y: Ending Y coordinate.
139
- duration_ms: Duration of swipe in milliseconds (auto-calculated if None).
140
- device_id: Optional ADB device ID.
141
- delay: Delay in seconds after swipe. If None, uses configured default.
142
- """
143
- if delay is None:
144
- delay = TIMING_CONFIG.device.default_swipe_delay
145
-
146
- adb_prefix = _get_adb_prefix(device_id)
147
-
148
- if duration_ms is None:
149
- # Calculate duration based on distance
150
- dist_sq = (start_x - end_x) ** 2 + (start_y - end_y) ** 2
151
- duration_ms = int(dist_sq / 1000)
152
- duration_ms = max(1000, min(duration_ms, 2000)) # Clamp between 1000-2000ms
153
-
154
- subprocess.run(
155
- adb_prefix
156
- + [
157
- "shell",
158
- "input",
159
- "swipe",
160
- str(start_x),
161
- str(start_y),
162
- str(end_x),
163
- str(end_y),
164
- str(duration_ms),
165
- ],
166
- capture_output=True,
167
- )
168
- time.sleep(delay)
169
-
170
-
171
- def back(device_id: str | None = None, delay: float | None = None) -> None:
172
- """
173
- Press the back button.
174
-
175
- Args:
176
- device_id: Optional ADB device ID.
177
- delay: Delay in seconds after pressing back. If None, uses configured default.
178
- """
179
- if delay is None:
180
- delay = TIMING_CONFIG.device.default_back_delay
181
-
182
- adb_prefix = _get_adb_prefix(device_id)
183
-
184
- subprocess.run(
185
- adb_prefix + ["shell", "input", "keyevent", "4"], capture_output=True
186
- )
187
- time.sleep(delay)
188
-
189
-
190
- def home(device_id: str | None = None, delay: float | None = None) -> None:
191
- """
192
- Press the home button.
193
-
194
- Args:
195
- device_id: Optional ADB device ID.
196
- delay: Delay in seconds after pressing home. If None, uses configured default.
197
- """
198
- if delay is None:
199
- delay = TIMING_CONFIG.device.default_home_delay
200
-
201
- adb_prefix = _get_adb_prefix(device_id)
202
-
203
- subprocess.run(
204
- adb_prefix + ["shell", "input", "keyevent", "KEYCODE_HOME"], capture_output=True
205
- )
206
- time.sleep(delay)
207
-
208
-
209
- def launch_app(
210
- app_name: str, device_id: str | None = None, delay: float | None = None
211
- ) -> bool:
212
- """
213
- Launch an app by name.
214
-
215
- Args:
216
- app_name: The app name (must be in APP_PACKAGES).
217
- device_id: Optional ADB device ID.
218
- delay: Delay in seconds after launching. If None, uses configured default.
219
-
220
- Returns:
221
- True if app was launched, False if app not found.
222
- """
223
- if delay is None:
224
- delay = TIMING_CONFIG.device.default_launch_delay
225
-
226
- if app_name not in APP_PACKAGES:
227
- return False
228
-
229
- adb_prefix = _get_adb_prefix(device_id)
230
- package = APP_PACKAGES[app_name]
231
-
232
- subprocess.run(
233
- adb_prefix
234
- + [
235
- "shell",
236
- "monkey",
237
- "-p",
238
- package,
239
- "-c",
240
- "android.intent.category.LAUNCHER",
241
- "1",
242
- ],
243
- capture_output=True,
244
- )
245
- time.sleep(delay)
246
- return True
247
-
248
-
249
- def _get_adb_prefix(device_id: str | None) -> list:
250
- """Get ADB command prefix with optional device specifier."""
251
- if device_id:
252
- return ["adb", "-s", device_id]
253
- return ["adb"]
phone_agent/adb/input.py DELETED
@@ -1,108 +0,0 @@
1
- """Input utilities for Android device text input."""
2
-
3
- import base64
4
- import subprocess
5
-
6
-
7
- def type_text(text: str, device_id: str | None = None) -> None:
8
- """
9
- Type text into the currently focused input field using ADB Keyboard.
10
-
11
- Args:
12
- text: The text to type.
13
- device_id: Optional ADB device ID for multi-device setups.
14
-
15
- Note:
16
- Requires ADB Keyboard to be installed on the device.
17
- See: https://github.com/nicnocquee/AdbKeyboard
18
- """
19
- adb_prefix = _get_adb_prefix(device_id)
20
- encoded_text = base64.b64encode(text.encode("utf-8")).decode("utf-8")
21
-
22
- subprocess.run(
23
- adb_prefix
24
- + [
25
- "shell",
26
- "am",
27
- "broadcast",
28
- "-a",
29
- "ADB_INPUT_B64",
30
- "--es",
31
- "msg",
32
- encoded_text,
33
- ],
34
- capture_output=True,
35
- text=True,
36
- )
37
-
38
-
39
- def clear_text(device_id: str | None = None) -> None:
40
- """
41
- Clear text in the currently focused input field.
42
-
43
- Args:
44
- device_id: Optional ADB device ID for multi-device setups.
45
- """
46
- adb_prefix = _get_adb_prefix(device_id)
47
-
48
- subprocess.run(
49
- adb_prefix + ["shell", "am", "broadcast", "-a", "ADB_CLEAR_TEXT"],
50
- capture_output=True,
51
- text=True,
52
- )
53
-
54
-
55
- def detect_and_set_adb_keyboard(device_id: str | None = None) -> str:
56
- """
57
- Detect current keyboard and switch to ADB Keyboard if needed.
58
-
59
- Args:
60
- device_id: Optional ADB device ID for multi-device setups.
61
-
62
- Returns:
63
- The original keyboard IME identifier for later restoration.
64
- """
65
- adb_prefix = _get_adb_prefix(device_id)
66
-
67
- # Get current IME
68
- result = subprocess.run(
69
- adb_prefix + ["shell", "settings", "get", "secure", "default_input_method"],
70
- capture_output=True,
71
- text=True,
72
- )
73
- current_ime = (result.stdout + result.stderr).strip()
74
-
75
- # Switch to ADB Keyboard if not already set
76
- if "com.android.adbkeyboard/.AdbIME" not in current_ime:
77
- subprocess.run(
78
- adb_prefix + ["shell", "ime", "set", "com.android.adbkeyboard/.AdbIME"],
79
- capture_output=True,
80
- text=True,
81
- )
82
-
83
- # Warm up the keyboard
84
- type_text("", device_id)
85
-
86
- return current_ime
87
-
88
-
89
- def restore_keyboard(ime: str, device_id: str | None = None) -> None:
90
- """
91
- Restore the original keyboard IME.
92
-
93
- Args:
94
- ime: The IME identifier to restore.
95
- device_id: Optional ADB device ID for multi-device setups.
96
- """
97
- adb_prefix = _get_adb_prefix(device_id)
98
-
99
- subprocess.run(
100
- adb_prefix + ["shell", "ime", "set", ime], capture_output=True, text=True
101
- )
102
-
103
-
104
- def _get_adb_prefix(device_id: str | None) -> list:
105
- """Get ADB command prefix with optional device specifier."""
106
- if device_id:
107
- return ["adb", "-s", device_id]
108
- return ["adb"]
@@ -1,108 +0,0 @@
1
- """Screenshot utilities for capturing Android device screen."""
2
-
3
- import base64
4
- import os
5
- import subprocess
6
- import tempfile
7
- import uuid
8
- from dataclasses import dataclass
9
- from io import BytesIO
10
-
11
- from PIL import Image
12
-
13
-
14
- @dataclass
15
- class Screenshot:
16
- """Represents a captured screenshot."""
17
-
18
- base64_data: str
19
- width: int
20
- height: int
21
- is_sensitive: bool = False
22
-
23
-
24
- def get_screenshot(device_id: str | None = None, timeout: int = 10) -> Screenshot:
25
- """
26
- Capture a screenshot from the connected Android device.
27
-
28
- Args:
29
- device_id: Optional ADB device ID for multi-device setups.
30
- timeout: Timeout in seconds for screenshot operations.
31
-
32
- Returns:
33
- Screenshot object containing base64 data and dimensions.
34
-
35
- Note:
36
- If the screenshot fails (e.g., on sensitive screens like payment pages),
37
- a black fallback image is returned with is_sensitive=True.
38
- """
39
- temp_path = os.path.join(tempfile.gettempdir(), f"screenshot_{uuid.uuid4()}.png")
40
- adb_prefix = _get_adb_prefix(device_id)
41
-
42
- try:
43
- # Execute screenshot command
44
- result = subprocess.run(
45
- adb_prefix + ["shell", "screencap", "-p", "/sdcard/tmp.png"],
46
- capture_output=True,
47
- text=True,
48
- timeout=timeout,
49
- )
50
-
51
- # Check for screenshot failure (sensitive screen)
52
- output = result.stdout + result.stderr
53
- if "Status: -1" in output or "Failed" in output:
54
- return _create_fallback_screenshot(is_sensitive=True)
55
-
56
- # Pull screenshot to local temp path
57
- subprocess.run(
58
- adb_prefix + ["pull", "/sdcard/tmp.png", temp_path],
59
- capture_output=True,
60
- text=True,
61
- timeout=5,
62
- )
63
-
64
- if not os.path.exists(temp_path):
65
- return _create_fallback_screenshot(is_sensitive=False)
66
-
67
- # Read and encode image
68
- img = Image.open(temp_path)
69
- width, height = img.size
70
-
71
- buffered = BytesIO()
72
- img.save(buffered, format="PNG")
73
- base64_data = base64.b64encode(buffered.getvalue()).decode("utf-8")
74
-
75
- # Cleanup
76
- os.remove(temp_path)
77
-
78
- return Screenshot(
79
- base64_data=base64_data, width=width, height=height, is_sensitive=False
80
- )
81
-
82
- except Exception as e:
83
- print(f"Screenshot error: {e}")
84
- return _create_fallback_screenshot(is_sensitive=False)
85
-
86
-
87
- def _get_adb_prefix(device_id: str | None) -> list:
88
- """Get ADB command prefix with optional device specifier."""
89
- if device_id:
90
- return ["adb", "-s", device_id]
91
- return ["adb"]
92
-
93
-
94
- def _create_fallback_screenshot(is_sensitive: bool) -> Screenshot:
95
- """Create a black fallback image when screenshot fails."""
96
- default_width, default_height = 1080, 2400
97
-
98
- black_img = Image.new("RGB", (default_width, default_height), color="black")
99
- buffered = BytesIO()
100
- black_img.save(buffered, format="PNG")
101
- base64_data = base64.b64encode(buffered.getvalue()).decode("utf-8")
102
-
103
- return Screenshot(
104
- base64_data=base64_data,
105
- width=default_width,
106
- height=default_height,
107
- is_sensitive=is_sensitive,
108
- )