autoglm-gui 1.3.1__py3-none-any.whl → 1.4.1__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 (61) hide show
  1. AutoGLM_GUI/__main__.py +0 -4
  2. AutoGLM_GUI/adb_plus/qr_pair.py +8 -8
  3. AutoGLM_GUI/agents/__init__.py +20 -0
  4. AutoGLM_GUI/agents/factory.py +160 -0
  5. AutoGLM_GUI/agents/mai_adapter.py +627 -0
  6. AutoGLM_GUI/agents/protocols.py +23 -0
  7. AutoGLM_GUI/api/__init__.py +50 -7
  8. AutoGLM_GUI/api/agents.py +61 -19
  9. AutoGLM_GUI/api/devices.py +12 -18
  10. AutoGLM_GUI/api/dual_model.py +24 -17
  11. AutoGLM_GUI/api/health.py +13 -0
  12. AutoGLM_GUI/api/layered_agent.py +659 -0
  13. AutoGLM_GUI/api/mcp.py +11 -10
  14. AutoGLM_GUI/api/version.py +23 -10
  15. AutoGLM_GUI/api/workflows.py +2 -1
  16. AutoGLM_GUI/config_manager.py +56 -24
  17. AutoGLM_GUI/device_adapter.py +263 -0
  18. AutoGLM_GUI/device_protocol.py +266 -0
  19. AutoGLM_GUI/devices/__init__.py +49 -0
  20. AutoGLM_GUI/devices/adb_device.py +205 -0
  21. AutoGLM_GUI/devices/mock_device.py +183 -0
  22. AutoGLM_GUI/devices/remote_device.py +172 -0
  23. AutoGLM_GUI/dual_model/decision_model.py +4 -4
  24. AutoGLM_GUI/dual_model/protocols.py +3 -3
  25. AutoGLM_GUI/exceptions.py +3 -3
  26. AutoGLM_GUI/mai_ui_adapter/agent_wrapper.py +291 -0
  27. AutoGLM_GUI/metrics.py +13 -20
  28. AutoGLM_GUI/phone_agent_manager.py +219 -134
  29. AutoGLM_GUI/phone_agent_patches.py +2 -1
  30. AutoGLM_GUI/platform_utils.py +5 -2
  31. AutoGLM_GUI/prompts.py +6 -1
  32. AutoGLM_GUI/schemas.py +45 -14
  33. AutoGLM_GUI/scrcpy_stream.py +17 -13
  34. AutoGLM_GUI/server.py +3 -1
  35. AutoGLM_GUI/socketio_server.py +16 -4
  36. AutoGLM_GUI/state.py +10 -30
  37. AutoGLM_GUI/static/assets/{about-Cj6QXqMf.js → about-_XNhzQZX.js} +1 -1
  38. AutoGLM_GUI/static/assets/chat-DwJpiAWf.js +126 -0
  39. AutoGLM_GUI/static/assets/{dialog-CxJlnjzH.js → dialog-B3uW4T8V.js} +3 -3
  40. AutoGLM_GUI/static/assets/index-Cpv2gSF1.css +1 -0
  41. AutoGLM_GUI/static/assets/{index-C_B-Arvf.js → index-Cy8TmmHV.js} +1 -1
  42. AutoGLM_GUI/static/assets/{index-CxJQuE4y.js → index-UYYauTly.js} +6 -6
  43. AutoGLM_GUI/static/assets/{workflows-BTiGCNI0.js → workflows-Du_de-dt.js} +1 -1
  44. AutoGLM_GUI/static/index.html +2 -2
  45. AutoGLM_GUI/types.py +125 -0
  46. {autoglm_gui-1.3.1.dist-info → autoglm_gui-1.4.1.dist-info}/METADATA +147 -65
  47. {autoglm_gui-1.3.1.dist-info → autoglm_gui-1.4.1.dist-info}/RECORD +58 -39
  48. mai_agent/base.py +137 -0
  49. mai_agent/mai_grounding_agent.py +263 -0
  50. mai_agent/mai_naivigation_agent.py +526 -0
  51. mai_agent/prompt.py +148 -0
  52. mai_agent/unified_memory.py +67 -0
  53. mai_agent/utils.py +73 -0
  54. phone_agent/config/prompts.py +6 -1
  55. phone_agent/config/prompts_zh.py +6 -1
  56. AutoGLM_GUI/config.py +0 -23
  57. AutoGLM_GUI/static/assets/chat-BJeomZgh.js +0 -124
  58. AutoGLM_GUI/static/assets/index-Z0uYCPOO.css +0 -1
  59. {autoglm_gui-1.3.1.dist-info → autoglm_gui-1.4.1.dist-info}/WHEEL +0 -0
  60. {autoglm_gui-1.3.1.dist-info → autoglm_gui-1.4.1.dist-info}/entry_points.txt +0 -0
  61. {autoglm_gui-1.3.1.dist-info → autoglm_gui-1.4.1.dist-info}/licenses/LICENSE +0 -0
AutoGLM_GUI/__main__.py CHANGED
@@ -140,7 +140,6 @@ def main() -> None:
140
140
  import uvicorn
141
141
 
142
142
  from AutoGLM_GUI import server
143
- from AutoGLM_GUI.config import config
144
143
  from AutoGLM_GUI.config_manager import config_manager
145
144
  from AutoGLM_GUI.logger import configure_logger
146
145
 
@@ -170,9 +169,6 @@ def main() -> None:
170
169
  # 5. 同步到环境变量(reload 模式需要)
171
170
  config_manager.sync_to_env()
172
171
 
173
- # 6. 刷新旧的 config 对象(保持现有代码兼容)
174
- config.refresh_from_env()
175
-
176
172
  # 获取配置来源
177
173
  config_source = config_manager.get_config_source()
178
174
 
@@ -124,9 +124,9 @@ class QRPairingListener(ServiceListener):
124
124
 
125
125
  self.last_paired_host: Optional[str] = None
126
126
 
127
- def add_service(self, zc: Zeroconf, service_type: str, name: str) -> None:
127
+ def add_service(self, zc: Zeroconf, type_: str, name: str) -> None:
128
128
  """Handle new service discovery."""
129
- info = zc.get_service_info(service_type, name, timeout=3000)
129
+ info = zc.get_service_info(type_, name, timeout=3000)
130
130
  if not info:
131
131
  logger.debug(f"[QR Pair] No info for service: {name}")
132
132
  return
@@ -144,7 +144,7 @@ class QRPairingListener(ServiceListener):
144
144
  key = (host, port)
145
145
 
146
146
  # Handle pairing service
147
- if service_type == PAIR_SERVICE_TYPE and not self.paired:
147
+ if type_ == PAIR_SERVICE_TYPE and not self.paired:
148
148
  if key in self.attempted_pair:
149
149
  logger.debug(f"[QR Pair] Already attempted pairing for {host}:{port}")
150
150
  return
@@ -161,7 +161,7 @@ class QRPairingListener(ServiceListener):
161
161
  logger.info("[QR Pair] Pairing OK. Waiting for connect service...")
162
162
 
163
163
  # Handle connect service
164
- if service_type == CONNECT_SERVICE_TYPE and self.paired and not self.connected:
164
+ if type_ == CONNECT_SERVICE_TYPE and self.paired and not self.connected:
165
165
  # Prefer same host as paired if we have it
166
166
  if self.last_paired_host and host != self.last_paired_host:
167
167
  logger.debug(
@@ -186,13 +186,13 @@ class QRPairingListener(ServiceListener):
186
186
  self.session.device_id = f"{host}:{port}"
187
187
  logger.info(f"[QR Pair] Connected! Device ID: {self.session.device_id}")
188
188
 
189
- def update_service(self, zc: Zeroconf, service_type: str, name: str) -> None:
189
+ def update_service(self, zc: Zeroconf, type_: str, name: str) -> None:
190
190
  """Handle service updates (treat as adds)."""
191
- self.add_service(zc, service_type, name)
191
+ self.add_service(zc, type_, name)
192
192
 
193
- def remove_service(self, _zc: Zeroconf, _service_type: str, _name: str) -> None:
193
+ def remove_service(self, zc: Zeroconf, type_: str, name: str) -> None:
194
194
  """Handle service removal (no action needed)."""
195
- pass
195
+ _ = (zc, type_, name) # Mark as intentionally unused
196
196
 
197
197
 
198
198
  class QRPairingManager:
@@ -0,0 +1,20 @@
1
+ """Agent adapters and factory for different agent implementations."""
2
+
3
+ from .factory import (
4
+ create_agent,
5
+ is_agent_type_registered,
6
+ list_agent_types,
7
+ register_agent,
8
+ )
9
+ from .mai_adapter import MAIAgentAdapter, MAIAgentConfig
10
+
11
+ __all__ = [
12
+ # Factory
13
+ "create_agent",
14
+ "register_agent",
15
+ "list_agent_types",
16
+ "is_agent_type_registered",
17
+ # Adapters
18
+ "MAIAgentAdapter",
19
+ "MAIAgentConfig",
20
+ ]
@@ -0,0 +1,160 @@
1
+ """Agent factory for creating different agent implementations.
2
+
3
+ This module provides a factory pattern + registry for creating agents,
4
+ making it easy to add new agent types without modifying existing code.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import TYPE_CHECKING, Callable, Dict
10
+
11
+ from AutoGLM_GUI.logger import logger
12
+ from AutoGLM_GUI.types import AgentSpecificConfig
13
+
14
+ from .protocols import BaseAgent
15
+
16
+ if TYPE_CHECKING:
17
+ from phone_agent import PhoneAgent
18
+ from phone_agent.agent import AgentConfig
19
+ from phone_agent.model import ModelConfig
20
+
21
+ from .mai_adapter import MAIAgentAdapter
22
+
23
+
24
+ # Agent registry: agent_type -> (creator_function, config_schema)
25
+ AGENT_REGISTRY: Dict[str, Callable] = {}
26
+
27
+
28
+ def register_agent(
29
+ agent_type: str,
30
+ creator: Callable,
31
+ ) -> None:
32
+ """
33
+ Register a new agent type.
34
+
35
+ Args:
36
+ agent_type: Unique identifier for the agent type (e.g., "glm", "mai")
37
+ creator: Function that creates the agent instance.
38
+ Signature: (model_config, agent_config, agent_specific_config, callbacks) -> BaseAgent
39
+
40
+ Example:
41
+ >>> def create_mai_agent(model_config, agent_config, mai_config, callbacks):
42
+ >>> return MAIAgentAdapter(...)
43
+ >>>
44
+ >>> register_agent("mai", create_mai_agent)
45
+ """
46
+ if agent_type in AGENT_REGISTRY:
47
+ logger.warning(f"Agent type '{agent_type}' already registered, overwriting")
48
+
49
+ AGENT_REGISTRY[agent_type] = creator
50
+ logger.info(f"Registered agent type: {agent_type}")
51
+
52
+
53
+ def create_agent(
54
+ agent_type: str,
55
+ model_config: "ModelConfig",
56
+ agent_config: "AgentConfig",
57
+ agent_specific_config: AgentSpecificConfig,
58
+ takeover_callback: Callable | None = None,
59
+ confirmation_callback: Callable | None = None,
60
+ ) -> "BaseAgent":
61
+ """
62
+ Create an agent instance using the factory pattern.
63
+
64
+ Args:
65
+ agent_type: Type of agent to create (e.g., "glm", "mai")
66
+ model_config: Model configuration
67
+ agent_config: Agent configuration
68
+ agent_specific_config: Agent-specific configuration (e.g., MAIConfig fields)
69
+ takeover_callback: Takeover callback
70
+ confirmation_callback: Confirmation callback
71
+
72
+ Returns:
73
+ Agent instance implementing BaseAgent interface
74
+
75
+ Raises:
76
+ ValueError: If agent_type is not registered
77
+ """
78
+ if agent_type not in AGENT_REGISTRY:
79
+ available = ", ".join(AGENT_REGISTRY.keys())
80
+ raise ValueError(
81
+ f"Unknown agent type: '{agent_type}'. Available types: {available}"
82
+ )
83
+
84
+ creator = AGENT_REGISTRY[agent_type]
85
+
86
+ try:
87
+ agent = creator(
88
+ model_config=model_config,
89
+ agent_config=agent_config,
90
+ agent_specific_config=agent_specific_config,
91
+ takeover_callback=takeover_callback,
92
+ confirmation_callback=confirmation_callback,
93
+ )
94
+ logger.debug(f"Created agent of type '{agent_type}'")
95
+ return agent
96
+ except Exception as e:
97
+ logger.error(f"Failed to create agent of type '{agent_type}': {e}")
98
+ raise
99
+
100
+
101
+ def list_agent_types() -> list[str]:
102
+ """Get list of registered agent types."""
103
+ return list(AGENT_REGISTRY.keys())
104
+
105
+
106
+ def is_agent_type_registered(agent_type: str) -> bool:
107
+ """Check if an agent type is registered."""
108
+ return agent_type in AGENT_REGISTRY
109
+
110
+
111
+ # ==================== Built-in Agent Creators ====================
112
+
113
+
114
+ def _create_phone_agent(
115
+ model_config: "ModelConfig",
116
+ agent_config: "AgentConfig",
117
+ agent_specific_config: AgentSpecificConfig,
118
+ takeover_callback: Callable | None = None,
119
+ confirmation_callback: Callable | None = None,
120
+ ) -> "PhoneAgent":
121
+ from phone_agent import PhoneAgent
122
+
123
+ return PhoneAgent(
124
+ model_config=model_config,
125
+ agent_config=agent_config,
126
+ takeover_callback=takeover_callback,
127
+ confirmation_callback=confirmation_callback,
128
+ )
129
+
130
+
131
+ def _create_mai_agent(
132
+ model_config: "ModelConfig",
133
+ agent_config: "AgentConfig",
134
+ agent_specific_config: AgentSpecificConfig,
135
+ takeover_callback: Callable | None = None,
136
+ confirmation_callback: Callable | None = None,
137
+ ) -> "MAIAgentAdapter":
138
+ from .mai_adapter import MAIAgentAdapter, MAIAgentConfig
139
+
140
+ # Build MAI config from dict
141
+ mai_config = MAIAgentConfig(
142
+ history_n=agent_specific_config.get("history_n", 3),
143
+ max_pixels=agent_specific_config.get("max_pixels"),
144
+ min_pixels=agent_specific_config.get("min_pixels"),
145
+ tools=agent_specific_config.get("tools"),
146
+ use_mai_prompt=agent_specific_config.get("use_mai_prompt", False),
147
+ )
148
+
149
+ return MAIAgentAdapter(
150
+ model_config=model_config,
151
+ agent_config=agent_config,
152
+ mai_config=mai_config,
153
+ takeover_callback=takeover_callback,
154
+ confirmation_callback=confirmation_callback,
155
+ )
156
+
157
+
158
+ # Register built-in agents
159
+ register_agent("glm", _create_phone_agent)
160
+ register_agent("mai", _create_mai_agent)