autoglm-gui 1.5.3__tar.gz → 1.5.5__tar.gz
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-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/__main__.py +33 -7
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/glm/async_agent.py +64 -99
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/protocols.py +3 -14
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/__init__.py +16 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/agents.py +0 -1
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/logger.py +3 -2
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/about-DTrVqEQH.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/about-BwLRPh96.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/alert-dialog-B2KxPLtZ.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/alert-dialog-BvDNaR9v.js +1 -1
- autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/chat-DAmrsouh.js +129 -0
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/circle-alert-vnNxOaxv.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/circle-alert-C8768IhH.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/dialog-Cuw3N8_F.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/dialog-IM0Ds7Lf.js +2 -2
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/eye-JD1jbm99.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/eye-BWBwz8sy.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/history-CobYdXju.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/history-BkQlPjpV.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/index-y1vOOBHH.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/index-B0fISVXF.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/index-BzP-Te33.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/index-CH4jPveL.js +8 -8
- autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/index-DSIMVL8V.css +1 -0
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/label-BpCMrXj_.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/label-CmQFo_IT.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/logs-BcsSAeol.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/logs-ChcSA2r_.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/popover-BHbCs5Wl.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/popover-BnpBfSOh.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/scheduled-tasks-WvtmRsex.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/scheduled-tasks-BwgoPEdP.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/textarea-B84jf3cE.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/textarea-BlKvI11g.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/workflows-DhBpqdz_.js → autoglm_gui-1.5.5/AutoGLM_GUI/static/assets/workflows-CRq1fJf5.js +1 -1
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/static/index.html +2 -2
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/PKG-INFO +7 -5
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/README.md +6 -4
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/pyproject.toml +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/chat-BkrVbc3X.js +0 -129
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/index-CV7jGxGm.css +0 -1
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/.gitignore +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/actions/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/actions/handler.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/actions/types.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb/apps.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb/connection.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb/device.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb/input.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb/screenshot.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb/timing.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/device.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/ip.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/keyboard_installer.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/mdns.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/pair.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/qr_pair.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/screenshot.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/serial.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/touch.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/adb_plus/version.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/events.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/factory.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/glm/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/glm/agent.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/glm/message_builder.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/glm/parser.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/glm/prompts_en.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/glm/prompts_zh.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/mai/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/mai/agent.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/mai/parser.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/mai/prompts.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/mai/traj_memory.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/agents/stream_runner.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/control.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/devices.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/health.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/history.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/layered_agent.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/mcp.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/media.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/metrics.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/scheduled_tasks.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/version.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/api/workflows.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/config.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/config_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/device_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/device_metadata_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/device_protocol.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/devices/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/devices/adb_device.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/devices/mock_device.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/devices/remote_device.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/exceptions.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/history_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/i18n.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/metrics.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/model/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/model/message_builder.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/model/types.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/models/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/models/history.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/models/scheduled_task.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/parsers/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/parsers/base.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/parsers/phone_parser.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/phone_agent_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/platform_utils.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/prompt_config.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/prompts/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/prompts.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/scheduler_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/schemas.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/scrcpy_protocol.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/scrcpy_stream.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/server.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/socketio_server.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/state.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/static/assets/logo-Cyfm06Ym.png +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/static/assets/worker-D6BRitjy.js +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/static/favicon.ico +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/static/logo-192.png +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/static/logo-512.png +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/types.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/version.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/AutoGLM_GUI/workflow_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/LICENSE +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.5}/scrcpy-server-v3.3.3 +0 -0
|
@@ -76,6 +76,39 @@ def open_browser(
|
|
|
76
76
|
|
|
77
77
|
def main() -> None:
|
|
78
78
|
"""Start the AutoGLM-GUI server."""
|
|
79
|
+
# Configure logging BEFORE any other imports to ensure DEBUG level from the start
|
|
80
|
+
# This is especially important for --reload mode where subprocess reimports modules
|
|
81
|
+
import os
|
|
82
|
+
import sys
|
|
83
|
+
|
|
84
|
+
# Parse args early to get log level
|
|
85
|
+
early_parser = argparse.ArgumentParser(add_help=False)
|
|
86
|
+
early_parser.add_argument(
|
|
87
|
+
"--log-level",
|
|
88
|
+
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
|
89
|
+
default="INFO",
|
|
90
|
+
)
|
|
91
|
+
early_parser.add_argument(
|
|
92
|
+
"--log-file", default="logs/autoglm_{time:YYYY-MM-DD}.log"
|
|
93
|
+
)
|
|
94
|
+
early_parser.add_argument("--no-log-file", action="store_true")
|
|
95
|
+
early_args, _ = early_parser.parse_known_args()
|
|
96
|
+
|
|
97
|
+
# Set environment variable for reload mode (subprocess will read this)
|
|
98
|
+
os.environ["AUTOGLM_LOG_LEVEL"] = early_args.log_level
|
|
99
|
+
if early_args.no_log_file:
|
|
100
|
+
os.environ["AUTOGLM_NO_LOG_FILE"] = "1"
|
|
101
|
+
else:
|
|
102
|
+
os.environ["AUTOGLM_LOG_FILE"] = early_args.log_file
|
|
103
|
+
|
|
104
|
+
# Import and configure logger FIRST
|
|
105
|
+
from AutoGLM_GUI.logger import configure_logger
|
|
106
|
+
|
|
107
|
+
configure_logger(
|
|
108
|
+
console_level=early_args.log_level,
|
|
109
|
+
log_file=None if early_args.no_log_file else early_args.log_file,
|
|
110
|
+
)
|
|
111
|
+
|
|
79
112
|
parser = argparse.ArgumentParser(
|
|
80
113
|
description="AutoGLM-GUI - Web GUI for AutoGLM Phone Agent"
|
|
81
114
|
)
|
|
@@ -163,13 +196,6 @@ def main() -> None:
|
|
|
163
196
|
|
|
164
197
|
from AutoGLM_GUI import server
|
|
165
198
|
from AutoGLM_GUI.config_manager import config_manager
|
|
166
|
-
from AutoGLM_GUI.logger import configure_logger
|
|
167
|
-
|
|
168
|
-
# Configure logging system
|
|
169
|
-
configure_logger(
|
|
170
|
-
console_level=args.log_level,
|
|
171
|
-
log_file=None if args.no_log_file else args.log_file,
|
|
172
|
-
)
|
|
173
199
|
|
|
174
200
|
# ==================== 配置系统初始化 ====================
|
|
175
201
|
# 使用统一配置管理器(四层优先级:CLI > ENV > FILE > DEFAULT)
|
|
@@ -8,7 +8,8 @@ from typing import Any, AsyncIterator, Callable
|
|
|
8
8
|
from openai import AsyncOpenAI
|
|
9
9
|
|
|
10
10
|
from AutoGLM_GUI.actions import ActionHandler, ActionResult
|
|
11
|
-
from AutoGLM_GUI.
|
|
11
|
+
from AutoGLM_GUI.agents.protocols import AsyncAgent
|
|
12
|
+
from AutoGLM_GUI.config import AgentConfig, ModelConfig
|
|
12
13
|
from AutoGLM_GUI.device_protocol import DeviceProtocol
|
|
13
14
|
from AutoGLM_GUI.logger import logger
|
|
14
15
|
from AutoGLM_GUI.prompt_config import get_messages, get_system_prompt
|
|
@@ -17,7 +18,7 @@ from .message_builder import MessageBuilder
|
|
|
17
18
|
from .parser import GLMParser
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
class AsyncGLMAgent:
|
|
21
|
+
class AsyncGLMAgent(AsyncAgent):
|
|
21
22
|
"""异步 GLM Agent 实现。
|
|
22
23
|
|
|
23
24
|
核心特性:
|
|
@@ -61,8 +62,18 @@ class AsyncGLMAgent:
|
|
|
61
62
|
# 取消机制
|
|
62
63
|
self._cancel_event = asyncio.Event()
|
|
63
64
|
|
|
65
|
+
# 初始化 system prompt(Agent 一创建就有"人格")
|
|
66
|
+
system_prompt = self.agent_config.system_prompt
|
|
67
|
+
if system_prompt is None:
|
|
68
|
+
system_prompt = get_system_prompt(self.agent_config.lang)
|
|
69
|
+
|
|
70
|
+
# 保存初始 system message 用于 reset()
|
|
71
|
+
self._initial_system_message = MessageBuilder.create_system_message(
|
|
72
|
+
system_prompt
|
|
73
|
+
)
|
|
74
|
+
|
|
64
75
|
# 状态
|
|
65
|
-
self._context: list[dict[str, Any]] = []
|
|
76
|
+
self._context: list[dict[str, Any]] = [self._initial_system_message]
|
|
66
77
|
self._step_count = 0
|
|
67
78
|
self._is_running = False
|
|
68
79
|
|
|
@@ -82,35 +93,46 @@ class AsyncGLMAgent:
|
|
|
82
93
|
- "cancelled": {"message": str}
|
|
83
94
|
- "error": {"message": str}
|
|
84
95
|
"""
|
|
85
|
-
self._context = []
|
|
86
|
-
self._step_count = 0
|
|
87
96
|
self._is_running = True
|
|
88
97
|
self._cancel_event.clear()
|
|
89
98
|
|
|
90
99
|
try:
|
|
91
|
-
#
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
# ===== 初始化阶段:添加首次用户输入 =====
|
|
101
|
+
try:
|
|
102
|
+
screenshot = await asyncio.to_thread(self.device.get_screenshot)
|
|
103
|
+
current_app = await asyncio.to_thread(self.device.get_current_app)
|
|
104
|
+
except Exception as e:
|
|
105
|
+
logger.error(f"Failed to get device info during initialization: {e}")
|
|
106
|
+
yield {
|
|
107
|
+
"type": "error",
|
|
108
|
+
"data": {"message": f"Device error: {e}"},
|
|
109
|
+
}
|
|
110
|
+
yield {
|
|
111
|
+
"type": "done",
|
|
112
|
+
"data": {
|
|
113
|
+
"message": f"Device error: {e}",
|
|
114
|
+
"steps": 0,
|
|
115
|
+
"success": False,
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
return
|
|
94
119
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
},
|
|
104
|
-
}
|
|
105
|
-
return
|
|
120
|
+
screen_info = MessageBuilder.build_screen_info(current_app)
|
|
121
|
+
initial_message = f"{task}\n\n** Screen Info **\n\n{screen_info}"
|
|
122
|
+
|
|
123
|
+
self._context.append(
|
|
124
|
+
MessageBuilder.create_user_message(
|
|
125
|
+
text=initial_message, image_base64=screenshot.base64_data
|
|
126
|
+
)
|
|
127
|
+
)
|
|
106
128
|
|
|
107
|
-
#
|
|
129
|
+
# ===== 执行阶段:循环执行步骤 =====
|
|
108
130
|
while self._step_count < self.agent_config.max_steps and self._is_running:
|
|
109
131
|
# 检查取消
|
|
110
132
|
if self._cancel_event.is_set():
|
|
111
133
|
raise asyncio.CancelledError()
|
|
112
134
|
|
|
113
|
-
async for event in self._execute_step_async(
|
|
135
|
+
async for event in self._execute_step_async():
|
|
114
136
|
yield event
|
|
115
137
|
|
|
116
138
|
# 检查是否完成
|
|
@@ -147,21 +169,19 @@ class AsyncGLMAgent:
|
|
|
147
169
|
finally:
|
|
148
170
|
self._is_running = False
|
|
149
171
|
|
|
150
|
-
async def _execute_step_async(
|
|
151
|
-
self, user_prompt: str | None, is_first: bool
|
|
152
|
-
) -> AsyncIterator[dict[str, Any]]:
|
|
172
|
+
async def _execute_step_async(self) -> AsyncIterator[dict[str, Any]]:
|
|
153
173
|
"""执行单步,支持流式输出和取消。
|
|
154
174
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
175
|
+
注意:不再需要 user_prompt 参数,因为:
|
|
176
|
+
- 首次用户输入已在 stream() 的初始化阶段添加
|
|
177
|
+
- 此方法只负责执行步骤:获取屏幕 → 调用 LLM → 执行动作
|
|
158
178
|
|
|
159
179
|
Yields:
|
|
160
180
|
dict[str, Any]: 事件字典
|
|
161
181
|
"""
|
|
162
182
|
self._step_count += 1
|
|
163
183
|
|
|
164
|
-
# 1.
|
|
184
|
+
# 1. 获取当前屏幕状态(使用线程池)
|
|
165
185
|
try:
|
|
166
186
|
screenshot = await asyncio.to_thread(self.device.get_screenshot)
|
|
167
187
|
current_app = await asyncio.to_thread(self.device.get_current_app)
|
|
@@ -184,42 +204,21 @@ class AsyncGLMAgent:
|
|
|
184
204
|
}
|
|
185
205
|
return
|
|
186
206
|
|
|
187
|
-
# 2.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if system_prompt is None:
|
|
191
|
-
system_prompt = get_system_prompt(self.agent_config.lang)
|
|
192
|
-
|
|
193
|
-
self._context.append(MessageBuilder.create_system_message(system_prompt))
|
|
194
|
-
|
|
195
|
-
screen_info = MessageBuilder.build_screen_info(current_app)
|
|
196
|
-
text_content = f"{user_prompt}\n\n{screen_info}"
|
|
197
|
-
|
|
198
|
-
self._context.append(
|
|
199
|
-
MessageBuilder.create_user_message(
|
|
200
|
-
text=text_content, image_base64=screenshot.base64_data
|
|
201
|
-
)
|
|
202
|
-
)
|
|
203
|
-
else:
|
|
204
|
-
screen_info = MessageBuilder.build_screen_info(current_app)
|
|
205
|
-
if user_prompt:
|
|
206
|
-
text_content = f"{user_prompt}\n\n** Screen Info **\n\n{screen_info}"
|
|
207
|
-
else:
|
|
208
|
-
text_content = f"** Screen Info **\n\n{screen_info}"
|
|
207
|
+
# 2. 构建消息(统一格式:只有屏幕信息)
|
|
208
|
+
screen_info = MessageBuilder.build_screen_info(current_app)
|
|
209
|
+
text_content = f"** Screen Info **\n\n{screen_info}"
|
|
209
210
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
)
|
|
211
|
+
self._context.append(
|
|
212
|
+
MessageBuilder.create_user_message(
|
|
213
|
+
text=text_content, image_base64=screenshot.base64_data
|
|
214
214
|
)
|
|
215
|
+
)
|
|
215
216
|
|
|
216
217
|
# 3. 流式调用 OpenAI(真正的异步,可取消)
|
|
217
218
|
try:
|
|
218
219
|
if self.agent_config.verbose:
|
|
219
220
|
msgs = get_messages(self.agent_config.lang)
|
|
220
|
-
|
|
221
|
-
print(f"💭 {msgs['thinking']}:")
|
|
222
|
-
print("-" * 50)
|
|
221
|
+
logger.debug(f"💭 {msgs['thinking']}:")
|
|
223
222
|
|
|
224
223
|
thinking_parts = []
|
|
225
224
|
raw_content = ""
|
|
@@ -240,7 +239,7 @@ class AsyncGLMAgent:
|
|
|
240
239
|
|
|
241
240
|
# Verbose output
|
|
242
241
|
if self.agent_config.verbose:
|
|
243
|
-
|
|
242
|
+
logger.debug(chunk_data["content"])
|
|
244
243
|
|
|
245
244
|
elif chunk_data["type"] == "raw":
|
|
246
245
|
raw_content += chunk_data["content"]
|
|
@@ -254,7 +253,7 @@ class AsyncGLMAgent:
|
|
|
254
253
|
except Exception as e:
|
|
255
254
|
logger.error(f"LLM error: {e}")
|
|
256
255
|
if self.agent_config.verbose:
|
|
257
|
-
traceback.
|
|
256
|
+
logger.debug(traceback.format_exc())
|
|
258
257
|
|
|
259
258
|
yield {
|
|
260
259
|
"type": "error",
|
|
@@ -285,11 +284,8 @@ class AsyncGLMAgent:
|
|
|
285
284
|
|
|
286
285
|
if self.agent_config.verbose:
|
|
287
286
|
msgs = get_messages(self.agent_config.lang)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
print(f"🎯 {msgs['action']}:")
|
|
291
|
-
print(json.dumps(action, ensure_ascii=False, indent=2))
|
|
292
|
-
print("=" * 50 + "\n")
|
|
287
|
+
logger.debug(f"🎯 {msgs['action']}:")
|
|
288
|
+
logger.debug(json.dumps(action, ensure_ascii=False, indent=2))
|
|
293
289
|
|
|
294
290
|
# 5. 执行 action(使用线程池)
|
|
295
291
|
try:
|
|
@@ -299,7 +295,7 @@ class AsyncGLMAgent:
|
|
|
299
295
|
except Exception as e:
|
|
300
296
|
logger.error(f"Action execution error: {e}")
|
|
301
297
|
if self.agent_config.verbose:
|
|
302
|
-
traceback.
|
|
298
|
+
logger.debug(traceback.format_exc())
|
|
303
299
|
result = ActionResult(success=False, should_finish=True, message=str(e))
|
|
304
300
|
|
|
305
301
|
# 6. 更新上下文
|
|
@@ -316,11 +312,9 @@ class AsyncGLMAgent:
|
|
|
316
312
|
|
|
317
313
|
if finished and self.agent_config.verbose:
|
|
318
314
|
msgs = get_messages(self.agent_config.lang)
|
|
319
|
-
|
|
320
|
-
print(
|
|
315
|
+
logger.debug(
|
|
321
316
|
f"✅ {msgs['task_completed']}: {result.message or action.get('message', msgs['done'])}"
|
|
322
317
|
)
|
|
323
|
-
print("=" * 50 + "\n")
|
|
324
318
|
|
|
325
319
|
# 8. 返回步骤结果
|
|
326
320
|
yield {
|
|
@@ -452,8 +446,8 @@ class AsyncGLMAgent:
|
|
|
452
446
|
logger.info("AsyncGLMAgent cancelled by user")
|
|
453
447
|
|
|
454
448
|
def reset(self) -> None:
|
|
455
|
-
"""
|
|
456
|
-
self._context = []
|
|
449
|
+
"""重置状态(恢复到初始状态,保留 system message)。"""
|
|
450
|
+
self._context = [self._initial_system_message]
|
|
457
451
|
self._step_count = 0
|
|
458
452
|
self._is_running = False
|
|
459
453
|
self._cancel_event.clear()
|
|
@@ -473,35 +467,6 @@ class AsyncGLMAgent:
|
|
|
473
467
|
final_message = event["data"].get("message", "")
|
|
474
468
|
return final_message
|
|
475
469
|
|
|
476
|
-
async def step(self, task: str | None = None) -> StepResult:
|
|
477
|
-
"""执行单步(兼容接口)。
|
|
478
|
-
|
|
479
|
-
Args:
|
|
480
|
-
task: 任务描述(首步必需,后续可选)
|
|
481
|
-
|
|
482
|
-
Returns:
|
|
483
|
-
StepResult: 步骤结果
|
|
484
|
-
"""
|
|
485
|
-
is_first = len(self._context) == 0
|
|
486
|
-
if is_first and not task:
|
|
487
|
-
raise ValueError("Task is required for the first step")
|
|
488
|
-
|
|
489
|
-
result = None
|
|
490
|
-
async for event in self._execute_step_async(task, is_first):
|
|
491
|
-
if event["type"] == "step":
|
|
492
|
-
result = StepResult(
|
|
493
|
-
thinking=event["data"]["thinking"],
|
|
494
|
-
action=event["data"]["action"],
|
|
495
|
-
success=event["data"]["success"],
|
|
496
|
-
finished=event["data"]["finished"],
|
|
497
|
-
message=event["data"].get("message"),
|
|
498
|
-
)
|
|
499
|
-
|
|
500
|
-
if result is None:
|
|
501
|
-
raise RuntimeError("Step execution did not produce a result")
|
|
502
|
-
|
|
503
|
-
return result
|
|
504
|
-
|
|
505
470
|
@property
|
|
506
471
|
def step_count(self) -> int:
|
|
507
472
|
return self._step_count
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, Protocol
|
|
5
5
|
|
|
6
6
|
from AutoGLM_GUI.config import AgentConfig, ModelConfig, StepResult
|
|
7
7
|
|
|
@@ -76,19 +76,8 @@ class AsyncAgent(Protocol):
|
|
|
76
76
|
"""
|
|
77
77
|
...
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
"""
|
|
81
|
-
|
|
82
|
-
Args:
|
|
83
|
-
task: 任务描述(首步必需,后续可选)
|
|
84
|
-
|
|
85
|
-
Returns:
|
|
86
|
-
StepResult: 步骤结果
|
|
87
|
-
"""
|
|
88
|
-
...
|
|
89
|
-
|
|
90
|
-
async def stream(self, task: str) -> AsyncIterator[dict[str, Any]]:
|
|
91
|
-
"""流式执行任务,yield 事件字典。
|
|
79
|
+
def stream(self, task: str) -> Any:
|
|
80
|
+
"""流式执行任务,返回异步生成器。
|
|
92
81
|
|
|
93
82
|
这是核心方法,支持:
|
|
94
83
|
- 实时流式输出 (thinking chunks)
|
|
@@ -79,6 +79,22 @@ def _get_static_dir() -> Path | None:
|
|
|
79
79
|
def create_app() -> FastAPI:
|
|
80
80
|
"""Build the FastAPI app with routers and static assets."""
|
|
81
81
|
|
|
82
|
+
# Configure logging from environment variables (for reload mode)
|
|
83
|
+
# In reload mode, the subprocess imports this module directly, bypassing __main__.py
|
|
84
|
+
# So we need to read log config from environment variables set by the parent process
|
|
85
|
+
import os
|
|
86
|
+
|
|
87
|
+
log_level = os.getenv("AUTOGLM_LOG_LEVEL", "INFO")
|
|
88
|
+
log_file = (
|
|
89
|
+
None
|
|
90
|
+
if os.getenv("AUTOGLM_NO_LOG_FILE")
|
|
91
|
+
else os.getenv("AUTOGLM_LOG_FILE", "logs/autoglm_{time:YYYY-MM-DD}.log")
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
from AutoGLM_GUI.logger import configure_logger
|
|
95
|
+
|
|
96
|
+
configure_logger(console_level=log_level, log_file=log_file)
|
|
97
|
+
|
|
82
98
|
# Create MCP ASGI app
|
|
83
99
|
mcp_app = mcp.get_mcp_asgi_app()
|
|
84
100
|
|
|
@@ -182,7 +182,6 @@ async def chat(request: ChatRequest) -> ChatResponse:
|
|
|
182
182
|
result = await agent.run(request.message) # type: ignore[misc]
|
|
183
183
|
|
|
184
184
|
steps = agent.step_count
|
|
185
|
-
agent.reset()
|
|
186
185
|
return ChatResponse(result=result, steps=steps, success=True) # type: ignore[arg-type]
|
|
187
186
|
|
|
188
187
|
except AgentInitializationError as e:
|
|
@@ -79,7 +79,8 @@ def configure_logger(
|
|
|
79
79
|
_configured = True
|
|
80
80
|
|
|
81
81
|
|
|
82
|
-
#
|
|
83
|
-
configure_logger()
|
|
82
|
+
# Note: Logger is NOT auto-initialized to allow early configuration
|
|
83
|
+
# The first call to configure_logger() will initialize the logger
|
|
84
|
+
# If not configured before use, it will use loguru's default behavior (no handlers)
|
|
84
85
|
|
|
85
86
|
__all__ = ["logger", "configure_logger"]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as o}from"./index-
|
|
1
|
+
import{j as o}from"./index-CH4jPveL.js";function t(){return o.jsx("div",{className:"p-2",children:o.jsx("h3",{children:"About"})})}export{t as component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as u,r as o,j as a,b as r,B as d}from"./index-
|
|
1
|
+
import{o as u,r as o,j as a,b as r,B as d}from"./index-CH4jPveL.js";import{P as g,c as x,b as f,d as m}from"./popover-BnpBfSOh.js";import{D as p,d as h,e as w,f as j,g as D}from"./dialog-IM0Ds7Lf.js";const N=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],b=u("check",N),c=o.createContext(void 0),P=({value:t="",onValueChange:e,children:s})=>{const[n,l]=o.useState(!1);return a.jsx(c.Provider,{value:{value:t,onValueChange:e||(()=>{}),open:n,setOpen:l},children:a.jsx(g,{open:n,onOpenChange:l,children:s})})},C=o.forwardRef(({className:t,children:e,...s},n)=>{if(!o.useContext(c))throw new Error("SelectTrigger must be used within Select");return a.jsx(x,{asChild:!0,children:a.jsxs("button",{ref:n,className:r("flex h-10 w-full items-center justify-between rounded-md border border-slate-200 bg-white px-3 py-2 text-sm ring-offset-white placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-slate-950 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-800 dark:bg-slate-950 dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus:ring-slate-300",t),...s,children:[e,a.jsx(f,{className:"h-4 w-4 opacity-50"})]})})});C.displayName="SelectTrigger";const V=({placeholder:t})=>{const e=o.useContext(c);if(!e)throw new Error("SelectValue must be used within Select");return a.jsx("span",{className:e.value?"":"text-slate-500",children:e.value||t})},I=({children:t,className:e})=>a.jsx(m,{className:r("w-[var(--radix-popover-trigger-width)] p-1",e),children:t}),O=({value:t,children:e,disabled:s,className:n})=>{const l=o.useContext(c);if(!l)throw new Error("SelectItem must be used within Select");const i=l.value===t;return a.jsxs("div",{role:"option","aria-selected":i,className:r("relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none hover:bg-slate-100 focus:bg-slate-100 dark:hover:bg-slate-800 dark:focus:bg-slate-800",s&&"pointer-events-none opacity-50",n),onClick:()=>{s||(l.onValueChange(t),l.setOpen(!1))},children:[a.jsx("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:i&&a.jsx(b,{className:"h-4 w-4"})}),e]})},B=({open:t,onOpenChange:e,children:s})=>a.jsx(p,{open:t,onOpenChange:e,children:s}),v=o.forwardRef(({className:t,...e},s)=>a.jsx(h,{ref:s,className:r("sm:max-w-[425px]",t),...e}));v.displayName="AlertDialogContent";const F=({className:t,...e})=>a.jsx(w,{className:r(t),...e}),H=({className:t,...e})=>a.jsx(D,{className:r(t),...e}),A=o.forwardRef(({className:t,...e},s)=>a.jsx(j,{ref:s,className:r(t),...e}));A.displayName="AlertDialogTitle";const S=o.forwardRef(({className:t,...e},s)=>a.jsx("p",{ref:s,className:r("text-sm text-slate-500 dark:text-slate-400",t),...e}));S.displayName="AlertDialogDescription";const y=o.forwardRef(({className:t,...e},s)=>a.jsx(d,{ref:s,className:r(t),...e}));y.displayName="AlertDialogAction";const k=o.forwardRef(({className:t,...e},s)=>a.jsx(d,{ref:s,variant:"outline",className:r(t),...e}));k.displayName="AlertDialogCancel";export{B as A,P as S,C as a,V as b,I as c,O as d,v as e,F as f,A as g,S as h,H as i,k as j,y as k};
|