autoglm-gui 1.0.2__py3-none-any.whl → 1.2.0__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 (38) hide show
  1. AutoGLM_GUI/adb_plus/__init__.py +12 -1
  2. AutoGLM_GUI/adb_plus/mdns.py +192 -0
  3. AutoGLM_GUI/adb_plus/pair.py +60 -0
  4. AutoGLM_GUI/adb_plus/qr_pair.py +372 -0
  5. AutoGLM_GUI/adb_plus/serial.py +61 -2
  6. AutoGLM_GUI/adb_plus/version.py +81 -0
  7. AutoGLM_GUI/api/__init__.py +16 -1
  8. AutoGLM_GUI/api/agents.py +329 -94
  9. AutoGLM_GUI/api/devices.py +304 -100
  10. AutoGLM_GUI/api/workflows.py +70 -0
  11. AutoGLM_GUI/device_manager.py +760 -0
  12. AutoGLM_GUI/exceptions.py +18 -0
  13. AutoGLM_GUI/phone_agent_manager.py +549 -0
  14. AutoGLM_GUI/phone_agent_patches.py +146 -0
  15. AutoGLM_GUI/schemas.py +380 -2
  16. AutoGLM_GUI/state.py +21 -0
  17. AutoGLM_GUI/static/assets/{about-BOnRPlKQ.js → about-PcGX7dIG.js} +1 -1
  18. AutoGLM_GUI/static/assets/chat-B0FKL2ne.js +124 -0
  19. AutoGLM_GUI/static/assets/dialog-BSNX0L1i.js +45 -0
  20. AutoGLM_GUI/static/assets/index-BjYIY--m.css +1 -0
  21. AutoGLM_GUI/static/assets/index-CnEYDOXp.js +11 -0
  22. AutoGLM_GUI/static/assets/index-DOt5XNhh.js +1 -0
  23. AutoGLM_GUI/static/assets/logo-Cyfm06Ym.png +0 -0
  24. AutoGLM_GUI/static/assets/workflows-B1hgBC_O.js +1 -0
  25. AutoGLM_GUI/static/favicon.ico +0 -0
  26. AutoGLM_GUI/static/index.html +9 -2
  27. AutoGLM_GUI/static/logo-192.png +0 -0
  28. AutoGLM_GUI/static/logo-512.png +0 -0
  29. AutoGLM_GUI/workflow_manager.py +181 -0
  30. {autoglm_gui-1.0.2.dist-info → autoglm_gui-1.2.0.dist-info}/METADATA +80 -35
  31. {autoglm_gui-1.0.2.dist-info → autoglm_gui-1.2.0.dist-info}/RECORD +34 -19
  32. AutoGLM_GUI/static/assets/chat-CGW6uMKB.js +0 -149
  33. AutoGLM_GUI/static/assets/index-CRFVU0eu.js +0 -1
  34. AutoGLM_GUI/static/assets/index-DH-Dl4tK.js +0 -10
  35. AutoGLM_GUI/static/assets/index-DzUQ89YC.css +0 -1
  36. {autoglm_gui-1.0.2.dist-info → autoglm_gui-1.2.0.dist-info}/WHEEL +0 -0
  37. {autoglm_gui-1.0.2.dist-info → autoglm_gui-1.2.0.dist-info}/entry_points.txt +0 -0
  38. {autoglm_gui-1.0.2.dist-info → autoglm_gui-1.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,12 +1,61 @@
1
1
  """Get device serial number using ADB."""
2
2
 
3
+ import re
4
+ from typing import Optional
5
+
3
6
  from AutoGLM_GUI.platform_utils import run_cmd_silently_sync
4
7
 
5
8
 
9
+ def extract_serial_from_mdns(device_id: str) -> Optional[str]:
10
+ """
11
+ Extract hardware serial number from mDNS device ID.
12
+
13
+ mDNS service names follow the pattern: adb-{serial}[-{suffix}].{service_type}
14
+
15
+ Examples:
16
+ - "adb-243a09b7-cbCO6P._adb-tls-connect._tcp" → "243a09b7"
17
+ - "adb-243a09b7._adb._tcp" → "243a09b7"
18
+ - "adb-ABC123DEF.local" → "ABC123DEF"
19
+
20
+ Args:
21
+ device_id: The device ID (can be mDNS service name or regular device ID)
22
+
23
+ Returns:
24
+ Extracted serial number, or None if not a valid mDNS format
25
+ """
26
+ # Check if this is an mDNS device ID
27
+ mdns_indicators = [
28
+ "._adb-tls-connect._tcp",
29
+ "._adb-tls-pairing._tcp",
30
+ "._adb._tcp",
31
+ ".local",
32
+ ]
33
+
34
+ if not any(indicator in device_id for indicator in mdns_indicators):
35
+ return None
36
+
37
+ # Pattern: adb-{serial}[-{suffix}].{service_type}
38
+ # The serial is everything after "adb-" until the next hyphen or dot
39
+ # Match alphanumeric characters (not just hex)
40
+ pattern = r"adb-([0-9a-zA-Z]+)"
41
+ match = re.search(pattern, device_id)
42
+
43
+ if match:
44
+ serial = match.group(1)
45
+ # Validate serial format (alphanumeric, typically 6-16 chars)
46
+ if len(serial) >= 6 and serial.isalnum():
47
+ return serial
48
+
49
+ return None
50
+
51
+
6
52
  def get_device_serial(device_id: str, adb_path: str = "adb") -> str | None:
7
53
  """
8
54
  Get the real hardware serial number of a device.
9
55
 
56
+ For mDNS devices, attempts to extract serial from service name first.
57
+ Falls back to getprop for USB/WiFi devices or if extraction fails.
58
+
10
59
  This works for both USB and WiFi connected devices,
11
60
  returning the actual hardware serial number (ro.serialno).
12
61
 
@@ -17,6 +66,15 @@ def get_device_serial(device_id: str, adb_path: str = "adb") -> str | None:
17
66
  Returns:
18
67
  The device hardware serial number, or None if failed
19
68
  """
69
+ from AutoGLM_GUI.logger import logger
70
+
71
+ # Fast path: Try mDNS extraction first
72
+ mdns_serial = extract_serial_from_mdns(device_id)
73
+ if mdns_serial:
74
+ logger.debug(f"Extracted serial from mDNS name: {device_id} → {mdns_serial}")
75
+ return mdns_serial
76
+
77
+ # Fallback: Use getprop (original behavior)
20
78
  try:
21
79
  # Use getprop to get the actual hardware serial number
22
80
  # This works for both USB and WiFi connections
@@ -28,8 +86,9 @@ def get_device_serial(device_id: str, adb_path: str = "adb") -> str | None:
28
86
  serial = result.stdout.strip()
29
87
  # Filter out error messages and empty values
30
88
  if serial and not serial.startswith("error:") and serial != "unknown":
89
+ logger.debug(f"Got serial via getprop: {device_id} → {serial}")
31
90
  return serial
32
- except Exception:
33
- pass
91
+ except Exception as e:
92
+ logger.debug(f"Failed to get serial via getprop for {device_id}: {e}")
34
93
 
35
94
  return None
@@ -0,0 +1,81 @@
1
+ """ADB version detection and feature support checking."""
2
+
3
+ import re
4
+ from typing import Optional, Tuple
5
+
6
+ from AutoGLM_GUI.logger import logger
7
+ from AutoGLM_GUI.platform_utils import run_cmd_silently_sync
8
+
9
+
10
+ def get_adb_version(adb_path: str = "adb") -> Optional[Tuple[int, int, int]]:
11
+ """
12
+ Get ADB version as (major, minor, patch) tuple.
13
+
14
+ Args:
15
+ adb_path: Path to adb executable
16
+
17
+ Returns:
18
+ Version tuple or None if failed
19
+
20
+ Example:
21
+ >>> get_adb_version()
22
+ (34, 0, 5) # ADB version 34.0.5
23
+ """
24
+ try:
25
+ result = run_cmd_silently_sync([adb_path, "version"], timeout=3)
26
+
27
+ if result.returncode != 0:
28
+ return None
29
+
30
+ # Parse "Android Debug Bridge version 1.0.41"
31
+ # Or "Version 34.0.5-11580240"
32
+ match = re.search(r"version (\d+)\.(\d+)\.(\d+)", result.stdout, re.IGNORECASE)
33
+ if match:
34
+ return (int(match.group(1)), int(match.group(2)), int(match.group(3)))
35
+
36
+ # Legacy format: "Android Debug Bridge version 1.0.XX"
37
+ match = re.search(r"version 1\.0\.(\d+)", result.stdout)
38
+ if match:
39
+ return (1, 0, int(match.group(1)))
40
+
41
+ return None
42
+
43
+ except Exception as e:
44
+ logger.debug(f"Failed to get ADB version: {e}")
45
+ return None
46
+
47
+
48
+ def supports_mdns_services(adb_path: str = "adb") -> bool:
49
+ """
50
+ Check if ADB supports 'mdns services' command.
51
+
52
+ This feature was added in ADB 30.0.0+ (Android 11 SDK Platform Tools).
53
+
54
+ Args:
55
+ adb_path: Path to adb executable
56
+
57
+ Returns:
58
+ True if supported, False otherwise
59
+ """
60
+ # Quick feature detection: try running the command
61
+ try:
62
+ result = run_cmd_silently_sync([adb_path, "mdns", "services"], timeout=5)
63
+
64
+ # If command succeeds or returns "List of discovered mdns services", it's supported
65
+ if result.returncode == 0 or "mdns services" in result.stdout.lower():
66
+ return True
67
+
68
+ # Check for "unknown command" error
69
+ stderr_lower = result.stderr.lower()
70
+ if "unknown" in stderr_lower or "not found" in stderr_lower:
71
+ logger.info(
72
+ "ADB does not support 'mdns services' command (requires ADB 30.0.0+)"
73
+ )
74
+ return False
75
+
76
+ # If we get here, assume not supported
77
+ return False
78
+
79
+ except Exception as e:
80
+ logger.debug(f"Failed to check mDNS support: {e}")
81
+ return False
@@ -1,5 +1,6 @@
1
1
  """FastAPI application factory and route registration."""
2
2
 
3
+ import asyncio
3
4
  import sys
4
5
  from importlib.resources import files
5
6
  from pathlib import Path
@@ -10,8 +11,9 @@ from fastapi.responses import FileResponse
10
11
  from fastapi.staticfiles import StaticFiles
11
12
 
12
13
  from AutoGLM_GUI.version import APP_VERSION
14
+ from AutoGLM_GUI.adb_plus.qr_pair import qr_pairing_manager
13
15
 
14
- from . import agents, control, devices, media, version
16
+ from . import agents, control, devices, media, version, workflows
15
17
 
16
18
 
17
19
  def _get_static_dir() -> Path | None:
@@ -55,6 +57,19 @@ def create_app() -> FastAPI:
55
57
  app.include_router(control.router)
56
58
  app.include_router(media.router)
57
59
  app.include_router(version.router)
60
+ app.include_router(workflows.router)
61
+
62
+ @app.on_event("startup")
63
+ async def startup_event():
64
+ """Initialize background tasks on server startup."""
65
+ # Start QR pairing session cleanup task
66
+ asyncio.create_task(qr_pairing_manager.cleanup_expired_sessions())
67
+
68
+ # Start device polling
69
+ from AutoGLM_GUI.device_manager import DeviceManager
70
+
71
+ device_manager = DeviceManager.get_instance()
72
+ device_manager.start_polling()
58
73
 
59
74
  static_dir = _get_static_dir()
60
75
  if static_dir is not None and static_dir.exists():