autoglm-gui 1.5.1__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 +2 -2
- AutoGLM_GUI/agents/glm/async_agent.py +515 -0
- AutoGLM_GUI/agents/glm/parser.py +4 -2
- AutoGLM_GUI/agents/protocols.py +111 -1
- AutoGLM_GUI/agents/stream_runner.py +4 -5
- AutoGLM_GUI/api/__init__.py +3 -1
- AutoGLM_GUI/api/agents.py +78 -37
- AutoGLM_GUI/api/devices.py +72 -0
- 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/phone_agent_manager.py +145 -32
- AutoGLM_GUI/scheduler_manager.py +6 -6
- AutoGLM_GUI/schemas.py +89 -0
- AutoGLM_GUI/scrcpy_stream.py +2 -1
- AutoGLM_GUI/static/assets/{about-CfwX1Cmc.js → about-D7r9gCvG.js} +1 -1
- AutoGLM_GUI/static/assets/{alert-dialog-CtGlN2IJ.js → alert-dialog-BKM-yRiQ.js} +1 -1
- AutoGLM_GUI/static/assets/chat-k6TTD7PW.js +129 -0
- AutoGLM_GUI/static/assets/{circle-alert-t08bEMPO.js → circle-alert-sohSDLhl.js} +1 -1
- AutoGLM_GUI/static/assets/{dialog-FNwZJFwk.js → dialog-BgtPh0d5.js} +1 -1
- AutoGLM_GUI/static/assets/{eye-D0UPWCWC.js → eye-DLqKbQmg.js} +1 -1
- AutoGLM_GUI/static/assets/{history-CRo95B7i.js → history-Bv1lfGUU.js} +1 -1
- AutoGLM_GUI/static/assets/index-CxWwh1VO.js +1 -0
- AutoGLM_GUI/static/assets/{index-CTHbFvKl.js → index-SysdKciY.js} +5 -5
- AutoGLM_GUI/static/assets/label-DTUnzN4B.js +1 -0
- AutoGLM_GUI/static/assets/{logs-RW09DyYY.js → logs-BIhnDizW.js} +1 -1
- AutoGLM_GUI/static/assets/{popover--JTJrE5v.js → popover-CikYqu2P.js} +1 -1
- AutoGLM_GUI/static/assets/scheduled-tasks-B-KBsGbl.js +1 -0
- AutoGLM_GUI/static/assets/{textarea-PRmVnWq5.js → textarea-knJZrz77.js} +1 -1
- AutoGLM_GUI/static/assets/workflows-DzcSYwLZ.js +1 -0
- AutoGLM_GUI/static/index.html +1 -1
- {autoglm_gui-1.5.1.dist-info → autoglm_gui-1.5.2.dist-info}/METADATA +10 -1
- {autoglm_gui-1.5.1.dist-info → autoglm_gui-1.5.2.dist-info}/RECORD +44 -43
- AutoGLM_GUI/static/assets/chat-BYa-foUI.js +0 -129
- AutoGLM_GUI/static/assets/index-BaLMSqd3.js +0 -1
- AutoGLM_GUI/static/assets/label-DJFevVmr.js +0 -1
- AutoGLM_GUI/static/assets/scheduled-tasks-DTRKsQXF.js +0 -1
- AutoGLM_GUI/static/assets/square-pen-CPK_K680.js +0 -1
- AutoGLM_GUI/static/assets/workflows-CdcsAoaT.js +0 -1
- {autoglm_gui-1.5.1.dist-info → autoglm_gui-1.5.2.dist-info}/WHEEL +0 -0
- {autoglm_gui-1.5.1.dist-info → autoglm_gui-1.5.2.dist-info}/entry_points.txt +0 -0
- {autoglm_gui-1.5.1.dist-info → autoglm_gui-1.5.2.dist-info}/licenses/LICENSE +0 -0
AutoGLM_GUI/__init__.py
CHANGED
|
@@ -28,7 +28,7 @@ _original_popen = subprocess.Popen
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
@wraps(_original_run)
|
|
31
|
-
def _patched_run(*args, **kwargs):
|
|
31
|
+
def _patched_run(*args, **kwargs) -> subprocess.CompletedProcess:
|
|
32
32
|
"""Patched subprocess.run that defaults to UTF-8 encoding on Windows."""
|
|
33
33
|
if sys.platform == "win32":
|
|
34
34
|
# Add encoding='utf-8' if text=True is set but encoding is not specified
|
AutoGLM_GUI/__main__.py
CHANGED
|
@@ -56,7 +56,7 @@ def open_browser(
|
|
|
56
56
|
delay: Delay in seconds before opening browser
|
|
57
57
|
"""
|
|
58
58
|
|
|
59
|
-
def _open():
|
|
59
|
+
def _open() -> None:
|
|
60
60
|
time.sleep(delay)
|
|
61
61
|
protocol = "https" if use_ssl else "http"
|
|
62
62
|
url = (
|
|
@@ -141,6 +141,12 @@ def main() -> None:
|
|
|
141
141
|
default=None,
|
|
142
142
|
help="SSL certificate file path (for HTTPS)",
|
|
143
143
|
)
|
|
144
|
+
parser.add_argument(
|
|
145
|
+
"--layered-max-turns",
|
|
146
|
+
type=int,
|
|
147
|
+
default=None,
|
|
148
|
+
help="Maximum turns for layered agent mode (default: 50, minimum: 1)",
|
|
149
|
+
)
|
|
144
150
|
|
|
145
151
|
args = parser.parse_args()
|
|
146
152
|
|
|
@@ -170,7 +176,10 @@ def main() -> None:
|
|
|
170
176
|
|
|
171
177
|
# 1. 设置 CLI 参数配置(最高优先级)
|
|
172
178
|
config_manager.set_cli_config(
|
|
173
|
-
base_url=args.base_url,
|
|
179
|
+
base_url=args.base_url,
|
|
180
|
+
model_name=args.model,
|
|
181
|
+
api_key=args.apikey,
|
|
182
|
+
layered_max_turns=args.layered_max_turns,
|
|
174
183
|
)
|
|
175
184
|
|
|
176
185
|
# 2. 加载环境变量配置
|
AutoGLM_GUI/adb_plus/qr_pair.py
CHANGED
|
@@ -238,10 +238,10 @@ class QRPairingManager:
|
|
|
238
238
|
|
|
239
239
|
return session
|
|
240
240
|
|
|
241
|
-
def _start_listener(self, session: PairingSession, adb_path: str):
|
|
241
|
+
def _start_listener(self, session: PairingSession, adb_path: str) -> None:
|
|
242
242
|
"""Start zeroconf listener (runs in thread pool to avoid blocking)."""
|
|
243
243
|
|
|
244
|
-
def _listen():
|
|
244
|
+
def _listen() -> None:
|
|
245
245
|
"""Listener thread function."""
|
|
246
246
|
try:
|
|
247
247
|
zc = Zeroconf()
|
|
@@ -350,7 +350,7 @@ class QRPairingManager:
|
|
|
350
350
|
logger.warning(f"[QR Pair] Session {session_id} not found for cancellation")
|
|
351
351
|
return False
|
|
352
352
|
|
|
353
|
-
async def cleanup_expired_sessions(self):
|
|
353
|
+
async def cleanup_expired_sessions(self) -> None:
|
|
354
354
|
"""Background task to cleanup expired sessions.
|
|
355
355
|
|
|
356
356
|
Runs indefinitely, checking every 60 seconds for expired sessions.
|
AutoGLM_GUI/agents/__init__.py
CHANGED
|
@@ -2,6 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import Callable
|
|
4
4
|
|
|
5
|
+
from .protocols import AsyncAgent, BaseAgent, is_async_agent
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
def register_agent(agent_type: str, creator: Callable) -> None:
|
|
7
9
|
from .factory import register_agent as _register_agent
|
|
@@ -44,8 +46,11 @@ def is_agent_type_registered(agent_type: str) -> bool:
|
|
|
44
46
|
|
|
45
47
|
|
|
46
48
|
__all__ = [
|
|
49
|
+
"AsyncAgent",
|
|
50
|
+
"BaseAgent",
|
|
47
51
|
"create_agent",
|
|
48
|
-
"register_agent",
|
|
49
|
-
"list_agent_types",
|
|
50
52
|
"is_agent_type_registered",
|
|
53
|
+
"is_async_agent",
|
|
54
|
+
"list_agent_types",
|
|
55
|
+
"register_agent",
|
|
51
56
|
]
|
AutoGLM_GUI/agents/factory.py
CHANGED
|
@@ -12,7 +12,7 @@ from AutoGLM_GUI.config import AgentConfig, ModelConfig
|
|
|
12
12
|
from AutoGLM_GUI.logger import logger
|
|
13
13
|
from AutoGLM_GUI.types import AgentSpecificConfig
|
|
14
14
|
|
|
15
|
-
from .protocols import BaseAgent
|
|
15
|
+
from .protocols import AsyncAgent, BaseAgent
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
# Agent registry: agent_type -> (creator_function, config_schema)
|
|
@@ -52,7 +52,7 @@ def create_agent(
|
|
|
52
52
|
device,
|
|
53
53
|
takeover_callback: Callable | None = None,
|
|
54
54
|
confirmation_callback: Callable | None = None,
|
|
55
|
-
) -> BaseAgent:
|
|
55
|
+
) -> AsyncAgent | BaseAgent:
|
|
56
56
|
"""
|
|
57
57
|
Create an agent instance using the factory pattern.
|
|
58
58
|
|
|
@@ -66,7 +66,8 @@ def create_agent(
|
|
|
66
66
|
confirmation_callback: Confirmation callback
|
|
67
67
|
|
|
68
68
|
Returns:
|
|
69
|
-
Agent instance implementing BaseAgent interface
|
|
69
|
+
Agent instance implementing AsyncAgent or BaseAgent interface.
|
|
70
|
+
Use runtime type detection (e.g., inspect.iscoroutinefunction) to determine which.
|
|
70
71
|
|
|
71
72
|
Raises:
|
|
72
73
|
ValueError: If agent_type is not registered
|
|
@@ -108,14 +109,51 @@ def is_agent_type_registered(agent_type: str) -> bool:
|
|
|
108
109
|
# ==================== Built-in Agent Creators ====================
|
|
109
110
|
|
|
110
111
|
|
|
111
|
-
def
|
|
112
|
+
def _create_async_glm_agent(
|
|
112
113
|
model_config: ModelConfig,
|
|
113
114
|
agent_config: AgentConfig,
|
|
114
|
-
agent_specific_config: AgentSpecificConfig,
|
|
115
|
+
agent_specific_config: AgentSpecificConfig, # noqa: ARG001
|
|
116
|
+
device,
|
|
117
|
+
takeover_callback: Callable | None = None,
|
|
118
|
+
confirmation_callback: Callable | None = None,
|
|
119
|
+
) -> AsyncAgent:
|
|
120
|
+
"""Create AsyncGLMAgent instance.
|
|
121
|
+
|
|
122
|
+
This is the default async implementation that supports:
|
|
123
|
+
- Native streaming with AsyncIterator
|
|
124
|
+
- Immediate cancellation with asyncio.CancelledError
|
|
125
|
+
- No worker threads or queues needed
|
|
126
|
+
|
|
127
|
+
Note: 'glm' now uses AsyncGLMAgent by default for better performance.
|
|
128
|
+
Use 'glm-sync' if you need the old synchronous implementation.
|
|
129
|
+
"""
|
|
130
|
+
from .glm.async_agent import AsyncGLMAgent
|
|
131
|
+
|
|
132
|
+
# Note: AsyncGLMAgent implements AsyncAgent Protocol, but pyright cannot verify
|
|
133
|
+
# async generator function compatibility with Protocol. This is a known limitation
|
|
134
|
+
# of Python's type system. The implementation is correct at runtime.
|
|
135
|
+
return AsyncGLMAgent( # type: ignore[return-value]
|
|
136
|
+
model_config=model_config,
|
|
137
|
+
agent_config=agent_config,
|
|
138
|
+
device=device,
|
|
139
|
+
confirmation_callback=confirmation_callback,
|
|
140
|
+
takeover_callback=takeover_callback,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _create_glm_agent_sync(
|
|
145
|
+
model_config: ModelConfig,
|
|
146
|
+
agent_config: AgentConfig,
|
|
147
|
+
agent_specific_config: AgentSpecificConfig, # noqa: ARG001
|
|
115
148
|
device,
|
|
116
149
|
takeover_callback: Callable | None = None,
|
|
117
150
|
confirmation_callback: Callable | None = None,
|
|
118
151
|
) -> BaseAgent:
|
|
152
|
+
"""Create synchronous GLMAgent (legacy, for backward compatibility).
|
|
153
|
+
|
|
154
|
+
This is the old synchronous implementation using AgentStepStreamer.
|
|
155
|
+
Only use this if you have compatibility issues with AsyncGLMAgent.
|
|
156
|
+
"""
|
|
119
157
|
from .glm.agent import GLMAgent
|
|
120
158
|
|
|
121
159
|
return GLMAgent(
|
|
@@ -149,5 +187,7 @@ def _create_internal_mai_agent(
|
|
|
149
187
|
)
|
|
150
188
|
|
|
151
189
|
|
|
152
|
-
register_agent("glm",
|
|
190
|
+
register_agent("glm", _create_glm_agent_sync) # 默认使用同步实现 (向后兼容)
|
|
191
|
+
register_agent("glm-async", _create_async_glm_agent) # 异步实现 (显式选择)
|
|
192
|
+
register_agent("async-glm", _create_async_glm_agent) # 别名
|
|
153
193
|
register_agent("mai", _create_internal_mai_agent)
|
AutoGLM_GUI/agents/glm/agent.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import traceback
|
|
3
|
-
from typing import Any, Callable
|
|
3
|
+
from typing import Any, Callable
|
|
4
4
|
|
|
5
5
|
from openai import OpenAI
|
|
6
6
|
|
|
@@ -90,7 +90,7 @@ class GLMAgent:
|
|
|
90
90
|
on_thinking_chunk: Callable[[str], None] | None = None,
|
|
91
91
|
) -> tuple[str, str, str]:
|
|
92
92
|
stream = self.openai_client.chat.completions.create(
|
|
93
|
-
messages=
|
|
93
|
+
messages=messages, # type: ignore[arg-type]
|
|
94
94
|
model=self.model_config.model_name,
|
|
95
95
|
max_tokens=self.model_config.max_tokens,
|
|
96
96
|
temperature=self.model_config.temperature,
|