autoglm-gui 1.5.3__tar.gz → 1.5.4__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.4}/AutoGLM_GUI/__main__.py +33 -7
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/async_agent.py +84 -72
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/__init__.py +16 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/agents.py +0 -1
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/logger.py +3 -2
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/about-DTrVqEQH.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/about-BZglkj97.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/alert-dialog-B2KxPLtZ.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/alert-dialog-5vNoxwIO.js +1 -1
- autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/chat-ta_RqZfZ.js +129 -0
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/circle-alert-vnNxOaxv.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/circle-alert-CnwO7Du-.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/dialog-Cuw3N8_F.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/dialog-DSAhQHru.js +2 -2
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/eye-JD1jbm99.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/eye-Deqw6dbm.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/history-CobYdXju.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/history-CL-JjUbk.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/index-y1vOOBHH.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/index-BjaUZM-7.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/index-BzP-Te33.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/index-CX4NAYCk.js +8 -8
- autoglm_gui-1.5.4/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.4/AutoGLM_GUI/static/assets/label-CEmK7RW4.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/logs-BcsSAeol.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/logs-C-Pnb4jI.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/popover-BHbCs5Wl.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/popover-CauTjrhB.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/scheduled-tasks-WvtmRsex.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/scheduled-tasks-Ds1WrRVN.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/textarea-B84jf3cE.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/textarea-nLU4tGQH.js +1 -1
- autoglm_gui-1.5.3/AutoGLM_GUI/static/assets/workflows-DhBpqdz_.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/workflows-QIA3_mdp.js +1 -1
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/index.html +2 -2
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/PKG-INFO +1 -1
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/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.4}/.gitignore +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/actions/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/actions/handler.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/actions/types.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/apps.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/connection.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/device.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/input.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/screenshot.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/timing.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/device.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/ip.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/keyboard_installer.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/mdns.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/pair.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/qr_pair.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/screenshot.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/serial.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/touch.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/version.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/events.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/factory.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/agent.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/message_builder.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/parser.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/prompts_en.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/prompts_zh.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/mai/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/mai/agent.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/mai/parser.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/mai/prompts.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/mai/traj_memory.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/protocols.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/stream_runner.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/control.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/devices.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/health.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/history.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/layered_agent.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/mcp.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/media.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/metrics.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/scheduled_tasks.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/version.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/workflows.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/config.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/config_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/device_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/device_metadata_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/device_protocol.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/devices/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/devices/adb_device.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/devices/mock_device.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/devices/remote_device.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/exceptions.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/history_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/i18n.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/metrics.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/model/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/model/message_builder.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/model/types.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/models/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/models/history.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/models/scheduled_task.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/parsers/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/parsers/base.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/parsers/phone_parser.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/phone_agent_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/platform_utils.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/prompt_config.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/prompts/__init__.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/prompts.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/scheduler_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/schemas.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/scrcpy_protocol.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/scrcpy_stream.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/server.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/socketio_server.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/state.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/assets/logo-Cyfm06Ym.png +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/assets/worker-D6BRitjy.js +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/favicon.ico +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/logo-192.png +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/logo-512.png +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/types.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/version.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/AutoGLM_GUI/workflow_manager.py +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/LICENSE +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/README.md +0 -0
- {autoglm_gui-1.5.3 → autoglm_gui-1.5.4}/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)
|
|
@@ -61,8 +61,18 @@ class AsyncGLMAgent:
|
|
|
61
61
|
# 取消机制
|
|
62
62
|
self._cancel_event = asyncio.Event()
|
|
63
63
|
|
|
64
|
+
# 初始化 system prompt(Agent 一创建就有"人格")
|
|
65
|
+
system_prompt = self.agent_config.system_prompt
|
|
66
|
+
if system_prompt is None:
|
|
67
|
+
system_prompt = get_system_prompt(self.agent_config.lang)
|
|
68
|
+
|
|
69
|
+
# 保存初始 system message 用于 reset()
|
|
70
|
+
self._initial_system_message = MessageBuilder.create_system_message(
|
|
71
|
+
system_prompt
|
|
72
|
+
)
|
|
73
|
+
|
|
64
74
|
# 状态
|
|
65
|
-
self._context: list[dict[str, Any]] = []
|
|
75
|
+
self._context: list[dict[str, Any]] = [self._initial_system_message]
|
|
66
76
|
self._step_count = 0
|
|
67
77
|
self._is_running = False
|
|
68
78
|
|
|
@@ -82,35 +92,46 @@ class AsyncGLMAgent:
|
|
|
82
92
|
- "cancelled": {"message": str}
|
|
83
93
|
- "error": {"message": str}
|
|
84
94
|
"""
|
|
85
|
-
self._context = []
|
|
86
|
-
self._step_count = 0
|
|
87
95
|
self._is_running = True
|
|
88
96
|
self._cancel_event.clear()
|
|
89
97
|
|
|
90
98
|
try:
|
|
91
|
-
#
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
# ===== 初始化阶段:添加首次用户输入 =====
|
|
100
|
+
try:
|
|
101
|
+
screenshot = await asyncio.to_thread(self.device.get_screenshot)
|
|
102
|
+
current_app = await asyncio.to_thread(self.device.get_current_app)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
logger.error(f"Failed to get device info during initialization: {e}")
|
|
105
|
+
yield {
|
|
106
|
+
"type": "error",
|
|
107
|
+
"data": {"message": f"Device error: {e}"},
|
|
108
|
+
}
|
|
109
|
+
yield {
|
|
110
|
+
"type": "done",
|
|
111
|
+
"data": {
|
|
112
|
+
"message": f"Device error: {e}",
|
|
113
|
+
"steps": 0,
|
|
114
|
+
"success": False,
|
|
115
|
+
},
|
|
116
|
+
}
|
|
117
|
+
return
|
|
94
118
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
yield {
|
|
98
|
-
"type": "done",
|
|
99
|
-
"data": {
|
|
100
|
-
"message": event["data"].get("message", "Task completed"),
|
|
101
|
-
"steps": self._step_count,
|
|
102
|
-
"success": event["data"].get("success", True),
|
|
103
|
-
},
|
|
104
|
-
}
|
|
105
|
-
return
|
|
119
|
+
screen_info = MessageBuilder.build_screen_info(current_app)
|
|
120
|
+
initial_message = f"{task}\n\n** Screen Info **\n\n{screen_info}"
|
|
106
121
|
|
|
107
|
-
|
|
122
|
+
self._context.append(
|
|
123
|
+
MessageBuilder.create_user_message(
|
|
124
|
+
text=initial_message, image_base64=screenshot.base64_data
|
|
125
|
+
)
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# ===== 执行阶段:循环执行步骤 =====
|
|
108
129
|
while self._step_count < self.agent_config.max_steps and self._is_running:
|
|
109
130
|
# 检查取消
|
|
110
131
|
if self._cancel_event.is_set():
|
|
111
132
|
raise asyncio.CancelledError()
|
|
112
133
|
|
|
113
|
-
async for event in self._execute_step_async(
|
|
134
|
+
async for event in self._execute_step_async():
|
|
114
135
|
yield event
|
|
115
136
|
|
|
116
137
|
# 检查是否完成
|
|
@@ -147,21 +168,19 @@ class AsyncGLMAgent:
|
|
|
147
168
|
finally:
|
|
148
169
|
self._is_running = False
|
|
149
170
|
|
|
150
|
-
async def _execute_step_async(
|
|
151
|
-
self, user_prompt: str | None, is_first: bool
|
|
152
|
-
) -> AsyncIterator[dict[str, Any]]:
|
|
171
|
+
async def _execute_step_async(self) -> AsyncIterator[dict[str, Any]]:
|
|
153
172
|
"""执行单步,支持流式输出和取消。
|
|
154
173
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
174
|
+
注意:不再需要 user_prompt 参数,因为:
|
|
175
|
+
- 首次用户输入已在 stream() 的初始化阶段添加
|
|
176
|
+
- 此方法只负责执行步骤:获取屏幕 → 调用 LLM → 执行动作
|
|
158
177
|
|
|
159
178
|
Yields:
|
|
160
179
|
dict[str, Any]: 事件字典
|
|
161
180
|
"""
|
|
162
181
|
self._step_count += 1
|
|
163
182
|
|
|
164
|
-
# 1.
|
|
183
|
+
# 1. 获取当前屏幕状态(使用线程池)
|
|
165
184
|
try:
|
|
166
185
|
screenshot = await asyncio.to_thread(self.device.get_screenshot)
|
|
167
186
|
current_app = await asyncio.to_thread(self.device.get_current_app)
|
|
@@ -184,42 +203,21 @@ class AsyncGLMAgent:
|
|
|
184
203
|
}
|
|
185
204
|
return
|
|
186
205
|
|
|
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))
|
|
206
|
+
# 2. 构建消息(统一格式:只有屏幕信息)
|
|
207
|
+
screen_info = MessageBuilder.build_screen_info(current_app)
|
|
208
|
+
text_content = f"** Screen Info **\n\n{screen_info}"
|
|
194
209
|
|
|
195
|
-
|
|
196
|
-
|
|
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}"
|
|
209
|
-
|
|
210
|
-
self._context.append(
|
|
211
|
-
MessageBuilder.create_user_message(
|
|
212
|
-
text=text_content, image_base64=screenshot.base64_data
|
|
213
|
-
)
|
|
210
|
+
self._context.append(
|
|
211
|
+
MessageBuilder.create_user_message(
|
|
212
|
+
text=text_content, image_base64=screenshot.base64_data
|
|
214
213
|
)
|
|
214
|
+
)
|
|
215
215
|
|
|
216
216
|
# 3. 流式调用 OpenAI(真正的异步,可取消)
|
|
217
217
|
try:
|
|
218
218
|
if self.agent_config.verbose:
|
|
219
219
|
msgs = get_messages(self.agent_config.lang)
|
|
220
|
-
|
|
221
|
-
print(f"💭 {msgs['thinking']}:")
|
|
222
|
-
print("-" * 50)
|
|
220
|
+
logger.debug(f"💭 {msgs['thinking']}:")
|
|
223
221
|
|
|
224
222
|
thinking_parts = []
|
|
225
223
|
raw_content = ""
|
|
@@ -240,7 +238,7 @@ class AsyncGLMAgent:
|
|
|
240
238
|
|
|
241
239
|
# Verbose output
|
|
242
240
|
if self.agent_config.verbose:
|
|
243
|
-
|
|
241
|
+
logger.debug(chunk_data["content"])
|
|
244
242
|
|
|
245
243
|
elif chunk_data["type"] == "raw":
|
|
246
244
|
raw_content += chunk_data["content"]
|
|
@@ -254,7 +252,7 @@ class AsyncGLMAgent:
|
|
|
254
252
|
except Exception as e:
|
|
255
253
|
logger.error(f"LLM error: {e}")
|
|
256
254
|
if self.agent_config.verbose:
|
|
257
|
-
traceback.
|
|
255
|
+
logger.debug(traceback.format_exc())
|
|
258
256
|
|
|
259
257
|
yield {
|
|
260
258
|
"type": "error",
|
|
@@ -285,11 +283,8 @@ class AsyncGLMAgent:
|
|
|
285
283
|
|
|
286
284
|
if self.agent_config.verbose:
|
|
287
285
|
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")
|
|
286
|
+
logger.debug(f"🎯 {msgs['action']}:")
|
|
287
|
+
logger.debug(json.dumps(action, ensure_ascii=False, indent=2))
|
|
293
288
|
|
|
294
289
|
# 5. 执行 action(使用线程池)
|
|
295
290
|
try:
|
|
@@ -299,7 +294,7 @@ class AsyncGLMAgent:
|
|
|
299
294
|
except Exception as e:
|
|
300
295
|
logger.error(f"Action execution error: {e}")
|
|
301
296
|
if self.agent_config.verbose:
|
|
302
|
-
traceback.
|
|
297
|
+
logger.debug(traceback.format_exc())
|
|
303
298
|
result = ActionResult(success=False, should_finish=True, message=str(e))
|
|
304
299
|
|
|
305
300
|
# 6. 更新上下文
|
|
@@ -316,11 +311,9 @@ class AsyncGLMAgent:
|
|
|
316
311
|
|
|
317
312
|
if finished and self.agent_config.verbose:
|
|
318
313
|
msgs = get_messages(self.agent_config.lang)
|
|
319
|
-
|
|
320
|
-
print(
|
|
314
|
+
logger.debug(
|
|
321
315
|
f"✅ {msgs['task_completed']}: {result.message or action.get('message', msgs['done'])}"
|
|
322
316
|
)
|
|
323
|
-
print("=" * 50 + "\n")
|
|
324
317
|
|
|
325
318
|
# 8. 返回步骤结果
|
|
326
319
|
yield {
|
|
@@ -452,8 +445,8 @@ class AsyncGLMAgent:
|
|
|
452
445
|
logger.info("AsyncGLMAgent cancelled by user")
|
|
453
446
|
|
|
454
447
|
def reset(self) -> None:
|
|
455
|
-
"""
|
|
456
|
-
self._context = []
|
|
448
|
+
"""重置状态(恢复到初始状态,保留 system message)。"""
|
|
449
|
+
self._context = [self._initial_system_message]
|
|
457
450
|
self._step_count = 0
|
|
458
451
|
self._is_running = False
|
|
459
452
|
self._cancel_event.clear()
|
|
@@ -482,12 +475,31 @@ class AsyncGLMAgent:
|
|
|
482
475
|
Returns:
|
|
483
476
|
StepResult: 步骤结果
|
|
484
477
|
"""
|
|
485
|
-
|
|
486
|
-
if
|
|
487
|
-
|
|
478
|
+
is_first_execution = len(self._context) == 1 # 只有 system message
|
|
479
|
+
if is_first_execution:
|
|
480
|
+
if not task:
|
|
481
|
+
raise ValueError("Task is required for the first step")
|
|
482
|
+
|
|
483
|
+
# 首次执行:需要先添加用户输入
|
|
484
|
+
try:
|
|
485
|
+
screenshot = await asyncio.to_thread(self.device.get_screenshot)
|
|
486
|
+
current_app = await asyncio.to_thread(self.device.get_current_app)
|
|
487
|
+
except Exception as e:
|
|
488
|
+
logger.error(f"Failed to get device info during initialization: {e}")
|
|
489
|
+
raise RuntimeError(f"Device error: {e}") from e
|
|
490
|
+
|
|
491
|
+
screen_info = MessageBuilder.build_screen_info(current_app)
|
|
492
|
+
initial_message = f"{task}\n\n** Screen Info **\n\n{screen_info}"
|
|
493
|
+
|
|
494
|
+
self._context.append(
|
|
495
|
+
MessageBuilder.create_user_message(
|
|
496
|
+
text=initial_message, image_base64=screenshot.base64_data
|
|
497
|
+
)
|
|
498
|
+
)
|
|
488
499
|
|
|
500
|
+
# 执行步骤
|
|
489
501
|
result = None
|
|
490
|
-
async for event in self._execute_step_async(
|
|
502
|
+
async for event in self._execute_step_async():
|
|
491
503
|
if event["type"] == "step":
|
|
492
504
|
result = StepResult(
|
|
493
505
|
thinking=event["data"]["thinking"],
|
|
@@ -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-CX4NAYCk.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-CX4NAYCk.js";import{P as g,c as x,b as f,d as m}from"./popover-CauTjrhB.js";import{D as p,d as h,e as w,f as j,g as D}from"./dialog-DSAhQHru.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};
|