autoglm-gui 1.2.0__py3-none-any.whl → 1.3.0__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/adb_plus/__init__.py +6 -6
- AutoGLM_GUI/api/__init__.py +49 -15
- AutoGLM_GUI/api/agents.py +163 -209
- AutoGLM_GUI/api/dual_model.py +310 -0
- AutoGLM_GUI/api/mcp.py +134 -0
- AutoGLM_GUI/api/metrics.py +36 -0
- AutoGLM_GUI/config_manager.py +110 -6
- AutoGLM_GUI/dual_model/__init__.py +53 -0
- AutoGLM_GUI/dual_model/decision_model.py +664 -0
- AutoGLM_GUI/dual_model/dual_agent.py +917 -0
- AutoGLM_GUI/dual_model/protocols.py +354 -0
- AutoGLM_GUI/dual_model/vision_model.py +442 -0
- AutoGLM_GUI/exceptions.py +75 -3
- AutoGLM_GUI/metrics.py +283 -0
- AutoGLM_GUI/phone_agent_manager.py +264 -14
- AutoGLM_GUI/prompts.py +97 -0
- AutoGLM_GUI/schemas.py +40 -9
- AutoGLM_GUI/static/assets/{about-PcGX7dIG.js → about-CrBXGOgB.js} +1 -1
- AutoGLM_GUI/static/assets/chat-Di2fwu8V.js +124 -0
- AutoGLM_GUI/static/assets/dialog-CHJSPLHJ.js +45 -0
- AutoGLM_GUI/static/assets/{index-DOt5XNhh.js → index-9IaIXvyy.js} +1 -1
- AutoGLM_GUI/static/assets/index-Dt7cVkfR.js +12 -0
- AutoGLM_GUI/static/assets/index-Z0uYCPOO.css +1 -0
- AutoGLM_GUI/static/assets/{workflows-B1hgBC_O.js → workflows-DHadKApI.js} +1 -1
- AutoGLM_GUI/static/index.html +2 -2
- {autoglm_gui-1.2.0.dist-info → autoglm_gui-1.3.0.dist-info}/METADATA +11 -4
- {autoglm_gui-1.2.0.dist-info → autoglm_gui-1.3.0.dist-info}/RECORD +30 -20
- AutoGLM_GUI/static/assets/chat-B0FKL2ne.js +0 -124
- AutoGLM_GUI/static/assets/dialog-BSNX0L1i.js +0 -45
- AutoGLM_GUI/static/assets/index-BjYIY--m.css +0 -1
- AutoGLM_GUI/static/assets/index-CnEYDOXp.js +0 -11
- {autoglm_gui-1.2.0.dist-info → autoglm_gui-1.3.0.dist-info}/WHEEL +0 -0
- {autoglm_gui-1.2.0.dist-info → autoglm_gui-1.3.0.dist-info}/entry_points.txt +0 -0
- {autoglm_gui-1.2.0.dist-info → autoglm_gui-1.3.0.dist-info}/licenses/LICENSE +0 -0
AutoGLM_GUI/prompts.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""MCP-specific prompts with Fail-Fast and Step Limit constraints.
|
|
2
|
+
|
|
3
|
+
These prompts are optimized for MCP tool calls where:
|
|
4
|
+
1. Tasks should be atomic and complete within 5 steps
|
|
5
|
+
2. Fail-fast behavior is preferred over exploratory attempts
|
|
6
|
+
3. Clear error reporting is required for the caller to handle
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
today = datetime.today()
|
|
12
|
+
weekday_names = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]
|
|
13
|
+
weekday = weekday_names[today.weekday()]
|
|
14
|
+
formatted_date = today.strftime("%Y年%m月%d日") + " " + weekday
|
|
15
|
+
|
|
16
|
+
MCP_SYSTEM_PROMPT_ZH = f"""
|
|
17
|
+
# Context
|
|
18
|
+
当前日期: {formatted_date}
|
|
19
|
+
角色: 你是 Mobile UI Executor(移动端界面执行器)。
|
|
20
|
+
职责: 接收上层指令,分析手机屏幕截图,输出最精准的单步操作指令。
|
|
21
|
+
**当前任务步数**: current_step_count / 5
|
|
22
|
+
|
|
23
|
+
# CRITICAL CONSTRAINTS (核心约束)
|
|
24
|
+
|
|
25
|
+
1. **Fail Fast (快速报错)**:
|
|
26
|
+
上层指令通常包含一个明确的目标(如"点击设置按钮")。
|
|
27
|
+
**在执行任何点击操作前,必须在屏幕上确认识别到了该元素。**
|
|
28
|
+
如果当前屏幕**根本没有**上层要求的元素,且你判断简单的滑动也无法找到它,**禁止猜测坐标**,必须立即调用 `finish` 报错。
|
|
29
|
+
|
|
30
|
+
2. **Step Limit (步数熔断)**:
|
|
31
|
+
如果当前子任务连续操作已达 **5步** 仍未完成,立即调用 `finish` 中断。
|
|
32
|
+
|
|
33
|
+
# Output Format
|
|
34
|
+
严格 XML 格式:
|
|
35
|
+
<think>
|
|
36
|
+
1. **Target Check**: 上层让我找什么?屏幕上有吗?
|
|
37
|
+
2. **Step Check**: 步数是否超限?
|
|
38
|
+
3. **Observation**: 屏幕布局描述。
|
|
39
|
+
4. **Reasoning**: 决策逻辑。
|
|
40
|
+
</think>
|
|
41
|
+
<answer>
|
|
42
|
+
{{action}}
|
|
43
|
+
</answer>
|
|
44
|
+
|
|
45
|
+
# Action Space (API)
|
|
46
|
+
|
|
47
|
+
## 1. 基础交互
|
|
48
|
+
- do(action="Tap", element=[x,y]): 点击坐标。**严禁点击不存在的元素。**
|
|
49
|
+
- do(action="Tap", element=[x,y], message="Sensitive"): 敏感点击。
|
|
50
|
+
- do(action="Double Tap", element=[x,y]): 双击。
|
|
51
|
+
- do(action="Long Press", element=[x,y]): 长按。
|
|
52
|
+
|
|
53
|
+
## 2. 输入与文本
|
|
54
|
+
- do(action="Type", text="string"): 在已聚焦输入框输入。
|
|
55
|
+
- do(action="Type_Name", text="string"): 输入人名。
|
|
56
|
+
|
|
57
|
+
## 3. 导航与滑动
|
|
58
|
+
- do(action="Swipe", start=[x1,y1], end=[x2,y2]): 滑动。
|
|
59
|
+
- do(action="Back"): 返回/关闭。
|
|
60
|
+
- do(action="Home"): 回到桌面。
|
|
61
|
+
- do(action="Launch", app="AppName"): 启动 App。
|
|
62
|
+
|
|
63
|
+
## 4. 流程控制与结束
|
|
64
|
+
- do(action="Wait", duration="seconds"): 等待加载。
|
|
65
|
+
- do(action="Note", message="content"): 记录信息。
|
|
66
|
+
- finish(message="reason"): 任务终止。
|
|
67
|
+
- *正常完成*: message="任务已完成..."
|
|
68
|
+
- *未找到元素*: message="ELEMENT_NOT_FOUND: 当前屏幕未发现'xxx'按钮/元素,无法继续执行。" (目标缺失时必填此格式)
|
|
69
|
+
- *步数超限*: message="STEP_LIMIT_EXCEEDED: 已执行5步..."
|
|
70
|
+
|
|
71
|
+
# Execution Heuristics (执行原则)
|
|
72
|
+
|
|
73
|
+
## A. 目标验证 (Target Verification) - 优先级最高
|
|
74
|
+
1. **所见即所得**: 在输出 `Tap` 之前,问自己:"我真的在截图里看到这个按钮了吗?"
|
|
75
|
+
- 如果看到了 -> 执行 `Tap`。
|
|
76
|
+
- 如果没看到,且页面已加载完毕 -> 执行 `finish(message="ELEMENT_NOT_FOUND...")`。
|
|
77
|
+
- **绝对禁止**幻视或根据经验猜测坐标。
|
|
78
|
+
|
|
79
|
+
## B. 异常与等待
|
|
80
|
+
1. **加载中**: 如果屏幕是白屏或转圈,不要报错找不到元素,请执行 `Wait`。
|
|
81
|
+
2. **干扰**: 如果有弹窗挡住了目标,先点击关闭弹窗,不要直接报错。
|
|
82
|
+
|
|
83
|
+
## C. 搜索策略
|
|
84
|
+
1. **有限尝试**: 如果目标可能在屏幕下方(如列表),可以尝试 `Swipe` 一次。但如果上层指令非常具体(如"点击右上角的保存"),而该位置没有按钮,直接报错,不要滑动。
|
|
85
|
+
|
|
86
|
+
# Thinking Example (找不到元素场景)
|
|
87
|
+
Instruction: "点击'提交订单'按钮"
|
|
88
|
+
Screen: 屏幕显示购物车列表,底部只有'去结算'按钮,没有'提交订单'字样。
|
|
89
|
+
<think>
|
|
90
|
+
1. Target Check: 目标是"提交订单"。
|
|
91
|
+
2. Observation: 屏幕底部显示的是"去结算",而不是"提交订单"。可能UI文案不匹配,或者流程还没到那一步。
|
|
92
|
+
3. Reasoning: 我无法在当前视野找到指令要求的"提交订单"元素。盲目点击"去结算"可能会导致非预期行为(虽然意思相近,但应由上层决策)。根据 Fail Fast 原则,我应该上报缺失情况。
|
|
93
|
+
</think>
|
|
94
|
+
<answer>
|
|
95
|
+
finish(message="ELEMENT_NOT_FOUND: 当前页面底部只有'去结算'按钮,未找到'提交订单'按钮,请确认下一步指令。")
|
|
96
|
+
</answer>
|
|
97
|
+
"""
|
AutoGLM_GUI/schemas.py
CHANGED
|
@@ -319,16 +319,17 @@ class ConfigResponse(BaseModel):
|
|
|
319
319
|
model_name: str
|
|
320
320
|
api_key: str # 返回实际值(明文)
|
|
321
321
|
source: str # "CLI arguments" | "environment variables" | "config file (...)" | "default"
|
|
322
|
+
|
|
323
|
+
# 双模型配置
|
|
324
|
+
dual_model_enabled: bool = False
|
|
325
|
+
decision_base_url: str = ""
|
|
326
|
+
decision_model_name: str = ""
|
|
327
|
+
decision_api_key: str = ""
|
|
328
|
+
|
|
329
|
+
# 思考模式
|
|
330
|
+
thinking_mode: str = "deep" # "fast" | "deep"
|
|
331
|
+
|
|
322
332
|
conflicts: list[dict] | None = None # 配置冲突信息(可选)
|
|
323
|
-
# conflicts 示例:
|
|
324
|
-
# [
|
|
325
|
-
# {
|
|
326
|
-
# "field": "base_url",
|
|
327
|
-
# "file_value": "http://localhost:8080/v1",
|
|
328
|
-
# "override_value": "https://api.example.com",
|
|
329
|
-
# "override_source": "CLI arguments"
|
|
330
|
-
# }
|
|
331
|
-
# ]
|
|
332
333
|
|
|
333
334
|
|
|
334
335
|
class ConfigSaveRequest(BaseModel):
|
|
@@ -338,6 +339,15 @@ class ConfigSaveRequest(BaseModel):
|
|
|
338
339
|
model_name: str = "autoglm-phone-9b"
|
|
339
340
|
api_key: str | None = None
|
|
340
341
|
|
|
342
|
+
# 双模型配置
|
|
343
|
+
dual_model_enabled: bool | None = None
|
|
344
|
+
decision_base_url: str | None = None
|
|
345
|
+
decision_model_name: str | None = None
|
|
346
|
+
decision_api_key: str | None = None
|
|
347
|
+
|
|
348
|
+
# 思考模式
|
|
349
|
+
thinking_mode: str | None = None # "fast" | "deep"
|
|
350
|
+
|
|
341
351
|
@field_validator("base_url")
|
|
342
352
|
@classmethod
|
|
343
353
|
def validate_base_url(cls, v: str) -> str:
|
|
@@ -357,6 +367,27 @@ class ConfigSaveRequest(BaseModel):
|
|
|
357
367
|
raise ValueError("model_name cannot be empty")
|
|
358
368
|
return v.strip()
|
|
359
369
|
|
|
370
|
+
@field_validator("thinking_mode")
|
|
371
|
+
@classmethod
|
|
372
|
+
def validate_thinking_mode(cls, v: str | None) -> str | None:
|
|
373
|
+
"""验证 thinking_mode."""
|
|
374
|
+
if v is None:
|
|
375
|
+
return v
|
|
376
|
+
if v not in ("fast", "deep"):
|
|
377
|
+
raise ValueError("thinking_mode must be 'fast' or 'deep'")
|
|
378
|
+
return v
|
|
379
|
+
|
|
380
|
+
@field_validator("decision_base_url")
|
|
381
|
+
@classmethod
|
|
382
|
+
def validate_decision_base_url(cls, v: str | None) -> str | None:
|
|
383
|
+
"""验证 decision_base_url 格式."""
|
|
384
|
+
if v is None or not v.strip():
|
|
385
|
+
return None
|
|
386
|
+
v = v.strip()
|
|
387
|
+
if not re.match(r"^https?://", v):
|
|
388
|
+
raise ValueError("decision_base_url must start with http:// or https://")
|
|
389
|
+
return v
|
|
390
|
+
|
|
360
391
|
|
|
361
392
|
class WiFiConnectRequest(BaseModel):
|
|
362
393
|
device_id: str | None = None
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as o}from"./index-
|
|
1
|
+
import{j as o}from"./index-Dt7cVkfR.js";function t(){return o.jsx("div",{className:"p-2",children:o.jsx("h3",{children:"About"})})}export{t as component};
|