fix: dedup working_mem hint, flush incremental output tail, sche_tasks path, CLI KeyboardInterrupt handling; add Termux instructions to README
This commit is contained in:
@@ -13,8 +13,7 @@ def _dump_u2():
|
||||
import uiautomator2 as u2
|
||||
d = u2.connect()
|
||||
xml_str = d.dump_hierarchy()
|
||||
if xml_str and len(xml_str) > 100:
|
||||
return xml_str
|
||||
if xml_str and len(xml_str) > 100: return xml_str
|
||||
except Exception as e:
|
||||
print(f"[u2 fallback] {e}")
|
||||
return None
|
||||
@@ -24,9 +23,7 @@ def _dump_native():
|
||||
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 None
|
||||
if "dumped" not in r.stdout.lower() and "dumped" not in r.stderr.lower(): print(f"dump failed: {r.stdout}{r.stderr}"); return None
|
||||
subprocess.run([ADB, "pull", "/sdcard/ui.xml", LOCAL_XML], capture_output=True, timeout=10)
|
||||
with open(LOCAL_XML, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
@@ -36,6 +33,8 @@ def _parse_xml(xml_str, keyword=None, clickable_only=False, raw=False):
|
||||
root = ET.fromstring(xml_str)
|
||||
nodes = []
|
||||
for n in root.iter("node"):
|
||||
pkg = n.get("package", "")
|
||||
if "termux" in pkg.lower(): continue
|
||||
text = n.get("text", "")
|
||||
desc = n.get("content-desc", "")
|
||||
bounds = n.get("bounds", "")
|
||||
@@ -43,20 +42,17 @@ def _parse_xml(xml_str, keyword=None, clickable_only=False, raw=False):
|
||||
cls = n.get("class", "").split(".")[-1]
|
||||
rid = n.get("resource-id", "")
|
||||
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
|
||||
if not label and not raw: continue
|
||||
if clickable_only and not click: continue
|
||||
if keyword and keyword.lower() not in label.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, "id": rid})
|
||||
nodes.append({"text": text or desc, "click": click,
|
||||
"bounds": bounds, "cx": cx, "cy": cy, "class": cls, "id": rid})
|
||||
return nodes
|
||||
|
||||
def ui(keyword=None, clickable_only=False, raw=False):
|
||||
@@ -66,15 +62,13 @@ def ui(keyword=None, clickable_only=False, raw=False):
|
||||
raw: 返回原始节点列表而非打印
|
||||
"""
|
||||
xml_str = _dump_u2() or _dump_native()
|
||||
if not xml_str:
|
||||
print("dump failed (both u2 and native)")
|
||||
return []
|
||||
if not xml_str: print("dump failed (both u2 and native)"); return []
|
||||
nodes = _parse_xml(xml_str, keyword, clickable_only, raw)
|
||||
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"[{flag}] {n['text']} {coord} {n['bounds']}")
|
||||
print(f"\ntotal: {len(nodes)} nodes")
|
||||
return nodes
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
授权你进行自主行动,只要不对环境造成副作用都可进行。
|
||||
请先选择核心目标,再选择一个小目标进行。最终探测结果形成报告(含操作申请),待用户回来确认后再进行可能的写入或修改操作。
|
||||
|
||||
> **启动时写入工作记忆**:`自主探索|≤15回合|只有cwd内可写|用户不在(问题存报告)|收尾:更新history.txt+重读本SOP检查遗漏|产出=报告+记忆提案`
|
||||
> **启动时写入工作记忆**:`自主探索|≤15回合|只有cwd内可写|用户不在(问题存报告)|收尾:重读本SOP检查遗漏+更新history|产出=报告+记忆提案`
|
||||
|
||||
## 🎯 核心目标(按价值优先级排序)
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
### 阶段 1:自主探测(用户离开时)
|
||||
- **启动检查**:
|
||||
- 读取可能有的 `./autonomous_reports/history.txt` 了解历史记录。
|
||||
- **不连续选择相同方向**。
|
||||
- **TODO优先**:若cwd下存在 `TODO.txt`,优先从中选择任务执行;任务完成后从TODO.txt中移除对应条目。
|
||||
- **不连续选择相同方向**(TODO任务除外)。
|
||||
- **预期收益声明**:选定任务后,必须先用一句话写明「做这个任务预期带来什么收益」。允许探索失败,但必须事先想清楚为什么值得做。这句话写入报告开头。
|
||||
- **执行方式**:基于目标自由进行,无需预先批准,直接执行只读或实验性操作。
|
||||
- **约束**:小步快跑,每次只做一个小任务(剩下的下次再做),控制在15个回合以内。严禁修改核心记忆/系统设置;严禁读取敏感数据(但可以检测存在性)。
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# 定时任务 SOP
|
||||
|
||||
目录:`../tasks/{pending,running,done}/`
|
||||
目录:`../sche_tasks/{pending,running,done}/`
|
||||
文件名:`YYYY-MM-DD_HHMM_描述.md`,内容含prompt和schedule
|
||||
|
||||
## 流程
|
||||
1. [AUTO]唤醒 → `datetime.now()`取当前时间,`ls ../tasks/pending/`,文件名时间≤当前→到期,选择一个
|
||||
1. [AUTO]唤醒 → `datetime.now()`取当前时间,`ls ../sche_tasks/pending/`,文件名时间≤当前→到期,选择一个
|
||||
2. **立即rename到running/**(先占再读,防多进程重复领)
|
||||
3. 读文件执行
|
||||
4. 完成→移到done/,**在文件内追加执行报告**供用户查阅
|
||||
5. schedule非once→算下次时间,新建文件到pending/
|
||||
|
||||
注意tasks目录在../,即你的code root下
|
||||
注意sche_tasks目录在../,即你的code root下
|
||||
|
||||
@@ -40,3 +40,17 @@
|
||||
- "访问"链接:遍历所有`a`找`textContent.includes('访问')`的href
|
||||
- 缩略图base64:结果中`img[src^="data:image"]`可直接提取保存
|
||||
- 下载大图时注意JS返回的src可能被截断,用`return img.src`获取完整URL
|
||||
|
||||
## Chrome下载PDF(fetch+blob方案)
|
||||
- 场景:页面上的PDF链接点击后会在浏览器内预览而非下载
|
||||
- 方案:用JS `fetch(url)` 获取blob → `URL.createObjectURL(blob)` → 创建隐藏`<a>`标签设`download`属性 → 触发click → 自动下载到~/Downloads
|
||||
- 模板:
|
||||
```js
|
||||
fetch('PDF_URL').then(r=>r.blob()).then(b=>{
|
||||
const a=document.createElement('a');
|
||||
a.href=URL.createObjectURL(b);
|
||||
a.download='filename.pdf';
|
||||
a.click();
|
||||
});
|
||||
```
|
||||
- 注意:需同源或CORS允许;跨域时可能需要先导航到目标域再执行
|
||||
|
||||
Reference in New Issue
Block a user