Skip to content

新增跨任务 AI 记忆系统 + 绕过微信 8.0.52+ 无障碍节点隐藏 - #8

Open
plzkeepaway-huaQ wants to merge 1 commit into
apkclaw-team:mainfrom
plzkeepaway-huaQ:feature/ai-memory-and-chat-safety
Open

新增跨任务 AI 记忆系统 + 绕过微信 8.0.52+ 无障碍节点隐藏#8
plzkeepaway-huaQ wants to merge 1 commit into
apkclaw-team:mainfrom
plzkeepaway-huaQ:feature/ai-memory-and-chat-safety

Conversation

@plzkeepaway-huaQ

Copy link
Copy Markdown

PR: 新增跨任务 AI 记忆系统 + 绕过微信 8.0.52+ 无障碍节点隐藏

概述

这个 PR 解决两个长期存在的问题,显著提升 ApkClaw 在微信场景下的自动化能力:

  1. AI Agent 没有记忆 — 每次任务从零开始,历史经验无法复用,同样的坑反复踩
  2. 微信故意对第三方无障碍服务隐藏 UI 节点 — 导致 Agent 看不到微信界面元素,自动化完全失效

功能一:跨任务 AI 长期记忆系统

问题

之前 Agent 每次执行任务都是"失忆"状态 —— 上一轮学会了某个按钮的坐标,下一轮又要重新扫描。典型痛点:

  • 微信底部 Tab 的 TextView 不可点击,必须 tap 父容器 —— Agent 每轮都要重新试错
  • 同一个 App 的同一个页面,每次都要全量扫描 UI 树找元素,浪费大量 token 和轮次
  • 没有任何机制让 Agent 把学到的经验保留下来

解决方案

引入了两层记忆系统:

① 任务经验记忆(TaskMemory + RememberTool)

Agent 完成一个任务后,通过 remember(action="save", ...) 保存关键步骤和经验教训。下次新任务开始时,相关经验自动注入到系统提示中。

示例:
任务: "打开微信给树发消息"
经验:
  - 微信聊天列表项点击整行区域 [0,251][1080,447] 中心约 (540,349)
  - 发送按钮在输入框右侧 bounds=[916,1315][1052,1434]
  • MMKV 持久化存储,最多 100 条,超限自动淘汰最旧条目
  • 支持 save / search / list 三种操作
  • 开源 LLM(如 DeepSeek)的 ReAct 循环中注入记忆,不依赖 OpenAI/Anthropic 的原生记忆 API
  • 新增屏幕记忆(ScreenMemory):按应用缓存 UI 元素位置,支持跨任务复用(7 天过期)—— 已集成至获取屏幕信息工具(GetScreenInfoTool)和查找节点信息工具(FindNodeInfoTool)

② UI 元素位置缓存(ScreenMemory)

每次 get_screen_info 扫描屏幕时,自动把 UI 元素的坐标、类名、可点击性缓存下来。下次再进同一页面,直接贴坐标给 Agent:

[记忆 — 该 App 已知元素位置]
- 朋友圈: bounds=[153,297][288,359]
- 微信: bounds=[102,2245][168,2289] ⚠非clickable,需tap父容器
- 发现: bounds=[494,154][586,216] ⚠非clickable,需tap父容器
  • 按包名分组存储(com.tencent.mmcom.android.launcher 等)
  • 7 天自动过期,防止 UI 更新后坐标过时
  • GetScreenInfoTool 扫描时自动录入,FindNodeInfoTool 查找时优先查缓存

效果

  • Agent 打开微信后不需要再扫描找 Tab 栏,直接从缓存读坐标
  • 同一页面多次访问,跳过全量 UI 扫描
  • 历史任务的经验教训直接指导新任务,避免重复踩坑

功能二:绕过微信 8.0.52+ 无障碍节点隐藏

问题

微信 8.0.52 版本开始,主动检测正在运行的无障碍服务。对于第三方服务(即非系统自带的服务),微信故意将 UI 节点树中的元素标记为不可见(AccessibilityNodeInfo.isVisibleToUser() = false),导致:

  • get_screen_info 返回空白或残缺的屏幕内容
  • find_node_info 找不到任何元素
  • Agent 完全"瞎了",无法操作微信

社区的典型绕过方法(如反射修改 AccessibilityServiceInfo、Hook 系统 API)都因 Android 14+ 权限收紧而失效。

解决方案

采用双重策略:

① 伪装系统无障碍服务(SelectToSpeakService)

注册了一个完全空白的无障碍服务,其完整限定名伪装成 Google 系统服务:

com.google.android.accessibility.selecttospeak.SelectToSpeakService

关键细节:

  • FQN 与 Android 自带的 SelectToSpeak 服务完全一致
  • 服务本身不执行任何操作(onAccessibilityEvent() 为空)
  • AndroidManifest.xml 中声明 android:priority="10000",确保最先被系统注册
  • 微信检查无障碍服务列表时,看到一个系统级服务在运行,信任它并展示完整节点树
  • 真正的自动化由独立的 ClawAccessibilityService 执行,微信不感知
<service
    android:name="com.google.android.accessibility.selecttospeak.SelectToSpeakService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
    android:priority="10000">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
</service>

② 宽松可见性模式(Lenient Visibility)

即使伪装成系统服务,微信仍可能在某些场景下把节点设为不可见。ClawAccessibilityService 实现了专门的应对:

  • ANTI_A11Y_APPS — 维护反无障碍应用名单(微信、企业微信、支付宝、QQ)
  • getScreenTreeSmart() — 检测到目标 App 在前台时,自动切换宽松模式
  • buildNodeTreeLenient() — 获取 UI 树时忽略 isVisibleToUser() 标志,只要节点有文字、描述或交互属性就纳入结果
  • findNodesByTextAntiObfuscated() — 三层查找策略:
    1. 标准文本搜索 → 过滤可见节点
    2. 手动遍历整棵树,同时匹配 textcontentDescription
    3. viewId 片段匹配(微信的 viewId 部分可读)

效果

  • 微信界面完整可见:聊天列表、聊天窗口、Tab 栏、弹出菜单全部可读取
  • Agent 可以正常在微信中执行 tap、swipe、输入文字等操作
  • 稳定性好:不依赖反射、不 Hook 系统、不修改微信进程,纯靠无障碍服务标准 API

验证环境

  • 设备:OnePlus PLY110, Android 16 (API 36)
  • 微信版本:8.0.52 ~ 8.0.54
  • 两个无障碍服务均需在系统设置中手动开启

其他改进

  • 微信聊天操作指引:新增聊天场景的导航规则,明确 Agent 保持在聊天 Tab 内操作,避免误入朋友圈(测试中存在账号限制使用的风险)
  • 通用操作规则:进入页面先验证身份、操作前确认元素存在、连续失败 3 次换思路
  • maxIterations 修复:Builder 默认值从 20 改为 60,与主类一致
  • 工具返回截断放宽:300 → 2000 字符,让 Agent 看到更完整的屏幕信息

文件变更

新增文件:
  .../google/android/accessibility/selecttospeak/SelectToSpeakService.java   (29 行)
  .../apk/claw/android/utils/TaskMemory.java                                 (194 行)
  .../apk/claw/android/utils/ScreenMemory.java                               (206 行)
  .../apk/claw/android/tool/impl/RememberTool.java                           (119 行)

修改文件:
  .../service/ClawAccessibilityService.java       (新增 lenient visibility 模式)
  .../agent/DefaultAgentService.kt                (注入记忆 + 微信聊天指引)
  .../tool/impl/GetScreenInfoTool.java            (集成 ScreenMemory)
  .../tool/impl/FindNodeInfoTool.java             (集成 ScreenMemory)
  .../tool/ToolRegistry.kt                        (注册 RememberTool)
  .../TaskOrchestrator.kt                         (截断放宽)
  .../agent/AgentConfig.kt                        (maxIterations 修复)
  .../AndroidManifest.xml                         (声明 SelectToSpeakService)
  .../res/values/strings.xml                      (工具名)
  .../res/values-zh/strings.xml                   (工具名)

注意事项

  1. 两个无障碍服务都需要开启:用户安装后需在系统设置 → 无障碍中同时开启 SelectToSpeakApkClaw,可能会显示两个Apkclaw的无障碍服务按钮,需同时开启
  2. SelectToSpeakService 可能与其他阅读类无障碍工具冲突:如果用户同时使用 TalkBack 或系统自带的 SelectToSpeak,可能需要关闭一个
  3. 微信版本兼容性:在微信 8.0.52 ~ 8.0.54 上测试通过,如果微信升级了检测逻辑,需要同步更新

- New TaskMemory + RememberTool: Persists task learnings across sessions (MMKV-backed, 100 entries max), auto-injected into system prompt
- New ScreenMemory: Caches UI element positions per app, reused across tasks (7-day expiry) — integrated into GetScreenInfoTool and FindNodeInfoTool
- WeChat operation guide: Added chat-specific navigation guidance and safety rules (avoid Moments/Discover tab)
- General operation rules: Page verification before actions, retry limits
- Fix maxIterations Builder default (20 → 60) to match AgentConfig
- Increase tool result truncation limit (300 → 2000 chars) for better AI context
- Register RememberTool in ToolRegistry

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant