autoglm-gui 1.5.2__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.
Files changed (121) hide show
  1. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/__main__.py +33 -7
  2. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/async_agent.py +84 -72
  3. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/__init__.py +16 -0
  4. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/agents.py +2 -3
  5. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/logger.py +3 -2
  6. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/about-D7r9gCvG.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/about-BZglkj97.js +1 -1
  7. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/alert-dialog-BKM-yRiQ.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/alert-dialog-5vNoxwIO.js +1 -1
  8. autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/chat-ta_RqZfZ.js +129 -0
  9. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/circle-alert-sohSDLhl.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/circle-alert-CnwO7Du-.js +1 -1
  10. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/dialog-BgtPh0d5.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/dialog-DSAhQHru.js +2 -2
  11. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/eye-DLqKbQmg.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/eye-Deqw6dbm.js +1 -1
  12. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/history-Bv1lfGUU.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/history-CL-JjUbk.js +1 -1
  13. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/index-CxWwh1VO.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/index-BjaUZM-7.js +1 -1
  14. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/index-SysdKciY.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/index-CX4NAYCk.js +8 -8
  15. autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/index-DSIMVL8V.css +1 -0
  16. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/label-DTUnzN4B.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/label-CEmK7RW4.js +1 -1
  17. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/logs-BIhnDizW.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/logs-C-Pnb4jI.js +1 -1
  18. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/popover-CikYqu2P.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/popover-CauTjrhB.js +1 -1
  19. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/scheduled-tasks-B-KBsGbl.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/scheduled-tasks-Ds1WrRVN.js +1 -1
  20. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/textarea-knJZrz77.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/textarea-nLU4tGQH.js +1 -1
  21. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/workflows-DzcSYwLZ.js → autoglm_gui-1.5.4/AutoGLM_GUI/static/assets/workflows-QIA3_mdp.js +1 -1
  22. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/index.html +2 -2
  23. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/PKG-INFO +1 -1
  24. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/pyproject.toml +1 -1
  25. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/chat-k6TTD7PW.js +0 -129
  26. autoglm_gui-1.5.2/AutoGLM_GUI/static/assets/index-CV7jGxGm.css +0 -1
  27. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/.gitignore +0 -0
  28. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/__init__.py +0 -0
  29. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/actions/__init__.py +0 -0
  30. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/actions/handler.py +0 -0
  31. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/actions/types.py +0 -0
  32. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/__init__.py +0 -0
  33. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/apps.py +0 -0
  34. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/connection.py +0 -0
  35. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/device.py +0 -0
  36. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/input.py +0 -0
  37. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/screenshot.py +0 -0
  38. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb/timing.py +0 -0
  39. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/__init__.py +0 -0
  40. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/device.py +0 -0
  41. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/ip.py +0 -0
  42. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/keyboard_installer.py +0 -0
  43. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/mdns.py +0 -0
  44. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/pair.py +0 -0
  45. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/qr_pair.py +0 -0
  46. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/screenshot.py +0 -0
  47. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/serial.py +0 -0
  48. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/touch.py +0 -0
  49. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/adb_plus/version.py +0 -0
  50. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/__init__.py +0 -0
  51. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/events.py +0 -0
  52. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/factory.py +0 -0
  53. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/__init__.py +0 -0
  54. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/agent.py +0 -0
  55. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/message_builder.py +0 -0
  56. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/parser.py +0 -0
  57. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/prompts_en.py +0 -0
  58. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/glm/prompts_zh.py +0 -0
  59. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/mai/__init__.py +0 -0
  60. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/mai/agent.py +0 -0
  61. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/mai/parser.py +0 -0
  62. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/mai/prompts.py +0 -0
  63. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/mai/traj_memory.py +0 -0
  64. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/protocols.py +0 -0
  65. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/agents/stream_runner.py +0 -0
  66. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/control.py +0 -0
  67. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/devices.py +0 -0
  68. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/health.py +0 -0
  69. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/history.py +0 -0
  70. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/layered_agent.py +0 -0
  71. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/mcp.py +0 -0
  72. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/media.py +0 -0
  73. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/metrics.py +0 -0
  74. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/scheduled_tasks.py +0 -0
  75. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/version.py +0 -0
  76. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/api/workflows.py +0 -0
  77. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/config.py +0 -0
  78. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/config_manager.py +0 -0
  79. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/device_manager.py +0 -0
  80. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/device_metadata_manager.py +0 -0
  81. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/device_protocol.py +0 -0
  82. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/devices/__init__.py +0 -0
  83. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/devices/adb_device.py +0 -0
  84. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/devices/mock_device.py +0 -0
  85. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/devices/remote_device.py +0 -0
  86. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/exceptions.py +0 -0
  87. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/history_manager.py +0 -0
  88. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/i18n.py +0 -0
  89. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/metrics.py +0 -0
  90. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/model/__init__.py +0 -0
  91. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/model/message_builder.py +0 -0
  92. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/model/types.py +0 -0
  93. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/models/__init__.py +0 -0
  94. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/models/history.py +0 -0
  95. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/models/scheduled_task.py +0 -0
  96. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/parsers/__init__.py +0 -0
  97. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/parsers/base.py +0 -0
  98. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/parsers/phone_parser.py +0 -0
  99. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/phone_agent_manager.py +0 -0
  100. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/platform_utils.py +0 -0
  101. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/prompt_config.py +0 -0
  102. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/prompts/__init__.py +0 -0
  103. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/prompts.py +0 -0
  104. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/scheduler_manager.py +0 -0
  105. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/schemas.py +0 -0
  106. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/scrcpy_protocol.py +0 -0
  107. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/scrcpy_stream.py +0 -0
  108. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/server.py +0 -0
  109. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/socketio_server.py +0 -0
  110. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/state.py +0 -0
  111. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/assets/logo-Cyfm06Ym.png +0 -0
  112. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/assets/worker-D6BRitjy.js +0 -0
  113. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/favicon.ico +0 -0
  114. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/logo-192.png +0 -0
  115. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/static/logo-512.png +0 -0
  116. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/types.py +0 -0
  117. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/version.py +0 -0
  118. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/AutoGLM_GUI/workflow_manager.py +0 -0
  119. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/LICENSE +0 -0
  120. {autoglm_gui-1.5.2 → autoglm_gui-1.5.4}/README.md +0 -0
  121. {autoglm_gui-1.5.2 → 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
- async for event in self._execute_step_async(task, is_first=True):
93
- yield event
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
- if event["type"] == "step" and event["data"].get("finished"):
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(None, is_first=False):
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
- Args:
156
- user_prompt: 用户输入(首步必需,后续可选)
157
- is_first: 是否是首步
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
- if is_first:
189
- system_prompt = self.agent_config.system_prompt
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
- 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}"
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
- print("\n" + "=" * 50)
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
- print(chunk_data["content"], end="", flush=True)
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.print_exc()
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
- print()
289
- print("-" * 50)
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.print_exc()
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
- print("\n" + "🎉 " + "=" * 48)
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
- is_first = len(self._context) == 0
486
- if is_first and not task:
487
- raise ValueError("Task is required for the first step")
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(task, is_first):
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
 
@@ -168,7 +168,7 @@ async def chat(request: ChatRequest) -> ChatResponse:
168
168
  acquired = False
169
169
  try:
170
170
  acquired = await asyncio.to_thread(
171
- manager.acquire_device, device_id, timeout=None, auto_initialize=False
171
+ manager.acquire_device, device_id, timeout=None, auto_initialize=True
172
172
  )
173
173
  # Use chat context with async agent
174
174
  agent = await asyncio.to_thread(
@@ -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:
@@ -247,7 +246,7 @@ async def chat_stream(request: ChatRequest):
247
246
  device_id,
248
247
  timeout=0,
249
248
  raise_on_timeout=True,
250
- auto_initialize=False,
249
+ auto_initialize=True,
251
250
  )
252
251
 
253
252
  try:
@@ -79,7 +79,8 @@ def configure_logger(
79
79
  _configured = True
80
80
 
81
81
 
82
- # Default initialization (can be reconfigured later)
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-SysdKciY.js";function t(){return o.jsx("div",{className:"p-2",children:o.jsx("h3",{children:"About"})})}export{t as component};
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-SysdKciY.js";import{P as g,c as x,b as f,d as m}from"./popover-CikYqu2P.js";import{D as p,d as h,e as w,f as j,g as D}from"./dialog-BgtPh0d5.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};
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};