update SOPs (web_setup, tmwebdriver, autonomous_op) + whitelist adb_ui.py

This commit is contained in:
Liang Jiaqing
2026-02-15 13:53:41 +08:00
parent caa39776ce
commit 04833eda0e
5 changed files with 102 additions and 13 deletions

3
.gitignore vendored
View File

@@ -58,6 +58,9 @@ memory/*
# TMWebDriver SOP
!memory/tmwebdriver_sop.md
# ADB UI tool
!memory/adb_ui.py
# Visual Studio
.vs/
restore_commit.txt

60
memory/adb_ui.py Normal file
View File

@@ -0,0 +1,60 @@
# adb_ui.py - 一键dump+解析Android UI
# PITFALLS: dump已内置--compressed; 美团等动画app需先禁动画(adb shell settings put global animator_duration_scale 0 ...共3条);
# 弹窗检测: ui(clickable_only=True, raw=True) 找全屏FrameLayout+底部小ImageView(关闭X)
# 已知包名: 美团外卖=com.sankuai.meituan.takeoutnew 淘宝=com.taobao.taobao
import subprocess, xml.etree.ElementTree as ET, os, re, shutil
ADB = shutil.which("adb") or "adb"
LOCAL_XML = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ui_mt.xml")
def ui(keyword=None, clickable_only=False, raw=False):
"""一键dump+解析Android UI
keyword: 过滤含关键词的节点
clickable_only: 只显示可点击节点
raw: 返回原始节点列表而非打印
"""
subprocess.run([ADB, "shell", "rm", "-f", "/sdcard/ui.xml"], capture_output=True)
r = subprocess.run([ADB, "shell", "uiautomator", "dump", "--compressed", "/sdcard/ui.xml"],
capture_output=True, text=True, timeout=15)
if "dumped" not in r.stdout.lower() and "dumped" not in r.stderr.lower():
print(f"dump failed: {r.stdout}{r.stderr}")
return []
subprocess.run([ADB, "pull", "/sdcard/ui.xml", LOCAL_XML], capture_output=True, timeout=10)
tree = ET.parse(LOCAL_XML)
nodes = []
for n in tree.getroot().iter("node"):
text = n.get("text", "")
desc = n.get("content-desc", "")
bounds = n.get("bounds", "")
click = n.get("clickable") == "true"
cls = n.get("class", "").split(".")[-1]
label = text or desc
if not label and not raw:
continue
if clickable_only and not click:
continue
if keyword and keyword.lower() not in (label or "").lower():
continue
cx, cy = 0, 0
if bounds:
m = re.findall(r'\[(\d+),(\d+)\]', bounds)
if len(m) == 2:
cx = (int(m[0][0]) + int(m[1][0])) // 2
cy = (int(m[0][1]) + int(m[1][1])) // 2
nodes.append({"label": label, "click": click, "bounds": bounds, "cx": cx, "cy": cy, "class": cls})
if not raw:
for n in nodes:
flag = "Y" if n["click"] else " "
coord = f"({n['cx']},{n['cy']})" if n['cx'] else ""
print(f"[{flag}] {n['label']} {coord} {n['bounds']}")
print(f"\ntotal: {len(nodes)} nodes")
return nodes
def tap(x, y):
subprocess.run([ADB, "shell", "input", "tap", str(x), str(y)], capture_output=True)
print(f"tap({x},{y}) ok")
if __name__ == "__main__":
ui()

View File

@@ -16,6 +16,7 @@
### 选择原则
- **增量价值优先**:必须产生新知识/新能力,优先选择能扩展自身操作能力的任务
- **盲区优先**:探索产出须为自身参数无法复现的知识(小众库发现与用法、环境特有的坑),学已熟知库的基础用法无价值
- **自主发现**主动扫描用户环境pip list、项目目录、配置文件发现未知工具而非等用户告知
- **假设驱动**:明确"要验证什么假设",实验必须有动手验证环节
- **禁止低价值验证**:不验证 global_mem 中的静态配置,不做无假设的巡检

View File

@@ -17,7 +17,7 @@
- 受浏览器 **InTrusted / 权限策略** 限制,有些操作不能单靠 TMWebDriver 完成:
1. **打开新窗口 / 新标签**
- 部分浏览器/脚本设置中,需要用户显式允许脚本打开新标签/窗口”;否则相关命令会被拦截
- 已通过 GM_openInTab 替换 window.open 解决。潜在问题:部分浏览器可能仍需用户显式允许脚本打开新标签。
2. **上传文件等受信任交互**
- 通常无法单纯用 JS 填充 `<input type="file">` 等敏感控件。
- 需要配合键鼠控制工具(`ljqCtrl.py` / 控制 SOP在前台模拟真实点击和文件选择。

View File

@@ -1,18 +1,43 @@
# Web 工具链初始化执行 SOP (精简版)
# Web 工具链初始化执行 SOP
若web_scanweb_execute_js已测试可用无需行此sop
此sop仅供初始安装时code_run可用但web工具第一次配置使用
web_scanweb_execute_js 已测试可用,无需行此 SOP
仅供初始安装时code_run 可用但 web 工具尚未配置的场景
## 目标
在仅具备系统级权限时,引导用户建立 Web 交互能力
在仅具备系统级权限code_run建立 Web 交互能力web_scan / web_execute_js
## 阶段一:引导安装 (Action: code_run)
1. **启动导航**:使用 PowerShell 启动 Chrome 并直达测试版页面:
`start chrome "https://chromewebstore.google.com/detail/%E7%AF%A1%E6%94%B9%E7%8C%B4%E6%B5%8B%E8%AF%95%E7%89%88/gcalenpjmijncebpfijmoaglllgpjagf"`
## 前置:检测浏览器
```python
import shutil, subprocess
browser = "chrome" if shutil.which("chrome") else "msedge" # Edge内置必存在Chrome可选
```
## 阶段二:脚本分发 (Action: file_read + code_run)
1. **资源提取与写入**:使用 Python 读取 `../assets/ljq_web_driver.user.js` 并通过 `pyperclip` 写入系统剪贴板
2. **用户交互指令**:通知用户“脚本已入剪贴板”,请求用户在插件中完成【新建-全选-粘贴-保存】操作。
## 阶段一:安装 Tampermonkey (手动)
**状态**: 尚未实现自动化,需用户手动操作
1. `start` 打开扩展商店页面(自动适配浏览器):
- Chrome: `start "" "https://chromewebstore.google.com/detail/篡改猴测试版/gcalenpjmijncebpfijmoaglllgpjagf"`
- Edge: `start "" "https://microsoftedge.microsoft.com/addons/detail/tampermonkey/iikmkjmpaadaobahmlepeloendndfphd"`
2. 提示用户点击"安装"并确认。
## 阶段三:环境确认 (Action: code_run)
1. **切换驱动**:尝试调用 `web_scan` 或注入 JS 进行心跳检测,确认 `ljq_web_driver.user.js` 是否已在目标域生效。
## 阶段二:安装 ljq_web_driver.user.js
**脚本路径**: `../assets/ljq_web_driver.user.js`
### 方案A自动化优先
本地 HTTP 服务器 + TM 中间页,用 `start` 命令打开:
1. Python 启动 `http.server` 托管脚本Content-Type: text/javascript
2. `start "" "https://www.tampermonkey.net/script_installation.php#url=http://127.0.0.1:{port}/ljq_web_driver.user.js"`
- ⚠️ 以上步骤均须用 `Popen` 非阻塞执行,禁止 `subprocess.run`,否则阻塞 agent
3. TM 秒弹安装确认,用户点"安装"即可
### 方案B手动 fallback
若方案A失败用剪贴板
1. 读取脚本内容 → `pyperclip.copy()`
2. 通知用户在 TM 中【新建脚本 → 全选 → 粘贴 → 保存】
## 阶段三:验证
调用 `web_scan` 或注入 JS 心跳检测,确认脚本已生效。
## 避坑 (Chromium untrusted 拦截)
- ❌ 直接导航到 `localhost/.user.js` → Chromium 弹 untrusted 拦截 + "另存为"延迟约1分钟
- ✅ 必须用 `start` 命令(系统级)打开 TM 中间页 URL → 秒弹安装,无拦截
- 此问题 Chrome 和 Edge 均存在Chromium 内核通病)